From da7324dbf248c852fa9a18f1f4426e61d5690b1d Mon Sep 17 00:00:00 2001 From: gabest11 Date: Fri, 10 Feb 2012 07:03:55 +0000 Subject: [PATCH 01/83] Not transferring unused vif registers to the MTVU thread can save at least half of the ring buffer space. The whole set is about 400 bytes, including padding, but I could find references to only 6 regs. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5092 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/MTVU.h | 26 +++++++++++++++++++++++--- pcsx2/Vif.h | 9 +++++++++ plugins/GSdx/GSDrawScanline.cpp | 11 +++++++++-- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/pcsx2/MTVU.h b/pcsx2/MTVU.h index 1e18065bf..a2fe81ff4 100644 --- a/pcsx2/MTVU.h +++ b/pcsx2/MTVU.h @@ -134,6 +134,16 @@ protected: memcpy_fast(dest, &buffer[read_pos], size); incReadPos(size_u32(size)); } + __fi void ReadRegs(VIFregisters* dest) { + VIFregistersMTVU* src = (VIFregistersMTVU*)&buffer[read_pos]; + dest->cycle = src->cycle; + dest->mode = src->mode; + dest->num = src->num; + dest->mask = src->mask; + dest->itop = src->itop; + dest->top = src->top; + incReadPos(size_u32(sizeof(VIFregistersMTVU))); + } __fi void Write(u32 val) { GetWritePtr()[0] = val; @@ -143,6 +153,16 @@ protected: memcpy_fast(GetWritePtr(), src, size); write_offset += size_u32(size); } + __fi void WriteRegs(VIFregisters* src) { + VIFregistersMTVU* dest = (VIFregistersMTVU*)GetWritePtr(); + dest->cycle = src->cycle; + dest->mode = src->mode; + dest->num = src->num; + dest->mask = src->mask; + dest->top = src->top; + dest->itop = src->itop; + write_offset += size_u32(sizeof(VIFregistersMTVU)); + } void ExecuteTaskInThread() { PCSX2_PAGEFAULT_PROTECT { @@ -192,7 +212,7 @@ protected: case MTVU_VIF_UNPACK: { u32 vif_copy_size = (uptr)&vif.StructEnd - (uptr)&vif.tag; Read(&vif.tag, vif_copy_size); - Read(&vifRegs, sizeof(vifRegs)); + ReadRegs(&vifRegs); u32 size = Read(); MTVU_Unpack(&buffer[read_pos], vifRegs); incReadPos(size_u32(size)); @@ -252,10 +272,10 @@ public: void VifUnpack(vifStruct& _vif, VIFregisters& _vifRegs, u8* data, u32 size) { MTVU_LOG("MTVU - VifUnpack!"); u32 vif_copy_size = (uptr)&_vif.StructEnd - (uptr)&_vif.tag; - ReserveSpace(1 + size_u32(vif_copy_size) + size_u32(sizeof(_vifRegs)) + 1 + size_u32(size)); + ReserveSpace(1 + size_u32(vif_copy_size) + size_u32(sizeof(VIFregistersMTVU)) + 1 + size_u32(size)); Write(MTVU_VIF_UNPACK); Write(&_vif.tag, vif_copy_size); - Write(&_vifRegs, sizeof(_vifRegs)); + WriteRegs(&_vifRegs); Write(size); Write(data, size); incWritePos(); diff --git a/pcsx2/Vif.h b/pcsx2/Vif.h index e1df7ca46..4488efd8c 100644 --- a/pcsx2/Vif.h +++ b/pcsx2/Vif.h @@ -215,6 +215,15 @@ struct VIFregisters { u32 addr; }; +struct VIFregistersMTVU { + vifCycle cycle; //data write cycle + u32 mode; + u32 num; + u32 mask; + u32 itop; + u32 top; // Not used in VIF0 +}; + static VIFregisters& vif0Regs = (VIFregisters&)eeHw[0x3800]; static VIFregisters& vif1Regs = (VIFregisters&)eeHw[0x3C00]; diff --git a/plugins/GSdx/GSDrawScanline.cpp b/plugins/GSdx/GSDrawScanline.cpp index af79af75f..fcad7494d 100644 --- a/plugins/GSdx/GSDrawScanline.cpp +++ b/plugins/GSdx/GSDrawScanline.cpp @@ -103,8 +103,6 @@ void GSDrawScanline::EndDraw(uint64 frame, uint64 ticks, int pixels) #ifndef ENABLE_JIT_RASTERIZER -// FIXME: something's not right with the sky in burnout 3 - void GSDrawScanline::SetupPrim(const GSVertexSW* vertex, const uint32* index, const GSVertexSW& dscan) { GSScanlineSelector sel = m_global.sel; @@ -1179,6 +1177,15 @@ void GSDrawScanline::DrawScanline(int pixels, int left, int top, const GSVertexS case 2: break; } } + else + { + switch(sel.abd) + { + case 0: break; + case 1: ga = gad; break; + case 2: ga = GSVector4i::zero(); break; + } + } if(sel.pabe) { From b75b61cb1d9baa682d557ca74ad9f4dbd933c0be Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Fri, 10 Feb 2012 21:18:47 +0000 Subject: [PATCH 02/83] linux compilation fix git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5093 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSThread.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/GSdx/GSThread.h b/plugins/GSdx/GSThread.h index 4a9e7223d..160bd541c 100644 --- a/plugins/GSdx/GSThread.h +++ b/plugins/GSdx/GSThread.h @@ -182,6 +182,8 @@ public: void Lock() {pthread_mutex_lock(&m_mutex);} bool TryLock() {return pthread_mutex_trylock(&m_mutex) == 0;} void Unlock() {pthread_mutex_unlock(&m_mutex);} + + operator pthread_mutex_t* () {return &m_mutex;} }; class GSEvent : public IGSEvent From c6417674310e1802d535e466ad941b7f4e5b68a1 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Sun, 12 Feb 2012 10:31:08 +0000 Subject: [PATCH 03/83] GSdx: Offset_UV can be defined again. (Need it to hack Wild Arms 3 text placement issues) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5095 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSState.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index 3562a94f5..78bbfc8f8 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -471,8 +471,8 @@ void GSState::GIFPackedRegHandlerUV(const GIFPackedReg* RESTRICT r) m_v.UV = (uint32)GSVector4i::store(v.ps32(v)); #ifdef Offset_UV - m_v.UV.U = min((uint16)m_v.UV.U, (uint16)(m_v.UV.U - 4U)); - m_v.UV.V = min((uint16)m_v.UV.V, (uint16)(m_v.UV.V - 4U)); + m_v.U = min((uint16)m_v.U, (uint16)(m_v.U - 4U)); + m_v.V = min((uint16)m_v.V, (uint16)(m_v.V - 4U)); #endif } @@ -657,8 +657,8 @@ void GSState::GIFRegHandlerUV(const GIFReg* RESTRICT r) m_v.UV = r->UV.u32[0] & 0x3fff3fff; #ifdef Offset_UV - m_v.UV.U = min((uint16)m_v.UV.U, (uint16)(m_v.UV.U - 4U)); - m_v.UV.V = min((uint16)m_v.UV.V, (uint16)(m_v.UV.V - 4U)); + m_v.U = min((uint16)m_v.U, (uint16)(m_v.U - 4U)); + m_v.V = min((uint16)m_v.V, (uint16)(m_v.V - 4U)); #endif } From 67ef7811161703539a3e0da40f388d9473e61653 Mon Sep 17 00:00:00 2001 From: gabest11 Date: Sun, 12 Feb 2012 17:56:06 +0000 Subject: [PATCH 04/83] GSdx: this may fix silent hill shadows and mister mosquito intro blur, also reduced texture cache keep-alive time from 30 to 10 frames and found two memory leaks, killzone can run a few seconds longer before crashing, I think there is something in pcsx2 allocating too much memory. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5096 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSDrawScanline.cpp | 52 +++++------ plugins/GSdx/GSDrawScanlineCodeGenerator.cpp | 19 ++++ plugins/GSdx/GSDrawScanlineCodeGenerator.h | 1 + .../GSDrawScanlineCodeGenerator.x86.avx.cpp | 93 +++++++++---------- .../GSdx/GSDrawScanlineCodeGenerator.x86.cpp | 93 +++++++++---------- plugins/GSdx/GSLocalMemory.cpp | 1 + plugins/GSdx/GSRendererSW.cpp | 25 +++-- plugins/GSdx/GSScanlineEnvironment.h | 3 +- plugins/GSdx/GSTextureCacheSW.cpp | 37 ++++---- plugins/GSdx/GSTextureCacheSW.h | 1 - plugins/GSdx/GSVector.h | 7 ++ 11 files changed, 174 insertions(+), 158 deletions(-) diff --git a/plugins/GSdx/GSDrawScanline.cpp b/plugins/GSdx/GSDrawScanline.cpp index fcad7494d..2f9613f8a 100644 --- a/plugins/GSdx/GSDrawScanline.cpp +++ b/plugins/GSdx/GSDrawScanline.cpp @@ -324,7 +324,7 @@ void GSDrawScanline::DrawScanline(int pixels, int left, int top, const GSVertexS } else if(sel.ltf) { - vf = v.xxzzlh().srl16(16 - GS_BILINEAR_PRECISION).sll16(15 - GS_BILINEAR_PRECISION); + vf = v.xxzzlh().srl16(12); } s = GSVector4::cast(u); @@ -514,8 +514,8 @@ void GSDrawScanline::DrawScanline(int pixels, int left, int top, const GSVertexS u -= 0x8000; v -= 0x8000; - uf = u.xxzzlh().srl16(16 - GS_BILINEAR_PRECISION).sll16(15 - GS_BILINEAR_PRECISION); - vf = v.xxzzlh().srl16(16 - GS_BILINEAR_PRECISION).sll16(15 - GS_BILINEAR_PRECISION); + uf = u.xxzzlh().srl16(12); + vf = v.xxzzlh().srl16(12); } GSVector4i uv0 = u.sra32(16).ps32(v.sra32(16)); @@ -581,19 +581,19 @@ void GSDrawScanline::DrawScanline(int pixels, int left, int top, const GSVertexS GSVector4i rb01 = c01.sll16(8).srl16(8); GSVector4i ga01 = c01.srl16(8); - rb00 = rb00.lerp16<0>(rb01, uf); - ga00 = ga00.lerp16<0>(ga01, uf); + rb00 = rb00.lerp16_4(rb01, uf); + ga00 = ga00.lerp16_4(ga01, uf); GSVector4i rb10 = c10.sll16(8).srl16(8); GSVector4i ga10 = c10.srl16(8); GSVector4i rb11 = c11.sll16(8).srl16(8); GSVector4i ga11 = c11.srl16(8); - rb10 = rb10.lerp16<0>(rb11, uf); - ga10 = ga10.lerp16<0>(ga11, uf); + rb10 = rb10.lerp16_4(rb11, uf); + ga10 = ga10.lerp16_4(ga11, uf); - rb = rb00.lerp16<0>(rb10, vf); - ga = ga00.lerp16<0>(ga10, vf); + rb = rb00.lerp16_4(rb10, vf); + ga = ga00.lerp16_4(ga10, vf); } else { @@ -635,8 +635,8 @@ void GSDrawScanline::DrawScanline(int pixels, int left, int top, const GSVertexS u -= 0x8000; v -= 0x8000; - uf = u.xxzzlh().srl16(16 - GS_BILINEAR_PRECISION).sll16(15 - GS_BILINEAR_PRECISION); - vf = v.xxzzlh().srl16(16 - GS_BILINEAR_PRECISION).sll16(15 - GS_BILINEAR_PRECISION); + uf = u.xxzzlh().srl16(12); + vf = v.xxzzlh().srl16(12); } GSVector4i uv0 = u.sra32(16).ps32(v.sra32(16)); @@ -702,19 +702,19 @@ void GSDrawScanline::DrawScanline(int pixels, int left, int top, const GSVertexS GSVector4i rb01 = c01.sll16(8).srl16(8); GSVector4i ga01 = c01.srl16(8); - rb00 = rb00.lerp16<0>(rb01, uf); - ga00 = ga00.lerp16<0>(ga01, uf); + rb00 = rb00.lerp16_4(rb01, uf); + ga00 = ga00.lerp16_4(ga01, uf); GSVector4i rb10 = c10.sll16(8).srl16(8); GSVector4i ga10 = c10.srl16(8); GSVector4i rb11 = c11.sll16(8).srl16(8); GSVector4i ga11 = c11.srl16(8); - rb10 = rb10.lerp16<0>(rb11, uf); - ga10 = ga10.lerp16<0>(ga11, uf); + rb10 = rb10.lerp16_4(rb11, uf); + ga10 = ga10.lerp16_4(ga11, uf); - rb2 = rb00.lerp16<0>(rb10, vf); - ga2 = ga00.lerp16<0>(ga10, vf); + rb2 = rb00.lerp16_4(rb10, vf); + ga2 = ga00.lerp16_4(ga10, vf); } else { @@ -745,7 +745,7 @@ void GSDrawScanline::DrawScanline(int pixels, int left, int top, const GSVertexS rb = rb.lerp16<0>(rb2, lodf); ga = ga.lerp16<0>(ga2, lodf); - } + } } else { @@ -770,11 +770,11 @@ void GSDrawScanline::DrawScanline(int pixels, int left, int top, const GSVertexS if(sel.ltf) { - uf = u.xxzzlh().srl16(16 - GS_BILINEAR_PRECISION).sll16(15 - GS_BILINEAR_PRECISION); + uf = u.xxzzlh().srl16(12); if(sel.prim != GS_SPRITE_CLASS) { - vf = v.xxzzlh().srl16(16 - GS_BILINEAR_PRECISION).sll16(15 - GS_BILINEAR_PRECISION); + vf = v.xxzzlh().srl16(12); } } @@ -835,19 +835,19 @@ void GSDrawScanline::DrawScanline(int pixels, int left, int top, const GSVertexS GSVector4i rb01 = c01.sll16(8).srl16(8); GSVector4i ga01 = c01.srl16(8); - rb00 = rb00.lerp16<0>(rb01, uf); - ga00 = ga00.lerp16<0>(ga01, uf); + rb00 = rb00.lerp16_4(rb01, uf); + ga00 = ga00.lerp16_4(ga01, uf); GSVector4i rb10 = c10.sll16(8).srl16(8); GSVector4i ga10 = c10.srl16(8); GSVector4i rb11 = c11.sll16(8).srl16(8); GSVector4i ga11 = c11.srl16(8); - rb10 = rb10.lerp16<0>(rb11, uf); - ga10 = ga10.lerp16<0>(ga11, uf); + rb10 = rb10.lerp16_4(rb11, uf); + ga10 = ga10.lerp16_4(ga11, uf); - rb = rb00.lerp16<0>(rb10, vf); - ga = ga00.lerp16<0>(ga10, vf); + rb = rb00.lerp16_4(rb10, vf); + ga = ga00.lerp16_4(ga10, vf); } else { diff --git a/plugins/GSdx/GSDrawScanlineCodeGenerator.cpp b/plugins/GSdx/GSDrawScanlineCodeGenerator.cpp index 7309f75fe..e2d731978 100644 --- a/plugins/GSdx/GSDrawScanlineCodeGenerator.cpp +++ b/plugins/GSdx/GSDrawScanlineCodeGenerator.cpp @@ -97,6 +97,25 @@ void GSDrawScanlineCodeGenerator::lerp16(const Xmm& a, const Xmm& b, const Xmm& #endif } +void GSDrawScanlineCodeGenerator::lerp16_4(const Xmm& a, const Xmm& b, const Xmm& f) +{ + #if _M_SSE >= 0x500 + + vpsubw(a, b); + vpmullw(a, f); + vpsraw(a, 4); + vpaddw(a, b); + + #else + + psubw(a, b); + pmullw(a, f); + psraw(a, 4); + paddw(a, b); + + #endif +} + void GSDrawScanlineCodeGenerator::mix16(const Xmm& a, const Xmm& b, const Xmm& temp) { #if _M_SSE >= 0x500 diff --git a/plugins/GSdx/GSDrawScanlineCodeGenerator.h b/plugins/GSdx/GSDrawScanlineCodeGenerator.h index 4b5b6c746..73f4b59f0 100644 --- a/plugins/GSdx/GSDrawScanlineCodeGenerator.h +++ b/plugins/GSdx/GSDrawScanlineCodeGenerator.h @@ -71,6 +71,7 @@ class GSDrawScanlineCodeGenerator : public GSCodeGenerator void modulate16(const Xmm& a, const Operand& f, int shift); void lerp16(const Xmm& a, const Xmm& b, const Xmm& f, int shift); + void lerp16_4(const Xmm& a, const Xmm& b, const Xmm& f); void mix16(const Xmm& a, const Xmm& b, const Xmm& temp); void clamp16(const Xmm& a, const Xmm& temp); void alltrue(); diff --git a/plugins/GSdx/GSDrawScanlineCodeGenerator.x86.avx.cpp b/plugins/GSdx/GSDrawScanlineCodeGenerator.x86.avx.cpp index c0d938f10..374b3d24f 100644 --- a/plugins/GSdx/GSDrawScanlineCodeGenerator.x86.avx.cpp +++ b/plugins/GSdx/GSDrawScanlineCodeGenerator.x86.avx.cpp @@ -389,8 +389,7 @@ void GSDrawScanlineCodeGenerator::Init() { vpshuflw(xmm6, xmm3, _MM_SHUFFLE(2, 2, 0, 0)); vpshufhw(xmm6, xmm6, _MM_SHUFFLE(2, 2, 0, 0)); - vpsrlw(xmm6, 16 - GS_BILINEAR_PRECISION); - if(GS_BILINEAR_PRECISION < 15) vpsllw(xmm6, 15 - GS_BILINEAR_PRECISION); + vpsrlw(xmm6, 12); vmovdqa(ptr[&m_local.temp.vf], xmm6); } } @@ -743,8 +742,7 @@ void GSDrawScanlineCodeGenerator::SampleTexture() vpshuflw(xmm0, xmm2, _MM_SHUFFLE(2, 2, 0, 0)); vpshufhw(xmm0, xmm0, _MM_SHUFFLE(2, 2, 0, 0)); - vpsrlw(xmm0, 16 - GS_BILINEAR_PRECISION); - if(GS_BILINEAR_PRECISION < 15) vpsllw(xmm0, 15 - GS_BILINEAR_PRECISION); + vpsrlw(xmm0, 12); vmovdqa(ptr[&m_local.temp.uf], xmm0); if(m_sel.prim != GS_SPRITE_CLASS) @@ -753,8 +751,7 @@ void GSDrawScanlineCodeGenerator::SampleTexture() vpshuflw(xmm0, xmm3, _MM_SHUFFLE(2, 2, 0, 0)); vpshufhw(xmm0, xmm0, _MM_SHUFFLE(2, 2, 0, 0)); - vpsrlw(xmm0, 16 - GS_BILINEAR_PRECISION); - if(GS_BILINEAR_PRECISION < 15) vpsllw(xmm0, 15 - GS_BILINEAR_PRECISION); + vpsrlw(xmm0, 12); vmovdqa(ptr[&m_local.temp.vf], xmm0); } } @@ -878,11 +875,11 @@ void GSDrawScanlineCodeGenerator::SampleTexture() // xmm5 = c11 // xmm7 = used - // rb00 = rb00.lerp16<0>(rb01, uf); - // ga00 = ga00.lerp16<0>(ga01, uf); + // rb00 = rb00.lerp16_4(rb01, uf); + // ga00 = ga00.lerp16_4(ga01, uf); - lerp16(xmm3, xmm2, xmm0, 0); - lerp16(xmm4, xmm6, xmm0, 0); + lerp16_4(xmm3, xmm2, xmm0); + lerp16_4(xmm4, xmm6, xmm0); // xmm0 = uf // xmm3 = rb00 @@ -915,11 +912,11 @@ void GSDrawScanlineCodeGenerator::SampleTexture() // xmm6 = ga11 // xmm7 = used - // rb10 = rb10.lerp16<0>(rb11, uf); - // ga10 = ga10.lerp16<0>(ga11, uf); + // rb10 = rb10.lerp16_4(rb11, uf); + // ga10 = ga10.lerp16_4(ga11, uf); - lerp16(xmm5, xmm1, xmm0, 0); - lerp16(xmm6, xmm2, xmm0, 0); + lerp16_4(xmm5, xmm1, xmm0); + lerp16_4(xmm6, xmm2, xmm0); // xmm3 = rb00 // xmm4 = ga00 @@ -928,13 +925,13 @@ void GSDrawScanlineCodeGenerator::SampleTexture() // xmm0, xmm1, xmm2 = free // xmm7 = used - // rb00 = rb00.lerp16<0>(rb10, vf); - // ga00 = ga00.lerp16<0>(ga10, vf); + // rb00 = rb00.lerp16_4(rb10, vf); + // ga00 = ga00.lerp16_4(ga10, vf); vmovdqa(xmm0, ptr[&m_local.temp.vf]); - lerp16(xmm5, xmm3, xmm0, 0); - lerp16(xmm6, xmm4, xmm0, 0); + lerp16_4(xmm5, xmm3, xmm0); + lerp16_4(xmm6, xmm4, xmm0); } else { @@ -1298,16 +1295,14 @@ return; vpshuflw(xmm0, xmm2, _MM_SHUFFLE(2, 2, 0, 0)); vpshufhw(xmm0, xmm0, _MM_SHUFFLE(2, 2, 0, 0)); - vpsrlw(xmm0, 16 - GS_BILINEAR_PRECISION); - if(GS_BILINEAR_PRECISION < 15) vpsllw(xmm0, 15 - GS_BILINEAR_PRECISION); + vpsrlw(xmm0, 12); vmovdqa(ptr[&m_local.temp.uf], xmm0); // GSVector4i vf = v.xxzzlh().srl16(1); vpshuflw(xmm0, xmm3, _MM_SHUFFLE(2, 2, 0, 0)); vpshufhw(xmm0, xmm0, _MM_SHUFFLE(2, 2, 0, 0)); - vpsrlw(xmm0, 16 - GS_BILINEAR_PRECISION); - if(GS_BILINEAR_PRECISION < 15) vpsllw(xmm0, 15 - GS_BILINEAR_PRECISION); + vpsrlw(xmm0, 12); vmovdqa(ptr[&m_local.temp.vf], xmm0); } @@ -1430,11 +1425,11 @@ return; // xmm5 = c11 // xmm7 = used - // rb00 = rb00.lerp16<0>(rb01, uf); - // ga00 = ga00.lerp16<0>(ga01, uf); + // rb00 = rb00.lerp16_4(rb01, uf); + // ga00 = ga00.lerp16_4(ga01, uf); - lerp16(xmm3, xmm2, xmm0, 0); - lerp16(xmm4, xmm6, xmm0, 0); + lerp16_4(xmm3, xmm2, xmm0); + lerp16_4(xmm4, xmm6, xmm0); // xmm0 = uf // xmm3 = rb00 @@ -1467,11 +1462,11 @@ return; // xmm6 = ga11 // xmm7 = used - // rb10 = rb10.lerp16<0>(rb11, uf); - // ga10 = ga10.lerp16<0>(ga11, uf); + // rb10 = rb10.lerp16_4(rb11, uf); + // ga10 = ga10.lerp16_4(ga11, uf); - lerp16(xmm5, xmm1, xmm0, 0); - lerp16(xmm6, xmm2, xmm0, 0); + lerp16_4(xmm5, xmm1, xmm0); + lerp16_4(xmm6, xmm2, xmm0); // xmm3 = rb00 // xmm4 = ga00 @@ -1480,13 +1475,13 @@ return; // xmm0, xmm1, xmm2 = free // xmm7 = used - // rb00 = rb00.lerp16<0>(rb10, vf); - // ga00 = ga00.lerp16<0>(ga10, vf); + // rb00 = rb00.lerp16_4(rb10, vf); + // ga00 = ga00.lerp16_4(ga10, vf); vmovdqa(xmm0, ptr[&m_local.temp.vf]); - lerp16(xmm5, xmm3, xmm0, 0); - lerp16(xmm6, xmm4, xmm0, 0); + lerp16_4(xmm5, xmm3, xmm0); + lerp16_4(xmm6, xmm4, xmm0); } else { @@ -1541,16 +1536,14 @@ return; vpshuflw(xmm0, xmm2, _MM_SHUFFLE(2, 2, 0, 0)); vpshufhw(xmm0, xmm0, _MM_SHUFFLE(2, 2, 0, 0)); - vpsrlw(xmm0, 16 - GS_BILINEAR_PRECISION); - if(GS_BILINEAR_PRECISION < 15) vpsllw(xmm0, 15 - GS_BILINEAR_PRECISION); + vpsrlw(xmm0, 12); vmovdqa(ptr[&m_local.temp.uf], xmm0); // GSVector4i vf = v.xxzzlh().srl16(1); vpshuflw(xmm0, xmm3, _MM_SHUFFLE(2, 2, 0, 0)); vpshufhw(xmm0, xmm0, _MM_SHUFFLE(2, 2, 0, 0)); - vpsrlw(xmm0, 16 - GS_BILINEAR_PRECISION); - if(GS_BILINEAR_PRECISION < 15) vpsllw(xmm0, 15 - GS_BILINEAR_PRECISION); + vpsrlw(xmm0, 12); vmovdqa(ptr[&m_local.temp.vf], xmm0); } @@ -1673,11 +1666,11 @@ return; // xmm5 = c11 // xmm7 = used - // rb00 = rb00.lerp16<0>(rb01, uf); - // ga00 = ga00.lerp16<0>(ga01, uf); + // rb00 = rb00.lerp16_4(rb01, uf); + // ga00 = ga00.lerp16_4(ga01, uf); - lerp16(xmm3, xmm2, xmm0, 0); - lerp16(xmm4, xmm6, xmm0, 0); + lerp16_4(xmm3, xmm2, xmm0); + lerp16_4(xmm4, xmm6, xmm0); // xmm0 = uf // xmm3 = rb00 @@ -1710,11 +1703,11 @@ return; // xmm6 = ga11 // xmm7 = used - // rb10 = rb10.lerp16<0>(rb11, uf); - // ga10 = ga10.lerp16<0>(ga11, uf); + // rb10 = rb10.lerp16_4(rb11, uf); + // ga10 = ga10.lerp16_4(ga11, uf); - lerp16(xmm5, xmm1, xmm0, 0); - lerp16(xmm6, xmm2, xmm0, 0); + lerp16_4(xmm5, xmm1, xmm0); + lerp16_4(xmm6, xmm2, xmm0); // xmm3 = rb00 // xmm4 = ga00 @@ -1723,13 +1716,13 @@ return; // xmm0, xmm1, xmm2 = free // xmm7 = used - // rb00 = rb00.lerp16<0>(rb10, vf); - // ga00 = ga00.lerp16<0>(ga10, vf); + // rb00 = rb00.lerp16_4(rb10, vf); + // ga00 = ga00.lerp16_4(ga10, vf); vmovdqa(xmm0, ptr[&m_local.temp.vf]); - lerp16(xmm5, xmm3, xmm0, 0); - lerp16(xmm6, xmm4, xmm0, 0); + lerp16_4(xmm5, xmm3, xmm0); + lerp16_4(xmm6, xmm4, xmm0); } else { diff --git a/plugins/GSdx/GSDrawScanlineCodeGenerator.x86.cpp b/plugins/GSdx/GSDrawScanlineCodeGenerator.x86.cpp index b37dc1163..51ba25f4b 100644 --- a/plugins/GSdx/GSDrawScanlineCodeGenerator.x86.cpp +++ b/plugins/GSdx/GSDrawScanlineCodeGenerator.x86.cpp @@ -389,8 +389,7 @@ void GSDrawScanlineCodeGenerator::Init() { pshuflw(xmm6, xmm3, _MM_SHUFFLE(2, 2, 0, 0)); pshufhw(xmm6, xmm6, _MM_SHUFFLE(2, 2, 0, 0)); - psrlw(xmm6, 16 - GS_BILINEAR_PRECISION); - if(GS_BILINEAR_PRECISION < 15) psllw(xmm6, 15 - GS_BILINEAR_PRECISION); + psrlw(xmm6, 12); movdqa(ptr[&m_local.temp.vf], xmm6); } } @@ -748,8 +747,7 @@ void GSDrawScanlineCodeGenerator::SampleTexture() pshuflw(xmm0, xmm2, _MM_SHUFFLE(2, 2, 0, 0)); pshufhw(xmm0, xmm0, _MM_SHUFFLE(2, 2, 0, 0)); - psrlw(xmm0, 16 - GS_BILINEAR_PRECISION); - if(GS_BILINEAR_PRECISION < 15) psllw(xmm0, 15 - GS_BILINEAR_PRECISION); + psrlw(xmm0, 12); movdqa(ptr[&m_local.temp.uf], xmm0); if(m_sel.prim != GS_SPRITE_CLASS) @@ -758,8 +756,7 @@ void GSDrawScanlineCodeGenerator::SampleTexture() pshuflw(xmm0, xmm3, _MM_SHUFFLE(2, 2, 0, 0)); pshufhw(xmm0, xmm0, _MM_SHUFFLE(2, 2, 0, 0)); - psrlw(xmm0, 16 - GS_BILINEAR_PRECISION); - if(GS_BILINEAR_PRECISION < 15) psllw(xmm0, 15 - GS_BILINEAR_PRECISION); + psrlw(xmm0, 12); movdqa(ptr[&m_local.temp.vf], xmm0); } } @@ -891,11 +888,11 @@ void GSDrawScanlineCodeGenerator::SampleTexture() // xmm5 = c11 // xmm7 = used - // rb00 = rb00.lerp16<0>(rb01, uf); - // ga00 = ga00.lerp16<0>(ga01, uf); + // rb00 = rb00.lerp_4(rb01, uf); + // ga00 = ga00.lerp_4(ga01, uf); - lerp16(xmm3, xmm2, xmm0, 0); - lerp16(xmm4, xmm6, xmm0, 0); + lerp16_4(xmm3, xmm2, xmm0); + lerp16_4(xmm4, xmm6, xmm0); // xmm0 = uf // xmm3 = rb00 @@ -930,11 +927,11 @@ void GSDrawScanlineCodeGenerator::SampleTexture() // xmm6 = ga11 // xmm7 = used - // rb10 = rb10.lerp16<0>(rb11, uf); - // ga10 = ga10.lerp16<0>(ga11, uf); + // rb10 = rb10.lerp_4(rb11, uf); + // ga10 = ga10.lerp_4(ga11, uf); - lerp16(xmm5, xmm1, xmm0, 0); - lerp16(xmm6, xmm2, xmm0, 0); + lerp16_4(xmm5, xmm1, xmm0); + lerp16_4(xmm6, xmm2, xmm0); // xmm3 = rb00 // xmm4 = ga00 @@ -943,13 +940,13 @@ void GSDrawScanlineCodeGenerator::SampleTexture() // xmm0, xmm1, xmm2 = free // xmm7 = used - // rb00 = rb00.lerp16<0>(rb10, vf); - // ga00 = ga00.lerp16<0>(ga10, vf); + // rb00 = rb00.lerp_4(rb10, vf); + // ga00 = ga00.lerp_4(ga10, vf); movdqa(xmm0, ptr[&m_local.temp.vf]); - lerp16(xmm5, xmm3, xmm0, 0); - lerp16(xmm6, xmm4, xmm0, 0); + lerp16_4(xmm5, xmm3, xmm0); + lerp16_4(xmm6, xmm4, xmm0); } else { @@ -1353,16 +1350,14 @@ void GSDrawScanlineCodeGenerator::SampleTextureLOD() pshuflw(xmm0, xmm2, _MM_SHUFFLE(2, 2, 0, 0)); pshufhw(xmm0, xmm0, _MM_SHUFFLE(2, 2, 0, 0)); - psrlw(xmm0, 16 - GS_BILINEAR_PRECISION); - if(GS_BILINEAR_PRECISION < 15) psllw(xmm0, 15 - GS_BILINEAR_PRECISION); + psrlw(xmm0, 12); movdqa(ptr[&m_local.temp.uf], xmm0); // GSVector4i vf = v.xxzzlh().srl16(1); pshuflw(xmm0, xmm3, _MM_SHUFFLE(2, 2, 0, 0)); pshufhw(xmm0, xmm0, _MM_SHUFFLE(2, 2, 0, 0)); - psrlw(xmm0, 16 - GS_BILINEAR_PRECISION); - if(GS_BILINEAR_PRECISION < 15) psllw(xmm0, 15 - GS_BILINEAR_PRECISION); + psrlw(xmm0, 12); movdqa(ptr[&m_local.temp.vf], xmm0); } @@ -1493,11 +1488,11 @@ void GSDrawScanlineCodeGenerator::SampleTextureLOD() // xmm5 = c11 // xmm7 = used - // rb00 = rb00.lerp16<0>(rb01, uf); - // ga00 = ga00.lerp16<0>(ga01, uf); + // rb00 = rb00.lerp_4(rb01, uf); + // ga00 = ga00.lerp_4(ga01, uf); - lerp16(xmm3, xmm2, xmm0, 0); - lerp16(xmm4, xmm6, xmm0, 0); + lerp16_4(xmm3, xmm2, xmm0); + lerp16_4(xmm4, xmm6, xmm0); // xmm0 = uf // xmm3 = rb00 @@ -1532,11 +1527,11 @@ void GSDrawScanlineCodeGenerator::SampleTextureLOD() // xmm6 = ga11 // xmm7 = used - // rb10 = rb10.lerp16<0>(rb11, uf); - // ga10 = ga10.lerp16<0>(ga11, uf); + // rb10 = rb10.lerp_4(rb11, uf); + // ga10 = ga10.lerp_4(ga11, uf); - lerp16(xmm5, xmm1, xmm0, 0); - lerp16(xmm6, xmm2, xmm0, 0); + lerp16_4(xmm5, xmm1, xmm0); + lerp16_4(xmm6, xmm2, xmm0); // xmm3 = rb00 // xmm4 = ga00 @@ -1545,13 +1540,13 @@ void GSDrawScanlineCodeGenerator::SampleTextureLOD() // xmm0, xmm1, xmm2 = free // xmm7 = used - // rb00 = rb00.lerp16<0>(rb10, vf); - // ga00 = ga00.lerp16<0>(ga10, vf); + // rb00 = rb00.lerp_4(rb10, vf); + // ga00 = ga00.lerp_4(ga10, vf); movdqa(xmm0, ptr[&m_local.temp.vf]); - lerp16(xmm5, xmm3, xmm0, 0); - lerp16(xmm6, xmm4, xmm0, 0); + lerp16_4(xmm5, xmm3, xmm0); + lerp16_4(xmm6, xmm4, xmm0); } else { @@ -1608,16 +1603,14 @@ void GSDrawScanlineCodeGenerator::SampleTextureLOD() pshuflw(xmm0, xmm2, _MM_SHUFFLE(2, 2, 0, 0)); pshufhw(xmm0, xmm0, _MM_SHUFFLE(2, 2, 0, 0)); - psrlw(xmm0, 16 - GS_BILINEAR_PRECISION); - if(GS_BILINEAR_PRECISION < 15) psllw(xmm0, 15 - GS_BILINEAR_PRECISION); + psrlw(xmm0, 12); movdqa(ptr[&m_local.temp.uf], xmm0); // GSVector4i vf = v.xxzzlh().srl16(1); pshuflw(xmm0, xmm3, _MM_SHUFFLE(2, 2, 0, 0)); pshufhw(xmm0, xmm0, _MM_SHUFFLE(2, 2, 0, 0)); - psrlw(xmm0, 16 - GS_BILINEAR_PRECISION); - if(GS_BILINEAR_PRECISION < 15) psllw(xmm0, 15 - GS_BILINEAR_PRECISION); + psrlw(xmm0, 12); movdqa(ptr[&m_local.temp.vf], xmm0); } @@ -1748,11 +1741,11 @@ void GSDrawScanlineCodeGenerator::SampleTextureLOD() // xmm5 = c11 // xmm7 = used - // rb00 = rb00.lerp16<0>(rb01, uf); - // ga00 = ga00.lerp16<0>(ga01, uf); + // rb00 = rb00.lerp_4(rb01, uf); + // ga00 = ga00.lerp_4(ga01, uf); - lerp16(xmm3, xmm2, xmm0, 0); - lerp16(xmm4, xmm6, xmm0, 0); + lerp16_4(xmm3, xmm2, xmm0); + lerp16_4(xmm4, xmm6, xmm0); // xmm0 = uf // xmm3 = rb00 @@ -1787,11 +1780,11 @@ void GSDrawScanlineCodeGenerator::SampleTextureLOD() // xmm6 = ga11 // xmm7 = used - // rb10 = rb10.lerp16<0>(rb11, uf); - // ga10 = ga10.lerp16<0>(ga11, uf); + // rb10 = rb10.lerp_4(rb11, uf); + // ga10 = ga10.lerp_4(ga11, uf); - lerp16(xmm5, xmm1, xmm0, 0); - lerp16(xmm6, xmm2, xmm0, 0); + lerp16_4(xmm5, xmm1, xmm0); + lerp16_4(xmm6, xmm2, xmm0); // xmm3 = rb00 // xmm4 = ga00 @@ -1800,13 +1793,13 @@ void GSDrawScanlineCodeGenerator::SampleTextureLOD() // xmm0, xmm1, xmm2 = free // xmm7 = used - // rb00 = rb00.lerp16<0>(rb10, vf); - // ga00 = ga00.lerp16<0>(ga10, vf); + // rb00 = rb00.lerp_4(rb10, vf); + // ga00 = ga00.lerp_4(ga10, vf); movdqa(xmm0, ptr[&m_local.temp.vf]); - lerp16(xmm5, xmm3, xmm0, 0); - lerp16(xmm6, xmm4, xmm0, 0); + lerp16_4(xmm5, xmm3, xmm0); + lerp16_4(xmm6, xmm4, xmm0); } else { diff --git a/plugins/GSdx/GSLocalMemory.cpp b/plugins/GSdx/GSLocalMemory.cpp index dfdd11274..cd6e28b49 100644 --- a/plugins/GSdx/GSLocalMemory.cpp +++ b/plugins/GSdx/GSLocalMemory.cpp @@ -447,6 +447,7 @@ GSLocalMemory::~GSLocalMemory() vmfree(m_vm8, m_vmsize * 2); for_each(m_omap.begin(), m_omap.end(), aligned_free_second()); + for_each(m_pomap.begin(), m_pomap.end(), aligned_free_second()); for_each(m_po4map.begin(), m_po4map.end(), aligned_free_second()); for(hash_map*>::iterator i = m_p2tmap.begin(); i != m_p2tmap.end(); i++) diff --git a/plugins/GSdx/GSRendererSW.cpp b/plugins/GSdx/GSRendererSW.cpp index 44de11026..3869b8fae 100644 --- a/plugins/GSdx/GSRendererSW.cpp +++ b/plugins/GSdx/GSRendererSW.cpp @@ -680,6 +680,8 @@ bool GSRendererSW::CheckTargetPages(const uint32* fb_pages, const uint32* zb_pag bool fb = fb_pages != NULL; bool zb = zb_pages != NULL; + bool res = false; + if(m_fzb != m_context->offset.fzb4) { // targets changed, check everything @@ -724,7 +726,7 @@ bool GSRendererSW::CheckTargetPages(const uint32* fb_pages, const uint32* zb_pag { if(LOG) {fprintf(s_fp, "syncpoint 0\n"); fflush(s_fp);} - return true; + res = true; } //if(LOG) {fprintf(s_fp, "no syncpoint *\n"); fflush(s_fp);} @@ -785,7 +787,7 @@ bool GSRendererSW::CheckTargetPages(const uint32* fb_pages, const uint32* zb_pag { if(LOG) {fprintf(s_fp, "syncpoint 1\n"); fflush(s_fp);} - return true; + res = true; } } } @@ -795,7 +797,7 @@ bool GSRendererSW::CheckTargetPages(const uint32* fb_pages, const uint32* zb_pag // chross-check frame and z-buffer pages, they cannot overlap with eachother and with previous batches in queue, // have to be careful when the two buffers are mutually enabled/disabled and alternating (Bully FBP/ZBP = 0x2300) - if(fb) + if(fb && !res) { for(const uint32* p = fb_pages; *p != GSOffset::EOP; p++) { @@ -803,12 +805,14 @@ bool GSRendererSW::CheckTargetPages(const uint32* fb_pages, const uint32* zb_pag { if(LOG) {fprintf(s_fp, "syncpoint 2\n"); fflush(s_fp);} - return true; + res = true; + + break; } } } - if(zb) + if(zb && !res) { for(const uint32* p = zb_pages; *p != GSOffset::EOP; p++) { @@ -816,14 +820,19 @@ bool GSRendererSW::CheckTargetPages(const uint32* fb_pages, const uint32* zb_pag { if(LOG) {fprintf(s_fp, "syncpoint 3\n"); fflush(s_fp);} - return true; + res = true; + + break; } } } } } - return false; + if(!fb && fb_pages != NULL) delete [] fb_pages; + if(!zb && zb_pages != NULL) delete [] zb_pages; + + return res; } bool GSRendererSW::CheckSourcePages(SharedData* sd) @@ -1334,7 +1343,7 @@ bool GSRendererSW::GetScanlineGlobalData(SharedData* data) gd.zm |= GSVector4i::xffff0000(); } - if(gd.sel.prim == GS_SPRITE_CLASS && !gd.sel.ftest && !gd.sel.ztest && data->bbox.eq(data->bbox.rintersect(data->scissor))) + if(gd.sel.prim == GS_SPRITE_CLASS && !gd.sel.ftest && !gd.sel.ztest && data->bbox.eq(data->bbox.rintersect(data->scissor))) // TODO: check scissor horizontally only { gd.sel.notest = 1; diff --git a/plugins/GSdx/GSScanlineEnvironment.h b/plugins/GSdx/GSScanlineEnvironment.h index a8d9637c4..aee43b840 100644 --- a/plugins/GSdx/GSScanlineEnvironment.h +++ b/plugins/GSdx/GSScanlineEnvironment.h @@ -24,8 +24,6 @@ #include "GSLocalMemory.h" #include "GSVector.h" -#define GS_BILINEAR_PRECISION 4 // max precision 15, but several games like okami, rogue galaxy, dq8 break above 4 - union GSScanlineSelector { struct @@ -70,6 +68,7 @@ union GSScanlineSelector uint32 lcm:1; // 52 uint32 mmin:2; // 53 uint32 notest:1; // 54 (no ztest, no atest, no date, no scissor test, and horizontally aligned to 4 pixels) + // TODO: 1D texture flag? could save 2 texture reads and 4 lerps with bilinear, and also the texture coordinate clamp/wrap code in one direction }; struct diff --git a/plugins/GSdx/GSTextureCacheSW.cpp b/plugins/GSdx/GSTextureCacheSW.cpp index 37e272006..5f9fd5e1b 100644 --- a/plugins/GSdx/GSTextureCacheSW.cpp +++ b/plugins/GSdx/GSTextureCacheSW.cpp @@ -131,25 +131,6 @@ void GSTextureCacheSW::RemoveAll() } } -void GSTextureCacheSW::RemoveAt(Texture* t) -{ - m_textures.erase(t); - - for(uint32 start = t->m_TEX0.TBP0 >> 5, end = countof(m_map) - 1; start <= end; start++) - { - list& m = m_map[start]; - - for(list::iterator i = m.begin(); i != m.end(); ) - { - list::iterator j = i++; - - if(*j == t) {m.erase(j); break;} - } - } - - delete t; -} - void GSTextureCacheSW::IncAge() { for(hash_set::iterator i = m_textures.begin(); i != m_textures.end(); ) @@ -158,9 +139,23 @@ void GSTextureCacheSW::IncAge() Texture* t = *j; - if(++t->m_age > 30) + if(++t->m_age > 10) { - RemoveAt(t); + m_textures.erase(j); + + for(const uint32* p = t->m_pages.n; *p != GSOffset::EOP; p++) + { + list& m = m_map[*p]; + + for(list::iterator i = m.begin(); i != m.end(); ) + { + list::iterator j = i++; + + if(*j == t) {m.erase(j); break;} + } + } + + delete t; } } } diff --git a/plugins/GSdx/GSTextureCacheSW.h b/plugins/GSdx/GSTextureCacheSW.h index 8c80456c1..f15998c64 100644 --- a/plugins/GSdx/GSTextureCacheSW.h +++ b/plugins/GSdx/GSTextureCacheSW.h @@ -68,6 +68,5 @@ public: void InvalidatePages(const uint32* pages, uint32 psm); void RemoveAll(); - void RemoveAt(Texture* t); void IncAge(); }; diff --git a/plugins/GSdx/GSVector.h b/plugins/GSdx/GSVector.h index de2080735..19a21ded0 100644 --- a/plugins/GSdx/GSVector.h +++ b/plugins/GSdx/GSVector.h @@ -1004,6 +1004,13 @@ public: return d.add16(a.sub16(b).modulate16(c)); } + __forceinline GSVector4i lerp16_4(const GSVector4i& a, const GSVector4i& f) const + { + // (a - this) * f >> 4 + this (a, this: 8-bit, f: 4-bit) + + return add16(a.sub16(*this).mul16l(f).sra16(4)); + } + template __forceinline GSVector4i modulate16(const GSVector4i& f) const { // a * f << shift From 5d9a5b6ee661a9b5d0dbff9e183c16f5ab41c2c9 Mon Sep 17 00:00:00 2001 From: gabest11 Date: Tue, 14 Feb 2012 08:03:27 +0000 Subject: [PATCH 05/83] GSdx: there was a float-int conversion overflow in vertex trace, texture coord min/max could have been detected wrong, silent hill origins should look better now. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5097 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSLocalMemory.cpp | 7 +++ plugins/GSdx/GSLocalMemory.h | 1 + plugins/GSdx/GSRendererSW.cpp | 84 ++++++++++++++++++------------- plugins/GSdx/GSState.cpp | 4 +- plugins/GSdx/GSTextureCacheSW.cpp | 2 +- plugins/GSdx/GSVertexTrace.cpp | 4 +- plugins/GSdx/GSVertexTrace.h | 2 +- 7 files changed, 62 insertions(+), 42 deletions(-) diff --git a/plugins/GSdx/GSLocalMemory.cpp b/plugins/GSdx/GSLocalMemory.cpp index cd6e28b49..bca4e345e 100644 --- a/plugins/GSdx/GSLocalMemory.cpp +++ b/plugins/GSdx/GSLocalMemory.cpp @@ -221,6 +221,7 @@ GSLocalMemory::GSLocalMemory() m_psm[i].pgs = GSVector2i(64, 32); for(int j = 0; j < 8; j++) m_psm[i].rowOffset[j] = rowOffset32; m_psm[i].blockOffset = blockOffset32; + m_psm[i].msk = 0xff; } m_psm[PSM_PSMCT16].pa = &GSLocalMemory::PixelAddress16; @@ -440,6 +441,12 @@ GSLocalMemory::GSLocalMemory() m_psm[PSM_PSMZ24].blockOffset = blockOffset32Z; m_psm[PSM_PSMZ16].blockOffset = blockOffset16Z; m_psm[PSM_PSMZ16S].blockOffset = blockOffset16SZ; + + m_psm[PSM_PSMCT24].msk = 0x3f; + m_psm[PSM_PSMZ24].msk = 0x3f; + m_psm[PSM_PSMT8H].msk = 0xc0; + m_psm[PSM_PSMT4HL].msk = 0x40; + m_psm[PSM_PSMT4HH].msk = 0x80; } GSLocalMemory::~GSLocalMemory() diff --git a/plugins/GSdx/GSLocalMemory.h b/plugins/GSdx/GSLocalMemory.h index 8cda1b73b..9a32b0169 100644 --- a/plugins/GSdx/GSLocalMemory.h +++ b/plugins/GSdx/GSLocalMemory.h @@ -111,6 +111,7 @@ public: GSVector2i bs, pgs; int* rowOffset[8]; short* blockOffset; + uint8 msk; }; static psm_t m_psm[64]; diff --git a/plugins/GSdx/GSRendererSW.cpp b/plugins/GSdx/GSRendererSW.cpp index 3869b8fae..8209d5b81 100644 --- a/plugins/GSdx/GSRendererSW.cpp +++ b/plugins/GSdx/GSRendererSW.cpp @@ -426,21 +426,9 @@ void GSRendererSW::Draw() // - if(LOG) - { - fprintf(s_fp, "[%d] queue %05x %d (%d) %05x %d (%d) %05x %d %dx%d (%d %d %d) | %d %d %d\n", - sd->counter, - m_context->FRAME.Block(), m_context->FRAME.PSM, gd.sel.fwrite, - m_context->ZBUF.Block(), m_context->ZBUF.PSM, gd.sel.zwrite, - PRIM->TME ? m_context->TEX0.TBP0 : 0xfffff, m_context->TEX0.PSM, (int)m_context->TEX0.TW, (int)m_context->TEX0.TH, m_context->TEX0.CSM, m_context->TEX0.CPSM, m_context->TEX0.CSA, - PRIM->PRIM, sd->vertex_count, sd->index_count); - - fflush(s_fp); - } - if(s_dump) { - Sync(3); + Sync(2); uint64 frame = m_perfmon.GetFrame(); @@ -473,7 +461,7 @@ void GSRendererSW::Draw() Queue(data); - Sync(4); + Sync(3); if(s_save && s_n >= s_saven) { @@ -514,13 +502,34 @@ void GSRendererSW::Queue(shared_ptr& item) if(sd->m_syncpoint == SharedData::SyncSource) { - m_rl->Sync(); + Sync(4); } // update previously invalidated parts sd->UpdateSource(); + if(sd->m_syncpoint == SharedData::SyncTarget) + { + Sync(5); + } + + if(LOG) + { + GSScanlineGlobalData& gd = ((SharedData*)item.get())->global; + + fprintf(s_fp, "[%d] queue %05x %d (%d) %05x %d (%d) %05x %d %dx%d (%d %d %d) | %d %d %d\n", + sd->counter, + m_context->FRAME.Block(), m_context->FRAME.PSM, gd.sel.fwrite, + m_context->ZBUF.Block(), m_context->ZBUF.PSM, gd.sel.zwrite, + PRIM->TME ? m_context->TEX0.TBP0 : 0xfffff, m_context->TEX0.PSM, (int)m_context->TEX0.TW, (int)m_context->TEX0.TH, m_context->TEX0.CSM, m_context->TEX0.CPSM, m_context->TEX0.CSA, + PRIM->PRIM, sd->vertex_count, sd->index_count); + + fflush(s_fp); + } + + m_rl->Queue(item); + // invalidate new parts rendered onto if(sd->global.sel.fwrite) @@ -532,13 +541,6 @@ void GSRendererSW::Queue(shared_ptr& item) { m_tc->InvalidatePages(sd->m_zb_pages, sd->m_zpsm); } - - if(sd->m_syncpoint == SharedData::SyncTarget) - { - m_rl->Sync(); - } - - m_rl->Queue(item); } void GSRendererSW::Sync(int reason) @@ -597,7 +599,7 @@ void GSRendererSW::InvalidateVideoMem(const GIFRegBITBLTBUF& BITBLTBUF, const GS { if(m_fzb_pages[*p] | m_tex_pages[*p]) { - Sync(5); + Sync(6); break; } @@ -1066,12 +1068,6 @@ bool GSRendererSW::GetScanlineGlobalData(SharedData* data) static int s_counter = 0; - if(0) - //if(context->TEX0.TH > context->TEX0.TW) - //if(s_n >= s_saven && s_n < s_saven + 3) - //if(context->TEX0.TBP0 >= 0x2b80 && context->TEX0.TBW == 2 && context->TEX0.PSM == PSM_PSMT4) - t->Save(format("c:/temp1/%08d_%05x_0.bmp", s_counter, context->TEX0.TBP0)); - for(int i = 1, j = std::min((int)context->TEX1.MXL, 6); i <= j; i++) { switch(i) @@ -1473,21 +1469,37 @@ void GSRendererSW::SharedData::UpdateSource() global.sel.tfx = TFX_NONE; } + } - // TODO + // TODO - if(m_parent->s_dump) + if(m_parent->s_dump) + { + uint64 frame = m_parent->m_perfmon.GetFrame(); + + string s; + + if(m_parent->s_save && m_parent->s_n >= m_parent->s_saven) { - uint64 frame = m_parent->m_perfmon.GetFrame(); - - string s; - - if(m_parent->s_save && m_parent->s_n >= m_parent->s_saven) + for(size_t i = 0; m_tex[i].t != NULL; i++) { s = format("c:\\temp1\\_%05d_f%lld_tex%d_%05x_%d.bmp", m_parent->s_n - 2, frame, i, (int)m_parent->m_context->TEX0.TBP0, (int)m_parent->m_context->TEX0.PSM); m_tex[i].t->Save(s); } + + if(global.clut != NULL) + { + GSTextureSW* t = new GSTextureSW(0, 256, 1); + + t->Update(GSVector4i(0, 0, 256, 1), global.clut, sizeof(uint32) * 256); + + s = format("c:\\temp1\\_%05d_f%lld_texp_%05x_%d.bmp", m_parent->s_n - 2, frame, (int)m_parent->m_context->TEX0.TBP0, (int)m_parent->m_context->TEX0.PSM); + + t->Save(s); + + delete t; + } } } } diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index 78bbfc8f8..2ff94cc7f 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -2518,10 +2518,10 @@ void GSState::GetTextureMinMax(GSVector4i& r, const GIFRegTEX0& TEX0, const GIFR if(linear) { - st += GSVector4(-0x8000, 0x8000).xxyy(); + st += GSVector4(-0.5f, 0.5f).xxyy(); } - GSVector4i uv = GSVector4i(st).sra32(16); + GSVector4i uv = GSVector4i(st); GSVector4i u, v; diff --git a/plugins/GSdx/GSTextureCacheSW.cpp b/plugins/GSdx/GSTextureCacheSW.cpp index 5f9fd5e1b..ea71154a9 100644 --- a/plugins/GSdx/GSTextureCacheSW.cpp +++ b/plugins/GSdx/GSTextureCacheSW.cpp @@ -363,7 +363,7 @@ bool GSTextureCacheSW::Texture::Save(const string& fn, bool dds) const { for(int i = 0; i < w; i++) { - ((uint32*)m.bits)[i] = clut[((uint8*)src)[i]]; + ((uint32*)m.bits)[i] = clut[src[i]]; } } } diff --git a/plugins/GSdx/GSVertexTrace.cpp b/plugins/GSdx/GSVertexTrace.cpp index 955c1bc80..5d3e3b482 100644 --- a/plugins/GSdx/GSVertexTrace.cpp +++ b/plugins/GSdx/GSVertexTrace.cpp @@ -455,11 +455,11 @@ void GSVertexTrace::FindMinMax(const void* vertex, const uint32* index, int coun { if(fst) { - s = GSVector4(1 << (16 - 4), 1).xxyy(); + s = GSVector4(1.0f / 16, 1.0f).xxyy(); } else { - s = GSVector4(0x10000 << context->TEX0.TW, 0x10000 << context->TEX0.TH, 1, 1); + s = GSVector4(1 << context->TEX0.TW, 1 << context->TEX0.TH, 1, 1); } m_min.t = tmin * s; diff --git a/plugins/GSdx/GSVertexTrace.h b/plugins/GSdx/GSVertexTrace.h index a5734fafc..c7fd01228 100644 --- a/plugins/GSdx/GSVertexTrace.h +++ b/plugins/GSdx/GSVertexTrace.h @@ -32,7 +32,7 @@ class GSState; __aligned(class, 32) GSVertexTrace : public GSAlignedClass<32> { public: - struct Vertex {GSVector4i c; GSVector4 p, t;}; // t.xy * 0x10000 + struct Vertex {GSVector4i c; GSVector4 p, t;}; struct VertexAlpha {int min, max; bool valid;}; protected: From f53d70c483e2b99825127d7a0577c7b490f24b4b Mon Sep 17 00:00:00 2001 From: gabest11 Date: Tue, 14 Feb 2012 19:26:04 +0000 Subject: [PATCH 06/83] GSdx: fix for Vexx, a few vertices were bogus, s/t/q all zero. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5098 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSState.cpp | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index 2ff94cc7f..7fa74ce0d 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -444,18 +444,14 @@ void GSState::GIFPackedRegHandlerRGBA(const GIFPackedReg* RESTRICT r) void GSState::GIFPackedRegHandlerSTQ(const GIFPackedReg* RESTRICT r) { - #if defined(_M_AMD64) + GSVector4i st = GSVector4i::loadl(&r->u64[0]); + GSVector4i q = GSVector4i::loadl(&r->u64[1]); - m_v.ST.u64 = r->u64[0]; + GSVector4i::storel(&m_v.ST, st); - #else - - GSVector4i v = GSVector4i::loadl(r); - GSVector4i::storel(&m_v.ST.u64, v); - - #endif - - m_q = r->STQ.Q; + q = q.blend8(GSVector4i::cast(GSVector4::m_one), q == GSVector4i::zero()); // character shadow in Vexx, q = 0 (st also 0 on the first 16 vertices), setting it to 1.0f to avoid div by zero later + + *(int*)&m_q = GSVector4i::store(q); #ifdef Offset_ST GIFRegTEX0 TEX0 = m_context->TEX0; @@ -539,6 +535,8 @@ void GSState::GIFPackedRegHandlerSTQRGBAXYZF2(const GIFPackedReg* RESTRICT r, ui GSVector4i q = GSVector4i::loadl(&r[0].u64[1]); GSVector4i rgba = (GSVector4i::load(&r[1]) & GSVector4i::x000000ff()).ps32().pu16(); + q = q.blend8(GSVector4i::cast(GSVector4::m_one), q == GSVector4i::zero()); // see GIFPackedRegHandlerSTQ + m_v.m[0] = st.upl64(rgba.upl32(q)); // TODO: only store the last one GSVector4i xy = GSVector4i::loadl(&r[2].u64[0]); @@ -569,6 +567,8 @@ void GSState::GIFPackedRegHandlerSTQRGBAXYZ2(const GIFPackedReg* RESTRICT r, uin GSVector4i q = GSVector4i::loadl(&r[0].u64[1]); GSVector4i rgba = (GSVector4i::load(&r[1]) & GSVector4i::x000000ff()).ps32().pu16(); + q = q.blend8(GSVector4i::cast(GSVector4::m_one), q == GSVector4i::zero()); // see GIFPackedRegHandlerSTQ + m_v.m[0] = st.upl64(rgba.upl32(q)); // TODO: only store the last one GSVector4i xy = GSVector4i::loadl(&r[2].u64[0]); @@ -638,7 +638,11 @@ void GSState::GIFRegHandlerPRIM(const GIFReg* RESTRICT r) void GSState::GIFRegHandlerRGBAQ(const GIFReg* RESTRICT r) { - m_v.RGBAQ = (GSVector4i)r->RGBAQ; + GSVector4i rgbaq = (GSVector4i)r->RGBAQ; + + rgbaq = rgbaq.upl32(rgbaq.blend8(GSVector4i::cast(GSVector4::m_one), rgbaq == GSVector4i::zero()).yyyy()); // see GIFPackedRegHandlerSTQ + + m_v.RGBAQ = rgbaq; } void GSState::GIFRegHandlerST(const GIFReg* RESTRICT r) From 344d0c09ce74a18949e19c4b9c76648416e9ece6 Mon Sep 17 00:00:00 2001 From: gabest11 Date: Tue, 14 Feb 2012 22:22:56 +0000 Subject: [PATCH 07/83] GSdx: check sprite edges! (r5098) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5099 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSState.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index 7fa74ce0d..9580097db 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -2525,7 +2525,7 @@ void GSState::GetTextureMinMax(GSVector4i& r, const GIFRegTEX0& TEX0, const GIFR st += GSVector4(-0.5f, 0.5f).xxyy(); } - GSVector4i uv = GSVector4i(st); + GSVector4i uv = GSVector4i(st.floor()); GSVector4i u, v; From 78c1667a9c3b70935d2ad5f9185ebf409eda04c1 Mon Sep 17 00:00:00 2001 From: gabest11 Date: Wed, 15 Feb 2012 18:57:52 +0000 Subject: [PATCH 08/83] GSdx: Yakuza fix. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5100 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSState.cpp | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index 9580097db..da5ae9291 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -780,13 +780,31 @@ template void GSState::GIFRegHandlerTEX0(const GIFReg* RESTRICT r) { GIFRegTEX0 TEX0 = r->TEX0; - // Tokyo Xtreme Racer Drift 2, TW/TH == 0, PRIM->FST == 1 - // Just setting the max texture size to make the texture cache allocate some surface. - // The vertex trace will narrow the updated area down to the minimum, upper-left 8x8 - // for a single letter, but it may address the whole thing if it wants to. + int tw = (int)TEX0.TW; + int th = (int)TEX0.TH; - if(TEX0.TW > 10 || TEX0.TW == 0) TEX0.TW = 10; - if(TEX0.TH > 10 || TEX0.TH == 0) TEX0.TH = 10; + if(tw > 10) tw = 10; + if(th > 10) th = 10; + + if(PRIM->FST) + { + // Tokyo Xtreme Racer Drift 2, TW/TH == 0 + // Just setting the max texture size to make the texture cache allocate some surface. + // The vertex trace will narrow the updated area down to the minimum, upper-left 8x8 + // for a single letter, but it may address the whole thing if it wants to. + + if(tw == 0) tw = 10; + if(th == 0) th = 10; + } + else + { + // Yakuza, TW/TH == 0 + // The minimap is drawn using solid colors, the texture is really a 1x1 white texel, + // modulated by the vertex color. Cannot change the dimension because S/T are normalized. + } + + TEX0.TW = tw; + TEX0.TH = th; if((TEX0.TBW & 1) && (TEX0.PSM == PSM_PSMT8 || TEX0.PSM == PSM_PSMT4)) { From 7e435329ca71cbc78a51dc4fe6da4b71ba71e764 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Wed, 22 Feb 2012 19:53:59 +0000 Subject: [PATCH 09/83] GSdx: Committing a hack KrossX prepared (thanks) ;) It can be used to fix bad character sprites in Gust games. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5101 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSDeviceDX.h | 1 + plugins/GSdx/GSRendererDX.cpp | 3 +- plugins/GSdx/GSSettingsDlg.cpp | 5 +++ plugins/GSdx/GSTextureCache.cpp | 6 +++ plugins/GSdx/GSTextureCache.h | 2 + plugins/GSdx/GSTextureFX11.cpp | 4 +- plugins/GSdx/GSTextureFX9.cpp | 4 +- plugins/GSdx/GSdx.rc | 76 +++++++++++++++++---------------- plugins/GSdx/res/tfx.fx | 17 ++++++++ plugins/GSdx/resource.h | 4 +- 10 files changed, 82 insertions(+), 40 deletions(-) diff --git a/plugins/GSdx/GSDeviceDX.h b/plugins/GSdx/GSDeviceDX.h index 4ce845665..d3461f46f 100644 --- a/plugins/GSdx/GSDeviceDX.h +++ b/plugins/GSdx/GSDeviceDX.h @@ -173,6 +173,7 @@ public: uint32 ltf:1; uint32 colclip:2; uint32 date:2; + uint32 spritehack; }; uint32 key; diff --git a/plugins/GSdx/GSRendererDX.cpp b/plugins/GSdx/GSRendererDX.cpp index c8b447a79..e3117dcd6 100644 --- a/plugins/GSdx/GSRendererDX.cpp +++ b/plugins/GSdx/GSRendererDX.cpp @@ -280,8 +280,9 @@ void GSRendererDX::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sourc ps_sel.aem = env.TEXA.AEM; ps_sel.tfx = context->TEX0.TFX; ps_sel.tcc = context->TEX0.TCC; - ps_sel.ltf = m_filter == 2 ? m_vt.IsLinear() : m_filter; + ps_sel.ltf = m_filter == 2 ? m_vt.IsLinear() : m_filter; ps_sel.rt = tex->m_target; + ps_sel.spritehack = tex->m_spritehack_t; int w = tex->m_texture->GetWidth(); int h = tex->m_texture->GetHeight(); diff --git a/plugins/GSdx/GSSettingsDlg.cpp b/plugins/GSdx/GSSettingsDlg.cpp index 905b8b5f1..8d723db9d 100644 --- a/plugins/GSdx/GSSettingsDlg.cpp +++ b/plugins/GSdx/GSSettingsDlg.cpp @@ -109,6 +109,7 @@ void GSSettingsDlg::OnInit() // Hacks CheckDlgButton(m_hWnd, IDC_ALPHAHACK, theApp.GetConfig("UserHacks_AlphaHack", 0)); CheckDlgButton(m_hWnd, IDC_OFFSETHACK, theApp.GetConfig("UserHacks_HalfPixelOffset", 0)); + CheckDlgButton(m_hWnd, IDC_SPRITEHACK, theApp.GetConfig("UserHacks_SpriteHack", 0)); SendMessage(GetDlgItem(m_hWnd, IDC_SKIPDRAWHACK), UDM_SETRANGE, 0, MAKELPARAM(1000, 0)); SendMessage(GetDlgItem(m_hWnd, IDC_SKIPDRAWHACK), UDM_SETPOS, 0, MAKELPARAM(theApp.GetConfig("UserHacks_SkipDraw", 0), 0)); @@ -275,6 +276,7 @@ bool GSSettingsDlg::OnCommand(HWND hWnd, UINT id, UINT code) // Hacks theApp.SetConfig("UserHacks_AlphaHack", (int)IsDlgButtonChecked(m_hWnd, IDC_ALPHAHACK)); theApp.SetConfig("UserHacks_HalfPixelOffset", (int)IsDlgButtonChecked(m_hWnd, IDC_OFFSETHACK)); + theApp.SetConfig("UserHacks_SpriteHack", (int)IsDlgButtonChecked(m_hWnd, IDC_SPRITEHACK)); theApp.SetConfig("UserHacks_SkipDraw", (int)SendMessage(GetDlgItem(m_hWnd, IDC_SKIPDRAWHACK), UDM_GETPOS, 0, 0)); } @@ -287,6 +289,7 @@ void GSSettingsDlg::UpdateControls() INT_PTR i; bool allowHacks = !!theApp.GetConfig("allowHacks", 0); + theApp.SetConfig("allowHacks", (int)allowHacks); int scaling = 1; // in case reading the combo doesn't work, enable the custom res control anyway @@ -324,12 +327,14 @@ void GSSettingsDlg::UpdateControls() EnableWindow(GetDlgItem(m_hWnd, IDC_MSAA), hw); //ShowWindow(GetDlgItem(m_hWnd, IDC_USERHACKS), allowHacks && hw) ? SW_SHOW : SW_HIDE; //Don't disable the "Hacks" frame + ShowWindow(GetDlgItem(m_hWnd, IDC_HACKDISABLED), !(allowHacks && hw)) ? SW_SHOW : SW_HIDE; ShowWindow(GetDlgItem(m_hWnd, IDC_MSAAEDIT), allowHacks && hw) ? SW_SHOW : SW_HIDE; ShowWindow(GetDlgItem(m_hWnd, IDC_MSAA), allowHacks && hw) ? SW_SHOW : SW_HIDE; ShowWindow(GetDlgItem(m_hWnd, IDC_STATIC_TEXT_HWAA), allowHacks && hw) ? SW_SHOW : SW_HIDE; ShowWindow(GetDlgItem(m_hWnd, IDC_ALPHAHACK), allowHacks && hw) ? SW_SHOW : SW_HIDE; ShowWindow(GetDlgItem(m_hWnd, IDC_OFFSETHACK), allowHacks && hw) ? SW_SHOW : SW_HIDE; + ShowWindow(GetDlgItem(m_hWnd, IDC_SPRITEHACK), allowHacks && hw) ? SW_SHOW : SW_HIDE; ShowWindow(GetDlgItem(m_hWnd, IDC_SKIPDRAWHACKEDIT), allowHacks && hw) ? SW_SHOW : SW_HIDE; ShowWindow(GetDlgItem(m_hWnd, IDC_SKIPDRAWHACK), allowHacks && hw) ? SW_SHOW : SW_HIDE; diff --git a/plugins/GSdx/GSTextureCache.cpp b/plugins/GSdx/GSTextureCache.cpp index 49743f557..1831d3c25 100644 --- a/plugins/GSdx/GSTextureCache.cpp +++ b/plugins/GSdx/GSTextureCache.cpp @@ -25,6 +25,7 @@ GSTextureCache::GSTextureCache(GSRenderer* r) : m_renderer(r) { + m_spritehack = !!theApp.GetConfig("UserHacks_SpriteHack", 0); m_paltex = !!theApp.GetConfig("paltex", 0); m_temp = (uint8*)_aligned_malloc(1024 * 1024 * sizeof(uint32), 32); @@ -584,6 +585,11 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con if(dst == NULL) { + if(m_spritehack && TEX0.CPSM == 2 && (TEX0.PSM == 19 || TEX0.PSM == 27)) + src->m_spritehack_t = true; + else + src->m_spritehack_t = false; + if(m_paltex && GSLocalMemory::m_psm[TEX0.PSM].pal > 0) { src->m_fmt = FMT_8; diff --git a/plugins/GSdx/GSTextureCache.h b/plugins/GSdx/GSTextureCache.h index 3706ac785..7f5e3ba89 100644 --- a/plugins/GSdx/GSTextureCache.h +++ b/plugins/GSdx/GSTextureCache.h @@ -75,6 +75,7 @@ public: bool m_target; bool m_complete; bool m_repeating; + bool m_spritehack_t; vector* m_p2t; public: @@ -118,6 +119,7 @@ protected: SourceMap m_src; list m_dst[2]; bool m_paltex; + bool m_spritehack; uint8* m_temp; virtual Source* CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* t = NULL); diff --git a/plugins/GSdx/GSTextureFX11.cpp b/plugins/GSdx/GSTextureFX11.cpp index 5e7171b29..84189a7d8 100644 --- a/plugins/GSdx/GSTextureFX11.cpp +++ b/plugins/GSdx/GSTextureFX11.cpp @@ -177,7 +177,7 @@ void GSDevice11::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSe if(i == m_ps.end()) { - string str[15]; + string str[16]; str[0] = format("%d", sel.fst); str[1] = format("%d", sel.wms); @@ -194,6 +194,7 @@ void GSDevice11::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSe str[12] = format("%d", sel.ltf); str[13] = format("%d", sel.colclip); str[14] = format("%d", sel.date); + str[15] = format("%d", sel.spritehack); D3D11_SHADER_MACRO macro[] = { @@ -212,6 +213,7 @@ void GSDevice11::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSe {"PS_LTF", str[12].c_str()}, {"PS_COLCLIP", str[13].c_str()}, {"PS_DATE", str[14].c_str()}, + {"PS_SPRITEHACK", str[15].c_str()}, {NULL, NULL}, }; diff --git a/plugins/GSdx/GSTextureFX9.cpp b/plugins/GSdx/GSTextureFX9.cpp index 617333412..a8e0d913b 100644 --- a/plugins/GSdx/GSTextureFX9.cpp +++ b/plugins/GSdx/GSTextureFX9.cpp @@ -135,7 +135,7 @@ void GSDevice9::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSel if(i == m_ps.end()) { - string str[14]; + string str[15]; str[0] = format("%d", sel.fst); str[1] = format("%d", sel.wms); @@ -151,6 +151,7 @@ void GSDevice9::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSel str[11] = format("%d", sel.ltf); str[12] = format("%d", sel.colclip); str[13] = format("%d", sel.date); + str[14] = format("%d", sel.spritehack); D3DXMACRO macro[] = { @@ -168,6 +169,7 @@ void GSDevice9::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSel {"PS_LTF", str[11].c_str()}, {"PS_COLCLIP", str[12].c_str()}, {"PS_DATE", str[13].c_str()}, + {"PS_SPRITEHACK", str[14].c_str()}, {NULL, NULL}, }; diff --git a/plugins/GSdx/GSdx.rc b/plugins/GSdx/GSdx.rc index 5c7c47230..061d51bc9 100644 --- a/plugins/GSdx/GSdx.rc +++ b/plugins/GSdx/GSdx.rc @@ -72,7 +72,7 @@ IDB_LOGO10 BITMAP "res\\logo10.bmp" // Dialog // -IDD_CONFIG DIALOGEX 0, 0, 189, 351 +IDD_CONFIG DIALOGEX 0, 0, 189, 327 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Settings..." FONT 8, "MS Shell Dlg", 400, 0, 0x1 @@ -87,8 +87,8 @@ BEGIN COMBOBOX IDC_INTERLACE,71,86,111,98,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Aspect Ratio (F6):",IDC_STATIC,7,104,60,8 COMBOBOX IDC_ASPECTRATIO,71,101,111,98,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - DEFPUSHBUTTON "OK",IDOK,43,323,50,14 - PUSHBUTTON "Cancel",IDCANCEL,96,323,50,14 + DEFPUSHBUTTON "OK",IDOK,43,303,50,14 + PUSHBUTTON "Cancel",IDCANCEL,96,303,50,14 CONTROL "Windowed",IDC_WINDOWED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,89,231,93,10 LTEXT "D3D internal res:",IDC_STATIC,18,135,55,8 EDITTEXT IDC_RESX_EDIT,82,132,35,13,ES_AUTOHSCROLL | ES_NUMBER @@ -99,9 +99,9 @@ BEGIN COMBOBOX IDC_UPSCALE_MULTIPLIER,82,147,74,98,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Or use Scaling:",IDC_STATIC,18,150,49,8 LTEXT "Or use original PS2 resolution :",IDC_STATIC,18,165,99,8 - EDITTEXT IDC_MSAAEDIT,75,258,35,13,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_MSAA,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,109,261,11,14 - LTEXT "HW Anti Aliasing",IDC_STATIC_TEXT_HWAA,18,261,53,8 + EDITTEXT IDC_MSAAEDIT,45,259,35,13,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_MSAA,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,76,261,11,14 + LTEXT "HW AA",IDC_STATIC_TEXT_HWAA,18,261,24,8 GROUPBOX "D3D Enhancements (can cause glitches)",IDC_STATIC,7,117,175,66 LTEXT "Extra rendering threads:",IDC_STATIC,7,189,80,8 EDITTEXT IDC_SWTHREADS_EDIT,89,187,35,13,ES_AUTOHSCROLL | ES_NUMBER @@ -111,12 +111,14 @@ BEGIN CONTROL "Allow 8-bit textures",IDC_PALTEX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,217,82,10 CONTROL "Alpha correction (FBA)",IDC_FBA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,89,217,93,10 CONTROL "Edge anti-aliasing",IDC_AA1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,231,72,10 - CONTROL "Alpha Hack",IDC_ALPHAHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,279,51,10 - CONTROL "Offset Hack",IDC_OFFSETHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,85,279,51,10 - GROUPBOX "Hacks",IDC_USERHACKS,13,244,161,71,BS_CENTER - EDITTEXT IDC_SKIPDRAWHACKEDIT,55,291,40,14,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_SKIPDRAWHACK,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,94,293,11,14 - LTEXT "SkipDraw:",IDC_STATIC_TEXT_SKIPDRAW,20,293,33,8 + CONTROL "Alpha Hack",IDC_ALPHAHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,280,51,10 + CONTROL "Offset Hack",IDC_OFFSETHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,67,280,51,10 + GROUPBOX "Hacks",IDC_USERHACKS,7,244,175,53,BS_CENTER + EDITTEXT IDC_SKIPDRAWHACKEDIT,122,259,40,14,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_SKIPDRAWHACK,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,161,261,11,14 + LTEXT "SkipDraw:",IDC_STATIC_TEXT_SKIPDRAW,89,261,33,8 + CONTROL "Sprite Hack",IDC_SPRITEHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,123,280,51,10 + LTEXT "HACKS DISABLED",IDC_HACKDISABLED,64,268,57,8,WS_DISABLED END IDD_CAPTURE DIALOGEX 0, 0, 279, 71 @@ -163,48 +165,50 @@ BEGIN CONTROL "Windowed",IDC_WINDOWED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,129,157,49,10 END -IDD_CONFIG2 DIALOGEX 0, 0, 187, 341 +IDD_CONFIG2 DIALOGEX 0, 0, 187, 325 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Settings..." FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN CONTROL 2022,IDC_LOGO11,"Static",SS_BITMAP,6,6,173,42 - DEFPUSHBUTTON "OK",IDOK,41,312,50,14 + DEFPUSHBUTTON "OK",IDOK,41,301,50,14 LTEXT "Renderer:",IDC_STATIC,6,57,34,8 COMBOBOX IDC_RENDERER,70,55,111,118,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Interlacing (F5):",IDC_STATIC,6,73,81,8 COMBOBOX IDC_INTERLACE,70,70,111,98,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "Custom resolution:",IDC_STATIC,26,135,65,8 + LTEXT "Custom resolution:",IDC_STATIC,26,134,65,8 EDITTEXT IDC_RESX_EDIT,92,132,35,13,ES_AUTOHSCROLL | ES_NUMBER CONTROL "",IDC_RESX,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,120,135,11,14 EDITTEXT IDC_RESY_EDIT,130,132,35,13,ES_AUTOHSCROLL | ES_NUMBER CONTROL "",IDC_RESY,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,154,130,11,14 CONTROL "Native",IDC_NATIVERES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,92,105,33,10 - LTEXT "Extra rendering threads:",IDC_STATIC,19,214,80,8 - EDITTEXT IDC_SWTHREADS_EDIT,102,212,35,13,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_SWTHREADS,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,135,215,11,14 + LTEXT "Extra rendering threads:",IDC_STATIC,11,214,80,8 + EDITTEXT IDC_SWTHREADS_EDIT,94,212,35,13,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_SWTHREADS,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,127,215,11,14 COMBOBOX IDC_UPSCALE_MULTIPLIER,92,117,74,98,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "Or use Scaling:",IDC_STATIC,38,120,49,8 + LTEXT "Or use Scaling:",IDC_STATIC,38,119,49,8 LTEXT "Original PS2 resolution :",IDC_STATIC,10,105,80,8 - CONTROL "Edge anti-aliasing (AA1)",IDC_AA1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,230,93,10 - PUSHBUTTON "Cancel",IDCANCEL,95,312,50,14 + CONTROL "Edge anti-aliasing (AA1)",IDC_AA1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,230,93,10 + PUSHBUTTON "Cancel",IDCANCEL,95,301,50,14 CONTROL 2021,IDC_LOGO9,"Static",SS_BITMAP,6,6,175,44 - CONTROL "Alpha Hack",IDC_ALPHAHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,275,51,10 - CONTROL "Offset Hack",IDC_OFFSETHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,87,275,51,10 - GROUPBOX "Hacks",IDC_USERHACKS,6,250,175,55,BS_CENTER - EDITTEXT IDC_SKIPDRAWHACKEDIT,65,286,40,14,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_SKIPDRAWHACK,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,104,288,11,14 - LTEXT "Skipdraw Hack:",IDC_STATIC_TEXT_SKIPDRAW,11,289,50,8 - EDITTEXT IDC_MSAAEDIT,69,260,35,13,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_MSAA,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,103,263,11,14 + CONTROL "Alpha Hack",IDC_ALPHAHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,279,51,10 + CONTROL "Offset Hack",IDC_OFFSETHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,65,279,51,10 + GROUPBOX "Hacks",IDC_USERHACKS,6,250,175,45,BS_CENTER + EDITTEXT IDC_SKIPDRAWHACKEDIT,125,260,40,14,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_SKIPDRAWHACK,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,164,262,11,14 + LTEXT "Skipdraw",IDC_STATIC_TEXT_SKIPDRAW,93,262,30,8 + EDITTEXT IDC_MSAAEDIT,38,260,35,13,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_MSAA,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,72,263,11,14 GROUPBOX "D3D Internal resolution (can cause glitches)",IDC_STATIC,6,87,175,64,BS_CENTER GROUPBOX "Software Mode Settings",IDC_STATIC,6,198,175,50,BS_CENTER GROUPBOX "Hardware Mode Settings",IDC_STATIC,6,152,175,45,BS_CENTER - CONTROL "Logarithmic Z",IDC_LOGZ,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,88,166,58,10 - CONTROL "Alpha correction (FBA)",IDC_FBA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,88,179,87,10 - CONTROL "Allow 8-bit textures",IDC_PALTEX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,179,82,10 - CONTROL "Texture filtering",IDC_FILTER,"Button",BS_AUTO3STATE | WS_TABSTOP,6,165,67,10 - LTEXT "HW Anti Aliasing",IDC_STATIC_TEXT_HWAA,11,263,53,8 + CONTROL "Logarithmic Z",IDC_LOGZ,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,92,166,58,10 + CONTROL "Alpha correction (FBA)",IDC_FBA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,92,179,87,10 + CONTROL "Allow 8-bit textures",IDC_PALTEX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,179,82,10 + CONTROL "Texture filtering",IDC_FILTER,"Button",BS_AUTO3STATE | WS_TABSTOP,10,165,67,10 + LTEXT "HW AA",IDC_STATIC_TEXT_HWAA,11,262,24,8 + CONTROL "Sprite Hack",IDC_SPRITEHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,125,279,51,10 + LTEXT "HACKS DISABLED",IDC_HACKDISABLED,62,268,57,8,WS_DISABLED END @@ -224,7 +228,7 @@ BEGIN VERTGUIDE, 89 VERTGUIDE, 182 TOPMARGIN, 7 - BOTTOMMARGIN, 344 + BOTTOMMARGIN, 320 HORZGUIDE, 49 END @@ -252,7 +256,7 @@ BEGIN RIGHTMARGIN, 181 VERTGUIDE, 87 TOPMARGIN, 6 - BOTTOMMARGIN, 334 + BOTTOMMARGIN, 318 END END #endif // APSTUDIO_INVOKED diff --git a/plugins/GSdx/res/tfx.fx b/plugins/GSdx/res/tfx.fx index 2372bbf1d..96f4354ff 100644 --- a/plugins/GSdx/res/tfx.fx +++ b/plugins/GSdx/res/tfx.fx @@ -36,6 +36,7 @@ #define PS_LTF 1 #define PS_COLCLIP 0 #define PS_DATE 0 +#define PS_SPRITEHACK 0 #endif struct VS_INPUT @@ -412,7 +413,19 @@ float4 sample(float2 st, float q) if(PS_LTF) { + #if PS_SPRITEHACK + c[0].rgb *= c[0].a; + c[1].rgb *= c[1].a; + c[2].rgb *= c[2].a; + c[3].rgb *= c[3].a; + #endif + t = lerp(lerp(c[0], c[1], dd.x), lerp(c[2], c[3], dd.x), dd.y); + + #if PS_SPRITEHACK + t.rgb /= t.a; + if(t.a < 0.25) t.a = 0; + #endif } else { @@ -422,6 +435,10 @@ float4 sample(float2 st, float q) if(PS_FMT == FMT_32) { + #if PS_SPRITEHACK + if(t.a < 0.25) t.a = 0; + #endif + #if SHADER_MODEL <= 0x300 if(PS_RT) t.a *= 128.0f / 255; #endif diff --git a/plugins/GSdx/resource.h b/plugins/GSdx/resource.h index b3e8f0207..884f58900 100644 --- a/plugins/GSdx/resource.h +++ b/plugins/GSdx/resource.h @@ -74,6 +74,8 @@ #define IDC_USERHACKS 2047 #define IDC_SKIPDRAWHACKEDIT 2048 #define IDC_STATIC10 2049 +#define IDC_HACKDISABLED 2050 +#define IDC_SPRITEHACK 2051 #define IDC_COLORSPACE 3000 #define IDR_CONVERT_FX 10000 #define IDR_TFX_FX 10001 @@ -89,7 +91,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 10007 #define _APS_NEXT_COMMAND_VALUE 32771 -#define _APS_NEXT_CONTROL_VALUE 2050 +#define _APS_NEXT_CONTROL_VALUE 2052 #define _APS_NEXT_SYMED_VALUE 5000 #endif #endif From 3bbb2d6ed342fb3773bc9bb9c36d53a00c654326 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Wed, 22 Feb 2012 20:05:41 +0000 Subject: [PATCH 10/83] Small mistake fixed. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5102 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSDeviceDX.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/GSdx/GSDeviceDX.h b/plugins/GSdx/GSDeviceDX.h index d3461f46f..76edd6939 100644 --- a/plugins/GSdx/GSDeviceDX.h +++ b/plugins/GSdx/GSDeviceDX.h @@ -173,7 +173,7 @@ public: uint32 ltf:1; uint32 colclip:2; uint32 date:2; - uint32 spritehack; + uint32 spritehack:1; }; uint32 key; From bc4ce5b1bf3af4b55adf6c67fc7f4f1a7390d7be Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Wed, 22 Feb 2012 21:04:58 +0000 Subject: [PATCH 11/83] Removed the mVU block hack. This hack didn't help speed a lot (generally only about 2% if at all) but it caused slow downs and bugs in some games. People enabled it for a performance boost and often got the reverse, so now it's gone. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5103 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/Config.h | 1 - pcsx2/Pcsx2Config.cpp | 1 - pcsx2/gui/AppConfig.cpp | 3 +-- pcsx2/gui/Panels/ConfigurationPanels.h | 1 - pcsx2/gui/Panels/SpeedhacksPanel.cpp | 11 ----------- pcsx2/x86/microVU_Flags.inl | 2 +- pcsx2/x86/microVU_Misc.h | 7 ------- 7 files changed, 2 insertions(+), 24 deletions(-) diff --git a/pcsx2/Config.h b/pcsx2/Config.h index f129d5148..b46ce04f2 100644 --- a/pcsx2/Config.h +++ b/pcsx2/Config.h @@ -381,7 +381,6 @@ struct Pcsx2Config IntcStat :1, // tells Pcsx2 to fast-forward through intc_stat waits. WaitLoop :1, // enables constant loop detection and fast-forwarding vuFlagHack :1, // microVU specific flag hack - vuBlockHack :1, // microVU specific block flag no-propagation hack vuThread :1; // Enable Threaded VU1 BITFIELD_END diff --git a/pcsx2/Pcsx2Config.cpp b/pcsx2/Pcsx2Config.cpp index 7bb835c65..a9ca357a4 100644 --- a/pcsx2/Pcsx2Config.cpp +++ b/pcsx2/Pcsx2Config.cpp @@ -63,7 +63,6 @@ void Pcsx2Config::SpeedhackOptions::LoadSave( IniInterface& ini ) IniBitBool( IntcStat ); IniBitBool( WaitLoop ); IniBitBool( vuFlagHack ); - IniBitBool( vuBlockHack ); IniBitBool( vuThread ); } diff --git a/pcsx2/gui/AppConfig.cpp b/pcsx2/gui/AppConfig.cpp index e64649939..ddf65394c 100644 --- a/pcsx2/gui/AppConfig.cpp +++ b/pcsx2/gui/AppConfig.cpp @@ -922,9 +922,8 @@ bool AppConfig::IsOkApplyPreset(int n) case 4 : //set EE cyclerate to 2 clicks (maximum) eeUsed?0:(eeUsed=true, EmuOptions.Speedhacks.EECycleRate = 2); - case 3 : //Set VU cycle steal to 1 click, enable (m)vuBlockHack, set VU clamp mode to 'none' + case 3 : //Set VU cycle steal to 1 click, set VU clamp mode to 'none' vuUsed?0:(vuUsed=true, EmuOptions.Speedhacks.VUCycleSteal = 1); - EmuOptions.Speedhacks.vuBlockHack = true; EmuOptions.Cpu.Recompiler.vuOverflow = EmuOptions.Cpu.Recompiler.vuExtraOverflow = EmuOptions.Cpu.Recompiler.vuSignOverflow = false; //VU Clamp mode to 'none' diff --git a/pcsx2/gui/Panels/ConfigurationPanels.h b/pcsx2/gui/Panels/ConfigurationPanels.h index 19366862e..43209f89a 100644 --- a/pcsx2/gui/Panels/ConfigurationPanels.h +++ b/pcsx2/gui/Panels/ConfigurationPanels.h @@ -334,7 +334,6 @@ namespace Panels pxCheckBox* m_check_waitloop; pxCheckBox* m_check_fastCDVD; pxCheckBox* m_check_vuFlagHack; - pxCheckBox* m_check_vuBlockHack; pxCheckBox* m_check_vuThread; public: diff --git a/pcsx2/gui/Panels/SpeedhacksPanel.cpp b/pcsx2/gui/Panels/SpeedhacksPanel.cpp index d7db4d164..0052b1a0d 100644 --- a/pcsx2/gui/Panels/SpeedhacksPanel.cpp +++ b/pcsx2/gui/Panels/SpeedhacksPanel.cpp @@ -163,9 +163,6 @@ Panels::SpeedHacksPanel::SpeedHacksPanel( wxWindow* parent ) m_check_vuFlagHack = new pxCheckBox( vuHacksPanel, _("mVU Flag Hack"), _("Good Speedup and High Compatibility; may cause bad graphics... [Recommended]" ) ); - m_check_vuBlockHack = new pxCheckBox( vuHacksPanel, _("mVU Block Hack"), - _("Good Speedup and High Compatibility; may cause bad graphics, SPS, etc...") ); - m_check_vuThread = new pxCheckBox( vuHacksPanel, _("MTVU (Multi-Threaded microVU1)"), _("Good Speedup and High Compatibility; may cause hanging... [Recommended if 3+ cores]") ); @@ -174,11 +171,6 @@ Panels::SpeedHacksPanel::SpeedHacksPanel( wxWindow* parent ) L"This is safe most of the time, and Super VU does something similar by default." ) ); - m_check_vuBlockHack->SetToolTip( pxEt( "!ContextTip:Speedhacks:vuBlockHack", - L"Assumes that very far into future blocks will not need old flag instance data. " - L"This should be pretty safe. It is unknown if this breaks any game..." - ) ); - m_check_vuThread->SetToolTip( pxEt( "!ContextTip:Speedhacks:vuThread", L"Runs VU1 on its own thread (microVU1-only). Generally a speedup on CPUs with 3 or more cores. " L"This is safe for most games, but a few games are incompatible and may hang. " @@ -234,7 +226,6 @@ Panels::SpeedHacksPanel::SpeedHacksPanel( wxWindow* parent ) *vuSliderPanel += m_msg_vustealer | sliderFlags; *vuHacksPanel += m_check_vuFlagHack; - *vuHacksPanel += m_check_vuBlockHack; *vuHacksPanel += m_check_vuThread; //*vuHacksPanel += 57; // Aligns left and right boxes in default language and font size @@ -313,7 +304,6 @@ void Panels::SpeedHacksPanel::ApplyConfigToGui( AppConfig& configToApply, int fl SetVUcycleSliderMsg(); m_check_vuFlagHack ->SetValue(opts.vuFlagHack); - m_check_vuBlockHack ->SetValue(opts.vuBlockHack); m_check_vuThread ->SetValue(opts.vuThread); m_check_intc ->SetValue(opts.IntcStat); m_check_waitloop ->SetValue(opts.WaitLoop); @@ -343,7 +333,6 @@ void Panels::SpeedHacksPanel::Apply() opts.fastCDVD = m_check_fastCDVD->GetValue(); opts.IntcStat = m_check_intc->GetValue(); opts.vuFlagHack = m_check_vuFlagHack->GetValue(); - opts.vuBlockHack = m_check_vuBlockHack->GetValue(); opts.vuThread = m_check_vuThread->GetValue(); // If the user has a command line override specified, we need to disable it diff --git a/pcsx2/x86/microVU_Flags.inl b/pcsx2/x86/microVU_Flags.inl index 7d215ab42..b908e5231 100644 --- a/pcsx2/x86/microVU_Flags.inl +++ b/pcsx2/x86/microVU_Flags.inl @@ -290,7 +290,7 @@ __fi void mVUsetupFlags(mV, microFlagCycles& mFC) { branch = 0; \ } \ else if (branch == 5) { /*JR/JARL*/ \ - if(!CHECK_VU_BLOCKHACK && (sCount+found<4)) { \ + if(sCount+found<4) { \ mVUregs.needExactMatch |= 7; \ } \ break; \ diff --git a/pcsx2/x86/microVU_Misc.h b/pcsx2/x86/microVU_Misc.h index 17aed5ed7..bc05ddc53 100644 --- a/pcsx2/x86/microVU_Misc.h +++ b/pcsx2/x86/microVU_Misc.h @@ -359,13 +359,6 @@ static const bool doJumpAsSameProgram = 0; // Set to 1 to treat jumps as same pr // This hack only updates the Status Flag on blocks that will read it. // Most blocks do not read status flags, so this is a big speedup. -// Block Flag Instance No-Propagation Hack -#define CHECK_VU_BLOCKHACK (EmuConfig.Speedhacks.vuBlockHack) -// There are times when it is unknown if future blocks will need old -// flag instance data (due to indirect jumps). This hack assumes -// that they won't need old flag data. This effectively removes a lot -// of end-of-block flag instance shuffling, causing nice speedups. - // Min/Max Speed Hack #define CHECK_VU_MINMAXHACK 0 //(EmuConfig.Speedhacks.vuMinMax) // This hack uses SSE min/max instructions instead of emulated "logical min/max" From 538bc76686132c8f5ba088db6e0a4bdc2bb6c68f Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Sat, 25 Feb 2012 20:06:39 +0000 Subject: [PATCH 12/83] GSdx: KrossX updated the sprite hack to also work on other games with a similar problem. It works with a 3 state checkbox now. Try to use full when half checked doesn't fix your game. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5104 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSTextureCache.cpp | 9 +++++++-- plugins/GSdx/GSTextureCache.h | 2 +- plugins/GSdx/GSdx.rc | 4 ++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/plugins/GSdx/GSTextureCache.cpp b/plugins/GSdx/GSTextureCache.cpp index 1831d3c25..8ca4952f1 100644 --- a/plugins/GSdx/GSTextureCache.cpp +++ b/plugins/GSdx/GSTextureCache.cpp @@ -25,7 +25,7 @@ GSTextureCache::GSTextureCache(GSRenderer* r) : m_renderer(r) { - m_spritehack = !!theApp.GetConfig("UserHacks_SpriteHack", 0); + m_spritehack = theApp.GetConfig("UserHacks_SpriteHack", 0); m_paltex = !!theApp.GetConfig("paltex", 0); m_temp = (uint8*)_aligned_malloc(1024 * 1024 * sizeof(uint32), 32); @@ -585,8 +585,13 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con if(dst == NULL) { - if(m_spritehack && TEX0.CPSM == 2 && (TEX0.PSM == 19 || TEX0.PSM == 27)) + if(m_spritehack && (TEX0.PSM == PSM_PSMT8 || TEX0.PSM == PSM_PSMT8H)) + { src->m_spritehack_t = true; + + if(m_spritehack == 2 && TEX0.CPSM != PSM_PSMCT16) + src->m_spritehack_t = false; + } else src->m_spritehack_t = false; diff --git a/plugins/GSdx/GSTextureCache.h b/plugins/GSdx/GSTextureCache.h index 7f5e3ba89..726917048 100644 --- a/plugins/GSdx/GSTextureCache.h +++ b/plugins/GSdx/GSTextureCache.h @@ -119,7 +119,7 @@ protected: SourceMap m_src; list m_dst[2]; bool m_paltex; - bool m_spritehack; + int m_spritehack; uint8* m_temp; virtual Source* CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* t = NULL); diff --git a/plugins/GSdx/GSdx.rc b/plugins/GSdx/GSdx.rc index 061d51bc9..dadfc1de6 100644 --- a/plugins/GSdx/GSdx.rc +++ b/plugins/GSdx/GSdx.rc @@ -117,7 +117,7 @@ BEGIN EDITTEXT IDC_SKIPDRAWHACKEDIT,122,259,40,14,ES_AUTOHSCROLL | ES_NUMBER CONTROL "",IDC_SKIPDRAWHACK,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,161,261,11,14 LTEXT "SkipDraw:",IDC_STATIC_TEXT_SKIPDRAW,89,261,33,8 - CONTROL "Sprite Hack",IDC_SPRITEHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,123,280,51,10 + CONTROL "Sprite Hack",IDC_SPRITEHACK,"Button",BS_AUTO3STATE | WS_TABSTOP,123,280,51,10 LTEXT "HACKS DISABLED",IDC_HACKDISABLED,64,268,57,8,WS_DISABLED END @@ -207,7 +207,7 @@ BEGIN CONTROL "Allow 8-bit textures",IDC_PALTEX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,179,82,10 CONTROL "Texture filtering",IDC_FILTER,"Button",BS_AUTO3STATE | WS_TABSTOP,10,165,67,10 LTEXT "HW AA",IDC_STATIC_TEXT_HWAA,11,262,24,8 - CONTROL "Sprite Hack",IDC_SPRITEHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,125,279,51,10 + CONTROL "Sprite Hack",IDC_SPRITEHACK,"Button",BS_AUTO3STATE | WS_TABSTOP,125,279,51,10 LTEXT "HACKS DISABLED",IDC_HACKDISABLED,62,268,57,8,WS_DISABLED END From aa987595b4e10a95eaf65351d3ffdf8695b286f4 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Sun, 26 Feb 2012 11:34:29 +0000 Subject: [PATCH 13/83] Attempt to fix ICO NTSC CDVD flag bug that appeared in r4961. Works with my copies of Time Crisis 2 and 3 as well. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5105 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/CDVD/CDVD.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pcsx2/CDVD/CDVD.cpp b/pcsx2/CDVD/CDVD.cpp index 90931da71..63550938b 100644 --- a/pcsx2/CDVD/CDVD.cpp +++ b/pcsx2/CDVD/CDVD.cpp @@ -897,8 +897,9 @@ static uint cdvdStartSeek( uint newsector, CDVD_MODE_TYPE mode ) cdvd.Ready = CDVD_NOTREADY; cdvd.Reading = 0; cdvd.Readed = 0; - //cdvd.Status = CDVD_STATUS_STOP; - cdvd.Status = CDVD_STATUS_SEEK | CDVD_STATUS_SPIN; // Time Crisis 2 + //cdvd.Status = CDVD_STATUS_STOP; // before r4961 + //cdvd.Status = CDVD_STATUS_SEEK | CDVD_STATUS_SPIN; // Time Crisis 2 // but breaks ICO NTSC + cdvd.Status = CDVD_STATUS_PAUSE; // best so far in my tests (rama) if( !cdvd.Spinning ) { From 2ea4b2fe49ab3089bd9ec6633da7c4a4065b5358 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Tue, 28 Feb 2012 11:22:02 +0000 Subject: [PATCH 14/83] i18n: refresh po/mo git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5106 96395faa-99c1-11dd-bbfe-3dabce05a288 --- bin/Langs/cs_CZ/pcsx2_Iconized.mo | Bin 18553 -> 18311 bytes bin/Langs/cs_CZ/pcsx2_Main.mo | Bin 55883 -> 55658 bytes bin/Langs/de_DE/pcsx2_Iconized.mo | Bin 11834 -> 11717 bytes bin/Langs/de_DE/pcsx2_Main.mo | Bin 47265 -> 47179 bytes bin/Langs/es_ES/pcsx2_Iconized.mo | Bin 19737 -> 19494 bytes bin/Langs/es_ES/pcsx2_Main.mo | Bin 57261 -> 57032 bytes bin/Langs/hu_HU/pcsx2_Iconized.mo | Bin 19196 -> 18941 bytes bin/Langs/hu_HU/pcsx2_Main.mo | Bin 51327 -> 51241 bytes bin/Langs/it_IT/pcsx2_Iconized.mo | Bin 19989 -> 19750 bytes bin/Langs/it_IT/pcsx2_Main.mo | Bin 57221 -> 56983 bytes bin/Langs/ja_JP/pcsx2_Iconized.mo | Bin 20759 -> 20499 bytes bin/Langs/ja_JP/pcsx2_Main.mo | Bin 59284 -> 59238 bytes bin/Langs/pl_PL/pcsx2_Iconized.mo | Bin 18162 -> 17914 bytes bin/Langs/pl_PL/pcsx2_Main.mo | Bin 55153 -> 54925 bytes bin/Langs/pt_BR/pcsx2_Iconized.mo | Bin 19248 -> 19013 bytes bin/Langs/pt_BR/pcsx2_Main.mo | Bin 56810 -> 56589 bytes bin/Langs/ru_RU/pcsx2_Iconized.mo | Bin 28771 -> 28339 bytes bin/Langs/ru_RU/pcsx2_Main.mo | Bin 70322 -> 70252 bytes bin/Langs/sv_SE/pcsx2_Iconized.mo | Bin 18365 -> 18127 bytes bin/Langs/sv_SE/pcsx2_Main.mo | Bin 54315 -> 54102 bytes bin/Langs/tr_TR/pcsx2_Iconized.mo | Bin 6242 -> 6156 bytes bin/Langs/tr_TR/pcsx2_Main.mo | Bin 52757 -> 52711 bytes bin/Langs/zh_CN/pcsx2_Iconized.mo | Bin 15479 -> 15304 bytes bin/Langs/zh_CN/pcsx2_Main.mo | Bin 51293 -> 51084 bytes bin/Langs/zh_TW/pcsx2_Iconized.mo | Bin 17055 -> 16888 bytes bin/Langs/zh_TW/pcsx2_Main.mo | Bin 53213 -> 52968 bytes locales/cs_CZ/pcsx2_Iconized.po | 327 ++++++++++--- locales/cs_CZ/pcsx2_Main.po | 697 ++++++++++++++++++--------- locales/de_DE/pcsx2_Iconized.po | 27 +- locales/de_DE/pcsx2_Main.po | 78 ++- locales/es_ES/pcsx2_Iconized.po | 35 +- locales/es_ES/pcsx2_Main.po | 80 ++- locales/hu_HU/pcsx2_Iconized.po | 33 +- locales/hu_HU/pcsx2_Main.po | 82 ++-- locales/it_IT/pcsx2_Iconized.po | 35 +- locales/it_IT/pcsx2_Main.po | 80 ++- locales/ja_JP/pcsx2_Iconized.po | 31 +- locales/ja_JP/pcsx2_Main.po | 82 ++-- locales/pl_PL/pcsx2_Iconized.po | 35 +- locales/pl_PL/pcsx2_Main.po | 80 ++- locales/pt_BR/pcsx2_Iconized.po | 33 +- locales/pt_BR/pcsx2_Main.po | 80 ++- locales/ru_RU/pcsx2_Iconized.po | 33 +- locales/ru_RU/pcsx2_Main.po | 82 ++-- locales/sv_SE/pcsx2_Iconized.po | 35 +- locales/sv_SE/pcsx2_Main.po | 78 ++- locales/templates/pcsx2_Iconized.pot | 24 +- locales/templates/pcsx2_Main.pot | 68 ++- locales/tr_TR/pcsx2_Iconized.po | 27 +- locales/tr_TR/pcsx2_Main.po | 82 ++-- locales/zh_CN/pcsx2_Iconized.po | 31 +- locales/zh_CN/pcsx2_Main.po | 430 ++++++++++------- locales/zh_TW/pcsx2_Iconized.po | 31 +- locales/zh_TW/pcsx2_Main.po | 80 ++- 54 files changed, 1638 insertions(+), 1178 deletions(-) diff --git a/bin/Langs/cs_CZ/pcsx2_Iconized.mo b/bin/Langs/cs_CZ/pcsx2_Iconized.mo index 7db2fc6f1990dbe0dc3e53dc708542a3519da239..8cebe24e3e8ad0f441116f050ddc82839193b1de 100644 GIT binary patch delta 1643 zcmY+^duWYe9KiA4*=F~P9dp^(c8nck&YYdu91Js#%fgN_(ui_duBkECI{C|GiZUs= z#}Z4ja*JGsGLkVInK=W&{UHFj8ay&P5llw&PmNAU=coUK6Hc3%an|zMdH+(x12(hu}OMid(EW zB**LvcTpSqfWt97T4W%4(1SBE6F1{vJZ#6;Q9FKxso06yPI8R(d>-lq=AaIw3bQeU z=@Jq-Yd_FrKkx?o@xXV~hT>u^bFeRQ0Cnb-s2y%YZMY7d*nm3l+n9x~(T&}hhS_l< zNmzo}^e;h9bOtrHb*KZlj4phH+TkbEnZ(3f4QHVl5b6LbQSVoyW@?`uH=uU>0Cm7E zsL%hxkdD-uV2wD>whZ-!m8cEvv^`~e7j+3*QJ)J>v>MJpZP<^Ri6H6#m!ZyhE0(gq z_TXCLC%wu4UQWg)i!|eXJc;{x`x<)th#bd{SdF_=xaSc0gG-6`k*0EN#~V0--j`z+ z25~XzILz}G@iXx>M*9^Dne}ya4v22lFq;>$$oFaD4NQLt_Hi*=ti~_g zuNW+HfjGdHeoEYdRm6ALS-UWY1#iboxE+rV6RG97v>cI1#P!2P^t1aA;^ZYKJ4O&- zMJ}Vp;*n$pkKj&xjz@96N8~+zLodF}6L~?yF{7*o-*NE-@uqwR#{IqpA`9_7YDOoH zW)R%(#H$!`7Li77G>;MafeZYk31`#0rnC;vVfi>VAa>zjY#T2!iUwMXnI&=ZL@Sf` za2@etrl}cuj2p3_gzVrsT!gD8i>#-AdB};Ttgw{z!&?}{-{_`;SyM!cuzIRBu=4@- z3HLkj8D3$u+%_8xdJ4_T461HC#@tght0c$#W2Wo(uZ1L-Z#K+C)`2}EtcpZY$-c0J zl0aoV<`2erdJ0J}MRz?bBkWg`MZHKu%~wK#|0^U)hG_p~RI(&2p(%wN*}%e*$xJFs zCE-*p>>r7xYNl9f^MgsjRB9$w3yBdvBvTSOvPDcu=NL`pV-Z$QT-32X4rE&5sai_R z(fYpilnrfuKE06tkNG2l}u*Kf7+izX^C$aXB-sDW@0%JOBb>5iwu4!JF-NI(2oY=ZhaK*pgx7#?*f+M4K(P< zPPNzIQtFT3T^Pc<@ugHfAro%HdDMY!;wmi25h=m-=*4Zg0tay=zJqt-Ik){s)CuIy z7g>gtsN-!y?dL~b$R5-QjbNE1L{4y_9p~H!Zn_WTFA%w%_6pR2Hn?ubCDflo-GP0m zFPuOf_$)5QOQ;L@1$Dxng(BrxhsF35=JS5(<)RGtqE2Mo^(^WHuA;%eQD0b^n_9^_ z)PbKwXF{kG*yr9qin{VMZv7JKi~m5Ka6z6(LOXc5(3!Tn`dwc@?J$fw(3I=fuD_zD zpwN?gt^sx6$5F=(qwd6B)CnHKe0&dEIAOC;pCa<7f1q#$bWS zo4CA?-NH|Bf0{@Qqwb)7hHct{hPQrs3<`%yX;viu{|14iUo%w*Y@(ZZj(-$owZrQXQV{*w9?+)4ce2_MAb z3X$u01fR#DdqiI0x!lAmktQ16s1!Mfb2x|5Dv|H8ty<(6^m#?r;H$U?KgYw^?i2YA zuVO8ps}Z@#z<;5RcfL;KE$Tb#nHcr#`&cY~gVUI(y`S0fzz_H#W;F5=Zk${#@*8&W z)`zfZZE9;@#ADQ(9}u~Q*YF>_xQ=wt|H68a52(*$Rl1{7*o|8@rgr2M#;BJyi+sxa zWrT~TY1rPvs&N{1%PJn^+sF4&b9f!gdBKKFA`NJ@rY3fn+0AhO3Vwyh+C;eRd^vEd zFsyVCdH|WTQ!4fQXF&h~MtVlM&?h7fDJc9W+pD**dRdnK7 z^z@S%;rt5oa*C$0gkXbp{r?ws%K2;Dj2j8frB%;$+2#`+H_gHu}G(hY2WC~XqP{1_nBS0`*`*2SlEvDby+^2 KZ!%t*SNR_VwgrIz diff --git a/bin/Langs/cs_CZ/pcsx2_Main.mo b/bin/Langs/cs_CZ/pcsx2_Main.mo index 475afad40dba00c2cd38929560f08562e6c352a8..814a7d52d9feb3cbb9d7109d5843088feae674bf 100644 GIT binary patch delta 11633 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 Au>b%7 diff --git a/bin/Langs/de_DE/pcsx2_Iconized.mo b/bin/Langs/de_DE/pcsx2_Iconized.mo index 41a61b64bb3e1b57ff686f2dc8a0776ba8841348..2726f669aaacf0e9dae3178f457d3d5e3093a9f0 100644 GIT binary patch delta 1615 zcmYk+OGs2v7{KvQ9mhv%lc{4qujVry9jC|Gl=(h0aHB53_}`%w8tVV%EHQ!6sx5R7rhYLMgQ;KyYRqwf9Kq}k8{5B-5F_r)fW7o=(sAh zMk0e~4;R^s{SFQ^!zq%AIcQ+O9=Bl@<724zUB*ltLIcO`^FPteI4(+LIp$#=Hd^DL z9HyfWxP-;{0Ml^_Jvfiqm>bO`unzS_`*0baMZLct^}1oy2~VTG_z&h|Y>aiE7xniR zbW2d=0G$+01W_M!%{GL|j6b5TbQbl6k+If;voVpeA9cc8Fc&+p0DCYEhj1~zL!HPB z>H@+RA@7%LIy!+WG;jy%3y-7D^a|>O2hp4m>dI#A-~XYm+#P3K??-*{Hq;3pM7_Qn zb)vUyhcT!pCh6!6zfm6)7jIc=+l-p}L#WsFqCWT@>Vrp7GckiY!5^qAb|i?r2op)d zX2xGQS%Y~lYrNk@{x5LiAt$b5V2Q|9oWNEzcAkm#O#XkCRXEUGWoBi6G8rUMGbfw_ux1Din_uP4kvK}cVjdAGLH9A z??1)OZ}2H@!fw)Z0^i#IAIqt+t3Qe!;4bs^~XA--xjLNu!1L!7oEfhj0cCat? zoS!m8ZewPS$R~V;P1r|)=nJOtGj1nMgILJ7rW2XO4s4+UYw;02!Qfvy7wLowm^IcH zioC=z9K*gMYYSS*o2Kk7Qg0Ho!b*LzZ5GaRzR(_Llvuy#+m<1_Dt>IkCS*ZDxodS~ z4s~YbrB-S?@f_nC51$IM6T)ACP@`s%g88S#!ps(7tLPrH9&r*I2>qJ0@hCIx+FwIN z>i4fLU|}9NawPk*njnj2C70vE=3`Jn7zKX_VCltKdNS^u0*+Ua*&uo;6uHQ;$ z9cp@O2x>~=i84Z~p2V1+odaVC5@S|9MJ+C(iU=pPvHh}+U{_^5!EVS}LfcA$l*=lD z55&xNekC1keuA&dY_S|S6I%JyrR0Q)ops@%-sm)^%jfa>Jibb!!WZy)OS~1K#|cSM Jp@fvu)c=@jlVJb= delta 1707 zcmYk+Uu=_A7{~EvTiHKGow&({Ox|t-8MDxp=>|GRr|chp5@(EyGcHY6UFq!R9E#D= z5I_>IL_>gO(U@|<#l{88h)%Kq(};#J3Et_5iE;5_i8sbXFVyd^?`y(Io_^l*w(ohL z^PF?~b>G~}>3eH^XN=ZGY#;`5&7wHvhyDRL9ogq!HMpq`6ig{94oc|VxIhxy_%YM^gDm$96FUa>plO4JLRQ8VkowRi}X z_&6%j^SBwW;(GiAAHaW5iTGEO2=BK>U0@F?ff01@6sp7*Q8W1lHSo`vO{m08pc1o7 zgqnG`*FS`M@o`kbpP&-{9F^$znAXLLccXBP`#>#fpjOX*&orv^pP~l7jvDwU)WCnD zD&hCL2?kIzZo(TmW*xYnesQVU9(=Ks`s>CyZk)nj@hranpxFUj#b__#^O(X*7{aQD z+|6_l-={x{EVuoI4(66ICf1<(S8*Jda0L4(Uj%QJQ~x?H{M5Y_n^9jJLCtIq-@_kp z37=z{n(21x{SJ2ED|j7mqr*db{&&2I4V0-J|HdO2q1z}T7zn}2TAgi3VDK7f>;XGmPURMC?$3i zxr7?aZch`es&P1sBHJ!Pt&wDsDQwIyZ3u>T2E)xxIJ7I=R38e@ob;C!MD|5fDQ6%NcRJ#4#s=R`qy`eN zCF6-PXDFVC4UReS(ZPi)gYnchrz_>OxA!{9;ndh@bYygR;Bay*@m65wTzRnKKeQmP A4*&oF diff --git a/bin/Langs/de_DE/pcsx2_Main.mo b/bin/Langs/de_DE/pcsx2_Main.mo index fdf3d48b05616af97676c571f8118c1f0cbfea1d..1d8548b26f5530bf1ff35b6bab8265f00d002ad7 100644 GIT binary patch delta 11213 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 WYvg6T`g^l^7hb8BH+e@`zW)Kj8HK3; delta 11291 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 G_4q$5r;;cD diff --git a/bin/Langs/es_ES/pcsx2_Iconized.mo b/bin/Langs/es_ES/pcsx2_Iconized.mo index f731c10b88fe4773d3b4535080d201b0cfbeecae..2960121a08f77e9491163aad208b485148db11c4 100644 GIT binary patch delta 1643 zcmY+^duWYu9LMp`F1Fdlu?@p!=ggd$&6%^~w#{uW!{*YKOQBHAZA!UcJLZyvQX`kh zZHV~CDN)37DJk&>C1O&_3jZjPrT`hYt@h1bv~eh>TO8!W;<*cXFo zk`Jpf$oQ(~!d9@+^9b4mZeRePpbgl8wvw*tZpZ!6nGo6p7N9*}hnA^>UVII0;74c^ zZbxhX3!^sEtPFR?WuA3te^`drQM2bc&o;Cz_<+_fp_|)rK3c~WXql)-o8S_(6>q`0 zoUi@3o4CC@`QOUL(oE?gzQ_C6%D=B;W43e!vwKKu@h3ce<@t@FWQBOvFewq!M@Vb9 zpE=UaXfxXXhEzyh*ox@(O6fQac8#KQ9^{T@--t`b&^d0yQ#gJsnc(?5{7yWnnmr}1 z951~fuASg!EO(;21@~|#_lsD?CcKOt=&z9$V(MgPVo|N+!Wz6r`clIbX$7`mG6Vd^ zGEA&>CpNT>gTwPZcpn?5Nj!EA8gv%xYbw=8t?InXgt;!KvJ;wO@4pqYK+M&BcVt|pgd9) S373Y;V->yzU#!;uJoFdwN2J^U delta 1864 zcmYk+ZEO@p7{Kx8YJ0Q=uG%6{pzXBU0;PAf)GpWy}b=; zVouX2e36(CEmRXlBSd3Oq{J9w0;Vcz_#nYVz9{-Z6JL@NLqHQ1|Ih9Qon-EJ&+P8( z%ri54^ib^ZWUTOAW$}wb*+yMP%@>K-c&3;i%AUB$VzkiUlTrLK))JpUeeN9A;6*f; zm=m_I#zn;acoPod&A2~|3o;cooJH;EGOom`Qjw+DiAj6_>u?`7;4!SnFQfL~PzNxt zOr#o{QTyvgea=Fi$TO$|n#4vah#cpSK6pO5;c|3CMY+gA+Lxnt)D`(4-bnm7Y6cFV zzHkb)hgJL-TFb48l44VU09tl<6P@uv~TQ3vu?IbSU7>7U?oqT!f$X24^@#B z>|G#|!;82tCX%MtJ;c9~rrp@jTW9eY4&ej~z7zk!_ql%uqq{;}#%$||W6Q|DzObIW zAHkpSBongijj9QoCI6jTlJtBK? z5`SU;No6l-rQvVXkv+5}yx|Per*!v`W_%9k@Pb)P;gzl7z?!y^9j@=iQ@E?2te~Ep z{};w3JQ8fc+oB82dj6SkumtQWq3@t<;8)K)3At8uXRo62eF{EED{wwlm!*-)gsv5m z78LfcuyVrw73LEZ5*?g260h_BuaL>$)5t{R4k}9;6qYRba!@1TM^a8@ zRfMGvKCyb#mQW2<3yBpDR!}&3!qy2&Ex%h!`Qfw(%N?9$_KmP~!Z#u)n<5(`o3M^r zLY+(Hzyzh`U^2cawtTuLK2lV+IqRlJ`mFTG!Isj+)9;pUiC^EAY->%nt~2ee8{5{b zYHgn`sn}jo@cdERJm%ZRc1+eaV>x%ocLrTEXcKy7AnS6`Gedsf&k;MWaqP71W%5>T z=7?i#FHh^B75v&J<9K#zQANHV~_e-D|~`MS=r&44;}NUZx6ev)b!5UbIE@J DK&JMj diff --git a/bin/Langs/es_ES/pcsx2_Main.mo b/bin/Langs/es_ES/pcsx2_Main.mo index a4e25775db51fa1c1cbbd2b4618b5a39e6abb2b3..b8028dd33a023385b03a855b17f301e43ccbde86 100644 GIT binary patch delta 11634 zcmZA737C%6|Htt&#tdUDv(GS=F)OoRCi@b`zVD1(q!>FPsh(t~gvXkl?0c3}A|fJ{ zkR?R6@Us;~TK@0Poa4H>{`cj~>-#ck#5|ad+CS9gqcDVgjH{pJ>KCBSTj5-b zxw*gDOrQ&IcRTi@E_@h$@jK^93@1N>y3k$Biw~WDqt5eZxB{^t=EfqZ<4T~;D}~Qv z8RgvH3~)P!p@wc0>O#{o3g=-h+=`l_U$Ge$DsN0v?25X5JFpTS#!hG|8q*j$V_jT@rSLYYfngl15lqA8SPhv~GX=Fq zKE(+95;X!BFbuC$V*GXDV^`r{nPDT3M%If-#!&2pwQ(S7NVi}x?m(S?2(<=Ip*nCL zH6r&=H-3zol0sE%&!aJjJf#Zbub?^=8i8i03ypR86bvB$+|?gJ_24+FXQy5L&sdfG zCPraANj((K4bGr${4>6UH&HEaS>5)q3w9>Y#&G-+i{W`> z7R;a67Sn6kr)dIqCI1G~FqH+6jGeF@jz^8G=SPB~1oyBo=C5gckch>|Yhr%viajwK zJK`}cf=RXP@tLS8>5LlD0WN@lQi5mJdSR8MnZk)HiU4#uWp8OqD2ezU|Jw8aF z3tmGFebENIov;Dw@fv|@*f>-V=3*_}h`P~TR09h%v?J08{mJ{I9}Yu}$SBmB8t3Yl zH)Q_Rk~LIB;%?LpPon1hXVmli6t&nw_yp36BMp^jqAuJO)$=~64va!A#t%>(+=(&x z1M2ucupj1X%=jk~3~X#4m)V#~{u{<%OcP_`ur}t#-l!gBqefyd@<^Kr=!^SMBX z<3nfhrZkqkA*umWQTLhSA>id_zCiW(DQYc*HDeuMI_eeO5%XeS)Cdek&HY5ogP&jm z?nk``e!&2&(cC^I4KP1>dzbfedWI6HXJarIPCyO$WYh(gqHeej)$+ZlwQ$7kzkq7+ z4b%%NcMJQW)C1d)Z$$0)X=$gpIO={Cv7Mg(Y6O~s85o4Sko9D~LamM9R>r)J38+Q2 z9JSciqNe7Ws}E>x-wQ#QLVYsU#rCKXT!8ApdJM#!IrYr{egduH@39;{a0kTFe9d7Q zq%9^3HOFgFL%9)ih931s+>e@qqKv;rFcX8ZBWlg`!vZ)2)c}w7bAL0HKrLH@dOX%( zdHmA(6t%w`<0Y%17F~VhpBclC7(9)&@G>5=b1G`FEJV%yGVF?LP#5y=WP2Qdk>rgr345ZhGX=}y0@R2cMJ?*n zSP(CFV*H~B?o$zi0W4t+RWfR>8es}{z>+u?3*$=EaeG~U5xbE;MqRi=7drwkp>8|~ zLvb{!Bk!Ts#2gQS7SlrH2{LO@L;e`+VMDr0Xr`g&?l$TIVcbm@j>aOGgdv#eY=;`+ zJ{X3Bu^5g=b$A78iafgsbl^cu!($kZPf-mB?rw*$18Qg|qNZ#!YIR@1bbN$44e8+; z;%tYyZXeW|nS<)^GONdIBG8UcQH$tHR8M}uXuOFUD!&)(5C$R(*OWjtd<1H)-^84u z#YFNssOx^_JdE_ooIqVSqo=0Q!>|)*uKS=KyAh}htw#;4Oz<4C*o6 zg}T6fR0E!1WsH2;jzCLnOg0_rftPkU_AuK|LhBN_{S3*5TnWz(6 zp`P20s2lcj`54sHO+}5!e5{JMa4aVD<*Ple#T2}bJuoEOel;7G&G@V3A5xKlx3MV} z@5lQd`(Z;ofQ_+0f4;q77HY09U_A^OV0)H@HOTv816+rCe1F9i*kYjl7X2H(M&8~t z$PVdoEI>uTV7s~_u{QZY%)~9oTiE=DIEtJ{68gPrr@98#As>N$dj3Blh@|3kR71`m-pK|TO=;c=*j z?!&BHyeUy@rRRfvm5F$?t?mRFlq!wz0LUNCz$9CoQ3}6 zi%}=6boCoi4gJXN{~C4P3G~HFs0&}kD7@ox|FQN}TnM#4+8K{JKW!{M%}r3%Rn$a3 z@}}4bTf2Orb2%2KehmiVe$+^PgLUvWmc+8WBsyU$WOmF3)D26Gw^qQ)iR1% z4tF9W=rQLAlBl?jd9dJA+v5n-sxOPWaeZu#-OwL5Vg=le0eA~_{zLS`zfe8S^^P6U zFl%Yp z*P|Y%Z*c%#z-(+nFJf^g>b$e4#rqfwVaP1TUqLK^dXj-5SQ~XXK_>Q@Ze@lXcRJ6i~d3LD! zpbnUby3kzIBK-(8GCyH?e1c=J%zXRdv;~`yKgC+u=zZIfDOi(yKSpA%1@iULDa}xLN)L{#$&!EcBIOp8qfkYMg1^8&crZW zf)#N)meBKmn?OAZTxu^+9rKZQ!ME{c)STbKL0F7u^f`PNHMjdv=ifjr(x~Ou;#iD4 z9vfpO7R7h5Dy~EQ{n=b2c%F)4E9_q|x}aVtyRZ`O$F}$<(qhx%1N#SvL8uF@M~%>R z)JXn~y0QOC``dIps=hC3=!arwT!aDK-#j4*M&DI-afG9WDh)$16Lo?1mh8mtV(3@~5aZ5xd&{X=VoM`=_}^pbNBHV^183{^YapHC%vk7_rv& zv?{(x-U<_NCoaYFmG_*@=Pp1!^&V ziyDDTs0KX5@))(j9@h*t1s$<3&cb~74{DJHY_!J}#vbGes0K{HDBQY{@z)#a2o>t_ z1q{cls0;mxdS3lD*;i~aR6|m*GPb}>oP>dR6!YV0tbzvKbhFv#>TU#)fza)zH%0?FH+i=Da6r1hesV9OCNlVk`3B zF%28;u#f8q4At|$n&3Hhe2N9}9;yfbpjL7Iop!EDqZVl<>M?u~gK!*{!P%&%;sD0r zO;m^SePmxq@%R#XEsVs~SU}JJUV;!Rj$s&HLiPL+sz?8#7L)%j78*uiCmf6&@FF2IVo3S;mB zcENwJI(Gilj>J5yOnwN}A+y`ohhsU?x~K*WM^9mbX#@>$4Qg@RN45NKXTi^GeF@YB zQ?V%4#uV&^8nG#;r(+gs)$elkaeHjX(oh|0fjTd1596;Jj-x_DJOg{-GAx3Ad+prC zpoXqG*231PwcTwCmttuw^o4Cu6)aBP0c+z34}mVQ z3)RA3P;-}fz&=*pQ6uv*#^6X)59Xm7auW3l&U?_laLQm^@}Z~>eT4D22fN`Fd>%8u zw7&;<#t>AY;xcM(q7T`{5s%7ipys?jYREdHo|ZwVhP{ot(M;4-%*RArhk5Wg>b$d< zg?F$4)<2x{E!tzI5j3G9@+;erUO0e!5vnJFN9@ONORP>l3ESX7?1F`l+7Fu%*qrVZUp)YXJe$7tBR^)B5B(6dq z?7fuLcTW9{%&Rh&LE+;I3pR0~dz1~N;O#UVYa~uzV;c+(esUtO? zQr;ncADJP;bm#nTv7Ndd6m1XjYZre{Ua~1kWy%mrQ7VGm&ehIa-Y0Q!!TGrU5?8aC zquP7Z;*$ywpeBy;D>eV!KJ^ZWj|?xwo(U9&DCgUvj(F2MKfXkj0@Nl^YEV-H$5U1k zFQeQh4yJrY(Tr3;ZT0Y=_d$GQt93*>ZDr2SZte&r-?;cD>KXh9eQEnX>`OkHqLug~ z`D}`|y55cnap}v+co7&)$S(YlGTI$MXo~+QR^G(BF(KM>gxVOg+}z{W|96CrxU1NVBC7qJMc`?*|>5kP$S}PYXAl4SZG1`jZ%j{c0 zIp>b~$61zrpSZXR9;58xoOzT6#I5jmA6}FFNis-&z(Sl<+Fe{90DCE8sh@#YDfuYV z$e*X=;kc6cYKUqJr}hl zP<~V{y6m1_k6)&O`qpWpxb8r>q zRqDQ>{6-m0(Z+W%lai|!j{w19N&!k24i0oDcgLdK^gEaP;8IE|#oyJf^Swf#hSL|w_8Ea!)}T55R7ozy+ssu3R`+2AT#ldtyd$uif!CzRD`Zut!Yj2v{ z_Yqd5ly>KhBn}}?p-d-^es(;0Hu+h~c}iaLtCUs5`|&->NUg0zfc@zNh@lK5gM#u)YmVU+Ul3_Mps>m~FXRmQUH%VDvDb npp3L~8EF}nW70FKW|T`Qm%i=D>tj;3En73M!nT$dyZZbeX1YxK delta 11723 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 diff --git a/bin/Langs/hu_HU/pcsx2_Iconized.mo b/bin/Langs/hu_HU/pcsx2_Iconized.mo index dcfaf137c92a1b1622394e5bafb865815adea649..bb3932f03da8b5e052a4ecb6169a1eab88d465de 100644 GIT binary patch delta 1601 zcmY+^duWYu9LMp`X3oa$SDP_s!`N(W$Hr_J+uTBt#UEOlgmU>qmSt_HS&Hl*lOore zm|N&X`NPU3A^s9kZVCTTN?2->_xJZaieLTC>-j#yWB8$@1f*}jMzz=aEzDIjMZiIKg5N$xU zm_`3u!-X}l-S+@y68E9auph0X*Jytnz%)!A=?%013y9}pAvWV^+=t27i#Cu5+CX0V z4qz7jD>L3(vJ$iom!r*KD_X;Q(G3V~0R8^+=V&wj>c`0mUdNNs23(K!eiPb?w)h_O zy^LWS=|e88p%1<>iC#PbZOI$Z-rI=Qa3@;B$Iws-jv~7iZ$nRB5WBqU9UEG81dG?e)*z`l}{HUPxoUnp*@5OkwXb)b&YTm13 z>vj;glhEVDgE*J?=p^5Sd4k`jm$=(UkJ zr&_v&+tCJEQp29(dH5L@mupg2ik=%wFPUgw!gQ%ARzm z0^CQ6Ot>=4*I>2X5ewiPD(Q8FMHT(I!UAcye{HGoN|>B-W#^xjbjQthFsuJxVf95O z+$s6{fITZF=gxeRf0OjPlj4Vt%zp!}Ijv&x+`g%$e|Oe7Deh}G4cQy+n8hI98nHzb zN6nz7P|1|otFGkpOG@1*l}x%XD5-ZP#4p(pTSe*AdDNLyD{K>Yblu=a5|9pergJeE o$qCd&M>^sX11X`>vQTNLDp($>4wX$QD~}vYx{wq}&HG&P2ZM*6LI3~& delta 1832 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 Vyb}V`1BIc<@h9U#hdd4A{{iVFt(pJ; delta 1859 zcmX|>TWl0n7=ZtlTHCd3g@RPEa414;>24`XRcH$>lv^vYMuUVJJG&jr+U+jxY#TzT zE7qv-fvB|*E|CXKiN>1f;w5UrgBR5BV!%W+7B#6nR1;$eULXAaGn1aoKi~ZSoXdYX z=S&};==PqylB0}B9+jA1|A6X6L1Oo8K~nfz$*AVG%$R< zZ*PE$(7WJr*avTe&-r>zCIiFQP$#+uYhgu+$YR(6BXBod3ZI45@HAWozY6TXLUo|5 zRODt@2X(&9P{%n?133iMq2q9cwIX+r3Ow{`kPs1MfZa`wRtxk(U;6m1fy<`{EKV-?Cc}hFmbZ4(ZxS#BWL`j7M zU^f_L7Xq7YB+WMVuTVj$K#0#a5^hf$74SEMweljP_G%iSKny%1xR_hq6PNwAq(QdtPENZ4xHNJn_8=lS-$IGn{c! zskDhDymUY8bCXHO47=LFFK<~vEPd0%88;Sljq7=C z#x+hX=6KC?J>VEG5ogt?*~uDS!gyG4DdRfoNG$0NCQKq_9v^a&>Suo<9ZyH2(fmtQ HFE{)TVjA|% diff --git a/bin/Langs/it_IT/pcsx2_Main.mo b/bin/Langs/it_IT/pcsx2_Main.mo index 639fb543c90b7510ead93a4250232e5f21341b75..5ba3801e29c52133f1d9ff768bab64fc972c10d4 100644 GIT binary patch delta 11631 zcmZA72UwR?|HttgK?FBLK~Xj$AgH(piVFqz7I&KFKy#!ys$cHXGV_-xxo2u_(@aUr za%AO5Q^--KmR9Co`BeY+hjYBHuK#^?e0{&?UT5B*&okqI=fY1tU6=g57C0Q$3OP;% zT;k_Aw-iUI)^YNZ9H$26V>*_o>NpYD9gE^bEQQlC1mDB5xD9!fa|DNCK4xOGYUaA7 z*voNT&L;#dIZ>v%<5a>v*cYecaJ+)v*glz;V>c{}&tnlBhB`mS<`dDMe2T4q&(<$S z-M8Ah0lj#?vz0&({>YvtWB6}O|N=q|R!QZ*f?4fa93V54;>Mw90vmpYeG zFDz5bOj#E!Mcxlx3SK1OKgY!%{vp&#x--G2nN z2EIpi-~wtyZlPZM7&RrO>Y1L0U}^G%dW^qdPu zv-Lk?eexR^jL{@5Fa?|8G@Oq|FbjJ&Fz-F$BG3!+P%r)&2jdM?i#s$lJ?xFW$cJGW zJd73b0x}EEU)Tk!rM%HznpaQ`yEQiG#n;ulcisX&4 zIQGE-I1DrKTP%;Uspk5os43}%8qpCpe+_m2JnK@_i#K8=?f?A*>iIR)kp6*c=_6E6 zBbj&&XK{nRm{YEzspSO$l`4NDRY? z7>PNkRh)}z;7!z&+(*4Y6B`MEsQNmn#n}w?yjIAdI-QZha^|Bt^d0K@>&kh*bDuy{ zP?Wu;p2T7}*2m|t7qT3jPmxYIPf&B-fEAXEW2|dYL!XDCcmwrfpER=wTVXW$Tc{3f zN0)khh(Hg#h8p?`E%`cOOVsunk80R-R1X$nDsD!-=ucDwOSCd0l8)ZwSy&jyqDEvQ zYE4bI^{ZMj|7yv4DuOT<^};i#IsX~8f1jcjn?FB+^x;TEyq88&C zR0nrsIG#ma{|JX;p$x{q62Zs}vt1To74mx+j^V8xCkmUO7Y;)8Xc%fFMj>0;nTekG zIcnq%VI1DKhPI)xe&=5gfme?{wC@HD^M@oh-&!()LJ-Z z&tF6}_*c{i%B#Kkq0}EclW#_y_vm1zI2851+Spb5zX5@!;9V?@dyw_ye1%#YejOd> z6^ubGs#U1PwgELY*KECSC-Yq>jS1ApV{`0=8o|Y=4t$8kaCbpH^M8;)tN1&thIi}* zku+a(n1r;&>4BQ#4XB~qj0HoF`XU}gO+f|5UnAHQ{V)@?W`<)49F1y#OXqpNGlxJe zTZ-Bq>#-&twmwCjuf}-E2B<}shWzJD;g4`UhpG4&^@4ic_^k2L!Wyc0)Lf-w0(Qp;oQCCaE$X@hHot^@$seO0+`YFM zfx)O3zlZ@i8P$<@P-`OFMWDsB1ld8(2Go#0#unI$?h-n4QFHe@>H&egO%D#i@)(Q$ z*woq;HN-(_s>3UdE@umYPV7T1qQj`3oW&5lff}m9&zT`ChAdns4At=Q zsJVU(3x*aek!Pcx`>FLP(kJIM>bc1SG?gxfoj`Lv1hwtPqaO4jYKV8BhHgJgVQ=^oSrZlfCT1nXkZ3uXj5UgJ$EBnRu`Z#WHOhVrXDZomZm1^c7_F!QU~*kO#nTE2sd zWc(f5VCZnZ_c$C|;g^_!C9?SK1$&_8`XaVK{}HBVJurnl3tQqw)b_oLtFiq^^IP;i zoJ8Ku^`aTlQ&@ru-%)0D2VoQPk=PWsAzxwV9_qT*qs!gIW7Krr&3^BjK^#XR)GE2t@WVDr?MO~X22 zP3i}sUiiMvmtl4C(^v-!PcT!Rg3ZXsV`1(8y#zs2e1>XBp7kcyBQG@3+}IGK$j70s z&%vs=9W}(4F&-bGMl_NMR((ILjN`BhE<;V>*HZgGpFl(WD{5%}Lfue#viVYV#Iocg zP!FDtYUt-!q!3?9Y)pRXRdxo3zGi;UpNe|X2UxH+FogUNhT&y&F$azZt)R07e;Z*d zJ9Eh+@B#8nC+Kza8_ohuBfo_+u=W&w#9}V`V9TlIg&k1awJ)lE2x=RTMm1z2YD(Xn z%J_Q|ET*C`u0rMOZN3$~$ai6J+-uJtLA~HOYR>bl7f>Vh6Y4pSP}luqbDwFZL8Y)5 z^}*BVpRq zY>2Vg-bIi`@G@$3@5iF(JJU2M5OqTY>cdhK!*C30EzHN!cmjK4lUe2iwhWWWf5&JH zeZwrqX4scJ6KkVu4?z)vTc|mCWOLs)&4!;g_8F1~=lnZ<`@&IM+0!6Y7COk@e(^ zM{TbssC{1K9kYunqIORN34-@!=SiE7wcRKu>Iw)0@O`MLiiYRH}U%t%(mQlz!fRgxf$Kt1V-$_Jvp zaAPnIXQSryBh*lSf>rTzRDBYtxUnvxBz`|9jXJ{7BK#r+cQ+? zK{u^MvdxPltgTUVJP!4u*ReUSM(u*@sD{NXG%rlVX!0f)i-WNk&P8?Pebk68Ut z+iaqu3;HfHFX)SE@f6h1&Bt1}71hvdn27)4SWL_@Jzt4U$S+_641M1;v?uER<){() z9<>N>xCpdu{1=-alfAGt`6jH0kFhP5U1EMLKabVOw_r{D5w+?Amzr%_5w(qzaU3?s zP~3~@n2#|SwajcsS2}@)t^=xNJunHgP}^uR2IESsfO}DE#Q_Gxfa#X^H^~I zDl@mWPz|q-Wib^sqTSIGSEKIx0OPd(&l1$7LcgGCD(aycFctOUxtM{6Q6u5E#`Gi} z^`LarkWWBO#cV8(Zft~GZ2e8FO#To%V%SSTHHMFa3z7O@_Q&KD0JI+h! zg9-R5YK?3_4e6(-2K#PcI57-$-w|w&$FT~AZZr*RjnU+tu`y2A$oLN+*h7UL9P**r zmsL?C&=57`T~Moi1UAD}SQLLjEwVc}9+NhiIbMrebQ`b;evEza0BXuAZZ-{XvzhVN z&<~(OEgy^eG)}@|I2+ZFY%Gpjurlt$6ugREF>;IfvQ0oeXDVjkn>Z2ApuU*xwwhnp zUqfH=vo3;>1V5qXsQot6!jY&&xfC^2XHg?mcDwoeK|J;&pMuZhWlY1g9j51Rqef`4 zbscJrY{!!L4f>$#Jb{MhD*9v7oo11BMfJD`sv(0g6_=s5)sLt}_z*S30UsGda1MDC zYO!v`j<^Fgl3u&aujLi6wDx~Hf|i`XUq7RJ-4A6{BCL;VP|yDnHPR2!oA*1ud(HMMjcRcfYa7%YWg$c5jKf+u z6U$*PYU<8n1FX5vtesI?@NKQIKNb4`a+(N&&`Oae{8OIQMPQ9V9p%}4d* zItJl=48-D}njw!sjZ_Paz}A?BBT#GO2UO30Ms?^3Y8MsS&-klF3H!~9TjC({uBe9X z!(cp%df_chN3R3sLG4gO*&SnWm~|fNzTK#XpTOpL9vfizXXbgmKXaLFH<}9dU>>Rm z*{BEXLG}0)R>T`v4U2qk7GqtkPTn7raXvQ1L)aO84w~zFqZ&FLHL?p)_pNi;AP+US zMZYkA=}bj!ze%VYW?>j+V*>8RIQ$tkl*PX^ADmj)n*4Rthv*xO#M9UuAEMsV;E-9& zuF(YQ(P7kFJwi>%zcvp!Y`#=cs704(^OmT!(h=3bey9eI#2B26dfrOZ)NQ~vxF73d zu_KIv_J10IPF%uNOgPHTn1!mpj?J*vS7z=eVq5ZEI2=8XnNRAA*n|8C@-cP7zc!2d zBn~4F{>F4*8nz@~iv6|!uMv!-BJErLO%8YAOmrRRe=0-o6Q&_<^dWSUS`(kO_jq!K{TkwA8E;L?-8%56ujGo;(Nr@E;7u()p%Aap+0@0;-|I^BMmnf)%#n1lA?@ z`oZ)x1q+kEfm+3Lu^ev4^7u72!e3DL#hf=^y1uCGnvFXD5vn2gusRmMVE)IdMi&@= z4aNIZ=mCeY2L6NULGnfO`#^InL*4~z;V{(oD^Lx~$7=XLOvS`YW?PO#5Ay!};igno z!f_3KDfM0a(aY31f9WLi@fEHj48zY<$Dv+-PPt6}8v1eFF=UrIIn9@k+|?#D0`d zDGB7YP)7?qGB&=W3E6`?D3k3Kgih#xV&$#fn`1&;$EXb_^Wq(M|KAn5>I!vJY<)xPKh#$s z?m!t%*+#C#d7F4Yg%4!Gv6WayD?`DbtaE1!^^GvYgMVt$BJ4|fj>`FX8bfK!UgAN- zEO=*>dqkxmS7B;(Y^RLmOq9)4SDoC8Qj)r{_yr}6^6b!8Y9+Y`=O5uIa($uRCjJ0p zkk70$3$<QVB@f5#85@!E264E3ZwPS?=cnUX)UlSh24xZ@(q4CfIE!;- z+|R`ZjPS9wx_TgIg2)%+5z4cpGI0R)fBdKJc^fyyhFqu*eG=EiQ+~GRW>EJc@lKm} zabJ!N@R;X*5L?5wkh*J}FGi_OiQ&F*>JHm$^%JF|jTaN^@Z}mE74Zemt)~27uldJX zm2-P-To1pc?B||El$OLD@u3Hw$t;p&lCxNfo8s)lqp3SUnMVD)c$HF=GMBs&MgKq? zfzOV22#VQzRoBFx%lpqY`eCFakn1Wb@Nid(^LI_HjPFg!tJJMBR@R9akt-IA4hJH*qste_1CvhLE4cF%Gr6+Cffh#CgDBiYiBlo1*xI7lOaV_d~3?q+s zFGz@Wy+ZU0r3WRF(!pHdv?sn#98Za)JRwh}w6W(;5x+zN&2h>FrWCee?8&oM1v75SQM+4$7NjBMvPUIiDM^{N`k!!EohW$C~MTzCfL$C;S z>6Bo~3CaNK_)W`sfpUqmgu1d^yWM@cN*z~QvS-H<8~hI&Q~xTKv+Yf^=RU^zlsJ3e z%f$Y~36y!nAA!00Zm=U95>T^fB*u{0W|NL3c_vC+|>>QeG$D zY%e}atmA8|;w0iqwzs#43sW}^YuamWkyo^FADlzkZ1Zzif_uN$Vt#h~NxX*SJzKX3 z`;f;{%2VF7^LQhJTy$nrI& zDsBrl=4axj@v1fEcDgZj@eX#tvuo$&OA=$=s#0<>Gd8m#YcYcNmrJtZS*D2KfS5bT9 zzo-G+Ma@XXMz-Nd)RJVN2HXTI;eCyme+B)i&S7Mm6l))R+e_0M+A(s1eRZUKg_% zE919V4euhWVX8DUrU!P#T-=NU@H(bpK0B^9&c>d&2{p5xKMAT5RBT~P6sDp^&;~xj|JA0mPhq8 z0yWZBs1Ef(Hnf?9>gZtt*Duk-s0ei9a*V+O ztbuz`yZ9`sgF!5$mLv?-KrHIIY**hKwK<2Oo;M1aTr&lkEVBzWpkGnXDa)%=nf6T> zftH{)Y9zTBi}&LYoP%r+a}F7liDGAI&HG^%u6DkQn)=&V9Ru3ghHD{hno*d5+fV~2 zMvq2(g+LGVW9MkkMN95VxmKu4?eV&GFjQT#z!W8sk8$5^=u{6EWK*BJP_Du|dPNblAa}%tC z_m^B?%o5aEu0#4}ico7E!aQqA!%<5RkNPsEpqAnh)J$&0U_6Z4J0~#+&tM?!oA2BO zH&H$FXFBwn1Y|+05PTXnW!o_ie?>i@Ssw~6!wUETszYa-S5Px~12rR>4sF`9$eU+^QA^to zwb#b>W&U;H1S;y{3~Yc~-G!H&H<8U^{O-4FTn_cR2BRJ{0dsINMqnW(;RmP&f5Qwc z%}=OiBpbE4bNVs=8c7}%k=PewaWZPEyr{L>h1yJqFb;pjD6G)mURMj1=i)#df_m;D z)C`g2nz27ZQG zl3S<`QqvLkzGWCrz7_Sn!`Qk9Oy90&Tu=s1eOZeesr})^ZPO zvlOF7cn$TM#*MUlr!T7GL$M*wN6o-q%){%LgpEeor5b`-!qKCce?NkGRA>qpqB^kL z`Wg1e|G%A8_HIvzWazk%93K2zGOHqNaKQ@}D`*AKDu&XV|@wk9p(+UH%G& zknh86{1`POrDoc^3}%uy#RfPY8{%ect@r-|fi_|MEc@e;jOs{BXD@6-J_dE;Ce%pJ zV+8uLei>K=D`Otk#=)o=UE=DGVJ-6Wn2KfQu(|dAXA@{GTRXd=Ml=XD#gkDtzKGHI zK8E8JR0DTW9d0z2hx+pSfi1{;J;eWv;95+;KTz$&(5UuE8hZ4=W&|}e5oC2t0@I}> zUhi?iZqz68C~8W7M(y(YkJ{b80M((Ts2dAVADC?zgV#`dq1++YO`&_NGw9_nKRfKucJEHoQ=>P zyJBg48l&(9)F*u}`s@8aMo^WC6Ic#^M2+Zo)Raanu{Xq{)-ns#a0g7mp;!i&qo#Z< z>N%fdS-gmTcnvj!H&ECAh28Z2`z^JvS0C)hi3Ruop2K&r%`*Na3j>zhDcg z7m@vIuA_GQq!n&zQE$;2jKc~mZHMb%PxAgakoL_kf?*iE%Kj)!!-nKvVw&n#+YYrr zP2pxt#X~Ot3FFDjc?ER#j@tNq+RIVYYh&!+X9zc!cBbR@L z`qEv)Wb|EQ*EAJ1m6@1N zXoS;)YPi681hvLLp&Gi4Z7_PBeG3MoI`$l@!A+=LzZaA6JO-lwQ_R11XUJ1_$|6v& zO#=471*ir-NA>s)YO|Iru>W3|gzD%3)KbmBDYywW@~Efn&vy@OLcSK&(ND1+MtGjF zJ?x0Js2GBJZ5Cq}{0#5IglFyFcqU>;^5xh8&te@+e9r#b^+xUbr5J{5P_OY8oQ7{> zbJ_@m&~>Z=z=O1eVhKAN`WOF$UFpr5-DLk39f-}z6H)aeuomr`@dRCQ9cov9kJ@ZEu`>E?wo@C8%Il&Y z&;fn18)_+fqB=SmtKdVZr7S?r?0T2)L3Q{5dd3o*BN&Q#FWV2zc6^vT>_7I`Z5`Gk zFGPPli&OCureL2}>>4jZP3=>tj$TF{W&S|jw_%I@jd%t10lTw>`Bx7Ux7znJ9b1rh zM|H@H+B~;VU$k=D>`X+Ural9+u|2lNd8ipILT$DWaXJQUw|_5~kJ@~TQ0=bX&ioG` zc$x~W-ECCQlXlo8Xol)}C)5|RCkEmO)NY@I9zAx&Aoj4x%q1LMQPTRo_Sh6`$Gqn>nL%(1z^xMVX8?iqQ$G5Q^ z#ueI;k3!ARbf;$lfi}xhtbi|LS=@t~nS&UD)ppy>RtGiWx~PuiU=GegyFlWhEZ66+5?4{gdaL@ zVla8tH|#%9q+>k!P)xu_F$T9{q~8Az2qsc-8AGw>n|29CqZ*ik;kXplk(ba9cc5l$ zH}=3I*b^i7+W%)9kJHJIVj4Do%kF`(sDVtu#? zgj%9p)J%23dN>3%GwV=Gw-cLS#kcL=xeptX&qfWj5IqeDjuJ%UJ&eTY{dP}eV=j4T z48nD&5pQztMvdeMM&Jny!>gz%zl)lw*aP-&K#4e(ygh1fyncZB*U0x%p%I-#y+-Fy z9r8bD8?J#P$m?JgT#M@HPE>=(u>)Q}Jtz5)oyjb$N#52u26f*mRL8d*^4Qzw_t&@5Vf{fun|VTV_(0XsOyJf3{JunT!qQFA2pL#Q6HR2@7hmuKh)lO z8Ec?t2SFQxVpK!n@7dj)j~dZ>)LMOtT9Pv^zlHix{f*jmWslmt25PUQqB__Z^}XnT zHL(|#!MVsxd(0w&d@2gCF@B5dFz%SG--|iq{_peeHJFRK{s^|lO2_Te^}vqgD{%~- z$KIItfqfk}ARk-vC+6bT4~=<{_RVhu8o|Ji?1`B;nEViq$GDIAUv6B9kK+9&_!i(r zR7b{tVn@CY2a>;w>PSMd{UlFzzK_~lv7g!>qk7nz_Dv&#O1KJZ;|6StA7KWDe#Q?J zw#Ilok6JR{leU3e%p-puJK^`3iVaWMw`Bxolh4Oy_&WB*-_WB6cKqC~%_LL@)}b#R zM(x&jkx4R9U)VkHEhdrserc_Z8hJO|h&wR=d!4o)n!z}nd@2UxX^g}lPBZ`NQRy>w zN?M_M+78okj?1@TL-Gr#kw$)HU&~>rT|642a4A;7&Db1^Q1_X$_OEV@P_OGG)cF-> znSb@flkVgV!(z zqc7Okv%iPHhl(Nm@g${=5{_@N9Hj|G9n$e9u@CEV95;~1Vi84$MqfnvhWsH6(RIjM zZJwr%)a;`yBYqlLLBsN!mOc67bt?Bzbo>`TaxweQbR=#>nM|ol9_-Hj$N7WzbbNep zAkTl%)x648y}dyRNm1jeNuc~n&A*Sgy&V%GDp%snV-%*eWOwKak9Sr=Orr|a)}l0{ zra3-J*+jga@*{Bwu26Eq#n-R``I}gpz8}WX zejV1G=jo<#? z6}sv&bq~AxX3oEEv2VWv>u9PjhtpPsY{ z2U3Poxf)Mm44rw4_yOXtaFVxUVuZ(^S{*wn6F8ILa@A##m!?#tZYsV*$))^r=qt8? z+?VsWkuP1zmuflj%fyMuXV*NA`T$&~6jIhuBB-0@W4xCV97g?5|Ee3|;?~%d3-!UT z!!@atOYYnw)J-Jb?ed=9qNGrtRo+ucbv;i}cZKtT6n#h%xi5~oqwZS$;&gNIGsHT| zagC1ZIEr%{DPOs3?m06#x6j3m@ngyX?srh8c%J-aqo^pqxulRYqNr@o-lcL|Qx5x`A_fvE%rJSJX-?d{YEmX z#!KAahY$Y_g4tB+*EgN=6J-)*n0IG#XuV%K)1T}NUU0Wwck0(_32|A}@i*~mO0f4% zaY4sUyAYS~Aj$wPF7Iw0jMZqg*yTRBo{~l> zPfHg^V~~sMQLkeRd5U*hN|I+D(N#)cN<5{Dy})!KzDZo0QiJjbd0k4rJO3&1lf<_u zHHoWZ6&&Hti;?7GFo@pjxIno@U0g|4@`pD%wQ}4W)ctcbC4Prwo2%$fzRlY;HKpx- zchycD%-PbET0D6amZdI_5=HrhGL*WLl#!J4l;^06;M!f@qSOYSPGtWa&${3)=1@Nm ztGNEAxpQw|V@hpz-wfhV;#A5?;;QcYbn*wuPgBlP0?4mWHWMGwwUn9KTS)|eP}v#x zQgk%H@mLYNVFy+6;ABWf{T)q5L(T_MdQki+I{3Sy@w#{hjw27lP@UxHVKEsz=Qiz| zP=dQ$(1)^?lfO`oQ5KMIcNf1;tm8wc;tb*>?$vRF*bk>;J$KE|%I<8!6$fJcaVQB z?DRhocG`_%71{W2kPQV8%H;2$h(&Omp6};cM?ve9e@Du{3Uj(uB?uW%G3PtI9uNHp z=~oVthD0O$YeWqx7NHqL2Z@x5R6Aoh&&ddNDN^qIK`8}i1bJG~Q9|mEOh+geXH4Wt z(>ZM`encXTPEXT0@`ckpr9HwsW8*yuL4P3V4;J|HgOh`SF@gN>$$r`1@R9Vo;2(ZK Brt$y) delta 1820 zcmY+EeQZ=k5WweZJ-AwEDfR=jctt9-(DQm#3q?Us!Bc}VCJm7`VrhsUfJQOoEP;MlEg$r@_Ne z{R~50e;I1vw_z#F_ode_glc~c7D`lPJ(B_qTcJ8Q;PP9TkA4a2Nk^e>l$(`4Q8~;* z4?_*O7HWX+!$;t5I31pbIq+Agfs8;6Jo`S#{!-3F1BgIBTnTl<%}^uV2i5TqbOM5! z(oy%hFWb!!)b(Mg8`nV%cq7#HZBPU4b9n|v)o_K0zHl3A>Ix^NS?zK;)Rb?6x~>bV zeH&?NfLZM7!M+wYqrc0sd(m&eQS`k;c^2;AbU(vd>e>a%$omEOJv;_? z&mjLpOu`)d4R{Ow3+w#^g~PfMqKD7Yx~H%=(z^Yym_jbW{sU}5&zUW92E7w*La#3q zIR}4%?br{Li`+r4nwLIERRuoLPehq~$7BqS!NCAc$P0-_MSg-m21Q=wN`4k13q1ex zF_ER%yB-%=2CqCJvK)J0zR2Hj3#`Td!2)c&ccF#`$A0HYkyY5&KP9pP{o*40!)S0Z zn=+B7MZRRg5c~)Aov?@(eHCHeLVx?YbjnsQ5m|>mb*acF(7+y8^gLN${nxM){cJ>} z8@~Pmr-V0QEj;>S`XCuEiM;8d{>PYXBw4N773zXgIbEBSEw~CL?$5gsMDmt z`Dp3Kgu}@_YH$Zxcdnopa!}_s=_8UX#On+aC->_8*Fl#4A6ggsL&&i6#nMiu8g~t< zA(e=KoRuCHk|VT$(D2Tf!@u6J@uOh8qWg1=g=`Cz&?-1rYZ9atg!0Q=WIB?G_z-$X z_^3HoEf-Q!$v||>L>40SrErOaz7tx(8CCpKMWKa+3nkAWrSyw4s`<}z=UI?4Iv*4L zB9dAF{c~eYpEaG< z9MPwy@9OD9D$(8HpO)XSO^vawsl>;rX4bIaxHa9@^jgzpH^;2OPlvPSgzge2nEtCn p+f&VhskV=-X}x}O(3%c{K9r4)=A_8VCfEJByn_{{jBCE5iT) diff --git a/bin/Langs/ja_JP/pcsx2_Main.mo b/bin/Langs/ja_JP/pcsx2_Main.mo index acada50ca7338ccd943b9a8c5306357197c36709..49150be6b1d28916b8e7cdaad30a4f9b2b4e6277 100644 GIT binary patch delta 9035 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 L7nU`v8144|b~;3i delta 9073 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 diff --git a/bin/Langs/pl_PL/pcsx2_Iconized.mo b/bin/Langs/pl_PL/pcsx2_Iconized.mo index bad1d66eee4c738423fc12fc4b83193c7b07f7d9..ece1605b1ecc4792eacc535dde53287368dee8f3 100644 GIT binary patch delta 1643 zcmY+^TSygA6oBD%)J~e3x61N*(ljp}(^KBH)Y4QcjIttMipWT#9_%W?sVFMciZr4J zAF_N148o&?R7hlj5cMdQi6%%WM3f*{SpS+C1UKyYX3b^Kp0)POuNK=}lg&LE>T_Rc zmGmh3NiUIO_{xV3t;#O48uy?B>#Vp5V~C%i-uD)xaSR- zc1yc;;0@|PlbDR&z9Nz6L?>2YES|@;_`r($P#-*uYj75IoDe_r`ZUxR*o``o@r**+w>w*zn#RW5{1NkpAO~RGLrKoRSgZjWm)PdVD6uVF--j8wk1ru=|BQU{V zBnXQzf#*vVJNgFaEZa~g(2WipM19~C>YMllm;=Y5F(K3m)S#YkK+ROM6?dUN_#Ntm z$55}IL$}T}G|-%Jnq?*G4YjBPU9o&*`3AKFqvDiQfm4|I_TaLPT1z121D1cX#6pypDBYWCwp@xs4jG5V=YGoYBiMmvnjXDjviv zX0ZeB;8z^N-`GofzTs2S@DiIN$bSbr<)q;mPGc1hcu3(piKnQ`F1$T9$SLhOxqi@dlp7BP@V3TsMTp#5G8ql!EhK zn?+8bJ2X?Ii4&Ky%oO=%v%-o0Vh@(&m;=pX8aE8&ihSqz?>v!zIFc{Yt`<;VY%CNx zj5BxwtG7^Z?8j-W*vdZ!GmDH&xut_09bi>4C$R^$hV%FX50sE%EZb&IENQ!0yHogy z<0;J6hAf3ejoXd2p$m_>E;QzEWR`@pMyS6wUf%d-y^P4*uvUa>2>&A?+p?Y>NM|0# zAB^WOG+y3ltXH8T5=JjGj_@^L1f7H~Y9vJB_4$=_vLYMl+Ng-}8Br=DBa}+K>DpK> z!hb}_u25p*2gAo;eAlt4P0PoJWHi1sVQCmGnyoLLk3^`NIOw^o3n9Z2K-X4eY|Zam zcN6F_^d)qEy8aQhrM4E@!)=M4YJ0txXTrDC9_(_ayPU2ZM}{lUm7bcO;mHY_4Dd`u H1*QB4vMsK{ delta 1871 zcmYM!ZEO@p7{KwT6>4eAwNeynZ5>;&w)FZcsI^pztrTk`e$W(5jC*%W-QIEA+?}31 zHK!1yN+2El1`OghycPFi9lnpZ;b(sRWz+$b zEfcB2Ce;4=P}^Ck6L}eRKnHP+WJL~hqYc0EUs&{CC@&GYiTVcAj(U8bz#Az)hZ=zc zs2`j`?f5vZz;mb*xPm(1K&i+b*p4^jFqZRuNpiCWccTvE1K;DQ1NZ?A{)PI%nzH;% zx=}lR47~xN4&Z?Q{5{l}AM?xSP(S=T>VPYki)6JykQ*Iozpv%{B5H#v)Q)C-Py1d) zU4oT?{Cn$BJAM?k-zaJ%cB2mPO)ST0>}H?M1&Du?ia#nuT(oZxnZz&gC3I+g7%$=; ze5+FAS*%|vGEl%8;soUj^ge(w!j;1#IE)UX*o>dzcUZy(_zi!;^Z0EQ@&A~cV@&gH ze4a4OV=W6lgBNfsA9|g2d6)8e;y;8FgyS1LgMae;BO~%TnGe(F1EG(!0kJVCj!Q{-`6#A(b9-Nl;l!ZmcTWWC5f9;EKhhf3~Y zUr@e^v)FZSzN25Th4<&W2q*QI?i2YNPj|CS>IRW;!(WB_oa6u z>qbSeHy^5ls2v10iEP1X9L7cb86SCo5MxhYeqe^t=@Rb1lUVnl2;=fj4*ZvB?)9e| zkgSEKZAV)9;M-wG=t zm1NzBnh2bC+6bu5|NlfpykFxWZX~ynHL)VzpNkcehsf*5*O4``U4;LO5M6J7)FX$% zJGKTj5fI@(c`3k^t>L9wu3L(^a5{u#^UgB+LWr=Gku|XzUaIqD1AG61rC3U?@#~u> zgGH+f8gl(b(ZXe$Vs1D(V1=WT&Bd#89~N&es%Q_kw*}kQnU1!u_Rh6!9l53DKbB>; zThWDGR>U&S!kkH)kd=sJTobWkcGR&)%~&Ecp3E%lau*JTon{k?xlzZ&9ovNFry}!v z%$S=>WbBZew&wSmWXej6ho3f1oV$2<)S;iaR_usbBP}Ic-Lw;ryC&tD&^WKB%}%G^ zO3Y80kewNG>~JP-H+!9r+R2njJ66QqX`66nT!&#NGf^v&vCOEYBa6DRv|~rj2v1sa J7pp6p{s94m1`PlJ diff --git a/bin/Langs/pl_PL/pcsx2_Main.mo b/bin/Langs/pl_PL/pcsx2_Main.mo index 2cc793e5127337f20ffa517d2999c9da3d71c66a..2fe77aed965fd806b442df31c048f90240311701 100644 GIT binary patch delta 11634 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 delta 11716 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 diff --git a/bin/Langs/pt_BR/pcsx2_Iconized.mo b/bin/Langs/pt_BR/pcsx2_Iconized.mo index d01940b0b6f97003cc4d04f45633e107266ded30..a2ecfed0f34f3c595a4f3120b2152851a2d99fda 100644 GIT binary patch delta 1643 zcmY+EduYyK6vw~Y*v4GP%w?B%o6Tn4dH2rc9bO}4%!FMq0Dt@Q*-275b_L9X3*bn& z#j~S2?oZr?w$Ue81QU{_5ikgYuoh;+CYS?{`1Vz32fu;C;16i~4D99kmq5F~Txfx; zg!wQEGZmH2`VMz}hj(xY4&R_{l+xQ{Axy)rhIaGC&<@-NZQ~eBh3(J+zXfyQTUY>p z!{IPLMd}Z$U_R%oo`Kz9v(Ff`06Jg*K7@AQXJ|L+)yLa77rKC;1+W;}`bKD(I_TT& z&RmG3@hn))81q!Morq$Pv0SN;-~Tq|ke5FN>s8%;!W$ zb2|q2U>XjGilrsk=f+6uV9%hJiA~V_2A6Pq_yNwbgU3pjVP>gxhxzAW=@@oPne-jI zbiB7;;RG^)y${Z3y=)>438VWW(n%KfPVxdMm@G}juBf0Ka67b{)l4Bv@EuIz!w#G> z;I&FGbFZqTi>x1><^?`|y0i7 zAJnAE{d(`)hWRLuK|RqFl!xM^`0$j(^tgh~g^6q8J3l5@Ck_Y)L*ZaJ5-1H%3WthA QrJa%f8~SxF%X%{AFD(zOga7~l delta 1858 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 delta 11713 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 diff --git a/bin/Langs/ru_RU/pcsx2_Iconized.mo b/bin/Langs/ru_RU/pcsx2_Iconized.mo index 4d560e15e99d523938384617997499593000f16e..17ea4528678b72fc8a67b284cb4a84140ecde401 100644 GIT binary patch delta 1601 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 XiAfEUYF4Y6xO3b1?-ysYKHTsBy6;j) delta 11974 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 BW%d97 diff --git a/bin/Langs/sv_SE/pcsx2_Iconized.mo b/bin/Langs/sv_SE/pcsx2_Iconized.mo index 16dd84d2fe478e74df1930681ad1af4afeebf4d8..3be60a9a8627c101c9aeff0c0e10249205bc16ac 100644 GIT binary patch delta 1640 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 CFEq6P delta 11717 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 OJ~knGYok-a9{&fc@<)mQ diff --git a/bin/Langs/tr_TR/pcsx2_Iconized.mo b/bin/Langs/tr_TR/pcsx2_Iconized.mo index 12f4b5acb6a147699dcd99afe6cd86f227dcceb3..0fb0a71b2679e2f2048f1fb565af5b2a1edcbd8b 100644 GIT binary patch delta 1599 zcmYk+OGs2v9LMp0<7oEK87CiER+E|enw+^=nU$7K7Ckm0)W$-RHa!+mw6Z~Z5Hth@ zu7pS=Fsen&G8lp&bkRx(f|@`i5`uO~VAS__?+HB2|9#}R;`%3WGyP%Ib+>U7KE*iZ-SMwjLw^akVdYA*2JA%o z85?9r1B_xbKEaJRjR~B`Ef^~`+ln4)q5-VMYpCn9sPmqq5}v{BIEOmFbX9P?5tUF6 zRx`hyVMha8bw0o<`ctSC=1~)UL0!0rF^sGZ60OI2`rX)wL%0F&V+1EriR4g;d~z;g zHS=55nxJHDs0mM@R&W_L@Llv1LM4!Q|9?cS_^0bf)&>(dp%U&xoj-`G=ndy1=PS%8 z(;0R&(7ZET7W5lXB~PQyyNDWi6gBWTsuDR=g6~l){)}m!qaUb+q@uwBkE8mRPz${i zrT!}YBnMQQx9-FO>iA#OM0FLx!_$F!c+R^12Q%MEVM4Tpb2%nAC=H~tj3$D>mNE_peiwqT44b-(I3=xHI+fd z+EI!2X4ug^K8JdEMp31nLY49zDv?=K=D(da%%TK#V;oPSCcJ`5G>aPd8S=AfHcFs? z`u`WIGMNaY=s-Ja;$x_cFQ6_ML1jATeC_;zI)4E*P?(ctgENgP`7r9dd#G_Ike|I_ zLy@l-+Jlj9(E8anUdH^EN>|~NkS|9-+0C>P3X3jyMsGWt6ko-xaEzv)eaNgL=W@( z<>yWDpV)S6Ayg`Tf%(>0E5S$1xb?;hVF!p1p{5dd5qc~36M73e2{n)CBX$uye|Cu2 zOQ`K3D8FBM<3nWq1eN#ibv##F(i_U%DlIFCdWoc$@H*ouuggoeCR4fb@}e+*O%(qF Dg0Ou! delta 1635 zcmY+^OGs2v9LMp$% z#3%?{g`m+xs70-U+!Pih5fT!#2q}n2qVMnC1KGjevsj4*ng0A{)cAfZ zw1nA7E*3Lz3H5-x&SzLa{{w2LGpL1f=lMIT#(erQRKj~u37)`}cpaDG80O#vDv@ba z;#u>N^{tuPa&&h&MSev} zP#djBt+N|-UvGj7*0erU#y3$Jj-n3HJ52pm z{3&YQB=X#Z{p5l_%OeX_B81AY1-0W{n1q_ctH3y;-U8sgv~&(yh-3}8rZb@G@$Rur zgesw?v#{N}GTVTu`u(dl`FNjO`BZ7w6FO{4Vl6SZMd;KK!8wDRIon255gd50t>RPF zncFDbzozy18C#5KB{mZ(H@_fTLxhPMLM781nRk$_CU~iNRpN(Y8;Jm+rti3!&>7(j zS~bx~sI4Q~hJ20qlHgvzhR3(9s7RNgzyWh0qsu|Q_**zvBOcxPA7NL@x% fT5er!xUn|U5R8PIBGH;~WaMaea>{>`#!~+RYXXEl diff --git a/bin/Langs/tr_TR/pcsx2_Main.mo b/bin/Langs/tr_TR/pcsx2_Main.mo index 1d31f0c812aba12c1eb0ef1a103b8f2ba827b5ab..cf1e44131d60597cf05ac4eb18cfa990b8659814 100644 GIT binary patch delta 9031 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 delta 9069 zcmYk=d0bZ2zQ^$m2!etrGB|+DgQ9|nA}E3rPKXnt;)L@d@F-5#G<&pAQ}Z}`&3VYw zG)-~NC`-$!%ue03!BUS|>CH|@E6d@2zO41f?e*&QUTZyjui^Lm?fpD>d%ef%4IZv* z0o7JJ{FmVFIH5SSj^o^C}upwT>V0?f~;rJ#wPBAvZ z!T1vDx*IqIpI}$VaXE#_juXegHXM%UumlrYIF1*tLO)!Op12#U<9_@3QQNP?0LDMC z<5%tYcc}Y*u>OqI=-)>_)^{G-52~k_iT%)n3xcfmF^GN`YND3tjp^2os15bRn%Ez; zzzF;K7}R|eusu$({ezPAontf8U$q`WS1Sfi(+I#nF%A6~EW|F@1Givjyn_jt+}dn#Fe){ZF%Rb; z*>f(T7Sv?HP!kn_C=A2|)P0$0#9sqF8K{LtNL@G+u`X`L4p@N-=>x2Tf1)PvZDVSr z0qOvesEDMZ7S2SaBp-G1BCL&*taIBCe-7oWU_ixo7S+FmKIoZl#{E$z2u7VO)Q-nv z2L0w(4~wx2zJQ(ZEUrLbE-J;%s15kGHS>qLXlUVh9EZ(OJ6?@C;Z_`i`!NV>wxbX+ z5{a^th50xgd7PXJI1KA%I!-ez!zQ>H2jF>BWFshyP;{lzs86FW>I5YihUMss+i(=_ z$H5qoPIl1t-$&j5x%CEW;d>Z|9@$j~cR5XHD5Nb=J8g$L>3Gxv zvyr-V)}S_e0aYuvP&vPky1zPwq6Gp_pU0s-Z)NRtKXFPI9=QY$pzDK3>k?ng^7z%wO3}AhyEsY4w z!;v@lU^bpYE#yw6X@ij%g~QMb=b$GpKt*H;s+QK;@gt~>oWv0P zq$}~)f|Jb(_pJ4MIu2=eI$;f* zk6LIs^3HN9QAPb5ss{XBxjg$cnxfuN`RI*fP;bTwsGPrm)$uUK;@ha_{wDfhn_i~s zJEAZBzP3NyIstXC=g=MJq9X1pr=bbfqZZtO+W84o4VwyrFH}v8 zKtCLdT6l{6+=bfEa#YoCz*Ib8y=Om<>2Iz}!VK1TGH57d(=Y-rU^d=GEzpca6C5WU z6L29m$AcJy*D(OSm_!k(k3DcW>b~8Wi4UGnm8Rp^hsE~hzT`-JCWhjnDrS4tS{Xe4S{l!J2 z0gXqf9ENbUY=R1LCI(^`R8bY8PCNsZqUEUT)?qW;hC%oVY6IV+BG{C;$Ky~`%F0ni z?K(!I1&#AqwGph^2;r#O2x{U?RIQYtPCVWEq8(p`s-g9$`}SZ%tVBiXOH>5EL(0Xu zk8IrK^c-Pw-5;w$i*Z~~f?9Bebt7_*vkNtG^&*qHXjHBls29;L40F+VNFx|SMw^M7V^jJaP#gF=M&M$M#=WTAe}YQIRn&>T$Hw>vDwR=V zOs!<14p@L`xCC|o8FXpqAJfpu@1kBDkz-A6a-4tQcD#dR z$yr*;%L9K!g>u3KbCMmXs;JcR()kZgZBRiu5*m-~&7U&_zR!P2Y*8NJe5a z`sJwS_#pPfv#5O)(o;jDhqwqc(5|r{iN(ZA_hNUofZ?EVuoyF@XNhn5yUB zZJJrIH8S92U<;gx3h`D{uCHPz3}6*cEWi*Pih(%Qx)9UpZ$jO71$ELo|7EUkg-P^# zVG!#(vuQM8U?nP~l~o@&&R>|I8)uluF#~JSACJoAbZa^4L@Q7s-hsOBpQsnrBMioR z&zkv@P#Z4A9G5%4#b~56aCR2ocFABwSO@j1SrHgw$BV6# z(U7N4;Tny;3L$+H|>RYP{s7XjyrSAM!m5bKb&Uoh9V#JcpeF$?pt9yuMT; z0jQ@V7ZsW3QN^_o71AxJgX}~V>pQ60`4|AcN=Hqr8iGNrNUou5{61B09QS*L@Mfe@+@$0ZqlK%o4ISiDb zitr$Y;#usDw{QR^EixyWhdRNhs2cEHY;u~3tU@l_oS7P$7O|`*l~D6X&277>Y$W3ybk

R6}tU^`)9#mw`+P?cM=8w*BRQ2Ye4^F`X zoQ?7L8U76)VH}QKXI^M8qf)yMb>CO$rRV<^jrt7S#qQ{}-V{e4ROs?iIi80}cmP}D zbyOtkZ7}bHNK^#-qu!wFP#ZdlD!zYV0Qzk-_eEd>J^zhqWbr{~R56xgDlSDWbQ*o} zFI4WlH<{`W#Cr5&F$CMA2Ns|^7Gf9cOMq&4=K2^wQF`e~@hjYSpT zJk)iYQBOf74#KZd^S0Vs6$zJ{~Q?{5c&qjp+`QMeQ}(LwaV6R09Pjj?ziM`45g=6x|6 z_4z?mL~o!L3VzePF&kqv{XC4s$yoLG|0)`Z3>-u)bPa3a57ysNDeyXALK=oK^xI(q zjzoW4gxbJ5?1$&=c-TSnN^gdWY!A%B{^-&|D{0imZ8!icFcf_%Ox4Gs-f$gI3k=4Z zxDW$yHKyV&RL;La)xsn6!_Y(KyQ2xl(I1SuZ_Xi}e_gne0S~M|~A{PxUv>JnO zBPvG~wto_pnom)oyoox=zfmc0PMC3DR8cj+8rTl&Vpr^oLoglR!0~t++o7xXTjoSB z<0J+SVJD0|X>wMKA@tW`2EK_3?H%la*>9UKsl}-KD^Zb5sx&{*MxY|N6BU`Gs5k8s z9Krg|sCUe_)O$FM5AxqNRec`Y(fJPq7958}+zGe_%G4iv_Ij^r7(@?nG5*-iKz#qfrYyi#p*7T!z^Y>8m{12+=?qD^HIcI)?HO40N3((b+##|c7xDVUow^#=ooj28;j5As5U7S*RK)wfzmK2%N(l{0mi69WU}Px|uWzFPe$gqN@7}s@iX( za{mBzGOv$JY8s$I-VGbzEL5b{U>@#ArRYh;!l+AbKH={CKBXJIa%9X-x0ni_*boo5 zsFjfk``r>ME+<60*NNkbyIk?D8^3_~KVqe4Vz^smMQoynn_Fx}TsfIj? zye&prkN4vEB8B6n5x4~XxW$W);b`J^wEuNsHoiqa{_&ps21psiGjJ>}!*ST?#t~ic z9(1BL)QkBTn;?zE00wX&`mh0Wu+59_pmqEbGw~-{JE;TR`h{o{Sd2E1jhKrO%vMCY z>Q(6SD)iuRD*QleC~=T$9u6a}Mw|I+v<~;8HQa(}cmr+V_i+rq#_{+EvoJSNO2#V8 zrGJGf*bH`iwxA8*7W(lqT8E#}W->6zZFmei140|XYP8?$(N?P2i*KNH+>JKiw`lc$ zVZ=t7HrO3;p=S-+A2y&hbkOsXXD8YgyhE!OJH%~xG+M(Uw3P^>4X_Sv#(VH|4&z{wnhQPew(Q;FNT3ReGBgu+1zRon?1;RBq5YdNAe z<96JM-|&b%=OkUmPuPRa6Qn#E-kits5}(fJwh$*xl&%w(7f6e+7j4ERlcW#$9CuPL z(h+c%IDfKqn;*_2ABBr(3=g0UAibD9 zIcU(AW>H!|P9{^eFWGi72j?9#-|oL92Ibt@7$Gsf@S66W_`sw5g~{o6jzB-`vP*#XHQv$9%9W@Qyiw!}7T5V?ZP z&Nwfap_obbku6n|Q=O8;O;e#)=FBRA%w-UZCO^51ZFH_s5?ZQqzTNw6Mb4e`^68I> zWG;Y{3eHr-XY?B%T^_$RCi*_1IzA;BC<+FGA%AhOJXlmvR2&T@hZ3V-vX15a1%m;i A@c;k- delta 1799 zcmYM!Yiv|S6u|LAZOg)97usSA0&Y<#l&*b%rKL~-+49gBEj2zc(M>U$lt>9AB4U>E z$hI-9yh=-@V4AeNWQ*O#G%T^k4`Pg83?}fwfRVkoZ34j|Qz7{XWaF^u6{JdFkToo&C38o-oE zA~UcEb-XpG&qYut(u^8VH_nr&$RGuM@Vf1A-*yO07I}pBLezn3tebE;^_{3I(2n}T z3#bEM!EC&VI)UF%1J3e`%*QgEiLYRQ_sez)^Kc((AZM*tPy=uikyM19~m>Oe!*AFcOLw;(sm z>sNs~@QbM9HlnV?KGXn@VE{kFI}=1MXR-b-&~R=l%YlDlH`Y%R*^PJc5N=_VZTL5C zz@{9LbOuP`^VGk}6$U~FMzKx zoBoT-MXu3ayO_ao&JqqV`k2)&97NrsP=!bX?#Au-GalspN&QlhH)wG1bqrUEyo0?+ zOyXy~wY>_HcnpWJZkZRDzgpyT>eZ-Qcn68gd^zx6((|#NtOt-TCKc)T&p5&)B$vF- zG;>&xt(G)fS7wk|J>h;bfw9uU2Ow+6`uT>*|E3kTkc}*;a86~dZ6kj3wJ|@P|NrS} zifp^NidP~lZW1eHZZ1~VoB=&A51D_wn{qPc8ZtX#uGs0wxs@PUQ!RO#DRBv*Zl@-_ zOV<1N$s;c(7m(RTbKtlmOj>2-z?#IlGj~A-`pF!8lZuaoGV>-BCc>GGX_HoO+1k*! zF4E9=q}Z3Ai2K%NPAv-4o~Bp1#rU{Z3D3 zYPfCu#GbMKX1DV+E$*i=XQb1KpGZsodaj+ zNxN1L_B#WY$6`b7@UYwRu@k#A+J14oGd|wil}fga?*D>!jh^bGv!s#-5-Vr66g&VI Cp8~%C diff --git a/bin/Langs/zh_CN/pcsx2_Main.mo b/bin/Langs/zh_CN/pcsx2_Main.mo index 5ea65f5a2be981daf664d994530e2a8d6b1a45b9..b5061363bcdd7e63b843fd1fe52f000731ebc52e 100644 GIT binary patch delta 11634 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 P)r;qr-u*d%Z(T^=$ delta 11698 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 MdE0Et-VmSv0Tt#T-v9sr diff --git a/bin/Langs/zh_TW/pcsx2_Iconized.mo b/bin/Langs/zh_TW/pcsx2_Iconized.mo index 6511ed323b4f4e7b1d1d857f81cc5b8b75d94a4e..d1577be23911c6efbeebd765a035eebbf71e67c9 100644 GIT binary patch delta 1643 zcmYM!duWYu9LMp`jI)iooVm&&&v~BT^ZR{&-{(1dFrlL+A^tY4 zYlCRz^bGojF4Ahe*_9t!ML-&ei!g+heq4(~i7%ktcNa799ft6ae?BWoN++I*BXBW} z#2sE7*J=Mm8`?l0F&7h)r6Cx>2+qSS+>XPr(T`iv9{dsq;V-mtf+^nh`DhDRh&GY6 zn2mAFR9w2~UvSsI;0+Gof*)uD_2}+78v7HMp{;x=+5>l?4P1|D*n~FmTR0qFV-Eho z!I<4c>Ww9s&GS{kfvuq0w;pW**D!<+(H_{2wvv=oZ{XqRCWJPDrD*?eMa$GtKW;*M z@IAB%zeBtJH^yzIX+6Ce=lhnU-LM92p#8q*eB02r;62)PiM_mmhoTK!h?a>8vX@yN5~X$bw2kH-x}zz-x`Z@?<~dH*{B(jWhK$cuGk?_ z@R~`tFW4;lzh--Cjd~S3AnH`J>DEY)drKy{=>HGv(g=HgIi1Cct#XY_yVr;van;RE zDAD~RQ6B0}CrM%}-3O*0QrPZQ1y?sgJD~BViBfPaliy@IFNxRUBzS*-7<-nkG0_+$ec-|WH|MC6%=yjCIWuSG zn>lATl5?y-Cv?3$@34@zk(ZEP$rX7Pzslo6>dY6Z!XUcw4X1ttmr|cZ?RO1p@DFrj z$y~dAH7=z72(H9u@Ggwn^^ig8H=qxnz-2gqEAT^Hj+dSG-%uw| zG*4s^dQivPjM^`Vx{xsHgyL8$A(68bwBrxX1Gk(9N()5pq`eMxpjOAHZ~^tbs1Z1b z`oam+fiGe?-auWzpQsZqDHORIo3I+UV=3>KJrrs&f;y3tju%lUV4)jtqrR}F$X-bc z>cEeqnGos(4m$S}s4GA3)Ni1^coucS6~!VU?ck%JGYvQf9rvMj7)2du((xO|zfiZJ zvc!IF4eG#;p^n>w8i@$%1c$K{PobZ4cCLi@zeL0D^F^M=9c3b);026fFTLYfSRwK% zCU6_pREoToBhrm~ssGIA9rz^Sn#JQdh~vy+Bi6I=?L7Y?o}zw+S$>H-s)>Juf`{c# zViNaY7aOiG{vMan@n!bq5cPM7e-!Ho$0aHN1lD z>~klUaS#GJZiqq)4e2^6_%|NI7w!?cimp{6Tk$6h;7SjlD0bsXypEq^w4RVNV24+v z8G}BNKHB3AM2vdPYLPFfcQ=YWiryxXPcgKQLJaOi$} zg;!7`(6@#a(XVhV`$+xAW;-IoJe;Qf^m==ost4>XIE3A_e}_Ad2)S6h7`Q~#?&AxDEgec2gGSL-wNQ%ju$@=-~_WYYzgGuFF*#Y6)$`;dN zPkJ$B0;cQ#Kd~_LYt$3oMrNx_BGTs1#ZJh>WOhLAAZy}SNCBDP2s>$hu?w)8>?Uh^ zh+Jk${DhFBVA4{q9WE~Vt?D6MPGVd$BF5w12d_C%<$+hy?q7Q z@uOBcZ6)_x{U@l?Cv#-KH8qkMi)fkaXUDVQSSET_s}mpaa6?0bSdo6~^x#ag*Lr6- J)w1MV?LQ~V0%8CF diff --git a/bin/Langs/zh_TW/pcsx2_Main.mo b/bin/Langs/zh_TW/pcsx2_Main.mo index 7b4147090b510944081ec351d48ac893af546b70..49af0ba0fac8b4b02101c1d587f3166a5e0c7a2f 100644 GIT binary patch delta 11637 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 BEw%sv delta 11742 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\n" "Language-Team: Zbyněk Schwarz\n" @@ -23,35 +23,58 @@ msgstr "" #: common/src/Utilities/Exceptions.cpp:254 msgid "!Notice:VirtualMemoryMap" -msgstr "Není dostatek virtuální paměti, nebo potřebná mapování virtuální paměti již byly vyhrazeny jinými procesy, službami, nebo DLL." +msgstr "" +"Není dostatek virtuální paměti, nebo potřebná mapování virtuální paměti již " +"byly vyhrazeny jinými procesy, službami, nebo DLL." -#: pcsx2/CDVD/CDVD.cpp:385 +#: pcsx2/CDVD/CDVD.cpp:390 msgid "!Notice:PsxDisc" -msgstr "Herní disky Playstation nejsou PCSX2 podporovány. Pokud chcete emulovat hry PSX, pak si budete muset stáhnout PSX emulátor, jako ePSXe nebo PCSX." +msgstr "" +"Herní disky Playstation nejsou PCSX2 podporovány. Pokud chcete emulovat hry " +"PSX, pak si budete muset stáhnout PSX emulátor, jako ePSXe nebo PCSX." #: pcsx2/System.cpp:114 msgid "!Notice:Recompiler:VirtualMemoryAlloc" -msgstr "Tento rekompilátor nemohl vyhradit přilehlou paměť potřebnou pro vnitřní vyrovnávací paměti. Tato chyba může být způsobena nízkými zdroji virtuální paměti, jako např. vypnutý nebo malý stránkovací soubor, nebo jiným programem náročným na paměť. Můžete také zkusit snížit výchozí velikost vyrovnávací paměti pro všechny rekompilátory PCSX2, naleznete v Nastavení Hostitele." +msgstr "" +"Tento rekompilátor nemohl vyhradit přilehlou paměť potřebnou pro vnitřní " +"vyrovnávací paměti. Tato chyba může být způsobena nízkými zdroji virtuální " +"paměti, jako např. vypnutý nebo malý stránkovací soubor, nebo jiným " +"programem náročným na paměť. Můžete také zkusit snížit výchozí velikost " +"vyrovnávací paměti pro všechny rekompilátory PCSX2, naleznete v Nastavení " +"Hostitele." #: pcsx2/System.cpp:348 msgid "!Notice:EmuCore::MemoryForVM" -msgstr "PCSX2 nemůže přidělit paměť potřebnou pro virtuální stroj PS2. Zavřete některé úlohy na pozadí náročné na paměť a zkuste to znovu." +msgstr "" +"PCSX2 nemůže přidělit paměť potřebnou pro virtuální stroj PS2. Zavřete " +"některé úlohy na pozadí náročné na paměť a zkuste to znovu." #: pcsx2/gui/AppInit.cpp:43 msgid "!Notice:Startup:NoSSE2" -msgstr "Varování: Váš počítač nepodporuje SSE2, která je vyžadována většinou rekompilátorů PCSX2 a zásuvných modulů. Vaše volby budou omezené a emulace bude *velmi* pomalá." +msgstr "" +"Varování: Váš počítač nepodporuje SSE2, která je vyžadována většinou " +"rekompilátorů PCSX2 a zásuvných modulů. Vaše volby budou omezené a emulace " +"bude *velmi* pomalá." #: pcsx2/gui/AppInit.cpp:162 msgid "!Notice:RecompilerInit:Header" -msgstr "Varování: Některé z nastavených rekompilátorů PS2 nelze spustit a byly zakázány:" +msgstr "" +"Varování: Některé z nastavených rekompilátorů PS2 nelze spustit a byly " +"zakázány:" #: pcsx2/gui/AppInit.cpp:211 msgid "!Notice:RecompilerInit:Footer" -msgstr "Poznámka: Rekompilátory nejsou potřeba ke spuštění PCSX2, nicméně normálně výrazně zlepšují rychlost emulace. Možná budete muset ruřne rekompilátory znovu zapnout, pokud vyřešíte chyby." +msgstr "" +"Poznámka: Rekompilátory nejsou potřeba ke spuštění PCSX2, nicméně normálně " +"výrazně zlepšují rychlost emulace. Možná budete muset ruřne rekompilátory " +"znovu zapnout, pokud vyřešíte chyby." #: pcsx2/gui/AppMain.cpp:546 msgid "!Notice:BiosDumpRequired" -msgstr "PCSX2 vyžaduje ke spuštění BIOS PS2. Z právních důvodů *musíte* BIOS získat ze skutečného PS2, které vlastníte (půjčení se nepočítá). Podívejte se prosím na Nejčastější Otázky a Průvodce pro další instrukce." +msgstr "" +"PCSX2 vyžaduje ke spuštění BIOS PS2. Z právních důvodů *musíte* BIOS získat " +"ze skutečného PS2, které vlastníte (půjčení se nepočítá). Podívejte se " +"prosím na Nejčastější Otázky a Průvodce pro další instrukce." #: pcsx2/gui/AppMain.cpp:629 msgid "!Notice Error:Thread Deadlock Actions" @@ -61,23 +84,40 @@ msgstr "" #: pcsx2/gui/AppUserMode.cpp:57 msgid "!Notice:PortableModeRights" -msgstr "Ujistěte se prosím, že tyto adresáře jsou vytvořeny a že Váš uživatelský účet má udělená oprávnění k zápisu do těchto adresářů -- nebo znovu spusťte PCSX2 jako správce (administrátorské oprávnění), což by mělo udělit PCSX2 schopnost samo si potřebné adresáře vytvořit. Pokud nemáte na tomto počítači správcovská oprávnění, pak budete muset přepnout do režimu Uživatelských Dokumentů (klikněte na tlačítko níže)." +msgstr "" +"Ujistěte se prosím, že tyto adresáře jsou vytvořeny a že Váš uživatelský " +"účet má udělená oprávnění k zápisu do těchto adresářů -- nebo znovu spusťte " +"PCSX2 jako správce (administrátorské oprávnění), což by mělo udělit PCSX2 " +"schopnost samo si potřebné adresáře vytvořit. Pokud nemáte na tomto počítači " +"správcovská oprávnění, pak budete muset přepnout do režimu Uživatelských " +"Dokumentů (klikněte na tlačítko níže)." #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:181 msgid "!ContextTip:ChangingNTFS" -msgstr "Komprese NTFS může být kdykoliv ručně změněna použitím vlastností souboru z Průzkumníku Windows." +msgstr "" +"Komprese NTFS může být kdykoliv ručně změněna použitím vlastností souboru z " +"Průzkumníku Windows." #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:49 msgid "!ContextTip:Folders:Settings" -msgstr "Do tohoto adresáře PCSX2 ukládá Vaše nastavení, zahrnující i nastavení vytvořená většinou zásuvných modulů (některé starší moduly nemusí tuto hodnotu respektovat)." +msgstr "" +"Do tohoto adresáře PCSX2 ukládá Vaše nastavení, zahrnující i nastavení " +"vytvořená většinou zásuvných modulů (některé starší moduly nemusí tuto " +"hodnotu respektovat)." #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:54 msgid "!Panel:Folders:Settings" -msgstr "Můžete také zde dobrovolně zadat umístění Vašeho nastavení PCSX2. Pokud umístění obsahuje existující nastavení PCSX2, bude Vám dána možnost je importovat nebo přepsat." +msgstr "" +"Můžete také zde dobrovolně zadat umístění Vašeho nastavení PCSX2. Pokud " +"umístění obsahuje existující nastavení PCSX2, bude Vám dána možnost je " +"importovat nebo přepsat." #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:94 msgid "!Wizard:Welcome" -msgstr "Tento průvodce Vám pomůže skrz nastavení zásuvných modulů, paměťových karet a BIOSu. Je doporučeno, pokud je toto poprvé co instalujete %s, si prohlédnout 'Přečti mě' a průvodce nastavením." +msgstr "" +"Tento průvodce Vám pomůže skrz nastavení zásuvných modulů, paměťových karet " +"a BIOSu. Je doporučeno, pokud je toto poprvé co instalujete %s, si " +"prohlédnout 'Přečti mě' a průvodce nastavením." #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:140 msgid "!Wizard:Bios:Tutorial" @@ -89,34 +129,50 @@ msgstr "" #: pcsx2/gui/Dialogs/ImportSettingsDialog.cpp:31 msgid "!Notice:ImportExistingSettings" msgstr "" -"Existující nastavení %s byly nalezeny v určeném adresáři nastavení. Chtěli byste tyto nastavení importovat nebo je přepsat výchozími hodnotami %s?\n" +"Existující nastavení %s byly nalezeny v určeném adresáři nastavení. Chtěli " +"byste tyto nastavení importovat nebo je přepsat výchozími hodnotami %s?\n" "\n" "(nebo stiskněte Zrušit pro vybrání jiného adresáře nastavení)" #: pcsx2/gui/Dialogs/McdConfigDialog.cpp:30 msgid "!Panel:Mcd:NtfsCompress" -msgstr "Komprimace NTFS je zabudovaná, rychlá a naprosto spolehlivá a většinou komprimuje paměťové karty velmi dobře (tato volba je vysoce doporučená)." +msgstr "" +"Komprimace NTFS je zabudovaná, rychlá a naprosto spolehlivá a většinou " +"komprimuje paměťové karty velmi dobře (tato volba je vysoce doporučená)." #: pcsx2/gui/Dialogs/McdConfigDialog.cpp:41 msgid "!Panel:Mcd:EnableEjection" -msgstr "Zabraňuje poškození paměťové karty tím, že donutí hry reindexovat obsah karty po načtení uloženého stavu. Nemusí být kompatibilní se všemi hrami (Guitar Hero)." +msgstr "" +"Zabraňuje poškození paměťové karty tím, že donutí hry reindexovat obsah " +"karty po načtení uloženého stavu. Nemusí být kompatibilní se všemi hrami " +"(Guitar Hero)." #: pcsx2/gui/Dialogs/StuckThreadDialog.cpp:33 msgid "!Panel:StuckThread:Heading" -msgstr "Vlákno '%s' neodpovídá. Mohlo uváznout, nebo prostě běží *velmi* pomalu." +msgstr "" +"Vlákno '%s' neodpovídá. Mohlo uváznout, nebo prostě běží *velmi* pomalu." #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:38 msgid "!Panel:HasHacksOverrides" -msgstr "Varování! Spouštíte PCSX2 s volbami příkazového řádku, které potlačují Vaše uložená nastavení. Tyto volby příkazového řádku se nebudou odrážet v dialogovém okně Nastavení a budou zrušeny, pokud zde použijete jakékoli změny." +msgstr "" +"Varování! Spouštíte PCSX2 s volbami příkazového řádku, které potlačují Vaše " +"uložená nastavení. Tyto volby příkazového řádku se nebudou odrážet v " +"dialogovém okně Nastavení a budou zrušeny, pokud zde použijete jakékoli " +"změny." #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:58 msgid "!Panel:HasPluginsOverrides" -msgstr "Varování! Spouštíte PCSX2 s volbami příkazového řádku, které potlačují Vaše uložená nastavení zásuvných modulů a/nebo adresářů. Tyto volby příkazového řádku se nebudou odrážet v dialogovém okně Nastavení a budou zrušeny, když zde použijete jakékoli změny nastavení." +msgstr "" +"Varování! Spouštíte PCSX2 s volbami příkazového řádku, které potlačují Vaše " +"uložená nastavení zásuvných modulů a/nebo adresářů. Tyto volby příkazového " +"řádku se nebudou odrážet v dialogovém okně Nastavení a budou zrušeny, když " +"zde použijete jakékoli změny nastavení." #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:135 msgid "!Notice:Tooltip:Presets:Slider" msgstr "" -"Předvolby použijí hacky rychlosti, některá nastavení rekompilátoru a některé opravy her známé tím, že zvyšují rychlost.\n" +"Předvolby použijí hacky rychlosti, některá nastavení rekompilátoru a některé " +"opravy her známé tím, že zvyšují rychlost.\n" "Známé důležité opravy budou použity automaticky.\n" "\n" "Informace o předvolbách:\n" @@ -128,21 +184,28 @@ msgstr "" #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:149 msgid "!Notice:Tooltip:Presets:Checkbox" msgstr "" -"Předvolby použijí hacky rychlosti, některá nastavení rekompilátoru a některé opravy her známé tím, že zvyšují rychlost.\n" +"Předvolby použijí hacky rychlosti, některá nastavení rekompilátoru a některé " +"opravy her známé tím, že zvyšují rychlost.\n" "Známé důležité opravy budou použity automaticky.\n" "\n" -" --> Odškrtněte pro ruční změnu nastavení (se současnými předvolbami jako základ)" +" --> Odškrtněte pro ruční změnu nastavení (se současnými předvolbami jako " +"základ)" #: pcsx2/gui/IsoDropTarget.cpp:28 msgid "!Notice:ConfirmSysReset" -msgstr "Tato činnost resetuje existující stav virtuálního stroje PS2; veškerý současný postup bude ztracen. Jste si jisti?" +msgstr "" +"Tato činnost resetuje existující stav virtuálního stroje PS2; veškerý " +"současný postup bude ztracen. Jste si jisti?" #: pcsx2/gui/MainMenuClicks.cpp:106 msgid "!Notice:DeleteSettings" msgstr "" -"Tento příkaz vyčistí nastavení %s a umožňuje Vám znovu spustit Průvodce Prvním Spuštěním. Po této operaci budete muset ručně restartovat %s.\n" +"Tento příkaz vyčistí nastavení %s a umožňuje Vám znovu spustit Průvodce " +"Prvním Spuštěním. Po této operaci budete muset ručně restartovat %s.\n" "\n" -"VAROVÁNÍ!! Kliknutím na OK smažete *VŠECHNA* nastavení pro %s a přinutíte tuto aplikaci uzavřít, čímž ztratíte jakýkoli postup emulace. Jste si naprosto jisti?\n" +"VAROVÁNÍ!! Kliknutím na OK smažete *VŠECHNA* nastavení pro %s a přinutíte " +"tuto aplikaci uzavřít, čímž ztratíte jakýkoli postup emulace. Jste si " +"naprosto jisti?\n" "\n" "(poznámka: nastavení zásuvných modulů nejsou ovlivněna)" @@ -154,7 +217,9 @@ msgstr "" #: pcsx2/gui/Panels/BiosSelectorPanel.cpp:138 msgid "!Notice:BIOS:InvalidSelection" -msgstr "Prosím zvolte platný BIOS. Pokud nejste schopni provést platnou volbu, pak stiskněte Zrušit pro zavření Konfiguračního panelu." +msgstr "" +"Prosím zvolte platný BIOS. Pokud nejste schopni provést platnou volbu, pak " +"stiskněte Zrušit pro zavření Konfiguračního panelu." #: pcsx2/gui/Panels/CpuPanel.cpp:111 msgid "!Panel:EE/IOP:Heading" @@ -170,37 +235,59 @@ msgstr "Zadaná cesta/adresář neexistuje. Chtěli byste je vytvořit?" #: pcsx2/gui/Panels/DirPickerPanel.cpp:158 msgid "!ContextTip:DirPicker:UseDefault" -msgstr "Je-li zaškrtnuto, tento adresář bude automaticky odrážet výchozí asociaci se současným nastavením uživatelského režimu PCSX2." +msgstr "" +"Je-li zaškrtnuto, tento adresář bude automaticky odrážet výchozí asociaci se " +"současným nastavením uživatelského režimu PCSX2." #: pcsx2/gui/Panels/GSWindowPanel.cpp:55 msgid "!ContextTip:Window:Zoom" msgstr "" "Přiblížení = 100: Celý obraz bude umístěn do okna bez jakéhokoliv oříznutí.\n" "Nad/Pod 100: Přiblížení/Oddálení\n" -"0: Automaticky přibližovat, dokud černé čáry nezmizí (poměr stran je zachován, část obrazu bude mimo obrazovku).\n" -"POZNÁMKA: Některé hry vykreslují vlastní černé čáry, které pomocí '0' nebudou odstraněny.\n" +"0: Automaticky přibližovat, dokud černé čáry nezmizí (poměr stran je " +"zachován, část obrazu bude mimo obrazovku).\n" +"POZNÁMKA: Některé hry vykreslují vlastní černé čáry, které pomocí '0' " +"nebudou odstraněny.\n" "\n" -"Klávesnice: CTRL + PLUS: Přiblížení, CTRL + MÍNUS: Oddálení, CTRL + HVĚZDIČKA: Přepínání 100/0." +"Klávesnice: CTRL + PLUS: Přiblížení, CTRL + MÍNUS: Oddálení, CTRL + " +"HVĚZDIČKA: Přepínání 100/0." #: pcsx2/gui/Panels/GSWindowPanel.cpp:63 msgid "!ContextTip:Window:Vsync" -msgstr "Vsynch odstraňuje trhání obrazovky, ale má velký vliv na výkon. Většinou se toto týká režimu celé obrazovky a nemusí fungovat se všemi zásuvnými moduly GS." +msgstr "" +"Vsynch odstraňuje trhání obrazovky, ale má velký vliv na výkon. Většinou se " +"toto týká režimu celé obrazovky a nemusí fungovat se všemi zásuvnými moduly " +"GS." #: pcsx2/gui/Panels/GSWindowPanel.cpp:68 msgid "!ContextTip:Window:ManagedVsync" -msgstr "Povolí Vsynch když snímkovací frekvence je přesně na plné rychlosti. Pokud spadne pod tuto hodnotu, Vsynch je zakázána k zabránění dalších penalizací výkonu. Poznámka: Toto nyní správně funguje pouze s GSdx jako zásuvný modul GS a nastaveným na použití hardwarového vykreslování DX10/11. Jakýkoli jiný modul nebo režim vykreslování toto bude ignorovat, nebo vytvoří černý snímek, který blikne, kdykoliv je režim přepnut. Také vyžaduje povolenou Vsynch." +msgstr "" +"Povolí Vsynch když snímkovací frekvence je přesně na plné rychlosti. Pokud " +"spadne pod tuto hodnotu, Vsynch je zakázána k zabránění dalších penalizací " +"výkonu. Poznámka: Toto nyní správně funguje pouze s GSdx jako zásuvný modul " +"GS a nastaveným na použití hardwarového vykreslování DX10/11. Jakýkoli jiný " +"modul nebo režim vykreslování toto bude ignorovat, nebo vytvoří černý " +"snímek, který blikne, kdykoliv je režim přepnut. Také vyžaduje povolenou " +"Vsynch." #: pcsx2/gui/Panels/GSWindowPanel.cpp:76 msgid "!ContextTip:Window:HideMouse" -msgstr "Zašrktněte toto pro vynucení zneviditelnění kurzoru myši uvnitř okna GS; užitečné, jestli myš používáte jako hlavní kontrolní zařízení pro hraní. Standardně je myš schována po 2 vteřinách nečinnosti." +msgstr "" +"Zašrktněte toto pro vynucení zneviditelnění kurzoru myši uvnitř okna GS; " +"užitečné, jestli myš používáte jako hlavní kontrolní zařízení pro hraní. " +"Standardně je myš schována po 2 vteřinách nečinnosti." #: pcsx2/gui/Panels/GSWindowPanel.cpp:82 msgid "!ContextTip:Window:Fullscreen" -msgstr "Povolí automatické přepnutí režimu na celou obrazovku, při spuštění nebo obnově emulace. Stále můžete přepnout na celou obrazovku pomocí alt-enter." +msgstr "" +"Povolí automatické přepnutí režimu na celou obrazovku, při spuštění nebo " +"obnově emulace. Stále můžete přepnout na celou obrazovku pomocí alt-enter." #: pcsx2/gui/Panels/GSWindowPanel.cpp:93 msgid "!ContextTip:Window:HideGS" -msgstr "Úplně zavře často velké a rozměrné okno GS při stisku ESC nebo pozastavení emulátoru." +msgstr "" +"Úplně zavře často velké a rozměrné okno GS při stisku ESC nebo pozastavení " +"emulátoru." #: pcsx2/gui/Panels/GameFixesPanel.cpp:67 msgid "!ContextTip:Gamefixes:EE Timing Hack" @@ -235,16 +322,21 @@ msgstr "" msgid "!Panel:Gamefixes:Compat Warning" msgstr "" "Opravy her můžou obejít špatnou emulaci v některých hrách.\n" -"Můžou ale také způsobit problémy s kompatibilitou a výkonem, takže nejsou doporučeny.\n" +"Můžou ale také způsobit problémy s kompatibilitou a výkonem, takže nejsou " +"doporučeny.\n" "Opravy her jsou použity automaticky, takže zde nic nemusíte nastavovat." #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:720 msgid "!Notice:Mcd:Delete" -msgstr "Chystáte se smazat formátovanou paměťovou kartu '%s'. Všechna data na kartě budou ztracena! Jste si naprosto a zcela jisti?" +msgstr "" +"Chystáte se smazat formátovanou paměťovou kartu '%s'. Všechna data na kartě " +"budou ztracena! Jste si naprosto a zcela jisti?" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:758 msgid "!Notice:Mcd:CantDuplicate" -msgstr "Selhání: Kopírování je povoleno pouze na prázdnou pozici PS2 nebo do systému souborů." +msgstr "" +"Selhání: Kopírování je povoleno pouze na prázdnou pozici PS2 nebo do systému " +"souborů." #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:801 msgid "!Notice:Mcd:Copy Failed" @@ -252,23 +344,38 @@ msgstr "Selhání: Cílová paměťová karta '%s' se používá." #: pcsx2/gui/Panels/MiscPanelStuff.cpp:35 msgid "!Panel:Usermode:Explained" -msgstr "Prosím vyberte níže Vaši upřednostňované výchozí umístění pro dokumenty uživatelské úrovně PCSX2 (zahrnující paměťové karty, snímky obrazovky, nastavení a uložené stavy). Tyto umístění adresářů mohou být kdykoli potlačena použitím panelu Hlavního Nastavení." +msgstr "" +"Prosím vyberte níže Vaši upřednostňované výchozí umístění pro dokumenty " +"uživatelské úrovně PCSX2 (zahrnující paměťové karty, snímky obrazovky, " +"nastavení a uložené stavy). Tyto umístění adresářů mohou být kdykoli " +"potlačena použitím panelu Hlavního Nastavení." #: pcsx2/gui/Panels/MiscPanelStuff.cpp:41 msgid "!Panel:Usermode:Warning" -msgstr "Prosím vyberte níže Vaši upřednostňované výchozí umístění pro dokumenty uživatelské úrovně PCSX2 (zahrnující paměťové karty, snímky obrazovky, nastavení a uložené stavy). Tato volba ovlivňuje pouze Standardní Cesty, které jsou nastaveny, aby používali výchozí hodnoty instalace." +msgstr "" +"Prosím vyberte níže Vaši upřednostňované výchozí umístění pro dokumenty " +"uživatelské úrovně PCSX2 (zahrnující paměťové karty, snímky obrazovky, " +"nastavení a uložené stavy). Tato volba ovlivňuje pouze Standardní Cesty, " +"které jsou nastaveny, aby používali výchozí hodnoty instalace." #: pcsx2/gui/Panels/PathsPanel.cpp:40 msgid "!ContextTip:Folders:Savestates" -msgstr "Do tohoto adresáře PCSX2 ukládá uložené stavy, které jsou zaznamenány buď použitím menu/panelů nástrojů, nebo stisknutím F1/F3 (uložit/nahrát)." +msgstr "" +"Do tohoto adresáře PCSX2 ukládá uložené stavy, které jsou zaznamenány buď " +"použitím menu/panelů nástrojů, nebo stisknutím F1/F3 (uložit/nahrát)." #: pcsx2/gui/Panels/PathsPanel.cpp:50 msgid "!ContextTip:Folders:Snapshots" -msgstr "Toto je adresář, kde PCSX2 ukládá snímky obrazovky. Vlastní formát a styl snímku se může měnit v závislosti na používaném zásuvném modulu GS." +msgstr "" +"Toto je adresář, kde PCSX2 ukládá snímky obrazovky. Vlastní formát a styl " +"snímku se může měnit v závislosti na používaném zásuvném modulu GS." #: pcsx2/gui/Panels/PathsPanel.cpp:60 msgid "!ContextTip:Folders:Logs" -msgstr "Toto je adresář, kde PCSX2 ukládá své soubory se záznamem a diagnostické výpisy. Většina zásuvných modulů bude také používat tento adresář, ale některé starší ho můžou ignorovat." +msgstr "" +"Toto je adresář, kde PCSX2 ukládá své soubory se záznamem a diagnostické " +"výpisy. Většina zásuvných modulů bude také používat tento adresář, ale " +"některé starší ho můžou ignorovat." #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:242 msgid "!Notice:PluginSelector:ConfirmShutdown" @@ -276,19 +383,28 @@ msgstr "Varování! Změna zásuvných modulů vyžaduje" #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:457 msgid "!Notice:PluginSelector:ApplyFailed" -msgstr "Všechny zásuvné moduly musí mít platný výběr pro %s ke spuštění. Pokud nemůžete provést výběr kvůli chybějícímu modulu nebo nedokončené instalaci %s, pak stiskněte Zrušit pro uzavření panelu Nastavení." +msgstr "" +"Všechny zásuvné moduly musí mít platný výběr pro %s ke spuštění. Pokud " +"nemůžete provést výběr kvůli chybějícímu modulu nebo nedokončené instalaci " +"%s, pak stiskněte Zrušit pro uzavření panelu Nastavení." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:27 msgid "!Panel:Speedhacks:EECycleX1" -msgstr "Výchozí množství cyklů. Toto se blíže shoduje se skutečnou rychlostí opravdového EmotionEngine PS2." +msgstr "" +"Výchozí množství cyklů. Toto se blíže shoduje se skutečnou rychlostí " +"opravdového EmotionEngine PS2." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:32 msgid "!Panel:Speedhacks:EECycleX2" -msgstr "Sníží množství cyklů EE asi o 33%. Mírné zrychlení ve většině her s vysokou kompatibilitou." +msgstr "" +"Sníží množství cyklů EE asi o 33%. Mírné zrychlení ve většině her s vysokou " +"kompatibilitou." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:37 msgid "!Panel:Speedhacks:EECycleX3" -msgstr "Sníží množství cyklů EE asi o 50%. Průměrné zrychlení, ale *způsobí* zadrhování zvuku ve spoustě FMV." +msgstr "" +"Sníží množství cyklů EE asi o 50%. Průměrné zrychlení, ale *způsobí* " +"zadrhování zvuku ve spoustě FMV." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:54 msgid "!Panel:Speedhacks:VUCycleStealOff" @@ -296,78 +412,129 @@ msgstr "Zakáže krádež cyklů VJ. Nejkompatibilnější nastavení" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:59 msgid "!Panel:Speedhacks:VUCycleSteal1" -msgstr "Mírná krádež cyklů VJ. Nižší kompatibilita, ale jisté zrychlení ve většině her." +msgstr "" +"Mírná krádež cyklů VJ. Nižší kompatibilita, ale jisté zrychlení ve většině " +"her." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:64 msgid "!Panel:Speedhacks:VUCycleSteal2" -msgstr "Průměrná krádež cyklů VJ. Ještě nižší kompatibilita, ale výrazné zrychlení v některých hrách." +msgstr "" +"Průměrná krádež cyklů VJ. Ještě nižší kompatibilita, ale výrazné zrychlení v " +"některých hrách." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:70 msgid "!Panel:Speedhacks:VUCycleSteal3" -msgstr "Maximální krádež cyklů VJ. Užitečnost je omezená protože toto způsobuje blikání grafiky nebo zpomalení ve většině her. " +msgstr "" +"Maximální krádež cyklů VJ. Užitečnost je omezená protože toto způsobuje " +"blikání grafiky nebo zpomalení ve většině her. " #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:97 msgid "!Panel:Speedhacks:Overview" -msgstr "Hacky Rychlosti většinou zlepšují rychlost emulace, ale můžou způsobovat chyby, špatný zvuk a špatné údaje o SZS. Když máte problémy s emulací, tento panel zakažte nejdříve." +msgstr "" +"Hacky Rychlosti většinou zlepšují rychlost emulace, ale můžou způsobovat " +"chyby, špatný zvuk a špatné údaje o SZS. Když máte problémy s emulací, tento " +"panel zakažte nejdříve." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:129 msgid "!ContextTip:Speedhacks:EECycleRate Slider" -msgstr "Nastavením vyšších hodnot na tomto šoupátku účinně sníží rychlost hodin jádra R5900 procesoru EmotionEngine a typicky přináší velké zrychlení hrám, které nemohou využívat plný potenciál skutečného hardwaru PS2. " +msgstr "" +"Nastavením vyšších hodnot na tomto šoupátku účinně sníží rychlost hodin " +"jádra R5900 procesoru EmotionEngine a typicky přináší velké zrychlení hrám, " +"které nemohou využívat plný potenciál skutečného hardwaru PS2. " #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:150 msgid "!ContextTip:Speedhacks:VUCycleStealing Slider" -msgstr "Toto šoupátko kontroluje množství cyklů, které VJ ukradne od EmotionEngine. Vyšší hodnoty zvyšují počet ukradených cyklů od EE pro každý mikroprogram, který VJ spustí." +msgstr "" +"Toto šoupátko kontroluje množství cyklů, které VJ ukradne od EmotionEngine. " +"Vyšší hodnoty zvyšují počet ukradených cyklů od EE pro každý mikroprogram, " +"který VJ spustí." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:172 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "!ContextTip:Speedhacks:vuFlagHack" -msgstr "Aktualizuje Příznaky Stavu pouze v blocích, které je budou číst, místo neustále. Toto je většinou bezpečné a Super VJ dělá standardně něco podobného." +msgstr "" +"Aktualizuje Příznaky Stavu pouze v blocích, které je budou číst, místo " +"neustále. Toto je většinou bezpečné a Super VJ dělá standardně něco " +"podobného." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:177 -msgid "!ContextTip:Speedhacks:vuBlockHack" -msgstr "Předpokládá, že daleko v budoucnosti bloky nebudou potřebovat staré příznaky dat instancí. Toto by mělo být celkem bezpečné. Není známo, jestli toto nějakou hru poškozuje..." - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:182 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:174 msgid "!ContextTip:Speedhacks:vuThread" -msgstr "Spouští VJ1 na svém vlastním vlákně (pouze mikroVJ1). Na počítačích s 3 a více jádry většinou zrychlení. Toto je pro většinu her bezpečné, ale některé jsou nekompatibilní a mohou se zaseknout. V případě her omezených GS může dojít ke zpomalení (zvláště na počítačích s dvoujádrovým procesorem)." +msgstr "" +"Spouští VJ1 na svém vlastním vlákně (pouze mikroVJ1). Na počítačích s 3 a " +"více jádry většinou zrychlení. Toto je pro většinu her bezpečné, ale některé " +"jsou nekompatibilní a mohou se zaseknout. V případě her omezených GS může " +"dojít ke zpomalení (zvláště na počítačích s dvoujádrovým procesorem)." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:203 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:195 msgid "!ContextTip:Speedhacks:INTC" -msgstr "Tento hack funguje nejlépe v hrách, které používají stavy KPŘE registru pro čekání na vsynch, což hlavně zahrnuje ne-3D rpg hry. Ty, co tuto metodu v synch nepoužívají z tohoto hacku nedostanou žádné nebo malé zrychlení." +msgstr "" +"Tento hack funguje nejlépe v hrách, které používají stavy KPŘE registru pro " +"čekání na vsynch, což hlavně zahrnuje ne-3D rpg hry. Ty, co tuto metodu v " +"synch nepoužívají z tohoto hacku nedostanou žádné nebo malé zrychlení." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:208 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 msgid "!ContextTip:Speedhacks:BIFC0" -msgstr "Má za cíl hlavně čekací smyčku EE na adrese 0x81FC0 v kernelu, tento hack se pokusí zjistit smyčky, jejichž těla mají zaručeně za následek stejný stav stroje pro každé opakování doku naplánovaná událost nespustí emulaci další jednotky. Po prvním opakováním takovýchto smyček, pokročíme do doby další události nebo konce pracovního intervalu procesoru, co nastane dříve." +msgstr "" +"Má za cíl hlavně čekací smyčku EE na adrese 0x81FC0 v kernelu, tento hack se " +"pokusí zjistit smyčky, jejichž těla mají zaručeně za následek stejný stav " +"stroje pro každé opakování doku naplánovaná událost nespustí emulaci další " +"jednotky. Po prvním opakováním takovýchto smyček, pokročíme do doby další " +"události nebo konce pracovního intervalu procesoru, co nastane dříve." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:215 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:207 msgid "!ContextTip:Speedhacks:fastCDVD" -msgstr "Zkontrolujte seznam kompatibility HDLoadera pro hry, známé, že s tímto mají problémy. (často označené jako vyžadující 'mode 1' nebo 'slow DVD'" +msgstr "" +"Zkontrolujte seznam kompatibility HDLoadera pro hry, známé, že s tímto mají " +"problémy. (často označené jako vyžadující 'mode 1' nebo 'slow DVD'" #: pcsx2/gui/Panels/VideoPanel.cpp:37 msgid "!ContextTip:Framelimiter:Disable" -msgstr "Nezapomeňte, že když je omezení snímků vypnuté, nebudou ani také dostupné režimy Turbo a ZpomalenýPohyb." +msgstr "" +"Nezapomeňte, že když je omezení snímků vypnuté, nebudou ani také dostupné " +"režimy Turbo a ZpomalenýPohyb." -#: pcsx2/gui/Panels/VideoPanel.cpp:223 +#: pcsx2/gui/Panels/VideoPanel.cpp:227 msgid "!Panel:Frameskip:Heading" -msgstr "Upozornění: Kvůli hardwarovému designu PS2 je přesné přeskakování snímků nemožné. Zapnutím tohoto způsobí vážné grafické chyby v některých hrách." - -#: pcsx2/gui/Panels/VideoPanel.cpp:302 -msgid "!ContextTip:GS:SyncMTGS" -msgstr "Zapněte toto, pokud si myslíte, že synch vlákna VVGS způsobuje pády a grafické problémy." +msgstr "" +"Upozornění: Kvůli hardwarovému designu PS2 je přesné přeskakování snímků " +"nemožné. Zapnutím tohoto způsobí vážné grafické chyby v některých hrách." #: pcsx2/gui/Panels/VideoPanel.cpp:306 +msgid "!ContextTip:GS:SyncMTGS" +msgstr "" +"Zapněte toto, pokud si myslíte, že synch vlákna VVGS způsobuje pády a " +"grafické problémy." + +#: pcsx2/gui/Panels/VideoPanel.cpp:310 msgid "!ContextTip:GS:DisableOutput" msgstr "" -"Odstraní jakýkoli šum výkonnostního testu způsobený vláknem VVGS nebo časem zpracování grafického procesoru. Tato volba se nejlépe používá spolu s uloženými stavy: uložte stav v ideální scéně, zapněte tuto volbu, a znovu načtěte uložený stav.\n" +"Odstraní jakýkoli šum výkonnostního testu způsobený vláknem VVGS nebo časem " +"zpracování grafického procesoru. Tato volba se nejlépe používá spolu s " +"uloženými stavy: uložte stav v ideální scéně, zapněte tuto volbu, a znovu " +"načtěte uložený stav.\n" "\n" -"Varování: Tato volba může být zapnuta za běhu ale typicky nemůže být takto vypnuta (obraz bude většinou poškozený)" +"Varování: Tato volba může být zapnuta za běhu ale typicky nemůže být takto " +"vypnuta (obraz bude většinou poškozený)" #: pcsx2/vtlb.cpp:710 msgid "!Notice:HostVmReserve" -msgstr "Váš systém má příliš nízké virtuální zdroje, aby mohl být PCSX2 spuštěn. To může být způsobeno malým nebo vypnutým stránkovacím souborem, nebo jinými programy, které jsou náročné na zdroje." +msgstr "" +"Váš systém má příliš nízké virtuální zdroje, aby mohl být PCSX2 spuštěn. To " +"může být způsobeno malým nebo vypnutým stránkovacím souborem, nebo jinými " +"programy, které jsou náročné na zdroje." #: pcsx2/x86/sVU_zerorec.cpp:363 msgid "!Notice:superVU:VirtualMemoryAlloc" -msgstr "Došla Paměť (tak trochu): Rekompilátor SuperVJ nemohl vyhradit určitý vyžadovaný rozsah paměti a nebude dostupný k použití. To není kritická chyba, protože rek sVU je zastaralý a stejně byste místo něj měli používat mVU :)." +msgstr "" +"Došla Paměť (tak trochu): Rekompilátor SuperVJ nemohl vyhradit určitý " +"vyžadovaný rozsah paměti a nebude dostupný k použití. To není kritická " +"chyba, protože rek sVU je zastaralý a stejně byste místo něj měli používat " +"mVU :)." + +#~ msgid "!ContextTip:Speedhacks:vuBlockHack" +#~ msgstr "" +#~ "Předpokládá, že daleko v budoucnosti bloky nebudou potřebovat staré " +#~ "příznaky dat instancí. Toto by mělo být celkem bezpečné. Není známo, " +#~ "jestli toto nějakou hru poškozuje..." #~ msgid "No reason given." #~ msgstr "Bez udání důvodu." diff --git a/locales/cs_CZ/pcsx2_Main.po b/locales/cs_CZ/pcsx2_Main.po index 8a6a640b8..a6f5e0303 100644 --- a/locales/cs_CZ/pcsx2_Main.po +++ b/locales/cs_CZ/pcsx2_Main.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-09-28 20:27+0200\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: 2011-09-29 13:05+0100\n" "Last-Translator: Zbyněk Schwarz \n" "Language-Team: Zbyněk Schwarz\n" @@ -38,8 +38,14 @@ msgid "Oh noes! Out of memory!" msgstr "Ale ne! Došla paměť!" #: common/src/Utilities/Exceptions.cpp:234 -msgid "Virtual memory mapping failure! Your system may have conflicting device drivers, services, or may simply have insufficient memory or resources to meet PCSX2's lofty needs." -msgstr "Selhání mapování virtuální paměti! Váš systém může mít konfliktní ovladače zařízení, služby, nebo má prostě nedostatečnou paměť nebo zdroje, pro splnění vysokých nároků PCSX2." +msgid "" +"Virtual memory mapping failure! Your system may have conflicting device " +"drivers, services, or may simply have insufficient memory or resources to " +"meet PCSX2's lofty needs." +msgstr "" +"Selhání mapování virtuální paměti! Váš systém může mít konfliktní ovladače " +"zařízení, služby, nebo má prostě nedostatečnou paměť nebo zdroje, pro " +"splnění vysokých nároků PCSX2." #: common/src/Utilities/Exceptions.cpp:309 msgid "Path: " @@ -58,12 +64,20 @@ msgid "File not found." msgstr "Soubor nenalezen." #: common/src/Utilities/Exceptions.cpp:373 -msgid "Permission denied while trying to open file, likely due to insufficient user account rights." -msgstr "Oprávnění zamítnuto při pokusu o otevření souboru, pravděpodobně kvůli nedostatečným uživatelským oprávněním." +msgid "" +"Permission denied while trying to open file, likely due to insufficient user " +"account rights." +msgstr "" +"Oprávnění zamítnuto při pokusu o otevření souboru, pravděpodobně kvůli " +"nedostatečným uživatelským oprávněním." #: common/src/Utilities/Exceptions.cpp:393 -msgid "Unexpected end of file or stream encountered. File is probably truncated or corrupted." -msgstr "Objeven nečekaný konec souboru nebo proudu. Soubor je pravděpodobně zkrácen nebo poškozen." +msgid "" +"Unexpected end of file or stream encountered. File is probably truncated or " +"corrupted." +msgstr "" +"Objeven nečekaný konec souboru nebo proudu. Soubor je pravděpodobně zkrácen " +"nebo poškozen." #: common/src/Utilities/ThreadTools.cpp:41 msgid "Threading activity: start, detach, sync, deletion, etc." @@ -79,7 +93,8 @@ msgstr "Čekám na úkol..." #: common/src/Utilities/wxAppWithHelpers.cpp:36 msgid "Includes idle event processing and some other uncommon event usages." -msgstr "Zahrnuje zpracování nečinné události a další neobyčejné používání událostí." +msgstr "" +"Zahrnuje zpracování nečinné události a další neobyčejné používání událostí." #: pcsx2/CDVD/IsoFileFormats.cpp:416 msgid "Unrecognized ISO image file format" @@ -90,26 +105,42 @@ msgid "Cannot load ELF binary image. The file may be corrupt or incomplete." msgstr "Nelze načíst binární obraz ELF. Soubor může být poškozen nebo neúplný." #: pcsx2/Elfheader.cpp:268 -msgid "If loading from an ISO image, this error may be caused by an unsupported ISO image type or a bug in PCSX2 ISO image support." -msgstr "Pokud načítáte z obrazu ISO, tato chyba mohla být způsobena nepodporovaným typem obrazu ISO nebo chyba PCSX2 v podpoře obrazů ISO." +msgid "" +"If loading from an ISO image, this error may be caused by an unsupported ISO " +"image type or a bug in PCSX2 ISO image support." +msgstr "" +"Pokud načítáte z obrazu ISO, tato chyba mohla být způsobena nepodporovaným " +"typem obrazu ISO nebo chyba PCSX2 v podpoře obrazů ISO." #: pcsx2/MTGS.cpp:859 -msgid "The MTGS thread has become unresponsive while waiting for the GS plugin to open." -msgstr "Vlákno VVGS přestalo odpovídat při čekání na otevření zásuvného modulu GS." +msgid "" +"The MTGS thread has become unresponsive while waiting for the GS plugin to " +"open." +msgstr "" +"Vlákno VVGS přestalo odpovídat při čekání na otevření zásuvného modulu GS." #: pcsx2/PluginManager.cpp:709 -msgid "The savestate cannot be loaded, as it appears to be corrupt or incomplete." +msgid "" +"The savestate cannot be loaded, as it appears to be corrupt or incomplete." msgstr "Uložený stav nelze načíst, protože vypadá poškozený nebo neúplný" #: pcsx2/PluginManager.cpp:719 #, c-format -msgid "%s plugin failed to open. Your computer may have insufficient resources, or incompatible hardware/drivers." -msgstr "Zásuvný modul %s nelze otevřít. Váš počítač může mít nedostatečné zdroje, nebo nekompatibilní hardware/ovladače." +msgid "" +"%s plugin failed to open. Your computer may have insufficient resources, or " +"incompatible hardware/drivers." +msgstr "" +"Zásuvný modul %s nelze otevřít. Váš počítač může mít nedostatečné zdroje, " +"nebo nekompatibilní hardware/ovladače." #: pcsx2/PluginManager.cpp:726 #, c-format -msgid "%s plugin failed to initialize. Your system may have insufficient memory or resources needed." -msgstr "Zásuvný modul %s nelze spustit. Váš systém možná nemá dostatečnou paměť nebo potřebné zdroje." +msgid "" +"%s plugin failed to initialize. Your system may have insufficient memory or " +"resources needed." +msgstr "" +"Zásuvný modul %s nelze spustit. Váš systém možná nemá dostatečnou paměť nebo " +"potřebné zdroje." #: pcsx2/PluginManager.cpp:832 #, c-format @@ -123,21 +154,36 @@ msgstr "Nastavený soubor zásuvného modulu %s není platná dynamická knihovn #: pcsx2/PluginManager.cpp:854 #, c-format -msgid "The configured %s plugin is not a PCSX2 plugin, or is for an older unsupported version of PCSX2." -msgstr "Nastavený zásuvný modul %s není platný modul PCSX2, nebo je pro starší nepodporovanou verzi PCSX2." +msgid "" +"The configured %s plugin is not a PCSX2 plugin, or is for an older " +"unsupported version of PCSX2." +msgstr "" +"Nastavený zásuvný modul %s není platný modul PCSX2, nebo je pro starší " +"nepodporovanou verzi PCSX2." #: pcsx2/PluginManager.cpp:879 -msgid "The plugin reports that your hardware or software/drivers are not supported." -msgstr "Zásuvný modul hlásí, že Váš hardware nebo software/ovladače nejsou podporovány." +msgid "" +"The plugin reports that your hardware or software/drivers are not supported." +msgstr "" +"Zásuvný modul hlásí, že Váš hardware nebo software/ovladače nejsou " +"podporovány." #: pcsx2/PluginManager.cpp:900 -msgid "Configured plugin is not a PCSX2 plugin, or is for an older unsupported version of PCSX2." -msgstr "Nastavený zásuvný modul není modul PCSX2. nebo je pro starší nepodporovanou verzi PCSX2." +msgid "" +"Configured plugin is not a PCSX2 plugin, or is for an older unsupported " +"version of PCSX2." +msgstr "" +"Nastavený zásuvný modul není modul PCSX2. nebo je pro starší nepodporovanou " +"verzi PCSX2." #: pcsx2/PluginManager.cpp:926 #, c-format -msgid "Configured %s plugin is not a valid PCSX2 plugin, or is for an older unsupported version of PCSX2." -msgstr "Nastavený zásuvný modul %s není platný modul PCSX2, nebo je pro starší nepodporovanou verzi PCSX2." +msgid "" +"Configured %s plugin is not a valid PCSX2 plugin, or is for an older " +"unsupported version of PCSX2." +msgstr "" +"Nastavený zásuvný modul %s není platný modul PCSX2, nebo je pro starší " +"nepodporovanou verzi PCSX2." #: pcsx2/PluginManager.cpp:1355 msgid "Internal Memorycard Plugin failed to initialize." @@ -147,7 +193,7 @@ msgstr "Vnitřní zásuvný modul Paměťové Karty nelze spustit." msgid "Unloaded Plugin" msgstr "Uvolněný Zásuvný Modul" -#: pcsx2/SaveState.cpp:339 +#: pcsx2/SaveState.cpp:342 msgid "Cannot load savestate. It is of an unknown or unsupported version." msgstr "Nelze načíst uložený stav. Je neznámé nebo nepodporované verze." @@ -156,8 +202,12 @@ msgid "Dumps detailed information for PS2 executables (ELFs)." msgstr "Vypíše detailní informace pro spustitelné soubory PS2 (ELF)." #: pcsx2/SourceLog.cpp:101 -msgid "Logs manual protection, split blocks, and other things that might impact performance." -msgstr "Zaznamená ruční ochranu, rozdělené bloky, a jiné věci, které můžou mít vliv na výkon." +msgid "" +"Logs manual protection, split blocks, and other things that might impact " +"performance." +msgstr "" +"Zaznamená ruční ochranu, rozdělené bloky, a jiné věci, které můžou mít vliv " +"na výkon." #: pcsx2/SourceLog.cpp:106 msgid "Shows the game developer's logging text (EE processor)" @@ -177,10 +227,10 @@ msgstr "Aktivita SYSCALL a DECI2" #: pcsx2/SourceLog.cpp:151 msgid "Direct memory accesses to unknown or unmapped EE memory space." -msgstr "Přístupy přímé paměti do neznámého nebo nezmapovaného paměťového místa EE." +msgstr "" +"Přístupy přímé paměti do neznámého nebo nezmapovaného paměťového místa EE." -#: pcsx2/SourceLog.cpp:157 -#: pcsx2/SourceLog.cpp:276 +#: pcsx2/SourceLog.cpp:157 pcsx2/SourceLog.cpp:276 msgid "Disasm of executing core instructions (excluding COPs and CACHE)." msgstr "Rozložení spouštění instrukcí jádra (mimo COP a CACHE)" @@ -201,16 +251,19 @@ msgid "Execution of EE cache instructions." msgstr "Spuštění instrukcí vyrovnávací paměti EE." #: pcsx2/SourceLog.cpp:187 -msgid "All known hardware register accesses (very slow!); not including sub filter options below." -msgstr "Všechny známé přístupy hardwarového registru (velmi pomalé!); nezahrnuje možnosti pod filtru níže." +msgid "" +"All known hardware register accesses (very slow!); not including sub filter " +"options below." +msgstr "" +"Všechny známé přístupy hardwarového registru (velmi pomalé!); nezahrnuje " +"možnosti pod filtru níže." -#: pcsx2/SourceLog.cpp:193 -#: pcsx2/SourceLog.cpp:294 +#: pcsx2/SourceLog.cpp:193 pcsx2/SourceLog.cpp:294 msgid "Logs only unknown, unmapped, or unimplemented register accesses." -msgstr "Zaznamená pouze neznámé, nezmapované, nebo nezavedené přístupy registru." +msgstr "" +"Zaznamená pouze neznámé, nezmapované, nebo nezavedené přístupy registru." -#: pcsx2/SourceLog.cpp:199 -#: pcsx2/SourceLog.cpp:300 +#: pcsx2/SourceLog.cpp:199 pcsx2/SourceLog.cpp:300 msgid "Logs only DMA-related registers." msgstr "Zaznamená pouze registry vztahující se k DMA." @@ -236,7 +289,8 @@ msgstr "MFIFO aktivita Schratchpadu." #: pcsx2/SourceLog.cpp:235 msgid "Actual data transfer logs, bus right arbitration, stalls, etc." -msgstr "Skutečné záznamy přenosu dat, arbitráž oprávnění sběrnice, zahlcení, atd." +msgstr "" +"Skutečné záznamy přenosu dat, arbitráž oprávnění sběrnice, zahlcení, atd." #: pcsx2/SourceLog.cpp:241 msgid "Tracks all EE counters events and some counter register activity." @@ -256,15 +310,19 @@ msgstr "Aktivita SYSCALL a IRX" #: pcsx2/SourceLog.cpp:270 msgid "Direct memory accesses to unknown or unmapped IOP memory space." -msgstr "Přímé vstupy paměti do neznámého nebo nezmapovaného prostoru paměti IOP." +msgstr "" +"Přímé vstupy paměti do neznámého nebo nezmapovaného prostoru paměti IOP." #: pcsx2/SourceLog.cpp:282 msgid "Disasm of the IOP's GPU co-processor instructions." msgstr "Rozložení instrukcí koprocesoru IOP z GPU." #: pcsx2/SourceLog.cpp:288 -msgid "All known hardware register accesses, not including the sub-filters below." -msgstr "Všechny známé přístupy hardwarového registru, nezahrnuje možnosti pod filtru níže." +msgid "" +"All known hardware register accesses, not including the sub-filters below." +msgstr "" +"Všechny známé přístupy hardwarového registru, nezahrnuje možnosti pod filtru " +"níže." #: pcsx2/SourceLog.cpp:306 msgid "Memorycard reads, writes, erases, terminators, and other processing." @@ -280,48 +338,50 @@ msgstr "Skutečné zpracování události DMA a záznamy přenosu dat." #: pcsx2/SourceLog.cpp:324 msgid "Tracks all IOP counters events and some counter register activity." -msgstr "Sleduje všechny události čítače IOP a některé aktivity registru čítače." +msgstr "" +"Sleduje všechny události čítače IOP a některé aktivity registru čítače." #: pcsx2/SourceLog.cpp:330 msgid "Detailed logging of CDVD hardware." msgstr "Detailní záznam hardwaru CDVD." -#: pcsx2/System.h:206 -#: pcsx2/System.h:207 -#: pcsx2/System.h:208 +#: pcsx2/System.h:206 pcsx2/System.h:207 pcsx2/System.h:208 msgid "PCSX2 Message" msgstr "Zpráva PCSX2" #: pcsx2/ZipTools/thread_gzip.cpp:82 -msgid "The savestate was not properly saved. The temporary file was created successfully but could not be moved to its final resting place." -msgstr "Uložený stav nebyl správně uložen. Dočasný soubor byl úspěšně vytvořen ale nemohl být přesunut do svého posledního místa odpočinku." +msgid "" +"The savestate was not properly saved. The temporary file was created " +"successfully but could not be moved to its final resting place." +msgstr "" +"Uložený stav nebyl správně uložen. Dočasný soubor byl úspěšně vytvořen ale " +"nemohl být přesunut do svého posledního místa odpočinku." -#: pcsx2/gui/AppConfig.cpp:837 +#: pcsx2/gui/AppConfig.cpp:842 msgid "Safest" msgstr "Nejbezpečnější" -#: pcsx2/gui/AppConfig.cpp:838 +#: pcsx2/gui/AppConfig.cpp:843 msgid "Safe (faster)" msgstr "Bezpečné (rychlejší)" -#: pcsx2/gui/AppConfig.cpp:839 +#: pcsx2/gui/AppConfig.cpp:844 msgid "Balanced" msgstr "Vyrovnaný" -#: pcsx2/gui/AppConfig.cpp:840 +#: pcsx2/gui/AppConfig.cpp:845 msgid "Aggressive" msgstr "Agresivní" -#: pcsx2/gui/AppConfig.cpp:841 +#: pcsx2/gui/AppConfig.cpp:846 msgid "Aggressive plus" msgstr "Agresivní plus" -#: pcsx2/gui/AppConfig.cpp:842 +#: pcsx2/gui/AppConfig.cpp:847 msgid "Mostly Harmful" msgstr "Většinou Škodlivý" -#: pcsx2/gui/AppConfig.cpp:999 -#: pcsx2/gui/AppConfig.cpp:1005 +#: pcsx2/gui/AppConfig.cpp:1007 pcsx2/gui/AppConfig.cpp:1013 msgid "Failed to overwrite existing settings file; permission was denied." msgstr "Nelze přepsat existující soubor nastavení; oprávnění bylo zamítnuto." @@ -334,8 +394,12 @@ msgid "PCSX2 - SSE2 Recommended" msgstr "PCSX2 - SSE2 Doporučeno" #: pcsx2/gui/AppInit.cpp:71 -msgid "SSE extensions are not available. PCSX2 requires a cpu that supports the SSE instruction set." -msgstr "Rozšíření SSE nejsou dostupná. PCSX2 vyžaduje procesor, který podporuje instrukční sadu SSE." +msgid "" +"SSE extensions are not available. PCSX2 requires a cpu that supports the " +"SSE instruction set." +msgstr "" +"Rozšíření SSE nejsou dostupná. PCSX2 vyžaduje procesor, který podporuje " +"instrukční sadu SSE." #: pcsx2/gui/AppInit.cpp:154 msgid "PCSX2 Recompiler Error(s)" @@ -345,8 +409,7 @@ msgstr "Chyba/y Rekompilátoru PCSX2" msgid "All options are for the current session only and will not be saved.\n" msgstr "Všechny volby jsou pouze pro současnou relaci a nebudou uloženy.\n" -#: pcsx2/gui/AppInit.cpp:237 -#: pcsx2/gui/AppMain.cpp:299 +#: pcsx2/gui/AppInit.cpp:237 pcsx2/gui/AppMain.cpp:299 msgid "IsoFile" msgstr "Soubor ISO" @@ -376,7 +439,8 @@ msgstr "spustí obraz ELF" #: pcsx2/gui/AppInit.cpp:245 msgid "boots an empty dvd tray; use to enter the PS2 system menu" -msgstr "zavede prázdnou mechaniku dvd; použijte pro vstup do systémového menu PS2" +msgstr "" +"zavede prázdnou mechaniku dvd; použijte pro vstup do systémového menu PS2" #: pcsx2/gui/AppInit.cpp:246 msgid "boots from the CDVD plugin (overrides IsoFile parameter)" @@ -409,7 +473,8 @@ msgstr "donutí %s spustit Průvodce Prvním Spuštěním" #: pcsx2/gui/AppInit.cpp:255 msgid "enables portable mode operation (requires admin/root access)" -msgstr "povolí operace přenosného režimu (vyžaduje administrátorský/kořenový přístup)" +msgstr "" +"povolí operace přenosného režimu (vyžaduje administrátorský/kořenový přístup)" #: pcsx2/gui/AppInit.cpp:259 #, c-format @@ -424,23 +489,26 @@ msgstr "Chyba Potlačení Zásuvného Modulu - %s" #: pcsx2/gui/AppInit.cpp:310 #, c-format msgid "" -"%s Plugin Override Error! The following file does not exist or is not a valid %s plugin:\n" +"%s Plugin Override Error! The following file does not exist or is not a " +"valid %s plugin:\n" "\n" msgstr "" -"Chyba Potlačení Zásuvného Modulu %s! Následující soubor neexistuje nebo není platný modul %s:\n" +"Chyba Potlačení Zásuvného Modulu %s! Následující soubor neexistuje nebo není " +"platný modul %s:\n" "\n" #: pcsx2/gui/AppInit.cpp:317 #, c-format msgid "Press OK to use the default configured plugin, or Cancel to close %s." -msgstr "Stiskněte OK pro použití výchozího nastaveného zásuvného modulu, nebo Zrušit pro zavření %s." +msgstr "" +"Stiskněte OK pro použití výchozího nastaveného zásuvného modulu, nebo Zrušit " +"pro zavření %s." #: pcsx2/gui/AppInit.cpp:496 msgid "PCSX2 Error: Hardware Deficiency" msgstr "Chyba PCSX2: Hardwarová Vada" -#: pcsx2/gui/AppInit.cpp:496 -#: pcsx2/gui/AppInit.cpp:508 +#: pcsx2/gui/AppInit.cpp:496 pcsx2/gui/AppInit.cpp:508 #, c-format msgid "Press OK to close %s." msgstr "Stiskněte OK pro uzavření %s." @@ -528,10 +596,12 @@ msgstr "" "\n" "Stiskněte Ok pro přechod na Panel Nastavení Zásuvných Modulů." -#: pcsx2/gui/AppMain.cpp:140 -#: pcsx2/gui/AppMain.cpp:154 -msgid "Warning! System plugins have not been loaded. PCSX2 may be inoperable." -msgstr "Varování! Systémové zásuvné moduly nebyly načteny. PCSX2 může být nepoužitelný." +#: pcsx2/gui/AppMain.cpp:140 pcsx2/gui/AppMain.cpp:154 +msgid "" +"Warning! System plugins have not been loaded. PCSX2 may be inoperable." +msgstr "" +"Varování! Systémové zásuvné moduly nebyly načteny. PCSX2 může být " +"nepoužitelný." #: pcsx2/gui/AppMain.cpp:309 #, c-format @@ -580,8 +650,12 @@ msgid "Portable mode error - %s" msgstr "Chyba přenosného režimu - %s" #: pcsx2/gui/AppUserMode.cpp:157 -msgid "PCSX2 has been installed as a portable application but cannot run due to the following errors:" -msgstr "PCSX2 byl nainstalován jako přenosná aplikace, ale nemůže být spuštěn kvůli následujícím chybám:" +msgid "" +"PCSX2 has been installed as a portable application but cannot run due to the " +"following errors:" +msgstr "" +"PCSX2 byl nainstalován jako přenosná aplikace, ale nemůže být spuštěn kvůli " +"následujícím chybám:" #: pcsx2/gui/AppUserMode.cpp:165 msgid "Switch to User Documents Mode" @@ -593,8 +667,12 @@ msgid "%s is switching to local install mode." msgstr "%s se přepíná do režimu místní instalace." #: pcsx2/gui/AppUserMode.cpp:179 -msgid "Try to remove the file called \"portable.ini\" from your installation directory manually." -msgstr "Zkuste odstranit soubor nazvaný \"portable.ini\" z Vašeho instalačního adresáře ručně. " +msgid "" +"Try to remove the file called \"portable.ini\" from your installation " +"directory manually." +msgstr "" +"Zkuste odstranit soubor nazvaný \"portable.ini\" z Vašeho instalačního " +"adresáře ručně. " #: pcsx2/gui/ApplyState.h:55 msgid "Cannot apply new settings, one of the settings is invalid." @@ -616,8 +694,7 @@ msgstr "Malé" msgid "It's what I use (the programmer guy)." msgstr "To, co používám já (programátor)." -#: pcsx2/gui/ConsoleLogger.cpp:415 -#: pcsx2/gui/Panels/CpuPanel.cpp:38 +#: pcsx2/gui/ConsoleLogger.cpp:415 pcsx2/gui/Panels/CpuPanel.cpp:38 msgid "Normal" msgstr "Normální" @@ -646,8 +723,12 @@ msgid "Light theme" msgstr "Světlý vzhled" #: pcsx2/gui/ConsoleLogger.cpp:424 -msgid "Classic black color scheme for people who enjoy having text seared into their optic nerves." -msgstr "Klasický vzhled černé barvy pro lidi, kteří mají rádi text vypálen do jejich optických nervů." +msgid "" +"Classic black color scheme for people who enjoy having text seared into " +"their optic nerves." +msgstr "" +"Klasický vzhled černé barvy pro lidi, kteří mají rádi text vypálen do jejich " +"optických nervů." #: pcsx2/gui/ConsoleLogger.cpp:424 msgid "Dark theme" @@ -658,8 +739,10 @@ msgid "Always on Top" msgstr "Vždy Nahoře" #: pcsx2/gui/ConsoleLogger.cpp:428 -msgid "When checked the log window will be visible over other foreground windows." -msgstr "Při zaškrtnutí bude okno záznamu viditelné nad ostatními okny v popředí." +msgid "" +"When checked the log window will be visible over other foreground windows." +msgstr "" +"Při zaškrtnutí bude okno záznamu viditelné nad ostatními okny v popředí." #: pcsx2/gui/ConsoleLogger.cpp:430 msgid "&Save..." @@ -677,8 +760,7 @@ msgstr "&Vyčistit" msgid "Clear the log window contents" msgstr "Vyčistit obsah okna se záznamem" -#: pcsx2/gui/ConsoleLogger.cpp:433 -#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:280 +#: pcsx2/gui/ConsoleLogger.cpp:433 pcsx2/gui/Dialogs/SysConfigDialog.cpp:280 msgid "Appearance" msgstr "Vzhled" @@ -800,12 +882,20 @@ msgid "Do not show this dialog again." msgstr "Už toto dialogové okno nezobrazovat." #: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:199 -msgid "Disables this popup and whatever response you select here will be automatically used from now on." -msgstr "Zakáže toto vyskakovací okno a jakákoliv odpověď, kterou zde vyberete bude, odteď automaticky použita." +msgid "" +"Disables this popup and whatever response you select here will be " +"automatically used from now on." +msgstr "" +"Zakáže toto vyskakovací okno a jakákoliv odpověď, kterou zde vyberete bude, " +"odteď automaticky použita." #: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:201 -msgid "The popup will not be shown again. This setting can be undone from the settings panels." -msgstr "Vyskakující okno už se znovu nezobrazí. Toto nastavení může být zrušeno z panelů nastavení." +msgid "" +"The popup will not be shown again. This setting can be undone from the " +"settings panels." +msgstr "" +"Vyskakující okno už se znovu nezobrazí. Toto nastavení může být zrušeno z " +"panelů nastavení." #: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:247 #: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:292 @@ -862,12 +952,20 @@ msgid "8 MB [most compatible]" msgstr "8 MB [nejvíce kompatibilní]" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:195 -msgid "This is the standard Sony-provisioned size, and is supported by all games and BIOS versions." -msgstr "Toto je standardní velikost dodávaná Sony a je podporována všemi hrami a verzemi BIOS." +msgid "" +"This is the standard Sony-provisioned size, and is supported by all games " +"and BIOS versions." +msgstr "" +"Toto je standardní velikost dodávaná Sony a je podporována všemi hrami a " +"verzemi BIOS." #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:196 -msgid "Always use this option if you want the safest and surest memory card behavior." -msgstr "Používejte tuto volbu vždy, když chcete nejbezpečnější a nejjistější chování paměťové karty." +msgid "" +"Always use this option if you want the safest and surest memory card " +"behavior." +msgstr "" +"Používejte tuto volbu vždy, když chcete nejbezpečnější a nejjistější chování " +"paměťové karty." #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:199 msgid "16 MB" @@ -875,8 +973,11 @@ msgstr "16 MB" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:199 #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:203 -msgid "A typical size for 3rd-party memory cards which should work with most games." -msgstr "Typická velikost pro paměťové karty 3. strany, která by měla fungovat ve většině her." +msgid "" +"A typical size for 3rd-party memory cards which should work with most games." +msgstr "" +"Typická velikost pro paměťové karty 3. strany, která by měla fungovat ve " +"většině her." #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:200 #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:204 @@ -892,12 +993,20 @@ msgid "64 MB" msgstr "64 MB" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:207 -msgid "Low compatibility warning: Yes it's very big, but may not work with many games." -msgstr "Varování nízké kompatibility: Ano, je velmi velká, ale nefunguje ve spoustě hrách." +msgid "" +"Low compatibility warning: Yes it's very big, but may not work with many " +"games." +msgstr "" +"Varování nízké kompatibility: Ano, je velmi velká, ale nefunguje ve spoustě " +"hrách." #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:208 -msgid "Use at your own risk. Erratic memory card behavior is possible (though unlikely)." -msgstr "Používejte na vlastní riziko. Je možné nestálé chování paměťové karty (i když nepravděpodobné)." +msgid "" +"Use at your own risk. Erratic memory card behavior is possible (though " +"unlikely)." +msgstr "" +"Používejte na vlastní riziko. Je možné nestálé chování paměťové karty (i " +"když nepravděpodobné)." #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:47 #, c-format @@ -976,7 +1085,8 @@ msgid "" "Note: Duplicate/Rename/Create/Delete will NOT be reverted with 'Cancel'." msgstr "" "\n" -"Poznámka: Kopírovat/Přejmenovat/Vytvořit/Smazat NEBUDE tlačítkem 'Zrušit' přerušeno." +"Poznámka: Kopírovat/Přejmenovat/Vytvořit/Smazat NEBUDE tlačítkem 'Zrušit' " +"přerušeno." #: pcsx2/gui/Dialogs/PickUserModeDialog.cpp:24 msgid "PCSX2 First Time configuration" @@ -985,7 +1095,8 @@ msgstr "Prvotní nastavení PCSX2" #: pcsx2/gui/Dialogs/PickUserModeDialog.cpp:29 #, c-format msgid "%s is starting from a new or unknown folder and needs to be configured." -msgstr "%s je spouštěn z nového nebo neznámého adresáře a potřebuje být nastaven." +msgstr "" +"%s je spouštěn z nového nebo neznámého adresáře a potřebuje být nastaven." #: pcsx2/gui/Dialogs/StuckThreadDialog.cpp:28 msgid "PCSX2 Thread is not responding" @@ -1075,8 +1186,7 @@ msgstr "Ukončit Aplikaci" msgid "GS Output is Disabled!" msgstr "Výstup GS je Zakázán!" -#: pcsx2/gui/GlobalCommands.cpp:387 -#: pcsx2/gui/MainFrame.cpp:414 +#: pcsx2/gui/GlobalCommands.cpp:387 pcsx2/gui/MainFrame.cpp:414 msgid "Save state" msgstr "Uložit stav" @@ -1084,8 +1194,7 @@ msgstr "Uložit stav" msgid "Saves the virtual machine state to the current slot." msgstr "Uloží stav virtuálního stroje do současné pozice." -#: pcsx2/gui/GlobalCommands.cpp:393 -#: pcsx2/gui/MainFrame.cpp:413 +#: pcsx2/gui/GlobalCommands.cpp:393 pcsx2/gui/MainFrame.cpp:413 msgid "Load state" msgstr "Nahrát stav" @@ -1123,11 +1232,12 @@ msgstr "Chyba Přetáhnutí" #: pcsx2/gui/IsoDropTarget.cpp:58 #, c-format -msgid "It is an error to drop multiple files onto a %s window. One at a time please, thank you." +msgid "" +"It is an error to drop multiple files onto a %s window. One at a time " +"please, thank you." msgstr "Je chyba přetahovat mnoho souborů do okna %s. " -#: pcsx2/gui/IsoDropTarget.cpp:89 -#: pcsx2/gui/MainMenuClicks.cpp:342 +#: pcsx2/gui/IsoDropTarget.cpp:89 pcsx2/gui/MainMenuClicks.cpp:342 msgid "Confirm PS2 Reset" msgstr "Potvrdit Resetování PS2" @@ -1150,8 +1260,7 @@ msgstr "Přetáhli jste následující obraz ISO do %s:" msgid "Slot %d" msgstr "Pozice %d" -#: pcsx2/gui/MainFrame.cpp:44 -#: pcsx2/gui/Saveslots.cpp:150 +#: pcsx2/gui/MainFrame.cpp:44 pcsx2/gui/Saveslots.cpp:150 msgid "Backup" msgstr "Záloha" @@ -1197,8 +1306,7 @@ msgstr "%s %d.%d.%d %s" msgid "(modded)" msgstr "(pozměněno)" -#: pcsx2/gui/MainFrame.cpp:399 -#: pcsx2/gui/MainFrame.cpp:401 +#: pcsx2/gui/MainFrame.cpp:399 pcsx2/gui/MainFrame.cpp:401 #: pcsx2/gui/MainFrame.cpp:407 msgid "Initializing..." msgstr "Zavádím..." @@ -1292,8 +1400,7 @@ msgstr "&Paměťové karty" msgid "&Plugin/BIOS Selector" msgstr "&Výběr Zásuvných Modulů/BIOSu" -#: pcsx2/gui/MainFrame.cpp:460 -#: pcsx2/gui/Panels/GameDatabasePanel.cpp:346 +#: pcsx2/gui/MainFrame.cpp:460 pcsx2/gui/Panels/GameDatabasePanel.cpp:346 msgid "Game Database Editor" msgstr "Editor Databáze Her" @@ -1412,10 +1519,10 @@ msgstr "Zavést CDVD (rychle)" #: pcsx2/gui/MainFrame.cpp:642 msgid "Use fast boot to skip PS2 startup and splash screens" -msgstr "Použít rychlé zavedení pro přeskočení spouštěcích a úvodních obrazovek PS2" +msgstr "" +"Použít rychlé zavedení pro přeskočení spouštěcích a úvodních obrazovek PS2" -#: pcsx2/gui/MainFrame.cpp:703 -#: pcsx2/gui/MainFrame.cpp:738 +#: pcsx2/gui/MainFrame.cpp:703 pcsx2/gui/MainFrame.cpp:738 msgid "No plugin loaded" msgstr "Nejsou načteny žádné zásuvné moduly" @@ -1424,8 +1531,12 @@ msgid "Core GS Settings..." msgstr "Nastavení Jádra GS..." #: pcsx2/gui/MainFrame.cpp:709 -msgid "Modify hardware emulation settings regulated by the PCSX2 core virtual machine." -msgstr "Změnit nastavení emulace hardwaru, regulované jádrem virtuálního stroje PCSX2." +msgid "" +"Modify hardware emulation settings regulated by the PCSX2 core virtual " +"machine." +msgstr "" +"Změnit nastavení emulace hardwaru, regulované jádrem virtuálního stroje " +"PCSX2." #: pcsx2/gui/MainFrame.cpp:711 msgid "Window Settings..." @@ -1456,8 +1567,7 @@ msgstr "Potvrdit změnu obrazu ISO" msgid "Do you want to swap discs or boot the new image (via system reset)?" msgstr "Chcete vyměnit disky nebo zavést nový obraz (přes reset systému)?" -#: pcsx2/gui/MainMenuClicks.cpp:148 -#: pcsx2/gui/MainMenuClicks.cpp:194 +#: pcsx2/gui/MainMenuClicks.cpp:148 pcsx2/gui/MainMenuClicks.cpp:194 msgid "Swap Disc" msgstr "Vyměnit Disk" @@ -1489,8 +1599,7 @@ msgstr "Obrazy Disku (%s)" msgid "Blockdumps (%s)" msgstr "Výpisy bloků (%s)" -#: pcsx2/gui/MainMenuClicks.cpp:270 -#: pcsx2/gui/MainMenuClicks.cpp:291 +#: pcsx2/gui/MainMenuClicks.cpp:270 pcsx2/gui/MainMenuClicks.cpp:291 msgid "All Files (*.*)" msgstr "Všechny soubory (*.*)" @@ -1511,8 +1620,12 @@ msgid "An error occurred while trying to open the file:" msgstr "Vyskytla se chyba při pokusu o otevření souboru:" #: pcsx2/gui/MainMenuClicks.cpp:319 -msgid "Error: The configured ISO file does not exist. Click OK to select a new ISO source for CDVD." -msgstr "Chyba: Nastavený soubor ISO neexistuje. Klikněte na OK pro vybrání nového zdroje ISO pro CDVD." +msgid "" +"Error: The configured ISO file does not exist. Click OK to select a new ISO " +"source for CDVD." +msgstr "" +"Chyba: Nastavený soubor ISO neexistuje. Klikněte na OK pro vybrání nového " +"zdroje ISO pro CDVD." #: pcsx2/gui/MainMenuClicks.cpp:390 msgid "" @@ -1577,8 +1690,12 @@ msgid "Select folder with PS2 BIOS roms" msgstr "Vyberte adresář s romy BIOSu PS2" #: pcsx2/gui/Panels/BiosSelectorPanel.cpp:111 -msgid "Click the Browse button to select a different folder where PCSX2 will look for PS2 BIOS roms." -msgstr "Klikněte na tlačítko Procházet pro vybrání jiného adresáře, kde bude PCSX2 hledat romy BIOSu PS2." +msgid "" +"Click the Browse button to select a different folder where PCSX2 will look " +"for PS2 BIOS roms." +msgstr "" +"Klikněte na tlačítko Procházet pro vybrání jiného adresáře, kde bude PCSX2 " +"hledat romy BIOSu PS2." #: pcsx2/gui/Panels/BiosSelectorPanel.cpp:113 #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:156 @@ -1622,8 +1739,7 @@ msgstr "Žádný" msgid "EE/FPU Advanced Recompiler Options" msgstr "EE/MKO Pokročilé Možnosti Rekompilátoru" -#: pcsx2/gui/Panels/CpuPanel.cpp:87 -#: pcsx2/gui/Panels/CpuPanel.cpp:102 +#: pcsx2/gui/Panels/CpuPanel.cpp:87 pcsx2/gui/Panels/CpuPanel.cpp:102 msgid "Extra + Preserve Sign" msgstr "Extra + Zachovat Znaménko" @@ -1639,8 +1755,7 @@ msgstr "VJ0 / VJ1 Pokročilé Volby Rekompilátoru" msgid "Extra" msgstr "Extra" -#: pcsx2/gui/Panels/CpuPanel.cpp:117 -#: pcsx2/gui/Panels/CpuPanel.cpp:126 +#: pcsx2/gui/Panels/CpuPanel.cpp:117 pcsx2/gui/Panels/CpuPanel.cpp:126 #: pcsx2/gui/Panels/CpuPanel.cpp:184 msgid "Interpreter" msgstr "Převaděč" @@ -1649,22 +1764,27 @@ msgstr "Převaděč" msgid "Quite possibly the slowest thing in the universe." msgstr "Dost možná ta nejpomalejší věc ve vesmíru." -#: pcsx2/gui/Panels/CpuPanel.cpp:120 -#: pcsx2/gui/Panels/CpuPanel.cpp:129 +#: pcsx2/gui/Panels/CpuPanel.cpp:120 pcsx2/gui/Panels/CpuPanel.cpp:129 msgid "Recompiler" msgstr "Rekompilátor" #: pcsx2/gui/Panels/CpuPanel.cpp:121 -msgid "Performs just-in-time binary translation of 64-bit MIPS-IV machine code to x86." -msgstr "Provádí binární překlad 'za běhu' 64 bitového strojového kódu MIPS-IV do x86." +msgid "" +"Performs just-in-time binary translation of 64-bit MIPS-IV machine code to " +"x86." +msgstr "" +"Provádí binární překlad 'za běhu' 64 bitového strojového kódu MIPS-IV do x86." #: pcsx2/gui/Panels/CpuPanel.cpp:127 msgid "Pretty slow; provided for diagnostic purposes only." msgstr "Pěkně pomalý; poskytnutý pouze pro diagnostické účely." #: pcsx2/gui/Panels/CpuPanel.cpp:130 -msgid "Performs just-in-time binary translation of 32-bit MIPS-I machine code to x86." -msgstr "Provádí binární překlad 'za běhu' 32 bitového strojového kódu MIPS-I do x86." +msgid "" +"Performs just-in-time binary translation of 32-bit MIPS-I machine code to " +"x86." +msgstr "" +"Provádí binární překlad 'za běhu' 32 bitového strojového kódu MIPS-I do x86." #: pcsx2/gui/Panels/CpuPanel.cpp:154 msgid "Enable EE Cache (Slower)" @@ -1674,31 +1794,40 @@ msgstr "Povolit Vyr. Paměť EE (Pomalejší)" msgid "Interpreter only; provided for diagnostic" msgstr "Pouze převaděč; pro diagnostické účely" -#: pcsx2/gui/Panels/CpuPanel.cpp:170 -#: pcsx2/gui/Panels/CpuPanel.cpp:223 +#: pcsx2/gui/Panels/CpuPanel.cpp:170 pcsx2/gui/Panels/CpuPanel.cpp:223 #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:110 msgid "Restore Defaults" msgstr "Obnovit Výchozí" #: pcsx2/gui/Panels/CpuPanel.cpp:185 -msgid "Vector Unit Interpreter. Slow and not very compatible. Only use for diagnostics." -msgstr "Převaděč Vektorové Jednotky. Pomalý a ne moc kompatibilní. Používaný pouze pro diagnostiku." +msgid "" +"Vector Unit Interpreter. Slow and not very compatible. Only use for " +"diagnostics." +msgstr "" +"Převaděč Vektorové Jednotky. Pomalý a ne moc kompatibilní. Používaný pouze " +"pro diagnostiku." #: pcsx2/gui/Panels/CpuPanel.cpp:187 msgid "microVU Recompiler" msgstr "Rekompilátor mikroVJ" #: pcsx2/gui/Panels/CpuPanel.cpp:188 -msgid "New Vector Unit recompiler with much improved compatibility. Recommended." -msgstr "Nový rekompilátor Vektorové Jednotky s mnohem lepší kompatibilitou. Doporučeno." +msgid "" +"New Vector Unit recompiler with much improved compatibility. Recommended." +msgstr "" +"Nový rekompilátor Vektorové Jednotky s mnohem lepší kompatibilitou. " +"Doporučeno." #: pcsx2/gui/Panels/CpuPanel.cpp:190 msgid "superVU Recompiler [legacy]" msgstr "Rekompilátor superVJ [zastaralé]" #: pcsx2/gui/Panels/CpuPanel.cpp:191 -msgid "Useful for diagnosing bugs or clamping issues in the new mVU recompiler." -msgstr "Užitečné pro zjišťování chyb nebo problémů s upnutím v novém mVJ rekompilátoru." +msgid "" +"Useful for diagnosing bugs or clamping issues in the new mVU recompiler." +msgstr "" +"Užitečné pro zjišťování chyb nebo problémů s upnutím v novém mVJ " +"rekompilátoru." #: pcsx2/gui/Panels/DirPickerPanel.cpp:64 msgid "Path does not exist" @@ -1759,7 +1888,9 @@ msgstr "Čekat na Vsynch při obnově" #: pcsx2/gui/Panels/GSWindowPanel.cpp:51 msgid "Dynamically toggle Vsync depending on frame rate (read tooltip!)" -msgstr "Dynamicky přepínat Vsynch v závislosti na snímkové frekvenci (přečtěte si popisek!)" +msgstr "" +"Dynamicky přepínat Vsynch v závislosti na snímkové frekvenci (přečtěte si " +"popisek!)" #: pcsx2/gui/Panels/GSWindowPanel.cpp:52 msgid "Double-click toggles fullscreen mode" @@ -1778,8 +1909,12 @@ msgid "Zoom:" msgstr "Přiblížení:" #: pcsx2/gui/Panels/GSWindowPanel.cpp:196 -msgid "Invalid window dimensions specified: Size cannot contain non-numeric digits! >_<" -msgstr "Zadány neplatné rozměry okna: Velikost nemůže obsahovat nečíselné číslice! >_<" +msgid "" +"Invalid window dimensions specified: Size cannot contain non-numeric digits! " +">_<" +msgstr "" +"Zadány neplatné rozměry okna: Velikost nemůže obsahovat nečíselné číslice! " +">_<" #: pcsx2/gui/Panels/GameDatabasePanel.cpp:334 msgid "Search" @@ -1808,7 +1943,8 @@ msgstr "" #: pcsx2/gui/Panels/GameFixesPanel.cpp:42 msgid "VU Clip Flag Hack - For Persona games (SuperVU recompiler only!)" -msgstr "Hack Příznaku Sevření VJ - Pro hry Persona (pouze rekompilátor superVJ)" +msgstr "" +"Hack Příznaku Sevření VJ - Pro hry Persona (pouze rekompilátor superVJ)" #: pcsx2/gui/Panels/GameFixesPanel.cpp:46 msgid "FPU Compare Hack - For Digimon Rumble Arena 2." @@ -1835,12 +1971,17 @@ msgid "EE timing hack - Multi purpose hack. Try if all else fails." msgstr "Hack časování EE - Víceúčelový hack. Zkuste, pokud vše ostatní selže." #: pcsx2/gui/Panels/GameFixesPanel.cpp:75 -msgid "Skip MPEG hack - Skips videos/FMVs in games to avoid game hanging/freezes." -msgstr "Hack přeskočení MPEG - Přeskočí videa/FMV v hrách k zabránění zaseknutí/zamrznutí her." +msgid "" +"Skip MPEG hack - Skips videos/FMVs in games to avoid game hanging/freezes." +msgstr "" +"Hack přeskočení MPEG - Přeskočí videa/FMV v hrách k zabránění zaseknutí/" +"zamrznutí her." #: pcsx2/gui/Panels/GameFixesPanel.cpp:79 msgid "OPH Flag hack - Try if your game freezes showing the same frame." -msgstr "Hack Příznaku OPH - Zkuste, pokud se Vaše hra zasekne a zobrazuje stejný snímek." +msgstr "" +"Hack Příznaku OPH - Zkuste, pokud se Vaše hra zasekne a zobrazuje stejný " +"snímek." #: pcsx2/gui/Panels/GameFixesPanel.cpp:88 msgid "Ignore DMAC writes when it is busy." @@ -1863,20 +2004,31 @@ msgid "Enable manual game fixes [Not recommended]" msgstr "Povolit ruční záplaty her [Nedoporučeno]" #: pcsx2/gui/Panels/GameFixesPanel.cpp:127 -msgid "The safest way to make sure that all game fixes are completely disabled." -msgstr "Nejbezpečnější způsob, jak se ujistit, že všechny záplaty her jsou úplně vypnuté." +msgid "" +"The safest way to make sure that all game fixes are completely disabled." +msgstr "" +"Nejbezpečnější způsob, jak se ujistit, že všechny záplaty her jsou úplně " +"vypnuté." #: pcsx2/gui/Panels/LogOptionsPanels.cpp:249 msgid "Enable Trace Logging" msgstr "Povolit Záznam Sledování" #: pcsx2/gui/Panels/LogOptionsPanels.cpp:250 -msgid "Trace logs are all written to emulog.txt. Toggle trace logging at any time using F10." -msgstr "Záznamy sledování jsou všechny zapisovány do emulog.txt. Přepnout záznam sledování můžete kdykoli použitím F10." +msgid "" +"Trace logs are all written to emulog.txt. Toggle trace logging at any time " +"using F10." +msgstr "" +"Záznamy sledování jsou všechny zapisovány do emulog.txt. Přepnout záznam " +"sledování můžete kdykoli použitím F10." #: pcsx2/gui/Panels/LogOptionsPanels.cpp:251 -msgid "Warning: Enabling trace logs is typically very slow, and is a leading cause of 'What happened to my FPS?' problems. :)" -msgstr "Varování: Zapnutí sledování záznamu je obyčejně velmi pomalé, a je to hlavní důvod v problémech s 'Co se stalo s mými SZS?'. :)" +msgid "" +"Warning: Enabling trace logs is typically very slow, and is a leading cause " +"of 'What happened to my FPS?' problems. :)" +msgstr "" +"Varování: Zapnutí sledování záznamu je obyčejně velmi pomalé, a je to hlavní " +"důvod v problémech s 'Co se stalo s mými SZS?'. :)" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:151 msgid "Select folder with PS2 memory cards" @@ -1936,7 +2088,8 @@ msgstr "Smazat" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:545 msgid "Permanently delete this memory card from disk (all contents are lost)" -msgstr "Natrvalo smazat tuto paměťovou kartu z disku (veškerý obsah bude ztracen)" +msgstr "" +"Natrvalo smazat tuto paměťovou kartu z disku (veškerý obsah bude ztracen)" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:547 msgid "Create a new memory card and assign it to this Port." @@ -2113,8 +2266,12 @@ msgid "Custom folder:" msgstr "Vlastní adresář:" #: pcsx2/gui/Panels/MiscPanelStuff.cpp:57 -msgid "This setting may require administration privileges from your operating system, depending on how your system is configured." -msgstr "Toto nastavení může vyžadovat administrátorské výsady od Vašeho operačního systému, v závislosti na tom, jak je Váš systém nastaven." +msgid "" +"This setting may require administration privileges from your operating " +"system, depending on how your system is configured." +msgstr "" +"Toto nastavení může vyžadovat administrátorské výsady od Vašeho operačního " +"systému, v závislosti na tom, jak je Váš systém nastaven." #: pcsx2/gui/Panels/MiscPanelStuff.cpp:66 #, c-format @@ -2183,7 +2340,9 @@ msgstr "Nastavit..." #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:379 msgid "Click the Browse button to select a different folder for PCSX2 plugins." -msgstr "Klikněte na tlačítko Procházet k vybrání jiného adresáře pro zásuvné moduly PCSX2." +msgstr "" +"Klikněte na tlačítko Procházet k vybrání jiného adresáře pro zásuvné moduly " +"PCSX2." #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:481 #, c-format @@ -2212,12 +2371,19 @@ msgid "Enable speedhacks" msgstr "Povolit hacky rychlosti" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:102 -msgid "A safe and easy way to make sure that all speedhacks are completely disabled." -msgstr "Bezpečný a jednoduchý způsob, jak se ujistit, že všechny hacky rychlosti jsou úplně zakázané." +msgid "" +"A safe and easy way to make sure that all speedhacks are completely disabled." +msgstr "" +"Bezpečný a jednoduchý způsob, jak se ujistit, že všechny hacky rychlosti " +"jsou úplně zakázané." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:111 -msgid "Resets all speedhack options to their defaults, which consequently turns them all OFF." -msgstr "Resetuje všechny volby hacků rychlosti na jejich výchozí hodnoty, což následně všechny VYPNE." +msgid "" +"Resets all speedhack options to their defaults, which consequently turns " +"them all OFF." +msgstr "" +"Resetuje všechny volby hacků rychlosti na jejich výchozí hodnoty, což " +"následně všechny VYPNE." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:120 msgid "EE Cyclerate [Not Recommended]" @@ -2236,50 +2402,56 @@ msgid "mVU Flag Hack" msgstr "Hack Příznaku mVJ" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:164 -msgid "Good Speedup and High Compatibility; may cause bad graphics... [Recommended]" -msgstr "Dobré Zrychlení a Vysoká Kompatibilita; může způsobit grafické chyby... [Doporučeno]" +msgid "" +"Good Speedup and High Compatibility; may cause bad graphics... [Recommended]" +msgstr "" +"Dobré Zrychlení a Vysoká Kompatibilita; může způsobit grafické chyby... " +"[Doporučeno]" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:166 -msgid "mVU Block Hack" -msgstr "Hack Bloku mVJ" - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 -msgid "Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." -msgstr "Dobré Zrychlení a Vysoká Kompatibilita; může způsobit grafické chyby, SŠP, atd..." - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "MTVU (Multi-Threaded microVU1)" msgstr "VVVJ (Vícevláknová mikroVJ1)" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:170 -msgid "Good Speedup and High Compatibility; may cause hanging... [Recommended if 3+ cores]" -msgstr "Dobré Zrychlení a Vysoká Kompatibilita; může způsobit zaseknutí... [Doporučeno při 3+ více jádrech]" +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 +msgid "" +"Good Speedup and High Compatibility; may cause hanging... [Recommended if 3+ " +"cores]" +msgstr "" +"Dobré Zrychlení a Vysoká Kompatibilita; může způsobit zaseknutí... " +"[Doporučeno při 3+ více jádrech]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:183 msgid "Other Hacks" msgstr "Jiné Hacky" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:193 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:185 msgid "Enable INTC Spin Detection" msgstr "Povolit Zjišťování Otáčení KPŘE" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:194 -msgid "Huge speedup for some games, with almost no compatibility side effects. [Recommended]" -msgstr "Velké zrychlení v některých hrách bez jakýchkoliv vedlejších účinků na kompatibilitu. [Doporučeno]" +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:186 +msgid "" +"Huge speedup for some games, with almost no compatibility side effects. " +"[Recommended]" +msgstr "" +"Velké zrychlení v některých hrách bez jakýchkoliv vedlejších účinků na " +"kompatibilitu. [Doporučeno]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:196 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:188 msgid "Enable Wait Loop Detection" msgstr "Povolit Zjištění Čekací Smyčky" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:197 -msgid "Moderate speedup for some games, with no known side effects. [Recommended]" -msgstr "Mírné zrychlení v některých hrách bez žádných známých vedlejších účinků. [Doporučeno]" +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:189 +msgid "" +"Moderate speedup for some games, with no known side effects. [Recommended]" +msgstr "" +"Mírné zrychlení v některých hrách bez žádných známých vedlejších účinků. " +"[Doporučeno]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:199 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 msgid "Enable fast CDVD" msgstr "Zapnout rychlé CDVD" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:192 msgid "Fast disc access, less loading times. [Not Recommended]" msgstr "Rychlý přístup k disku, menší doba nahrávání. [Nedoporučeno]" @@ -2292,8 +2464,12 @@ msgid "Select folder containing PCSX2 visual themes" msgstr "Vyberte adresář obsahující grafické vzhledy PCSX2" #: pcsx2/gui/Panels/ThemeSelectorPanel.cpp:45 -msgid "Click the Browse button to select a different folder containing PCSX2 visual themes." -msgstr "Klikněte na tlačítko Procházet pro vybrání jiného adresáře obsahující grafické vzhledy PCSX2." +msgid "" +"Click the Browse button to select a different folder containing PCSX2 visual " +"themes." +msgstr "" +"Klikněte na tlačítko Procházet pro vybrání jiného adresáře obsahující " +"grafické vzhledy PCSX2." #: pcsx2/gui/Panels/ThemeSelectorPanel.cpp:49 msgid "Select a visual theme:" @@ -2304,8 +2480,11 @@ msgid "Disable Framelimiting" msgstr "Vypnout Omezování Snímků" #: pcsx2/gui/Panels/VideoPanel.cpp:35 -msgid "Useful for running benchmarks. Toggle this option in-game by pressing F4." -msgstr "Užitečné pro spuštění zatěžovacích testů. Tuto možnost přepínáte ve hře stiskem F4." +msgid "" +"Useful for running benchmarks. Toggle this option in-game by pressing F4." +msgstr "" +"Užitečné pro spuštění zatěžovacích testů. Tuto možnost přepínáte ve hře " +"stiskem F4." #: pcsx2/gui/Panels/VideoPanel.cpp:61 msgid "Base Framerate Adjust:" @@ -2323,8 +2502,7 @@ msgstr "Turbo Úprava:" msgid "NTSC Framerate:" msgstr "Frekvence Snímků NTSC:" -#: pcsx2/gui/Panels/VideoPanel.cpp:91 -#: pcsx2/gui/Panels/VideoPanel.cpp:97 +#: pcsx2/gui/Panels/VideoPanel.cpp:91 pcsx2/gui/Panels/VideoPanel.cpp:97 msgid "FPS" msgstr "SZS" @@ -2332,94 +2510,132 @@ msgstr "SZS" msgid "PAL Framerate:" msgstr "Frekvence Snímků PAL:" -#: pcsx2/gui/Panels/VideoPanel.cpp:162 -msgid "Error while parsing either NTSC or PAL framerate settings. Settings must be valid floating point numerics." -msgstr "Chyba při analýze nastavení snímkovací frekvence NTSC nebo PAL. Nastavení musí být platná čísla s plovoucí čárkou." +#: pcsx2/gui/Panels/VideoPanel.cpp:166 +msgid "" +"Error while parsing either NTSC or PAL framerate settings. Settings must be " +"valid floating point numerics." +msgstr "" +"Chyba při analýze nastavení snímkovací frekvence NTSC nebo PAL. Nastavení " +"musí být platná čísla s plovoucí čárkou." -#: pcsx2/gui/Panels/VideoPanel.cpp:180 +#: pcsx2/gui/Panels/VideoPanel.cpp:184 msgid "Disabled [default]" msgstr "Vypnuto [výchozí]" -#: pcsx2/gui/Panels/VideoPanel.cpp:184 +#: pcsx2/gui/Panels/VideoPanel.cpp:188 msgid "Skip when on Turbo only (TAB to enable)" msgstr "Přeskočit pouze když je použito Turbo (TAB pro zapnutí)" -#: pcsx2/gui/Panels/VideoPanel.cpp:188 +#: pcsx2/gui/Panels/VideoPanel.cpp:192 msgid "Constant skipping" msgstr "Neustálé přeskakování" -#: pcsx2/gui/Panels/VideoPanel.cpp:190 -msgid "Normal and Turbo limit rates skip frames. Slow motion mode will still disable frameskipping." -msgstr "Normální a Turbo omezují množství přeskočených snímků. Režim zpomaleného pohybu přesto vypne přeskakování snímků." +#: pcsx2/gui/Panels/VideoPanel.cpp:194 +msgid "" +"Normal and Turbo limit rates skip frames. Slow motion mode will still " +"disable frameskipping." +msgstr "" +"Normální a Turbo omezují množství přeskočených snímků. Režim zpomaleného " +"pohybu přesto vypne přeskakování snímků." -#: pcsx2/gui/Panels/VideoPanel.cpp:213 +#: pcsx2/gui/Panels/VideoPanel.cpp:217 msgid "Frames to Draw" msgstr "Snímky na Vykreslení" -#: pcsx2/gui/Panels/VideoPanel.cpp:218 +#: pcsx2/gui/Panels/VideoPanel.cpp:222 msgid "Frames to Skip" msgstr "Snímky na Přeskočení" -#: pcsx2/gui/Panels/VideoPanel.cpp:294 +#: pcsx2/gui/Panels/VideoPanel.cpp:298 msgid "Use Synchronized MTGS" msgstr "Použít Synchronizovaný VVGS" -#: pcsx2/gui/Panels/VideoPanel.cpp:295 -msgid "For troubleshooting potential bugs in the MTGS only, as it is potentially very slow." -msgstr "Pouze pro řešení možných chyb v VVGS, protože je toto potenciálně velmi pomalé." +#: pcsx2/gui/Panels/VideoPanel.cpp:299 +msgid "" +"For troubleshooting potential bugs in the MTGS only, as it is potentially " +"very slow." +msgstr "" +"Pouze pro řešení možných chyb v VVGS, protože je toto potenciálně velmi " +"pomalé." -#: pcsx2/gui/Panels/VideoPanel.cpp:298 +#: pcsx2/gui/Panels/VideoPanel.cpp:302 msgid "Disable all GS output" msgstr "Zakázat všechen výstup GS" -#: pcsx2/gui/Panels/VideoPanel.cpp:299 -msgid "Completely disables all GS plugin activity; ideal for benchmarking EEcore components." -msgstr "Úplně zakáže jakoukoli aktivitu zásuvného modulu GS; ideální pro měření výkonu hlavních součástí EE." +#: pcsx2/gui/Panels/VideoPanel.cpp:303 +msgid "" +"Completely disables all GS plugin activity; ideal for benchmarking EEcore " +"components." +msgstr "" +"Úplně zakáže jakoukoli aktivitu zásuvného modulu GS; ideální pro měření " +"výkonu hlavních součástí EE." -#: pcsx2/gui/Panels/VideoPanel.cpp:316 +#: pcsx2/gui/Panels/VideoPanel.cpp:320 msgid "Frame Skipping" msgstr "Přeskakování Snímků" -#: pcsx2/gui/Panels/VideoPanel.cpp:319 +#: pcsx2/gui/Panels/VideoPanel.cpp:323 msgid "Framelimiter" msgstr "Omezovač Snímků" #: pcsx2/gui/SysState.cpp:283 -msgid "Cannot load this savestate. The state is from an incompatible edition of PCSX2 that is either newer than this version, or is no longer supported." -msgstr "Nelze načíst tento uložený stav. Stav je z nekompatibilní edice PCSX2, která je buď novější než tato, nebo už není podporována." +msgid "" +"Cannot load this savestate. The state is from an incompatible edition of " +"PCSX2 that is either newer than this version, or is no longer supported." +msgstr "" +"Nelze načíst tento uložený stav. Stav je z nekompatibilní edice PCSX2, která " +"je buď novější než tato, nebo už není podporována." #: pcsx2/gui/SysState.cpp:290 -msgid "Cannot load this savestate. The state is an unsupported version, likely created by a newer edition of PCSX2." -msgstr "Nelze načíst tento uložený stav. Stav je z nepodporované verze, pravděpodobně vytvořen novou edicí PCSX2." +msgid "" +"Cannot load this savestate. The state is an unsupported version, likely " +"created by a newer edition of PCSX2." +msgstr "" +"Nelze načíst tento uložený stav. Stav je z nepodporované verze, " +"pravděpodobně vytvořen novou edicí PCSX2." #: pcsx2/gui/SysState.cpp:326 msgid "There is no active virtual machine state to download or save." msgstr "Neexistuje žádný stav virtuálního stroje k načtení nebo uložení." #: pcsx2/gui/SysState.cpp:520 -msgid "This savestate cannot be loaded because it is not a valid gzip archive. It may have been created by an older unsupported version of PCSX2, or it may be corrupted." -msgstr "Uložený stav nemůže být nahrán, protože to není platný archiv gzip. Mohl být vytvořen starší nepodporovanou verzí PCSX2 nebo může být poškozen." +msgid "" +"This savestate cannot be loaded because it is not a valid gzip archive. It " +"may have been created by an older unsupported version of PCSX2, or it may be " +"corrupted." +msgstr "" +"Uložený stav nemůže být nahrán, protože to není platný archiv gzip. Mohl být " +"vytvořen starší nepodporovanou verzí PCSX2 nebo může být poškozen." #: pcsx2/gui/SysState.cpp:579 msgid "This file is not a valid PCSX2 savestate. See the logfile for details." -msgstr "Tento soubor není platný uložený stav PCSX2. Podívejte se na soubor se záznamem pro podrobnosti." +msgstr "" +"Tento soubor není platný uložený stav PCSX2. Podívejte se na soubor se " +"záznamem pro podrobnosti." #: pcsx2/gui/SysState.cpp:598 -msgid "This savestate cannot be loaded due to missing critical components. See the log file for details." -msgstr "Uložený stav nemůže být nahrán kvůli chybějícím důležitým součástem. Prohlédněte si záznam pro podrobnosti." +msgid "" +"This savestate cannot be loaded due to missing critical components. See the " +"log file for details." +msgstr "" +"Uložený stav nemůže být nahrán kvůli chybějícím důležitým součástem. " +"Prohlédněte si záznam pro podrobnosti." #: pcsx2/gui/i18n.cpp:63 msgid " (default)" msgstr " (výchozí)" -#: pcsx2/ps2/BiosTools.cpp:83 -#: pcsx2/ps2/BiosTools.cpp:151 +#: pcsx2/ps2/BiosTools.cpp:83 pcsx2/ps2/BiosTools.cpp:151 msgid "The selected BIOS file is not a valid PS2 BIOS. Please re-configure." msgstr "Vybraný soubor BIOSu není platný BIOS PS2. Prosím nastavte znovu." #: pcsx2/ps2/BiosTools.cpp:244 -msgid "The PS2 BIOS could not be loaded. The BIOS has not been configured, or the configuration has been corrupted. Please re-configure." -msgstr "BIOS PS2 nemohl nýt načten. BIOS nebyl nastaven nebo bylo nastavení poškozeno. Nastavte prosím znovu." +msgid "" +"The PS2 BIOS could not be loaded. The BIOS has not been configured, or the " +"configuration has been corrupted. Please re-configure." +msgstr "" +"BIOS PS2 nemohl nýt načten. BIOS nebyl nastaven nebo bylo nastavení " +"poškozeno. Nastavte prosím znovu." #: pcsx2/ps2/BiosTools.cpp:251 msgid "The configured BIOS file does not exist. Please re-configure." @@ -2427,13 +2643,30 @@ msgstr "Nastavený soubor BIOSu neexistuje. Prosím nastavte znovu." #: pcsx2/x86/ix86-32/iR5900-32.cpp:578 #, c-format -msgid "%s Extensions not found. The R5900-32 recompiler requires a host CPU with MMX, SSE, and SSE2 extensions." -msgstr "Rozšíření %s nenalezeno. Rekompilátor R5900-32 potřebuje hostitelský procesor s rozšířením MMX, SSE, a SSE2." +msgid "" +"%s Extensions not found. The R5900-32 recompiler requires a host CPU with " +"MMX, SSE, and SSE2 extensions." +msgstr "" +"Rozšíření %s nenalezeno. Rekompilátor R5900-32 potřebuje hostitelský " +"procesor s rozšířením MMX, SSE, a SSE2." #: pcsx2/x86/microVU.cpp:28 #, c-format -msgid "%s Extensions not found. microVU requires a host CPU with MMX, SSE, and SSE2 extensions." -msgstr "Rozšíření %s nenalezeno. mikroVJ vyžaduje, aby hostitelský procesor měl rozšíření MMX, SSE, a SSE2." +msgid "" +"%s Extensions not found. microVU requires a host CPU with MMX, SSE, and " +"SSE2 extensions." +msgstr "" +"Rozšíření %s nenalezeno. mikroVJ vyžaduje, aby hostitelský procesor měl " +"rozšíření MMX, SSE, a SSE2." + +#~ msgid "mVU Block Hack" +#~ msgstr "Hack Bloku mVJ" + +#~ msgid "" +#~ "Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." +#~ msgstr "" +#~ "Dobré Zrychlení a Vysoká Kompatibilita; může způsobit grafické chyby, " +#~ "SŠP, atd..." #~ msgid "ISO mounting failed: PCSX2 is unable to identify the ISO image type." #~ msgstr "Připojení ISO selhalo: PCSX2 nedokáže rozpoznat typ obrazu ISO." diff --git a/locales/de_DE/pcsx2_Iconized.po b/locales/de_DE/pcsx2_Iconized.po index 415638139..dc474314c 100644 --- a/locales/de_DE/pcsx2_Iconized.po +++ b/locales/de_DE/pcsx2_Iconized.po @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-09-28 20:27+0200\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: 2011-04-09 01:11+0100\n" "Last-Translator: \n" "Language-Team: PCSX2\n" @@ -24,7 +24,7 @@ msgstr "" "Es steht nicht genügend virtueller Speicher zur Verfügung bzw. der Speicher " "wird von anderen Programmen / DLLs belegt." -#: pcsx2/CDVD/CDVD.cpp:385 +#: pcsx2/CDVD/CDVD.cpp:390 msgid "!Notice:PsxDisc" msgstr "PlayStation 1 (PSX) Spiele werden von PCSX2 noch nicht unterstützt!" @@ -361,28 +361,24 @@ msgstr "" "\"Stiehlt\" der PS2 CPU einige Zyklen bei jeder VU Programmausführung. " "Geschwindigkeitsgewinn bei reduzierter Kompatibilität." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:172 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "!ContextTip:Speedhacks:vuFlagHack" msgstr "Lässt einige VU Statusflags aus. Sicher." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:177 -msgid "!ContextTip:Speedhacks:vuBlockHack" -msgstr "Kann die Geschwindigkeit leicht erhöhen. In FFX kontraproduktiv!" - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:182 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:174 #, fuzzy msgid "!ContextTip:Speedhacks:vuThread" msgstr "Funktioniert nicht mit Gran Turismo 4 oder Tekken 5." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:203 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:195 msgid "!ContextTip:Speedhacks:INTC" msgstr "Kann gefahrlos aktiviert werden." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:208 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 msgid "!ContextTip:Speedhacks:BIFC0" msgstr "Kann gefahrlos aktiviert werden." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:215 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:207 msgid "!ContextTip:Speedhacks:fastCDVD" msgstr "" "Einige Spiele erwarten ein standardkonformes (langsam lesendes) DVD " @@ -394,17 +390,17 @@ msgstr "" "Deaktiviert den Framelimiter. Das Spiel läuft so schnell wie es dein Rechner " "ermöglicht." -#: pcsx2/gui/Panels/VideoPanel.cpp:223 +#: pcsx2/gui/Panels/VideoPanel.cpp:227 msgid "!Panel:Frameskip:Heading" msgstr "" "Aufgrund des spezifischen Designs der PS2 ist ein akkurates Frameskipping " "nicht möglich. Versuche die Werte anzupassen oder benutze Speedhacks." -#: pcsx2/gui/Panels/VideoPanel.cpp:302 +#: pcsx2/gui/Panels/VideoPanel.cpp:306 msgid "!ContextTip:GS:SyncMTGS" msgstr "Nur für das Debugging aktivieren. Sehr langsam." -#: pcsx2/gui/Panels/VideoPanel.cpp:306 +#: pcsx2/gui/Panels/VideoPanel.cpp:310 msgid "!ContextTip:GS:DisableOutput" msgstr "" "Entfernt störende Faktoren von der Grafikkarte oder Treiberproblemen. Nur " @@ -422,6 +418,9 @@ msgstr "" "Der SuperVU Recompiler konnte nicht genügend virtuellen Speicher allokieren. " "Versuche es mit microVU!" +#~ msgid "!ContextTip:Speedhacks:vuBlockHack" +#~ msgstr "Kann die Geschwindigkeit leicht erhöhen. In FFX kontraproduktiv!" + #~ msgid "No reason given." #~ msgstr "Kein Grund angegeben." diff --git a/locales/de_DE/pcsx2_Main.po b/locales/de_DE/pcsx2_Main.po index 0952644c6..6b224a343 100644 --- a/locales/de_DE/pcsx2_Main.po +++ b/locales/de_DE/pcsx2_Main.po @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-09-28 20:27+0200\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: 2011-04-09 01:44+0100\n" "Last-Translator: \n" "Language-Team: PCSX2\n" @@ -185,7 +185,7 @@ msgstr "Internes Memory Card Plugin konnte nicht Initialisiert werden." msgid "Unloaded Plugin" msgstr "Plugin entladen" -#: pcsx2/SaveState.cpp:339 +#: pcsx2/SaveState.cpp:342 msgid "Cannot load savestate. It is of an unknown or unsupported version." msgstr "" "Kann Savestate nicht laden. Er ist von einer unbekannten, nicht " @@ -340,31 +340,31 @@ msgstr "" "Der Savestate wurde nicht korrekt gespeichert. Die temporäre Datei konnte " "zwar erstellt, aber nicht an den finalen Platz kopiert werden." -#: pcsx2/gui/AppConfig.cpp:837 +#: pcsx2/gui/AppConfig.cpp:842 msgid "Safest" msgstr "Sicher" -#: pcsx2/gui/AppConfig.cpp:838 +#: pcsx2/gui/AppConfig.cpp:843 msgid "Safe (faster)" msgstr "Sicher (schneller)" -#: pcsx2/gui/AppConfig.cpp:839 +#: pcsx2/gui/AppConfig.cpp:844 msgid "Balanced" msgstr "Ausbalanciert" -#: pcsx2/gui/AppConfig.cpp:840 +#: pcsx2/gui/AppConfig.cpp:845 msgid "Aggressive" msgstr "Aggressiv" -#: pcsx2/gui/AppConfig.cpp:841 +#: pcsx2/gui/AppConfig.cpp:846 msgid "Aggressive plus" msgstr "Aggressiv Plus" -#: pcsx2/gui/AppConfig.cpp:842 +#: pcsx2/gui/AppConfig.cpp:847 msgid "Mostly Harmful" msgstr "Maximum" -#: pcsx2/gui/AppConfig.cpp:999 pcsx2/gui/AppConfig.cpp:1005 +#: pcsx2/gui/AppConfig.cpp:1007 pcsx2/gui/AppConfig.cpp:1013 msgid "Failed to overwrite existing settings file; permission was denied." msgstr "" "Konnte existierende Konfigurationsdatei nicht überschreiben. Zugriff " @@ -2374,35 +2374,25 @@ msgid "" msgstr "Guter FPS Anstieg, gute Kompatibilität [empfohlen]" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:166 -msgid "mVU Block Hack" -msgstr "mVU Block Hack" - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 -#, fuzzy -msgid "" -"Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." -msgstr "Guter FPS Anstieg, gute Kompatibilität [empfohlen]" - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "MTVU (Multi-Threaded microVU1)" msgstr "" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:170 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 #, fuzzy msgid "" "Good Speedup and High Compatibility; may cause hanging... [Recommended if 3+ " "cores]" msgstr "Guter FPS Anstieg, gute Kompatibilität [empfohlen]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:183 msgid "Other Hacks" msgstr "Andere Hacks" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:193 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:185 msgid "Enable INTC Spin Detection" msgstr "Aktiviere INTC Warteschleifenerkennung" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:194 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:186 msgid "" "Huge speedup for some games, with almost no compatibility side effects. " "[Recommended]" @@ -2410,20 +2400,20 @@ msgstr "" "Gute Geschwindigkeitsverbesserung, fast keine " "Kompatibilitätseinschränkungen. [empfohlen]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:196 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:188 msgid "Enable Wait Loop Detection" msgstr "Aktiviere erkennen von Warteschleifen" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:197 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:189 msgid "" "Moderate speedup for some games, with no known side effects. [Recommended]" msgstr "Leichte Geschwindigkeitsverbesserung in einigen Spielen [empfohlen]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:199 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 msgid "Enable fast CDVD" msgstr "Aktiviere schnelles CDVD" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:192 msgid "Fast disc access, less loading times. [Not Recommended]" msgstr "Schnellerer Diskzugriff, kürzere Ladezeiten [nicht empfohlen]" @@ -2481,53 +2471,53 @@ msgstr "FPS" msgid "PAL Framerate:" msgstr "PAL Bildwiederholrate" -#: pcsx2/gui/Panels/VideoPanel.cpp:162 +#: pcsx2/gui/Panels/VideoPanel.cpp:166 msgid "" "Error while parsing either NTSC or PAL framerate settings. Settings must be " "valid floating point numerics." msgstr "Fehler beim Einlesen der NTSC oder PAL Framerateeinstellungen." -#: pcsx2/gui/Panels/VideoPanel.cpp:180 +#: pcsx2/gui/Panels/VideoPanel.cpp:184 msgid "Disabled [default]" msgstr "Deaktiviert [standard]" -#: pcsx2/gui/Panels/VideoPanel.cpp:184 +#: pcsx2/gui/Panels/VideoPanel.cpp:188 msgid "Skip when on Turbo only (TAB to enable)" msgstr "Skipping nur im Turbomodus" -#: pcsx2/gui/Panels/VideoPanel.cpp:188 +#: pcsx2/gui/Panels/VideoPanel.cpp:192 msgid "Constant skipping" msgstr "Konstantes Skipping" -#: pcsx2/gui/Panels/VideoPanel.cpp:190 +#: pcsx2/gui/Panels/VideoPanel.cpp:194 msgid "" "Normal and Turbo limit rates skip frames. Slow motion mode will still " "disable frameskipping." msgstr "Normal und Turbo werden Bilder auslassen, Slow motion nicht." -#: pcsx2/gui/Panels/VideoPanel.cpp:213 +#: pcsx2/gui/Panels/VideoPanel.cpp:217 msgid "Frames to Draw" msgstr "Bilder darstellen" -#: pcsx2/gui/Panels/VideoPanel.cpp:218 +#: pcsx2/gui/Panels/VideoPanel.cpp:222 msgid "Frames to Skip" msgstr "Bilder auslassen" -#: pcsx2/gui/Panels/VideoPanel.cpp:294 +#: pcsx2/gui/Panels/VideoPanel.cpp:298 msgid "Use Synchronized MTGS" msgstr "Benutze synchrones MTGS" -#: pcsx2/gui/Panels/VideoPanel.cpp:295 +#: pcsx2/gui/Panels/VideoPanel.cpp:299 msgid "" "For troubleshooting potential bugs in the MTGS only, as it is potentially " "very slow." msgstr "Um eventualle Fehler im MTGS Thread zu debuggen. Sehr langsam!" -#: pcsx2/gui/Panels/VideoPanel.cpp:298 +#: pcsx2/gui/Panels/VideoPanel.cpp:302 msgid "Disable all GS output" msgstr "Deaktiviere GS Ausgabe" -#: pcsx2/gui/Panels/VideoPanel.cpp:299 +#: pcsx2/gui/Panels/VideoPanel.cpp:303 msgid "" "Completely disables all GS plugin activity; ideal for benchmarking EEcore " "components." @@ -2535,11 +2525,11 @@ msgstr "" "Deaktiviert alle GS Plugin Aktivitäten. Ideal um den Emulatorkern zu " "Benchmarken." -#: pcsx2/gui/Panels/VideoPanel.cpp:316 +#: pcsx2/gui/Panels/VideoPanel.cpp:320 msgid "Frame Skipping" msgstr "Bilder auslassen (skipping)" -#: pcsx2/gui/Panels/VideoPanel.cpp:319 +#: pcsx2/gui/Panels/VideoPanel.cpp:323 msgid "Framelimiter" msgstr "FPS Limitierung" @@ -2626,6 +2616,14 @@ msgstr "" "%s Erweiterungen nicht gefunden. MicroVU benötigt einen Prozessor mit MMX, " "SSE und SSE2 Erweiterungen." +#~ msgid "mVU Block Hack" +#~ msgstr "mVU Block Hack" + +#, fuzzy +#~ msgid "" +#~ "Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." +#~ msgstr "Guter FPS Anstieg, gute Kompatibilität [empfohlen]" + #~ msgid "!ContextTip:ChangingNTFS" #~ msgstr "" #~ "Die NTFS Komprimierung kann jederzeit via Windows Explorer geändert " diff --git a/locales/es_ES/pcsx2_Iconized.po b/locales/es_ES/pcsx2_Iconized.po index fe734f293..f19f2c716 100644 --- a/locales/es_ES/pcsx2_Iconized.po +++ b/locales/es_ES/pcsx2_Iconized.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.7\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-10-05 20:13+0200\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: 2011-09-28 21:51+0100\n" "Last-Translator: Víctor González \n" "Language-Team: \n" @@ -31,7 +31,7 @@ msgstr "" "memoria virtual necesarias ya las han reservado otros procesos, servicios o " "DLLs." -#: pcsx2/CDVD/CDVD.cpp:385 +#: pcsx2/CDVD/CDVD.cpp:390 msgid "!Notice:PsxDisc" msgstr "" "PCSX2 no admite discos de juego de PlayStation 1. Si quieres emular juegos " @@ -496,7 +496,7 @@ msgstr "" "EmotionEngine. Un valor alto aumenta el número de ciclos robados del EE a " "cada microprograma del VU que utiliza el juego." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:172 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "!ContextTip:Speedhacks:vuFlagHack" msgstr "" "Actualiza las etiquetas de estado sólo en los bloques que podrán leerse, en " @@ -504,15 +504,7 @@ msgstr "" "Generalmente es la opción más segura, y Super VU ya hace algo parecido de " "forma predeterminada." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:177 -msgid "!ContextTip:Speedhacks:vuBlockHack" -msgstr "" -"Asume que en lo profundo de los bloques futuros no necesitarán estos datos " -"de instancia antiguos.\n" -"Debería ser una opción muy segura. No se sabe si dañará la emulación de " -"algún juego..." - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:182 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:174 msgid "!ContextTip:Speedhacks:vuThread" msgstr "" "Ejecuta VU1 en un hilo dedicado (sólo microVU1). Suele aumentar la velocidad " @@ -522,7 +514,7 @@ msgstr "" "En el caso de los juegos limitados por GS, podría ralentizarlos (sobre todo " "en CPUs de doble núcleo)." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:203 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:195 msgid "!ContextTip:Speedhacks:INTC" msgstr "" "Este arreglo funciona mejor en juegos que utilizan el registro de estado " @@ -530,7 +522,7 @@ msgstr "" "RPGs que no son 3D. Los juegos que no utilizan este método de sincronía " "vertical no recibirán aumentos de velocidad con este arreglo." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:208 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 msgid "!ContextTip:Speedhacks:BIFC0" msgstr "" "Al apuntar directamente al bucle de espera del EE en la dirección 0x81FC0 " @@ -540,7 +532,7 @@ msgstr "" "bucles, aumentamos el tiempo del siguiente evento o el final del espacio de " "tiempo del procesador, en función de lo que llegue primero." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:215 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:207 msgid "!ContextTip:Speedhacks:fastCDVD" msgstr "" "Comprueba las listas de compatibilidad del HDLoader para saber qué juegos " @@ -553,20 +545,20 @@ msgstr "" "Observa que al desactivar la limitación de fotogramas, los modos Turbo y " "Velocidad lenta no estarán disponibles." -#: pcsx2/gui/Panels/VideoPanel.cpp:223 +#: pcsx2/gui/Panels/VideoPanel.cpp:227 msgid "!Panel:Frameskip:Heading" msgstr "" "Aviso: Debido al diseño del hardware de PS2, es imposible hacer un salto de " "fotogramas preciso.\n" "Activarlo causará serios fallos visuales en varios juegos." -#: pcsx2/gui/Panels/VideoPanel.cpp:302 +#: pcsx2/gui/Panels/VideoPanel.cpp:306 msgid "!ContextTip:GS:SyncMTGS" msgstr "" "Activa esta opción si crees que la sincronía de hilos MTGS provoca caídas o " "fallos gráficos." -#: pcsx2/gui/Panels/VideoPanel.cpp:306 +#: pcsx2/gui/Panels/VideoPanel.cpp:310 msgid "!ContextTip:GS:DisableOutput" msgstr "" "Elimina cualquier ruido de benchmark provocado por el hilo MTGS o la " @@ -591,3 +583,10 @@ msgstr "" "los rangos de memoria concretos que son necesarios, y no podrá ser " "utilizado. Este no es un error crítico, ya que el recompilador SuperVU es " "obsoleto, y deberías utilizar en su lugar microVU." + +#~ msgid "!ContextTip:Speedhacks:vuBlockHack" +#~ msgstr "" +#~ "Asume que en lo profundo de los bloques futuros no necesitarán estos " +#~ "datos de instancia antiguos.\n" +#~ "Debería ser una opción muy segura. No se sabe si dañará la emulación de " +#~ "algún juego..." diff --git a/locales/es_ES/pcsx2_Main.po b/locales/es_ES/pcsx2_Main.po index ac6e23240..082be0981 100644 --- a/locales/es_ES/pcsx2_Main.po +++ b/locales/es_ES/pcsx2_Main.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.7\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-10-05 20:13+0200\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: 2011-09-28 21:53+0100\n" "Last-Translator: Víctor González \n" "Language-Team: \n" @@ -204,7 +204,7 @@ msgstr "El plugin interno de Memory Cards no se ha iniciado." msgid "Unloaded Plugin" msgstr "Plugin no cargado" -#: pcsx2/SaveState.cpp:339 +#: pcsx2/SaveState.cpp:342 msgid "Cannot load savestate. It is of an unknown or unsupported version." msgstr "" "No se ha podido cargar el guardado rápido. Es una versión desconocida o no " @@ -386,31 +386,31 @@ msgstr "" "El guardado rápido no se guardó correctamente. El archivo temporal ha sido " "creado con éxito, pero no se pudo trasladar a su destino final." -#: pcsx2/gui/AppConfig.cpp:837 +#: pcsx2/gui/AppConfig.cpp:842 msgid "Safest" msgstr "Lo más seguro" -#: pcsx2/gui/AppConfig.cpp:838 +#: pcsx2/gui/AppConfig.cpp:843 msgid "Safe (faster)" msgstr "Seguro (más rápido)" -#: pcsx2/gui/AppConfig.cpp:839 +#: pcsx2/gui/AppConfig.cpp:844 msgid "Balanced" msgstr "Equilibrado" -#: pcsx2/gui/AppConfig.cpp:840 +#: pcsx2/gui/AppConfig.cpp:845 msgid "Aggressive" msgstr "Agresivo" -#: pcsx2/gui/AppConfig.cpp:841 +#: pcsx2/gui/AppConfig.cpp:846 msgid "Aggressive plus" msgstr "Muy agresivo" -#: pcsx2/gui/AppConfig.cpp:842 +#: pcsx2/gui/AppConfig.cpp:847 msgid "Mostly Harmful" msgstr "Muy peligroso" -#: pcsx2/gui/AppConfig.cpp:999 pcsx2/gui/AppConfig.cpp:1005 +#: pcsx2/gui/AppConfig.cpp:1007 pcsx2/gui/AppConfig.cpp:1013 msgid "Failed to overwrite existing settings file; permission was denied." msgstr "" "Error al sobrescribir el archivo de configuración ya existente, se ha " @@ -2468,21 +2468,10 @@ msgstr "" "(Recomendado)" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:166 -msgid "mVU Block Hack" -msgstr "Arreglo de bloqueo mVU" - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 -msgid "" -"Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." -msgstr "" -"Buena subida y alta compatibilidad; puede crear gráficos dañados, SPS, " -"etcétera..." - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "MTVU (Multi-Threaded microVU1)" msgstr "MTVU (microVU1 multihilos)" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:170 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 msgid "" "Good Speedup and High Compatibility; may cause hanging... [Recommended if 3+ " "cores]" @@ -2490,15 +2479,15 @@ msgstr "" "Buena subida y alta compatibilidad; puede provocar cuelgues... (Recomendado " "si tienes 3 o más núcleos de CPU)" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:183 msgid "Other Hacks" msgstr "Otros arreglos" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:193 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:185 msgid "Enable INTC Spin Detection" msgstr "Activar detección de giro INTC" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:194 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:186 msgid "" "Huge speedup for some games, with almost no compatibility side effects. " "[Recommended]" @@ -2506,22 +2495,22 @@ msgstr "" "Subida enorme de velocidad en algunos juegos, sin prácticamente ningún " "efecto secundario de compatibilidad (Recomendado)" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:196 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:188 msgid "Enable Wait Loop Detection" msgstr "Activar detección de parada de bucles" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:197 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:189 msgid "" "Moderate speedup for some games, with no known side effects. [Recommended]" msgstr "" "Subida moderada en algunos juegos, sin efectos secundarios conocidos. " "(Recomendado)" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:199 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 msgid "Enable fast CDVD" msgstr "Activar CDVD rápido" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:192 msgid "Fast disc access, less loading times. [Not Recommended]" msgstr "" "Accede al disco más rápidamente, reduciendo los tiempos de carga. (No " @@ -2582,7 +2571,7 @@ msgstr "FPS (Fotogramas por segundo)" msgid "PAL Framerate:" msgstr "Velocidad de fotogramas PAL:" -#: pcsx2/gui/Panels/VideoPanel.cpp:162 +#: pcsx2/gui/Panels/VideoPanel.cpp:166 msgid "" "Error while parsing either NTSC or PAL framerate settings. Settings must be " "valid floating point numerics." @@ -2590,19 +2579,19 @@ msgstr "" "Error al analizar la configuración de la velocidad de fotogramas PAL o " "NTSC. La configuración debe ser un valor numeral entero." -#: pcsx2/gui/Panels/VideoPanel.cpp:180 +#: pcsx2/gui/Panels/VideoPanel.cpp:184 msgid "Disabled [default]" msgstr "Desactivado [por defecto]" -#: pcsx2/gui/Panels/VideoPanel.cpp:184 +#: pcsx2/gui/Panels/VideoPanel.cpp:188 msgid "Skip when on Turbo only (TAB to enable)" msgstr "Saltar sólo con el turbo activado (Activar pulsando TAB)" -#: pcsx2/gui/Panels/VideoPanel.cpp:188 +#: pcsx2/gui/Panels/VideoPanel.cpp:192 msgid "Constant skipping" msgstr "Salto constante" -#: pcsx2/gui/Panels/VideoPanel.cpp:190 +#: pcsx2/gui/Panels/VideoPanel.cpp:194 msgid "" "Normal and Turbo limit rates skip frames. Slow motion mode will still " "disable frameskipping." @@ -2610,19 +2599,19 @@ msgstr "" "Normal y Turbo limitan la velocidad de salto de fotogramas. El modo de " "velocidad lenta desactivará el salto de fotogramas." -#: pcsx2/gui/Panels/VideoPanel.cpp:213 +#: pcsx2/gui/Panels/VideoPanel.cpp:217 msgid "Frames to Draw" msgstr "Fotogramas a mostrar" -#: pcsx2/gui/Panels/VideoPanel.cpp:218 +#: pcsx2/gui/Panels/VideoPanel.cpp:222 msgid "Frames to Skip" msgstr "Fotogramas a saltar" -#: pcsx2/gui/Panels/VideoPanel.cpp:294 +#: pcsx2/gui/Panels/VideoPanel.cpp:298 msgid "Use Synchronized MTGS" msgstr "Utilizar GS multinúcleo sincronizado" -#: pcsx2/gui/Panels/VideoPanel.cpp:295 +#: pcsx2/gui/Panels/VideoPanel.cpp:299 msgid "" "For troubleshooting potential bugs in the MTGS only, as it is potentially " "very slow." @@ -2630,11 +2619,11 @@ msgstr "" "Usar sólo para evitar posibles fallos en el MTGS; ya que probablemente " "funcione muy lento." -#: pcsx2/gui/Panels/VideoPanel.cpp:298 +#: pcsx2/gui/Panels/VideoPanel.cpp:302 msgid "Disable all GS output" msgstr "Desactivar toda la salida de GS" -#: pcsx2/gui/Panels/VideoPanel.cpp:299 +#: pcsx2/gui/Panels/VideoPanel.cpp:303 msgid "" "Completely disables all GS plugin activity; ideal for benchmarking EEcore " "components." @@ -2642,11 +2631,11 @@ msgstr "" "Desactiva por completo toda actividad del plugin GS; ideal para probar " "componentes de EEcore." -#: pcsx2/gui/Panels/VideoPanel.cpp:316 +#: pcsx2/gui/Panels/VideoPanel.cpp:320 msgid "Frame Skipping" msgstr "Saltar fotogramas" -#: pcsx2/gui/Panels/VideoPanel.cpp:319 +#: pcsx2/gui/Panels/VideoPanel.cpp:323 msgid "Framelimiter" msgstr "Limitador de fotogramas" @@ -2734,3 +2723,12 @@ msgid "" msgstr "" "Extensiones %s no encontradas. La microVU necesita de una CPU anfitriona " "con extensiones MMX, SSE y SSE2." + +#~ msgid "mVU Block Hack" +#~ msgstr "Arreglo de bloqueo mVU" + +#~ msgid "" +#~ "Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." +#~ msgstr "" +#~ "Buena subida y alta compatibilidad; puede crear gráficos dañados, SPS, " +#~ "etcétera..." diff --git a/locales/hu_HU/pcsx2_Iconized.po b/locales/hu_HU/pcsx2_Iconized.po index 0b18f2ec3..472267667 100644 --- a/locales/hu_HU/pcsx2_Iconized.po +++ b/locales/hu_HU/pcsx2_Iconized.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.8\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-09-28 20:27+0200\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: 2011-04-17 17:56+0100\n" "Last-Translator: Delirious \n" "Language-Team: Delirious \n" @@ -24,7 +24,7 @@ msgstr "" "Nincs elegendő szabad virtuális memória, vagy a szükséges virtuális memória " "kiosztás más folyamatok, szolgáltatások vagy DLL-ek számára van fenntartva." -#: pcsx2/CDVD/CDVD.cpp:385 +#: pcsx2/CDVD/CDVD.cpp:390 msgid "!Notice:PsxDisc" msgstr "" "A PlayStation játék lemezeket nem támogatja a PCSX2. Ha PSX játékokat akarsz " @@ -471,26 +471,19 @@ msgstr "" "elvesz az EmotionEngine elől. Magasabb érték növeli az EE elől elvett és a " "játék által futtatott összes mikroprogram számára átadott ciklusok számát." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:172 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "!ContextTip:Speedhacks:vuFlagHack" msgstr "" "Az állapot jelzőket csak azokon a blokkokon frissíti amelyek olvassák " "azokat. Legtöbbször ez biztonságos és a Super VU is valami hasonlót végez " "alapértelmezettként." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:177 -msgid "!ContextTip:Speedhacks:vuBlockHack" -msgstr "" -"Elfogadva, hogy a távoli jövőbeni blokkoknak nem lesz szükségük a régi " -"jelzőre utaló adatokra. Ez meglehetősen biztonságos lehet. Nem ismeretes, " -"hogy valamelyik játék kifagyását okozná..." - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:182 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:174 #, fuzzy msgid "!ContextTip:Speedhacks:vuThread" msgstr "Nem működik a Gran Turismo 4 vagy Tekken 5 esetén." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:203 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:195 msgid "!ContextTip:Speedhacks:INTC" msgstr "" "Ez a hack működik legjobban azoknál a játékoknál, amelyek használják az INTC " @@ -499,7 +492,7 @@ msgstr "" "eljárást használják a függőleges szinkronhoz csak csekély, vagy semmilyen " "gyorsulás nem észlelhető a hack használatával." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:208 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 msgid "!ContextTip:Speedhacks:BIFC0" msgstr "" "Elsődlegesen megcélozva az EE üresjárati hurkot a 0x81FC0 címzésen a " @@ -510,7 +503,7 @@ msgstr "" "előrehozhatjuk a következő eseményt vagy a processzor időszeletének végét, " "bármelyik is következik előbb." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:215 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:207 msgid "!ContextTip:Speedhacks:fastCDVD" msgstr "" "Ellenőrizd a HDLoader kompatibilitási listát a problémás játékok végett. " @@ -522,20 +515,20 @@ msgstr "" "Nem árt tudni, ha a képkocka korlátozás ki van kapcsolva, a turbó és " "lassított mód sem érhető el." -#: pcsx2/gui/Panels/VideoPanel.cpp:223 +#: pcsx2/gui/Panels/VideoPanel.cpp:227 msgid "!Panel:Frameskip:Heading" msgstr "" "Megjegyzés: A PS2 hardver összetételének köszönhetően a pontos képkocka " "kihagyás nem lehetséges. Használata számos grafikai hibát okoz néhány " "játékban." -#: pcsx2/gui/Panels/VideoPanel.cpp:302 +#: pcsx2/gui/Panels/VideoPanel.cpp:306 msgid "!ContextTip:GS:SyncMTGS" msgstr "" "Kapcsold ezt be, ha úgy gondolod az MTGS folyamatág szinkron okozza a " "fagyást vagy grafikai hibákat." -#: pcsx2/gui/Panels/VideoPanel.cpp:306 +#: pcsx2/gui/Panels/VideoPanel.cpp:310 msgid "!ContextTip:GS:DisableOutput" msgstr "" "Eltávolít bármely teszt zajt, amit az MTGS folyamatág vagy az általános GPU " @@ -561,6 +554,12 @@ msgstr "" "azt. Ez nem kritikus hiba, amióta az sVU rec elavult és bármikor használható " "helyette a microVU. :)" +#~ msgid "!ContextTip:Speedhacks:vuBlockHack" +#~ msgstr "" +#~ "Elfogadva, hogy a távoli jövőbeni blokkoknak nem lesz szükségük a régi " +#~ "jelzőre utaló adatokra. Ez meglehetősen biztonságos lehet. Nem ismeretes, " +#~ "hogy valamelyik játék kifagyását okozná..." + #~ msgid "No reason given." #~ msgstr "Nincs meghatározott ok." diff --git a/locales/hu_HU/pcsx2_Main.po b/locales/hu_HU/pcsx2_Main.po index 2906516f7..51dbca791 100644 --- a/locales/hu_HU/pcsx2_Main.po +++ b/locales/hu_HU/pcsx2_Main.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.8\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-09-28 20:27+0200\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: 2011-04-17 16:35+0100\n" "Last-Translator: Delirious \n" "Language-Team: Delirious \n" @@ -195,7 +195,7 @@ msgstr "Belső memória kártya plugin iniciálása sikertelen." msgid "Unloaded Plugin" msgstr "Betöltetlen plugin" -#: pcsx2/SaveState.cpp:339 +#: pcsx2/SaveState.cpp:342 msgid "Cannot load savestate. It is of an unknown or unsupported version." msgstr "" "A mentett állás nem tölthető be. Ez egy ismeretlen vagy nem támogatott " @@ -350,31 +350,31 @@ msgstr "" "A mentett állás nem megfelelően van elmentve. Az ideiglenes fájl sikeresen " "létre lett hozva, de nem került át a végső helyére." -#: pcsx2/gui/AppConfig.cpp:837 +#: pcsx2/gui/AppConfig.cpp:842 msgid "Safest" msgstr "Legbiztonságosabb" -#: pcsx2/gui/AppConfig.cpp:838 +#: pcsx2/gui/AppConfig.cpp:843 msgid "Safe (faster)" msgstr "Biztonságos (gyorsabb)" -#: pcsx2/gui/AppConfig.cpp:839 +#: pcsx2/gui/AppConfig.cpp:844 msgid "Balanced" msgstr "Kiegyensúlyozott" -#: pcsx2/gui/AppConfig.cpp:840 +#: pcsx2/gui/AppConfig.cpp:845 msgid "Aggressive" msgstr "Agresszív" -#: pcsx2/gui/AppConfig.cpp:841 +#: pcsx2/gui/AppConfig.cpp:846 msgid "Aggressive plus" msgstr "Agresszív plusz" -#: pcsx2/gui/AppConfig.cpp:842 +#: pcsx2/gui/AppConfig.cpp:847 msgid "Mostly Harmful" msgstr "Legártalmasabb" -#: pcsx2/gui/AppConfig.cpp:999 pcsx2/gui/AppConfig.cpp:1005 +#: pcsx2/gui/AppConfig.cpp:1007 pcsx2/gui/AppConfig.cpp:1013 msgid "Failed to overwrite existing settings file; permission was denied." msgstr "A meglévő beállítás fájl felülírása sikertelen; hozzáférés megtagadva." @@ -2426,22 +2426,10 @@ msgstr "" "stb... [Ajánlott]" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:166 -msgid "mVU Block Hack" -msgstr "mVU blokk hack" - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 -#, fuzzy -msgid "" -"Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." -msgstr "" -"Látványos gyorsulás és magas kompatibilitás; grafikai hibákat okozhat, SPS, " -"stb..." - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "MTVU (Multi-Threaded microVU1)" msgstr "" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:170 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 #, fuzzy msgid "" "Good Speedup and High Compatibility; may cause hanging... [Recommended if 3+ " @@ -2450,15 +2438,15 @@ msgstr "" "Látványos gyorsulás és magas kompatibilitás; grafikai hibákat okozhat, SPS, " "stb... [Ajánlott]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:183 msgid "Other Hacks" msgstr "Egyéb hackek" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:193 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:185 msgid "Enable INTC Spin Detection" msgstr "INTC pörgés észlelés használata" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:194 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:186 msgid "" "Huge speedup for some games, with almost no compatibility side effects. " "[Recommended]" @@ -2466,22 +2454,22 @@ msgstr "" "Nagymértékű gyorsulás néhány játék esetében, többnyire nincs kompatibilitási " "mellékhatás. [Ajánlott]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:196 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:188 msgid "Enable Wait Loop Detection" msgstr "Hurok észlelésre várakozás használata" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:197 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:189 msgid "" "Moderate speedup for some games, with no known side effects. [Recommended]" msgstr "" "Enyhe sebesség növekedés néhány játéknál, nincs ismert mellékhatás. " "[Ajánlott]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:199 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 msgid "Enable fast CDVD" msgstr "Gyors CDVD használata" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:192 msgid "Fast disc access, less loading times. [Not Recommended]" msgstr "Gyors lemez hozzáférés, kevesebb betöltési idő. [Nem ajánlott]" @@ -2540,7 +2528,7 @@ msgstr "FPS" msgid "PAL Framerate:" msgstr "PAL képfrissítés:" -#: pcsx2/gui/Panels/VideoPanel.cpp:162 +#: pcsx2/gui/Panels/VideoPanel.cpp:166 msgid "" "Error while parsing either NTSC or PAL framerate settings. Settings must be " "valid floating point numerics." @@ -2548,19 +2536,19 @@ msgstr "" "Hiba vagy az NTSC vagy PAL képfrissítési beállítások elemzésekor. A " "beállításoknak érvényes lebegőpontos számoknak kell lenniük." -#: pcsx2/gui/Panels/VideoPanel.cpp:180 +#: pcsx2/gui/Panels/VideoPanel.cpp:184 msgid "Disabled [default]" msgstr "Kikapcsolva [alap]" -#: pcsx2/gui/Panels/VideoPanel.cpp:184 +#: pcsx2/gui/Panels/VideoPanel.cpp:188 msgid "Skip when on Turbo only (TAB to enable)" msgstr "Csak bekapcsolt Turbó esetén (TAB a használathoz)" -#: pcsx2/gui/Panels/VideoPanel.cpp:188 +#: pcsx2/gui/Panels/VideoPanel.cpp:192 msgid "Constant skipping" msgstr "Változatlan kihagyás" -#: pcsx2/gui/Panels/VideoPanel.cpp:190 +#: pcsx2/gui/Panels/VideoPanel.cpp:194 msgid "" "Normal and Turbo limit rates skip frames. Slow motion mode will still " "disable frameskipping." @@ -2568,19 +2556,19 @@ msgstr "" "Normál és turbó korlátozza a kihagyandó képkockák számát. A lassított mód " "is kikapcsolja a képkocka kihagyást." -#: pcsx2/gui/Panels/VideoPanel.cpp:213 +#: pcsx2/gui/Panels/VideoPanel.cpp:217 msgid "Frames to Draw" msgstr "Megjelenítendő képkockák" -#: pcsx2/gui/Panels/VideoPanel.cpp:218 +#: pcsx2/gui/Panels/VideoPanel.cpp:222 msgid "Frames to Skip" msgstr "Kihagyandó képkockák" -#: pcsx2/gui/Panels/VideoPanel.cpp:294 +#: pcsx2/gui/Panels/VideoPanel.cpp:298 msgid "Use Synchronized MTGS" msgstr "Szinkronizált MTGS használata" -#: pcsx2/gui/Panels/VideoPanel.cpp:295 +#: pcsx2/gui/Panels/VideoPanel.cpp:299 msgid "" "For troubleshooting potential bugs in the MTGS only, as it is potentially " "very slow." @@ -2588,11 +2576,11 @@ msgstr "" "Lehetséges hibák keresése csupán az MTGS-ben, mivel potenciálisan nagyon " "lassú." -#: pcsx2/gui/Panels/VideoPanel.cpp:298 +#: pcsx2/gui/Panels/VideoPanel.cpp:302 msgid "Disable all GS output" msgstr "Minden GS kimenet kikapcsolása" -#: pcsx2/gui/Panels/VideoPanel.cpp:299 +#: pcsx2/gui/Panels/VideoPanel.cpp:303 msgid "" "Completely disables all GS plugin activity; ideal for benchmarking EEcore " "components." @@ -2600,11 +2588,11 @@ msgstr "" "Teljesen leállít minden GS plugin tevékenységet; ideális az EEcore " "összetevők tesztelése esetén." -#: pcsx2/gui/Panels/VideoPanel.cpp:316 +#: pcsx2/gui/Panels/VideoPanel.cpp:320 msgid "Frame Skipping" msgstr "Képkocka kihagyás" -#: pcsx2/gui/Panels/VideoPanel.cpp:319 +#: pcsx2/gui/Panels/VideoPanel.cpp:323 msgid "Framelimiter" msgstr "Képkocka korlátozó" @@ -2690,6 +2678,16 @@ msgstr "" "%s kiterjesztés nem található. A microVU működéséhez szükséges egy MMX, SSE " "és SSE2 utasításkészletet támogató processzor." +#~ msgid "mVU Block Hack" +#~ msgstr "mVU blokk hack" + +#, fuzzy +#~ msgid "" +#~ "Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." +#~ msgstr "" +#~ "Látványos gyorsulás és magas kompatibilitás; grafikai hibákat okozhat, " +#~ "SPS, stb..." + #~ msgid "ISO mounting failed: PCSX2 is unable to identify the ISO image type." #~ msgstr "" #~ "ISO csatolása sikertelen: PCSX2 képtelen azonosítani az ISO képfájl " diff --git a/locales/it_IT/pcsx2_Iconized.po b/locales/it_IT/pcsx2_Iconized.po index 33eccdca6..83a059d78 100644 --- a/locales/it_IT/pcsx2_Iconized.po +++ b/locales/it_IT/pcsx2_Iconized.po @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-11-16 20:16+0100\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: 2011-10-05 21:01+0100\n" "Last-Translator: Leucos\n" "Language-Team: \n" @@ -26,7 +26,7 @@ msgstr "" "Non c'è abbastanza memoria virtuale disponibile o gli spazi della memoria " "virtuale necessari sono già stati riservati ad altri processi, servizi o DLL." -#: pcsx2/CDVD/CDVD.cpp:385 +#: pcsx2/CDVD/CDVD.cpp:390 msgid "!Notice:PsxDisc" msgstr "" "I dischi di gioco per PlayStation non sono supportati in PCSX2. Se desideri " @@ -508,7 +508,7 @@ msgstr "" "Valori più alti aumentano il numero di cicli 'rubati' dall'EE per ogni " "microprogramma VU eseguito dal gioco." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:172 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "!ContextTip:Speedhacks:vuFlagHack" msgstr "" "Aggiorna le Flag di stato solo nei blocchi che le leggeranno, invece che " @@ -516,15 +516,7 @@ msgstr "" "per la maggior parte dei casi e superVU fa qualcosa del genere in maniera " "predefinita." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:177 -msgid "!ContextTip:Speedhacks:vuBlockHack" -msgstr "" -"Prevede che nel futuro prossimo i blocchi non avranno bisogno della vecchia " -"Flag 'instance data'. \n" -"Questo dovrebbe essere abbastanza sicuro. Non si sa se crea problemi in " -"qualche gioco..." - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:182 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:174 msgid "!ContextTip:Speedhacks:vuThread" msgstr "" "Esegue la VU1 in un thread separato (solo la microVU1). Generalmente si " @@ -534,7 +526,7 @@ msgstr "" "Si possono invece verificare dei rallentamenti (specialmente con CPU dual-" "core) nel caso di giochi limitati dal thread GS ." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:203 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:195 msgid "!ContextTip:Speedhacks:INTC" msgstr "" "Questo hack funziona al meglio nei giochi che utilizzano il registro di " @@ -542,7 +534,7 @@ msgstr "" "3D. I giochi che non utilizzano questo metodo di sincronia verticale " "otterranno un aumento di velocità minimo se non nullo." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:208 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 msgid "!ContextTip:Speedhacks:BIFC0" msgstr "" "L'obiettivo principale è l'idle loop (ciclo per inattività) dell'EE " @@ -553,7 +545,7 @@ msgstr "" "successivo o alla fine del tempo riservato al processore, qualunque venga " "prima." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:215 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:207 msgid "!ContextTip:Speedhacks:fastCDVD" msgstr "" "Controlla la lista compatibilità di HDLoader per sapere quali giochi creano " @@ -566,20 +558,20 @@ msgstr "" "Nota che quando il Limitatore Fotogrammi è disattivato anche le modalità " "Turbo e Rallentatore non saranno più disponibili." -#: pcsx2/gui/Panels/VideoPanel.cpp:223 +#: pcsx2/gui/Panels/VideoPanel.cpp:227 msgid "!Panel:Frameskip:Heading" msgstr "" "Avviso: a causa del design hardware della PS2, un salto dei fotogrammi " "preciso non è possibile. La sua attivazione può causare gravi errori grafici " "in alcuni giochi." -#: pcsx2/gui/Panels/VideoPanel.cpp:302 +#: pcsx2/gui/Panels/VideoPanel.cpp:306 msgid "!ContextTip:GS:SyncMTGS" msgstr "" "Attiva questa opzione se pensi che la perdita di sincrona del thread MTGS " "sia la causa di crash o problemi grafici." -#: pcsx2/gui/Panels/VideoPanel.cpp:306 +#: pcsx2/gui/Panels/VideoPanel.cpp:310 msgid "!ContextTip:GS:DisableOutput" msgstr "" "Nei benchmark, permette di rimuovere ogni interferenza causata dal thread " @@ -605,3 +597,10 @@ msgstr "" "riservare il range di memoria specifico richiesto, non sarà quindi " "disponibile all'utilizzo. Questo non è un errore critico, dato che il " "ricompilatore sVU è obsoleto e in ogni caso dovresti utilizzare microVU. :)" + +#~ msgid "!ContextTip:Speedhacks:vuBlockHack" +#~ msgstr "" +#~ "Prevede che nel futuro prossimo i blocchi non avranno bisogno della " +#~ "vecchia Flag 'instance data'. \n" +#~ "Questo dovrebbe essere abbastanza sicuro. Non si sa se crea problemi in " +#~ "qualche gioco..." diff --git a/locales/it_IT/pcsx2_Main.po b/locales/it_IT/pcsx2_Main.po index d54c931eb..d6e664ec7 100644 --- a/locales/it_IT/pcsx2_Main.po +++ b/locales/it_IT/pcsx2_Main.po @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-11-16 20:15+0100\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: 2011-10-05 21:01+0100\n" "Last-Translator: Leucos\n" "Language-Team: \n" @@ -200,7 +200,7 @@ msgstr "Non è stato possibile inizializzare il plugin interno Memory Card." msgid "Unloaded Plugin" msgstr "Plugin Scaricato" -#: pcsx2/SaveState.cpp:339 +#: pcsx2/SaveState.cpp:342 msgid "Cannot load savestate. It is of an unknown or unsupported version." msgstr "" "Impossibile caricare il salvataggio di stato. Appartiene ad una versione " @@ -378,31 +378,31 @@ msgstr "" "temporaneo è stato creato con successo ma non è stato possibile spostarlo " "nel suo ultimo luogo di riposo." -#: pcsx2/gui/AppConfig.cpp:837 +#: pcsx2/gui/AppConfig.cpp:842 msgid "Safest" msgstr "Sicura +" -#: pcsx2/gui/AppConfig.cpp:838 +#: pcsx2/gui/AppConfig.cpp:843 msgid "Safe (faster)" msgstr "Sicura (più veloce)" -#: pcsx2/gui/AppConfig.cpp:839 +#: pcsx2/gui/AppConfig.cpp:844 msgid "Balanced" msgstr "Bilanciata" -#: pcsx2/gui/AppConfig.cpp:840 +#: pcsx2/gui/AppConfig.cpp:845 msgid "Aggressive" msgstr "Aggressiva" -#: pcsx2/gui/AppConfig.cpp:841 +#: pcsx2/gui/AppConfig.cpp:846 msgid "Aggressive plus" msgstr "Aggressiva +" -#: pcsx2/gui/AppConfig.cpp:842 +#: pcsx2/gui/AppConfig.cpp:847 msgid "Mostly Harmful" msgstr "Quasi dannosa" -#: pcsx2/gui/AppConfig.cpp:999 pcsx2/gui/AppConfig.cpp:1005 +#: pcsx2/gui/AppConfig.cpp:1007 pcsx2/gui/AppConfig.cpp:1013 msgid "Failed to overwrite existing settings file; permission was denied." msgstr "" "Sovrascrittura del file impostazioni esistente fallita: permesso negato." @@ -2467,21 +2467,10 @@ msgstr "" "grafica... [consigliato]" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:166 -msgid "mVU Block Hack" -msgstr "microVU Block Hack" - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 -msgid "" -"Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." -msgstr "" -"Buon aumento di velocità ed alta compatibilità. Può causare problemi nella " -"grafica, SPS, ecc..." - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "MTVU (Multi-Threaded microVU1)" msgstr "MTVU (microVU1 multi-threaded)" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:170 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 msgid "" "Good Speedup and High Compatibility; may cause hanging... [Recommended if 3+ " "cores]" @@ -2489,15 +2478,15 @@ msgstr "" "Buon aumento di velocità ed alta compatibilità. Può causare blocchi nei " "giochi... [consigliato, solo se possiedi 3 o più core]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:183 msgid "Other Hacks" msgstr "Altri Hack" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:193 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:185 msgid "Enable INTC Spin Detection" msgstr "Attiva rilevamento Spin INTC (INTC Spin Detection)" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:194 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:186 msgid "" "Huge speedup for some games, with almost no compatibility side effects. " "[Recommended]" @@ -2505,22 +2494,22 @@ msgstr "" "Grande aumento di velocità per alcuni giochi, con quasi nessun effetto " "negativo sulla compatibilità. [consigliato]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:196 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:188 msgid "Enable Wait Loop Detection" msgstr "Attiva rilevamento ciclo d'inattività (Wait Loop Detection)" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:197 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:189 msgid "" "Moderate speedup for some games, with no known side effects. [Recommended]" msgstr "" "Aumento di velocità moderato per alcuni giochi, nessun effetto collaterale " "noto. [consigliato]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:199 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 msgid "Enable fast CDVD" msgstr "Attiva CDVD veloce (fast CDVD)" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:192 msgid "Fast disc access, less loading times. [Not Recommended]" msgstr "" "Accesso rapido al disco, tempi di caricamento inferiori. [non consigliato]" @@ -2580,7 +2569,7 @@ msgstr "FPS" msgid "PAL Framerate:" msgstr "Frequenza fotogrammi PAL:" -#: pcsx2/gui/Panels/VideoPanel.cpp:162 +#: pcsx2/gui/Panels/VideoPanel.cpp:166 msgid "" "Error while parsing either NTSC or PAL framerate settings. Settings must be " "valid floating point numerics." @@ -2588,19 +2577,19 @@ msgstr "" "Errore nell'interpretazione dell'impostazione della frequenza dei fotogrammi " "PAL o NTSC. L'impostazione deve avere un valore numerico con virgola valido." -#: pcsx2/gui/Panels/VideoPanel.cpp:180 +#: pcsx2/gui/Panels/VideoPanel.cpp:184 msgid "Disabled [default]" msgstr "Disattivato [predefinito]" -#: pcsx2/gui/Panels/VideoPanel.cpp:184 +#: pcsx2/gui/Panels/VideoPanel.cpp:188 msgid "Skip when on Turbo only (TAB to enable)" msgstr "Salta solo in modalità Turbo (TAB per attivare)" -#: pcsx2/gui/Panels/VideoPanel.cpp:188 +#: pcsx2/gui/Panels/VideoPanel.cpp:192 msgid "Constant skipping" msgstr "Salto costante" -#: pcsx2/gui/Panels/VideoPanel.cpp:190 +#: pcsx2/gui/Panels/VideoPanel.cpp:194 msgid "" "Normal and Turbo limit rates skip frames. Slow motion mode will still " "disable frameskipping." @@ -2608,19 +2597,19 @@ msgstr "" "In modalità Normale e Turbo i fotogrammi saranno saltati. Nella modalità\n" "Rallentatore il salto dei fotogrammi sarà comunque disattivato." -#: pcsx2/gui/Panels/VideoPanel.cpp:213 +#: pcsx2/gui/Panels/VideoPanel.cpp:217 msgid "Frames to Draw" msgstr "Fotogrammi da disegnare" -#: pcsx2/gui/Panels/VideoPanel.cpp:218 +#: pcsx2/gui/Panels/VideoPanel.cpp:222 msgid "Frames to Skip" msgstr "Fotogrammi da saltare" -#: pcsx2/gui/Panels/VideoPanel.cpp:294 +#: pcsx2/gui/Panels/VideoPanel.cpp:298 msgid "Use Synchronized MTGS" msgstr "Utilizza MTGS (Multi Threaded GS) sincronizzato" -#: pcsx2/gui/Panels/VideoPanel.cpp:295 +#: pcsx2/gui/Panels/VideoPanel.cpp:299 msgid "" "For troubleshooting potential bugs in the MTGS only, as it is potentially " "very slow." @@ -2628,11 +2617,11 @@ msgstr "" "Solo per rilevare eventuali bug nel MTGS, dato che potenzialmente è molto " "lento." -#: pcsx2/gui/Panels/VideoPanel.cpp:298 +#: pcsx2/gui/Panels/VideoPanel.cpp:302 msgid "Disable all GS output" msgstr "Disabilita tutto l'output GS" -#: pcsx2/gui/Panels/VideoPanel.cpp:299 +#: pcsx2/gui/Panels/VideoPanel.cpp:303 msgid "" "Completely disables all GS plugin activity; ideal for benchmarking EEcore " "components." @@ -2640,11 +2629,11 @@ msgstr "" "Disattiva completamente l'attività del plugin GS; ideale per fare un " "benchmark dei componenti EEcore." -#: pcsx2/gui/Panels/VideoPanel.cpp:316 +#: pcsx2/gui/Panels/VideoPanel.cpp:320 msgid "Frame Skipping" msgstr "Salto Fotogrammi" -#: pcsx2/gui/Panels/VideoPanel.cpp:319 +#: pcsx2/gui/Panels/VideoPanel.cpp:323 msgid "Framelimiter" msgstr "Limitatore Fotogrammi" @@ -2734,3 +2723,12 @@ msgid "" msgstr "" "Estensioni %s non trovate. microVU richiede una CPU del sistema host con " "estensioni MMX, SSE ed SSE2." + +#~ msgid "mVU Block Hack" +#~ msgstr "microVU Block Hack" + +#~ msgid "" +#~ "Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." +#~ msgstr "" +#~ "Buon aumento di velocità ed alta compatibilità. Può causare problemi " +#~ "nella grafica, SPS, ecc..." diff --git a/locales/ja_JP/pcsx2_Iconized.po b/locales/ja_JP/pcsx2_Iconized.po index fdfbb3759..2461a90a1 100644 --- a/locales/ja_JP/pcsx2_Iconized.po +++ b/locales/ja_JP/pcsx2_Iconized.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-09-28 20:27+0200\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: 2011-04-30 10:48+0900\n" "Last-Translator: oreore\n" "Language-Team: \n" @@ -28,7 +28,7 @@ msgid "!Notice:VirtualMemoryMap" msgstr "" "十分な仮想メモリがありません。もしくは他のプロセスやDLLによって予約済みです。" -#: pcsx2/CDVD/CDVD.cpp:385 +#: pcsx2/CDVD/CDVD.cpp:390 msgid "!Notice:PsxDisc" msgstr "" "PCSX2 は Playstation のゲームをサポートしていません。プレイしたい場合は " @@ -460,19 +460,13 @@ msgstr "" "す。\n" "高い設定にするほどサイクルスティーリングを行う量が増加します。" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:172 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "!ContextTip:Speedhacks:vuFlagHack" msgstr "" "常時ではなくブロックされた時のみフラグステータスを更新します。\n" "ほとんどの安全であり、SuperVUにも同様の動作をさせます。" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:177 -msgid "!ContextTip:Speedhacks:vuBlockHack" -msgstr "" -"遠い将来にインスタンスデータの古いフラグを必要としないと仮定しています。\n" -"かなり安全なはずです。どんなゲームに不具合が起きるかは不明ですが..." - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:182 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:174 #, fuzzy msgid "!ContextTip:Speedhacks:vuThread" msgstr "" @@ -480,14 +474,14 @@ msgstr "" "ゲームに最適です。\n" "効果がなかった場合には使用しないでください。" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:203 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:195 msgid "!ContextTip:Speedhacks:INTC" msgstr "" "このhackは主に非3D系RPGにある INTC ステータスレジスタを使用しVSYNC待ちをする" "ゲームに最適です。\n" "効果がなかった場合には使用しないでください。" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:208 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 msgid "!ContextTip:Speedhacks:BIFC0" msgstr "" "主にEEのカーネル空間のアドレス 0x81FC0 のアイドルループ処理を対象にしていま" @@ -497,7 +491,7 @@ msgstr "" "このようなループを1度だけ繰り返したあと、次のイベントかタイムスライスの終りのいずれ" "か早いほうに進みます。" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:215 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:207 msgid "!ContextTip:Speedhacks:fastCDVD" msgstr "" "この問題を抱えている既知のゲーム用の設定。\n" @@ -509,19 +503,19 @@ msgstr "" "フレームリミットを無効にした場合、スローモーションモードとターボモードは使用" "できません。" -#: pcsx2/gui/Panels/VideoPanel.cpp:223 +#: pcsx2/gui/Panels/VideoPanel.cpp:227 msgid "!Panel:Frameskip:Heading" msgstr "" "注意!PS2はハードの設計上正確なフレームスキップはできません。よって一部のゲー" "ムでは深刻なグラフィックのエラーが発生します。" -#: pcsx2/gui/Panels/VideoPanel.cpp:302 +#: pcsx2/gui/Panels/VideoPanel.cpp:306 msgid "!ContextTip:GS:SyncMTGS" msgstr "" "映像の不具合の原因が MTGS スレッドの同期によるものだと思われる場合有効にして" "ください。" -#: pcsx2/gui/Panels/VideoPanel.cpp:306 +#: pcsx2/gui/Panels/VideoPanel.cpp:310 msgid "!ContextTip:GS:DisableOutput" msgstr "" "MTGSスレッドかGPUオーバーヘッドによって発生されたベンチマークノイズを除去しま" @@ -549,6 +543,11 @@ msgstr "" "もう廃れたため、\n" "お代わりにとにかくmicroVUを使用するべきでしょう。(笑)" +#~ msgid "!ContextTip:Speedhacks:vuBlockHack" +#~ msgstr "" +#~ "遠い将来にインスタンスデータの古いフラグを必要としないと仮定しています。\n" +#~ "かなり安全なはずです。どんなゲームに不具合が起きるかは不明ですが..." + #~ msgid "No reason given." #~ msgstr "不明な理由" diff --git a/locales/ja_JP/pcsx2_Main.po b/locales/ja_JP/pcsx2_Main.po index e0e6d450b..3c013fde0 100644 --- a/locales/ja_JP/pcsx2_Main.po +++ b/locales/ja_JP/pcsx2_Main.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-09-28 20:27+0200\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: 2011-04-30 09:01+0900\n" "Last-Translator: oreore\n" "Language-Team: \n" @@ -192,7 +192,7 @@ msgstr "内蔵メモリーカードプラグインの初期化に失敗しまし msgid "Unloaded Plugin" msgstr "プラグインのアンインストール" -#: pcsx2/SaveState.cpp:339 +#: pcsx2/SaveState.cpp:342 msgid "Cannot load savestate. It is of an unknown or unsupported version." msgstr "" "ステートセーブを読み込めません。未知のバージョン、または未サポートのデータで" @@ -358,31 +358,31 @@ msgstr "" "ステートセーブを保存できませんでした。一時ファイルは正常に作成されましたが、" "データの保存ができませんでした。" -#: pcsx2/gui/AppConfig.cpp:837 +#: pcsx2/gui/AppConfig.cpp:842 msgid "Safest" msgstr "最も安定" -#: pcsx2/gui/AppConfig.cpp:838 +#: pcsx2/gui/AppConfig.cpp:843 msgid "Safe (faster)" msgstr "最も安定(高速)" -#: pcsx2/gui/AppConfig.cpp:839 +#: pcsx2/gui/AppConfig.cpp:844 msgid "Balanced" msgstr "バランス" -#: pcsx2/gui/AppConfig.cpp:840 +#: pcsx2/gui/AppConfig.cpp:845 msgid "Aggressive" msgstr "アグレッシブ" -#: pcsx2/gui/AppConfig.cpp:841 +#: pcsx2/gui/AppConfig.cpp:846 msgid "Aggressive plus" msgstr "アグレッシブ+" -#: pcsx2/gui/AppConfig.cpp:842 +#: pcsx2/gui/AppConfig.cpp:847 msgid "Mostly Harmful" msgstr "害にしかならない" -#: pcsx2/gui/AppConfig.cpp:999 pcsx2/gui/AppConfig.cpp:1005 +#: pcsx2/gui/AppConfig.cpp:1007 pcsx2/gui/AppConfig.cpp:1013 msgid "Failed to overwrite existing settings file; permission was denied." msgstr "設定ファイルの更新に失敗しました。アクセスが拒否されました。" @@ -2386,22 +2386,10 @@ msgstr "" "がありますが...[推奨]" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:166 -msgid "mVU Block Hack" -msgstr "mVU Block Hack" - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 -#, fuzzy -msgid "" -"Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." -msgstr "" -"良いスピードアップと高い互換性があります;映像や音声に多少のゴミがデル可能性" -"がありますが..." - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "MTVU (Multi-Threaded microVU1)" msgstr "" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:170 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 #, fuzzy msgid "" "Good Speedup and High Compatibility; may cause hanging... [Recommended if 3+ " @@ -2410,36 +2398,36 @@ msgstr "" "良いスピードアップと高い互換性があります;映像や音声に多少の出るが出る可能性" "がありますが...[推奨]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:183 msgid "Other Hacks" msgstr "その他のHack" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:193 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:185 msgid "Enable INTC Spin Detection" msgstr "INTCのSpin検出を有効" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:194 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:186 msgid "" "Huge speedup for some games, with almost no compatibility side effects. " "[Recommended]" msgstr "" "多少の互換性と引き換えに、一部のゲームで大幅なスピードアップを図れます[推奨]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:196 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:188 msgid "Enable Wait Loop Detection" msgstr "ループ検出を有効" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:197 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:189 msgid "" "Moderate speedup for some games, with no known side effects. [Recommended]" msgstr "" "互換性と引き換えに、一部のゲームである程度のスピードアップを図れます[推奨]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:199 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 msgid "Enable fast CDVD" msgstr "CDVDの高速読み込みを有効" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:192 msgid "Fast disc access, less loading times. [Not Recommended]" msgstr "高速でディスクにアクセスしてロード時間を短縮[非推奨]" @@ -2498,7 +2486,7 @@ msgstr "FPS" msgid "PAL Framerate:" msgstr "PAL フレームレート:" -#: pcsx2/gui/Panels/VideoPanel.cpp:162 +#: pcsx2/gui/Panels/VideoPanel.cpp:166 msgid "" "Error while parsing either NTSC or PAL framerate settings. Settings must be " "valid floating point numerics." @@ -2506,19 +2494,19 @@ msgstr "" "NTSC または PAL のフレームレートの設定の解析中にエラーが発生しました。有効な" "浮動小数点値を入力してください。" -#: pcsx2/gui/Panels/VideoPanel.cpp:180 +#: pcsx2/gui/Panels/VideoPanel.cpp:184 msgid "Disabled [default]" msgstr "無効 [デフォルト]" -#: pcsx2/gui/Panels/VideoPanel.cpp:184 +#: pcsx2/gui/Panels/VideoPanel.cpp:188 msgid "Skip when on Turbo only (TAB to enable)" msgstr "ターボの時のみスキップ(Tabキーで有効)" -#: pcsx2/gui/Panels/VideoPanel.cpp:188 +#: pcsx2/gui/Panels/VideoPanel.cpp:192 msgid "Constant skipping" msgstr "常にフレームをスキップする" -#: pcsx2/gui/Panels/VideoPanel.cpp:190 +#: pcsx2/gui/Panels/VideoPanel.cpp:194 msgid "" "Normal and Turbo limit rates skip frames. Slow motion mode will still " "disable frameskipping." @@ -2526,40 +2514,40 @@ msgstr "" "通常、ターボモードの場合はフレームスキップを有効にしてください。スローモー" "ションモードでは無効にされます。" -#: pcsx2/gui/Panels/VideoPanel.cpp:213 +#: pcsx2/gui/Panels/VideoPanel.cpp:217 msgid "Frames to Draw" msgstr "フレーム描写" -#: pcsx2/gui/Panels/VideoPanel.cpp:218 +#: pcsx2/gui/Panels/VideoPanel.cpp:222 msgid "Frames to Skip" msgstr "フレームスキップ" -#: pcsx2/gui/Panels/VideoPanel.cpp:294 +#: pcsx2/gui/Panels/VideoPanel.cpp:298 msgid "Use Synchronized MTGS" msgstr "MTGSと同期" -#: pcsx2/gui/Panels/VideoPanel.cpp:295 +#: pcsx2/gui/Panels/VideoPanel.cpp:299 msgid "" "For troubleshooting potential bugs in the MTGS only, as it is potentially " "very slow." msgstr "MTGSに潜在的なバグがあった場合のみ有効に。非常に低速になります。" -#: pcsx2/gui/Panels/VideoPanel.cpp:298 +#: pcsx2/gui/Panels/VideoPanel.cpp:302 msgid "Disable all GS output" msgstr "GS出力を無効" -#: pcsx2/gui/Panels/VideoPanel.cpp:299 +#: pcsx2/gui/Panels/VideoPanel.cpp:303 msgid "" "Completely disables all GS plugin activity; ideal for benchmarking EEcore " "components." msgstr "" "GSプラグインを無効にします。EEコアコンポーネントのベンチマークに最適です。" -#: pcsx2/gui/Panels/VideoPanel.cpp:316 +#: pcsx2/gui/Panels/VideoPanel.cpp:320 msgid "Frame Skipping" msgstr "フレームスキップの設定" -#: pcsx2/gui/Panels/VideoPanel.cpp:319 +#: pcsx2/gui/Panels/VideoPanel.cpp:323 msgid "Framelimiter" msgstr "フレームリミットの設定" @@ -2645,6 +2633,16 @@ msgstr "" "%s 拡張命令が見つかりませんでした。microVU にはMMX, SSE, SSE2 拡張命令が必要" "です。" +#~ msgid "mVU Block Hack" +#~ msgstr "mVU Block Hack" + +#, fuzzy +#~ msgid "" +#~ "Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." +#~ msgstr "" +#~ "良いスピードアップと高い互換性があります;映像や音声に多少のゴミがデル可能" +#~ "性がありますが..." + #~ msgid "!ContextTip:ChangingNTFS" #~ msgstr "" #~ "NTFS 圧縮の設定は、Windowsのエクスプローラーでファイルのプロパティを開くこ" diff --git a/locales/pl_PL/pcsx2_Iconized.po b/locales/pl_PL/pcsx2_Iconized.po index 69917d760..e4a3c0475 100644 --- a/locales/pl_PL/pcsx2_Iconized.po +++ b/locales/pl_PL/pcsx2_Iconized.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-10-05 20:13+0200\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: 2011-09-28 21:55+0100\n" "Last-Translator: Miseru99 \n" "Language-Team: Miseru99 \n" @@ -30,7 +30,7 @@ msgstr "" "została\n" "już zarezerwowana przez inny process, usługę lub DLL." -#: pcsx2/CDVD/CDVD.cpp:385 +#: pcsx2/CDVD/CDVD.cpp:390 msgid "!Notice:PsxDisc" msgstr "" "Gry z Playstation nie są obsługiwane przez PCSX2. Jeśli chcesz emulować gry " @@ -490,7 +490,7 @@ msgstr "" "ilość skradzionych cykli używanych na każdy mikroprogram uruchamiany przez " "grę." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:172 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "!ContextTip:Speedhacks:vuFlagHack" msgstr "" "Uaktualnia Flagi Statusu tylko na blokach, które je odczytują zamiast cały " @@ -498,15 +498,7 @@ msgstr "" "Jest to bezpieczne w większości przypadków, SuperVU robi coś podobnego w " "standardzie." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:177 -msgid "!ContextTip:Speedhacks:vuBlockHack" -msgstr "" -"Zakłada iż w bardzo dalekiej przyszłości, bloki nie będą potrzebować starych " -"instancji danych flag.\n" -"Powinno to być w miarę bezpieczne, nie jest wiadome czy przeszkadza " -"jakiejkolwiek grze." - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:182 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:174 msgid "!ContextTip:Speedhacks:vuThread" msgstr "" "Dodaje osobny wątek dla VU1(działa tylko z microVU1). Najczęściej oznacza to " @@ -516,7 +508,7 @@ msgstr "" "Na gry ograniczone wątkiem GS może to mieć odwrotny skutek, szczególnie przy " "2-rdzeniowych procesorach." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:203 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:195 msgid "!ContextTip:Speedhacks:INTC" msgstr "" "Ta łatka działa najlepiej z grami, które używają zapisu stanu INTC do " @@ -524,7 +516,7 @@ msgstr "" "głównie wszelkie nie zrobione w 3D RPGi. Inne gry nie będą miały z tego " "żadnego, lub minimalny pożytek." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:208 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 msgid "!ContextTip:Speedhacks:BIFC0" msgstr "" "Ta łatka namierza bezczynne pętle o adresie 0x81FC0 w jądrze EE. Stara się " @@ -533,7 +525,7 @@ msgstr "" "odtwarza je\n" "dopiero gdy to zdarzenie nastąpi." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:215 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:207 msgid "!ContextTip:Speedhacks:fastCDVD" msgstr "" "Sprawdź listę kompatybilności HDLoader'a aby zobaczyć które gry mają z tą " @@ -546,7 +538,7 @@ msgstr "" "Miej na uwadze, że przy wyłączonym limicie klatek animacji,\n" "tryby Przyspieszony i Spowolniony nie będą dostępne." -#: pcsx2/gui/Panels/VideoPanel.cpp:223 +#: pcsx2/gui/Panels/VideoPanel.cpp:227 msgid "!Panel:Frameskip:Heading" msgstr "" "Uwaga: Ze względu na architekturę PS2,\n" @@ -555,13 +547,13 @@ msgstr "" "Włączenie tej opcji z całą pewnością BĘDZIE\n" " powodowało masę błędów graficznych w wielu grach." -#: pcsx2/gui/Panels/VideoPanel.cpp:302 +#: pcsx2/gui/Panels/VideoPanel.cpp:306 msgid "!ContextTip:GS:SyncMTGS" msgstr "" "Użyj tej opcji jeśli podejrzewasz, że synchronizacja wątku MTGS\n" "odpowiada za zawieszanie się lub graficzne błędy w jakiejś grze." -#: pcsx2/gui/Panels/VideoPanel.cpp:306 +#: pcsx2/gui/Panels/VideoPanel.cpp:310 msgid "!ContextTip:GS:DisableOutput" msgstr "" "Usuwa wszelkie nieprawidłowości spowodowane przez wątek MTGS lub GPU. " @@ -589,3 +581,10 @@ msgstr "" "ilości pamięci i nie będzie działać. To nie jest błąd krytyczny, gdyż sVU " "jest zbędny i tak czy siak\n" "powinieneś użyć rekompilatora microVU.:3" + +#~ msgid "!ContextTip:Speedhacks:vuBlockHack" +#~ msgstr "" +#~ "Zakłada iż w bardzo dalekiej przyszłości, bloki nie będą potrzebować " +#~ "starych instancji danych flag.\n" +#~ "Powinno to być w miarę bezpieczne, nie jest wiadome czy przeszkadza " +#~ "jakiejkolwiek grze." diff --git a/locales/pl_PL/pcsx2_Main.po b/locales/pl_PL/pcsx2_Main.po index 6032ddb11..4209aa7d8 100644 --- a/locales/pl_PL/pcsx2_Main.po +++ b/locales/pl_PL/pcsx2_Main.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-10-05 20:13+0200\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: 2011-09-28 22:22+0100\n" "Last-Translator: Miseru99 \n" "Language-Team: Miseru99 \n" @@ -198,7 +198,7 @@ msgstr "Nie udało się uruchomić wbudowanej wtyczki Kart Pamięci." msgid "Unloaded Plugin" msgstr "Wtyczka wyłączona" -#: pcsx2/SaveState.cpp:339 +#: pcsx2/SaveState.cpp:342 msgid "Cannot load savestate. It is of an unknown or unsupported version." msgstr "" "Nie można wgrać zapisanej gry. Pochodzi z nieznanej lub nieobsługiwanej " @@ -366,31 +366,31 @@ msgstr "" "Ten zapis gry nie został poprawnie zachowany. Tymczasowa kopia została " "stworzona pomyślnie, lecz nie mogła być przeniesiona we właściwe miejsce." -#: pcsx2/gui/AppConfig.cpp:837 +#: pcsx2/gui/AppConfig.cpp:842 msgid "Safest" msgstr "Najbezpieczniejszy" -#: pcsx2/gui/AppConfig.cpp:838 +#: pcsx2/gui/AppConfig.cpp:843 msgid "Safe (faster)" msgstr "Bezpieczny (szybszy)" -#: pcsx2/gui/AppConfig.cpp:839 +#: pcsx2/gui/AppConfig.cpp:844 msgid "Balanced" msgstr "Zbalansowany" -#: pcsx2/gui/AppConfig.cpp:840 +#: pcsx2/gui/AppConfig.cpp:845 msgid "Aggressive" msgstr "Agresywny" -#: pcsx2/gui/AppConfig.cpp:841 +#: pcsx2/gui/AppConfig.cpp:846 msgid "Aggressive plus" msgstr "Agresywny Plus" -#: pcsx2/gui/AppConfig.cpp:842 +#: pcsx2/gui/AppConfig.cpp:847 msgid "Mostly Harmful" msgstr "Głównie Szkodliwy" -#: pcsx2/gui/AppConfig.cpp:999 pcsx2/gui/AppConfig.cpp:1005 +#: pcsx2/gui/AppConfig.cpp:1007 pcsx2/gui/AppConfig.cpp:1013 msgid "Failed to overwrite existing settings file; permission was denied." msgstr "Nie udało się nadpisać istniejącego pliku ustawień; odmowa dostępu." @@ -2417,21 +2417,10 @@ msgstr "" "[Zalecane]" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:166 -msgid "mVU Block Hack" -msgstr "mVU Block Hack" - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 -msgid "" -"Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." -msgstr "" -"Dobre przyspieszenie i duża kompatybilność; może powodować błędy grafiki, " -"SPS, itd..." - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "MTVU (Multi-Threaded microVU1)" msgstr "MTVU(Wielo-Wątkowe microVU1)" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:170 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 msgid "" "Good Speedup and High Compatibility; may cause hanging... [Recommended if 3+ " "cores]" @@ -2440,15 +2429,15 @@ msgstr "" "powodować niestabilność...\n" "[Zalecane dla 3+ rdzeniowych procesorów]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:183 msgid "Other Hacks" msgstr "Inne Hack'i" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:193 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:185 msgid "Enable INTC Spin Detection" msgstr "Aktywuj Detekcję Rozruchu INTC" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:194 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:186 msgid "" "Huge speedup for some games, with almost no compatibility side effects. " "[Recommended]" @@ -2456,22 +2445,22 @@ msgstr "" "Ogrome przyspieszenie w pewnych grach, zwykle nie ma efektów ubocznych. " "[Zalecane]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:196 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:188 msgid "Enable Wait Loop Detection" msgstr "Aktywuj Wykrywanie Poczekania na Pętlę" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:197 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:189 msgid "" "Moderate speedup for some games, with no known side effects. [Recommended]" msgstr "" "Średnie przyspieszenie dla niektórych gier, bez znanych efektów ubocznych. " "[Zalecane]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:199 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 msgid "Enable fast CDVD" msgstr "Aktywuj szybkie CDVD" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:192 msgid "Fast disc access, less loading times. [Not Recommended]" msgstr "" "Szybki dostęp do dysku, mniejsze czasy wgrywania.\n" @@ -2530,7 +2519,7 @@ msgstr "FPS" msgid "PAL Framerate:" msgstr "Ilość klatek systemu PAL:" -#: pcsx2/gui/Panels/VideoPanel.cpp:162 +#: pcsx2/gui/Panels/VideoPanel.cpp:166 msgid "" "Error while parsing either NTSC or PAL framerate settings. Settings must be " "valid floating point numerics." @@ -2538,19 +2527,19 @@ msgstr "" "Błąd podczas składania ustawień klatek animacji NTSC lub PAL. Ustawienia " "muszą zawierać prawidłowe liczby rzeczywiste." -#: pcsx2/gui/Panels/VideoPanel.cpp:180 +#: pcsx2/gui/Panels/VideoPanel.cpp:184 msgid "Disabled [default]" msgstr "Wyłączone [standardowo]" -#: pcsx2/gui/Panels/VideoPanel.cpp:184 +#: pcsx2/gui/Panels/VideoPanel.cpp:188 msgid "Skip when on Turbo only (TAB to enable)" msgstr "Pomijaj tylko w trybie przyspieszonym (TAB przełącza)" -#: pcsx2/gui/Panels/VideoPanel.cpp:188 +#: pcsx2/gui/Panels/VideoPanel.cpp:192 msgid "Constant skipping" msgstr "Stale pomijaj" -#: pcsx2/gui/Panels/VideoPanel.cpp:190 +#: pcsx2/gui/Panels/VideoPanel.cpp:194 msgid "" "Normal and Turbo limit rates skip frames. Slow motion mode will still " "disable frameskipping." @@ -2558,19 +2547,19 @@ msgstr "" "Normalny i Przyspieszony limit pomija klatki animacji. Spowolniony nadal " "wyłącza pomijanie." -#: pcsx2/gui/Panels/VideoPanel.cpp:213 +#: pcsx2/gui/Panels/VideoPanel.cpp:217 msgid "Frames to Draw" msgstr "Klatek do Pokazania" -#: pcsx2/gui/Panels/VideoPanel.cpp:218 +#: pcsx2/gui/Panels/VideoPanel.cpp:222 msgid "Frames to Skip" msgstr "Klatek do Pominięcia" -#: pcsx2/gui/Panels/VideoPanel.cpp:294 +#: pcsx2/gui/Panels/VideoPanel.cpp:298 msgid "Use Synchronized MTGS" msgstr "Użyj Synchronizowanego MTGS" -#: pcsx2/gui/Panels/VideoPanel.cpp:295 +#: pcsx2/gui/Panels/VideoPanel.cpp:299 msgid "" "For troubleshooting potential bugs in the MTGS only, as it is potentially " "very slow." @@ -2578,11 +2567,11 @@ msgstr "" "Tylko w celach testowych i wyłapywania potencjalnych błędów w MTGS gdyż jest " "potencjalnie bardzo wolne." -#: pcsx2/gui/Panels/VideoPanel.cpp:298 +#: pcsx2/gui/Panels/VideoPanel.cpp:302 msgid "Disable all GS output" msgstr "Wyłącz całkowicie wyświetlanie obrazu" -#: pcsx2/gui/Panels/VideoPanel.cpp:299 +#: pcsx2/gui/Panels/VideoPanel.cpp:303 msgid "" "Completely disables all GS plugin activity; ideal for benchmarking EEcore " "components." @@ -2590,11 +2579,11 @@ msgstr "" "Całkowicie wyłącza całą aktywność silnika graficznego; idealne do testowania " "componentów EEcore." -#: pcsx2/gui/Panels/VideoPanel.cpp:316 +#: pcsx2/gui/Panels/VideoPanel.cpp:320 msgid "Frame Skipping" msgstr "Pomijanie Klatek Animacji" -#: pcsx2/gui/Panels/VideoPanel.cpp:319 +#: pcsx2/gui/Panels/VideoPanel.cpp:323 msgid "Framelimiter" msgstr "Limiter Klatek Animacji" @@ -2682,3 +2671,12 @@ msgid "" msgstr "" "Rozszerzenia %s nie znalezione. Recompilator microVU wymaga procesora " "obsługującego rozszerzenia MMX, SSE oraz SSE2." + +#~ msgid "mVU Block Hack" +#~ msgstr "mVU Block Hack" + +#~ msgid "" +#~ "Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." +#~ msgstr "" +#~ "Dobre przyspieszenie i duża kompatybilność; może powodować błędy grafiki, " +#~ "SPS, itd..." diff --git a/locales/pt_BR/pcsx2_Iconized.po b/locales/pt_BR/pcsx2_Iconized.po index 4f8706b00..2284086e7 100644 --- a/locales/pt_BR/pcsx2_Iconized.po +++ b/locales/pt_BR/pcsx2_Iconized.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.7\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-09-28 20:27+0200\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: 2011-09-11 23:09-0300\n" "Last-Translator: Rafael Ferreira \n" "Language-Team: \n" @@ -31,7 +31,7 @@ msgstr "" "virtual necessários já foram reservados para outros processos, serviços ou " "DLLs." -#: pcsx2/CDVD/CDVD.cpp:385 +#: pcsx2/CDVD/CDVD.cpp:390 msgid "!Notice:PsxDisc" msgstr "" "Discos de jogos de Playstation não têm suporte no PCSX2. Se você quiser " @@ -476,21 +476,14 @@ msgstr "" "EmotionEngine. Maiores valores aumentam o número de ciclos roubados do EE " "para cada micro-programa VU que o jogo roda." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:172 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "!ContextTip:Speedhacks:vuFlagHack" msgstr "" "Atualiza Sinalizadores de Estado somente nos blocos que vão ler eles, ao " "contrário de de o tempo todo. Isso é seguro na maioria do tempo, e o Super " "VU faz coisa semelhante por padrão." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:177 -msgid "!ContextTip:Speedhacks:vuBlockHack" -msgstr "" -"Presume que num futuro bem distante os blocos não vão precisar dos dados de " -"instâncias de sinalizadores antigos. Isso pode ser bem seguro. Não se sabe " -"se isso quebra algum jogo..." - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:182 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:174 msgid "!ContextTip:Speedhacks:vuThread" msgstr "" "Executa VU1 em uma thread própria (somente microVU1). Em geral, é uma " @@ -499,7 +492,7 @@ msgstr "" "caso de jogos limitados pelo GS, pode ser um atraso (especialmente em CPUs " "dual core)." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:203 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:195 msgid "!ContextTip:Speedhacks:INTC" msgstr "" "Esse hack funciona melhor para jogos que usam o registrador de INTC Status " @@ -507,7 +500,7 @@ msgstr "" "Jogos que não usam esse método de vsync vão aproveitar um pouco ou nada de " "aceleração desse hack." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:208 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 msgid "!ContextTip:Speedhacks:BIFC0" msgstr "" "Mirando primariamente o loop ocioso do EE no endereço 0x81Fc0 no kernel, " @@ -517,7 +510,7 @@ msgstr "" "avançamos para a vez do evento seguinte ou o fim da fatia de tempo do " "processador, seja qual for que vier a ocorrer primeiro." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:215 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:207 msgid "!ContextTip:Speedhacks:fastCDVD" msgstr "" "Verifica lista de compatibilidade de HDLoader para jogos conhecidos que " @@ -530,19 +523,19 @@ msgstr "" "Note que quando o Limitador de Frames está desabilitado, os modos Turbo e " "Câmera Lenta também não vão estar disponíveis." -#: pcsx2/gui/Panels/VideoPanel.cpp:223 +#: pcsx2/gui/Panels/VideoPanel.cpp:227 msgid "!Panel:Frameskip:Heading" msgstr "" "Nota: Por causa do design do PS2, frame skipping preciso não é possível. " "Ativar essa opção pode causar sérios erros gráficos em alguns jogos." -#: pcsx2/gui/Panels/VideoPanel.cpp:302 +#: pcsx2/gui/Panels/VideoPanel.cpp:306 msgid "!ContextTip:GS:SyncMTGS" msgstr "" "Habilite isso se você achar que a sincronização da thread MTGS está causando " "travamentos ou erros gráficos." -#: pcsx2/gui/Panels/VideoPanel.cpp:306 +#: pcsx2/gui/Panels/VideoPanel.cpp:310 msgid "!ContextTip:GS:DisableOutput" msgstr "" "Remove qualquer ruído padrão causado pela sobrecarga da thread MTGS ou da " @@ -567,6 +560,12 @@ msgstr "" "erro não é crítico, uma vez que o recompilador sVU está obsoleto, e, ao " "invés dele, você deveria usar o microVU. :)" +#~ msgid "!ContextTip:Speedhacks:vuBlockHack" +#~ msgstr "" +#~ "Presume que num futuro bem distante os blocos não vão precisar dos dados " +#~ "de instâncias de sinalizadores antigos. Isso pode ser bem seguro. Não se " +#~ "sabe se isso quebra algum jogo..." + #~ msgid "" #~ "The MTGS thread has become unresponsive while waiting for the GS plugin " #~ "to open." diff --git a/locales/pt_BR/pcsx2_Main.po b/locales/pt_BR/pcsx2_Main.po index 689525594..ca807db60 100644 --- a/locales/pt_BR/pcsx2_Main.po +++ b/locales/pt_BR/pcsx2_Main.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.7\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-09-28 20:27+0200\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: 2011-09-11 23:09-0300\n" "Last-Translator: Rafael Ferreira \n" "Language-Team: \n" @@ -202,7 +202,7 @@ msgstr "Plug-in de Cartão de Memória interno falhou em inicializar." msgid "Unloaded Plugin" msgstr "Plug-in descarregado" -#: pcsx2/SaveState.cpp:339 +#: pcsx2/SaveState.cpp:342 msgid "Cannot load savestate. It is of an unknown or unsupported version." msgstr "" "Não foi possível carregar o savestate. Ele é de uma versão desconhecida ou " @@ -382,31 +382,31 @@ msgstr "" "O savestate não foi armazenado corretamente. O arquivo temporário foi criado " "com sucesso, mas não pôde ser movido para seu destino de armazenamento." -#: pcsx2/gui/AppConfig.cpp:837 +#: pcsx2/gui/AppConfig.cpp:842 msgid "Safest" msgstr "Mais seguro" -#: pcsx2/gui/AppConfig.cpp:838 +#: pcsx2/gui/AppConfig.cpp:843 msgid "Safe (faster)" msgstr "Seguro (+ rápido)" -#: pcsx2/gui/AppConfig.cpp:839 +#: pcsx2/gui/AppConfig.cpp:844 msgid "Balanced" msgstr "Balanceado" -#: pcsx2/gui/AppConfig.cpp:840 +#: pcsx2/gui/AppConfig.cpp:845 msgid "Aggressive" msgstr "Agressivo" -#: pcsx2/gui/AppConfig.cpp:841 +#: pcsx2/gui/AppConfig.cpp:846 msgid "Aggressive plus" msgstr "Agressivo plus" -#: pcsx2/gui/AppConfig.cpp:842 +#: pcsx2/gui/AppConfig.cpp:847 msgid "Mostly Harmful" msgstr "Prejudicial" -#: pcsx2/gui/AppConfig.cpp:999 pcsx2/gui/AppConfig.cpp:1005 +#: pcsx2/gui/AppConfig.cpp:1007 pcsx2/gui/AppConfig.cpp:1013 msgid "Failed to overwrite existing settings file; permission was denied." msgstr "" "Falha em sobrescrever arquivo de configurações existentes; permissão negada." @@ -2461,21 +2461,10 @@ msgstr "" "[Recomendado]" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:166 -msgid "mVU Block Hack" -msgstr "Hack de Bloco mVU" - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 -msgid "" -"Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." -msgstr "" -"Boa Aceleração e Alta Compatibilidade; pode ocasionar gráficos ruins, SPS, " -"etc." - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "MTVU (Multi-Threaded microVU1)" msgstr "MTVU (Multi-Threaded microVU1)" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:170 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 msgid "" "Good Speedup and High Compatibility; may cause hanging... [Recommended if 3+ " "cores]" @@ -2483,15 +2472,15 @@ msgstr "" "Boa Aceleração e Alta Compatibilidade; pode causar travamento... " "[Recomendado para 3+ núcleos]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:183 msgid "Other Hacks" msgstr "Outros Hacks" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:193 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:185 msgid "Enable INTC Spin Detection" msgstr "Habilita Detecção de Rotação INTC" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:194 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:186 msgid "" "Huge speedup for some games, with almost no compatibility side effects. " "[Recommended]" @@ -2499,22 +2488,22 @@ msgstr "" "Imensa aceleração para alguns jogos, com quase nenhum efeito colateral. " "[Recomendado]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:196 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:188 msgid "Enable Wait Loop Detection" msgstr "Habilita Detecção de Loop de Espera" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:197 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:189 msgid "" "Moderate speedup for some games, with no known side effects. [Recommended]" msgstr "" "Moderada aceleração para alguns jogos, com nenhum efeito colateral conhecido " "[Recomendado]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:199 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 msgid "Enable fast CDVD" msgstr "Habilita CDVD rápido" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:192 msgid "Fast disc access, less loading times. [Not Recommended]" msgstr "Acesso rápido ao disco, menor tempo de carregamento. [Não recomendado]" @@ -2573,7 +2562,7 @@ msgstr "FPS" msgid "PAL Framerate:" msgstr "Framerate de PAL:" -#: pcsx2/gui/Panels/VideoPanel.cpp:162 +#: pcsx2/gui/Panels/VideoPanel.cpp:166 msgid "" "Error while parsing either NTSC or PAL framerate settings. Settings must be " "valid floating point numerics." @@ -2581,19 +2570,19 @@ msgstr "" "Erro enquanto analisava as configurações de taxas de frame de NTSC ou PAL. " "As cofigurações devem ser pontos flutuantes numéricos válidos." -#: pcsx2/gui/Panels/VideoPanel.cpp:180 +#: pcsx2/gui/Panels/VideoPanel.cpp:184 msgid "Disabled [default]" msgstr "Desabilitado [padrão]" -#: pcsx2/gui/Panels/VideoPanel.cpp:184 +#: pcsx2/gui/Panels/VideoPanel.cpp:188 msgid "Skip when on Turbo only (TAB to enable)" msgstr "Pular quando usar Turbo somente (TAB para habilitar)" -#: pcsx2/gui/Panels/VideoPanel.cpp:188 +#: pcsx2/gui/Panels/VideoPanel.cpp:192 msgid "Constant skipping" msgstr "Pular constantemente" -#: pcsx2/gui/Panels/VideoPanel.cpp:190 +#: pcsx2/gui/Panels/VideoPanel.cpp:194 msgid "" "Normal and Turbo limit rates skip frames. Slow motion mode will still " "disable frameskipping." @@ -2601,19 +2590,19 @@ msgstr "" "Taxa de limites Normal e Turbo aplicam Frame skipping. O modo câmera lenta " "vai manter desabilitado Frame skipping." -#: pcsx2/gui/Panels/VideoPanel.cpp:213 +#: pcsx2/gui/Panels/VideoPanel.cpp:217 msgid "Frames to Draw" msgstr "Frames a Serem Desenhados" -#: pcsx2/gui/Panels/VideoPanel.cpp:218 +#: pcsx2/gui/Panels/VideoPanel.cpp:222 msgid "Frames to Skip" msgstr "Frames a Serem Pulados" -#: pcsx2/gui/Panels/VideoPanel.cpp:294 +#: pcsx2/gui/Panels/VideoPanel.cpp:298 msgid "Use Synchronized MTGS" msgstr "Usar MTGS Sincronizado" -#: pcsx2/gui/Panels/VideoPanel.cpp:295 +#: pcsx2/gui/Panels/VideoPanel.cpp:299 msgid "" "For troubleshooting potential bugs in the MTGS only, as it is potentially " "very slow." @@ -2621,11 +2610,11 @@ msgstr "" "Somente para solucionar problemas de bugs em potencial no MTGS, pois ele é " "potencialmente muito lento." -#: pcsx2/gui/Panels/VideoPanel.cpp:298 +#: pcsx2/gui/Panels/VideoPanel.cpp:302 msgid "Disable all GS output" msgstr "Desabilita toda saída do GS" -#: pcsx2/gui/Panels/VideoPanel.cpp:299 +#: pcsx2/gui/Panels/VideoPanel.cpp:303 msgid "" "Completely disables all GS plugin activity; ideal for benchmarking EEcore " "components." @@ -2633,11 +2622,11 @@ msgstr "" "Desabilita completamente toda atividade do plug-in de GS; ideal para avaliar " "a performance dos componentes do EEcore." -#: pcsx2/gui/Panels/VideoPanel.cpp:316 +#: pcsx2/gui/Panels/VideoPanel.cpp:320 msgid "Frame Skipping" msgstr "Frame Skipping" -#: pcsx2/gui/Panels/VideoPanel.cpp:319 +#: pcsx2/gui/Panels/VideoPanel.cpp:323 msgid "Framelimiter" msgstr "Limitador de Frames" @@ -2725,3 +2714,12 @@ msgid "" msgstr "" "Extensões %s não encontradas. O microVU requer uma máquina com processador " "que tenha extensões MMX, SSE e SSE2." + +#~ msgid "mVU Block Hack" +#~ msgstr "Hack de Bloco mVU" + +#~ msgid "" +#~ "Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." +#~ msgstr "" +#~ "Boa Aceleração e Alta Compatibilidade; pode ocasionar gráficos ruins, " +#~ "SPS, etc." diff --git a/locales/ru_RU/pcsx2_Iconized.po b/locales/ru_RU/pcsx2_Iconized.po index d6b5d4dc5..c06daf708 100644 --- a/locales/ru_RU/pcsx2_Iconized.po +++ b/locales/ru_RU/pcsx2_Iconized.po @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-09-28 20:27+0200\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: 2011-04-25 01:25+0100\n" "Last-Translator: Bukhartsev Dmitriy \n" "Language-Team: Kein \n" @@ -26,7 +26,7 @@ msgstr "" "В вашей системе недостаточно виртуальной памяти, либо же, доступное адресное " "пространство уже занято другим процессом, службой или библиотеками." -#: pcsx2/CDVD/CDVD.cpp:385 +#: pcsx2/CDVD/CDVD.cpp:390 msgid "!Notice:PsxDisc" msgstr "" "Эмулятор PCSX2 не поддерживает игры от PlayStation. Если вы желаете " @@ -467,21 +467,14 @@ msgstr "" "EmotionEngine. Более высокое значение хака увеличивает количество циклов, " "которые будут \"позаимствованы\" у EE для обработки микропрограмм VU." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:172 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "!ContextTip:Speedhacks:vuFlagHack" msgstr "" "Обновляет флаги состояния только на тех блоках, которые будут читать данные " "флаги (вместо постоянного обновления всех блоков). Вполне безопасный хак, " "SuperVU-рекомпилятор делает нечто подобное по-умолчанию." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:177 -msgid "!ContextTip:Speedhacks:vuBlockHack" -msgstr "" -"Предугадывает, какие блоки микропрограмм не будут читать данные флагов в " -"обозримом будущем. Неизвестно, провоцирует ли это какие-либо проблемы в " -"каких-либо играх, посему, данный хак можно считать безопасным." - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:182 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:174 #, fuzzy msgid "!ContextTip:Speedhacks:vuThread" msgstr "" @@ -489,7 +482,7 @@ msgstr "" "дополнительных Min/Max-операций при просчете логики. \"Ломает\" Gran Turismo " "4 и Tekken 5. Возможно что-то еще." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:203 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:195 msgid "!ContextTip:Speedhacks:INTC" msgstr "" "Данный хак лучше всего применять для игр которые используют регистрацию " @@ -497,7 +490,7 @@ msgstr "" "не использующие 3D. Все остальные игры либо не получат никакого ускорения, " "либо оно будет чрезвычайно мало." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:208 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 msgid "!ContextTip:Speedhacks:BIFC0" msgstr "" "Изначально нацеленный на пустые циклы EE-рекомпилятора по адресу ядра " @@ -511,7 +504,7 @@ msgstr "" "событию или\n" "вообще к концу процессорного интервала." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:215 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:207 msgid "!ContextTip:Speedhacks:fastCDVD" msgstr "" "Для получения списка игр, которые испытывают проблемы при использовании " @@ -522,20 +515,20 @@ msgstr "" msgid "!ContextTip:Framelimiter:Disable" msgstr "Отключение лимита кадров отключит так же и Turbo-/Slowmotion-режимы." -#: pcsx2/gui/Panels/VideoPanel.cpp:223 +#: pcsx2/gui/Panels/VideoPanel.cpp:227 msgid "!Panel:Frameskip:Heading" msgstr "" "Примечание: ввиду особенностей архитектуры аппаратной части PS2, аккуратный " "пропуск кадров невозможен в принципе. Поэтому, его активация может " "спровоцировать появление графических артефактов в некоторых играх." -#: pcsx2/gui/Panels/VideoPanel.cpp:302 +#: pcsx2/gui/Panels/VideoPanel.cpp:306 msgid "!ContextTip:GS:SyncMTGS" msgstr "" "Включайте данную опцию только в том случае, если вы думаете что " "синхронизация потоков MTGS приводит к вылетам или графическим артефактам." -#: pcsx2/gui/Panels/VideoPanel.cpp:306 +#: pcsx2/gui/Panels/VideoPanel.cpp:310 msgid "!ContextTip:GS:DisableOutput" msgstr "" "Отключает обработку всех GS-данных, тем самым убирая возможный замедляющий " @@ -561,6 +554,12 @@ msgstr "" "стоит расстраиваться, ведь SuperVU устарел и вы всегда можете выбрать " "\"новый и блестящий\" microVU :P" +#~ msgid "!ContextTip:Speedhacks:vuBlockHack" +#~ msgstr "" +#~ "Предугадывает, какие блоки микропрограмм не будут читать данные флагов в " +#~ "обозримом будущем. Неизвестно, провоцирует ли это какие-либо проблемы в " +#~ "каких-либо играх, посему, данный хак можно считать безопасным." + #~ msgid "No reason given." #~ msgstr "Причина неизвестна." diff --git a/locales/ru_RU/pcsx2_Main.po b/locales/ru_RU/pcsx2_Main.po index d684b1d01..893a04dc7 100644 --- a/locales/ru_RU/pcsx2_Main.po +++ b/locales/ru_RU/pcsx2_Main.po @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-09-28 20:27+0200\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: 2011-04-25 19:40+0100\n" "Last-Translator: Bukhartsev Dmitriy \n" "Language-Team: Kein \n" @@ -197,7 +197,7 @@ msgstr "Ошибка инициализации встроенного плаг msgid "Unloaded Plugin" msgstr "Выгруженный плагин" -#: pcsx2/SaveState.cpp:339 +#: pcsx2/SaveState.cpp:342 msgid "Cannot load savestate. It is of an unknown or unsupported version." msgstr "" "Ошибка загрузки быстрого сохранения. Его версия неизвестна или не " @@ -370,31 +370,31 @@ msgstr "" "вполне успешно, но по каким-то причинам он не может быть перемещен в пункт " "назначения." -#: pcsx2/gui/AppConfig.cpp:837 +#: pcsx2/gui/AppConfig.cpp:842 msgid "Safest" msgstr "Очень безопасно" -#: pcsx2/gui/AppConfig.cpp:838 +#: pcsx2/gui/AppConfig.cpp:843 msgid "Safe (faster)" msgstr "Безопасно (и быстрее)" -#: pcsx2/gui/AppConfig.cpp:839 +#: pcsx2/gui/AppConfig.cpp:844 msgid "Balanced" msgstr "Сбалансировано" -#: pcsx2/gui/AppConfig.cpp:840 +#: pcsx2/gui/AppConfig.cpp:845 msgid "Aggressive" msgstr "Агрессивно" -#: pcsx2/gui/AppConfig.cpp:841 +#: pcsx2/gui/AppConfig.cpp:846 msgid "Aggressive plus" msgstr "Более агрессивно!" -#: pcsx2/gui/AppConfig.cpp:842 +#: pcsx2/gui/AppConfig.cpp:847 msgid "Mostly Harmful" msgstr "В большинстве случаев губительно..." -#: pcsx2/gui/AppConfig.cpp:999 pcsx2/gui/AppConfig.cpp:1005 +#: pcsx2/gui/AppConfig.cpp:1007 pcsx2/gui/AppConfig.cpp:1013 msgid "Failed to overwrite existing settings file; permission was denied." msgstr "Ошибка прав доступа при перезаписи текущего файла настроек." @@ -2446,22 +2446,10 @@ msgstr "" "[рекомендуется]" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:166 -msgid "mVU Block Hack" -msgstr "mVU Block Hack" - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 -#, fuzzy -msgid "" -"Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." -msgstr "" -"Неплохое ускорение и вполне неплохая совместимость. Возможно появление " -"графического \"мусора\", черного экрана, выпадающих полигонов и т.п." - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "MTVU (Multi-Threaded microVU1)" msgstr "" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:170 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 #, fuzzy msgid "" "Good Speedup and High Compatibility; may cause hanging... [Recommended if 3+ " @@ -2471,15 +2459,15 @@ msgstr "" "графического \"мусора\", черного экрана, выпадающих полигонов и т.п. " "[рекомендуется]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:183 msgid "Other Hacks" msgstr "Другие хаки" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:193 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:185 msgid "Enable INTC Spin Detection" msgstr "Включить INTC Spin Detection" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:194 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:186 msgid "" "Huge speedup for some games, with almost no compatibility side effects. " "[Recommended]" @@ -2487,22 +2475,22 @@ msgstr "" "Серьезное повышение производительности и почти без каких-либо побочных " "эффектов. [рекомендуется]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:196 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:188 msgid "Enable Wait Loop Detection" msgstr "Включить Wait Loop Detection" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:197 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:189 msgid "" "Moderate speedup for some games, with no known side effects. [Recommended]" msgstr "" "Неплохое ускорение некоторых игр без каких-либо побочных эффектов. " "[рекомендуется]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:199 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 msgid "Enable fast CDVD" msgstr "Включить fast CDVD" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:192 msgid "Fast disc access, less loading times. [Not Recommended]" msgstr "Ускоряет доступ к диску, уменьшает время загрузки. [не рекомендуется]" @@ -2559,7 +2547,7 @@ msgstr "FPS" msgid "PAL Framerate:" msgstr "Лимит кадров для PAL-игр" -#: pcsx2/gui/Panels/VideoPanel.cpp:162 +#: pcsx2/gui/Panels/VideoPanel.cpp:166 msgid "" "Error while parsing either NTSC or PAL framerate settings. Settings must be " "valid floating point numerics." @@ -2567,19 +2555,19 @@ msgstr "" "Возникла ошибка при чтении настроек частот кадров или NTSC или PAL. " "Настройки должны быть действительными числами с плавающей точкой." -#: pcsx2/gui/Panels/VideoPanel.cpp:180 +#: pcsx2/gui/Panels/VideoPanel.cpp:184 msgid "Disabled [default]" msgstr "Отключен (по умолчанию)" -#: pcsx2/gui/Panels/VideoPanel.cpp:184 +#: pcsx2/gui/Panels/VideoPanel.cpp:188 msgid "Skip when on Turbo only (TAB to enable)" msgstr "Пропускать только в режиме ускорения (TAB для включения)" -#: pcsx2/gui/Panels/VideoPanel.cpp:188 +#: pcsx2/gui/Panels/VideoPanel.cpp:192 msgid "Constant skipping" msgstr "Постоянный пропуск" -#: pcsx2/gui/Panels/VideoPanel.cpp:190 +#: pcsx2/gui/Panels/VideoPanel.cpp:194 msgid "" "Normal and Turbo limit rates skip frames. Slow motion mode will still " "disable frameskipping." @@ -2587,19 +2575,19 @@ msgstr "" "Normal- и Turbo-режимы позволяют пропуск кадров. Slowmotion-режим отключает " "любой пропуск кадров." -#: pcsx2/gui/Panels/VideoPanel.cpp:213 +#: pcsx2/gui/Panels/VideoPanel.cpp:217 msgid "Frames to Draw" msgstr "кол-во кадров для прорисовки" -#: pcsx2/gui/Panels/VideoPanel.cpp:218 +#: pcsx2/gui/Panels/VideoPanel.cpp:222 msgid "Frames to Skip" msgstr "кол-во кадров для пропуска" -#: pcsx2/gui/Panels/VideoPanel.cpp:294 +#: pcsx2/gui/Panels/VideoPanel.cpp:298 msgid "Use Synchronized MTGS" msgstr "Использовать синхронизацию MTGS" -#: pcsx2/gui/Panels/VideoPanel.cpp:295 +#: pcsx2/gui/Panels/VideoPanel.cpp:299 msgid "" "For troubleshooting potential bugs in the MTGS only, as it is potentially " "very slow." @@ -2607,11 +2595,11 @@ msgstr "" "Только для поиска потенциальных багов и неисправностей в MTGS, так как " "(потенциально) это слишком медленно" -#: pcsx2/gui/Panels/VideoPanel.cpp:298 +#: pcsx2/gui/Panels/VideoPanel.cpp:302 msgid "Disable all GS output" msgstr "Отключить вывод GS-данных." -#: pcsx2/gui/Panels/VideoPanel.cpp:299 +#: pcsx2/gui/Panels/VideoPanel.cpp:303 msgid "" "Completely disables all GS plugin activity; ideal for benchmarking EEcore " "components." @@ -2619,11 +2607,11 @@ msgstr "" "Сводит на ноль всю активность GS плагина. Идеально для тестирования " "компонентов EE ядра." -#: pcsx2/gui/Panels/VideoPanel.cpp:316 +#: pcsx2/gui/Panels/VideoPanel.cpp:320 msgid "Frame Skipping" msgstr "Пропуск кадров" -#: pcsx2/gui/Panels/VideoPanel.cpp:319 +#: pcsx2/gui/Panels/VideoPanel.cpp:323 msgid "Framelimiter" msgstr "Лимит кадров" @@ -2711,6 +2699,16 @@ msgstr "" "Расширение %s не обнаружено. microVU-рекомпилятору необходим процессор с " "поддержкой инструкций MMX, SSE, и SSE2." +#~ msgid "mVU Block Hack" +#~ msgstr "mVU Block Hack" + +#, fuzzy +#~ msgid "" +#~ "Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." +#~ msgstr "" +#~ "Неплохое ускорение и вполне неплохая совместимость. Возможно появление " +#~ "графического \"мусора\", черного экрана, выпадающих полигонов и т.п." + #~ msgid "!ContextTip:ChangingNTFS" #~ msgstr "" #~ "Режим NTFS-компрессии может быть изменен в любой момент времени через " diff --git a/locales/sv_SE/pcsx2_Iconized.po b/locales/sv_SE/pcsx2_Iconized.po index 7559d4a7a..401422ab3 100644 --- a/locales/sv_SE/pcsx2_Iconized.po +++ b/locales/sv_SE/pcsx2_Iconized.po @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-11-16 20:16+0100\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: 2011-11-16 12:51+0100\n" "Last-Translator: Georg Ronnert \n" "Language-Team: \n" @@ -28,7 +28,7 @@ msgstr "" "virtuella minnestilldelningen redan blivit reserverat av andra processer, " "tjänster, eller DLL'er." -#: pcsx2/CDVD/CDVD.cpp:385 +#: pcsx2/CDVD/CDVD.cpp:390 msgid "!Notice:PsxDisc" msgstr "" "Playstation speldiskar stödjes inte av PCSX2. Om Ni vill emulera PSX spel \n" @@ -488,22 +488,14 @@ msgstr "" "Högre värden ökar antalet cykler som stjäls från EE'n för varje VU-" "microprogram spelt kör." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:172 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "!ContextTip:Speedhacks:vuFlagHack" msgstr "" "Uppdaterar endast Statusflaggor för block som kommer att läsa dem, istället " "för alltid. \n" "Detta är för det mesta säkert, och Super-VU gör något liknande som standard." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:177 -msgid "!ContextTip:Speedhacks:vuBlockHack" -msgstr "" -"Förmodar att väldigt långt in i framtiden så kommer block inte behöva " -"gammelflagg-instansdata. \n" -"Detta borde vara rätt säkert. Det är okänt ifall detta har sönder något " -"spel..." - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:182 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:174 msgid "!ContextTip:Speedhacks:vuThread" msgstr "" "Kör VU1 i dess egna tråd (endast microVU1). I allmänhet en uppsnabbning för " @@ -512,7 +504,7 @@ msgstr "" "Vad gäller GS-begränsade spel, kan en nedbromsning förekomma (särskilt hos " "dubbelkärniga CPU'er)." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:203 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:195 msgid "!ContextTip:Speedhacks:INTC" msgstr "" "Denna fix fungerar bäst för spel som använder INTC-statusregistret för att " @@ -521,7 +513,7 @@ msgstr "" "Spel som inte använder denna Vsync-metod kommer på sin höjd att få en liten " "uppsnabbning av denna fix." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:208 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 msgid "!ContextTip:Speedhacks:BIFC0" msgstr "" "I första hand inriktat på EE tomgångs-loop hos adress 0x81FC0 i kärnan, " @@ -533,7 +525,7 @@ msgstr "" "avancerar vi till tiden för nästa händelse eller till slutet av processorns " "tidskvantum, vilket som än kommer först." -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:215 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:207 msgid "!ContextTip:Speedhacks:fastCDVD" msgstr "" "Kolla HDLaddar-förenlighetslistan för spel som till vetskap kommer till " @@ -547,20 +539,20 @@ msgstr "" "lägena \n" "inte att vara tillgängliga heller." -#: pcsx2/gui/Panels/VideoPanel.cpp:223 +#: pcsx2/gui/Panels/VideoPanel.cpp:227 msgid "!Panel:Frameskip:Heading" msgstr "" "Bemärk: Till följd av PS2 hårdvaruutformning så är precist bildöverhoppande " "omöjligt. \n" "Att tillämpa det kan orsaka rejäla grafikfel hos vissa spel." -#: pcsx2/gui/Panels/VideoPanel.cpp:302 +#: pcsx2/gui/Panels/VideoPanel.cpp:306 msgid "!ContextTip:GS:SyncMTGS" msgstr "" "Tillämpa detta ifall Ni tror att MTGS-trådsync orsakar braker eller grafiska " "fel." -#: pcsx2/gui/Panels/VideoPanel.cpp:306 +#: pcsx2/gui/Panels/VideoPanel.cpp:310 msgid "!ContextTip:GS:DisableOutput" msgstr "" "Tar bort allt norm-oljud orsakat av MTGS-trådens eler GPU'ns överdrag. Denna " @@ -588,6 +580,13 @@ msgstr "" "eftersom sVU är föråldrad, \n" "och följdaktligen borde Ni använda Er av microVU istället." +#~ msgid "!ContextTip:Speedhacks:vuBlockHack" +#~ msgstr "" +#~ "Förmodar att väldigt långt in i framtiden så kommer block inte behöva " +#~ "gammelflagg-instansdata. \n" +#~ "Detta borde vara rätt säkert. Det är okänt ifall detta har sönder något " +#~ "spel..." + #~ msgid "!Notice:Mcd:Overwrite" #~ msgstr "" #~ "Detta kommer att kopiera innehållet i minneskortet i sockel %u till " diff --git a/locales/sv_SE/pcsx2_Main.po b/locales/sv_SE/pcsx2_Main.po index 75583029c..7744ba3f2 100644 --- a/locales/sv_SE/pcsx2_Main.po +++ b/locales/sv_SE/pcsx2_Main.po @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-11-16 20:15+0100\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: 2011-11-16 12:28+0100\n" "Last-Translator: Georg Ronnert \n" "Language-Team: \n" @@ -196,7 +196,7 @@ msgstr "" msgid "Unloaded Plugin" msgstr "Oladdat insticksprogram" -#: pcsx2/SaveState.cpp:339 +#: pcsx2/SaveState.cpp:342 msgid "Cannot load savestate. It is of an unknown or unsupported version." msgstr "" "Kan inte ladda sparpunkten. Den är av en okänd eller ostödjande version." @@ -359,31 +359,31 @@ msgstr "" "Sparpunkten blev inte ordentligt sparad. Den tillfälliga filen skapades " "framgångsrikt med kunde inte flyttas till sin slutliga viloplats." -#: pcsx2/gui/AppConfig.cpp:837 +#: pcsx2/gui/AppConfig.cpp:842 msgid "Safest" msgstr "Säkrast" -#: pcsx2/gui/AppConfig.cpp:838 +#: pcsx2/gui/AppConfig.cpp:843 msgid "Safe (faster)" msgstr "Säkert (snabare)" -#: pcsx2/gui/AppConfig.cpp:839 +#: pcsx2/gui/AppConfig.cpp:844 msgid "Balanced" msgstr "Balanserat" -#: pcsx2/gui/AppConfig.cpp:840 +#: pcsx2/gui/AppConfig.cpp:845 msgid "Aggressive" msgstr "Aggressivt" -#: pcsx2/gui/AppConfig.cpp:841 +#: pcsx2/gui/AppConfig.cpp:846 msgid "Aggressive plus" msgstr "Aggressivt plus" -#: pcsx2/gui/AppConfig.cpp:842 +#: pcsx2/gui/AppConfig.cpp:847 msgid "Mostly Harmful" msgstr "Mest Skadligt" -#: pcsx2/gui/AppConfig.cpp:999 pcsx2/gui/AppConfig.cpp:1005 +#: pcsx2/gui/AppConfig.cpp:1007 pcsx2/gui/AppConfig.cpp:1013 msgid "Failed to overwrite existing settings file; permission was denied." msgstr "" "Misslyckades att skriva över befintlig inställningsfil; tillstånd nekades." @@ -2404,20 +2404,10 @@ msgstr "" "[Rekommenderas]" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:166 -msgid "mVU Block Hack" -msgstr "mVU Block Hack" - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 -msgid "" -"Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." -msgstr "" -"Bra Uppsnabbning och Hög Förenlighet; kan orsaka dålig grafik, SPS, etc..." - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "MTVU (Multi-Threaded microVU1)" msgstr "MTVU (Multi-Trådad microVU1)" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:170 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 msgid "" "Good Speedup and High Compatibility; may cause hanging... [Recommended if 3+ " "cores]" @@ -2425,15 +2415,15 @@ msgstr "" "Bra Uppsnabbning och Hög Förenlighet; kan orsaka att det hänger sig... " "[Rekommenderas för 3+ kärnor]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:183 msgid "Other Hacks" msgstr "Andra Hackisar" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:193 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:185 msgid "Enable INTC Spin Detection" msgstr "Möjliggör INTC Rotationsuppfattning" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:194 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:186 msgid "" "Huge speedup for some games, with almost no compatibility side effects. " "[Recommended]" @@ -2441,22 +2431,22 @@ msgstr "" "Enorm uppsnabbning för vissa spel, med nästan inga förenlighetsbieffekter. " "[Rekommenderas]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:196 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:188 msgid "Enable Wait Loop Detection" msgstr "Möjliggör Vänta Loop Uppfattning" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:197 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:189 msgid "" "Moderate speedup for some games, with no known side effects. [Recommended]" msgstr "" "Måttlig uppsnabbning för vissa spel, med inga kända bieffekter. " "[Rekommenderas]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:199 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 msgid "Enable fast CDVD" msgstr "Möjliggör snabb CDVD" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:192 msgid "Fast disc access, less loading times. [Not Recommended]" msgstr "Snabb disktillgång, färre laddningsgånger. [Rekommenderas Ej]" @@ -2515,7 +2505,7 @@ msgstr "FPS" msgid "PAL Framerate:" msgstr "PAL Bildfrekvens:" -#: pcsx2/gui/Panels/VideoPanel.cpp:162 +#: pcsx2/gui/Panels/VideoPanel.cpp:166 msgid "" "Error while parsing either NTSC or PAL framerate settings. Settings must be " "valid floating point numerics." @@ -2523,19 +2513,19 @@ msgstr "" "Fel under tolkning av antingen NTSC eller PAL bildfrekvensinstälningar. " "Inställningarna måste vara giltliga flyttalsnummer." -#: pcsx2/gui/Panels/VideoPanel.cpp:180 +#: pcsx2/gui/Panels/VideoPanel.cpp:184 msgid "Disabled [default]" msgstr "Förhindrad [förval]" -#: pcsx2/gui/Panels/VideoPanel.cpp:184 +#: pcsx2/gui/Panels/VideoPanel.cpp:188 msgid "Skip when on Turbo only (TAB to enable)" msgstr "Hoppa över endast vid Turbo (TAB för att möjliggöra)" -#: pcsx2/gui/Panels/VideoPanel.cpp:188 +#: pcsx2/gui/Panels/VideoPanel.cpp:192 msgid "Constant skipping" msgstr "Konstant överhoppande" -#: pcsx2/gui/Panels/VideoPanel.cpp:190 +#: pcsx2/gui/Panels/VideoPanel.cpp:194 msgid "" "Normal and Turbo limit rates skip frames. Slow motion mode will still " "disable frameskipping." @@ -2543,19 +2533,19 @@ msgstr "" "Normal och Turbobegränsad beräknad bildöverhoppning. Ultrarapidsläge " "förhindrar fortfarande bildöverhoppning." -#: pcsx2/gui/Panels/VideoPanel.cpp:213 +#: pcsx2/gui/Panels/VideoPanel.cpp:217 msgid "Frames to Draw" msgstr "Bilder att Rita" -#: pcsx2/gui/Panels/VideoPanel.cpp:218 +#: pcsx2/gui/Panels/VideoPanel.cpp:222 msgid "Frames to Skip" msgstr "Bilder att Hoppa över" -#: pcsx2/gui/Panels/VideoPanel.cpp:294 +#: pcsx2/gui/Panels/VideoPanel.cpp:298 msgid "Use Synchronized MTGS" msgstr "Använd Synkroniserad MTGS" -#: pcsx2/gui/Panels/VideoPanel.cpp:295 +#: pcsx2/gui/Panels/VideoPanel.cpp:299 msgid "" "For troubleshooting potential bugs in the MTGS only, as it is potentially " "very slow." @@ -2563,11 +2553,11 @@ msgstr "" "Enbart för att problemlösa eventuella fel inom \n" "MTGS, eftersom det möjligen är mycket långsamt." -#: pcsx2/gui/Panels/VideoPanel.cpp:298 +#: pcsx2/gui/Panels/VideoPanel.cpp:302 msgid "Disable all GS output" msgstr "Förhindra all GS utgång" -#: pcsx2/gui/Panels/VideoPanel.cpp:299 +#: pcsx2/gui/Panels/VideoPanel.cpp:303 msgid "" "Completely disables all GS plugin activity; ideal for benchmarking EEcore " "components." @@ -2575,11 +2565,11 @@ msgstr "" "Förhindrar helt all GS-insticksprogramsaktivitet; \n" "idealt som utgångspunkt för EE-kärnkomponenter." -#: pcsx2/gui/Panels/VideoPanel.cpp:316 +#: pcsx2/gui/Panels/VideoPanel.cpp:320 msgid "Frame Skipping" msgstr "Bildöverhoppande" -#: pcsx2/gui/Panels/VideoPanel.cpp:319 +#: pcsx2/gui/Panels/VideoPanel.cpp:323 msgid "Framelimiter" msgstr "Bildbegränsare" @@ -2663,6 +2653,14 @@ msgstr "" "%s Förlängningar ej funna. microVU kräven en värd-CPU med MMX, SSE, och SSE2 " "förlängningar." +#~ msgid "mVU Block Hack" +#~ msgstr "mVU Block Hack" + +#~ msgid "" +#~ "Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." +#~ msgstr "" +#~ "Bra Uppsnabbning och Hög Förenlighet; kan orsaka dålig grafik, SPS, etc..." + #~ msgid "Enable game fixes" #~ msgstr "Möjliggör spelfixar" diff --git a/locales/templates/pcsx2_Iconized.pot b/locales/templates/pcsx2_Iconized.pot index 1ebf0ea3d..c02324794 100644 --- a/locales/templates/pcsx2_Iconized.pot +++ b/locales/templates/pcsx2_Iconized.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-11-16 20:17+0100\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -26,7 +26,7 @@ msgstr "" msgid "!Notice:VirtualMemoryMap" msgstr "" -#: pcsx2/CDVD/CDVD.cpp:385 +#: pcsx2/CDVD/CDVD.cpp:390 msgid "!Notice:PsxDisc" msgstr "" @@ -270,27 +270,23 @@ msgstr "" msgid "!ContextTip:Speedhacks:VUCycleStealing Slider" msgstr "" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:172 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "!ContextTip:Speedhacks:vuFlagHack" msgstr "" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:177 -msgid "!ContextTip:Speedhacks:vuBlockHack" -msgstr "" - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:182 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:174 msgid "!ContextTip:Speedhacks:vuThread" msgstr "" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:203 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:195 msgid "!ContextTip:Speedhacks:INTC" msgstr "" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:208 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 msgid "!ContextTip:Speedhacks:BIFC0" msgstr "" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:215 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:207 msgid "!ContextTip:Speedhacks:fastCDVD" msgstr "" @@ -298,15 +294,15 @@ msgstr "" msgid "!ContextTip:Framelimiter:Disable" msgstr "" -#: pcsx2/gui/Panels/VideoPanel.cpp:223 +#: pcsx2/gui/Panels/VideoPanel.cpp:227 msgid "!Panel:Frameskip:Heading" msgstr "" -#: pcsx2/gui/Panels/VideoPanel.cpp:302 +#: pcsx2/gui/Panels/VideoPanel.cpp:306 msgid "!ContextTip:GS:SyncMTGS" msgstr "" -#: pcsx2/gui/Panels/VideoPanel.cpp:306 +#: pcsx2/gui/Panels/VideoPanel.cpp:310 msgid "!ContextTip:GS:DisableOutput" msgstr "" diff --git a/locales/templates/pcsx2_Main.pot b/locales/templates/pcsx2_Main.pot index 80ed6960d..eb4e0a280 100644 --- a/locales/templates/pcsx2_Main.pot +++ b/locales/templates/pcsx2_Main.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-11-16 20:17+0100\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -148,7 +148,7 @@ msgstr "" msgid "Unloaded Plugin" msgstr "" -#: pcsx2/SaveState.cpp:339 +#: pcsx2/SaveState.cpp:342 msgid "Cannot load savestate. It is of an unknown or unsupported version." msgstr "" @@ -292,31 +292,31 @@ msgstr "" msgid "The savestate was not properly saved. The temporary file was created successfully but could not be moved to its final resting place." msgstr "" -#: pcsx2/gui/AppConfig.cpp:837 +#: pcsx2/gui/AppConfig.cpp:842 msgid "Safest" msgstr "" -#: pcsx2/gui/AppConfig.cpp:838 +#: pcsx2/gui/AppConfig.cpp:843 msgid "Safe (faster)" msgstr "" -#: pcsx2/gui/AppConfig.cpp:839 +#: pcsx2/gui/AppConfig.cpp:844 msgid "Balanced" msgstr "" -#: pcsx2/gui/AppConfig.cpp:840 +#: pcsx2/gui/AppConfig.cpp:845 msgid "Aggressive" msgstr "" -#: pcsx2/gui/AppConfig.cpp:841 +#: pcsx2/gui/AppConfig.cpp:846 msgid "Aggressive plus" msgstr "" -#: pcsx2/gui/AppConfig.cpp:842 +#: pcsx2/gui/AppConfig.cpp:847 msgid "Mostly Harmful" msgstr "" -#: pcsx2/gui/AppConfig.cpp:999 pcsx2/gui/AppConfig.cpp:1005 +#: pcsx2/gui/AppConfig.cpp:1007 pcsx2/gui/AppConfig.cpp:1013 msgid "Failed to overwrite existing settings file; permission was denied." msgstr "" @@ -2184,46 +2184,38 @@ msgid "Good Speedup and High Compatibility; may cause bad graphics... [Recommend msgstr "" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:166 -msgid "mVU Block Hack" -msgstr "" - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 -msgid "Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." -msgstr "" - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "MTVU (Multi-Threaded microVU1)" msgstr "" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:170 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 msgid "Good Speedup and High Compatibility; may cause hanging... [Recommended if 3+ cores]" msgstr "" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:183 msgid "Other Hacks" msgstr "" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:193 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:185 msgid "Enable INTC Spin Detection" msgstr "" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:194 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:186 msgid "Huge speedup for some games, with almost no compatibility side effects. [Recommended]" msgstr "" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:196 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:188 msgid "Enable Wait Loop Detection" msgstr "" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:197 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:189 msgid "Moderate speedup for some games, with no known side effects. [Recommended]" msgstr "" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:199 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 msgid "Enable fast CDVD" msgstr "" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:192 msgid "Fast disc access, less loading times. [Not Recommended]" msgstr "" @@ -2275,55 +2267,55 @@ msgstr "" msgid "PAL Framerate:" msgstr "" -#: pcsx2/gui/Panels/VideoPanel.cpp:162 +#: pcsx2/gui/Panels/VideoPanel.cpp:166 msgid "Error while parsing either NTSC or PAL framerate settings. Settings must be valid floating point numerics." msgstr "" -#: pcsx2/gui/Panels/VideoPanel.cpp:180 +#: pcsx2/gui/Panels/VideoPanel.cpp:184 msgid "Disabled [default]" msgstr "" -#: pcsx2/gui/Panels/VideoPanel.cpp:184 +#: pcsx2/gui/Panels/VideoPanel.cpp:188 msgid "Skip when on Turbo only (TAB to enable)" msgstr "" -#: pcsx2/gui/Panels/VideoPanel.cpp:188 +#: pcsx2/gui/Panels/VideoPanel.cpp:192 msgid "Constant skipping" msgstr "" -#: pcsx2/gui/Panels/VideoPanel.cpp:190 +#: pcsx2/gui/Panels/VideoPanel.cpp:194 msgid "Normal and Turbo limit rates skip frames. Slow motion mode will still disable frameskipping." msgstr "" -#: pcsx2/gui/Panels/VideoPanel.cpp:213 +#: pcsx2/gui/Panels/VideoPanel.cpp:217 msgid "Frames to Draw" msgstr "" -#: pcsx2/gui/Panels/VideoPanel.cpp:218 +#: pcsx2/gui/Panels/VideoPanel.cpp:222 msgid "Frames to Skip" msgstr "" -#: pcsx2/gui/Panels/VideoPanel.cpp:294 +#: pcsx2/gui/Panels/VideoPanel.cpp:298 msgid "Use Synchronized MTGS" msgstr "" -#: pcsx2/gui/Panels/VideoPanel.cpp:295 +#: pcsx2/gui/Panels/VideoPanel.cpp:299 msgid "For troubleshooting potential bugs in the MTGS only, as it is potentially very slow." msgstr "" -#: pcsx2/gui/Panels/VideoPanel.cpp:298 +#: pcsx2/gui/Panels/VideoPanel.cpp:302 msgid "Disable all GS output" msgstr "" -#: pcsx2/gui/Panels/VideoPanel.cpp:299 +#: pcsx2/gui/Panels/VideoPanel.cpp:303 msgid "Completely disables all GS plugin activity; ideal for benchmarking EEcore components." msgstr "" -#: pcsx2/gui/Panels/VideoPanel.cpp:316 +#: pcsx2/gui/Panels/VideoPanel.cpp:320 msgid "Frame Skipping" msgstr "" -#: pcsx2/gui/Panels/VideoPanel.cpp:319 +#: pcsx2/gui/Panels/VideoPanel.cpp:323 msgid "Framelimiter" msgstr "" diff --git a/locales/tr_TR/pcsx2_Iconized.po b/locales/tr_TR/pcsx2_Iconized.po index d324e1f5a..5f0a7c44c 100644 --- a/locales/tr_TR/pcsx2_Iconized.po +++ b/locales/tr_TR/pcsx2_Iconized.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-09-28 20:27+0200\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: 2011-04-08 19:53+0200\n" "Last-Translator: PyramidHead \n" "Language-Team: Ceyhun Özgöç (PyramidHead) \n" @@ -27,7 +27,7 @@ msgstr "" msgid "!Notice:VirtualMemoryMap" msgstr "!Notice:VirtualMemoryMap" -#: pcsx2/CDVD/CDVD.cpp:385 +#: pcsx2/CDVD/CDVD.cpp:390 msgid "!Notice:PsxDisc" msgstr "!Notice:PsxDisc" @@ -273,28 +273,24 @@ msgstr "!ContextTip:Speedhacks:EECycleRate Slider" msgid "!ContextTip:Speedhacks:VUCycleStealing Slider" msgstr "!ContextTip:Speedhacks:VUCycleStealing Slider" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:172 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "!ContextTip:Speedhacks:vuFlagHack" msgstr "!ContextTip:Speedhacks:vuFlagHack" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:177 -msgid "!ContextTip:Speedhacks:vuBlockHack" -msgstr "!ContextTip:Speedhacks:vuBlockHack" - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:182 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:174 #, fuzzy msgid "!ContextTip:Speedhacks:vuThread" msgstr "!ContextTip:Speedhacks:vuMinMax" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:203 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:195 msgid "!ContextTip:Speedhacks:INTC" msgstr "!ContextTip:Speedhacks:INTC" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:208 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 msgid "!ContextTip:Speedhacks:BIFC0" msgstr "!ContextTip:Speedhacks:BIFC0" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:215 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:207 msgid "!ContextTip:Speedhacks:fastCDVD" msgstr "!ContextTip:Speedhacks:fastCDVD" @@ -302,15 +298,15 @@ msgstr "!ContextTip:Speedhacks:fastCDVD" msgid "!ContextTip:Framelimiter:Disable" msgstr "!ContextTip:Framelimiter:Disable" -#: pcsx2/gui/Panels/VideoPanel.cpp:223 +#: pcsx2/gui/Panels/VideoPanel.cpp:227 msgid "!Panel:Frameskip:Heading" msgstr "!Panel:Frameskip:Heading" -#: pcsx2/gui/Panels/VideoPanel.cpp:302 +#: pcsx2/gui/Panels/VideoPanel.cpp:306 msgid "!ContextTip:GS:SyncMTGS" msgstr "!ContextTip:GS:SyncMTGS" -#: pcsx2/gui/Panels/VideoPanel.cpp:306 +#: pcsx2/gui/Panels/VideoPanel.cpp:310 msgid "!ContextTip:GS:DisableOutput" msgstr "!ContextTip:GS:DisableOutput" @@ -322,6 +318,9 @@ msgstr "!Notice:HostVmReserve" msgid "!Notice:superVU:VirtualMemoryAlloc" msgstr "!Notice:superVU:VirtualMemoryAlloc" +#~ msgid "!ContextTip:Speedhacks:vuBlockHack" +#~ msgstr "!ContextTip:Speedhacks:vuBlockHack" + #~ msgid "No reason given." #~ msgstr "Sebep belirtilmemiş." diff --git a/locales/tr_TR/pcsx2_Main.po b/locales/tr_TR/pcsx2_Main.po index 82c02b6ea..c0febd4c7 100644 --- a/locales/tr_TR/pcsx2_Main.po +++ b/locales/tr_TR/pcsx2_Main.po @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-09-28 20:27+0200\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: 2011-04-09 16:40+0200\n" "Last-Translator: PyramidHead \n" "Language-Team: Ceyhun Özgöç (PyramidHead) \n" @@ -185,7 +185,7 @@ msgstr "Hafıza kartı eklentisi başlatılamadı." msgid "Unloaded Plugin" msgstr "Yüklenmemiş Eklenti" -#: pcsx2/SaveState.cpp:339 +#: pcsx2/SaveState.cpp:342 msgid "Cannot load savestate. It is of an unknown or unsupported version." msgstr "" "Kayıt konumu yüklenemiyor. Dosya bilinmeyen ya da desteklenmeyen bir sürüme " @@ -346,31 +346,31 @@ msgstr "" "Kayıt konumu doğru şekilde kaydedilemedi. Geçici dosya oluşturuldu fakat son " "kayıt işlemi tamamlanamadı." -#: pcsx2/gui/AppConfig.cpp:837 +#: pcsx2/gui/AppConfig.cpp:842 msgid "Safest" msgstr "En Güvenli" -#: pcsx2/gui/AppConfig.cpp:838 +#: pcsx2/gui/AppConfig.cpp:843 msgid "Safe (faster)" msgstr "Güvenli (daha hızlı)" -#: pcsx2/gui/AppConfig.cpp:839 +#: pcsx2/gui/AppConfig.cpp:844 msgid "Balanced" msgstr "Dengeli" -#: pcsx2/gui/AppConfig.cpp:840 +#: pcsx2/gui/AppConfig.cpp:845 msgid "Aggressive" msgstr "Agresif" -#: pcsx2/gui/AppConfig.cpp:841 +#: pcsx2/gui/AppConfig.cpp:846 msgid "Aggressive plus" msgstr "Daha Agresif" -#: pcsx2/gui/AppConfig.cpp:842 +#: pcsx2/gui/AppConfig.cpp:847 msgid "Mostly Harmful" msgstr "Çoğu Zaman Zararlı" -#: pcsx2/gui/AppConfig.cpp:999 pcsx2/gui/AppConfig.cpp:1005 +#: pcsx2/gui/AppConfig.cpp:1007 pcsx2/gui/AppConfig.cpp:1013 msgid "Failed to overwrite existing settings file; permission was denied." msgstr "Var olan dosya değiştirilemiyor; erişim engellendi." @@ -2372,22 +2372,10 @@ msgstr "" "neden olabilir [Önerilir]" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:166 -msgid "mVU Block Hack" -msgstr "mVU Block Hack" - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 -#, fuzzy -msgid "" -"Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." -msgstr "" -"Hızı oldukça artırır ve uyumluluğu yüksektir; görüntü ya da ses hatalarına " -"neden olabilir." - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "MTVU (Multi-Threaded microVU1)" msgstr "" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:170 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 #, fuzzy msgid "" "Good Speedup and High Compatibility; may cause hanging... [Recommended if 3+ " @@ -2396,35 +2384,35 @@ msgstr "" "Hızı oldukça artırır ve uyumluluğu yüksektir; görüntü ya da ses hatalarına " "neden olabilir [Önerilir]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:183 msgid "Other Hacks" msgstr "Diğer Hackler" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:193 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:185 msgid "Enable INTC Spin Detection" msgstr "INTC Spin Tanımlamasını Etkinleştir" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:194 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:186 msgid "" "Huge speedup for some games, with almost no compatibility side effects. " "[Recommended]" msgstr "" "Bazı oyunlarda hiçbir soruna yol açmadan büyük hız artışı sağlar. [Önerilir]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:196 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:188 msgid "Enable Wait Loop Detection" msgstr "Wait Loop Tanımlamasını Etkinleştir" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:197 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:189 msgid "" "Moderate speedup for some games, with no known side effects. [Recommended]" msgstr "Bazı oyunlarda hiçvir soruna yol açmadan hız artışı sağlar. [Önerilir]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:199 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 msgid "Enable fast CDVD" msgstr "Hızlı CDVD'yi etkinleştir" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:192 msgid "Fast disc access, less loading times. [Not Recommended]" msgstr "CD'ye daha hızlı ulaşarak yükleme süresini azaltır. [Önerilmez]" @@ -2482,7 +2470,7 @@ msgstr "FPS" msgid "PAL Framerate:" msgstr "PAL Kare hızı:" -#: pcsx2/gui/Panels/VideoPanel.cpp:162 +#: pcsx2/gui/Panels/VideoPanel.cpp:166 msgid "" "Error while parsing either NTSC or PAL framerate settings. Settings must be " "valid floating point numerics." @@ -2490,48 +2478,48 @@ msgstr "" "NTSC ya da PAL kare hızı ayarlarında hata. Ayarlar geçerli rakamlardan " "oluşmalı." -#: pcsx2/gui/Panels/VideoPanel.cpp:180 +#: pcsx2/gui/Panels/VideoPanel.cpp:184 msgid "Disabled [default]" msgstr "Devre dışı [varsayılan]" -#: pcsx2/gui/Panels/VideoPanel.cpp:184 +#: pcsx2/gui/Panels/VideoPanel.cpp:188 msgid "Skip when on Turbo only (TAB to enable)" msgstr "Yalnızca Turbo açıkken kare atla (TAB ile açın)" -#: pcsx2/gui/Panels/VideoPanel.cpp:188 +#: pcsx2/gui/Panels/VideoPanel.cpp:192 msgid "Constant skipping" msgstr "Sürekli kare atlama" -#: pcsx2/gui/Panels/VideoPanel.cpp:190 +#: pcsx2/gui/Panels/VideoPanel.cpp:194 msgid "" "Normal and Turbo limit rates skip frames. Slow motion mode will still " "disable frameskipping." msgstr "" "Normal ve Turbo kare atlar. Ağır çekim modu kare atlamayı devre dışı bırakır." -#: pcsx2/gui/Panels/VideoPanel.cpp:213 +#: pcsx2/gui/Panels/VideoPanel.cpp:217 msgid "Frames to Draw" msgstr "Çizilecek Kare Sayısı" -#: pcsx2/gui/Panels/VideoPanel.cpp:218 +#: pcsx2/gui/Panels/VideoPanel.cpp:222 msgid "Frames to Skip" msgstr "Atlanacak Kare Sayısı" -#: pcsx2/gui/Panels/VideoPanel.cpp:294 +#: pcsx2/gui/Panels/VideoPanel.cpp:298 msgid "Use Synchronized MTGS" msgstr "Senkronize MTGS Kullan" -#: pcsx2/gui/Panels/VideoPanel.cpp:295 +#: pcsx2/gui/Panels/VideoPanel.cpp:299 msgid "" "For troubleshooting potential bugs in the MTGS only, as it is potentially " "very slow." msgstr "MTGS hatalarını tespit etmek için. Çok yavaştır." -#: pcsx2/gui/Panels/VideoPanel.cpp:298 +#: pcsx2/gui/Panels/VideoPanel.cpp:302 msgid "Disable all GS output" msgstr "Tüm GS çıkışını devre dışı bırak" -#: pcsx2/gui/Panels/VideoPanel.cpp:299 +#: pcsx2/gui/Panels/VideoPanel.cpp:303 msgid "" "Completely disables all GS plugin activity; ideal for benchmarking EEcore " "components." @@ -2539,11 +2527,11 @@ msgstr "" "Tüm GS eklenti işlemlerini devre dışı bırakır; EEcore bileşenlerini test " "etmek için idealdir." -#: pcsx2/gui/Panels/VideoPanel.cpp:316 +#: pcsx2/gui/Panels/VideoPanel.cpp:320 msgid "Frame Skipping" msgstr "Kare Atlama" -#: pcsx2/gui/Panels/VideoPanel.cpp:319 +#: pcsx2/gui/Panels/VideoPanel.cpp:323 msgid "Framelimiter" msgstr "Kare Sınırlama" @@ -2628,6 +2616,16 @@ msgstr "" "%s Uzantıları bulunamıyor. microVU MMX, SSE ve SSE2 destekleyen bir işlemci " "gerektirir." +#~ msgid "mVU Block Hack" +#~ msgstr "mVU Block Hack" + +#, fuzzy +#~ msgid "" +#~ "Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." +#~ msgstr "" +#~ "Hızı oldukça artırır ve uyumluluğu yüksektir; görüntü ya da ses " +#~ "hatalarına neden olabilir." + #~ msgid "ISO mounting failed: PCSX2 is unable to identify the ISO image type." #~ msgstr "ISO yüklemesi başarısız: PCSX2 ISO dosyası türünü tanımlayamıyor." diff --git a/locales/zh_CN/pcsx2_Iconized.po b/locales/zh_CN/pcsx2_Iconized.po index 773b1501e..f2f491f59 100644 --- a/locales/zh_CN/pcsx2_Iconized.po +++ b/locales/zh_CN/pcsx2_Iconized.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-09-24 20:29+0800\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: 2011-08-13 16:51+0700\n" "Last-Translator: Wei Mingzhi \n" "Language-Team: \n" @@ -26,7 +26,7 @@ msgid "!Notice:VirtualMemoryMap" msgstr "" "没有足够的虚拟内存可用,或所需的虚拟内存映射已经被其它进程、服务或 DLL 保留。" -#: pcsx2/CDVD/CDVD.cpp:385 +#: pcsx2/CDVD/CDVD.cpp:390 msgid "!Notice:PsxDisc" msgstr "" "PCSX2 不支持 Playstation 1 游戏。如果您想模拟 PS1 游戏请下载一个 PS1 模拟器," @@ -390,39 +390,33 @@ msgstr "" "此选项控制 VU 单元从情感引擎挪用的时钟周期数目。较高数值将增加各个被游戏执行" "的 VU 微程序从 EE 挪用的周期数目。" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:172 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "!ContextTip:Speedhacks:vuFlagHack" msgstr "" "仅在标志位被读取时更新,而不是总是更新。此选项通常是安全的,Super VU 默认会以" "相似的方式处理。" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:177 -msgid "!ContextTip:Speedhacks:vuBlockHack" -msgstr "" -"假定未来的块不需要旧的标志实例数据。这应该是安全的。是否导致游戏出现问题仍然" -"未知。" - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:182 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:174 msgid "!ContextTip:Speedhacks:vuThread" msgstr "" "在单独的线程是运行 VU1 (仅限 microVU1)。通常在三核以上 CPU 中有提速效果。此选" "项对大多数游戏是安全的,但一部分游戏可能不兼容或导致没有响应。对于受限于 GS " "的游戏,可能会造成性能下降 (特别是在双核 CPU 上)。" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:203 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:195 msgid "!ContextTip:Speedhacks:INTC" msgstr "" "此选项对于使用 INTC 状态寄存器来等待垂直同步的游戏效果较好,包括一些主要的 " "3D RPG 游戏。对于不使用此方法的游戏没有提速效果。" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:208 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 msgid "!ContextTip:Speedhacks:BIFC0" msgstr "" "主要针对位于内核地址 0x81FC0 的 EE 空闲循环,此 Hack 试图检测循环体在一个另外" "的模拟单元计划的事件处理过程之前不保证产生相同结果的循环。在一次循环体执行之" "后,将下一事件的时间或处理器的时间片结束时间 (孰早) 做出更新。" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:215 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:207 msgid "!ContextTip:Speedhacks:fastCDVD" msgstr "" "请参看 HDLoader 兼容性列表以获取启用此项会出现问题的游戏列表。(通常标记为需" @@ -432,16 +426,16 @@ msgstr "" msgid "!ContextTip:Framelimiter:Disable" msgstr "注意: 如限帧被禁用,快速模式和慢动作模式将不可用。" -#: pcsx2/gui/Panels/VideoPanel.cpp:223 +#: pcsx2/gui/Panels/VideoPanel.cpp:227 msgid "!Panel:Frameskip:Heading" msgstr "" "注意: 由于 PS2 硬件设计,不可能准确跳帧。启用此选项可能在游戏中导致图像错误。" -#: pcsx2/gui/Panels/VideoPanel.cpp:302 +#: pcsx2/gui/Panels/VideoPanel.cpp:306 msgid "!ContextTip:GS:SyncMTGS" msgstr "如您认为 MTGS 线程同步导致崩溃或图像错误,请启用此项。" -#: pcsx2/gui/Panels/VideoPanel.cpp:306 +#: pcsx2/gui/Panels/VideoPanel.cpp:310 msgid "!ContextTip:GS:DisableOutput" msgstr "" "禁用全部由 MTGS 线程或 GPU 开销导致的测试信息。此选项可与即时存档配合使用: 在" @@ -461,6 +455,11 @@ msgstr "" "内存溢出: SuperVU 重编译器无法保留所需的指定内存范围,且将不可用。这不是一个" "严重错误,sVU 重编译器已过时,您应该使用 microVU。:)" +#~ msgid "!ContextTip:Speedhacks:vuBlockHack" +#~ msgstr "" +#~ "假定未来的块不需要旧的标志实例数据。这应该是安全的。是否导致游戏出现问题仍" +#~ "然未知。" + #~ msgid "!Notice:Mcd:Overwrite" #~ msgstr "" #~ "此操作将把 %u 插槽上的记忆卡内容复制到 %u 插槽。目标插槽记忆卡的数据将丢" diff --git a/locales/zh_CN/pcsx2_Main.po b/locales/zh_CN/pcsx2_Main.po index 154877fc0..34a988bb5 100644 --- a/locales/zh_CN/pcsx2_Main.po +++ b/locales/zh_CN/pcsx2_Main.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-09-24 20:29+0800\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: 2011-09-24 20:32+0800\n" "Last-Translator: Wei Mingzhi \n" "Language-Team: \n" @@ -37,8 +37,13 @@ msgid "Oh noes! Out of memory!" msgstr "不好! 内存不够!" #: common/src/Utilities/Exceptions.cpp:234 -msgid "Virtual memory mapping failure! Your system may have conflicting device drivers, services, or may simply have insufficient memory or resources to meet PCSX2's lofty needs." -msgstr "虚拟内存映射错误! 您的系统可能有冲突的硬件驱动程序、服务,或者没有足够的内存或资源来满足 PCSX2 的要求。" +msgid "" +"Virtual memory mapping failure! Your system may have conflicting device " +"drivers, services, or may simply have insufficient memory or resources to " +"meet PCSX2's lofty needs." +msgstr "" +"虚拟内存映射错误! 您的系统可能有冲突的硬件驱动程序、服务,或者没有足够的内存" +"或资源来满足 PCSX2 的要求。" #: common/src/Utilities/Exceptions.cpp:309 msgid "Path: " @@ -57,11 +62,15 @@ msgid "File not found." msgstr "文件未找到。" #: common/src/Utilities/Exceptions.cpp:373 -msgid "Permission denied while trying to open file, likely due to insufficient user account rights." +msgid "" +"Permission denied while trying to open file, likely due to insufficient user " +"account rights." msgstr "打开文件时拒绝访问,可能是由于用户账户权限限制。" #: common/src/Utilities/Exceptions.cpp:393 -msgid "Unexpected end of file or stream encountered. File is probably truncated or corrupted." +msgid "" +"Unexpected end of file or stream encountered. File is probably truncated or " +"corrupted." msgstr "遇到非预期的文件或串流结尾。文件可能被截断或被破坏。" #: common/src/Utilities/ThreadTools.cpp:41 @@ -89,25 +98,37 @@ msgid "Cannot load ELF binary image. The file may be corrupt or incomplete." msgstr "无法加载 ELF 二进制映像。文件可能已损坏或不完整。" #: pcsx2/Elfheader.cpp:268 -msgid "If loading from an ISO image, this error may be caused by an unsupported ISO image type or a bug in PCSX2 ISO image support." -msgstr "如从一个 ISO 镜像加载,此错误可能由一个不被支持的 ISO 镜像类型或 PCSX2 ISO 镜像支持的 bug 引起。" +msgid "" +"If loading from an ISO image, this error may be caused by an unsupported ISO " +"image type or a bug in PCSX2 ISO image support." +msgstr "" +"如从一个 ISO 镜像加载,此错误可能由一个不被支持的 ISO 镜像类型或 PCSX2 ISO 镜" +"像支持的 bug 引起。" #: pcsx2/MTGS.cpp:859 -msgid "The MTGS thread has become unresponsive while waiting for the GS plugin to open." +msgid "" +"The MTGS thread has become unresponsive while waiting for the GS plugin to " +"open." msgstr "MTGS 线程在等待 GS 插件打开时失去响应。" #: pcsx2/PluginManager.cpp:709 -msgid "The savestate cannot be loaded, as it appears to be corrupt or incomplete." +msgid "" +"The savestate cannot be loaded, as it appears to be corrupt or incomplete." msgstr "即时存档无法读取,文件可能已损坏或不完整。" #: pcsx2/PluginManager.cpp:719 #, c-format -msgid "%s plugin failed to open. Your computer may have insufficient resources, or incompatible hardware/drivers." -msgstr "打开 %s 插件失败。您的计算机可能没有可用资源,或由不兼容的硬件/驱动程序导致。" +msgid "" +"%s plugin failed to open. Your computer may have insufficient resources, or " +"incompatible hardware/drivers." +msgstr "" +"打开 %s 插件失败。您的计算机可能没有可用资源,或由不兼容的硬件/驱动程序导致。" #: pcsx2/PluginManager.cpp:726 #, c-format -msgid "%s plugin failed to initialize. Your system may have insufficient memory or resources needed." +msgid "" +"%s plugin failed to initialize. Your system may have insufficient memory or " +"resources needed." msgstr "%s 插件初始化失败。您的系统可能没有足够的内存或资源。" #: pcsx2/PluginManager.cpp:832 @@ -122,21 +143,33 @@ msgstr "配置的 %s 插件文件不是一个合法的动态链接库" #: pcsx2/PluginManager.cpp:854 #, c-format -msgid "The configured %s plugin is not a PCSX2 plugin, or is for an older unsupported version of PCSX2." -msgstr "配置的 %s 插件不是一个合法的 PCSX2 插件,或是为一个不受支持的 PCSX2 旧版本设计的。" +msgid "" +"The configured %s plugin is not a PCSX2 plugin, or is for an older " +"unsupported version of PCSX2." +msgstr "" +"配置的 %s 插件不是一个合法的 PCSX2 插件,或是为一个不受支持的 PCSX2 旧版本设" +"计的。" #: pcsx2/PluginManager.cpp:879 -msgid "The plugin reports that your hardware or software/drivers are not supported." +msgid "" +"The plugin reports that your hardware or software/drivers are not supported." msgstr "插件报告您的硬件或软件/驱动程序不受支持。" #: pcsx2/PluginManager.cpp:900 -msgid "Configured plugin is not a PCSX2 plugin, or is for an older unsupported version of PCSX2." -msgstr "配置的插件不是一个 PCSX2 插件,或是为一个不受支持的 PCSX2 旧版本设计的。" +msgid "" +"Configured plugin is not a PCSX2 plugin, or is for an older unsupported " +"version of PCSX2." +msgstr "" +"配置的插件不是一个 PCSX2 插件,或是为一个不受支持的 PCSX2 旧版本设计的。" #: pcsx2/PluginManager.cpp:926 #, c-format -msgid "Configured %s plugin is not a valid PCSX2 plugin, or is for an older unsupported version of PCSX2." -msgstr "配置的 %s 插件不是一个合法的 PCSX2 插件,或是为一个不受支持的 PCSX2 旧版本设计的。" +msgid "" +"Configured %s plugin is not a valid PCSX2 plugin, or is for an older " +"unsupported version of PCSX2." +msgstr "" +"配置的 %s 插件不是一个合法的 PCSX2 插件,或是为一个不受支持的 PCSX2 旧版本设" +"计的。" #: pcsx2/PluginManager.cpp:1355 msgid "Internal Memorycard Plugin failed to initialize." @@ -146,7 +179,7 @@ msgstr "内置记忆卡插件初始化失败。" msgid "Unloaded Plugin" msgstr "已卸载插件" -#: pcsx2/SaveState.cpp:339 +#: pcsx2/SaveState.cpp:342 msgid "Cannot load savestate. It is of an unknown or unsupported version." msgstr "无法加载即时存档。存档为一个未知或不支持的版本。" @@ -155,7 +188,9 @@ msgid "Dumps detailed information for PS2 executables (ELFs)." msgstr "转储 PS2 可执行文件 (ELF) 的详细信息。" #: pcsx2/SourceLog.cpp:101 -msgid "Logs manual protection, split blocks, and other things that might impact performance." +msgid "" +"Logs manual protection, split blocks, and other things that might impact " +"performance." msgstr "记录手动保护、分割块以及其它可能影响性能的东西。" #: pcsx2/SourceLog.cpp:106 @@ -178,8 +213,7 @@ msgstr "SYSCALL 及 DECI2 活动。" msgid "Direct memory accesses to unknown or unmapped EE memory space." msgstr "到未知或未映射的内存空间的直接内存访问。" -#: pcsx2/SourceLog.cpp:157 -#: pcsx2/SourceLog.cpp:276 +#: pcsx2/SourceLog.cpp:157 pcsx2/SourceLog.cpp:276 msgid "Disasm of executing core instructions (excluding COPs and CACHE)." msgstr "反汇编执行核心指令 (除了 COP 指令及 CACHE 指令)。" @@ -200,16 +234,16 @@ msgid "Execution of EE cache instructions." msgstr "EE 缓存指令的执行。" #: pcsx2/SourceLog.cpp:187 -msgid "All known hardware register accesses (very slow!); not including sub filter options below." +msgid "" +"All known hardware register accesses (very slow!); not including sub filter " +"options below." msgstr "全部已知硬件寄存器访问 (很慢!);不包括以下子过滤器选项。" -#: pcsx2/SourceLog.cpp:193 -#: pcsx2/SourceLog.cpp:294 +#: pcsx2/SourceLog.cpp:193 pcsx2/SourceLog.cpp:294 msgid "Logs only unknown, unmapped, or unimplemented register accesses." msgstr "仅记录未知、未映射或未实现的寄存器访问。" -#: pcsx2/SourceLog.cpp:199 -#: pcsx2/SourceLog.cpp:300 +#: pcsx2/SourceLog.cpp:199 pcsx2/SourceLog.cpp:300 msgid "Logs only DMA-related registers." msgstr "仅记录 DMA 相关寄存器。" @@ -262,7 +296,8 @@ msgid "Disasm of the IOP's GPU co-processor instructions." msgstr "反汇编 IOP GPU 协处理器指令。" #: pcsx2/SourceLog.cpp:288 -msgid "All known hardware register accesses, not including the sub-filters below." +msgid "" +"All known hardware register accesses, not including the sub-filters below." msgstr "全部已知硬件寄存器访问,不包括以下子过滤器。" #: pcsx2/SourceLog.cpp:306 @@ -285,42 +320,41 @@ msgstr "跟踪所有 IOP 计数器事件和一些计数器寄存器活动。" msgid "Detailed logging of CDVD hardware." msgstr "详细记录 CDVD 硬件信息。" -#: pcsx2/System.h:206 -#: pcsx2/System.h:207 -#: pcsx2/System.h:208 +#: pcsx2/System.h:206 pcsx2/System.h:207 pcsx2/System.h:208 msgid "PCSX2 Message" msgstr "PCSX2 消息" #: pcsx2/ZipTools/thread_gzip.cpp:82 -msgid "The savestate was not properly saved. The temporary file was created successfully but could not be moved to its final resting place." +msgid "" +"The savestate was not properly saved. The temporary file was created " +"successfully but could not be moved to its final resting place." msgstr "即时存档未正确保存。临时文件建立成功但无法移至存档位置。" -#: pcsx2/gui/AppConfig.cpp:837 +#: pcsx2/gui/AppConfig.cpp:842 msgid "Safest" msgstr "最安全" -#: pcsx2/gui/AppConfig.cpp:838 +#: pcsx2/gui/AppConfig.cpp:843 msgid "Safe (faster)" msgstr "安全 (较快)" -#: pcsx2/gui/AppConfig.cpp:839 +#: pcsx2/gui/AppConfig.cpp:844 msgid "Balanced" msgstr "平衡" -#: pcsx2/gui/AppConfig.cpp:840 +#: pcsx2/gui/AppConfig.cpp:845 msgid "Aggressive" msgstr "较激进" -#: pcsx2/gui/AppConfig.cpp:841 +#: pcsx2/gui/AppConfig.cpp:846 msgid "Aggressive plus" msgstr "激进" -#: pcsx2/gui/AppConfig.cpp:842 +#: pcsx2/gui/AppConfig.cpp:847 msgid "Mostly Harmful" msgstr "不稳定" -#: pcsx2/gui/AppConfig.cpp:999 -#: pcsx2/gui/AppConfig.cpp:1005 +#: pcsx2/gui/AppConfig.cpp:1007 pcsx2/gui/AppConfig.cpp:1013 msgid "Failed to overwrite existing settings file; permission was denied." msgstr "覆盖已存在文件失败;权限被拒绝。" @@ -333,7 +367,9 @@ msgid "PCSX2 - SSE2 Recommended" msgstr "PCSX2 - 推荐使用 SSE2" #: pcsx2/gui/AppInit.cpp:71 -msgid "SSE extensions are not available. PCSX2 requires a cpu that supports the SSE instruction set." +msgid "" +"SSE extensions are not available. PCSX2 requires a cpu that supports the " +"SSE instruction set." msgstr "SSE 扩展不可用。PCSX2 需要一个支持 SSE 指令集的 CPU。" #: pcsx2/gui/AppInit.cpp:154 @@ -344,8 +380,7 @@ msgstr "PCSX2 重编译器错误" msgid "All options are for the current session only and will not be saved.\n" msgstr "全部选项仅对当前会话有效,不会被保存。\n" -#: pcsx2/gui/AppInit.cpp:237 -#: pcsx2/gui/AppMain.cpp:299 +#: pcsx2/gui/AppInit.cpp:237 pcsx2/gui/AppMain.cpp:299 msgid "IsoFile" msgstr "Iso 文件" @@ -423,7 +458,8 @@ msgstr "插件覆盖错误 - %s" #: pcsx2/gui/AppInit.cpp:310 #, c-format msgid "" -"%s Plugin Override Error! The following file does not exist or is not a valid %s plugin:\n" +"%s Plugin Override Error! The following file does not exist or is not a " +"valid %s plugin:\n" "\n" msgstr "" "%s 插件覆盖错误! 以下文件不存在或不是一个合法的 %s 插件:\n" @@ -438,8 +474,7 @@ msgstr "单击确定使用默认配置的插件,或取消关闭 %s。" msgid "PCSX2 Error: Hardware Deficiency" msgstr "PCSX2 错误: 硬件缺陷" -#: pcsx2/gui/AppInit.cpp:496 -#: pcsx2/gui/AppInit.cpp:508 +#: pcsx2/gui/AppInit.cpp:496 pcsx2/gui/AppInit.cpp:508 #, c-format msgid "Press OK to close %s." msgstr "请单击 \"确定\" 来关闭 %s。" @@ -527,9 +562,9 @@ msgstr "" "\n" "单击确定进入插件配置面板。" -#: pcsx2/gui/AppMain.cpp:140 -#: pcsx2/gui/AppMain.cpp:154 -msgid "Warning! System plugins have not been loaded. PCSX2 may be inoperable." +#: pcsx2/gui/AppMain.cpp:140 pcsx2/gui/AppMain.cpp:154 +msgid "" +"Warning! System plugins have not been loaded. PCSX2 may be inoperable." msgstr "警告! 系统插件未被加载。PCSX2 可能不可使用。" #: pcsx2/gui/AppMain.cpp:309 @@ -579,7 +614,9 @@ msgid "Portable mode error - %s" msgstr "绿色模式错误 - %s" #: pcsx2/gui/AppUserMode.cpp:157 -msgid "PCSX2 has been installed as a portable application but cannot run due to the following errors:" +msgid "" +"PCSX2 has been installed as a portable application but cannot run due to the " +"following errors:" msgstr "PCSX2 已被安装为一个绿色软件,但由于以下错误无法运行:" #: pcsx2/gui/AppUserMode.cpp:165 @@ -592,7 +629,9 @@ msgid "%s is switching to local install mode." msgstr "%s 正在切换本地安装模式。" #: pcsx2/gui/AppUserMode.cpp:179 -msgid "Try to remove the file called \"portable.ini\" from your installation directory manually." +msgid "" +"Try to remove the file called \"portable.ini\" from your installation " +"directory manually." msgstr "请尝试手动删除您的安装目录中的 \"portable.ini\" 文件。" #: pcsx2/gui/ApplyState.h:55 @@ -615,8 +654,7 @@ msgstr "小" msgid "It's what I use (the programmer guy)." msgstr "我使用的 (程序员)。" -#: pcsx2/gui/ConsoleLogger.cpp:415 -#: pcsx2/gui/Panels/CpuPanel.cpp:38 +#: pcsx2/gui/ConsoleLogger.cpp:415 pcsx2/gui/Panels/CpuPanel.cpp:38 msgid "Normal" msgstr "正常" @@ -645,7 +683,9 @@ msgid "Light theme" msgstr "亮色主题" #: pcsx2/gui/ConsoleLogger.cpp:424 -msgid "Classic black color scheme for people who enjoy having text seared into their optic nerves." +msgid "" +"Classic black color scheme for people who enjoy having text seared into " +"their optic nerves." msgstr "经典黑色主题。" #: pcsx2/gui/ConsoleLogger.cpp:424 @@ -657,7 +697,8 @@ msgid "Always on Top" msgstr "总在最上面" #: pcsx2/gui/ConsoleLogger.cpp:428 -msgid "When checked the log window will be visible over other foreground windows." +msgid "" +"When checked the log window will be visible over other foreground windows." msgstr "如选中,日志窗口将在其它窗口上面显示。" #: pcsx2/gui/ConsoleLogger.cpp:430 @@ -676,8 +717,7 @@ msgstr "清除(&L)" msgid "Clear the log window contents" msgstr "清除日志窗口内容" -#: pcsx2/gui/ConsoleLogger.cpp:433 -#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:280 +#: pcsx2/gui/ConsoleLogger.cpp:433 pcsx2/gui/Dialogs/SysConfigDialog.cpp:280 msgid "Appearance" msgstr "外观" @@ -799,11 +839,15 @@ msgid "Do not show this dialog again." msgstr "不再显示此对话框。" #: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:199 -msgid "Disables this popup and whatever response you select here will be automatically used from now on." +msgid "" +"Disables this popup and whatever response you select here will be " +"automatically used from now on." msgstr "禁用弹出提示,以后任何您选定的内容将被自动使用。" #: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:201 -msgid "The popup will not be shown again. This setting can be undone from the settings panels." +msgid "" +"The popup will not be shown again. This setting can be undone from the " +"settings panels." msgstr "此提示框将不会再被显示。此设定可以从设置面板中撤消。" #: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:247 @@ -861,11 +905,15 @@ msgid "8 MB [most compatible]" msgstr "8 MB [兼容性最高]" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:195 -msgid "This is the standard Sony-provisioned size, and is supported by all games and BIOS versions." +msgid "" +"This is the standard Sony-provisioned size, and is supported by all games " +"and BIOS versions." msgstr "索尼的标准大小,支持所有游戏和 BIOS 版本。" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:196 -msgid "Always use this option if you want the safest and surest memory card behavior." +msgid "" +"Always use this option if you want the safest and surest memory card " +"behavior." msgstr "如果您需要最安全的记忆卡行为,请使用此选项。" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:199 @@ -874,7 +922,8 @@ msgstr "16 MB" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:199 #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:203 -msgid "A typical size for 3rd-party memory cards which should work with most games." +msgid "" +"A typical size for 3rd-party memory cards which should work with most games." msgstr "一个通常的第三方记忆卡大小,应该可以兼容大多数游戏。" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:200 @@ -891,11 +940,15 @@ msgid "64 MB" msgstr "64 MB" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:207 -msgid "Low compatibility warning: Yes it's very big, but may not work with many games." +msgid "" +"Low compatibility warning: Yes it's very big, but may not work with many " +"games." msgstr "兼容性低: 容量较大,但可能在很多游戏中不可用。" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:208 -msgid "Use at your own risk. Erratic memory card behavior is possible (though unlikely)." +msgid "" +"Use at your own risk. Erratic memory card behavior is possible (though " +"unlikely)." msgstr "可能出现错误的记忆卡行为 (一般不会)。" #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:47 @@ -1074,8 +1127,7 @@ msgstr "终止应用程序" msgid "GS Output is Disabled!" msgstr "GS 输出已禁用!" -#: pcsx2/gui/GlobalCommands.cpp:387 -#: pcsx2/gui/MainFrame.cpp:414 +#: pcsx2/gui/GlobalCommands.cpp:387 pcsx2/gui/MainFrame.cpp:414 msgid "Save state" msgstr "即时存档" @@ -1083,8 +1135,7 @@ msgstr "即时存档" msgid "Saves the virtual machine state to the current slot." msgstr "将虚拟机的状态保存至当前存档位置。" -#: pcsx2/gui/GlobalCommands.cpp:393 -#: pcsx2/gui/MainFrame.cpp:413 +#: pcsx2/gui/GlobalCommands.cpp:393 pcsx2/gui/MainFrame.cpp:413 msgid "Load state" msgstr "即时读档" @@ -1122,11 +1173,12 @@ msgstr "拖放错误" #: pcsx2/gui/IsoDropTarget.cpp:58 #, c-format -msgid "It is an error to drop multiple files onto a %s window. One at a time please, thank you." +msgid "" +"It is an error to drop multiple files onto a %s window. One at a time " +"please, thank you." msgstr "不可以将多个文件同时拖到到 %s 窗口上。一次只能拖动一个文件。" -#: pcsx2/gui/IsoDropTarget.cpp:89 -#: pcsx2/gui/MainMenuClicks.cpp:342 +#: pcsx2/gui/IsoDropTarget.cpp:89 pcsx2/gui/MainMenuClicks.cpp:342 msgid "Confirm PS2 Reset" msgstr "确认 PS2 重启" @@ -1149,8 +1201,7 @@ msgstr "您已将以下 ISO 镜像拖放至 %s:" msgid "Slot %d" msgstr "位置 %d" -#: pcsx2/gui/MainFrame.cpp:44 -#: pcsx2/gui/Saveslots.cpp:150 +#: pcsx2/gui/MainFrame.cpp:44 pcsx2/gui/Saveslots.cpp:150 msgid "Backup" msgstr "备份" @@ -1196,8 +1247,7 @@ msgstr "%s %d.%d.%d %s" msgid "(modded)" msgstr "(已修改)" -#: pcsx2/gui/MainFrame.cpp:399 -#: pcsx2/gui/MainFrame.cpp:401 +#: pcsx2/gui/MainFrame.cpp:399 pcsx2/gui/MainFrame.cpp:401 #: pcsx2/gui/MainFrame.cpp:407 msgid "Initializing..." msgstr "正在初始化..." @@ -1291,8 +1341,7 @@ msgstr "记忆卡(&M)" msgid "&Plugin/BIOS Selector" msgstr "插件/BIOS 选择器(&P)" -#: pcsx2/gui/MainFrame.cpp:460 -#: pcsx2/gui/Panels/GameDatabasePanel.cpp:346 +#: pcsx2/gui/MainFrame.cpp:460 pcsx2/gui/Panels/GameDatabasePanel.cpp:346 msgid "Game Database Editor" msgstr "游戏数据库编辑器" @@ -1413,8 +1462,7 @@ msgstr "启动 CDVD (快速模式)" msgid "Use fast boot to skip PS2 startup and splash screens" msgstr "使用快速启动模式来跳过 PS2 启动画面" -#: pcsx2/gui/MainFrame.cpp:703 -#: pcsx2/gui/MainFrame.cpp:738 +#: pcsx2/gui/MainFrame.cpp:703 pcsx2/gui/MainFrame.cpp:738 msgid "No plugin loaded" msgstr "未加载插件" @@ -1423,7 +1471,9 @@ msgid "Core GS Settings..." msgstr "核心 GS 设置..." #: pcsx2/gui/MainFrame.cpp:709 -msgid "Modify hardware emulation settings regulated by the PCSX2 core virtual machine." +msgid "" +"Modify hardware emulation settings regulated by the PCSX2 core virtual " +"machine." msgstr "修改 PCSX2 核心虚拟机相关的硬件模拟设置。" #: pcsx2/gui/MainFrame.cpp:711 @@ -1455,8 +1505,7 @@ msgstr "确认 ISO 镜像更改" msgid "Do you want to swap discs or boot the new image (via system reset)?" msgstr "是否要更换光盘或启动新光盘镜像 (通过系统复位)?" -#: pcsx2/gui/MainMenuClicks.cpp:148 -#: pcsx2/gui/MainMenuClicks.cpp:194 +#: pcsx2/gui/MainMenuClicks.cpp:148 pcsx2/gui/MainMenuClicks.cpp:194 msgid "Swap Disc" msgstr "更换光盘" @@ -1488,8 +1537,7 @@ msgstr "光盘映像 (%s)" msgid "Blockdumps (%s)" msgstr "块转储 (%s)" -#: pcsx2/gui/MainMenuClicks.cpp:270 -#: pcsx2/gui/MainMenuClicks.cpp:291 +#: pcsx2/gui/MainMenuClicks.cpp:270 pcsx2/gui/MainMenuClicks.cpp:291 msgid "All Files (*.*)" msgstr "全部文件 (*.*)" @@ -1510,7 +1558,9 @@ msgid "An error occurred while trying to open the file:" msgstr "打开文件时出现一个错误:" #: pcsx2/gui/MainMenuClicks.cpp:319 -msgid "Error: The configured ISO file does not exist. Click OK to select a new ISO source for CDVD." +msgid "" +"Error: The configured ISO file does not exist. Click OK to select a new ISO " +"source for CDVD." msgstr "错误: 配置的 ISO 文件不存在。单击确定为 CDVD 选择一个新的 ISO 源。" #: pcsx2/gui/MainMenuClicks.cpp:390 @@ -1576,7 +1626,9 @@ msgid "Select folder with PS2 BIOS roms" msgstr "选择 PS2 BIOS 文件所在文件夹" #: pcsx2/gui/Panels/BiosSelectorPanel.cpp:111 -msgid "Click the Browse button to select a different folder where PCSX2 will look for PS2 BIOS roms." +msgid "" +"Click the Browse button to select a different folder where PCSX2 will look " +"for PS2 BIOS roms." msgstr "单击浏览按钮可选择一个 PS2 BIOS 所在的不同文件夹。" #: pcsx2/gui/Panels/BiosSelectorPanel.cpp:113 @@ -1621,8 +1673,7 @@ msgstr "无" msgid "EE/FPU Advanced Recompiler Options" msgstr "EE/FPU 高级重编译器选项" -#: pcsx2/gui/Panels/CpuPanel.cpp:87 -#: pcsx2/gui/Panels/CpuPanel.cpp:102 +#: pcsx2/gui/Panels/CpuPanel.cpp:87 pcsx2/gui/Panels/CpuPanel.cpp:102 msgid "Extra + Preserve Sign" msgstr "额外 + 保留符号" @@ -1638,8 +1689,7 @@ msgstr "VU0 / VU1 高级重编译器选项" msgid "Extra" msgstr "额外" -#: pcsx2/gui/Panels/CpuPanel.cpp:117 -#: pcsx2/gui/Panels/CpuPanel.cpp:126 +#: pcsx2/gui/Panels/CpuPanel.cpp:117 pcsx2/gui/Panels/CpuPanel.cpp:126 #: pcsx2/gui/Panels/CpuPanel.cpp:184 msgid "Interpreter" msgstr "解释器" @@ -1648,13 +1698,14 @@ msgstr "解释器" msgid "Quite possibly the slowest thing in the universe." msgstr "很有可能是宇宙中最慢的东西。" -#: pcsx2/gui/Panels/CpuPanel.cpp:120 -#: pcsx2/gui/Panels/CpuPanel.cpp:129 +#: pcsx2/gui/Panels/CpuPanel.cpp:120 pcsx2/gui/Panels/CpuPanel.cpp:129 msgid "Recompiler" msgstr "重编译器" #: pcsx2/gui/Panels/CpuPanel.cpp:121 -msgid "Performs just-in-time binary translation of 64-bit MIPS-IV machine code to x86." +msgid "" +"Performs just-in-time binary translation of 64-bit MIPS-IV machine code to " +"x86." msgstr "进行从 64 位 MIPS-IV 机器代码到 x86 的即时代码翻译。" #: pcsx2/gui/Panels/CpuPanel.cpp:127 @@ -1662,7 +1713,9 @@ msgid "Pretty slow; provided for diagnostic purposes only." msgstr "很慢;仅供诊断用途。" #: pcsx2/gui/Panels/CpuPanel.cpp:130 -msgid "Performs just-in-time binary translation of 32-bit MIPS-I machine code to x86." +msgid "" +"Performs just-in-time binary translation of 32-bit MIPS-I machine code to " +"x86." msgstr "进行从 32 位 MIPS-IV 机器代码到 x86 的即时代码翻译。" #: pcsx2/gui/Panels/CpuPanel.cpp:154 @@ -1673,14 +1726,15 @@ msgstr "启用 EE 缓存 (较慢)" msgid "Interpreter only; provided for diagnostic" msgstr "很慢;仅供诊断用途。" -#: pcsx2/gui/Panels/CpuPanel.cpp:170 -#: pcsx2/gui/Panels/CpuPanel.cpp:223 +#: pcsx2/gui/Panels/CpuPanel.cpp:170 pcsx2/gui/Panels/CpuPanel.cpp:223 #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:110 msgid "Restore Defaults" msgstr "恢复默认值" #: pcsx2/gui/Panels/CpuPanel.cpp:185 -msgid "Vector Unit Interpreter. Slow and not very compatible. Only use for diagnostics." +msgid "" +"Vector Unit Interpreter. Slow and not very compatible. Only use for " +"diagnostics." msgstr "矢量单元解释器。速度慢且兼容性低。仅供诊断用途。" #: pcsx2/gui/Panels/CpuPanel.cpp:187 @@ -1688,7 +1742,8 @@ msgid "microVU Recompiler" msgstr "microVU 重编译器" #: pcsx2/gui/Panels/CpuPanel.cpp:188 -msgid "New Vector Unit recompiler with much improved compatibility. Recommended." +msgid "" +"New Vector Unit recompiler with much improved compatibility. Recommended." msgstr "新版矢量单元重编译器,兼容性有较大提升。推荐。" #: pcsx2/gui/Panels/CpuPanel.cpp:190 @@ -1696,7 +1751,8 @@ msgid "superVU Recompiler [legacy]" msgstr "superVU 重编译器 [旧式]" #: pcsx2/gui/Panels/CpuPanel.cpp:191 -msgid "Useful for diagnosing bugs or clamping issues in the new mVU recompiler." +msgid "" +"Useful for diagnosing bugs or clamping issues in the new mVU recompiler." msgstr "可用于诊断新的 mVU 重编译器的 bug 或限值问题。" #: pcsx2/gui/Panels/DirPickerPanel.cpp:64 @@ -1777,7 +1833,9 @@ msgid "Zoom:" msgstr "缩放:" #: pcsx2/gui/Panels/GSWindowPanel.cpp:196 -msgid "Invalid window dimensions specified: Size cannot contain non-numeric digits! >_<" +msgid "" +"Invalid window dimensions specified: Size cannot contain non-numeric digits! " +">_<" msgstr "指定了非法的数值: 大小数值不能包含非数字内容! >_<" #: pcsx2/gui/Panels/GameDatabasePanel.cpp:334 @@ -1834,7 +1892,8 @@ msgid "EE timing hack - Multi purpose hack. Try if all else fails." msgstr "EE 定时 Hack - 有多种用途。如以上皆失败请尝试。" #: pcsx2/gui/Panels/GameFixesPanel.cpp:75 -msgid "Skip MPEG hack - Skips videos/FMVs in games to avoid game hanging/freezes." +msgid "" +"Skip MPEG hack - Skips videos/FMVs in games to avoid game hanging/freezes." msgstr "跳过 MPEG hack - 跳过游戏中的 CG 以避免游戏挂起或失去响应。" #: pcsx2/gui/Panels/GameFixesPanel.cpp:79 @@ -1862,7 +1921,8 @@ msgid "Enable manual game fixes [Not recommended]" msgstr "手动设置游戏特殊修正 [不推荐]" #: pcsx2/gui/Panels/GameFixesPanel.cpp:127 -msgid "The safest way to make sure that all game fixes are completely disabled." +msgid "" +"The safest way to make sure that all game fixes are completely disabled." msgstr "确保所有游戏特殊修正被禁用的最安全的方法。" #: pcsx2/gui/Panels/LogOptionsPanels.cpp:249 @@ -1870,11 +1930,15 @@ msgid "Enable Trace Logging" msgstr "启用跟踪日志" #: pcsx2/gui/Panels/LogOptionsPanels.cpp:250 -msgid "Trace logs are all written to emulog.txt. Toggle trace logging at any time using F10." +msgid "" +"Trace logs are all written to emulog.txt. Toggle trace logging at any time " +"using F10." msgstr "跟踪记录将被写到 emuLog.txt 文件中。可随时用 F10 切换跟踪记录。" #: pcsx2/gui/Panels/LogOptionsPanels.cpp:251 -msgid "Warning: Enabling trace logs is typically very slow, and is a leading cause of 'What happened to my FPS?' problems. :)" +msgid "" +"Warning: Enabling trace logs is typically very slow, and is a leading cause " +"of 'What happened to my FPS?' problems. :)" msgstr "警告: 启用跟踪记录通常非常慢,且可能导致 \"FPS 怎么回事\" 类问题。:)" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:151 @@ -2112,7 +2176,9 @@ msgid "Custom folder:" msgstr "自定义文件夹:" #: pcsx2/gui/Panels/MiscPanelStuff.cpp:57 -msgid "This setting may require administration privileges from your operating system, depending on how your system is configured." +msgid "" +"This setting may require administration privileges from your operating " +"system, depending on how your system is configured." msgstr "此设置可能需要操作系统管理员权限,取决于您的操作系统的配置。" #: pcsx2/gui/Panels/MiscPanelStuff.cpp:66 @@ -2211,11 +2277,14 @@ msgid "Enable speedhacks" msgstr "启用速度 Hack" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:102 -msgid "A safe and easy way to make sure that all speedhacks are completely disabled." +msgid "" +"A safe and easy way to make sure that all speedhacks are completely disabled." msgstr "确认全部速度 Hack 被禁用的一个安全简易的方法。" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:111 -msgid "Resets all speedhack options to their defaults, which consequently turns them all OFF." +msgid "" +"Resets all speedhack options to their defaults, which consequently turns " +"them all OFF." msgstr "将所有速度 Hack 选项重置到默认值,即关闭所有选项。" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:120 @@ -2235,50 +2304,48 @@ msgid "mVU Flag Hack" msgstr "mVU 标志位 Hack" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:164 -msgid "Good Speedup and High Compatibility; may cause bad graphics... [Recommended]" +msgid "" +"Good Speedup and High Compatibility; may cause bad graphics... [Recommended]" msgstr "提速效果较好,兼容性较高;可能导致图像错误等。[推荐]" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:166 -msgid "mVU Block Hack" -msgstr "mVU 数据块 Hack" - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 -msgid "Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." -msgstr "提速效果较好,兼容性较高;可能导致图像错误等。" - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "MTVU (Multi-Threaded microVU1)" msgstr "MTVU (多线程 microVU1)" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:170 -msgid "Good Speedup and High Compatibility; may cause hanging... [Recommended if 3+ cores]" +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 +msgid "" +"Good Speedup and High Compatibility; may cause hanging... [Recommended if 3+ " +"cores]" msgstr "提速效果较好,兼容性较高;可能导致模拟器没有响应等。[三核以上用户推荐]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:183 msgid "Other Hacks" msgstr "其它 Hack" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:193 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:185 msgid "Enable INTC Spin Detection" msgstr "启用 INTC Spin 检测" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:194 -msgid "Huge speedup for some games, with almost no compatibility side effects. [Recommended]" +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:186 +msgid "" +"Huge speedup for some games, with almost no compatibility side effects. " +"[Recommended]" msgstr "对部分游戏有显著提速,基本无副作用。[推荐]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:196 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:188 msgid "Enable Wait Loop Detection" msgstr "启用等待循环检测" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:197 -msgid "Moderate speedup for some games, with no known side effects. [Recommended]" +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:189 +msgid "" +"Moderate speedup for some games, with no known side effects. [Recommended]" msgstr "对部分游戏有中等提速,无已知副作用。[推荐]" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:199 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 msgid "Enable fast CDVD" msgstr "启用快速 CDVD" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:192 msgid "Fast disc access, less loading times. [Not Recommended]" msgstr "加速光盘访问,缩短加载时间。[不推荐]" @@ -2291,7 +2358,9 @@ msgid "Select folder containing PCSX2 visual themes" msgstr "选择存放 PCSX2 视觉主题的文件夹" #: pcsx2/gui/Panels/ThemeSelectorPanel.cpp:45 -msgid "Click the Browse button to select a different folder containing PCSX2 visual themes." +msgid "" +"Click the Browse button to select a different folder containing PCSX2 visual " +"themes." msgstr "单击浏览按钮来选择一个不同的 PCSX2 视觉主题文件夹。" #: pcsx2/gui/Panels/ThemeSelectorPanel.cpp:49 @@ -2303,7 +2372,8 @@ msgid "Disable Framelimiting" msgstr "禁用限帧" #: pcsx2/gui/Panels/VideoPanel.cpp:35 -msgid "Useful for running benchmarks. Toggle this option in-game by pressing F4." +msgid "" +"Useful for running benchmarks. Toggle this option in-game by pressing F4." msgstr "在进行评测时有用。游戏中可按 F4 开关此选项。" #: pcsx2/gui/Panels/VideoPanel.cpp:61 @@ -2322,8 +2392,7 @@ msgstr "快速模式速率调整:" msgid "NTSC Framerate:" msgstr "NTSC 帧率:" -#: pcsx2/gui/Panels/VideoPanel.cpp:91 -#: pcsx2/gui/Panels/VideoPanel.cpp:97 +#: pcsx2/gui/Panels/VideoPanel.cpp:91 pcsx2/gui/Panels/VideoPanel.cpp:97 msgid "FPS" msgstr "FPS" @@ -2331,93 +2400,117 @@ msgstr "FPS" msgid "PAL Framerate:" msgstr "PAL 帧率:" -#: pcsx2/gui/Panels/VideoPanel.cpp:162 -msgid "Error while parsing either NTSC or PAL framerate settings. Settings must be valid floating point numerics." +#: pcsx2/gui/Panels/VideoPanel.cpp:166 +msgid "" +"Error while parsing either NTSC or PAL framerate settings. Settings must be " +"valid floating point numerics." msgstr "解析 NTSC 或 PAL 帧率时出错。设定值必须是一个合法的浮点数值。" -#: pcsx2/gui/Panels/VideoPanel.cpp:180 +#: pcsx2/gui/Panels/VideoPanel.cpp:184 msgid "Disabled [default]" msgstr "禁用 [默认]" -#: pcsx2/gui/Panels/VideoPanel.cpp:184 +#: pcsx2/gui/Panels/VideoPanel.cpp:188 msgid "Skip when on Turbo only (TAB to enable)" msgstr "仅在快速模式中跳帧 (按 TAB 键启用)" -#: pcsx2/gui/Panels/VideoPanel.cpp:188 +#: pcsx2/gui/Panels/VideoPanel.cpp:192 msgid "Constant skipping" msgstr "常数跳帧" -#: pcsx2/gui/Panels/VideoPanel.cpp:190 -msgid "Normal and Turbo limit rates skip frames. Slow motion mode will still disable frameskipping." +#: pcsx2/gui/Panels/VideoPanel.cpp:194 +msgid "" +"Normal and Turbo limit rates skip frames. Slow motion mode will still " +"disable frameskipping." msgstr "正常及加速模式帧率跳帧。慢动作模式仍将禁用跳帧。" -#: pcsx2/gui/Panels/VideoPanel.cpp:213 +#: pcsx2/gui/Panels/VideoPanel.cpp:217 msgid "Frames to Draw" msgstr "绘制帧数" -#: pcsx2/gui/Panels/VideoPanel.cpp:218 +#: pcsx2/gui/Panels/VideoPanel.cpp:222 msgid "Frames to Skip" msgstr "跳过帧数" -#: pcsx2/gui/Panels/VideoPanel.cpp:294 +#: pcsx2/gui/Panels/VideoPanel.cpp:298 msgid "Use Synchronized MTGS" msgstr "使用同步 MTGS" -#: pcsx2/gui/Panels/VideoPanel.cpp:295 -msgid "For troubleshooting potential bugs in the MTGS only, as it is potentially very slow." +#: pcsx2/gui/Panels/VideoPanel.cpp:299 +msgid "" +"For troubleshooting potential bugs in the MTGS only, as it is potentially " +"very slow." msgstr "仅供诊断 MTGS 中可能的错误,可能会非常慢。" -#: pcsx2/gui/Panels/VideoPanel.cpp:298 +#: pcsx2/gui/Panels/VideoPanel.cpp:302 msgid "Disable all GS output" msgstr "禁用所有 GS 输出" -#: pcsx2/gui/Panels/VideoPanel.cpp:299 -msgid "Completely disables all GS plugin activity; ideal for benchmarking EEcore components." +#: pcsx2/gui/Panels/VideoPanel.cpp:303 +msgid "" +"Completely disables all GS plugin activity; ideal for benchmarking EEcore " +"components." msgstr "彻底禁用所有的 GS 插件活动;可用于评测 EE 内核组件性能。" -#: pcsx2/gui/Panels/VideoPanel.cpp:316 +#: pcsx2/gui/Panels/VideoPanel.cpp:320 msgid "Frame Skipping" msgstr "跳帧" -#: pcsx2/gui/Panels/VideoPanel.cpp:319 +#: pcsx2/gui/Panels/VideoPanel.cpp:323 msgid "Framelimiter" msgstr "限帧" #: pcsx2/gui/SysState.cpp:283 -msgid "Cannot load this savestate. The state is from an incompatible edition of PCSX2 that is either newer than this version, or is no longer supported." -msgstr "无法读取即时存档。即时存档是由一个不兼容的 PCSX2 版本 (或新或旧) 创建的,或已经不再支持。" +msgid "" +"Cannot load this savestate. The state is from an incompatible edition of " +"PCSX2 that is either newer than this version, or is no longer supported." +msgstr "" +"无法读取即时存档。即时存档是由一个不兼容的 PCSX2 版本 (或新或旧) 创建的,或已" +"经不再支持。" #: pcsx2/gui/SysState.cpp:290 -msgid "Cannot load this savestate. The state is an unsupported version, likely created by a newer edition of PCSX2." -msgstr "无法读取即时存档。即时存档是一个不支持的版本。可能是由一个较新版本的 PCSX2 创建。" +msgid "" +"Cannot load this savestate. The state is an unsupported version, likely " +"created by a newer edition of PCSX2." +msgstr "" +"无法读取即时存档。即时存档是一个不支持的版本。可能是由一个较新版本的 PCSX2 创" +"建。" #: pcsx2/gui/SysState.cpp:326 msgid "There is no active virtual machine state to download or save." msgstr "没有活动的虚拟机状态可供下载或保存。" #: pcsx2/gui/SysState.cpp:520 -msgid "This savestate cannot be loaded because it is not a valid gzip archive. It may have been created by an older unsupported version of PCSX2, or it may be corrupted." -msgstr "此即时存档无法加载。它不是一个合法的 gzip 归档。它可能是由一个旧的不受支持的 PCSX2 版本创建的,或可能已损坏。" +msgid "" +"This savestate cannot be loaded because it is not a valid gzip archive. It " +"may have been created by an older unsupported version of PCSX2, or it may be " +"corrupted." +msgstr "" +"此即时存档无法加载。它不是一个合法的 gzip 归档。它可能是由一个旧的不受支持的 " +"PCSX2 版本创建的,或可能已损坏。" #: pcsx2/gui/SysState.cpp:579 msgid "This file is not a valid PCSX2 savestate. See the logfile for details." msgstr "这不是一个合法的 PCSX2 即时存档。请查看日志文件以获取详细信息。" #: pcsx2/gui/SysState.cpp:598 -msgid "This savestate cannot be loaded due to missing critical components. See the log file for details." +msgid "" +"This savestate cannot be loaded due to missing critical components. See the " +"log file for details." msgstr "此即时存档无法加载。关键组件缺失。请参看日志文件以获取详细信息。" #: pcsx2/gui/i18n.cpp:63 msgid " (default)" msgstr " (默认)" -#: pcsx2/ps2/BiosTools.cpp:83 -#: pcsx2/ps2/BiosTools.cpp:151 +#: pcsx2/ps2/BiosTools.cpp:83 pcsx2/ps2/BiosTools.cpp:151 msgid "The selected BIOS file is not a valid PS2 BIOS. Please re-configure." msgstr "选择的 BIOS 文件不是一个合法的 PS2 BIOS。请重新配置。" #: pcsx2/ps2/BiosTools.cpp:244 -msgid "The PS2 BIOS could not be loaded. The BIOS has not been configured, or the configuration has been corrupted. Please re-configure." +msgid "" +"The PS2 BIOS could not be loaded. The BIOS has not been configured, or the " +"configuration has been corrupted. Please re-configure." msgstr "PS2 BIOS 不可加载。BIOS 未被配置,或配置已被破坏。请重新配置。" #: pcsx2/ps2/BiosTools.cpp:251 @@ -2426,14 +2519,27 @@ msgstr "配置的 BIOS 文件不存在。请重新配置。" #: pcsx2/x86/ix86-32/iR5900-32.cpp:578 #, c-format -msgid "%s Extensions not found. The R5900-32 recompiler requires a host CPU with MMX, SSE, and SSE2 extensions." -msgstr "%s 扩展未找到。R5900-32 重编译器需要一个带有 MMX, SSE 及 SSE2 扩展的主机 CPU。" +msgid "" +"%s Extensions not found. The R5900-32 recompiler requires a host CPU with " +"MMX, SSE, and SSE2 extensions." +msgstr "" +"%s 扩展未找到。R5900-32 重编译器需要一个带有 MMX, SSE 及 SSE2 扩展的主机 " +"CPU。" #: pcsx2/x86/microVU.cpp:28 #, c-format -msgid "%s Extensions not found. microVU requires a host CPU with MMX, SSE, and SSE2 extensions." +msgid "" +"%s Extensions not found. microVU requires a host CPU with MMX, SSE, and " +"SSE2 extensions." msgstr "%s 扩展未找到。microVU 需要一个带有 MMX, SSE 及 SSE2 扩展的主机 CPU。" +#~ msgid "mVU Block Hack" +#~ msgstr "mVU 数据块 Hack" + +#~ msgid "" +#~ "Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." +#~ msgstr "提速效果较好,兼容性较高;可能导致图像错误等。" + #~ msgid "Enable game fixes" #~ msgstr "启用游戏特殊修正" diff --git a/locales/zh_TW/pcsx2_Iconized.po b/locales/zh_TW/pcsx2_Iconized.po index a6ba50100..1e11e38a3 100644 --- a/locales/zh_TW/pcsx2_Iconized.po +++ b/locales/zh_TW/pcsx2_Iconized.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-09-28 20:27+0200\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: 2011-09-09 11:52+0800\n" "Last-Translator: 呆丸北拜\n" "Language-Team: pcsx2fan\n" @@ -24,7 +24,7 @@ msgstr "" "可用的虛擬記憶體不足,\n" "或必備的虛擬記憶體映射已經被其他處理程序、服務,或 DLL 保留。" -#: pcsx2/CDVD/CDVD.cpp:385 +#: pcsx2/CDVD/CDVD.cpp:390 msgid "!Notice:PsxDisc" msgstr "" "PCSX2 不支援 Playstation 遊戲光碟。\n" @@ -435,33 +435,27 @@ msgstr "" "滑桿控制著 VU 從 EE 偷竊的週期的數目。\n" "數值愈高,遊戲執行的每一個 VU 微程式從 EE 偷的就愈多。" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:172 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "!ContextTip:Speedhacks:vuFlagHack" msgstr "" "僅對讀取狀態旗標的塊,更新狀態旗標,取代一直更新狀態旗標。\n" "大部分時間是安全的,Super VU 預設做類似的事情。" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:177 -msgid "!ContextTip:Speedhacks:vuBlockHack" -msgstr "" -"假定遙遠未來的塊不需要舊的旗標實例資料。\n" -"非常安全。不曉得會不會令遊戲不正常..." - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:182 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:174 msgid "!ContextTip:Speedhacks:vuThread" msgstr "" "microVU1 獨佔一個執行緒。對於 3 核或更多核的 CPU,通常會提升遊戲速度。\n" "對於大多數遊戲是安全的。但是少數遊戲不相容可能會遊戲停止回應。\n" "對顯示卡要求高的遊戲,可能會降低遊戲速度(尤其在雙核心 CPU 上)。" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:203 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:195 msgid "!ContextTip:Speedhacks:INTC" msgstr "" "對於使用 INTC 狀態暫存器等待垂直同步的遊戲,表現最好。\n" "主要包括 RPG 遊戲非 3D 的標題。\n" "不使用此垂直同步方式的遊戲,將會有少量或沒有速度提升。" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:208 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 msgid "!ContextTip:Speedhacks:BIFC0" msgstr "" "主要把核心內位址 0x81FC0 的 EE 空閒循環作為目標。\n" @@ -470,7 +464,7 @@ msgstr "" "這樣的循環重複一次之後,取決於哪個先到:\n" "我們前進到下次事件或處理器時間片段的結束。" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:215 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:207 msgid "!ContextTip:Speedhacks:fastCDVD" msgstr "" "查閱 HDLoader 相容性列表,以確定已知使用這個選項會出現問題的遊戲。\n" @@ -480,20 +474,20 @@ msgstr "" msgid "!ContextTip:Framelimiter:Disable" msgstr "注意:當畫框限制停用時,渦輪加速和慢動作無法使用。" -#: pcsx2/gui/Panels/VideoPanel.cpp:223 +#: pcsx2/gui/Panels/VideoPanel.cpp:227 msgid "!Panel:Frameskip:Heading" msgstr "" "注意:\n" "由於 PS2 的硬體設計,精確的跳框是不可能的。\n" "啟用跳框將導致一些遊戲出現嚴重的圖形錯誤。" -#: pcsx2/gui/Panels/VideoPanel.cpp:302 +#: pcsx2/gui/Panels/VideoPanel.cpp:306 msgid "!ContextTip:GS:SyncMTGS" msgstr "" "啟用這個選項,若您認為多執行緒圖形模式執行緒的同步正在導致模擬器當掉或圖形錯" "誤。" -#: pcsx2/gui/Panels/VideoPanel.cpp:306 +#: pcsx2/gui/Panels/VideoPanel.cpp:310 msgid "!ContextTip:GS:DisableOutput" msgstr "" "移除任何由多執行緒圖形模式的執行緒過載或 GPU 過載引起的效能測試產生的噪音。\n" @@ -518,6 +512,11 @@ msgstr "" "這不是嚴重的錯誤,因為 SuperVU 是過時的。無論如何,您應該使用 microVU 代" "替。:)" +#~ msgid "!ContextTip:Speedhacks:vuBlockHack" +#~ msgstr "" +#~ "假定遙遠未來的塊不需要舊的旗標實例資料。\n" +#~ "非常安全。不曉得會不會令遊戲不正常..." + #~ msgid "!ContextTip:Window:FullscreenExclusive" #~ msgstr "" #~ "可能在 CRT 螢幕上,畫面看起來更好;可能在老舊的顯示卡中,速度稍微快一" diff --git a/locales/zh_TW/pcsx2_Main.po b/locales/zh_TW/pcsx2_Main.po index 7283805c4..1adc50a1d 100644 --- a/locales/zh_TW/pcsx2_Main.po +++ b/locales/zh_TW/pcsx2_Main.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2011-09-28 20:27+0200\n" +"POT-Creation-Date: 2012-02-28 12:20+0100\n" "PO-Revision-Date: 2011-09-08 19:40+0800\n" "Last-Translator: 呆丸北拜\n" "Language-Team: pcsx2fan\n" @@ -175,7 +175,7 @@ msgstr "初始化內部記憶卡插件失敗。" msgid "Unloaded Plugin" msgstr "未載入的插件" -#: pcsx2/SaveState.cpp:339 +#: pcsx2/SaveState.cpp:342 msgid "Cannot load savestate. It is of an unknown or unsupported version." msgstr "無法讀取即時存檔,檔案版本未知或不支援。" @@ -326,31 +326,31 @@ msgid "" "successfully but could not be moved to its final resting place." msgstr "即時存檔未能正確地儲存。成功建立暫存檔,但是無法將其移至目的地。" -#: pcsx2/gui/AppConfig.cpp:837 +#: pcsx2/gui/AppConfig.cpp:842 msgid "Safest" msgstr "最安全" -#: pcsx2/gui/AppConfig.cpp:838 +#: pcsx2/gui/AppConfig.cpp:843 msgid "Safe (faster)" msgstr "安全(速度更快)" -#: pcsx2/gui/AppConfig.cpp:839 +#: pcsx2/gui/AppConfig.cpp:844 msgid "Balanced" msgstr "平衡" -#: pcsx2/gui/AppConfig.cpp:840 +#: pcsx2/gui/AppConfig.cpp:845 msgid "Aggressive" msgstr "激進" -#: pcsx2/gui/AppConfig.cpp:841 +#: pcsx2/gui/AppConfig.cpp:846 msgid "Aggressive plus" msgstr "更加激進" -#: pcsx2/gui/AppConfig.cpp:842 +#: pcsx2/gui/AppConfig.cpp:847 msgid "Mostly Harmful" msgstr "基本上有害" -#: pcsx2/gui/AppConfig.cpp:999 pcsx2/gui/AppConfig.cpp:1005 +#: pcsx2/gui/AppConfig.cpp:1007 pcsx2/gui/AppConfig.cpp:1013 msgid "Failed to overwrite existing settings file; permission was denied." msgstr "覆寫現存的設定檔失敗;沒有權限。" @@ -2327,21 +2327,10 @@ msgstr "" "【推薦】" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:166 -msgid "mVU Block Hack" -msgstr "mVU Block Hack" - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 -msgid "" -"Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." -msgstr "" -"不錯的速度提升而且相容性高;可能導致\n" -"圖像變得糟糕、有尖刺的多邊形,等等..." - -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "MTVU (Multi-Threaded microVU1)" msgstr "MTVU(多執行緒 microVU1)" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:170 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 msgid "" "Good Speedup and High Compatibility; may cause hanging... [Recommended if 3+ " "cores]" @@ -2350,15 +2339,15 @@ msgstr "" "遊戲停止回應...\n" "【推薦 3 核或更多核的 CPU 使用】" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:183 msgid "Other Hacks" msgstr "其他駭客" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:193 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:185 msgid "Enable INTC Spin Detection" msgstr "Enable INTC Spin Detection" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:194 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:186 msgid "" "Huge speedup for some games, with almost no compatibility side effects. " "[Recommended]" @@ -2366,22 +2355,22 @@ msgstr "" "對於一些遊戲有巨大的速度提升,\n" "幾乎沒有相容性副作用【推薦】" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:196 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:188 msgid "Enable Wait Loop Detection" msgstr "Enable Wait Loop Detection" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:197 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:189 msgid "" "Moderate speedup for some games, with no known side effects. [Recommended]" msgstr "" "對於一些遊戲有適度的速度提升,\n" "沒有已知的副作用【推薦】" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:199 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 msgid "Enable fast CDVD" msgstr "Enable fast CDVD" -#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:192 msgid "Fast disc access, less loading times. [Not Recommended]" msgstr "快速讀取光碟,減少載入時間【不推薦】" @@ -2438,7 +2427,7 @@ msgstr "FPS" msgid "PAL Framerate:" msgstr "PAL 遊戲的畫框速率:" -#: pcsx2/gui/Panels/VideoPanel.cpp:162 +#: pcsx2/gui/Panels/VideoPanel.cpp:166 msgid "" "Error while parsing either NTSC or PAL framerate settings. Settings must be " "valid floating point numerics." @@ -2446,19 +2435,19 @@ msgstr "" "當解析 NTSC 遊戲或 PAL 遊戲的畫框速率設定時出現錯誤。設定值必須是有效的浮點" "數。" -#: pcsx2/gui/Panels/VideoPanel.cpp:180 +#: pcsx2/gui/Panels/VideoPanel.cpp:184 msgid "Disabled [default]" msgstr "停用【預設】" -#: pcsx2/gui/Panels/VideoPanel.cpp:184 +#: pcsx2/gui/Panels/VideoPanel.cpp:188 msgid "Skip when on Turbo only (TAB to enable)" msgstr "僅在渦輪加速時跳框(按 TAB 啟動)" -#: pcsx2/gui/Panels/VideoPanel.cpp:188 +#: pcsx2/gui/Panels/VideoPanel.cpp:192 msgid "Constant skipping" msgstr "恆定的跳框" -#: pcsx2/gui/Panels/VideoPanel.cpp:190 +#: pcsx2/gui/Panels/VideoPanel.cpp:194 msgid "" "Normal and Turbo limit rates skip frames. Slow motion mode will still " "disable frameskipping." @@ -2466,19 +2455,19 @@ msgstr "" "普通模式和渦輪加速模式有限制速度,能夠跳框\n" "慢動作模式依然會停用跳框" -#: pcsx2/gui/Panels/VideoPanel.cpp:213 +#: pcsx2/gui/Panels/VideoPanel.cpp:217 msgid "Frames to Draw" msgstr "繪製的畫框" -#: pcsx2/gui/Panels/VideoPanel.cpp:218 +#: pcsx2/gui/Panels/VideoPanel.cpp:222 msgid "Frames to Skip" msgstr "跳過的畫框" -#: pcsx2/gui/Panels/VideoPanel.cpp:294 +#: pcsx2/gui/Panels/VideoPanel.cpp:298 msgid "Use Synchronized MTGS" msgstr "使用同步的多執行緒圖形模式" -#: pcsx2/gui/Panels/VideoPanel.cpp:295 +#: pcsx2/gui/Panels/VideoPanel.cpp:299 msgid "" "For troubleshooting potential bugs in the MTGS only, as it is potentially " "very slow." @@ -2486,11 +2475,11 @@ msgstr "" "僅用於排除多執行緒圖形模式潛在的程式錯誤,\n" "因為速度可能非常慢" -#: pcsx2/gui/Panels/VideoPanel.cpp:298 +#: pcsx2/gui/Panels/VideoPanel.cpp:302 msgid "Disable all GS output" msgstr "停止輸出遊戲畫面" -#: pcsx2/gui/Panels/VideoPanel.cpp:299 +#: pcsx2/gui/Panels/VideoPanel.cpp:303 msgid "" "Completely disables all GS plugin activity; ideal for benchmarking EEcore " "components." @@ -2498,11 +2487,11 @@ msgstr "" "完全停止圖形插件所有的活動;\n" "適合用來做 EEcore 的效能測試" -#: pcsx2/gui/Panels/VideoPanel.cpp:316 +#: pcsx2/gui/Panels/VideoPanel.cpp:320 msgid "Frame Skipping" msgstr "跳框" -#: pcsx2/gui/Panels/VideoPanel.cpp:319 +#: pcsx2/gui/Panels/VideoPanel.cpp:323 msgid "Framelimiter" msgstr "畫框限制" @@ -2576,6 +2565,15 @@ msgid "" "SSE2 extensions." msgstr "%s 指令集未找到。microVU 要求 CPU 支援 MMX、SSE、SSE2。" +#~ msgid "mVU Block Hack" +#~ msgstr "mVU Block Hack" + +#~ msgid "" +#~ "Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." +#~ msgstr "" +#~ "不錯的速度提升而且相容性高;可能導致\n" +#~ "圖像變得糟糕、有尖刺的多邊形,等等..." + #~ msgid "" #~ "Good Speedup and High Compatibility; may cause garbage graphics, SPS, " #~ "etc... [Recommended]" From df5502347443e78fc27a9278a7b5e711d18aa7b2 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Tue, 28 Feb 2012 11:28:31 +0000 Subject: [PATCH 15/83] i18n: new language indonesian git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5107 96395faa-99c1-11dd-bbfe-3dabce05a288 --- bin/Langs/id_ID/pcsx2_Iconized.mo | Bin 0 -> 3540 bytes bin/Langs/id_ID/pcsx2_Main.mo | Bin 0 -> 45182 bytes locales/id_ID/pcsx2_Iconized.po | 328 ++++ locales/id_ID/pcsx2_Main.po | 2665 +++++++++++++++++++++++++++++ 4 files changed, 2993 insertions(+) create mode 100644 bin/Langs/id_ID/pcsx2_Iconized.mo create mode 100644 bin/Langs/id_ID/pcsx2_Main.mo create mode 100644 locales/id_ID/pcsx2_Iconized.po create mode 100644 locales/id_ID/pcsx2_Main.po diff --git a/bin/Langs/id_ID/pcsx2_Iconized.mo b/bin/Langs/id_ID/pcsx2_Iconized.mo new file mode 100644 index 0000000000000000000000000000000000000000..312f559cada4db901bf66af0d0eee560e54f7f8e GIT binary patch literal 3540 zcmbVOO>7%Q6n1~05THPzKq;jgpd4DQ;}}}PP*5G)X{^?X6+3Q`I54p%_H=h=x3jZp zQcehQfdd!lt(=g!a)3%4khsAGE*ud(a6#gR1V<3x+g*F(Z6Yd0T7SFq-n{qbn>X+I z_M!cs6fjQUc?M5yPoZ!c=cfKH1Idz!@#}wByk)9QXF$Bc7f#I z04c5yfn?`1Ao>3eNdA6F<$nQ>Qn_j@4O{TWDc z{Q*1zuJ#-#6i(s$=>18Y=YiAs_JA({KLQdDUjk18e*(?`{{a$j#i?Z71t95P1(N;^ zAnog`RQ@CIB)pUr-qjijM{;iU*w&4IEJc;TI0#c@z)D z{TLqF7mfXR?u*~DAL8V3Jj4M~C(bP#dAv8;XJLBDH?k+Jy4JpCouL-IZ`JVQ`aQ?0 z^o;aXIMQPCjpa6Ls15GQep|RA7H3lFhqcHHR>ajvYSAAHs=iv6+G}rxDrte=_B}p6>++ zTeGgzCgN^FSjEN3?x59B(y#^JH$v|wT|`=JleP_q-GD9m?RLF9UNqsY$%C;Vi~^y% zt2>6%;!3!zUY}_!w;1`sK^3Nx*#+N)+mK}km(FYMiO`Wje!+RnuggslvMMOx#=69{ z+GdcBuday4`jt@%CniaMllgWaM1RP8PRN!wkXuq*8;eZTbCP?Lk7E^S z=;5STeKT;mRFpx9y|E-0S$8$ej9ik}x$d)h+$z?IjISkk3)AWBCE?7g08t6>QcsQQMDnPgE1T%!E z+F(#w=lOu{@T4aa$0Y0|=m?h&YjVj~+%a-}2a;2Qk`BUR4;`U-@Sm#L=`^{)mAixb z3&M$b$ho3+Gip8gAgSq~_vELywV#R`pH|#{?vSKXH W0v}nv`(B2BM%+W2MvFltg?|AEZ}~L< literal 0 HcmV?d00001 diff --git a/bin/Langs/id_ID/pcsx2_Main.mo b/bin/Langs/id_ID/pcsx2_Main.mo new file mode 100644 index 0000000000000000000000000000000000000000..da3828c7ec2f04d6ce086de4663af8f52b0945fc GIT binary patch literal 45182 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, YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: PCSX2 0.9.8 r4560\n" +"Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" +"POT-Creation-Date: 2012-02-28 12:25+0100\n" +"PO-Revision-Date: 2012-01-13 16:56+0700\n" +"Last-Translator: \n" +"Language-Team: ikazu \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-KeywordsList: pxE\n" +"X-Poedit-SourceCharset: utf-8\n" +"X-Poedit-Basepath: trunk\\\n" +"X-Poedit-Language: Indonesian\n" +"X-Poedit-Country: INDONESIA\n" +"X-Poedit-SearchPath-0: pcsx2\n" +"X-Poedit-SearchPath-1: common\n" + +#: common/src/Utilities/Exceptions.cpp:254 +msgid "!Notice:VirtualMemoryMap" +msgstr "!Pemberitahuan:MapVirtualMemory" + +#: pcsx2/CDVD/CDVD.cpp:390 +msgid "!Notice:PsxDisc" +msgstr "!Pemberitahuan:DiscPsx" + +#: pcsx2/System.cpp:114 +msgid "!Notice:Recompiler:VirtualMemoryAlloc" +msgstr "!Pemberitahuan:Recompiler:AlokasiMemoriVirtual" + +#: pcsx2/System.cpp:348 +msgid "!Notice:EmuCore::MemoryForVM" +msgstr "!Pemberitahuan:CoreEmu::MemoriUntukMesinVirtual" + +#: pcsx2/gui/AppInit.cpp:43 +msgid "!Notice:Startup:NoSSE2" +msgstr "!Pemberitahuan:Startup:NoSSE2" + +#: pcsx2/gui/AppInit.cpp:162 +msgid "!Notice:RecompilerInit:Header" +msgstr "!Pemberitahuan:InitRecompiler:Header" + +#: pcsx2/gui/AppInit.cpp:211 +msgid "!Notice:RecompilerInit:Footer" +msgstr "!Pemberitahuan:InitRecompiler:Footer" + +#: pcsx2/gui/AppMain.cpp:546 +msgid "!Notice:BiosDumpRequired" +msgstr "!Pemberitahuan:DumpBiosDiperlukan" + +#: pcsx2/gui/AppMain.cpp:629 +msgid "!Notice Error:Thread Deadlock Actions" +msgstr "!Pemberitahuan Eror:Aksi Deadlock Pada Trit" + +#: pcsx2/gui/AppUserMode.cpp:57 +msgid "!Notice:PortableModeRights" +msgstr "!Pemberitahuan:KekuasaanModePortable" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:181 +msgid "!ContextTip:ChangingNTFS" +msgstr "" + +#: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:49 +#, fuzzy +msgid "!ContextTip:Folders:Settings" +msgstr "!Panel:Folders:Pengaturan" + +#: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:54 +msgid "!Panel:Folders:Settings" +msgstr "!Panel:Folders:Pengaturan" + +#: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:94 +msgid "!Wizard:Welcome" +msgstr "!Wizard:Selamat Datang" + +#: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:140 +msgid "!Wizard:Bios:Tutorial" +msgstr "!Wizard:Bios:Tutorial" + +#: pcsx2/gui/Dialogs/ImportSettingsDialog.cpp:31 +msgid "!Notice:ImportExistingSettings" +msgstr "!Pemberitahuan:ImporPengaturanYangAda" + +#: pcsx2/gui/Dialogs/McdConfigDialog.cpp:30 +msgid "!Panel:Mcd:NtfsCompress" +msgstr "!Panel:Mcd:NtfsCompress" + +#: pcsx2/gui/Dialogs/McdConfigDialog.cpp:41 +msgid "!Panel:Mcd:EnableEjection" +msgstr "!Panel:Mcd:AkifkanEjection" + +#: pcsx2/gui/Dialogs/StuckThreadDialog.cpp:33 +msgid "!Panel:StuckThread:Heading" +msgstr "!Panel:TritSangkut:Heading" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:38 +#, fuzzy +msgid "!Panel:HasHacksOverrides" +msgstr "!Panel:Speedhacks:PenampakanSebagian" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:58 +msgid "!Panel:HasPluginsOverrides" +msgstr "" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:135 +msgid "!Notice:Tooltip:Presets:Slider" +msgstr "" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:149 +msgid "!Notice:Tooltip:Presets:Checkbox" +msgstr "" + +#: pcsx2/gui/IsoDropTarget.cpp:28 +msgid "!Notice:ConfirmSysReset" +msgstr "!Pemberitahuan:KonfirmasiResetSistem" + +#: pcsx2/gui/MainMenuClicks.cpp:106 +msgid "!Notice:DeleteSettings" +msgstr "!Pemberitahuan:HapusPengaturan" + +#: pcsx2/gui/MemoryCardFile.cpp:78 +msgid "!Notice:Mcd:HasBeenDisabled" +msgstr "!Pemberitahuan:Mcd:TelahDiNonaktifkan" + +#: pcsx2/gui/Panels/BiosSelectorPanel.cpp:138 +msgid "!Notice:BIOS:InvalidSelection" +msgstr "!Pemberitahuan:BIOS:PilihanTidakValid" + +#: pcsx2/gui/Panels/CpuPanel.cpp:111 +msgid "!Panel:EE/IOP:Heading" +msgstr "!Panel:EE/IOP:Heading" + +#: pcsx2/gui/Panels/CpuPanel.cpp:178 +msgid "!Panel:VUs:Heading" +msgstr "!Panel:VUs:Heading" + +#: pcsx2/gui/Panels/DirPickerPanel.cpp:69 +msgid "!Notice:DirPicker:CreatePath" +msgstr "!Pemberitahuan:PilihanDirektori:BuatLokasi" + +#: pcsx2/gui/Panels/DirPickerPanel.cpp:158 +#, fuzzy +msgid "!ContextTip:DirPicker:UseDefault" +msgstr "!Pemberitahuan:PilihanDirektori:BuatLokasi" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:55 +msgid "!ContextTip:Window:Zoom" +msgstr "" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:63 +msgid "!ContextTip:Window:Vsync" +msgstr "" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:68 +msgid "!ContextTip:Window:ManagedVsync" +msgstr "" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:76 +msgid "!ContextTip:Window:HideMouse" +msgstr "" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:82 +msgid "!ContextTip:Window:Fullscreen" +msgstr "" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:93 +msgid "!ContextTip:Window:HideGS" +msgstr "" + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:67 +msgid "!ContextTip:Gamefixes:EE Timing Hack" +msgstr "" + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:80 +msgid "!ContextTip:Gamefixes:OPH Flag hack" +msgstr "" + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:89 +msgid "!ContextTip:Gamefixes:DMA Busy hack" +msgstr "" + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:96 +msgid "!ContextTip:Gamefixes:VIF1 FIFO hack" +msgstr "" + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:119 +msgid "!Panel:Gamefixes:Compat Warning" +msgstr "!Panel:PerbaikanPermainan:Peringatan Compat" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:720 +msgid "!Notice:Mcd:Delete" +msgstr "!Pemberitahuan:Mcd:Hapus" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:758 +msgid "!Notice:Mcd:CantDuplicate" +msgstr "!Pemberitahuan:Mcd:TidakBisaDuplikat" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:801 +msgid "!Notice:Mcd:Copy Failed" +msgstr "!Pemberitahuan:Mcd:Salin Gagal" + +#: pcsx2/gui/Panels/MiscPanelStuff.cpp:35 +msgid "!Panel:Usermode:Explained" +msgstr "!Panel:Modepengguna:Terjelaskan" + +#: pcsx2/gui/Panels/MiscPanelStuff.cpp:41 +msgid "!Panel:Usermode:Warning" +msgstr "!Panel:Modepengguna:Peringatan" + +#: pcsx2/gui/Panels/PathsPanel.cpp:40 +#, fuzzy +msgid "!ContextTip:Folders:Savestates" +msgstr "!Panel:Folders:Pengaturan" + +#: pcsx2/gui/Panels/PathsPanel.cpp:50 +msgid "!ContextTip:Folders:Snapshots" +msgstr "" + +#: pcsx2/gui/Panels/PathsPanel.cpp:60 +msgid "!ContextTip:Folders:Logs" +msgstr "" + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:242 +msgid "!Notice:PluginSelector:ConfirmShutdown" +msgstr "!Pemberitahuan:PilihanPlugin:KonfirmasiMatikan" + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:457 +msgid "!Notice:PluginSelector:ApplyFailed" +msgstr "!Pemberitahuan:PilihanPlugin:GagalTerapkan" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:27 +#, fuzzy +msgid "!Panel:Speedhacks:EECycleX1" +msgstr "!Panel:Speedhacks:PenampakanSebagian" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:32 +#, fuzzy +msgid "!Panel:Speedhacks:EECycleX2" +msgstr "!Panel:Speedhacks:PenampakanSebagian" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:37 +#, fuzzy +msgid "!Panel:Speedhacks:EECycleX3" +msgstr "!Panel:Speedhacks:PenampakanSebagian" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:54 +#, fuzzy +msgid "!Panel:Speedhacks:VUCycleStealOff" +msgstr "!Panel:Speedhacks:PenampakanSebagian" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:59 +#, fuzzy +msgid "!Panel:Speedhacks:VUCycleSteal1" +msgstr "!Panel:Speedhacks:PenampakanSebagian" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:64 +#, fuzzy +msgid "!Panel:Speedhacks:VUCycleSteal2" +msgstr "!Panel:Speedhacks:PenampakanSebagian" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:70 +#, fuzzy +msgid "!Panel:Speedhacks:VUCycleSteal3" +msgstr "!Panel:Speedhacks:PenampakanSebagian" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:97 +msgid "!Panel:Speedhacks:Overview" +msgstr "!Panel:Speedhacks:PenampakanSebagian" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:129 +msgid "!ContextTip:Speedhacks:EECycleRate Slider" +msgstr "" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:150 +msgid "!ContextTip:Speedhacks:VUCycleStealing Slider" +msgstr "" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 +msgid "!ContextTip:Speedhacks:vuFlagHack" +msgstr "" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:174 +#, fuzzy +msgid "!ContextTip:Speedhacks:vuThread" +msgstr "!Panel:Speedhacks:PenampakanSebagian" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:195 +msgid "!ContextTip:Speedhacks:INTC" +msgstr "" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 +msgid "!ContextTip:Speedhacks:BIFC0" +msgstr "" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:207 +msgid "!ContextTip:Speedhacks:fastCDVD" +msgstr "" + +#: pcsx2/gui/Panels/VideoPanel.cpp:37 +msgid "!ContextTip:Framelimiter:Disable" +msgstr "" + +#: pcsx2/gui/Panels/VideoPanel.cpp:227 +msgid "!Panel:Frameskip:Heading" +msgstr "!Panel:Frameskip:Heading" + +#: pcsx2/gui/Panels/VideoPanel.cpp:306 +msgid "!ContextTip:GS:SyncMTGS" +msgstr "" + +#: pcsx2/gui/Panels/VideoPanel.cpp:310 +msgid "!ContextTip:GS:DisableOutput" +msgstr "" + +#: pcsx2/vtlb.cpp:710 +msgid "!Notice:HostVmReserve" +msgstr "!Pemberitahuan:HostVmReserve" + +#: pcsx2/x86/sVU_zerorec.cpp:363 +msgid "!Notice:superVU:VirtualMemoryAlloc" +msgstr "!Pemberitahuan:superVU:AlokasiMemoriVirtual" diff --git a/locales/id_ID/pcsx2_Main.po b/locales/id_ID/pcsx2_Main.po new file mode 100644 index 000000000..361f60ba3 --- /dev/null +++ b/locales/id_ID/pcsx2_Main.po @@ -0,0 +1,2665 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR PCSX2_Dev_Team +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: PCSX2 0.9.8 r4560\n" +"Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" +"POT-Creation-Date: 2012-02-28 12:25+0100\n" +"PO-Revision-Date: 2012-01-06 21:54+0700\n" +"Last-Translator: \n" +"Language-Team: ikazu \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-KeywordsList: _;pxL\n" +"X-Poedit-SourceCharset: utf-8\n" +"X-Poedit-Basepath: trunk\\\n" +"X-Poedit-Language: Indonesian\n" +"X-Poedit-Country: INDONESIA\n" +"X-Poedit-SearchPath-0: pcsx2\n" +"X-Poedit-SearchPath-1: common\n" + +#: common/include/Utilities/Exceptions.h:187 +msgid "No reason given." +msgstr "" + +#: common/include/Utilities/Exceptions.h:226 +msgid "Parse error" +msgstr "Unpacking gagal" + +#: common/include/Utilities/Exceptions.h:250 +msgid "Your machine's hardware is incapable of running PCSX2. Sorry dood." +msgstr "Hardware Anda tidak mampu menjalnkan PCSX2. Sorry sobat." + +#: common/src/Utilities/Exceptions.cpp:219 +msgid "Oh noes! Out of memory!" +msgstr "Oh tidak! Memori tidak mencukupi!" + +#: common/src/Utilities/Exceptions.cpp:234 +msgid "" +"Virtual memory mapping failure! Your system may have conflicting device " +"drivers, services, or may simply have insufficient memory or resources to " +"meet PCSX2's lofty needs." +msgstr "" +"Mapping virtual memori gagal! Sistem anda mungkin telah mengkonflik device " +"drivers, services, atau bisa jadi kekurangan memori dan sumber daya lainnya " +"untuk memenuhi kebutuhan PCSX2 yang berat." + +#: common/src/Utilities/Exceptions.cpp:309 +msgid "Path: " +msgstr "Lokasi:" + +#: common/src/Utilities/Exceptions.cpp:313 +msgid "[Unnamed or unknown]" +msgstr "[Tidak bernama atau tidak dikenal]" + +#: common/src/Utilities/Exceptions.cpp:333 +msgid "A file could not be created." +msgstr "Sebuah file tidak dapat dibuat." + +#: common/src/Utilities/Exceptions.cpp:353 +msgid "File not found." +msgstr "File tidak ketemu." + +#: common/src/Utilities/Exceptions.cpp:373 +msgid "" +"Permission denied while trying to open file, likely due to insufficient user " +"account rights." +msgstr "" +"Izin tertolak ketika membuka file, kemungkinan dikarenakan kurangnya kuasa " +"pengguna akun komputer." + +#: common/src/Utilities/Exceptions.cpp:393 +msgid "" +"Unexpected end of file or stream encountered. File is probably truncated or " +"corrupted." +msgstr "Eror yang tidak disangka terjadi. File mungkin rusak atau korup." + +#: common/src/Utilities/ThreadTools.cpp:41 +msgid "Threading activity: start, detach, sync, deletion, etc." +msgstr "" + +#: common/src/Utilities/ThreadingDialogs.cpp:30 +msgid "Waiting for tasks..." +msgstr "Sedang menunggu beberapa tugas..." + +#: common/src/Utilities/ThreadingDialogs.cpp:41 +msgid "Waiting for task..." +msgstr "Sedang menunggu tugas..." + +#: common/src/Utilities/wxAppWithHelpers.cpp:36 +msgid "Includes idle event processing and some other uncommon event usages." +msgstr "" + +#: pcsx2/CDVD/IsoFileFormats.cpp:416 +msgid "Unrecognized ISO image file format" +msgstr "File format ISO tak dikenal" + +#: pcsx2/Elfheader.cpp:266 +msgid "Cannot load ELF binary image. The file may be corrupt or incomplete." +msgstr "Load file image ELF gagal. File mungkin korup atau tidak utuh." + +#: pcsx2/Elfheader.cpp:268 +msgid "" +"If loading from an ISO image, this error may be caused by an unsupported ISO " +"image type or a bug in PCSX2 ISO image support." +msgstr "" +"Bila menjalankan dari file ISO, kegagalan ini mungkin disebabkan oleh jenis " +"file ISO yang tidak didukung oleh PCSX2 atau sebuah bug pada pembacaan file " +"ISO PCSX2 sendiri." + +#: pcsx2/MTGS.cpp:859 +msgid "" +"The MTGS thread has become unresponsive while waiting for the GS plugin to " +"open." +msgstr "" + +#: pcsx2/PluginManager.cpp:709 +msgid "" +"The savestate cannot be loaded, as it appears to be corrupt or incomplete." +msgstr "" +"Savestate yang terpilih tidak mau diload, kelihatannya korup atau tidak utuh." + +#: pcsx2/PluginManager.cpp:719 +#, c-format +msgid "" +"%s plugin failed to open. Your computer may have insufficient resources, or " +"incompatible hardware/drivers." +msgstr "" +"plugin %s gagal untuk dibuka. Komputer Anda mungkin kekurangan media, atau " +"perangkat keras/drivers yang tidak cocok." + +#: pcsx2/PluginManager.cpp:726 +#, c-format +msgid "" +"%s plugin failed to initialize. Your system may have insufficient memory or " +"resources needed." +msgstr "" +"plugin %s gagal untuk dijalankan. Sistem anda mungkin kekurangan memori " +"atau media lain dibutuhkan." + +#: pcsx2/PluginManager.cpp:832 +#, c-format +msgid "The configured %s plugin file was not found" +msgstr "File %s yang telah dikonfigurasi tidak ditemukan" + +#: pcsx2/PluginManager.cpp:836 +#, c-format +msgid "The configured %s plugin file is not a valid dynamic library" +msgstr "" +"File plugin %s yang telah dikonfigurasi bukanlah sebuah file dll yg valid" + +#: pcsx2/PluginManager.cpp:854 +#, c-format +msgid "" +"The configured %s plugin is not a PCSX2 plugin, or is for an older " +"unsupported version of PCSX2." +msgstr "" +"File plugin %s bukanlah sebuah plugin PCSX2, atau merupakan plugin lama yang " +"tidak didukung PCSX2." + +#: pcsx2/PluginManager.cpp:879 +msgid "" +"The plugin reports that your hardware or software/drivers are not supported." +msgstr "" +"Plugin tersebut menyatakan perangkat keras atau perangkat lunak/drivers Anda " +"tidak didukung." + +#: pcsx2/PluginManager.cpp:900 +msgid "" +"Configured plugin is not a PCSX2 plugin, or is for an older unsupported " +"version of PCSX2." +msgstr "" +"Plugin yang telah dikonfigurasi bukanlah sebuah plugin PCSX2, atau merupakan " +"plugin lama yang tidak dukung PCSX2." + +#: pcsx2/PluginManager.cpp:926 +#, c-format +msgid "" +"Configured %s plugin is not a valid PCSX2 plugin, or is for an older " +"unsupported version of PCSX2." +msgstr "" +"Plugin %s bukanlah sebuah plugin PCSX2 yg valid, atau merupakan plugin lama " +"yang tidak didukung PCSX2." + +#: pcsx2/PluginManager.cpp:1355 +msgid "Internal Memorycard Plugin failed to initialize." +msgstr "" + +#: pcsx2/PluginManager.cpp:1752 +msgid "Unloaded Plugin" +msgstr "Plugin yang jalam" + +#: pcsx2/SaveState.cpp:342 +msgid "Cannot load savestate. It is of an unknown or unsupported version." +msgstr "" +"Tidak bisa meng-load savestate. Savestate tersebut tidak dikenal atau tidak " +"didukung." + +#: pcsx2/SourceLog.cpp:96 +msgid "Dumps detailed information for PS2 executables (ELFs)." +msgstr "" + +#: pcsx2/SourceLog.cpp:101 +msgid "" +"Logs manual protection, split blocks, and other things that might impact " +"performance." +msgstr "" + +#: pcsx2/SourceLog.cpp:106 +msgid "Shows the game developer's logging text (EE processor)" +msgstr "" + +#: pcsx2/SourceLog.cpp:111 +msgid "Shows the game developer's logging text (IOP processor)" +msgstr "" + +#: pcsx2/SourceLog.cpp:116 +msgid "Shows DECI2 debugging logs (EE processor)" +msgstr "" + +#: pcsx2/SourceLog.cpp:145 +msgid "SYSCALL and DECI2 activity." +msgstr "" + +#: pcsx2/SourceLog.cpp:151 +msgid "Direct memory accesses to unknown or unmapped EE memory space." +msgstr "" + +#: pcsx2/SourceLog.cpp:157 pcsx2/SourceLog.cpp:276 +msgid "Disasm of executing core instructions (excluding COPs and CACHE)." +msgstr "" + +#: pcsx2/SourceLog.cpp:163 +msgid "Disasm of COP0 instructions (MMU, cpu and dma status, etc)." +msgstr "" + +#: pcsx2/SourceLog.cpp:169 +msgid "Disasm of the EE's floating point unit (FPU) only." +msgstr "" + +#: pcsx2/SourceLog.cpp:175 +msgid "Disasm of the EE's VU0macro co-processor instructions." +msgstr "" + +#: pcsx2/SourceLog.cpp:181 +msgid "Execution of EE cache instructions." +msgstr "" + +#: pcsx2/SourceLog.cpp:187 +msgid "" +"All known hardware register accesses (very slow!); not including sub filter " +"options below." +msgstr "" + +#: pcsx2/SourceLog.cpp:193 pcsx2/SourceLog.cpp:294 +msgid "Logs only unknown, unmapped, or unimplemented register accesses." +msgstr "" + +#: pcsx2/SourceLog.cpp:199 pcsx2/SourceLog.cpp:300 +msgid "Logs only DMA-related registers." +msgstr "" + +#: pcsx2/SourceLog.cpp:205 +msgid "IPU activity: hardware registers, decoding operations, DMA status, etc." +msgstr "" + +#: pcsx2/SourceLog.cpp:211 +msgid "All GIFtag parse activity; path index, tag type, etc." +msgstr "" + +#: pcsx2/SourceLog.cpp:217 +msgid "All VIFcode processing; command, tag style, interrupts." +msgstr "" + +#: pcsx2/SourceLog.cpp:223 +msgid "All processing involved in Path3 Masking" +msgstr "" + +#: pcsx2/SourceLog.cpp:229 +msgid "Scratchpad's MFIFO activity." +msgstr "" + +#: pcsx2/SourceLog.cpp:235 +msgid "Actual data transfer logs, bus right arbitration, stalls, etc." +msgstr "" + +#: pcsx2/SourceLog.cpp:241 +msgid "Tracks all EE counters events and some counter register activity." +msgstr "" + +#: pcsx2/SourceLog.cpp:247 +msgid "Dumps various VIF and VIFcode processing data." +msgstr "" + +#: pcsx2/SourceLog.cpp:253 +msgid "Dumps various GIF and GIFtag parsing data." +msgstr "" + +#: pcsx2/SourceLog.cpp:264 +msgid "SYSCALL and IRX activity." +msgstr "" + +#: pcsx2/SourceLog.cpp:270 +msgid "Direct memory accesses to unknown or unmapped IOP memory space." +msgstr "" + +#: pcsx2/SourceLog.cpp:282 +msgid "Disasm of the IOP's GPU co-processor instructions." +msgstr "" + +#: pcsx2/SourceLog.cpp:288 +msgid "" +"All known hardware register accesses, not including the sub-filters below." +msgstr "" + +#: pcsx2/SourceLog.cpp:306 +msgid "Memorycard reads, writes, erases, terminators, and other processing." +msgstr "" + +#: pcsx2/SourceLog.cpp:312 +msgid "Gamepad activity on the SIO." +msgstr "" + +#: pcsx2/SourceLog.cpp:318 +msgid "Actual DMA event processing and data transfer logs." +msgstr "" + +#: pcsx2/SourceLog.cpp:324 +msgid "Tracks all IOP counters events and some counter register activity." +msgstr "" + +#: pcsx2/SourceLog.cpp:330 +msgid "Detailed logging of CDVD hardware." +msgstr "" + +#: pcsx2/System.h:206 pcsx2/System.h:207 pcsx2/System.h:208 +msgid "PCSX2 Message" +msgstr "Pesan PCSX2" + +#: pcsx2/ZipTools/thread_gzip.cpp:82 +msgid "" +"The savestate was not properly saved. The temporary file was created " +"successfully but could not be moved to its final resting place." +msgstr "" +"Savestate tersebut tidak di-save dengan baik. File sementara telah dibuat " +"namun tidak dapat dipindah ke tempat peristirahatan akhir." + +#: pcsx2/gui/AppConfig.cpp:842 +msgid "Safest" +msgstr "" + +#: pcsx2/gui/AppConfig.cpp:843 +msgid "Safe (faster)" +msgstr "" + +#: pcsx2/gui/AppConfig.cpp:844 +msgid "Balanced" +msgstr "" + +#: pcsx2/gui/AppConfig.cpp:845 +msgid "Aggressive" +msgstr "" + +#: pcsx2/gui/AppConfig.cpp:846 +msgid "Aggressive plus" +msgstr "" + +#: pcsx2/gui/AppConfig.cpp:847 +msgid "Mostly Harmful" +msgstr "" + +#: pcsx2/gui/AppConfig.cpp:1007 pcsx2/gui/AppConfig.cpp:1013 +msgid "Failed to overwrite existing settings file; permission was denied." +msgstr "Gagal untuk menulis ulang pengaturan lama; izin ditolak." + +#: pcsx2/gui/AppCorePlugins.cpp:404 +msgid "Loading PS2 system plugins..." +msgstr "Sedang meng-load sistem plugin PS2..." + +#: pcsx2/gui/AppInit.cpp:41 +msgid "PCSX2 - SSE2 Recommended" +msgstr "PCSX2 - direkomendasikan SSE2" + +#: pcsx2/gui/AppInit.cpp:71 +msgid "" +"SSE extensions are not available. PCSX2 requires a cpu that supports the " +"SSE instruction set." +msgstr "" +"Ekstensi SSE tidak terdaftar. PCSX2 memerlukan sebuah cpu yang mendukung " +"instruksi SSE." + +#: pcsx2/gui/AppInit.cpp:154 +msgid "PCSX2 Recompiler Error(s)" +msgstr "Eror Recompiler PCSX2 " + +#: pcsx2/gui/AppInit.cpp:227 +msgid "All options are for the current session only and will not be saved.\n" +msgstr "Semua opsi adalah untuk sesi kini saja dan tidak akan disimpan.\n" + +#: pcsx2/gui/AppInit.cpp:237 pcsx2/gui/AppMain.cpp:299 +msgid "IsoFile" +msgstr "FileIso" + +#: pcsx2/gui/AppInit.cpp:238 +msgid "displays this list of command line options" +msgstr "menampilkan beberapa opsi command-line" + +#: pcsx2/gui/AppInit.cpp:239 +msgid "forces the program log/console to be visible" +msgstr "memaksa log program/console menjadi tampak" + +#: pcsx2/gui/AppInit.cpp:240 +msgid "use fullscreen GS mode" +msgstr "menggunakan mode fullscreen GS" + +#: pcsx2/gui/AppInit.cpp:241 +msgid "use windowed GS mode" +msgstr "menggunakan mode windowed GS" + +#: pcsx2/gui/AppInit.cpp:243 +msgid "disables display of the gui while running games" +msgstr "menghilangkan tampilan gui ketika game sedang jalan" + +#: pcsx2/gui/AppInit.cpp:244 +msgid "executes an ELF image" +msgstr "eksekusi sebuah file ELF" + +#: pcsx2/gui/AppInit.cpp:245 +msgid "boots an empty dvd tray; use to enter the PS2 system menu" +msgstr "" +"menalankan sebuah dvd kosong; berguna untuk masuk kedalam menu sistem PS2" + +#: pcsx2/gui/AppInit.cpp:246 +msgid "boots from the CDVD plugin (overrides IsoFile parameter)" +msgstr "menjalankan plugin CDVD (menggantikan parameter FileIso)" + +#: pcsx2/gui/AppInit.cpp:248 +msgid "disables all speedhacks" +msgstr "menghilangkan semua speedhacks" + +#: pcsx2/gui/AppInit.cpp:249 +msgid "use the specified comma or pipe-delimited list of gamefixes." +msgstr "" +"menggunakan koma yang telah dispesifikkan atau daftar gamefixes yang telah " +"dibatasi." + +#: pcsx2/gui/AppInit.cpp:250 +msgid "disables fast booting" +msgstr "menonaktifkan fast booting" + +#: pcsx2/gui/AppInit.cpp:252 +msgid "changes the configuration file path" +msgstr "mengubah lokasi konfigurasi file" + +#: pcsx2/gui/AppInit.cpp:253 +msgid "specifies the PCSX2 configuration file to use" +msgstr "memasukkan file konfigurasi untuk digunakan PCSX2" + +#: pcsx2/gui/AppInit.cpp:254 +#, c-format +msgid "forces %s to start the First-time Wizard" +msgstr "memaksa %s untuk menjalankan tampilan First-time" + +#: pcsx2/gui/AppInit.cpp:255 +msgid "enables portable mode operation (requires admin/root access)" +msgstr "mengaktifkan mode operasi portable (membutuhkan admin/akses root)" + +#: pcsx2/gui/AppInit.cpp:259 +#, c-format +msgid "specify the file to use as the %s plugin" +msgstr "memasukkan file yang digunakan sebagai plugin %s" + +#: pcsx2/gui/AppInit.cpp:307 +#, c-format +msgid "Plugin Override Error - %s" +msgstr "Eror pada saat penulisan ulang plugin - %s" + +#: pcsx2/gui/AppInit.cpp:310 +#, c-format +msgid "" +"%s Plugin Override Error! The following file does not exist or is not a " +"valid %s plugin:\n" +"\n" +msgstr "" +"%s Eror pada saat penulisan ulang plugin! File tersebut tidak terdaftar " +"atau bukan plugin %s yang valid:\n" + +#: pcsx2/gui/AppInit.cpp:317 +#, c-format +msgid "Press OK to use the default configured plugin, or Cancel to close %s." +msgstr "" +"Klik OK untuk menjalankan plugin biasa yang telah dikonfigurasi, atau Batal " +"untuk menutup %s." + +#: pcsx2/gui/AppInit.cpp:496 +msgid "PCSX2 Error: Hardware Deficiency" +msgstr "Eror PCSX2: Defisiensi Perangkat Keras" + +#: pcsx2/gui/AppInit.cpp:496 pcsx2/gui/AppInit.cpp:508 +#, c-format +msgid "Press OK to close %s." +msgstr "Klik OK untuk menutup %s." + +#: pcsx2/gui/AppInit.cpp:509 +#, c-format +msgid "%s Critical Error" +msgstr "Eror berat pada %s" + +#: pcsx2/gui/AppInit.cpp:679 +msgid "OK" +msgstr "OK" + +#: pcsx2/gui/AppInit.cpp:680 +msgid "&OK" +msgstr "&OK" + +#: pcsx2/gui/AppInit.cpp:681 +msgid "Cancel" +msgstr "Batal" + +#: pcsx2/gui/AppInit.cpp:682 +msgid "&Cancel" +msgstr "&Batal" + +#: pcsx2/gui/AppInit.cpp:683 +msgid "&Apply" +msgstr "&Terapkan" + +#: pcsx2/gui/AppInit.cpp:684 +msgid "&Next >" +msgstr "&Lanjut >" + +#: pcsx2/gui/AppInit.cpp:685 +msgid "< &Back" +msgstr "< &Kembali" + +#: pcsx2/gui/AppInit.cpp:686 +msgid "&Back" +msgstr "&Kembali" + +#: pcsx2/gui/AppInit.cpp:687 +msgid "&Finish" +msgstr "&Mengakhiri" + +#: pcsx2/gui/AppInit.cpp:688 +msgid "&Yes" +msgstr "&Ya" + +#: pcsx2/gui/AppInit.cpp:689 +msgid "&No" +msgstr "&Tidak" + +#: pcsx2/gui/AppInit.cpp:690 +msgid "Browse" +msgstr "Cari" + +#: pcsx2/gui/AppInit.cpp:691 +msgid "&Save" +msgstr "&Save" + +#: pcsx2/gui/AppInit.cpp:692 +msgid "Save &As..." +msgstr "Save &Sebagai..." + +#: pcsx2/gui/AppInit.cpp:693 +msgid "&Help" +msgstr "&Bantuan" + +#: pcsx2/gui/AppInit.cpp:694 +msgid "&Home" +msgstr "&Rumah" + +#: pcsx2/gui/AppInit.cpp:696 +msgid "Show about dialog" +msgstr "Tampilkan mengenai dialog" + +#: pcsx2/gui/AppMain.cpp:87 +msgid "" +"\n" +"\n" +"Press Ok to go to the Plugin Configuration Panel." +msgstr "" +"\n" +"\n" +"Klik Ok untuk memasuki Panel Konfigurasi Plugin." + +#: pcsx2/gui/AppMain.cpp:140 pcsx2/gui/AppMain.cpp:154 +msgid "" +"Warning! System plugins have not been loaded. PCSX2 may be inoperable." +msgstr "" +"Peringatan! Sistem plugin belum dijalankan. PCSX2 mungkin tidak dapat " +"beroperasi." + +#: pcsx2/gui/AppMain.cpp:309 +#, c-format +msgid "%s Commandline Options" +msgstr "%s Opsi Commandline" + +#: pcsx2/gui/AppMain.cpp:573 +msgid "PS2 BIOS Error" +msgstr "Eror BIOS PS2" + +#: pcsx2/gui/AppMain.cpp:574 +msgid "Press Ok to go to the BIOS Configuration Panel." +msgstr "Klik Ok untuk memasuki Panel Konfigurasi BIOS." + +#: pcsx2/gui/AppMain.cpp:626 +msgid "PCSX2 Unresponsive Thread" +msgstr "PCSX2 Tidak Respon" + +#: pcsx2/gui/AppMain.cpp:636 +msgid "Terminate" +msgstr "Gagalkan" + +#: pcsx2/gui/AppMain.cpp:963 +msgid "Executing PS2 Virtual Machine..." +msgstr "Sedang meng-eksekusi Mesin Virtual PS2..." + +#: pcsx2/gui/AppRes.cpp:72 +msgid "Browse for an Iso that is not in your recent history." +msgstr "Cari sebuah Iso yang tidak terdaftar dalam riwayat akhir Anda." + +#: pcsx2/gui/AppRes.cpp:72 +msgid "Browse..." +msgstr "Cari..." + +#: pcsx2/gui/AppUserMode.cpp:99 +msgid "The following folders exist, but are not writable:" +msgstr "Folders berikut ada, tetapi tidak dapat diubah:" + +#: pcsx2/gui/AppUserMode.cpp:104 +msgid "The following folders are missing and cannot be created:" +msgstr "Folder folder berikut hilang dan tidak dapat dibuat:" + +#: pcsx2/gui/AppUserMode.cpp:144 +#, c-format +msgid "Portable mode error - %s" +msgstr "Mode portable eror - %s" + +#: pcsx2/gui/AppUserMode.cpp:157 +msgid "" +"PCSX2 has been installed as a portable application but cannot run due to the " +"following errors:" +msgstr "" +"PCSX2 telah diinstal sebagai aplikasi portable namun tidak jalan dikarena " +"eror berikut:" + +#: pcsx2/gui/AppUserMode.cpp:165 +msgid "Switch to User Documents Mode" +msgstr "Beralih ke Mode User Documents" + +#: pcsx2/gui/AppUserMode.cpp:178 +#, c-format +msgid "%s is switching to local install mode." +msgstr "&s sedang beralih ke mode instalasi lokal." + +#: pcsx2/gui/AppUserMode.cpp:179 +msgid "" +"Try to remove the file called \"portable.ini\" from your installation " +"directory manually." +msgstr "" +"Coba hapus file \"portable.ini\" dari direktori instalasi Anda secara manual." + +#: pcsx2/gui/ApplyState.h:55 +msgid "Cannot apply new settings, one of the settings is invalid." +msgstr "" +"Gagal menjalankan pengaturan baru, salah satu dari aturan tersebut tidak " +"valid." + +#: pcsx2/gui/ConsoleLogger.cpp:120 +msgid "Save log question" +msgstr "Simpan pertanyaan log" + +#: pcsx2/gui/ConsoleLogger.cpp:413 +msgid "Fits a lot of log in a microcosmically small area." +msgstr "" + +#: pcsx2/gui/ConsoleLogger.cpp:413 +msgid "Small" +msgstr "Kecil" + +#: pcsx2/gui/ConsoleLogger.cpp:415 +msgid "It's what I use (the programmer guy)." +msgstr "" + +#: pcsx2/gui/ConsoleLogger.cpp:415 pcsx2/gui/Panels/CpuPanel.cpp:38 +msgid "Normal" +msgstr "Normal" + +#: pcsx2/gui/ConsoleLogger.cpp:417 +msgid "Its nice and readable." +msgstr "" + +#: pcsx2/gui/ConsoleLogger.cpp:417 +msgid "Large" +msgstr "Besar" + +#: pcsx2/gui/ConsoleLogger.cpp:419 +msgid "Huge" +msgstr "Sangat Besar" + +#: pcsx2/gui/ConsoleLogger.cpp:419 +msgid "In case you have a really high res display." +msgstr "" + +#: pcsx2/gui/ConsoleLogger.cpp:423 +msgid "Default soft-tone color scheme." +msgstr "" + +#: pcsx2/gui/ConsoleLogger.cpp:423 +msgid "Light theme" +msgstr "Tema terang" + +#: pcsx2/gui/ConsoleLogger.cpp:424 +msgid "" +"Classic black color scheme for people who enjoy having text seared into " +"their optic nerves." +msgstr "" + +#: pcsx2/gui/ConsoleLogger.cpp:424 +msgid "Dark theme" +msgstr "Tema gelap" + +#: pcsx2/gui/ConsoleLogger.cpp:427 +msgid "Always on Top" +msgstr "Selalu di Atas" + +#: pcsx2/gui/ConsoleLogger.cpp:428 +msgid "" +"When checked the log window will be visible over other foreground windows." +msgstr "" + +#: pcsx2/gui/ConsoleLogger.cpp:430 +msgid "&Save..." +msgstr "&Save..." + +#: pcsx2/gui/ConsoleLogger.cpp:430 +msgid "Save log contents to file" +msgstr "Simpan konten log ke file" + +#: pcsx2/gui/ConsoleLogger.cpp:431 +msgid "C&lear" +msgstr "C&lear" + +#: pcsx2/gui/ConsoleLogger.cpp:431 +msgid "Clear the log window contents" +msgstr "Hapus konten log window" + +#: pcsx2/gui/ConsoleLogger.cpp:433 pcsx2/gui/Dialogs/SysConfigDialog.cpp:280 +msgid "Appearance" +msgstr "Tampilan" + +#: pcsx2/gui/ConsoleLogger.cpp:435 +msgid "&Close" +msgstr "&Tutup" + +#: pcsx2/gui/ConsoleLogger.cpp:435 +msgid "Close this log window; contents are preserved" +msgstr "Tutup window log ini; konten terjaga" + +#: pcsx2/gui/ConsoleLogger.cpp:439 +msgid "Dev/Verbose" +msgstr "Dev/Verbose" + +#: pcsx2/gui/ConsoleLogger.cpp:439 +msgid "Shows PCSX2 developer logs" +msgstr "Tampilkan log log pengembang PCSX2" + +#: pcsx2/gui/ConsoleLogger.cpp:440 +msgid "CDVD reads" +msgstr "CDVD membaca" + +#: pcsx2/gui/ConsoleLogger.cpp:440 +msgid "Shows disk read activity" +msgstr "Tampilkan aktivitas pembacaan disk" + +#: pcsx2/gui/ConsoleLogger.cpp:457 +msgid "Enable all" +msgstr "Aktifkan semua" + +#: pcsx2/gui/ConsoleLogger.cpp:457 +msgid "Enables all log source filters." +msgstr "Aktifkan semua sumber filtrasi log." + +#: pcsx2/gui/ConsoleLogger.cpp:458 +msgid "Disable all" +msgstr "Nonaktifkan seluruhnya" + +#: pcsx2/gui/ConsoleLogger.cpp:458 +msgid "Disables all log source filters." +msgstr "Nonaktifkan seluruh sumber filtrasi log." + +#: pcsx2/gui/ConsoleLogger.cpp:460 +msgid "&Log" +msgstr "&Log" + +#: pcsx2/gui/ConsoleLogger.cpp:461 +msgid "&Sources" +msgstr "&Sumbersumber" + +#: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:35 +#, c-format +msgid "About %s" +msgstr "Tentang %s" + +#: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:55 +msgid "Betatesting" +msgstr "Betatesting" + +#: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:55 +msgid "Previous versions" +msgstr "Versi sebelumnya" + +#: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:55 +msgid "Webmasters" +msgstr "Webmasters" + +#: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:66 +msgid "Plugin Specialists" +msgstr "Para spesialis Plugin" + +#: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:66 +msgid "Special thanks to" +msgstr "Terima kasih khusus untuk" + +#: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:82 +msgid "Developers" +msgstr "Para pengembang" + +#: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:84 +msgid "Contributors" +msgstr "Para kontribusi" + +#: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:98 +msgid "A Playstation 2 Emulator" +msgstr "Sebuah Emulator Playstation 2" + +#: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:102 +msgid "PCSX2 Official Website and Forums" +msgstr "Situs Resmi dan Forums PCSX2 " + +#: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:106 +msgid "PCSX2 Official Svn Repository at Googlecode" +msgstr "Repository Svn Resmi PCSX2 di Googlecode" + +#: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:110 +msgid "I've seen enough" +msgstr "Saya telah cukup melihat" + +#: pcsx2/gui/Dialogs/AssertionDialog.cpp:23 +msgid "Assertion Failure - " +msgstr "Pernyataan Gagal -" + +#: pcsx2/gui/Dialogs/BaseConfigurationDialog.cpp:193 +msgid "Saves a snapshot of this settings panel to a PNG file." +msgstr "Simpan screenshot dari pengaturan ini ke sebuah file PNG." + +#: pcsx2/gui/Dialogs/BaseConfigurationDialog.cpp:308 +msgid "Save dialog screenshots to..." +msgstr "Simpan screenshot dialog ke..." + +#: pcsx2/gui/Dialogs/BiosSelectorDialog.cpp:31 +msgid "BIOS Selector" +msgstr "Pemilih BIOS" + +#: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:193 +msgid "Do not show this dialog again." +msgstr "Jangan tampilkan dialog ini lagi." + +#: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:199 +msgid "" +"Disables this popup and whatever response you select here will be " +"automatically used from now on." +msgstr "" +"Nonaktifkan popup ini dan respon apapun yang kamu pilih disini akan otomatis " +"digunakan mulai dari sekarang." + +#: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:201 +msgid "" +"The popup will not be shown again. This setting can be undone from the " +"settings panels." +msgstr "" +"Popup ini tidak akan ditampilkan lagi. Pengaturan ini dapat dinonaktifkan " +"dari panel Pengaturan." + +#: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:247 +#: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:292 +msgid "Ignore" +msgstr "Biarkan" + +#: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:278 +msgid "Reset" +msgstr "Reset" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:40 +msgid "Create a new memory card" +msgstr "Buat sebuah memory card baru" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:59 +#: pcsx2/gui/Panels/DirPickerPanel.cpp:74 +#: pcsx2/gui/Panels/DirPickerPanel.cpp:273 +msgid "Create" +msgstr "Buat" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:71 +msgid "New memory card:" +msgstr "Memory card baru:" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:72 +msgid "At folder: " +msgstr "Pada folder:" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:75 +msgid "Select file name: " +msgstr "Pilih nama file:" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:149 +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:855 +#, c-format +msgid "Error (%s)" +msgstr "Eror (%s)" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:150 +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:164 +msgid "Create memory card" +msgstr "Buat memory card" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:163 +msgid "Error: The memory card could not be created." +msgstr "Eror: Memory card tersebut tidak dapat dibuat." + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:177 +msgid "Use NTFS compression when creating this card." +msgstr "Gunakan kompresi NTFS ketika membuat card ini." + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:195 +msgid "8 MB [most compatible]" +msgstr "8 MB [paling cocok]" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:195 +msgid "" +"This is the standard Sony-provisioned size, and is supported by all games " +"and BIOS versions." +msgstr "" +"Ini adalah standar ukuran Sony, dan didukung oleh semua permainan dan versi " +"BIOS." + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:196 +msgid "" +"Always use this option if you want the safest and surest memory card " +"behavior." +msgstr "" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:199 +msgid "16 MB" +msgstr "16 MB" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:199 +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:203 +msgid "" +"A typical size for 3rd-party memory cards which should work with most games." +msgstr "" +"Sebuah memori card yang seharusnya jalan untuk sebagian besar permainan." + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:200 +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:204 +msgid "16 and 32 MB cards have roughly the same compatibility factor." +msgstr "" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:203 +msgid "32 MB" +msgstr "32 MB" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:207 +msgid "64 MB" +msgstr "64 MB" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:207 +msgid "" +"Low compatibility warning: Yes it's very big, but may not work with many " +"games." +msgstr "" +"Peringatan kompatibilitas rendah: Sangat besar, namun tidak jalan untuk " +"sebagian besar permainan." + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:208 +msgid "" +"Use at your own risk. Erratic memory card behavior is possible (though " +"unlikely)." +msgstr "" + +#: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:47 +#, c-format +msgid "Select a folder for %s settings" +msgstr "Pilih sebuah folder untuk pengaturan %s" + +#: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:47 +msgid "Settings" +msgstr "Pengaturan" + +#: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:81 +msgid "Language selector" +msgstr "Pilihan Bahasa" + +#: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:84 +msgid "" +"Change the language only if you need to.\n" +"The system default should be fine for most operating systems." +msgstr "" +"Ubah bahasa ketika Anda benar benar perlu.\n" +"Sistem biasa seharusnya cukup untuk sebagian besar sistem operasi." + +#: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:90 +msgid "Welcome to PCSX2!" +msgstr "Selamat datang ke PCSX2!" + +#: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:104 +msgid "Configuration Guides (online)" +msgstr "Petunjuk Konfigurasi (online)" + +#: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:108 +msgid "Readme / FAQ (Offline/PDF)" +msgstr "Readme / FAQ (Offline/PDF)" + +#: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:117 +#, c-format +msgid "%s First Time Configuration" +msgstr "%s Konfigurasi Pertama Kali" + +#: pcsx2/gui/Dialogs/GameDatabaseDialog.cpp:24 +#, c-format +msgid "Game database - %s" +msgstr "Database permainan - %s" + +#: pcsx2/gui/Dialogs/ImportSettingsDialog.cpp:24 +msgid "Import Existing Settings?" +msgstr "Impor Pengaturan yang sudah ada?" + +#: pcsx2/gui/Dialogs/ImportSettingsDialog.cpp:39 +msgid "Import" +msgstr "Impor" + +#: pcsx2/gui/Dialogs/ImportSettingsDialog.cpp:40 +msgid "Overwrite" +msgstr "Buat ulang" + +#: pcsx2/gui/Dialogs/LogOptionsDialog.cpp:27 +msgid "Trace Logging" +msgstr "Jajak Logging" + +#: pcsx2/gui/Dialogs/McdConfigDialog.cpp:40 +msgid "Auto-eject memory cards when loading savestates" +msgstr "Otomatis mengeluarkan memory cards ketika meng-load savestate" + +#: pcsx2/gui/Dialogs/McdConfigDialog.cpp:96 +msgid "MemoryCard Manager" +msgstr "Manager MemoryCard" + +#: pcsx2/gui/Dialogs/McdConfigDialog.cpp:112 +msgid "Drag cards to or from PS2-ports" +msgstr "Tarik cards ke PS2-ports atau dari PS2-ports" + +#: pcsx2/gui/Dialogs/McdConfigDialog.cpp:113 +msgid "" +"\n" +"Note: Duplicate/Rename/Create/Delete will NOT be reverted with 'Cancel'." +msgstr "" +"\n" +"Catatan: Gandakan/Ganti Nama/Buat/Hapus TIDAK akan dikembalikan ulang dengan " +"'Batal'." + +#: pcsx2/gui/Dialogs/PickUserModeDialog.cpp:24 +msgid "PCSX2 First Time configuration" +msgstr "PCSX2 Konfigurasi Pertama kali" + +#: pcsx2/gui/Dialogs/PickUserModeDialog.cpp:29 +#, c-format +msgid "%s is starting from a new or unknown folder and needs to be configured." +msgstr "" +"%s sedang memulai dari sebuah folder baru atau tidak dikenal dan perlu " +"dikonfigurasi." + +#: pcsx2/gui/Dialogs/StuckThreadDialog.cpp:28 +msgid "PCSX2 Thread is not responding" +msgstr "Trit PCSX2 tidak merespon" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:36 +msgid "Config Overrides Warning" +msgstr "Peringatan Penggantian Konfigurasi" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:56 +msgid "Components Overrides Warning" +msgstr "Peringatan Perubahan Komponen" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:147 +msgid "Preset:" +msgstr "Kini:" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:228 +#, c-format +msgid "Emulation Settings - %s" +msgstr "Pengaturan Emulasi - %s" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:237 +msgid "EE/IOP" +msgstr "EE/IOP" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:238 +msgid "VUs" +msgstr "VUs" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:239 +msgid "GS" +msgstr "GS" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:240 +msgid "GS Window" +msgstr "Tampilan GS" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:241 +msgid "Speedhacks" +msgstr "Speedhacks" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:242 +msgid "Game Fixes" +msgstr "Perbaikan untuk Permainan" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:253 +#, c-format +msgid "Components Selectors - %s" +msgstr "Pemilihan Komponen - %s" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:260 +msgid "Plugins" +msgstr "Plugins" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:261 +msgid "BIOS" +msgstr "BIOS" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:262 +msgid "Folders" +msgstr "Folder Folder" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:273 +#, c-format +msgid "Appearance/Themes - %s" +msgstr "Tampilan/Tema - %s" + +#: pcsx2/gui/ExecutorThread.cpp:40 +#, fuzzy +msgid "Logs events as they are passed to the PS2 virtual machine." +msgstr "Simulasi reset perangkat keras mesin virtual PS2." + +#: pcsx2/gui/ExecutorThread.cpp:430 +msgid "Press Cancel to attempt to cancel the action." +msgstr "Klik Batal untuk menggagalkan aksi tersebut." + +#: pcsx2/gui/ExecutorThread.cpp:431 +#, c-format +msgid "Press Terminate to kill %s immediately." +msgstr "Pilih Gagalkan untuk membunuh %s secara langsung." + +#: pcsx2/gui/ExecutorThread.cpp:434 +msgid "Terminate App" +msgstr "Gagalkan Aplikasi" + +#: pcsx2/gui/FrameForGS.cpp:384 +msgid "GS Output is Disabled!" +msgstr "Output GS ternonaktifkan!" + +#: pcsx2/gui/GlobalCommands.cpp:387 pcsx2/gui/MainFrame.cpp:414 +msgid "Save state" +msgstr "Save state" + +#: pcsx2/gui/GlobalCommands.cpp:388 +msgid "Saves the virtual machine state to the current slot." +msgstr "Simpan kondisi mesin virtual ke slot yang terpilih." + +#: pcsx2/gui/GlobalCommands.cpp:393 pcsx2/gui/MainFrame.cpp:413 +msgid "Load state" +msgstr "Load state" + +#: pcsx2/gui/GlobalCommands.cpp:394 +msgid "Loads a virtual machine state from the current slot." +msgstr "Jalankan sebuah kondisi mesin virtual dari slot yang terpilih." + +#: pcsx2/gui/GlobalCommands.cpp:399 +msgid "Load State Backup" +msgstr "Backup Load State" + +#: pcsx2/gui/GlobalCommands.cpp:400 +msgid "Loads virtual machine state backup for current slot." +msgstr "Jalankan backup kondisi mesin virtual untuk slot yang terpilih." + +#: pcsx2/gui/GlobalCommands.cpp:405 +msgid "Cycle to next slot" +msgstr "Lanjut ke slot berikutnya" + +#: pcsx2/gui/GlobalCommands.cpp:406 +msgid "Cycles the current save slot in +1 fashion!" +msgstr "Maju save slot sekarang ke +1!" + +#: pcsx2/gui/GlobalCommands.cpp:411 +msgid "Cycle to prev slot" +msgstr "Mundur ke slot sebelumnya" + +#: pcsx2/gui/GlobalCommands.cpp:412 +msgid "Cycles the current save slot in -1 fashion!" +msgstr "Mundur save slot kini ke dalam -1!" + +#: pcsx2/gui/IsoDropTarget.cpp:57 +msgid "Drag and Drop Error" +msgstr "Eror pada Tarik dan Lepas" + +#: pcsx2/gui/IsoDropTarget.cpp:58 +#, c-format +msgid "" +"It is an error to drop multiple files onto a %s window. One at a time " +"please, thank you." +msgstr "" +"Eror terjadi ketika menjatuhkan lebih dari satu file ke window %s. Satu file " +"sekali, terima kasih." + +#: pcsx2/gui/IsoDropTarget.cpp:89 pcsx2/gui/MainMenuClicks.cpp:342 +msgid "Confirm PS2 Reset" +msgstr "Konfirmasi Reset PS2" + +#: pcsx2/gui/IsoDropTarget.cpp:91 +#, c-format +msgid "" +"You have dropped the following ELF binary into %s:\n" +"\n" +msgstr "" +"Anda telah menjatuhkan binari ELF berikut kedalam %s:\n" +"\n" + +#: pcsx2/gui/IsoDropTarget.cpp:135 +#, c-format +msgid "You have dropped the following ISO image into %s:" +msgstr "Anda telah menjatuhkan file ISO berikut ke dalam %s:" + +#: pcsx2/gui/MainFrame.cpp:38 +#, c-format +msgid "Slot %d" +msgstr "Slot %d" + +#: pcsx2/gui/MainFrame.cpp:44 pcsx2/gui/Saveslots.cpp:150 +msgid "Backup" +msgstr "Backup" + +#: pcsx2/gui/MainFrame.cpp:324 +msgid "Show Console" +msgstr "Tampilkan Console" + +#: pcsx2/gui/MainFrame.cpp:325 +msgid "Console to Stdio" +msgstr "Konsol ke Stdio" + +#: pcsx2/gui/MainFrame.cpp:338 +msgid "&System" +msgstr "&Sistem" + +#: pcsx2/gui/MainFrame.cpp:339 +msgid "CD&VD" +msgstr "CD&VD" + +#: pcsx2/gui/MainFrame.cpp:340 +msgid "&Config" +msgstr "&Konfigurasi" + +#: pcsx2/gui/MainFrame.cpp:341 +msgid "&Misc" +msgstr "&Lainnya" + +#: pcsx2/gui/MainFrame.cpp:343 +msgid "&Debug" +msgstr "&Debug" + +#: pcsx2/gui/MainFrame.cpp:355 +#, c-format +msgid "%s %d.%d.%d.%d%s (svn) %s" +msgstr "%s %d.%d.%d.%d%s (svn) %s" + +#: pcsx2/gui/MainFrame.cpp:361 +#, c-format +msgid "%s %d.%d.%d %s" +msgstr "%s %d.%d.%d %s" + +#: pcsx2/gui/MainFrame.cpp:362 +msgid "(modded)" +msgstr "(termodifikasi)" + +#: pcsx2/gui/MainFrame.cpp:399 pcsx2/gui/MainFrame.cpp:401 +#: pcsx2/gui/MainFrame.cpp:407 +msgid "Initializing..." +msgstr "Sedang menyiapkan..." + +#: pcsx2/gui/MainFrame.cpp:403 +msgid "Run ELF..." +msgstr "Jalankan ELF..." + +#: pcsx2/gui/MainFrame.cpp:404 +msgid "For running raw PS2 binaries directly" +msgstr "Untuk menjalankan binari PS2 yang mentah" + +#: pcsx2/gui/MainFrame.cpp:416 +msgid "Backup before save" +msgstr "Backup sebelum simpan" + +#: pcsx2/gui/MainFrame.cpp:421 +msgid "Automatic Gamefixes" +msgstr "Perbaikan Permainan Otomatis" + +#: pcsx2/gui/MainFrame.cpp:422 +msgid "Automatically applies needed Gamefixes to known problematic games" +msgstr "Secara otomatis menerapkan Perbaikan untuk permainan yang bermasalah" + +#: pcsx2/gui/MainFrame.cpp:424 +msgid "Enable Cheats" +msgstr "Aktifkan Cheats" + +#: pcsx2/gui/MainFrame.cpp:427 +msgid "Enable Host Filesystem" +msgstr "Aktifkan Filesystem Host" + +#: pcsx2/gui/MainFrame.cpp:432 +msgid "Shutdown" +msgstr "Matikan" + +#: pcsx2/gui/MainFrame.cpp:433 +msgid "Wipes all internal VM states and shuts down plugins." +msgstr "Hapus semua kondisi internal VM dan matikan seluruh plugin." + +#: pcsx2/gui/MainFrame.cpp:435 +msgid "Exit" +msgstr "Keluar" + +#: pcsx2/gui/MainFrame.cpp:436 +#, c-format +msgid "Closing %s may be hazardous to your health" +msgstr "Menutup %s mungkin berbahaya bagi kesehatan Anda" + +#: pcsx2/gui/MainFrame.cpp:443 +msgid "Iso Selector" +msgstr "Pilih Iso" + +#: pcsx2/gui/MainFrame.cpp:444 +msgid "Plugin Menu" +msgstr "Menu Plugin" + +#: pcsx2/gui/MainFrame.cpp:447 +msgid "Iso" +msgstr "Iso" + +#: pcsx2/gui/MainFrame.cpp:447 +msgid "Makes the specified ISO image the CDVD source." +msgstr "Menetapkan file ISO yang terpilih sebagai sumber CDVD." + +#: pcsx2/gui/MainFrame.cpp:448 +msgid "Plugin" +msgstr "Plugin" + +#: pcsx2/gui/MainFrame.cpp:448 +msgid "Uses an external plugin as the CDVD source." +msgstr "Menggunakan sebuah plugin eksternal sebagai sumber CDVD." + +#: pcsx2/gui/MainFrame.cpp:449 +msgid "No disc" +msgstr "Tanpa disc" + +#: pcsx2/gui/MainFrame.cpp:449 +msgid "Use this to boot into your virtual PS2's BIOS configuration." +msgstr "Gunakan ini untuk masuk kedalam konfigurasi BIOS PS2 virtual Anda." + +#: pcsx2/gui/MainFrame.cpp:457 +msgid "Emulation &Settings" +msgstr "Emulasi &Pengaturan" + +#: pcsx2/gui/MainFrame.cpp:458 +msgid "&Memory cards" +msgstr "&Memory card" + +#: pcsx2/gui/MainFrame.cpp:459 +msgid "&Plugin/BIOS Selector" +msgstr "&Pemilih Plugin/BIOS" + +#: pcsx2/gui/MainFrame.cpp:460 pcsx2/gui/Panels/GameDatabasePanel.cpp:346 +msgid "Game Database Editor" +msgstr "Editor Database Game" + +#: pcsx2/gui/MainFrame.cpp:466 +msgid "&Video (GS)" +msgstr "&Video (GS)" + +#: pcsx2/gui/MainFrame.cpp:467 +msgid "&Audio (SPU2)" +msgstr "&Suara (SPU2)" + +#: pcsx2/gui/MainFrame.cpp:468 +msgid "&Controllers (PAD)" +msgstr "&Controllers (PAD)" + +#: pcsx2/gui/MainFrame.cpp:469 +msgid "Dev9" +msgstr "Dev9" + +#: pcsx2/gui/MainFrame.cpp:470 +msgid "USB" +msgstr "USB" + +#: pcsx2/gui/MainFrame.cpp:471 +msgid "Firewire" +msgstr "Firewire" + +#: pcsx2/gui/MainFrame.cpp:477 +msgid "Multitap 1" +msgstr "Multitap 1" + +#: pcsx2/gui/MainFrame.cpp:478 +msgid "Multitap 2" +msgstr "Multitap 2" + +#: pcsx2/gui/MainFrame.cpp:481 +msgid "Clear all settings..." +msgstr "Hapus semua pengaturan..." + +#: pcsx2/gui/MainFrame.cpp:482 +#, c-format +msgid "Clears all %s settings and re-runs the startup wizard." +msgstr "Hapus semua pengaturan %s dan jalankan ulang tampilan mula mula." + +#: pcsx2/gui/MainFrame.cpp:504 +msgid "About..." +msgstr "Tentang..." + +#: pcsx2/gui/MainFrame.cpp:508 +msgid "Logging..." +msgstr "Logging..." + +#: pcsx2/gui/MainFrame.cpp:585 +msgid "Pause" +msgstr "Pause" + +#: pcsx2/gui/MainFrame.cpp:586 +msgid "Safely pauses emulation and preserves the PS2 state." +msgstr "" +"Dengan aman menghentikan emulasi dan menjaga tetap kondisi PS2 yang sedang " +"jalan." + +#: pcsx2/gui/MainFrame.cpp:593 +msgid "Resume" +msgstr "Lanjut" + +#: pcsx2/gui/MainFrame.cpp:594 +msgid "Resumes the suspended emulation state." +msgstr "Melanjutkan kembali kondisi emulasi yang terhenti tadi." + +#: pcsx2/gui/MainFrame.cpp:598 +msgid "Pause/Resume" +msgstr "Pause/Lanjut" + +#: pcsx2/gui/MainFrame.cpp:599 +msgid "No emulation state is active; cannot suspend or resume." +msgstr "Tidak ada kondisi yang aktif; tidak bisa berhenti maupun lanjut." + +#: pcsx2/gui/MainFrame.cpp:608 +msgid "Restart" +msgstr "Restart" + +#: pcsx2/gui/MainFrame.cpp:609 +msgid "Simulates hardware reset of the PS2 virtual machine." +msgstr "Simulasi reset perangkat keras mesin virtual PS2." + +#: pcsx2/gui/MainFrame.cpp:614 +msgid "No emulation state is active; boot something first." +msgstr "" +"Tidak ada kondisi emulasi yang aktif; jalankan sesuatu terlebih dahulu." + +#: pcsx2/gui/MainFrame.cpp:622 +msgid "Reboot CDVD (full)" +msgstr "Jalankan ulang CDVD (full)" + +#: pcsx2/gui/MainFrame.cpp:623 +msgid "Hard reset of the active VM." +msgstr "Hard reset dari mesin virtual yang aktif." + +#: pcsx2/gui/MainFrame.cpp:627 +msgid "Boot CDVD (full)" +msgstr "Jalankan CDVD (full)" + +#: pcsx2/gui/MainFrame.cpp:628 +msgid "Boot the VM using the current DVD or Iso source media" +msgstr "" +"Jalankan mesin virtual menggunakan DVD yang sekarang atau sumber media Iso" + +#: pcsx2/gui/MainFrame.cpp:636 +msgid "Reboot CDVD (fast)" +msgstr "Jalankan ulang CDVD (cepat)" + +#: pcsx2/gui/MainFrame.cpp:637 +msgid "Reboot using fast BOOT (skips splash screens)" +msgstr "Menjalankan ulang menggunakan BOOT cepat (melewati layar splash)" + +#: pcsx2/gui/MainFrame.cpp:641 +msgid "Boot CDVD (fast)" +msgstr "Jalankan CDVD (cepat)" + +#: pcsx2/gui/MainFrame.cpp:642 +msgid "Use fast boot to skip PS2 startup and splash screens" +msgstr "Meggunakan fast boot untuk melewati awalan PS2 dan layar splash" + +#: pcsx2/gui/MainFrame.cpp:703 pcsx2/gui/MainFrame.cpp:738 +msgid "No plugin loaded" +msgstr "Tak ada plugin yang dijalankan" + +#: pcsx2/gui/MainFrame.cpp:708 +msgid "Core GS Settings..." +msgstr "Pengaturan Inti GS" + +#: pcsx2/gui/MainFrame.cpp:709 +msgid "" +"Modify hardware emulation settings regulated by the PCSX2 core virtual " +"machine." +msgstr "" +"Memodifikasi pengaturan emulasi perangkat keras yang diatur inti mesin " +"virtual PCSX2." + +#: pcsx2/gui/MainFrame.cpp:711 +msgid "Window Settings..." +msgstr "Pengaturan Window" + +#: pcsx2/gui/MainFrame.cpp:712 +msgid "Modify window and appearance options, including aspect ratio." +msgstr "Memodifikasi window dan opsi tampilan, termasuk aspect ratio." + +#: pcsx2/gui/MainFrame.cpp:719 +msgid "Plugin Settings..." +msgstr "Pengaturan Plugin" + +#: pcsx2/gui/MainFrame.cpp:720 +#, c-format +msgid "Opens the %s plugin's advanced settings dialog." +msgstr "Membuka plugin %s bagian kompleks." + +#: pcsx2/gui/MainMenuClicks.cpp:112 +msgid "Reset all settings?" +msgstr "Reset semua konfigurasi ?" + +#: pcsx2/gui/MainMenuClicks.cpp:140 +msgid "Confirm ISO image change" +msgstr "Konfirmasi ganti ISO" + +#: pcsx2/gui/MainMenuClicks.cpp:146 +msgid "Do you want to swap discs or boot the new image (via system reset)?" +msgstr "" +"Apakah Anda ingin tukar disc atau menjalankan file image baru (melalui reset " +"sistem)?" + +#: pcsx2/gui/MainMenuClicks.cpp:148 pcsx2/gui/MainMenuClicks.cpp:194 +msgid "Swap Disc" +msgstr "Ganti Disc" + +#: pcsx2/gui/MainMenuClicks.cpp:184 +msgid "Confirm CDVD source change" +msgstr "Konfirmasi penggantian sumber CDVD" + +#: pcsx2/gui/MainMenuClicks.cpp:187 +#, c-format +msgid "You've selected to switch the CDVD source from %s to %s." +msgstr "Anda telah memilih untuk menukar sumber CDVD dari %s menjadi %s." + +#: pcsx2/gui/MainMenuClicks.cpp:191 +msgid "Do you want to swap discs or boot the new image (system reset)?" +msgstr "" +"Apa anda ingin tukar disc atau ingin menjalankan file image baru (reset " +"sistem)?" + +#: pcsx2/gui/MainMenuClicks.cpp:261 +#, c-format +msgid "All Supported (%s)" +msgstr "Semua Didukung (%s)" + +#: pcsx2/gui/MainMenuClicks.cpp:264 +#, c-format +msgid "Disc Images (%s)" +msgstr "Images Disc (%s)" + +#: pcsx2/gui/MainMenuClicks.cpp:267 +#, c-format +msgid "Blockdumps (%s)" +msgstr "Blockdumps (%s)" + +#: pcsx2/gui/MainMenuClicks.cpp:270 pcsx2/gui/MainMenuClicks.cpp:291 +msgid "All Files (*.*)" +msgstr "Semua File (*.*)" + +#: pcsx2/gui/MainMenuClicks.cpp:273 +msgid "Select CDVD source iso..." +msgstr "Pilih sumber iso CDVD" + +#: pcsx2/gui/MainMenuClicks.cpp:290 +msgid "Select ELF file..." +msgstr "Pilih file ELF" + +#: pcsx2/gui/MainMenuClicks.cpp:316 +msgid "ISO file not found!" +msgstr "File ISO tidak ditemukan!" + +#: pcsx2/gui/MainMenuClicks.cpp:318 +msgid "An error occurred while trying to open the file:" +msgstr "Eror ketika mencoba membuka file:" + +#: pcsx2/gui/MainMenuClicks.cpp:319 +msgid "" +"Error: The configured ISO file does not exist. Click OK to select a new ISO " +"source for CDVD." +msgstr "" +"Eror: File ISO yang dikonfigurasikan tidak ada. Klik OK untuk memilih sebuah " +"sumber ISO baru untuk CDVD" + +#: pcsx2/gui/MainMenuClicks.cpp:390 +msgid "" +"You have selected the following ISO image into PCSX2:\n" +"\n" +msgstr "" +"Anda telah memilih ISO berikut kedalam PCSX2:\n" +"\n" + +#: pcsx2/gui/MemoryCardFile.cpp:183 +#, c-format +msgid "" +"Could not create a memory card: \n" +"\n" +"%s\n" +"\n" +msgstr "" +"Memoy card gagal dibuat: \n" +"\n" +"%s\n" +"\n" + +#: pcsx2/gui/MemoryCardFile.cpp:201 +#, c-format +msgid "" +"Access denied to memory card: \n" +"\n" +"%s\n" +"\n" +msgstr "" +"Akses ditolak untuk memory card: \n" +"\n" +"%s\n" +"\n" + +#: pcsx2/gui/MemoryCardFile.cpp:525 +msgid "File name empty or too short" +msgstr "Nama file kosong atau terlalu singkat" + +#: pcsx2/gui/MemoryCardFile.cpp:530 +msgid "File name outside of required directory" +msgstr "Nama file diluar direktori yang dibutuhkan" + +#: pcsx2/gui/MemoryCardFile.cpp:536 +msgid "File name already exists" +msgstr "Nama file telah ada" + +#: pcsx2/gui/MemoryCardFile.cpp:543 +msgid "The Operating-System prevents this file from being created" +msgstr "Sistem-Operasi menghalangi pembuatan file ini" + +#: pcsx2/gui/Panels/BaseApplicableConfigPanel.cpp:103 +msgid "Cannot apply settings..." +msgstr "Gagal menerapkan pengaturan..." + +#: pcsx2/gui/Panels/BiosSelectorPanel.cpp:103 +msgid "BIOS Search Path:" +msgstr "Lokasi Pencarian BIOS:" + +#: pcsx2/gui/Panels/BiosSelectorPanel.cpp:104 +msgid "Select folder with PS2 BIOS roms" +msgstr "Pilih folder yang memuat rom BIOS PS2" + +#: pcsx2/gui/Panels/BiosSelectorPanel.cpp:111 +msgid "" +"Click the Browse button to select a different folder where PCSX2 will look " +"for PS2 BIOS roms." +msgstr "" +"Klik tombol Cari untuk memilih sebuah folder lain dimana PCSX2 akan mencari " +"BIOS PS2." + +#: pcsx2/gui/Panels/BiosSelectorPanel.cpp:113 +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:156 +#: pcsx2/gui/Panels/ThemeSelectorPanel.cpp:47 +msgid "Refresh list" +msgstr "Refresh daftar" + +#: pcsx2/gui/Panels/BiosSelectorPanel.cpp:115 +msgid "Select a BIOS rom:" +msgstr "Pilih sebuah rom BIOS:" + +#: pcsx2/gui/Panels/CpuPanel.cpp:24 +msgid "Round Mode" +msgstr "Mode Round" + +#: pcsx2/gui/Panels/CpuPanel.cpp:25 +msgid "Clamping Mode" +msgstr "Mode Clamping" + +#: pcsx2/gui/Panels/CpuPanel.cpp:29 +msgid "Nearest" +msgstr "Terdekat" + +#: pcsx2/gui/Panels/CpuPanel.cpp:30 +msgid "Negative" +msgstr "Negatif" + +#: pcsx2/gui/Panels/CpuPanel.cpp:31 +msgid "Positive" +msgstr "Positif" + +#: pcsx2/gui/Panels/CpuPanel.cpp:32 +msgid "Chop / Zero" +msgstr "Nol / Terpotong" + +#: pcsx2/gui/Panels/CpuPanel.cpp:37 +msgid "None" +msgstr "Tidak ada" + +#: pcsx2/gui/Panels/CpuPanel.cpp:85 +msgid "EE/FPU Advanced Recompiler Options" +msgstr "Pengaturan Kompleks Recompiler EE/FPU" + +#: pcsx2/gui/Panels/CpuPanel.cpp:87 pcsx2/gui/Panels/CpuPanel.cpp:102 +msgid "Extra + Preserve Sign" +msgstr "Extra + Preserve Sign" + +#: pcsx2/gui/Panels/CpuPanel.cpp:88 +msgid "Full" +msgstr "Full" + +#: pcsx2/gui/Panels/CpuPanel.cpp:99 +msgid "VU0 / VU1 Advanced Recompiler Options" +msgstr "Pengaturan Kompleks Recompiler VU0 / VU1" + +#: pcsx2/gui/Panels/CpuPanel.cpp:101 +msgid "Extra" +msgstr "Extra" + +#: pcsx2/gui/Panels/CpuPanel.cpp:117 pcsx2/gui/Panels/CpuPanel.cpp:126 +#: pcsx2/gui/Panels/CpuPanel.cpp:184 +msgid "Interpreter" +msgstr "Interpreter" + +#: pcsx2/gui/Panels/CpuPanel.cpp:118 +msgid "Quite possibly the slowest thing in the universe." +msgstr "Kemungkinan besar paling lambat di dunia." + +#: pcsx2/gui/Panels/CpuPanel.cpp:120 pcsx2/gui/Panels/CpuPanel.cpp:129 +msgid "Recompiler" +msgstr "Recompiler" + +#: pcsx2/gui/Panels/CpuPanel.cpp:121 +msgid "" +"Performs just-in-time binary translation of 64-bit MIPS-IV machine code to " +"x86." +msgstr "" +"Menjalankan translasi binari just-in-time dari kode mesin 64-bit MIPS-IV ke " +"x86." + +#: pcsx2/gui/Panels/CpuPanel.cpp:127 +msgid "Pretty slow; provided for diagnostic purposes only." +msgstr "Cukup lambat; digunakan untuk tujuan diagnosa saja." + +#: pcsx2/gui/Panels/CpuPanel.cpp:130 +msgid "" +"Performs just-in-time binary translation of 32-bit MIPS-I machine code to " +"x86." +msgstr "" +"Menjalankan translasi binari just-in-time dari kode mesin 32-bit MIPS-IV ke " +"x86." + +#: pcsx2/gui/Panels/CpuPanel.cpp:154 +#, fuzzy +msgid "Enable EE Cache (Slower)" +msgstr "Aktifkan EE Cache - Interpreter Saja! (Lebih lambat)" + +#: pcsx2/gui/Panels/CpuPanel.cpp:154 +#, fuzzy +msgid "Interpreter only; provided for diagnostic" +msgstr "Cukup lambat; digunakan untuk tujuan diagnosa saja." + +#: pcsx2/gui/Panels/CpuPanel.cpp:170 pcsx2/gui/Panels/CpuPanel.cpp:223 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:110 +msgid "Restore Defaults" +msgstr "Restorasi Awal" + +#: pcsx2/gui/Panels/CpuPanel.cpp:185 +msgid "" +"Vector Unit Interpreter. Slow and not very compatible. Only use for " +"diagnostics." +msgstr "" +"Unit Vektor Interpreter. Lambat dan kompatibilitas rendah. Digunakan untuk " +"diagnosa." + +#: pcsx2/gui/Panels/CpuPanel.cpp:187 +msgid "microVU Recompiler" +msgstr "Recompiler microVU" + +#: pcsx2/gui/Panels/CpuPanel.cpp:188 +msgid "" +"New Vector Unit recompiler with much improved compatibility. Recommended." +msgstr "" +"Recompiler Unit Vektor baru dengan kompatibilitas yang meningkat. " +"Direkomendasikan." + +#: pcsx2/gui/Panels/CpuPanel.cpp:190 +msgid "superVU Recompiler [legacy]" +msgstr "Recompiler superVU [legacy]" + +#: pcsx2/gui/Panels/CpuPanel.cpp:191 +msgid "" +"Useful for diagnosing bugs or clamping issues in the new mVU recompiler." +msgstr "" +"Berguna untuk diagnosa bug atau permasalahan terkait jepitan dalam " +"recompiler baru mVU." + +#: pcsx2/gui/Panels/DirPickerPanel.cpp:64 +msgid "Path does not exist" +msgstr "Lokasi tidak ada" + +#: pcsx2/gui/Panels/DirPickerPanel.cpp:156 +msgid "Use default setting" +msgstr "Gunakan lokasi umum" + +#: pcsx2/gui/Panels/DirPickerPanel.cpp:176 +msgid "Open in Explorer" +msgstr "Buka dalam Explorer" + +#: pcsx2/gui/Panels/DirPickerPanel.cpp:177 +msgid "Open an explorer window to this folder." +msgstr "Buka tampilan explorer folder ini." + +#: pcsx2/gui/Panels/DirPickerPanel.cpp:268 +msgid "Create folder?" +msgstr "Buat folder?" + +#: pcsx2/gui/Panels/DirPickerPanel.cpp:269 +#, c-format +msgid "A configured folder does not exist. Should %s try to create it?" +msgstr "" +"Sebuah folder yang dikonfigurasi tidak ada. Perlukah %s mencoba membuatnya?" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:30 +msgid "Fit to Window/Screen" +msgstr "Fit to Window/Screen" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:31 +msgid "Standard (4:3)" +msgstr "Standard (4:3)" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:32 +msgid "Widescreen (16:9)" +msgstr "Widescreen (16:9)" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:46 +msgid "Disable window resize border" +msgstr "Nonaktifkan perbatasan layar" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:47 +msgid "Always hide mouse cursor" +msgstr "Selalu menyembunyikan kursor mouse" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:48 +msgid "Hide window when paused" +msgstr "Sembunyikan window ketika dipause" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:49 +msgid "Default to fullscreen mode on open" +msgstr "Buat ke mode fullscreen ketika dibuka" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:50 +msgid "Wait for Vsync on refresh" +msgstr "Tunggu Vsync ketika refresh" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:51 +msgid "Dynamically toggle Vsync depending on frame rate (read tooltip!)" +msgstr "" +"Secara dinamis mengatur Vsync tergantung dari frame rate (baca keterangan!)" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:52 +msgid "Double-click toggles fullscreen mode" +msgstr "Klik dua kali akan membuat mode fullscreen" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:110 +msgid "Aspect Ratio:" +msgstr "Aspect Ratio:" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:112 +msgid "Custom Window Size:" +msgstr "Ukuran Layar Buatan:" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:115 +msgid "Zoom:" +msgstr "Perbesar:" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:196 +msgid "" +"Invalid window dimensions specified: Size cannot contain non-numeric digits! " +">_<" +msgstr "" +"Terdeteksi pemasukan dimensi layar yang tidak valid: Ukuran tidak boleh " +"memuat bilangan non-angka! >_<" + +#: pcsx2/gui/Panels/GameDatabasePanel.cpp:334 +msgid "Search" +msgstr "Cari" + +#: pcsx2/gui/Panels/GameDatabasePanel.cpp:368 +#: pcsx2/gui/Panels/GameFixesPanel.cpp:25 +msgid "Gamefixes" +msgstr "Perbaikan Permainan" + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:38 +msgid "VU Add Hack - Fixes Tri-Ace games boot crash." +msgstr "VU Add Hack - Memperbaiki permainan Tri-Ace sewaktu booting gagal." + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:39 +msgid "" +"Games that need this hack to boot:\n" +" * Star Ocean 3\n" +" * Radiata Stories\n" +" * Valkyrie Profile 2" +msgstr "" +"Permainan yang membutuhkan perbaikan ini untuk bisa jalan:\n" +" * Star Ocean 3\n" +" * Radiata Stories\n" +" * Valkyrie Profile 2" + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:42 +msgid "VU Clip Flag Hack - For Persona games (SuperVU recompiler only!)" +msgstr "VU Clip Flag Hack - Untuk permainan Persona (recompiler SuperVU saja!)" + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:46 +msgid "FPU Compare Hack - For Digimon Rumble Arena 2." +msgstr "FPU Compare Hack - Untuk Digimon Rumble Arena 2." + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:50 +msgid "FPU Multiply Hack - For Tales of Destiny." +msgstr "FPU Multiply Hack - Untuk Tales of Destiny." + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:54 +msgid "FPU Negative Div Hack - For Gundam games." +msgstr "FPU Negative Div Hack - Untuk permainan Gundam." + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:58 +msgid "VU XGkick Hack - For Erementar Gerad." +msgstr "VU XGkick Hack - Untuk Erementar Gerad." + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:62 +msgid "FFX videos fix - Fixes bad graphics overlay in FFX videos." +msgstr "FFX videos fix - Memperbaiki hamparan grafis pada video FFX." + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:66 +msgid "EE timing hack - Multi purpose hack. Try if all else fails." +msgstr "" +"EE timing hack - Perbaikan multifungsional. Coba bila semua perbaikan gagal." + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:75 +msgid "" +"Skip MPEG hack - Skips videos/FMVs in games to avoid game hanging/freezes." +msgstr "" +"Skip MPEG hack - Melewati video/FMV di permainan untuk menghindari permainan " +"nge-hang/nge-freeze." + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:79 +msgid "OPH Flag hack - Try if your game freezes showing the same frame." +msgstr "" +"OPH Flag hack - Dicoba apabila permainan Anda freeze namun menampilkan frame " +"yang sama." + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:88 +msgid "Ignore DMAC writes when it is busy." +msgstr "Lupakan pembuatan DMAC ketika sedang sibuk." + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:95 +msgid "Simulate VIF1 FIFO read ahead. Fixes slow loading games." +msgstr "" + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:103 +msgid "Delay VIF1 Stalls (VIF1 FIFO) - For SOCOM 2 HUD." +msgstr "" + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:107 +msgid "Ignore Bus Direction on Path3 Transfer - Used for Hotwheels" +msgstr "" + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:118 +msgid "Enable manual game fixes [Not recommended]" +msgstr "Aktifkan perbaikan permainan secara manual [Tidak direkomendasikan]" + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:127 +msgid "" +"The safest way to make sure that all game fixes are completely disabled." +msgstr "" +"Hal paling aman untuk memastikan semua perbaikan permainan sepenuhnya " +"ternonaktifkan." + +#: pcsx2/gui/Panels/LogOptionsPanels.cpp:249 +msgid "Enable Trace Logging" +msgstr "Aktifkan Trace Logging" + +#: pcsx2/gui/Panels/LogOptionsPanels.cpp:250 +msgid "" +"Trace logs are all written to emulog.txt. Toggle trace logging at any time " +"using F10." +msgstr "" +"Log Penjajakan tertulis semua pada emulog.txt. Jalankan trace logging kapan " +"saja menggunakan F10." + +#: pcsx2/gui/Panels/LogOptionsPanels.cpp:251 +msgid "" +"Warning: Enabling trace logs is typically very slow, and is a leading cause " +"of 'What happened to my FPS?' problems. :)" +msgstr "" +"Peringatan: Mengaktifkan trace logs umumnya sangat lambat, dan merupakan " +"penyebab utama masalah 'Apa yang terjadi dengan FPS saya?' :)" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:151 +msgid "Select folder with PS2 memory cards" +msgstr "Pilih folder yang memuat memory card PS2" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:448 +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:533 +msgid "Eject" +msgstr "Eject" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:449 +msgid "Duplicate ..." +msgstr "Gandakan ..." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:450 +msgid "Rename ..." +msgstr "Ganti Nama ..." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:451 +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:515 +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:542 +msgid "Create ..." +msgstr "Buat ..." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:463 +msgid "Card: " +msgstr "Card:" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:516 +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:549 +msgid "Create a new memory card." +msgstr "Buat sebuah memory card baru." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:529 +msgid "Rename this memory card ..." +msgstr "Ganti nama memory card ini ..." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:533 +msgid "Insert ..." +msgstr "Masukkan ..." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:534 +msgid "Eject the card from this port" +msgstr "Eject card dari port ini" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:534 +msgid "Insert this card to a port ..." +msgstr "Masukkan card ini ke port ..." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:538 +msgid "Create a duplicate of this memory card ..." +msgstr "Buat duplikat dari memory card ini ..." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:542 +msgid "Delete" +msgstr "Hapus" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:545 +msgid "Permanently delete this memory card from disk (all contents are lost)" +msgstr "" +"Hapus memory card ini dari disk secara permanen (semua konten akan hilang)" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:547 +msgid "Create a new memory card and assign it to this Port." +msgstr "Buat sebuah memory card baru dan hubungkan ke Port ini." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:726 +msgid "Delete memory file?" +msgstr "Hapus file memory?" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:750 +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:762 +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:769 +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:783 +msgid "Duplicate memory card" +msgstr "Gandakan memory card" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:750 +msgid "Failed: Can only duplicate an existing card." +msgstr "Gagal: Hanya dapat menduplikat sebuah card yang telah ada." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:769 +msgid "" +"Select a name for the duplicate\n" +"( '.ps2' will be added automatically)" +msgstr "" +"Pilihlah sebuah nama untuk duplikat\n" +"( '.ps2' akan ditambahkan secara otomatis)" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:782 +#, c-format +msgid "Failed: %s" +msgstr "Gagal: %s" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:808 +msgid "Copy failed!" +msgstr "Salin gagal!" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:816 +#, c-format +msgid "Memory card '%s' duplicated to '%s'." +msgstr "Memory card '%s' telah diduplikat menjadi '%s'." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:820 +msgid "Success" +msgstr "Sukses" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:841 +#, c-format +msgid "" +"Select a new name for the memory card '%s'\n" +"( '.ps2' will be added automatically)" +msgstr "" +"Pilih sebuah nama baru untuk memory card '%s'\n" +"( '.ps2' akan ditambahkan secara otomatis)" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:844 +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:856 +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:872 +msgid "Rename memory card" +msgstr "Ganti Nama memory card" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:872 +msgid "Error: Rename could not be completed.\n" +msgstr "Eror: Penggantian nama tidak dilaksanakan.\n" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:962 +#: pcsx2/gui/Panels/MemoryCardListView.cpp:139 +#, c-format +msgid "Port-%u / Multitap-%u--Port-1" +msgstr "Port-%u / Multitap-%u--Port-1" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:963 +#: pcsx2/gui/Panels/MemoryCardListView.cpp:140 +#, c-format +msgid " Multitap-%u--Port-%u" +msgstr " Multitap-%u--Port-%u" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:988 +msgid "Empty" +msgstr "Kosong" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:994 +#, c-format +msgid "Select a target port for '%s'" +msgstr "Pilihlah port tujuan untuk '%s'" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:995 +msgid "Insert card" +msgstr "Masukkan card" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1055 +msgid "Eject card" +msgstr "Eject card" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1055 +msgid "Insert card ..." +msgstr "Masukkan card ..." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1056 +msgid "Duplicate card ..." +msgstr "Gandakan card ..." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1057 +msgid "Rename card ..." +msgstr "Ganti Nama card ..." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1058 +msgid "Delete card" +msgstr "Hapus card" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1061 +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1065 +msgid "Create a new card ..." +msgstr "Buat sebuah card baru ..." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1069 +msgid "Refresh List" +msgstr "Refresh daftar" + +#: pcsx2/gui/Panels/MemoryCardListView.cpp:105 +msgid "PS2 Port" +msgstr "Port PS2" + +#: pcsx2/gui/Panels/MemoryCardListView.cpp:107 +msgid "Card (file) name" +msgstr "Card nama (file)" + +#: pcsx2/gui/Panels/MemoryCardListView.cpp:108 +msgid "Card size" +msgstr "Ukuran kartu" + +#: pcsx2/gui/Panels/MemoryCardListView.cpp:109 +msgid "Formatted" +msgstr "Telah diformat" + +#: pcsx2/gui/Panels/MemoryCardListView.cpp:110 +msgid "Last Modified" +msgstr "Terakhir Diubah" + +#: pcsx2/gui/Panels/MemoryCardListView.cpp:111 +msgid "Created on" +msgstr "Dibuat pada" + +#: pcsx2/gui/Panels/MemoryCardListView.cpp:156 +msgid "No" +msgstr "Tidak" + +#: pcsx2/gui/Panels/MemoryCardListView.cpp:156 +msgid "Yes" +msgstr "Ya" + +#: pcsx2/gui/Panels/MemoryCardListView.cpp:169 +msgid "[-- Unused cards --]" +msgstr "[-- Card yang tidak dipakai --]" + +#: pcsx2/gui/Panels/MemoryCardListView.cpp:171 +msgid "[-- No unused cards --]" +msgstr "[-- Tiada card yang tidak terpakai --]" + +#: pcsx2/gui/Panels/MiscPanelStuff.cpp:33 +msgid "Usermode Selection" +msgstr "Pilihan mode User" + +#: pcsx2/gui/Panels/MiscPanelStuff.cpp:50 +msgid "User Documents (recommended)" +msgstr "User Documents (direkomendasikan)" + +#: pcsx2/gui/Panels/MiscPanelStuff.cpp:51 +msgid "Location: " +msgstr "Lokasi:" + +#: pcsx2/gui/Panels/MiscPanelStuff.cpp:55 +msgid "Custom folder:" +msgstr "Folder pilihan:" + +#: pcsx2/gui/Panels/MiscPanelStuff.cpp:57 +msgid "" +"This setting may require administration privileges from your operating " +"system, depending on how your system is configured." +msgstr "" +"Aturan ini mungkin memerlukan akses admin dari sistem operasi anda, " +"tergantung dari bagaimana sistem anda terkonfigurasi." + +#: pcsx2/gui/Panels/MiscPanelStuff.cpp:66 +#, c-format +msgid "Select a document root for %s" +msgstr "Pilih sebuah root dokumen untuk %s" + +#: pcsx2/gui/Panels/MiscPanelStuff.cpp:124 +msgid "Apply" +msgstr "Terapkan" + +#: pcsx2/gui/Panels/MiscPanelStuff.cpp:125 +msgid "Make this language my default right now!" +msgstr "Jadikan bahasa ini sebagai bahasa saya sekarang juga!" + +#: pcsx2/gui/Panels/PathsPanel.cpp:38 +msgid "Savestates:" +msgstr "Savestate:" + +#: pcsx2/gui/Panels/PathsPanel.cpp:39 +msgid "Select folder for Savestates" +msgstr "Pilih folder untuk Savestate" + +#: pcsx2/gui/Panels/PathsPanel.cpp:48 +msgid "Snapshots:" +msgstr "Snapshot:" + +#: pcsx2/gui/Panels/PathsPanel.cpp:49 +msgid "Select a folder for Snapshots" +msgstr "Pilih sebuah folder untuk Snapshot" + +#: pcsx2/gui/Panels/PathsPanel.cpp:58 +msgid "Logs/Dumps:" +msgstr "Logs/Dumps:" + +#: pcsx2/gui/Panels/PathsPanel.cpp:59 +msgid "Select a folder for logs/dumps" +msgstr "Pilih sebuah fodler untuk logs/dumps" + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:230 +msgid "Applying settings..." +msgstr "Sedang menerapkan aturan" + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:240 +msgid "Shutdown PS2 virtual machine?" +msgstr "Matikan mesin virtual PS2?" + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:321 +msgid "I'm givin' her all she's got, Captain!" +msgstr "Saya hanya memberikan dia apa yang dia miliki, Kapten!" + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:323 +msgid "Enumerating available plugins..." +msgstr "Menghitung plugin yang tersedia" + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:356 +msgid "Plugins Search Path:" +msgstr "Lokasi Pencarian Plugin" + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:357 +msgid "Select a folder with PCSX2 plugins" +msgstr "Pilih sebuah folder dengan plugin PCSX2" + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:370 +msgid "Configure..." +msgstr "Konfigurasi..." + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:379 +msgid "Click the Browse button to select a different folder for PCSX2 plugins." +msgstr "" +"Klik tombol Cari untuk memilih sebuah folder yang berbeda untuk plugin PCSX2." + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:481 +#, c-format +msgid "Please select a valid plugin for the %s." +msgstr "Silakan memilih sebuah plugin yang valid untuk %s." + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:519 +#, c-format +msgid "" +"The selected %s plugin failed to load.\n" +"\n" +"Reason: %s\n" +"\n" +msgstr "" +"Plugin %s yang terpilih gagal jalan.\n" +"\n" +"Alasan: %s\n" +"\n" + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:730 +msgid "Completing tasks..." +msgstr "Menyelesaikan tugas..." + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:96 +msgid "Enable speedhacks" +msgstr "Aktifkan speedhacks" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:102 +msgid "" +"A safe and easy way to make sure that all speedhacks are completely disabled." +msgstr "Sebuah hal untuk memastikan semua speedhacks ternonaktifkan." + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:111 +msgid "" +"Resets all speedhack options to their defaults, which consequently turns " +"them all OFF." +msgstr "" +"Mereset ulang semua opsi speedhack ke awal, yang akan menonaktifkan mereka." + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:120 +msgid "EE Cyclerate [Not Recommended]" +msgstr "EE Cyclerate [Tidak Direkomendasikan]" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:141 +msgid "VU Cycle Stealing [Not Recommended]" +msgstr "VU Cycle Stealing [Tidak Direkomendasikan]" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:161 +msgid "microVU Hacks" +msgstr "microVU Hacks" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:163 +msgid "mVU Flag Hack" +msgstr "mVU Flag Hack" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:164 +#, fuzzy +msgid "" +"Good Speedup and High Compatibility; may cause bad graphics... [Recommended]" +msgstr "" +"Peningkatan kecepatan dan Kompatibilitas Tinggi; bisa menyebabkan grafis " +"sampah, SPS, dll... [Direkomendasikan]" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:166 +msgid "MTVU (Multi-Threaded microVU1)" +msgstr "" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 +#, fuzzy +msgid "" +"Good Speedup and High Compatibility; may cause hanging... [Recommended if 3+ " +"cores]" +msgstr "" +"Peningkatan kecepatan dan Kompatibilitas Tinggi; bisa menyebabkan grafis " +"sampah, SPS, dll... [Direkomendasikan]" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:183 +msgid "Other Hacks" +msgstr "Hacks lainnya" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:185 +msgid "Enable INTC Spin Detection" +msgstr "Enable INTC Spin Detection" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:186 +msgid "" +"Huge speedup for some games, with almost no compatibility side effects. " +"[Recommended]" +msgstr "" +"Peningkatan besar kecepatan untuk beberapa permainan, tanpa ada efek samping " +"terhadap kompatibilitas. [Direkomendasikan]" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:188 +msgid "Enable Wait Loop Detection" +msgstr "Enable Wait Loop Detection" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:189 +msgid "" +"Moderate speedup for some games, with no known side effects. [Recommended]" +msgstr "" +"Penambahan sedang kecepatan untuk beberapa permainan, tanpa ada efek samping " +"yang diketahui. [Direkomendasikan]" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 +msgid "Enable fast CDVD" +msgstr "Enable fast CDVD" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:192 +msgid "Fast disc access, less loading times. [Not Recommended]" +msgstr "" +"Akses disc lebih cepat, waktu loading berkurang. {Tidak Direkomendasikan]" + +#: pcsx2/gui/Panels/ThemeSelectorPanel.cpp:37 +msgid "Themes Search Path:" +msgstr "Lokasi Pencarian Tema:" + +#: pcsx2/gui/Panels/ThemeSelectorPanel.cpp:38 +msgid "Select folder containing PCSX2 visual themes" +msgstr "Pilih folder yang memuat tema visual PCSX2" + +#: pcsx2/gui/Panels/ThemeSelectorPanel.cpp:45 +msgid "" +"Click the Browse button to select a different folder containing PCSX2 visual " +"themes." +msgstr "" +"Klik tombol Cari untuk memilih folder lain yang memuat tema visual PCSX2." + +#: pcsx2/gui/Panels/ThemeSelectorPanel.cpp:49 +msgid "Select a visual theme:" +msgstr "Pilih sebuah tema visual:" + +#: pcsx2/gui/Panels/VideoPanel.cpp:34 +msgid "Disable Framelimiting" +msgstr "Disable Framelimiting" + +#: pcsx2/gui/Panels/VideoPanel.cpp:35 +msgid "" +"Useful for running benchmarks. Toggle this option in-game by pressing F4." +msgstr "" +"Berguna untuk menjalankan benchmark. Aktifkan opsi ini di permainan dengan " +"menekan F4." + +#: pcsx2/gui/Panels/VideoPanel.cpp:61 +msgid "Base Framerate Adjust:" +msgstr "Base Framerate Adjust:" + +#: pcsx2/gui/Panels/VideoPanel.cpp:67 +msgid "Slow Motion Adjust:" +msgstr "Slow Motion Adjust:" + +#: pcsx2/gui/Panels/VideoPanel.cpp:73 +msgid "Turbo Adjust:" +msgstr "Turbo Adjust:" + +#: pcsx2/gui/Panels/VideoPanel.cpp:88 +msgid "NTSC Framerate:" +msgstr "NTSC Framerate:" + +#: pcsx2/gui/Panels/VideoPanel.cpp:91 pcsx2/gui/Panels/VideoPanel.cpp:97 +msgid "FPS" +msgstr "FPS" + +#: pcsx2/gui/Panels/VideoPanel.cpp:94 +msgid "PAL Framerate:" +msgstr "PAL Framerate:" + +#: pcsx2/gui/Panels/VideoPanel.cpp:166 +msgid "" +"Error while parsing either NTSC or PAL framerate settings. Settings must be " +"valid floating point numerics." +msgstr "" + +#: pcsx2/gui/Panels/VideoPanel.cpp:184 +msgid "Disabled [default]" +msgstr "Nonaktif [umum]" + +#: pcsx2/gui/Panels/VideoPanel.cpp:188 +msgid "Skip when on Turbo only (TAB to enable)" +msgstr "Frameskip bila hanya mode Turbo (TAB untuk mengaktifkan)" + +#: pcsx2/gui/Panels/VideoPanel.cpp:192 +msgid "Constant skipping" +msgstr "Constant skipping" + +#: pcsx2/gui/Panels/VideoPanel.cpp:194 +msgid "" +"Normal and Turbo limit rates skip frames. Slow motion mode will still " +"disable frameskipping." +msgstr "" +"Normal dan Turbo membatasi skip frame. Mode Slow Motion masih menonaktifkan " +"frameskipping." + +#: pcsx2/gui/Panels/VideoPanel.cpp:217 +msgid "Frames to Draw" +msgstr "Frames to Draw" + +#: pcsx2/gui/Panels/VideoPanel.cpp:222 +msgid "Frames to Skip" +msgstr "Frames to Skip" + +#: pcsx2/gui/Panels/VideoPanel.cpp:298 +msgid "Use Synchronized MTGS" +msgstr "Gunakan MTGS yang tersinkronisasi" + +#: pcsx2/gui/Panels/VideoPanel.cpp:299 +msgid "" +"For troubleshooting potential bugs in the MTGS only, as it is potentially " +"very slow." +msgstr "" + +#: pcsx2/gui/Panels/VideoPanel.cpp:302 +msgid "Disable all GS output" +msgstr "Nonaktifkan semua output GS" + +#: pcsx2/gui/Panels/VideoPanel.cpp:303 +msgid "" +"Completely disables all GS plugin activity; ideal for benchmarking EEcore " +"components." +msgstr "" + +#: pcsx2/gui/Panels/VideoPanel.cpp:320 +msgid "Frame Skipping" +msgstr "Frame Skipping" + +#: pcsx2/gui/Panels/VideoPanel.cpp:323 +msgid "Framelimiter" +msgstr "Framelimiter" + +#: pcsx2/gui/SysState.cpp:283 +msgid "" +"Cannot load this savestate. The state is from an incompatible edition of " +"PCSX2 that is either newer than this version, or is no longer supported." +msgstr "" +"Gagal me-load savestate ini. Savestate tersebut berasal dari versi PCSX2 " +"yang tidak cocok dimana versi tersebut mungkin lebih baru, ataupun tidak " +"didukung lagi." + +#: pcsx2/gui/SysState.cpp:290 +msgid "" +"Cannot load this savestate. The state is an unsupported version, likely " +"created by a newer edition of PCSX2." +msgstr "" +"Gagal me-load savestate ini. Savestate ini adalah versi yang tidak didukung, " +"kemungkinan besar dibuat oleh PCSX2 yang lebih baru." + +#: pcsx2/gui/SysState.cpp:326 +msgid "There is no active virtual machine state to download or save." +msgstr "Tidak ada mesin virtual yang sedang aktif untuk unduh maupun simpan." + +#: pcsx2/gui/SysState.cpp:520 +msgid "" +"This savestate cannot be loaded because it is not a valid gzip archive. It " +"may have been created by an older unsupported version of PCSX2, or it may be " +"corrupted." +msgstr "" +"Savestate ini tidak dapat di-load karena bukan merupakan gzip yang valid. " +"File tersebut mungkin telah dibuat oleh versi PCSX2 yang tua, ataupun korup." + +#: pcsx2/gui/SysState.cpp:579 +msgid "This file is not a valid PCSX2 savestate. See the logfile for details." +msgstr "" +"File ini bukanlah savestate PCSX2 yang valid. Lihat file log untuk lebih " +"lanjut." + +#: pcsx2/gui/SysState.cpp:598 +msgid "" +"This savestate cannot be loaded due to missing critical components. See the " +"log file for details." +msgstr "" +"Savestate ini tidak dapat di-load berhubung hilangnya komponen penting. " +"Lihat file log untuk lebih lanjut." + +#: pcsx2/gui/i18n.cpp:63 +msgid " (default)" +msgstr "" + +#: pcsx2/ps2/BiosTools.cpp:83 pcsx2/ps2/BiosTools.cpp:151 +msgid "The selected BIOS file is not a valid PS2 BIOS. Please re-configure." +msgstr "" +"File BIOS yang dipilih bukanlah BIOS PS2 yang valid. Silakan ulang " +"konfigurasi." + +#: pcsx2/ps2/BiosTools.cpp:244 +msgid "" +"The PS2 BIOS could not be loaded. The BIOS has not been configured, or the " +"configuration has been corrupted. Please re-configure." +msgstr "" +"BIOS PS2 gagal dijalankan. BIOS belum dikonfigurasi, atau hasil konfigurasi " +"korup. Silakan ulang konfigurasi." + +#: pcsx2/ps2/BiosTools.cpp:251 +msgid "The configured BIOS file does not exist. Please re-configure." +msgstr "File BIOS yang dikonfigurasi tidak wujud. Silakan ulang konfigurasi." + +#: pcsx2/x86/ix86-32/iR5900-32.cpp:578 +#, c-format +msgid "" +"%s Extensions not found. The R5900-32 recompiler requires a host CPU with " +"MMX, SSE, and SSE2 extensions." +msgstr "" +"Ekstensi %s tidak ditemukan. Recompiler R5900-32 membutuhkan sebuah komputer " +"hosti dengan ekstensi MMX, SSE, dan SSE2." + +#: pcsx2/x86/microVU.cpp:28 +#, c-format +msgid "" +"%s Extensions not found. microVU requires a host CPU with MMX, SSE, and " +"SSE2 extensions." +msgstr "" +"Ekstensi %s tidak ditemukan. microVU membutuhkan sebuah komputer hosti " +"dengan ekstensi MMX, SSE, dan SSE2." + +#~ msgid "mVU Block Hack" +#~ msgstr "mVU Block Hack" + +#~ msgid "" +#~ "Good Speedup and High Compatibility; may cause garbage graphics, SPS, " +#~ "etc..." +#~ msgstr "" +#~ "Peningkatan kecepatan dan Kompatibilitas Tinggi; bisa menyebabkan grafis " +#~ "sampah, SPS, dll... [Direkomendasikan]" From 004eb6a2f79d9520cfbf9916c4ec19eab8065e39 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Tue, 28 Feb 2012 12:07:06 +0000 Subject: [PATCH 16/83] i18n: update sv_SE too ;) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5108 96395faa-99c1-11dd-bbfe-3dabce05a288 --- bin/Langs/sv_SE/pcsx2_Iconized.mo | Bin 18127 -> 19153 bytes bin/Langs/sv_SE/pcsx2_Main.mo | Bin 54102 -> 54613 bytes locales/sv_SE/pcsx2_Iconized.po | 443 ++++++++++++---------- locales/sv_SE/pcsx2_Main.po | 603 +++++++++++++++--------------- 4 files changed, 544 insertions(+), 502 deletions(-) diff --git a/bin/Langs/sv_SE/pcsx2_Iconized.mo b/bin/Langs/sv_SE/pcsx2_Iconized.mo index 3be60a9a8627c101c9aeff0c0e10249205bc16ac..8aba6c8f320a8f7337ec65878df6db4bf1404c37 100644 GIT binary patch delta 5481 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 F{twP{(scj; diff --git a/bin/Langs/sv_SE/pcsx2_Main.mo b/bin/Langs/sv_SE/pcsx2_Main.mo index 94b3f45568c1e5ef446a1ba94c5d8085131fbcb4..a4f64e16c40ef829061e0e29da36502699e36330 100644 GIT binary patch delta 9651 zcmbW*33L=yy1?-YO9IWlg#-u|387ii4TOLaab!yXAtaJza9k^Nb<=crbzW5`!ng!P z5J3^Rps1)I1W+~=1VkMjBMPF3IL@Z?W;ySSGmhiv3_cx4o%jE$I=GB;-aGFc4!^q9 zwcPvN?=F>}?ri_oqwOEt(W`lyrfKbO*0cpU1Bc=s^x+xofp6nL{8QSjX779f-o*KF zXyN0SkNQ$gTZGf_QrwTj@dI3j{rQhaY4|nx$eP_pk=d zTfGM#L#f#FScEU5g!UYkVaW>b!9PUlvK819H{oTt6Z_#u_&v;8sc8vpF6TflIE2^W zKXDXZbDLM=)hG|#hH-oxrNV<(c`cuhIh4aFp>4)Iyggmsh0?IcQ6hH=$K%hC3N>rp zZl^yvQGgw=3A^JBD4|`Ay>K(?_$W#UPoX5`Pf;HHSCkfiiM_GMYVW>$yohoMcESXf zU=w!b{n{Q5GC6S+JK}RFEk2$;{}x_O`5i34;2KSvjq^~t=t10of5Q~6yu-WyAJ~O* zmpi@Z_D6$q9?JP1F;fX!a$Yf$@n^2lvRk|e?8e!YA4kdlFHkBrW~bM8 zr8t`MwfF*oE?@wA)ZZybn9$^C*#d1*IitQCgU@-;3Y~>_j<$7vlt+ zfi_Am9Ye{vpCOTJ);{1s9(WEH;OCf$*B#Kb=@>zo7xrQRUqT7>Is6`GKITQF45i{V zD8FBaGUeJRNw_NQUhGNv3Mk|8UKS1GA8jJ?13+!yyz?r!C#|PDC3Y9!a*q4 zO+<;zEX>CRn1d@(BKi=@b9Ui4JcNb#2fQA;KS^aIgey5H#^WgEPf_~l!o%JMV=fM+ zd=tvly9KlH5K14PLWw}u5ij)pun%QFN|#)W5{Vhu8|S0sLhK0fmkU;LLRz{JBX}64 z1%r=z4;qFN@=_d)W$AJwN(+~w+;=C+gFi-zSnsF27Y4AD@?@0cyaBu8txpmE3ph}m zkQ)!8)bvc+-{Pf||B8}~#mBrCUXPMgw_*p}jRSEX_QI1W5qKNrxqm^)v93>h!*wj` zlq;J#@N>|B<+vH=;jd9DR{V_D*Yi+nT#v)>KX4#!PJ0Mt9yo(?-3KU<{UTlN{H!;6 za!{@-$6Rae~AWhKjvUQ_BiQXxDeaR z1$ZUii2d>BD8ueUlon>a;$`_IcopUOI2fNqnQ(rB(=h*(rd^F;wDCn8gcrU_MP)qJ zaBwk3a4K#`iNNnslBD=GZ-SbGBPd^w9dR38j=PW%r~MrZ@rl#v3ZvZrAxevVuk)dc z)z}T+d!0Z@i$3LqT+ri;H+<%!WcMPRjw`Vpp28wLjZ%?+;Akv-!<)crv5fL6lnS0k zdCpJJjT}mavd((RJmf6#mlrJHL;>zb3C*i05B?*{4Y_Z6%j-Cl>#xNDxC3R>JcncP z9CpWHKk?>~@z{@YIZDN^!ZCO|=Hani4y1-Z#~FAIb8ymI2L}|4y`sao(lHZM<&6Wo z6$i!?2Z}G!#}=24FFAPqjT$5B;6 zW+$z1G}34rsc6!2stn7Fn^sWsO*Ip(JM37g?)Oh`tgnxow&C}W_WS1=39Eid$~~@* z84cdq*@ok|SLm^1B4OJ4thqIV%iK4%wxmp3UK=s3WP-;{X{xt*fZBZX+KjOBH_uWJ z9Lecm*p{K*Xzr64)CwIvtTs3Md)vBc=}lB46qr_3t0&Bm+HxfK{G~nQQoo~@(>Nz( z=qh7rewWr2PBfHsT6d&UYUI*Odk3QFhBnyAh;1ZFb@jugR)$}_yL1`y7`vE3|(!%Wm3j4^}AbY0;#LDNyBOgTD=i7v@%PtiW^I+Q*Ojw*k7!h ziN?5*O4`~iD`Ki^mgi(R>W1a@?aFNR&hp%GKAjfm3(a`S?S_R>D`XoX(>*I)ve3{& zreztr(UdUk7-0;lj<*i!W!Nc4Ped)tbYe+6rTf%{w+5(K=+@!7?(-2PpHC|{VyUPT z)2CNV2}mcKDbtKQrh4?&$NHv{@t760B90>$HAPeWs1hqS`sfn6$)R6V_m$b5Jc4nGh|q5^y=KPdN3H&hRriA$IymNn_f3vlmGO1>kda6Y1o>VSlVpE(xVnl zwO8lo>SmZ`IwT&EbW)N~Mw1?*v3pksb@!QV*Xwa36f*R(Ipu-+s70TdmilD%>@HtD zBBaXJ6!v%YCZ5P>37&tIB)aN#hpx7)DerE^87#WIQfhJVzt{B4P+51b@fzUPUymmv z5u#3oOj|m5VQULFr8MtXBOW*OLMNb}yEE@1zrQWL8AIfkrPtWWcsypZ^q zhTgyk^ZTa~ju7eP_p5em{o~F*+pt2WqgPFixBoM_DwI9E=g|Cc`##o30NpiKnw%FAMSeLVDUUf~xYa@dNc}$TZr1 zmAr3ExkH_3mATbG~)5jyZ##*S zjFEnSb>+0m3cZ+FcxLT%$r*R5Y?BGoPPqkj$HtKZ1Ehi-l7I%a+EkOdAQq>mNf*Ob zuWp>tCE!g6c4H!_-r1P1CT+@QOjd82&i|V?P0UECvzrQ3(H5Wja??$myYX(LTif{7 zr&U(@)q8i3$P6Tm1$I*9-g8$wqe<<)r&9Rjo^s)m%|#t!k{haF^D1V@Pd68~GaWVf z-e&^~mc-2XLW6}Pvd~QFS59fNTU$u1tF^K+R+W&$T(%&l2V|6mRk!d7rX;Hbv~L-KeO zY3%6cqM)A6*{>EhRrbKBc797WJm9aHEo)p=bulYKUDQrBG7b&B!f;|y%gwDi(~dd3 zl+%m`nFh+r+&NPk;mGV@H@cNI?I3fB6K_lz>YWDy!{e=oS={sxgESgp3AK%IG}d~U zS%8ri@z&Pz^7#Q3e6Vl;%VjhYO(ZRSUSon~Q=h^-Vo3L^=!5xXet(S-XDBAa`gD^( zT1#XMm$SOfH6u))P5ShxOfRNB(+j0^9s_$uqZKj|1SuA`@ohbDX#x?K<5 z)P9Q9pbEE!hK8cH8B0+`8J4XrhD4=pPNQvQJjzk~w#s7i%dK-VY&Cq_C7n{*jB5V* zRczb7nYvFO$y-_EY`t=U$rvBUySGTQP z3yH#&+Y7t$HFx)6%z{Wvb~d1zqb+(lSLt7k#NM|+nKD^?=CK4LW|N?x4z$Xk-Nhq)mzAOb$VsCdVlvoDwXxfm_FYzI8^B) zdF{Ax{v+q|d@R8{xKZLx4HB&_(h01J?t;4L(Quz+6K^)GNVJKp_Ts7Dd9+{{*}`Vb zuZPl`#gMnn^v(vgbQDynNRLae=`rt3^-(h%CVd%&=Tk$S z-c#P|Ut`gKZ_pQFp^nzekXCc|PROWNEA|!)stqI)>~I>$LYiT^`-;Sp1u+8ZQ?KnE z-RlRkEx_jT$&M9qf(oV3N zso(6&`##HqI~y!yoslJ>h=I}+jmz6YN#;Y^Wi`6JUm&FzN|rEMs*YWpHj_T$eCxWtILY@woG4qpoAT8 zwtC?}b_cpSseXB2q<4_{*a^D-^~Xl`m1$I~KEEAvo2I%yexPd&I|!2|$=ZAH&1@_&iwkt-}?3HLpj60xpJTX z_^7ezD-tR_2{Vn{d+10;qq_XbsxGpgGqFjW)y^lA1Jd6kU+Y3GeM&WK$X1ny`)3#` zeE7cn))k}_cc%>Pt3z*)HAoLL0)`$b>hCTU#MSLDI>w5)tGtRFxqnzaxio_C?O>Cx z%T4l=EF|&;AUnB;Z2MHf(V!Qt%a0Bs?unzT`+esqRi7Q5J2!BCZyt0zMq~dHU!=?4 z*3YWPpoqr-Q<*Pc9=n?mra{h z%ue>{?A!ofU<*vgN!laQKe|`?9rgax)l_=&GbQ}r_)J0mzgxyH)vBXzqz$#_nX8-K z`R}_I{Gc|I!D#62xYR4E%4W1}O=OT#FYkvY_M}OBba_RcpB|06i>o)Sx*Jq0B;T!a z$bKQc8jTLyOB~bT1uFGyUY4xq^(5%VXN!8umyDYQrP>_%*ivVn4RxNLj5RW+rUL4c zA05lk4}SWix(s)3`Pg%P)$PxR)rZgDmMya@Q-)(WdX&W~$lf5u=HtE}&!{c4C8kmb z_p^Wz>TPUf9}tc%rYZlQ@5`<){E4ZhFvtDmae{1Kr&#GtbE)j=RdMTBQa98(wP$)O zm1^5csokwNjvP+XS0}9{BXn7HS*$|R8GNYP?z-TxHHe!rmJ*-3?8O(_JFP9M%kkVE zm2y?0^|0*BWwGpaN4A=Fd}hW}_0I8;neH|rr0zIgp)y|@(b4^ORbyV7nA7&yD06}g zwPYliTFjpy)XguAEaC%c>=@ZZRr3iXi z+WQXO`LaJV%*@YZ@aD@?GiIsm6O((8B|0m4Lweh&A}2=obleXvQyL;4K0&qf#85tq zPoAjw#tb#^WCJz2Gnm(PUME%S4K|srT;V{ot%=XukCBD zyhPeH#oM14c3Udx!`r6(8(taOEZ^O-)|;}a{nj5l+^{LM%*jMYX@&$x7g;Vf9_K7xICLxa0WMe4q_QLU1%ZHo_3 zZ!is~T6{3*)r~AKH2WLt@(?D1THXDspaqBHp|3tE)K#Z)a{c}?+myjW&1SHYha?wc7{(<*AEcXf3Y0k!}173~>0 z>Q|=+WTtmQ{?`lpcpFS_8gXYh{^WGk>xB|AvqD|)##VlL l{*6Hw{4Zbo>XSDvR%6dD;j`?Kvt``#m$TPp1>Eg}_CMNQhVuXb delta 9093 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 DIyK%+ diff --git a/locales/sv_SE/pcsx2_Iconized.po b/locales/sv_SE/pcsx2_Iconized.po index 401422ab3..bfafd1c67 100644 --- a/locales/sv_SE/pcsx2_Iconized.po +++ b/locales/sv_SE/pcsx2_Iconized.po @@ -4,8 +4,8 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2012-02-28 12:20+0100\n" -"PO-Revision-Date: 2011-11-16 12:51+0100\n" +"POT-Creation-Date: 2012-02-28 13:06+0100\n" +"PO-Revision-Date: 2012-02-28 12:54+0100\n" "Last-Translator: Georg Ronnert \n" "Language-Team: \n" "Language: \n" @@ -23,41 +23,43 @@ msgstr "" #: common/src/Utilities/Exceptions.cpp:254 msgid "!Notice:VirtualMemoryMap" msgstr "" -"Det finns inte tillräkligt med virtuellt minne tillgängligt, eller så har " +"Det finns inte tillräckligt med virtuellt minne tillgängligt, eller så har " "den nödvändiga \n" -"virtuella minnestilldelningen redan blivit reserverat av andra processer, " +" virtuella minnestilldelningen redan blivit reserverat av andra processer, " "tjänster, eller DLL'er." #: pcsx2/CDVD/CDVD.cpp:390 msgid "!Notice:PsxDisc" msgstr "" -"Playstation speldiskar stödjes inte av PCSX2. Om Ni vill emulera PSX spel \n" -"så måste Ni ladda ner en PSX-specifik emulator, såsom ePSXe eller PCSX." +"PlayStation®One speldiskar stödjes inte av PCSX2. Om Ni vill emulera PSX-" +"spel \n" +" får Ni använda en särskild PSX-emulator, såsom ePSXe eller PCSX." #: pcsx2/System.cpp:114 msgid "!Notice:Recompiler:VirtualMemoryAlloc" msgstr "" "Denna omkompilerare var oförmögen att reservera det angränsande minne som " -"kräves för interna förråd. \n" -"Detta fel kan ha orsakats av låga VM-resurser, såsom en liten eller " -"förhindrad bytfil, \n" -"eller av ett annat program som tar för sig mycket minne. Ni kan annars pröva " -"minska förvalsförrådsstorleken \n" -"för alla av PCSX2's omkompilerare, vilket finns under Värdinställningar." +"krävs för inhemska förråd. \n" +"Detta fel kan ha orsakats av låga Virtuella Maskin resurser, såsom en liten " +"eller förhindrad bytfil, \n" +" eller av ett annat program som tar för sig mycket minne. Ni kan annars " +"pröva minska förvalsförrådsstorleken \n" +" för PCSX2's alla omkompilerare, vilket kan göras genom " +"''Värdinställningar''." #: pcsx2/System.cpp:348 msgid "!Notice:EmuCore::MemoryForVM" msgstr "" -"PCSX2 är oförmögen att tilldela det minne som kräves för PS2-VM. \n" +"PCSX2 är oförmögen att tilldela det minne som krävs för PS2's Virtuella " +"Maskin. \n" "Stäng minneskrävande bakgrundsprogram och försök igen." #: pcsx2/gui/AppInit.cpp:43 msgid "!Notice:Startup:NoSSE2" msgstr "" -"Varning: Er dator stödjer inte SSE2, vilket krävs av många PCSX2 " +"Varning: Er dator stödjer inte SSE2, vilket krävs för många av PCSX2's " "omkompilerare och insticksprogram. \n" -"Era möjligheter kommer att vara begränsade och emuleringen att vara *mycket* " -"långsam." +"Era möjligheter kommer vara begränsade och emuleringen blir *mycket* långsam." #: pcsx2/gui/AppInit.cpp:162 msgid "!Notice:RecompilerInit:Header" @@ -76,155 +78,155 @@ msgstr "" #: pcsx2/gui/AppMain.cpp:546 msgid "!Notice:BiosDumpRequired" msgstr "" -"PCSX2 kräver PS2-BIOS för att köras. \n" +"PCSX2 kräver PS2 BIOS för att köras. \n" "Av juridiska skäl *måste* Ni anskaffa ett BIOS från en faktisk PS2-enhet som " -"Ni äger (tillåns räknas inte). \n" -"Konsultera FAQ's och Guider för ytterligare information." +"Ni äger (tillåns gäller inte). \n" +"Undersök FAQ'er och Guider för ytterligare information." #: pcsx2/gui/AppMain.cpp:629 msgid "!Notice Error:Thread Deadlock Actions" msgstr "" -"Ignorera' för att fortsätta vänta på trådarna att svara. \n" -"Avbryt' för att försöka avbryta tråden. \n" -"Avsluta' för att avsluta PCSX2 omedelebart." +"''Ignorera'' för att fortsätta vänta på trådarna att svara. \n" +"''Avbryt'' för att försöka avbryta tråden. \n" +"''Avsluta'' för att avsluta PCSX2 omedelebart." #: pcsx2/gui/AppUserMode.cpp:57 msgid "!Notice:PortableModeRights" msgstr "" "Försäkra Er om att dessa mappar är skapade och att Er användarbehörighet " "medger \n" -"skrivskydd för dem -- eller återkör PCSX2 med upphöjd (administratör) " +" skrivning för dem -- eller återkör PCSX2 med upphöjd (Administratörs) " "behörighet, \n" -"vilket borde medge PCSX2 förmågan att skapa de nödvändiga mapparna självt. \n" -"Om Ni inte har upphöjd behörighet för denna dator, \n" -"måste Ni byta till Användar Dokument läge (klicka på knappen nedanför)." +" vilket borde medge PCSX2 förmågan att skapa de nödvändiga mapparna " +"självt. \n" +"Om Ni inte har upphöjd behörighet för Er dator, \n" +" får Ni byta till AnvändarDokument-läge (klicka på knappen nedanför)." #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:181 msgid "!ContextTip:ChangingNTFS" msgstr "" -"NTFS komprimering kan ändras manuellt när som helst genom att använda " -"filegenskaper hos Windows Explorer." +"NTFS-komprimering kan ändras manuellt när som helst \n" +" genom att använda filegenskaper hos Windows Explorer." #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:49 msgid "!ContextTip:Folders:Settings" msgstr "" "Detta är mappen där PCSX2 sparar Era inställningar, och då även " "inställningar skapade \n" -"av de flesta insticksprogram (gäller måhända dock inte för vissa äldre " +" av de flesta insticksprogram (gäller måhända dock inte för vissa äldre " "insticksprogram)." #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:54 msgid "!Panel:Folders:Settings" msgstr "" "Ni kan förslagsvis ange en placering för Era PCSX2-inställningar här. Om " -"placeringen \n" -"innehåller befintliga PCSX2-inställningar, så kommer Ni erbjudas möjligheten " -"att importera och överskriva." +"placeringen innehåller \n" +" befintliga PCSX2-inställningar kommer Ni ges möjlighet att importera och " +"överskriva." #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:94 msgid "!Wizard:Welcome" msgstr "" -"Denna trollkarl kommer att vägleda Er igenom " +"Denna trollkarl kommer att hjälpleda Er genom " "konfigurationsinsticksprogram, \n" -"minneskort, och BIOS. Ifall detta är första gången Ni installerar %s, \n" -"så rekommenderas Ni att kolla in Läsmig och konfigurationsvägledningen." +" minneskort, och BIOS. Ifall detta är första gången Ni installerar %s, \n" +" Anrådes Ni att undersöka ''Läs mig'' och ''KonfigurationsVägledningen''." #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:140 msgid "!Wizard:Bios:Tutorial" msgstr "" -"PCSX2 kräver *lagligt* PS2-BIOS för att köra spel. \n" -"Ni kan inte använda en kopia anförskaffat från en vän eller genom " -"Internet. \n" -"Ni måste dumpa BIOS'et från Er *egna* Playstation 2 konsol." +"PCSX2 kräver *lagligt* PS2 BIOS för att köra spel. \n" +"Ni får inte använda en kopia anförskaffat genom en vän eller Internet. \n" +"Ni måste dumpa BIOS'et från Er *egna* PlayStation®2 konsol." #: pcsx2/gui/Dialogs/ImportSettingsDialog.cpp:31 msgid "!Notice:ImportExistingSettings" msgstr "" -"Befintliga %s inställningar har hittats i " -"konfigurationsinställningsmappen. \n" -"Vill Ni importera dessa inställningar och överskriva %s förval med dem? \n" +"Befintliga %s-inställningar har hittats i " +"Konfigurationsinställningsmappen. \n" +"Vill Ni importera dessa inställningar och överskriva %s's förval med dem? \n" "\n" -"\n" -"(eller tryck Avbryt för att välja en annan mapp)" +"(eller tryck ''Avbryt'' för att välja en annan mapp)" #: pcsx2/gui/Dialogs/McdConfigDialog.cpp:30 msgid "!Panel:Mcd:NtfsCompress" msgstr "" -"NTFS komprimering är inbyggt, snabbt, och helt tillförlitligt; \n" -"det komprimerar vanligtvis minneskort mycket bra (denna tillämpning " -"rekommenderas)." +"NTFS-komprimering är inbyggt, snabbt, och helt tillförlitligt; det " +"komprimerar \n" +" vanligtvis minneskort mycket bra (denna tillämpning Anrådes tydligt)." #: pcsx2/gui/Dialogs/McdConfigDialog.cpp:41 msgid "!Panel:Mcd:EnableEjection" msgstr "" "Undviker minneskortsförstörelse genom att tvinga spel att återindexera " "kortinnehåll \n" -"efter att ha laddat från sparpunkt. Måhända inte förenligt med alla spel " -"(Guitar Hero)." +" efter att ha laddat från sparpunkt. Måhända inte förenligt med alla spel " +"(''Guitar Hero'')." #: pcsx2/gui/Dialogs/StuckThreadDialog.cpp:33 msgid "!Panel:StuckThread:Heading" msgstr "" -"Tråden '%s' svarar inte. \n" -"Den kan ha gått i baklås, eller kanske bara kör *väldigt* långsamt." +"Tråden ''%s'' svarar inte. \n" +"Den kan ha gått i baklås, eller kör kanske bara *väldigt* långsamt." #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:38 msgid "!Panel:HasHacksOverrides" msgstr "" -"Varning! Ni kör PCSX2 med instruktionsmöjligheter som upphäver Era " -"konfigurationsinställningar. Dessa instruktionsmöjligheter kommer inte " -"beaktas i Inställningar, och kommer att förhindras om Ni tillämpar några " -"förändringar här." +"Varning! Ni tillämpar PCSX2 med åsidosättning av Era " +"konfigurationsinställningar. \n" +"Detta åskådliggörs inte i Inställningar, och kommer att förhindras om Ni " +"tillämpar några förändringar här." #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:58 msgid "!Panel:HasPluginsOverrides" msgstr "" -"Varning! Ni kör PCSX2 med instruktionsmöjligheter som upphäver Era insticks- " -"och/eller mappkonfigurationsinställningar. Dessa instruktionsmöjligheter " -"kommer inte beaktas i Inställningar, och kommer att förhindras om Ni " -"tillämpar några förändringar här." +"Varning! Ni tillämpar PCSX2 med åsidosättning av Era insticks- och/eller " +"mappkonfigurationsinställningar. \n" +"Detta åskådliggörs inte i Inställningar, och kommer att förhindras om Ni " +"tillämpar inställningsförändringar här." #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:135 msgid "!Notice:Tooltip:Presets:Slider" msgstr "" -"Förinställningarna tillämpar snabbfixar, några omkompilerarmöjligheter, och " -"en del spelfixar som till vetskap höjer farten.\n" -"Spelfixar som till vetskap är viktiga ('Patchar') kommer tillämpas " -"automatiskt.\n" +"Förinställningarna tillämpar snabbfixar, några omkompilerarfunktioner, \n" +" och en del spelfixar som till vetskap ökar farten. \n" +"Spelfixar som till vetskap är viktiga (''Patchar'') kommer tillämpas " +"automatiskt. \n" "\n" -"Förinställningsinfo:\n" -"1 - Det riktigaste emuleringen, men också den långsammaste.\n" -"3 --> Försöker balansera hastighet med förenlighet.\n" -"4 - Några mer aggresiva fixar.\n" -"6 - För många fixar kommer förmodligen att sakta ner de flesta spel." +"Förinställningsinfo: \n" +" 1 - Det riktigaste emuleringen, men också den långsammaste. \n" +" 3 --> Försöker balansera hastighet med förenlighet. \n" +" 4 - Några mer aggresiva fixar. \n" +" 6 - För många fixar kommer förmodligen att sakta ner de flesta spel." #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:149 msgid "!Notice:Tooltip:Presets:Checkbox" msgstr "" -"Förinställningarna tillämpar snabbfixar, några omkompilerarmöjligheter, och " -"en del spelfixar som till vetskap höjer farten.\n" -"Spelfixar som till vetskap är viktiga ('Patchar') kommer tillämpas " -"automatiskt.\n" +"Förinställningarna tillämpar snabbfixar, några omkompilerarfunktioner, \n" +" och en del spelfixar som till vetskap höjer farten. \n" +"Spelfixar som till vetskap är viktiga (''Patchar'') kommer tillämpas " +"automatiskt. \n" "\n" -"--> Avmarkera för att ändra inställningarna manuellt (med nuvarande " +"--> Avmarkeras för att ändra inställningarna manuellt (med nuvarande " "inställningar som bas)" #: pcsx2/gui/IsoDropTarget.cpp:28 msgid "!Notice:ConfirmSysReset" msgstr "" -"Detta kommer att återställa det befintliga PS2-VM-tillståndet; \n" -"alla nuvarande processer kommer at förloras. Är Ni säker?" +"Detta kommer att återställa det befintliga Virtuella Maskin PS2-" +"tillståndet; \n" +" alla nuvarande processer kommer at förloras. Är Ni säker?" #: pcsx2/gui/MainMenuClicks.cpp:106 msgid "!Notice:DeleteSettings" msgstr "" -"Detta kommando rensar %s inställningarna \n" -"och låter Er att återköra Första-Gången Trollkarlen. \n" -"Ni måste manuellt återstarta %s efter detta. \n" +"Detta rensar %s-inställningarna \n" +" och låter Er att återköra ''Första gången Trollkarlen''. \n" +"Ni får återstarta %s manuellt efter detta. \n" "\n" -"VARNING! Tryck OK för att makulera *ALLA* inställningar för %s \n" -"och tvångstänga tillämpningen, \n" -"med följd att alla nuvarande emuleringsprocesser mistes. Är Ni helt säker? \n" +"VARNING! Tryck ''Vidare'' för att rensa *ALLA* inställningar \n" +"för %s och tvångstänga programmet, med följd att \n" +"alla nuvarande emuleringsprocesser mistes. Är Ni helt säker? \n" "\n" "(Bemärk: inställningar för insticksprogram påverkas ej)" @@ -233,46 +235,64 @@ msgid "!Notice:Mcd:HasBeenDisabled" msgstr "" "Minneskortet i sockel %d har blivit automatiskt förhindrat. Ni kan åtgärda " "problemet \n" -"och återmöjliggöra minneskortet när som helst genom Konfig:Minneskort i " +" och återmöjliggöra minneskortet när som helst genom Konfig:Minneskort i " "huvudmenyn." #: pcsx2/gui/Panels/BiosSelectorPanel.cpp:138 msgid "!Notice:BIOS:InvalidSelection" msgstr "" -"Välj ett giltligt BIOS. Om ni är oförmögen att göra ett giltligt val \n" -"så tryck Avbryt för att stänga Konfigurationspanelen." +"Välj ett giltligt BIOS. Är Ni oförmögen att göra detta \n" +" så tryck ''Avbryt'' för att stänga Konfigurationspanelen." #: pcsx2/gui/Panels/CpuPanel.cpp:111 msgid "!Panel:EE/IOP:Heading" -msgstr "Bemärk: De flesta spel har det fint med förvalstillämpningarna." +msgstr "" +"EE = Emotion Engine = Rörelse Motor \n" +"IOP = Input Output Processor = In Ut Processor \n" +"\n" +"Bemärk: De flesta spel har det fint med förvalssättningarna." #: pcsx2/gui/Panels/CpuPanel.cpp:178 msgid "!Panel:VUs:Heading" -msgstr "Bemärk: De flesta spel har det fint med förvalstillämpningarna." +msgstr "" +"VM = Virtual Machine = Virtuell Maskin \n" +"VU = Vector Unit = Vektor Enhet \n" +"\n" +"Bemärk: De flesta spel har det fint med förvalssättningarna." #: pcsx2/gui/Panels/DirPickerPanel.cpp:69 msgid "!Notice:DirPicker:CreatePath" -msgstr "Den angivna sökvägen/katalogen finnes ej. Vill Ni skapa den?" +msgstr "Den angivna sökvägen/katalogen finns ej. Vill Ni skapa den?" #: pcsx2/gui/Panels/DirPickerPanel.cpp:158 msgid "!ContextTip:DirPicker:UseDefault" msgstr "" -"När markerad kommer denna mapp att automatiskt begrunda förvalen assosierade " -"med PCSX2's nuvarande användarinställningar." +"När markerad kommer denna mapp automatiskt att fungera enligt förvalen " +"förknippade med PCSX2's nuvarande användarinställningar." #: pcsx2/gui/Panels/GSWindowPanel.cpp:55 msgid "!ContextTip:Window:Zoom" msgstr "" -"Påverkar till vetskap följande spel:\n" -"* Test Drive Unlimited\n" -"* Transformers" +"Zoom = 100.0: Anpassa hela bilden till fönstret utan beskärning. \n" +"Över/Under 100.0: Zooma in/ut. \n" +"Bemärk: Zoom-värdet återställs inte automatiskt; det sparas i \n" +" konfigurationsfilen, och tillämpas nästa gång Ni använder PCSX2. \n" +"Zoom = 0.0: Automatisk inzoomning tills de svarta räckena \n" +" är borta (bildkvot bevaras, en del av bilden går utanför fönstret). \n" +"Bemärk: Vissa spel ritar sina egna svarta räcken \n" +" vilka inte tas bort med ''0.0''. \n" +"\n" +"Tangentbord: \n" +" ''Ctrl'' + ''NumPad Plus'': Inzoomning \n" +" ''Ctrl'' + ''NumPad Minus'': Utzoomning \n" +" ''Ctrl'' + ''NumPad Stjärna'': Växla 100/0" #: pcsx2/gui/Panels/GSWindowPanel.cpp:63 msgid "!ContextTip:Window:Vsync" msgstr "" "Vsync slår ut skärmsönderrivning men har oftast en stor prestationseffekt. \n" -"Det tillämpas vanligtvis bara i helskärmsläge, och kanske inte fungerar för " -"alla GS-insticksprogram." +"Det tillämpas vanligtvis bara i helskärmsläge, \n" +" och kanske inte fungerar för alla GS-insticksprogram." #: pcsx2/gui/Panels/GSWindowPanel.cpp:68 msgid "!ContextTip:Window:ManagedVsync" @@ -282,74 +302,78 @@ msgstr "" "prestandastraff. \n" "Bemärk: Detta fungerar för närvarande bara bra med GSdx som GS-" "insticksprogram, \n" -"och konfigurationen DX10/11 Hårdvarutolkning. \n" -"Annat insticksprogram eller annat tolkningsläge kommer antingen att " -"ignoreras \n" -"eller producera en svart skärm som blinkar när läget byts. \n" -"Det kräver även att Vsync tillämpas." +" och med konfigurationen DX10/11 Hårdvarutolkning. \n" +"Annat insticksprogram eller tolkningsläge kommer antingen att ignoreras \n" +" eller alstra en svart skärm som blinkar när läget byts. \n" +"Det kräver även att Vsync möjliggörs." #: pcsx2/gui/Panels/GSWindowPanel.cpp:76 msgid "!ContextTip:Window:HideMouse" msgstr "" "Markera denna för att tvinga muspekaren att bli osynlig när den är i ett GS-" "fönster; \n" -"användbart om man har musen som främsta kontroll-mojäng för spelande. \n" -"Som förval auto-gömmer sig musen efter 2 sekunders inaktivitet." +" användbart vid brukande av musen som främsta styrmojäng för spelande. \n" +"Som förval gömmer sig muspekaren automatiskt efter 2 sekunders stillastående." #: pcsx2/gui/Panels/GSWindowPanel.cpp:82 msgid "!ContextTip:Window:Fullscreen" msgstr "" "Möjliggör automatiskt lägesbyte till fullskärm när emulering statas eller " "återupptas. \n" -"Ni kan ännu växla mellan helskärm och fönsterläge genom att trycka Alt + " -"Enter." +"Ni kan ännu växla mellan helskärm och fönsterläge genom att trycka ''Alt'' + " +"''Enter''." #: pcsx2/gui/Panels/GSWindowPanel.cpp:93 msgid "!ContextTip:Window:HideGS" msgstr "" "Stänger helt det ofta stora och omfångsrika GS-fönstret \n" -"när Ni trycker på Esc eller avbryter emulatorn." +" när Ni trycker på ''Esc'' eller avbryter emulatorn." #: pcsx2/gui/Panels/GameFixesPanel.cpp:67 msgid "!ContextTip:Gamefixes:EE Timing Hack" msgstr "" -"Påverkar till vetskap följande spel:\n" -" * Digital Devil Saga (Fixar FMV och brakar)\n" -" * SSX (Fixar dålig grafik och brakar)\n" -" * Resident Evil: Dead Aim (Orsakar förvrängda texturer)" +"Påverkar till vetskap följande spel: \n" +" * ''Digital Devil Saga'' (fixar FMV och brakar) \n" +" * ''SSX'' (fixar dålig grafik och brakar) \n" +" * ''Resident Evil: Dead Aim'' (orsakar förvrängda texturer)" #: pcsx2/gui/Panels/GameFixesPanel.cpp:80 msgid "!ContextTip:Gamefixes:OPH Flag hack" msgstr "" -"Påverkar till vetskap följande spel:\n" -" * Bleach Blade Battler\n" -" * Growlanser II & III\n" -" * Wizardry" +"Påverkar till vetskap följande spel: \n" +" * ''Bleach Blade Battler'' \n" +" * ''Growlanser II & III'' \n" +" * ''Wizardry''" #: pcsx2/gui/Panels/GameFixesPanel.cpp:89 msgid "!ContextTip:Gamefixes:DMA Busy hack" msgstr "" -"Påverkar till vetskap följande spel:\n" -" * Mana Khemia 1 (Går \"bortom behörighet\")" +"Påverkar till vetskap följande spel: \n" +" * ''Mana Khemia 1'' (går \"bortom behörighet\")" #: pcsx2/gui/Panels/GameFixesPanel.cpp:96 msgid "!ContextTip:Gamefixes:VIF1 FIFO hack" msgstr "" -"Påverkar till vetskap följande spel:\n" -"* Test Drive Unlimited\n" -"* Transformers" +"Påverkar till vetskap följande spel: \n" +"* ''Test Drive Unlimited'' \n" +"* ''Transformers''" #: pcsx2/gui/Panels/GameFixesPanel.cpp:119 msgid "!Panel:Gamefixes:Compat Warning" msgstr "" -"Spelfixar kan åtgärda felaktig emulering för vissa spel. \n" -"De kan dock orsaka förenlighets- eller prestandaproblem för andra spel. \n" -"Ni får stänga av Spelfixar manuellt när Ni byter spel." +"Spelfixar kan åtgärda felaktig emulering för vissa titlar. \n" +"De kan dock orsaka förenlighets- eller prestandaproblem. \n" +"Ni får stänga av Spelfixar manuellt när Ni byter spel. \n" +"\n" +"Det är i allmänhet bättre att förhindra denna tillämpning, och att " +"möjliggöra ''Automatiska Spelfixar'' i huvudmenyn \n" +" (''Automatiska'' innebär: använd särskilt utvalda och beprövade lösningar " +"för särskilda spel)." #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:720 msgid "!Notice:Mcd:Delete" msgstr "" -"Ni är på väg att radera det formaterade minneskortet i sockel %u. \n" +"Ni är på väg att kassera det formaterade minneskortet i sockel %u. \n" "All data på detta kort kommer att förloras! Är Ni helt säker?" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:758 @@ -367,184 +391,189 @@ msgstr "" #: pcsx2/gui/Panels/MiscPanelStuff.cpp:35 msgid "!Panel:Usermode:Explained" msgstr "" -"Välj Ert föredragna mål för PCSX2 användar-nivå dokument nedanför \n" -"(inräknar minneskort, skärmbilder, inställningar, och sparpunkter). \n" +"Välj Ert föredragna mål för PCSX2's Användarnivå Dokument nedanför \n" +" (innefattar minneskort, skärmbilder, inställningar, och sparpunkter). \n" "Detta kan ändras när som helst genom Kärninställningspanelen." #: pcsx2/gui/Panels/MiscPanelStuff.cpp:41 msgid "!Panel:Usermode:Warning" msgstr "" -"Ni kan ändra det föredragna förvalsmålet för PCSX2 användar-nivå dokument " +"Ni kan ändra det föredragna förvalsmålet för PCSX2's Användarnivå Dokument " "här \n" -"(inräknar minneskort, skärmbilder, inställningar, coh sparpunkter). \n" -"Detta påverkar bara Standard Sökvägarna vilka ställs in för att använda " +" (innefattar minneskort, skärmbilder, inställningar, och sparpunkter). \n" +"Detta påverkar bara StandardSökvägarna vilka ställs in för att använda " "installationsförvalsvärdena." #: pcsx2/gui/Panels/PathsPanel.cpp:40 msgid "!ContextTip:Folders:Savestates" msgstr "" -"I denna mapp sparar PCSX2 sparpunkter, vilka är sparade antingen genom " +"I denna mapp sparar PCSX2 sparpunkter, vilka sparas antingen genom " "användning \n" -"av menyer/verktygsrad, eller genom att trycka på F1/F3 (spara/ladda)." +" av menyer/verktygsrad, eller genom att trycka på ''F1''/''F3'' (spara/" +"ladda)." #: pcsx2/gui/Panels/PathsPanel.cpp:50 msgid "!ContextTip:Folders:Snapshots" msgstr "" "I denna mapp sparar PCSX2 skärmbilder. Det faktiska skärmbildsformatet och " "stilen \n" -"kan variera beroende på vilket GS-insticksprogram som användes." +" kan variera beroende på vilket GS-insticksprogram som används." #: pcsx2/gui/Panels/PathsPanel.cpp:60 msgid "!ContextTip:Folders:Logs" msgstr "" "I denna mapp sparar PCSX2 sina loggfiler och diagnostiska rapporter. De " "flesta insticksprogram \n" -"håller fast vid denna mapp, men dock kan vissa äldre insticksprogram " +" håller sig till denna mapp, även om vissa äldre insticksprogram kan " "ignorera den." #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:242 msgid "!Notice:PluginSelector:ConfirmShutdown" msgstr "" "Varning! Att byta insticksprogram kräver en full nedstängning och " -"återställning av PS2-VM. \n" +"återställning av PS2's Virtuella Maskin. \n" "PCSX2 kommer att försöka att spara och återställa tillståndet, men om de " "nyligen valda insticksprogrammen \n" -"är oförenliga kan detta misslyckas, och alla nuvarande framsteg kommer att " +" är oförenliga kan detta misslyckas, och alla nuvarande framsteg kommer att " "förloras. \n" "\n" -"\n" -"Är Ni säker att Ni vill tillämpa inställningarna nu?" +"Är Ni säker att Ni vill tillämpa ändringarna nu?" #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:457 msgid "!Notice:PluginSelector:ApplyFailed" msgstr "" -"Alla insticksprogram måste ha giltliga val för att %s ska kunna köras. \n" -"Om Ni är oförmögen att göra ett giltligt val till följd av saknade " -"insticksprogram \n" -"eller en ofullständig installaion av %s, så tryck Avbryt för att stänga " +"Alla insticksprogram måste ha giltliga inställningar för att %s ska kunna " +"köras. \n" +"Är Ni oförmögen att göra detta till följd av saknade insticksprogram eller " +"en \n" +" ofullständig installaion av %s, så tryck ''Avbryt'' för att stänga " "Konfigurationspanelen." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:27 msgid "!Panel:Speedhacks:EECycleX1" msgstr "" -"1 - Förvals cykelgrad. Detta överensstämmer nästan med den faktiska " -"hastigheten hos en PS2-RörelseMotor." +"1 - Förvalscykelgrad. Detta överensstämmer \n" +"nästan med den faktiska hastigheten \n" +"för en PS2-EE." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:32 msgid "!Panel:Speedhacks:EECycleX2" msgstr "" -"2 - Minskar EE's cykelgrad med ungefär 33%. Mild uppsnabbning för de flesta " -"spel med hög förenlighet." +"2 - Minskar EE's cykelgrad med ungefär 33%. \n" +"Mild uppsnabbning och hög förenlighet \n" +"för de flesta spel." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:37 msgid "!Panel:Speedhacks:EECycleX3" msgstr "" -"3 - Minskar EE's cykelgrad med ungefär 50%. Måttfull uppsnabbning, \n" -"men *kommer* att orsaka stamningsaudio hos många FMV'er." +"3 - Minskar EE's cykelgrad med ungefär 50%. \n" +"Måttfull uppsnabbning, men *kommer* att \n" +"orsaka stamningsljud för många FMV'er." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:54 msgid "!Panel:Speedhacks:VUCycleStealOff" -msgstr "0 - Förhndrar VU Cykelstöld. Den mest förenliga inställningen!" +msgstr "" +"0 - Förhndrar VU-cykelstöld. \n" +"Den mest förenliga inställningen!" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:59 msgid "!Panel:Speedhacks:VUCycleSteal1" msgstr "" -"1 - Mild VU Cykelstöld. Lägre förenlighet, men en viss uppsnabbning för de " +"1 - Mild VU-cykelstöld. Lägre förenlighet, men en viss uppsnabbning för de " "flesta spel." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:64 msgid "!Panel:Speedhacks:VUCycleSteal2" msgstr "" -"2 - Måttfull VU Cykelstöld. Ännu lägre förenlighet, men markant uppsnabbning " -"hos vissa spel." +"2 - Måttfull VU-cykelstöld. \n" +"Ännu lägre förenlighet, men en \n" +"markant uppsnabbning för vissa spel." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:70 msgid "!Panel:Speedhacks:VUCycleSteal3" msgstr "" -"3 - Maximal VU Cykelstöld. Användningen är begränsad, \n" -"eftersom detta kommer att orsaka synligt flimrande hos de flesta spel." +"3 - Maximal VU-cykelstöld. Användningen är \n" +"begränsad, eftersom detta kommer att orsaka \n" +"synligt flimrande för de flesta spel." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:97 msgid "!Panel:Speedhacks:Overview" msgstr "" -"Snabbfixar förbättrar vanligtvis emuleringshastighet, men kan orsaka " -"trassel, bruten audio, \n" -"och falska FPS avläsningar. När Ni har emuleringsproblem, så förhindra denna " -"panel först." +"Snabbfixar förbättrar vanligtvis emuleringshastigheten, men kan orsaka " +"trassel, brutet ljud, \n" +" och falska FPS-avläsningar. Förhindra denna panel det första Ni gör vid " +"emuleringsproblem." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:129 msgid "!ContextTip:Speedhacks:EECycleRate Slider" msgstr "" -"Att sätta ett högre värde för denna glidare minskar verkningsfullt " -"klockhastigheten hos RörelseMotorns R5900 kärn-CPU, \n" -"och för oftast en hastghetsökning till spel som misslyckas att nyttja " -"möjligheterna med PS2's verkliga hårdvara fullt ut." +"Att sätta ett högre värde genom denna manick minskar \n" +" verkningsfullt klockhastigheten hos EE'ns R5900 kärn-CPU, \n" +" och ger oftast en hög hastghetsökning till spel som misslyckas \n" +" att nyttja möjligheterna med PS2's verkliga hårdvara fullt ut." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:150 msgid "!ContextTip:Speedhacks:VUCycleStealing Slider" msgstr "" -"Denna glidare kontrollerar mängden cykler som VU-enheten stjäl ifrån " -"RörelseMotorn. \n" -"Högre värden ökar antalet cykler som stjäls från EE'n för varje VU-" -"microprogram spelt kör." +"Denna manick styr mängden cykler som VU-enheten stjäler ifrån EE'n. \n" +"Högre värden ökar antalet cykler som stjäls från EE'n per VU-microprogram " +"spelet kör." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "!ContextTip:Speedhacks:vuFlagHack" msgstr "" -"Uppdaterar endast Statusflaggor för block som kommer att läsa dem, istället " -"för alltid. \n" -"Detta är för det mesta säkert, och Super-VU gör något liknande som standard." +"Uppdaterar endast Statusflaggor för block som kommer att läsa dem, \n" +" istället för alltid. Detta är för det mesta säkert, \n" +" och Super-VU gör något liknande som standard." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:174 msgid "!ContextTip:Speedhacks:vuThread" msgstr "" -"Kör VU1 i dess egna tråd (endast microVU1). I allmänhet en uppsnabbning för " -"CPU'er med 3 eller fler kärnor.\n" +"Kör VU1 i dess egna tråd (endast microVU1). \n" +"I allmänhet en uppsnabbning för CPU'er med 3 eller fler kärnor.\n" "Detta är säkert för de flesta spel, men en del är oförenliga och kan hänga.\n" -"Vad gäller GS-begränsade spel, kan en nedbromsning förekomma (särskilt hos " -"dubbelkärniga CPU'er)." +"Vad gäller GS-begränsade spel, kan en nedbromsning förekomma \n" +" (i synnerhet för dubbelkärniga CPU'er)." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:195 msgid "!ContextTip:Speedhacks:INTC" msgstr "" -"Denna fix fungerar bäst för spel som använder INTC-statusregistret för att " -"invänta Vsync'ar, \n" -"vilket i första hand omfattar icke-3D-RPG titlar. \n" -"Spel som inte använder denna Vsync-metod kommer på sin höjd att få en liten " -"uppsnabbning av denna fix." +"Denna fix fungerar bäst för spel som använder INTC-statusregistret \n" +" för att invänta Vsync'ar, vilket främst omfattar icke-3D-RPG titlar. \n" +"Spel som inte använder denna Vsync-metod \n" +" kommer på sin höjd att få en liten uppsnabbning." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 msgid "!ContextTip:Speedhacks:BIFC0" msgstr "" -"I första hand inriktat på EE tomgångs-loop hos adress 0x81FC0 i kärnan, " -"denna fix försöker att \n" -"upptäcka loopar vars kroppar garanterat resulterar i samma maskintillstånd " -"för varje upprepning \n" -"tills en schemaläggd händelse utlöser emulering av en annan enhet. Efter en " -"enskild upprepning av en sådan loop, \n" -"avancerar vi till tiden för nästa händelse eller till slutet av processorns " -"tidskvantum, vilket som än kommer först." +"Främst inriktat på EE-tomgångsloop hos adress 0x81FC0 i kärnan, försöker " +"denna fix \n" +" att upptäcka loopar vars kroppar garanterat medför samma maskintillstånd \n" +" vid varje upprepning tills en schemalagd händelse utlöser emulering av en " +"annan enhet. \n" +"Efter en enskild upprepning av en sådan loop, avancerar Vi till tiden för " +"nästa händelse \n" +" eller till slutet av processorns tidskvantum, vilket som än kommer först." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:207 msgid "!ContextTip:Speedhacks:fastCDVD" msgstr "" -"Kolla HDLaddar-förenlighetslistan för spel som till vetskap kommer till " +"Undersök HD-laddarförenlighetslistan för spel som till vetskap kommer till " "fråga \n" -"med det här (ofta markerat som behövande 'läge 1' eller 'långsam DVD')." +" med det här (ofta markerat som behövande ''läge 1'' eller ''långsam DVD'')." #: pcsx2/gui/Panels/VideoPanel.cpp:37 msgid "!ContextTip:Framelimiter:Disable" msgstr "" -"Bemärk att när Bildbegränsning är förhindrad så kommer Turbo och SlowMotion " -"lägena \n" -"inte att vara tillgängliga heller." +"Bemärk att när Bildbegränsning är förhindrad så kommer \n" +" Turbo och SlowMotion lägena inte att vara tillgängliga heller." #: pcsx2/gui/Panels/VideoPanel.cpp:227 msgid "!Panel:Frameskip:Heading" msgstr "" -"Bemärk: Till följd av PS2 hårdvaruutformning så är precist bildöverhoppande " -"omöjligt. \n" -"Att tillämpa det kan orsaka rejäla grafikfel hos vissa spel." +"Bemärk: Till följd av PS2's hårdvaruutformning \n" +" så är precist bildöverhoppande omöjligt. \n" +"Att tillämpa det kan orsaka rejäla grafikfel för vissa spel." #: pcsx2/gui/Panels/VideoPanel.cpp:306 msgid "!ContextTip:GS:SyncMTGS" @@ -555,37 +584,37 @@ msgstr "" #: pcsx2/gui/Panels/VideoPanel.cpp:310 msgid "!ContextTip:GS:DisableOutput" msgstr "" -"Tar bort allt norm-oljud orsakat av MTGS-trådens eler GPU'ns överdrag. Denna " -"möjlighet användes bäst i förening med sparpunkter: \n" -"spara ett tillstånd i en idealisk scen, tillämpa denna möjlighet, och " -"återladda sparpunkten.\n" +"Tar bort allt norm-oljud orsakat av MTGS-trådens eler GPU'ns överdrag. \n" +"Denna tillämpning används bäst i förening med sparpunkter: \n" +" spara ett tillstånd i en idealisk scen, tillämpa denna funktion, \n" +" och återladda sedan sparpunkten.\n" "\n" -"\n" -"Varning: Denna tillämpning kan möjliggöras dynamiskt men kan vanligtvis inte " -"förhindras på samma vis (video blir ofta skräp)." +"Varning: Denna tillämpning kan möjliggöras dynamiskt \n" +" men kan vanligtvis inte förhindras på samma vis (video blir ofta skräp)." #: pcsx2/vtlb.cpp:710 msgid "!Notice:HostVmReserve" msgstr "" -"Ert system har för lite VM-resurser för att PCSX2 ska kunna köras. \n" +"Ert system har för lite virtuella resurser för att PCSX2 ska kunna köras. \n" "Detta kan ha orsakats av att ha en liten eller förhindrad bytfil, \n" -"eller av att andra program tar för sig av resurser." +" eller av att andra program tar för sig av systemets resurser." #: pcsx2/x86/sVU_zerorec.cpp:363 msgid "!Notice:superVU:VirtualMemoryAlloc" msgstr "" "Slut på Minne (typ): superVU-omkompileraren var oförmögen att reservera den " -"mängd specifika minne som krävs, \n" -"och kommer inte vara tillgängligt för bruk. Detta är inte ett kritiskt fel, " -"eftersom sVU är föråldrad, \n" -"och följdaktligen borde Ni använda Er av microVU istället." +"mängd särskilda minne \n" +" som krävs, och kommer inte vara tillgänglig för bruk. Detta är inte ett " +"kritiskt fel eftersom \n" +" sVU är föråldrad, och följdaktligen borde Ni hur som helst använda Er av " +"microVU istället." #~ msgid "!ContextTip:Speedhacks:vuBlockHack" #~ msgstr "" -#~ "Förmodar att väldigt långt in i framtiden så kommer block inte behöva " -#~ "gammelflagg-instansdata. \n" -#~ "Detta borde vara rätt säkert. Det är okänt ifall detta har sönder något " -#~ "spel..." +#~ "Förmodar att väldigt långt in i framtiden så \n" +#~ " kommer block inte behöva gammelflagg-instansdata. \n" +#~ "Det borde vara rätt säkert. \n" +#~ "Det är okänt ifall detta har sönder något spel..." #~ msgid "!Notice:Mcd:Overwrite" #~ msgstr "" diff --git a/locales/sv_SE/pcsx2_Main.po b/locales/sv_SE/pcsx2_Main.po index 7744ba3f2..dae853071 100644 --- a/locales/sv_SE/pcsx2_Main.po +++ b/locales/sv_SE/pcsx2_Main.po @@ -4,8 +4,8 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2012-02-28 12:20+0100\n" -"PO-Revision-Date: 2011-11-16 12:28+0100\n" +"POT-Creation-Date: 2012-02-28 13:06+0100\n" +"PO-Revision-Date: 2012-02-28 12:54+0100\n" "Last-Translator: Georg Ronnert \n" "Language-Team: \n" "Language: \n" @@ -30,7 +30,7 @@ msgstr "Tolkningsfel" #: common/include/Utilities/Exceptions.h:250 msgid "Your machine's hardware is incapable of running PCSX2. Sorry dood." -msgstr "Er maskinhårdvara är oförmögen att köra PCSX2. Beklagar snubben." +msgstr "Er maskinhårdvara är oförmögen att köra PCSX2. Beklagar snubben." #: common/src/Utilities/Exceptions.cpp:219 msgid "Oh noes! Out of memory!" @@ -75,25 +75,25 @@ msgid "" "Unexpected end of file or stream encountered. File is probably truncated or " "corrupted." msgstr "" -"Oväntat slut på fil eller ström påträffat. Filen är troligen stympt eller " +"Oväntat slut på fil eller flöde påträffat. Filen är troligen stympt eller " "förstörd." #: common/src/Utilities/ThreadTools.cpp:41 msgid "Threading activity: start, detach, sync, deletion, etc." -msgstr "Trådaktivitet: start, avskiljning, sync, borttagning, etc." +msgstr "Trådaktivitet: start, avskiljning, synkning, borttagning, etc." #: common/src/Utilities/ThreadingDialogs.cpp:30 msgid "Waiting for tasks..." -msgstr "Väntar på uppgifter..." +msgstr "Väntar på uppgifter ..." #: common/src/Utilities/ThreadingDialogs.cpp:41 msgid "Waiting for task..." -msgstr "Väntar på uppgift..." +msgstr "Väntar på uppgift ..." #: common/src/Utilities/wxAppWithHelpers.cpp:36 msgid "Includes idle event processing and some other uncommon event usages." msgstr "" -"Inkluderar tomgångshändelsebearbetning och några andra ovanliga " +"Innefattar tomgångshändelsebearbetning och några andra ovanliga " "händelseanvändningar." #: pcsx2/CDVD/IsoFileFormats.cpp:416 @@ -102,15 +102,16 @@ msgstr "Oerkänt ISO-filformat" #: pcsx2/Elfheader.cpp:266 msgid "Cannot load ELF binary image. The file may be corrupt or incomplete." -msgstr "Kan inte ladda ELF binär. Filen kan vara förstörd eller ofullständig." +msgstr "" +"Kan inte ladda ELF-binären. Filen kan vara förstörd eller ofullständig." #: pcsx2/Elfheader.cpp:268 msgid "" "If loading from an ISO image, this error may be caused by an unsupported ISO " "image type or a bug in PCSX2 ISO image support." msgstr "" -"Om försök att ladda en ISO har gjorts, kan detta fel ha orsakats av en " -"ostödjande ISO-typ, eller av ett fel i PCSX2's ISO-stöd." +"Om försök att ladda genom en ISO-avbild har gjorts, kan detta fel ha " +"orsakats av en ostödjandes ISO-typ, eller av ett fel i PCSX2's ISO-stöd." #: pcsx2/MTGS.cpp:859 msgid "" @@ -132,7 +133,7 @@ msgid "" "%s plugin failed to open. Your computer may have insufficient resources, or " "incompatible hardware/drivers." msgstr "" -"%s insticksprogram misslyckades att öppna. Er dator kan ha otillräckliga " +"%s's insticksprogram misslyckades att öppna. Er dator kan ha otillräckliga " "resurser, eller oförenlig hårdvara/drivrutiner." #: pcsx2/PluginManager.cpp:726 @@ -141,7 +142,7 @@ msgid "" "%s plugin failed to initialize. Your system may have insufficient memory or " "resources needed." msgstr "" -"%s insticksprogram misslyckades att initialiseras. Ert system kan ha " +"%s's insticksprogram misslyckades att initialiseras. Ert system kan ha " "otillräckligt med minne eller andra erfordeliga resurser." #: pcsx2/PluginManager.cpp:832 @@ -161,7 +162,7 @@ msgid "" "unsupported version of PCSX2." msgstr "" "Det konfigurerade %s-insticksprogrammet är inte ett PCSX2-insticksprogram, " -"eller är för en äldre version av PCSX2 och stödjes inte här." +"eller är för en äldre ostödjandes version av PCSX2." #: pcsx2/PluginManager.cpp:879 msgid "" @@ -176,7 +177,7 @@ msgid "" "version of PCSX2." msgstr "" "Det konfigurerade insticksprogrammet är inte ett PCSX2-insticksprogram, " -"eller för en äldre version av PCSX2 och stödjes inte här." +"eller för en äldre ostödjandes version av PCSX2." #: pcsx2/PluginManager.cpp:926 #, c-format @@ -184,46 +185,47 @@ msgid "" "Configured %s plugin is not a valid PCSX2 plugin, or is for an older " "unsupported version of PCSX2." msgstr "" -"Det konfigurerade %s insticksprogrammet är inte ett giltligt PCSX2-" -"insticksprogram, eller för en äldre version av PCSX2 och stödjes inte här." +"Det konfigurerade %s-insticksprogrammet är inte ett giltligt PCSX2-" +"insticksprogram, eller för en äldre ostödjandes version av PCSX2." #: pcsx2/PluginManager.cpp:1355 msgid "Internal Memorycard Plugin failed to initialize." msgstr "" -"Det interna minneskorts-insticksprogrammet misslyckades att initialiseras." +"Det inhemska MinneskortsInsticksprogrammet misslyckades att initialiseras." #: pcsx2/PluginManager.cpp:1752 msgid "Unloaded Plugin" -msgstr "Oladdat insticksprogram" +msgstr "Oladdat Insticksprogram" #: pcsx2/SaveState.cpp:342 msgid "Cannot load savestate. It is of an unknown or unsupported version." msgstr "" -"Kan inte ladda sparpunkten. Den är av en okänd eller ostödjande version." +"Kan inte ladda sparpunkten eftersom den är av en okänd eller ostödjandes " +"version." #: pcsx2/SourceLog.cpp:96 msgid "Dumps detailed information for PS2 executables (ELFs)." -msgstr "Dumpar detaljerad information om PS2-verkställare (ELFar)." +msgstr "Dumpar detaljerad information om PS2-verkställare (ELF'ar)." #: pcsx2/SourceLog.cpp:101 msgid "" "Logs manual protection, split blocks, and other things that might impact " "performance." msgstr "" -"Loggar manuellt skydd, delar block, och annat som kan vara av betydelse för " +"Loggar manuellt skydd, delade block, och annat som kan vara av betydelse för " "prestanda." #: pcsx2/SourceLog.cpp:106 msgid "Shows the game developer's logging text (EE processor)" -msgstr "Visar spelutvecklarens loggningstext (EE processor)" +msgstr "Visar spelutvecklarens loggningstext (EE-processor)" #: pcsx2/SourceLog.cpp:111 msgid "Shows the game developer's logging text (IOP processor)" -msgstr "Visar spelutvecklarens loggningstext (IOP processor)" +msgstr "Visar spelutvecklarens loggningstext (IOP-processor)" #: pcsx2/SourceLog.cpp:116 msgid "Shows DECI2 debugging logs (EE processor)" -msgstr "Visar DECI2 felsökningsloggar (EE processor)" +msgstr "Visar DECI2-felsökningsloggar (EE-processor)" #: pcsx2/SourceLog.cpp:145 msgid "SYSCALL and DECI2 activity." @@ -231,16 +233,16 @@ msgstr "SYSCALL och DECI2 aktivitet." #: pcsx2/SourceLog.cpp:151 msgid "Direct memory accesses to unknown or unmapped EE memory space." -msgstr "Direkt minnestillgång till okänt eller ofördelat EE minne." +msgstr "Direkt minnestillgång till okänt eller ofördelat EE-minnesrum." #: pcsx2/SourceLog.cpp:157 pcsx2/SourceLog.cpp:276 msgid "Disasm of executing core instructions (excluding COPs and CACHE)." msgstr "" -"Avassembering av verkställande kärninstruktioner (exklusive COPar och CACHE)." +"Avassembering av verkställande kärninstruktioner (förutom COP'ar och CACHE)." #: pcsx2/SourceLog.cpp:163 msgid "Disasm of COP0 instructions (MMU, cpu and dma status, etc)." -msgstr "Avassemblering av COP0 instruktioner (MMU, CPU och DMA status etc)." +msgstr "Avassemblering av COP0-instruktioner (MMU, CPU och DMA status etc)." #: pcsx2/SourceLog.cpp:169 msgid "Disasm of the EE's floating point unit (FPU) only." @@ -248,18 +250,18 @@ msgstr "Endast avassemblering av EE's flyttalsenhet (FPU)." #: pcsx2/SourceLog.cpp:175 msgid "Disasm of the EE's VU0macro co-processor instructions." -msgstr "Avassemblering av EE's VU0macro hjälpprocessorinstruktioner." +msgstr "Avassemblering av EE's VU0-macrohjälpprocessorinstruktioner." #: pcsx2/SourceLog.cpp:181 msgid "Execution of EE cache instructions." -msgstr "Verkställande av EE cacheinstruktioner." +msgstr "Verkställande av EE-förrådsinstruktioner." #: pcsx2/SourceLog.cpp:187 msgid "" "All known hardware register accesses (very slow!); not including sub filter " "options below." msgstr "" -"Alla kända hårdvaruregister ges åtkomst (mycket långsamt!); ej inräknat " +"Alla kända hårdvaruregisteråtkomster (mycket långsamt!); förutom " "underfilterstillämpningarna nedanför." #: pcsx2/SourceLog.cpp:193 pcsx2/SourceLog.cpp:294 @@ -277,7 +279,7 @@ msgstr "" #: pcsx2/SourceLog.cpp:211 msgid "All GIFtag parse activity; path index, tag type, etc." -msgstr "All slags GIF-märkesaktivitetstolkningar; sökvägsindex, märktyp, etc." +msgstr "All slags GIF-märkestolkningssaktiviteter; sökvägsindex, märktyp, etc." #: pcsx2/SourceLog.cpp:217 msgid "All VIFcode processing; command, tag style, interrupts." @@ -285,11 +287,11 @@ msgstr "All slags VIF-kodsbearbetning; betingande, märkstil, avbrott." #: pcsx2/SourceLog.cpp:223 msgid "All processing involved in Path3 Masking" -msgstr "All bearbetning inblandat i Path3 Maskning." +msgstr "All bearbetning inblandat i Path3-Maskning." #: pcsx2/SourceLog.cpp:229 msgid "Scratchpad's MFIFO activity." -msgstr "Antekningshäftets MFIFO aktivitet." +msgstr "Antekningshäftets MFIFO-aktivitet." #: pcsx2/SourceLog.cpp:235 msgid "Actual data transfer logs, bus right arbitration, stalls, etc." @@ -297,7 +299,7 @@ msgstr "Faktiska dataöverföringsloggar, rätt buss medling, uppehåll, etc." #: pcsx2/SourceLog.cpp:241 msgid "Tracks all EE counters events and some counter register activity." -msgstr "Spårar all EE räknarbegivenhet och en del registerräknaraktivitet." +msgstr "Spårar alla EE-räknarföreteelser och en del registerräknaraktivitet." #: pcsx2/SourceLog.cpp:247 msgid "Dumps various VIF and VIFcode processing data." @@ -305,7 +307,7 @@ msgstr "Dumpar diverse VIF och VIF-kod bearbetningsdata." #: pcsx2/SourceLog.cpp:253 msgid "Dumps various GIF and GIFtag parsing data." -msgstr "Dumpar diverse GIF och GIF-märkt tolkningsdata." +msgstr "Dumpar diverse GIF och GIF-märkes tolkningsdata." #: pcsx2/SourceLog.cpp:264 msgid "SYSCALL and IRX activity." @@ -313,7 +315,7 @@ msgstr "SYSCALL och IRX aktivitet." #: pcsx2/SourceLog.cpp:270 msgid "Direct memory accesses to unknown or unmapped IOP memory space." -msgstr "Direkt minnestillgång till okänd eller ofördelat IOP minne." +msgstr "Direkt minnestillgång till okänd eller ofördelat IOP-minne." #: pcsx2/SourceLog.cpp:282 msgid "Disasm of the IOP's GPU co-processor instructions." @@ -322,13 +324,12 @@ msgstr "Avassemblering av IOP's GPU-hjälpprocessorinstruktioner." #: pcsx2/SourceLog.cpp:288 msgid "" "All known hardware register accesses, not including the sub-filters below." -msgstr "" -"Alla kända hårdvaruregister ges tillgång, ej inräknat underfilterna nedanför." +msgstr "Alla kända hårdvaruregisteråtkomster, förutom underfilterna nedanför." #: pcsx2/SourceLog.cpp:306 msgid "Memorycard reads, writes, erases, terminators, and other processing." msgstr "" -"Minneskorts läs-, skriv-, raderings-, avslutar-, och andra, bearbetningar." +"Minneskorts läs-, skriv-, kasserings-, avslutar-, och andra - bearbetningar." #: pcsx2/SourceLog.cpp:312 msgid "Gamepad activity on the SIO." @@ -336,16 +337,16 @@ msgstr "Spelplattsaktivitet hos SIO." #: pcsx2/SourceLog.cpp:318 msgid "Actual DMA event processing and data transfer logs." -msgstr "Faktisk DMA begivenhetsbearbetning och dataöverföringsloggar." +msgstr "Faktisk DMA-företeelsebearbetning och dataöverföringsloggar." #: pcsx2/SourceLog.cpp:324 msgid "Tracks all IOP counters events and some counter register activity." msgstr "" -"Spårar alla IOP räknares begivenheter och några räknarregisters aktiviteter." +"Spårar alla IOP-räknarföreteelser och några räknarregisters aktiviteter." #: pcsx2/SourceLog.cpp:330 msgid "Detailed logging of CDVD hardware." -msgstr "Detaljerad loggning av CDVD hårdvara." +msgstr "Detaljerad loggning av CDVD-hårdvara." #: pcsx2/System.h:206 pcsx2/System.h:207 pcsx2/System.h:208 msgid "PCSX2 Message" @@ -365,7 +366,7 @@ msgstr "Säkrast" #: pcsx2/gui/AppConfig.cpp:843 msgid "Safe (faster)" -msgstr "Säkert (snabare)" +msgstr "Säkert (snabbare)" #: pcsx2/gui/AppConfig.cpp:844 msgid "Balanced" @@ -390,18 +391,18 @@ msgstr "" #: pcsx2/gui/AppCorePlugins.cpp:404 msgid "Loading PS2 system plugins..." -msgstr "Laddar PS2-systeminsticksprogram..." +msgstr "Laddar PS2-systeminsticksprogram ..." #: pcsx2/gui/AppInit.cpp:41 msgid "PCSX2 - SSE2 Recommended" -msgstr "PCSX2 - SSE2 Rekommenderas" +msgstr "PCSX2 - SSE2 Anrådes" #: pcsx2/gui/AppInit.cpp:71 msgid "" "SSE extensions are not available. PCSX2 requires a cpu that supports the " "SSE instruction set." msgstr "" -"SSE utvidgningar är ej tillgängliga. PCSX2 kräver en CPU som stödjer " +"SSE förlängningar ej tillgängliga. PCSX2 kräver en CPU som stödjer " "instruktionsuppsättningen SSE." #: pcsx2/gui/AppInit.cpp:154 @@ -412,7 +413,7 @@ msgstr "PCSX2 OmkompilerarFel" msgid "All options are for the current session only and will not be saved.\n" msgstr "" "Alla valmöjligheter gäller endast för den nuvarande sessionen och kommer " -"inte att sparas.\n" +"inte att sparas. \n" #: pcsx2/gui/AppInit.cpp:237 pcsx2/gui/AppMain.cpp:299 msgid "IsoFile" @@ -428,27 +429,27 @@ msgstr "tvingar programmets logg/konsol att uppenbara sig" #: pcsx2/gui/AppInit.cpp:240 msgid "use fullscreen GS mode" -msgstr "använd helskärms GS läge" +msgstr "använd helskärms GS-läge" #: pcsx2/gui/AppInit.cpp:241 msgid "use windowed GS mode" -msgstr "använd inramat GS läge" +msgstr "använd inramat GS-läge" #: pcsx2/gui/AppInit.cpp:243 msgid "disables display of the gui while running games" -msgstr "förhindrar uppvisning av GUI medans spel köres" +msgstr "förhindrar uppvisning av GUI medans spel körs" #: pcsx2/gui/AppInit.cpp:244 msgid "executes an ELF image" -msgstr "verkställer en ELF avbild" +msgstr "verkställer en ELF-avbild" #: pcsx2/gui/AppInit.cpp:245 msgid "boots an empty dvd tray; use to enter the PS2 system menu" -msgstr "kör en tom DVD tråg; använd för att åtkomma PS2's systemmeny" +msgstr "kör en tom DVD-tråg; använd för att åtkomma PS2's systemmeny" #: pcsx2/gui/AppInit.cpp:246 msgid "boots from the CDVD plugin (overrides IsoFile parameter)" -msgstr "kör från CDVD-insticksprogrammet (upphäver ISO-fil parameter)" +msgstr "kör från CDVD-insticksprogrammet (åsidosätter ISO-fil parameter)" #: pcsx2/gui/AppInit.cpp:248 msgid "disables all speedhacks" @@ -473,7 +474,7 @@ msgstr "anger PCSX2-konfigurationsfilen att använda" #: pcsx2/gui/AppInit.cpp:254 #, c-format msgid "forces %s to start the First-time Wizard" -msgstr "tvingar %s att köra Första-gången Trollkarlen" +msgstr "tvingar %s att köra ''Första gången Trollkarlen''" #: pcsx2/gui/AppInit.cpp:255 msgid "enables portable mode operation (requires admin/root access)" @@ -482,12 +483,12 @@ msgstr "möjliggör flyttbart-läge-procedur (kräver admin/rot behörighet)" #: pcsx2/gui/AppInit.cpp:259 #, c-format msgid "specify the file to use as the %s plugin" -msgstr "ange filen att använda som %s insticksprogram" +msgstr "ange filen att använda som %s's insticksprogram" #: pcsx2/gui/AppInit.cpp:307 #, c-format msgid "Plugin Override Error - %s" -msgstr "Insticks Upphävande Fel - %s" +msgstr "Insticks Åsidosättande Fel - %s" #: pcsx2/gui/AppInit.cpp:310 #, c-format @@ -496,16 +497,16 @@ msgid "" "valid %s plugin:\n" "\n" msgstr "" -"%s Insticks Upphävande Fel! Följande fil finns ej eller är icke ett giltligt " -"%s insticksprogram:\n" +"%s Insticks Åsidosättande Fel! Följande fil finns ej eller är icke ett " +"giltligt %s-insticksprogram: \n" "\n" #: pcsx2/gui/AppInit.cpp:317 #, c-format msgid "Press OK to use the default configured plugin, or Cancel to close %s." msgstr "" -"Tryck OK för att använda det förvaldskonfigurerade insticksprogrammet, eller " -"Avbryt för att stänga %s." +"Tryck ''Vidare'' för att använda det förvaldskonfigurerade " +"insticksprogrammet, eller ''Avbryt'' för att stänga %s." #: pcsx2/gui/AppInit.cpp:496 msgid "PCSX2 Error: Hardware Deficiency" @@ -514,7 +515,7 @@ msgstr "PCSX2 Fel: Hårdvarubristfällighet" #: pcsx2/gui/AppInit.cpp:496 pcsx2/gui/AppInit.cpp:508 #, c-format msgid "Press OK to close %s." -msgstr "Tryck OK för att stänga %s." +msgstr "Tryck ''Vidare'' för att stänga %s." #: pcsx2/gui/AppInit.cpp:509 #, c-format @@ -523,11 +524,11 @@ msgstr "%s Kritiskt Fel" #: pcsx2/gui/AppInit.cpp:679 msgid "OK" -msgstr "OK" +msgstr "Vidare" #: pcsx2/gui/AppInit.cpp:680 msgid "&OK" -msgstr "&OK" +msgstr "&Vidare" #: pcsx2/gui/AppInit.cpp:681 msgid "Cancel" @@ -575,7 +576,7 @@ msgstr "&Spara" #: pcsx2/gui/AppInit.cpp:692 msgid "Save &As..." -msgstr "Spara &Som" +msgstr "Spara &Som ..." #: pcsx2/gui/AppInit.cpp:693 msgid "&Help" @@ -587,7 +588,7 @@ msgstr "&Hem" #: pcsx2/gui/AppInit.cpp:696 msgid "Show about dialog" -msgstr "Visa om dialog" +msgstr "Info om PCSX2." #: pcsx2/gui/AppMain.cpp:87 msgid "" @@ -597,7 +598,7 @@ msgid "" msgstr "" "\n" "\n" -"Tryck OK för att gå till instickskonfigurationspanelen." +"Tryck ''Vidare'' för att gå till InsticksKonfigurationsPanelen." #: pcsx2/gui/AppMain.cpp:140 pcsx2/gui/AppMain.cpp:154 msgid "" @@ -612,11 +613,11 @@ msgstr "%s Instruktionsmöjligheter" #: pcsx2/gui/AppMain.cpp:573 msgid "PS2 BIOS Error" -msgstr "PS2-BIOS Fel" +msgstr "PS2 BIOS Fel" #: pcsx2/gui/AppMain.cpp:574 msgid "Press Ok to go to the BIOS Configuration Panel." -msgstr "Tryck OK för att gå till BIOS-konfigurationspanelen." +msgstr "Tryck ''Vidare'' för att gå till BIOS-KonfigurationsPanelen." #: pcsx2/gui/AppMain.cpp:626 msgid "PCSX2 Unresponsive Thread" @@ -628,19 +629,19 @@ msgstr "Avsluta" #: pcsx2/gui/AppMain.cpp:963 msgid "Executing PS2 Virtual Machine..." -msgstr "Verkställer PS2-VM..." +msgstr "Kör PS2's Virtuella Maskin ..." #: pcsx2/gui/AppRes.cpp:72 msgid "Browse for an Iso that is not in your recent history." -msgstr "Bläddra efter en ISO som inte är i Er lista." +msgstr "Bläddra efter en ISO som inte redan är i Er lista." #: pcsx2/gui/AppRes.cpp:72 msgid "Browse..." -msgstr "Bläddra..." +msgstr "Bläddra ..." #: pcsx2/gui/AppUserMode.cpp:99 msgid "The following folders exist, but are not writable:" -msgstr "Följande mappar finnes, men är inte skrivbara:" +msgstr "Följande mappar finns, men är inte skrivbara:" #: pcsx2/gui/AppUserMode.cpp:104 msgid "The following folders are missing and cannot be created:" @@ -661,7 +662,7 @@ msgstr "" #: pcsx2/gui/AppUserMode.cpp:165 msgid "Switch to User Documents Mode" -msgstr "Växla till Användardokumentsläge" +msgstr "Växla till AnvändarDokument-läge" #: pcsx2/gui/AppUserMode.cpp:178 #, c-format @@ -679,7 +680,8 @@ msgstr "" #: pcsx2/gui/ApplyState.h:55 msgid "Cannot apply new settings, one of the settings is invalid." msgstr "" -"Kan ej tillämpa de nya inställningarna; en av inställningarna är ogiltlig." +"Kan inte tillämpa de nya inställningarna eftersom minst en av dom är " +"ogiltlig." #: pcsx2/gui/ConsoleLogger.cpp:120 msgid "Save log question" @@ -691,7 +693,7 @@ msgstr "Klämmer in mycket loggning i en mikroskopiskt liten yta." #: pcsx2/gui/ConsoleLogger.cpp:413 msgid "Small" -msgstr "Liten" +msgstr "Litet" #: pcsx2/gui/ConsoleLogger.cpp:415 msgid "It's what I use (the programmer guy)." @@ -699,7 +701,7 @@ msgstr "Det är vad Jag (programmerarsnubben) använder." #: pcsx2/gui/ConsoleLogger.cpp:415 pcsx2/gui/Panels/CpuPanel.cpp:38 msgid "Normal" -msgstr "Normal" +msgstr "Normalt" #: pcsx2/gui/ConsoleLogger.cpp:417 msgid "Its nice and readable." @@ -707,11 +709,11 @@ msgstr "Det är fint och läsbart." #: pcsx2/gui/ConsoleLogger.cpp:417 msgid "Large" -msgstr "Stor" +msgstr "Stort" #: pcsx2/gui/ConsoleLogger.cpp:419 msgid "Huge" -msgstr "Enorm" +msgstr "Enormt" #: pcsx2/gui/ConsoleLogger.cpp:419 msgid "In case you have a really high res display." @@ -748,7 +750,7 @@ msgstr "När markerad kommer loggfönstret att bli synligt över andra fönster. #: pcsx2/gui/ConsoleLogger.cpp:430 msgid "&Save..." -msgstr "&Spara..." +msgstr "&Spara ..." #: pcsx2/gui/ConsoleLogger.cpp:430 msgid "Save log contents to file" @@ -756,11 +758,11 @@ msgstr "Spara logginnehåll till fil" #: pcsx2/gui/ConsoleLogger.cpp:431 msgid "C&lear" -msgstr "R&ensa" +msgstr "&Rensa" #: pcsx2/gui/ConsoleLogger.cpp:431 msgid "Clear the log window contents" -msgstr "Rensa Windowslogginnehåll" +msgstr "Rensa loggfönsterinnehållet" #: pcsx2/gui/ConsoleLogger.cpp:433 pcsx2/gui/Dialogs/SysConfigDialog.cpp:280 msgid "Appearance" @@ -776,15 +778,15 @@ msgstr "Stäng detta loggfönster; innehållet bevaras" #: pcsx2/gui/ConsoleLogger.cpp:439 msgid "Dev/Verbose" -msgstr "Moj/Ordrik" +msgstr "Utvecklarloggar" #: pcsx2/gui/ConsoleLogger.cpp:439 msgid "Shows PCSX2 developer logs" -msgstr "Visar PCSX2 utvecklarloggar" +msgstr "Visar PCSX2's utvecklarloggar" #: pcsx2/gui/ConsoleLogger.cpp:440 msgid "CDVD reads" -msgstr "CDVD läser" +msgstr "CDVD läsningar" #: pcsx2/gui/ConsoleLogger.cpp:440 msgid "Shows disk read activity" @@ -804,7 +806,7 @@ msgstr "Förhindra allt" #: pcsx2/gui/ConsoleLogger.cpp:458 msgid "Disables all log source filters." -msgstr "Förhindra alla loggkälsfilter." +msgstr "Förhindra alla loggkällsfilter." #: pcsx2/gui/ConsoleLogger.cpp:460 msgid "&Log" @@ -829,7 +831,7 @@ msgstr "Föregående versioner" #: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:55 msgid "Webmasters" -msgstr "Nätansvarig" +msgstr "Nätansvariga" #: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:66 msgid "Plugin Specialists" @@ -849,15 +851,15 @@ msgstr "Bidragare" #: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:98 msgid "A Playstation 2 Emulator" -msgstr "En Playstation 2 Emulator" +msgstr "En PlayStation®2 emulator" #: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:102 msgid "PCSX2 Official Website and Forums" -msgstr "PCSX2 Officiella Websida och Forum" +msgstr "PCSX2's officiella Websida och Forum" #: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:106 msgid "PCSX2 Official Svn Repository at Googlecode" -msgstr "PCSX2 Officiella SVN-magasin hos Googlecode" +msgstr "PCSX2's officiella SVN-magasin hos Googlecode" #: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:110 msgid "I've seen enough" @@ -873,7 +875,7 @@ msgstr "Sparar en snabbild av denna inställningspanel till en PNG-fil." #: pcsx2/gui/Dialogs/BaseConfigurationDialog.cpp:308 msgid "Save dialog screenshots to..." -msgstr "Spara dialogskärmsbilder i..." +msgstr "Spara dialogskärmsbilder i ..." #: pcsx2/gui/Dialogs/BiosSelectorDialog.cpp:31 msgid "BIOS Selector" @@ -896,8 +898,7 @@ msgid "" "The popup will not be shown again. This setting can be undone from the " "settings panels." msgstr "" -"Uppdykaren kommer att visas igen. Denna inställning kan ogöras i " -"inställningspanelen." +"Uppdykaren kommer inte visas igen. Detta kan ogöras i inställningspanelen." #: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:247 #: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:292 @@ -910,7 +911,7 @@ msgstr "Återställ" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:40 msgid "Create a new memory card" -msgstr "Skapa nytt minneskort" +msgstr "Skapa ett nytt minneskort" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:59 #: pcsx2/gui/Panels/DirPickerPanel.cpp:74 @@ -947,27 +948,27 @@ msgstr "Fel: Minneskortet kunde inte skapas." #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:177 msgid "Use NTFS compression when creating this card." -msgstr "Använd NTFS-komprimering för skapande att detta kort." +msgstr "Använd NTFS-komprimering vid skapande av detta kort." #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:195 msgid "8 MB [most compatible]" -msgstr "8 MB [mest förenlig]" +msgstr "8 MB [mest förenligt]" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:195 msgid "" "This is the standard Sony-provisioned size, and is supported by all games " "and BIOS versions." msgstr "" -"Detta är den standard-Sony-provianterade storleken, och stödjes av alla spel " -"och BIOS-versioner." +"Detta är den (av Sony) standardföreskrivna storleken \n" +" och stödjes av alla spel och BIOS-versioner." #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:196 msgid "" "Always use this option if you want the safest and surest memory card " "behavior." msgstr "" -"Använd alltid denna tillämpning om Ni vill ha det säkraste och " -"tillförlitligaste minneskortsbeteendet." +"Använd alltid denna tillämpning om Ni vill ha det \n" +" säkraste och tillförlitligaste minneskortsbeteendet." #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:199 msgid "16 MB" @@ -978,13 +979,13 @@ msgstr "16 MB" msgid "" "A typical size for 3rd-party memory cards which should work with most games." msgstr "" -"En typisk storlek för tredje-persons-minneskort som ska fungera med de " -"flesta spel." +"En typisk storlek för tredje-parts minneskort \n" +" som ska fungera med de flesta spel." #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:200 #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:204 msgid "16 and 32 MB cards have roughly the same compatibility factor." -msgstr "16 och 32 MB kort har ungefär samma förenlighetsfaktor." +msgstr "16 & 32 MB kort har ungefär samma förenlighetsfaktor." #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:203 msgid "32 MB" @@ -999,21 +1000,21 @@ msgid "" "Low compatibility warning: Yes it's very big, but may not work with many " "games." msgstr "" -"Låg förenlighetsvarning: Jo den är väldigt stor, men kan måhända inte " -"fungera för många spel." +"Låg förenlighetsvarning: Jo den är väldigt stor, \n" +" men fungerar måhända inte för många spel." #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:208 msgid "" "Use at your own risk. Erratic memory card behavior is possible (though " "unlikely)." msgstr "" -"Använd på egen risk. Oberäkneliga minneskortsbeteenden är möjliga (dock " -"osannolika)." +"Används på egen risk. Oberäkneliga minneskortsbeteenden \n" +" är möjliga (dock osannolika)." #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:47 #, c-format msgid "Select a folder for %s settings" -msgstr "Välj en mapp för %s inställningar" +msgstr "Välj en mapp för %s-inställningar" #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:47 msgid "Settings" @@ -1037,16 +1038,16 @@ msgstr "Välkommen till PCSX2!" #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:104 msgid "Configuration Guides (online)" -msgstr "Konfigurationsguider (uppkopplat)" +msgstr "KonfigurationsVägledningen (uppkopplat)" #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:108 msgid "Readme / FAQ (Offline/PDF)" -msgstr "Läs mig / FAQ (Urkopplat/PDF)" +msgstr "Läs mig / FAQ (urkopplat/PDF)" #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:117 #, c-format msgid "%s First Time Configuration" -msgstr "%s Första-gången Konfiguration" +msgstr "%s's Första gången Konfiguration" #: pcsx2/gui/Dialogs/GameDatabaseDialog.cpp:24 #, c-format @@ -1055,7 +1056,7 @@ msgstr "Speldatabas - %s" #: pcsx2/gui/Dialogs/ImportSettingsDialog.cpp:24 msgid "Import Existing Settings?" -msgstr "Importera Befintliga Inställningar?" +msgstr "Importera befintliga inställningar?" #: pcsx2/gui/Dialogs/ImportSettingsDialog.cpp:39 msgid "Import" @@ -1071,11 +1072,11 @@ msgstr "Spåra Loggning" #: pcsx2/gui/Dialogs/McdConfigDialog.cpp:40 msgid "Auto-eject memory cards when loading savestates" -msgstr "Auto-utmata minneskort när sparpunkter laddas" +msgstr "Utmata automatiskt minneskort när sparpunkter laddas" #: pcsx2/gui/Dialogs/McdConfigDialog.cpp:96 msgid "MemoryCard Manager" -msgstr "MinnesKorts Hanterare" +msgstr "Minneskorts Hanterare" #: pcsx2/gui/Dialogs/McdConfigDialog.cpp:112 msgid "Drag cards to or from PS2-ports" @@ -1087,12 +1088,12 @@ msgid "" "Note: Duplicate/Rename/Create/Delete will NOT be reverted with 'Cancel'." msgstr "" "\n" -"Bemärk: Dubblera/Byt namn/Skapa/Ta bort, kommer INTE att återgå om Ni " -"trycker 'Avbryt'." +"Bemärk: ''Dubblera''/''Namnbyt''/''Skapa''/''Kassera'' kommer INTE att " +"återgå genom ''Avbryt''." #: pcsx2/gui/Dialogs/PickUserModeDialog.cpp:24 msgid "PCSX2 First Time configuration" -msgstr "PCSX2 Första Gången konfiguration" +msgstr "PCSX2 Första gången Konfiguration" #: pcsx2/gui/Dialogs/PickUserModeDialog.cpp:29 #, c-format @@ -1105,11 +1106,11 @@ msgstr "PCSX2 Tråd är osvarandes" #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:36 msgid "Config Overrides Warning" -msgstr "Konfig Överskrider Varning" +msgstr "KonfigÅsidosättningVarning" #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:56 msgid "Components Overrides Warning" -msgstr "Komponent Överskrider Varning" +msgstr "KomponentÅsidosättningsVarning" #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:147 msgid "Preset:" @@ -1126,7 +1127,7 @@ msgstr "EE/IOP" #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:238 msgid "VUs" -msgstr "VUs" +msgstr "VU'ar" #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:239 msgid "GS" @@ -1168,16 +1169,16 @@ msgstr "Framträdande/Teman - %s" #: pcsx2/gui/ExecutorThread.cpp:40 msgid "Logs events as they are passed to the PS2 virtual machine." -msgstr "Loggar händelser medans de skickas till PS2-VM." +msgstr "Loggar händelser medans de skickas till PS2's Virtuella Maskin." #: pcsx2/gui/ExecutorThread.cpp:430 msgid "Press Cancel to attempt to cancel the action." -msgstr "Tryck Avbryt för att försöka avbryta verkan." +msgstr "Tryck ''Avbryt'' för att försöka avbryta verkan." #: pcsx2/gui/ExecutorThread.cpp:431 #, c-format msgid "Press Terminate to kill %s immediately." -msgstr "Tryck Avsluta för att avsluta %s omedelebart." +msgstr "Tryck ''Avsluta'' för att avsluta %s omedelebart." #: pcsx2/gui/ExecutorThread.cpp:434 msgid "Terminate App" @@ -1185,7 +1186,7 @@ msgstr "Avsluta tillämpning" #: pcsx2/gui/FrameForGS.cpp:384 msgid "GS Output is Disabled!" -msgstr "GS Utsignal är Förhindrad!" +msgstr "GS' Utsignal är Förhindrad!" #: pcsx2/gui/GlobalCommands.cpp:387 pcsx2/gui/MainFrame.cpp:414 msgid "Save state" @@ -1193,7 +1194,7 @@ msgstr "Spara tillstånd" #: pcsx2/gui/GlobalCommands.cpp:388 msgid "Saves the virtual machine state to the current slot." -msgstr "Sparar VM-tillståndet till den nuvarande sockeln." +msgstr "Sparar det Virtuella Maskin tillståndet till den nuvarande sockeln." #: pcsx2/gui/GlobalCommands.cpp:393 pcsx2/gui/MainFrame.cpp:413 msgid "Load state" @@ -1201,7 +1202,7 @@ msgstr "Ladda tillstånd" #: pcsx2/gui/GlobalCommands.cpp:394 msgid "Loads a virtual machine state from the current slot." -msgstr "Laddar VM tillståndet från den nuvarande sockeln." +msgstr "Laddar det Virtuella Maskin tillståndet från den nuvarande sockeln." #: pcsx2/gui/GlobalCommands.cpp:399 msgid "Load State Backup" @@ -1209,7 +1210,8 @@ msgstr "Ladda Tillståndskopia" #: pcsx2/gui/GlobalCommands.cpp:400 msgid "Loads virtual machine state backup for current slot." -msgstr "Laddar VM tillståndskopian för den nuvarande sockeln." +msgstr "" +"Laddar kopian för det Virtuella Maskin tillståndet för den nuvarande sockeln." #: pcsx2/gui/GlobalCommands.cpp:405 msgid "Cycle to next slot" @@ -1237,7 +1239,7 @@ msgid "" "It is an error to drop multiple files onto a %s window. One at a time " "please, thank you." msgstr "" -"Det är felaktigt att släppa flera filer på ett %s fönster. En i taget, tack." +"Det är felaktigt att släppa flera filer på ett %s-fönster. En i taget, tack." #: pcsx2/gui/IsoDropTarget.cpp:89 pcsx2/gui/MainMenuClicks.cpp:342 msgid "Confirm PS2 Reset" @@ -1249,13 +1251,13 @@ msgid "" "You have dropped the following ELF binary into %s:\n" "\n" msgstr "" -"Ni har släppt följande ELF-binär i %s:\n" +"Ni har släppt följande ELF-binär i %s: \n" "\n" #: pcsx2/gui/IsoDropTarget.cpp:135 #, c-format msgid "You have dropped the following ISO image into %s:" -msgstr "Ni har släppt följande ISO-bild i %s:" +msgstr "Ni har släppt följande ISO-avbild i %s:" #: pcsx2/gui/MainFrame.cpp:38 #, c-format @@ -1264,7 +1266,7 @@ msgstr "Sockel %d" #: pcsx2/gui/MainFrame.cpp:44 pcsx2/gui/Saveslots.cpp:150 msgid "Backup" -msgstr "&Säkerhetskopiera" +msgstr "Säkerhetskopiera" #: pcsx2/gui/MainFrame.cpp:324 msgid "Show Console" @@ -1280,7 +1282,7 @@ msgstr "&System" #: pcsx2/gui/MainFrame.cpp:339 msgid "CD&VD" -msgstr "CD&VD" +msgstr "&CDVD" #: pcsx2/gui/MainFrame.cpp:340 msgid "&Config" @@ -1311,15 +1313,15 @@ msgstr "(modifierade)" #: pcsx2/gui/MainFrame.cpp:399 pcsx2/gui/MainFrame.cpp:401 #: pcsx2/gui/MainFrame.cpp:407 msgid "Initializing..." -msgstr "Initialisering..." +msgstr "Initialisering ..." #: pcsx2/gui/MainFrame.cpp:403 msgid "Run ELF..." -msgstr "Kör ELF..." +msgstr "Kör ELF ..." #: pcsx2/gui/MainFrame.cpp:404 msgid "For running raw PS2 binaries directly" -msgstr "För att köra råa PS2-binärer direkt" +msgstr "För att direktköra råa PS2-binärer." #: pcsx2/gui/MainFrame.cpp:416 msgid "Backup before save" @@ -1333,7 +1335,7 @@ msgstr "Automatiska Spelfixar" msgid "Automatically applies needed Gamefixes to known problematic games" msgstr "" "Tillämpar automatiskt erfordeliga Spelfixar för till vetskap problematiska " -"spel" +"spel." #: pcsx2/gui/MainFrame.cpp:424 msgid "Enable Cheats" @@ -1349,16 +1351,16 @@ msgstr "Nedstängning" #: pcsx2/gui/MainFrame.cpp:433 msgid "Wipes all internal VM states and shuts down plugins." -msgstr "Rensar alla interna VM tillstånd och stänger ner insticksprogram." +msgstr "Rensar alla inhemska VM-tillstånd och stänger ner insticksprogram." #: pcsx2/gui/MainFrame.cpp:435 msgid "Exit" -msgstr "Utgå" +msgstr "Avsluta" #: pcsx2/gui/MainFrame.cpp:436 #, c-format msgid "Closing %s may be hazardous to your health" -msgstr "Att stänga %s kan vara skadligt för Er hälsa" +msgstr "Att stänga ner %s kan vara riskfyllt för Eder hälsa." #: pcsx2/gui/MainFrame.cpp:443 msgid "Iso Selector" @@ -1374,7 +1376,7 @@ msgstr "ISO" #: pcsx2/gui/MainFrame.cpp:447 msgid "Makes the specified ISO image the CDVD source." -msgstr "Gör den angivna ISO-bilden till CDVD-källa." +msgstr "Gör den ovan angivna ISO-avbilden till CDVD-källa." #: pcsx2/gui/MainFrame.cpp:448 msgid "Plugin" @@ -1382,11 +1384,11 @@ msgstr "Insticksprogram" #: pcsx2/gui/MainFrame.cpp:448 msgid "Uses an external plugin as the CDVD source." -msgstr "Använder ett externt insticksprogram som CDVD källa." +msgstr "Använder ett utomstående insticksprogram som CDVD-källa." #: pcsx2/gui/MainFrame.cpp:449 msgid "No disc" -msgstr "Ingen disk" +msgstr "Disklös" #: pcsx2/gui/MainFrame.cpp:449 msgid "Use this to boot into your virtual PS2's BIOS configuration." @@ -1414,7 +1416,7 @@ msgstr "&Video (GS)" #: pcsx2/gui/MainFrame.cpp:467 msgid "&Audio (SPU2)" -msgstr "&Audio (SPU2)" +msgstr "&Ljud (SPU2)" #: pcsx2/gui/MainFrame.cpp:468 msgid "&Controllers (PAD)" @@ -1442,36 +1444,36 @@ msgstr "Flerplugg 2" #: pcsx2/gui/MainFrame.cpp:481 msgid "Clear all settings..." -msgstr "Rensa alla inställningar..." +msgstr "Rensa alla inställningar ..." #: pcsx2/gui/MainFrame.cpp:482 #, c-format msgid "Clears all %s settings and re-runs the startup wizard." -msgstr "Rensa alla %s inställningar och återkör start-trollkarlen." +msgstr "Rensa alla %s-inställningar och återkör ''Första gången Trollkarlen''." #: pcsx2/gui/MainFrame.cpp:504 msgid "About..." -msgstr "Om..." +msgstr "Om ..." #: pcsx2/gui/MainFrame.cpp:508 msgid "Logging..." -msgstr "Loggning..." +msgstr "Loggning ..." #: pcsx2/gui/MainFrame.cpp:585 msgid "Pause" -msgstr "Pause" +msgstr "Pausa" #: pcsx2/gui/MainFrame.cpp:586 msgid "Safely pauses emulation and preserves the PS2 state." -msgstr "Pausar säkert emulering och bevarar PS2-tillståndet." +msgstr "Säker pausning av emulering som bevarar PS2-tillståndet." #: pcsx2/gui/MainFrame.cpp:593 msgid "Resume" -msgstr "Fortsätt" +msgstr "Återuppta" #: pcsx2/gui/MainFrame.cpp:594 msgid "Resumes the suspended emulation state." -msgstr "Återupptar det inställda emuleringstillståndet." +msgstr "Återupptar det pausade emuleringstillståndet." #: pcsx2/gui/MainFrame.cpp:598 msgid "Pause/Resume" @@ -1479,8 +1481,7 @@ msgstr "Pausa/Återuppta" #: pcsx2/gui/MainFrame.cpp:599 msgid "No emulation state is active; cannot suspend or resume." -msgstr "" -"Inget emuleringstillstånd är aktivt; kan inte inställa eller återuppta." +msgstr "Inget emuleringstillstånd är aktivt; kan inte Pausa eller Återuppta." #: pcsx2/gui/MainFrame.cpp:608 msgid "Restart" @@ -1488,7 +1489,7 @@ msgstr "Omstart" #: pcsx2/gui/MainFrame.cpp:609 msgid "Simulates hardware reset of the PS2 virtual machine." -msgstr "Simulerar hårdvaruåterställningen hos PS2-VM." +msgstr "Simulerar hårdvaruåterställningen för PS2's Virtuella Maskin." #: pcsx2/gui/MainFrame.cpp:614 msgid "No emulation state is active; boot something first." @@ -1500,7 +1501,7 @@ msgstr "Återkör CDVD (fullt)" #: pcsx2/gui/MainFrame.cpp:623 msgid "Hard reset of the active VM." -msgstr "Hård återställning av den aktiva VM." +msgstr "Hård återställning av den aktiva VM'n." #: pcsx2/gui/MainFrame.cpp:627 msgid "Boot CDVD (full)" @@ -1508,7 +1509,7 @@ msgstr "Kör CDVD (fullt)" #: pcsx2/gui/MainFrame.cpp:628 msgid "Boot the VM using the current DVD or Iso source media" -msgstr "Kör VM med nuvarande DVD/ISO mediumet som källa" +msgstr "Kör VM'n med det nuvarande DVD/ISO mediumet som källa." #: pcsx2/gui/MainFrame.cpp:636 msgid "Reboot CDVD (fast)" @@ -1516,7 +1517,7 @@ msgstr "Återkör CDVD (snabbt)" #: pcsx2/gui/MainFrame.cpp:637 msgid "Reboot using fast BOOT (skips splash screens)" -msgstr "Återkör med snabb BOOT (hoppar över plaskskärmar)" +msgstr "Återkör med snabbuppkörning (hoppar över plaskskärmar)" #: pcsx2/gui/MainFrame.cpp:641 msgid "Boot CDVD (fast)" @@ -1524,7 +1525,8 @@ msgstr "Kör CDVD (snabbt)" #: pcsx2/gui/MainFrame.cpp:642 msgid "Use fast boot to skip PS2 startup and splash screens" -msgstr "Använd snabb boot för att hoppa över PS2-uppstart och plaskskärmar" +msgstr "" +"Använd snabbuppkörning för att hoppa över PS2-uppstart och plaskskärmar." #: pcsx2/gui/MainFrame.cpp:703 pcsx2/gui/MainFrame.cpp:738 msgid "No plugin loaded" @@ -1532,43 +1534,45 @@ msgstr "Inget insticksprogram laddat" #: pcsx2/gui/MainFrame.cpp:708 msgid "Core GS Settings..." -msgstr "Kärn GS Inställningar..." +msgstr "Kärn-GS Inställningar ..." #: pcsx2/gui/MainFrame.cpp:709 msgid "" "Modify hardware emulation settings regulated by the PCSX2 core virtual " "machine." -msgstr "Ändra hårdvaruemuleringsinställningar reglerade av PCSX2's kärn-VM." +msgstr "" +"Ändra hårdvaruemuleringsinställningar reglerade av PCSX2's kärn Virtuella " +"Maskin." #: pcsx2/gui/MainFrame.cpp:711 msgid "Window Settings..." -msgstr "Fönster Inställningar..." +msgstr "Fönster Inställningar ..." #: pcsx2/gui/MainFrame.cpp:712 msgid "Modify window and appearance options, including aspect ratio." -msgstr "Ändra fönster och utseendetillämpningar, inklusive bildkvot." +msgstr "Ändra fönster och utseendetillämpningar, däribland bildkvot." #: pcsx2/gui/MainFrame.cpp:719 msgid "Plugin Settings..." -msgstr "Insticksinställningar" +msgstr "Insticksinställningar ..." #: pcsx2/gui/MainFrame.cpp:720 #, c-format msgid "Opens the %s plugin's advanced settings dialog." -msgstr "Öppnar %s insticksprograms avancerade inställningsdialog." +msgstr "Öppnar %s-insticksprogrammets avancerade inställningsdialog." #: pcsx2/gui/MainMenuClicks.cpp:112 msgid "Reset all settings?" -msgstr "Återställ alla inställningar?" +msgstr "Återställa alla inställningar?" #: pcsx2/gui/MainMenuClicks.cpp:140 msgid "Confirm ISO image change" -msgstr "Bekräfta ISO-bildförändring" +msgstr "Bekräfta ISO-avbildförändring" #: pcsx2/gui/MainMenuClicks.cpp:146 msgid "Do you want to swap discs or boot the new image (via system reset)?" msgstr "" -"Vill Ni byta disk eller köra den nya bilden (genom systemåterställning)?" +"Vill Ni byta disk eller köra den nya avbilden (genom systemåterställning)?" #: pcsx2/gui/MainMenuClicks.cpp:148 pcsx2/gui/MainMenuClicks.cpp:194 msgid "Swap Disc" @@ -1585,7 +1589,7 @@ msgstr "Ni har valt att byta CDVD-källa från %s till %s." #: pcsx2/gui/MainMenuClicks.cpp:191 msgid "Do you want to swap discs or boot the new image (system reset)?" -msgstr "Vill Ni byta disk eller köra den nya bilden (systemåterställning)?" +msgstr "Vill Ni byta disk eller köra den nya avbilden (systemåterställning)?" #: pcsx2/gui/MainMenuClicks.cpp:261 #, c-format @@ -1595,7 +1599,7 @@ msgstr "Alla Stödjandes (%s)" #: pcsx2/gui/MainMenuClicks.cpp:264 #, c-format msgid "Disc Images (%s)" -msgstr "Diskbilder (%s)" +msgstr "Diskavbilder (%s)" #: pcsx2/gui/MainMenuClicks.cpp:267 #, c-format @@ -1608,11 +1612,11 @@ msgstr "Alla Filer (*.*)" #: pcsx2/gui/MainMenuClicks.cpp:273 msgid "Select CDVD source iso..." -msgstr "Välj CDVD käll-ISO..." +msgstr "Välj CDVD'ns käll-ISO ..." #: pcsx2/gui/MainMenuClicks.cpp:290 msgid "Select ELF file..." -msgstr "Välj ELF fil..." +msgstr "Välj ELF-fil ..." #: pcsx2/gui/MainMenuClicks.cpp:316 msgid "ISO file not found!" @@ -1627,15 +1631,15 @@ msgid "" "Error: The configured ISO file does not exist. Click OK to select a new ISO " "source for CDVD." msgstr "" -"Fel: Den konfigurerade ISO-files finns ej. Klicka OK för att välja en ny ISO-" -"källa till CDVD." +"Fel: Den konfigurerade ISO-filen finns ej. Klicka ''Vidare'' för att välja " +"en ny ISO-källa till CDVD'n." #: pcsx2/gui/MainMenuClicks.cpp:390 msgid "" "You have selected the following ISO image into PCSX2:\n" "\n" msgstr "" -"Ni har valt följande ISO-bild för PCSX2:\n" +"Ni har valt följande ISO-avbild för PCSX2: \n" "\n" #: pcsx2/gui/MemoryCardFile.cpp:183 @@ -1646,9 +1650,9 @@ msgid "" "%s\n" "\n" msgstr "" -"Kunde inte skapa ett minneskort:\n" +"Kunde inte skapa ett minneskort: \n" "\n" -"%s\n" +"%s \n" "\n" #: pcsx2/gui/MemoryCardFile.cpp:201 @@ -1659,9 +1663,9 @@ msgid "" "%s\n" "\n" msgstr "" -"Tillgång nekades till minneskortet:\n" +"Tillgång nekades till minneskortet: \n" "\n" -"%s\n" +"%s \n" "\n" #: pcsx2/gui/MemoryCardFile.cpp:525 @@ -1682,23 +1686,23 @@ msgstr "Operativsystemet hindrar denna fil från att skapas" #: pcsx2/gui/Panels/BaseApplicableConfigPanel.cpp:103 msgid "Cannot apply settings..." -msgstr "Kan ej tillämpa inställningar..." +msgstr "Kan ej tillämpa inställningar ..." #: pcsx2/gui/Panels/BiosSelectorPanel.cpp:103 msgid "BIOS Search Path:" -msgstr "BIOS Sökväg:" +msgstr "BIOS-sökväg:" #: pcsx2/gui/Panels/BiosSelectorPanel.cpp:104 msgid "Select folder with PS2 BIOS roms" -msgstr "Välj mapp med PS2-BIOS-ROM" +msgstr "Välj mapp med PS2 BIOS ROM" #: pcsx2/gui/Panels/BiosSelectorPanel.cpp:111 msgid "" "Click the Browse button to select a different folder where PCSX2 will look " "for PS2 BIOS roms." msgstr "" -"Klicka på Bläddra för att välja en annan mapp för PCSX2 att söka efter PS2-" -"BIOS-ROM." +"Klicka på ''Bläddra'' för att välja en annan mapp för PCSX2 att söka efter " +"PS2 BIOS ROM." #: pcsx2/gui/Panels/BiosSelectorPanel.cpp:113 #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:156 @@ -1708,7 +1712,7 @@ msgstr "Fräscha upp listan" #: pcsx2/gui/Panels/BiosSelectorPanel.cpp:115 msgid "Select a BIOS rom:" -msgstr "Välj ett BIOS-ROM:" +msgstr "Välj ett BIOS ROM:" #: pcsx2/gui/Panels/CpuPanel.cpp:24 msgid "Round Mode" @@ -1732,15 +1736,15 @@ msgstr "Positiv" #: pcsx2/gui/Panels/CpuPanel.cpp:32 msgid "Chop / Zero" -msgstr "Hacka / Noll" +msgstr "Hack / Noll" #: pcsx2/gui/Panels/CpuPanel.cpp:37 msgid "None" -msgstr "Ingen" +msgstr "Inget" #: pcsx2/gui/Panels/CpuPanel.cpp:85 msgid "EE/FPU Advanced Recompiler Options" -msgstr "EE/FPU Avancerade Omkompilerar Möjligheter" +msgstr "EE/FPU Avancerade OmkompilerarFunktioner" #: pcsx2/gui/Panels/CpuPanel.cpp:87 pcsx2/gui/Panels/CpuPanel.cpp:102 msgid "Extra + Preserve Sign" @@ -1748,11 +1752,11 @@ msgstr "Extra + Bevara Skylt" #: pcsx2/gui/Panels/CpuPanel.cpp:88 msgid "Full" -msgstr "Full" +msgstr "Fullt" #: pcsx2/gui/Panels/CpuPanel.cpp:99 msgid "VU0 / VU1 Advanced Recompiler Options" -msgstr "VU0 / VU1 Avancerade Omkompilerar Möjligheter" +msgstr "VU0/VU1 Avancerade OmkompilerarFunktioner" #: pcsx2/gui/Panels/CpuPanel.cpp:101 msgid "Extra" @@ -1791,7 +1795,7 @@ msgstr "" #: pcsx2/gui/Panels/CpuPanel.cpp:154 msgid "Enable EE Cache (Slower)" -msgstr "Möjliggör EE Förråd (Långsammare)" +msgstr "Möjliggör EE-förråd (Långsammare)" #: pcsx2/gui/Panels/CpuPanel.cpp:154 msgid "Interpreter only; provided for diagnostic" @@ -1807,8 +1811,9 @@ msgid "" "Vector Unit Interpreter. Slow and not very compatible. Only use for " "diagnostics." msgstr "" -"Vektor Enhets Tolkare. Långsam och inte värst förenlig. Använd endast för " -"diagnostik." +"VU Tolkare. \n" +"Långsam och inte värst förenlig. \n" +"Använd endast för diagnostik." #: pcsx2/gui/Panels/CpuPanel.cpp:187 msgid "microVU Recompiler" @@ -1818,8 +1823,8 @@ msgstr "microVU Omkompilerare" msgid "" "New Vector Unit recompiler with much improved compatibility. Recommended." msgstr "" -"Ny Vektor Enhets omkompilerare med mycket förbättrad förenlighet. " -"Rekommenderas." +"Ny VU-omkompilerare med mycket \n" +" förbättrad förenlighet. Anrådes." #: pcsx2/gui/Panels/CpuPanel.cpp:190 msgid "superVU Recompiler [legacy]" @@ -1829,12 +1834,12 @@ msgstr "superVU Omkompilerare [legat]" msgid "" "Useful for diagnosing bugs or clamping issues in the new mVU recompiler." msgstr "" -"Användbar för att diagnostisera fel eller blockningsproblem i den nya mVU " -"omkompileraren." +"Användbar för att diagnostisera fel eller blockningsproblem \n" +" i den nya mVU-omkompileraren." #: pcsx2/gui/Panels/DirPickerPanel.cpp:64 msgid "Path does not exist" -msgstr "Väg finnes ej" +msgstr "Väg finns ej" #: pcsx2/gui/Panels/DirPickerPanel.cpp:156 msgid "Use default setting" @@ -1855,11 +1860,11 @@ msgstr "Skapa mapp?" #: pcsx2/gui/Panels/DirPickerPanel.cpp:269 #, c-format msgid "A configured folder does not exist. Should %s try to create it?" -msgstr "En konfigurerad mapp finnes ej. Ska %s försöka skapa en?" +msgstr "Ingen konfigurerad mapp finns. Ska %s försöka skapa en?" #: pcsx2/gui/Panels/GSWindowPanel.cpp:30 msgid "Fit to Window/Screen" -msgstr "Passa till Fönster/Skärm" +msgstr "Anpassa till Fönster/Skärm" #: pcsx2/gui/Panels/GSWindowPanel.cpp:31 msgid "Standard (4:3)" @@ -1895,7 +1900,7 @@ msgstr "Dynamiskt växla Vsync beroende på bildfrekvens (läs verktygstips!)" #: pcsx2/gui/Panels/GSWindowPanel.cpp:52 msgid "Double-click toggles fullscreen mode" -msgstr "Dubbel-klicka bryter helskärmsläge" +msgstr "Dubbelklick bryter helskärmsläge" #: pcsx2/gui/Panels/GSWindowPanel.cpp:110 msgid "Aspect Ratio:" @@ -1928,7 +1933,7 @@ msgstr "Spelfixar" #: pcsx2/gui/Panels/GameFixesPanel.cpp:38 msgid "VU Add Hack - Fixes Tri-Ace games boot crash." -msgstr "VU Add Hack - Fixar Tri-Ace spelens körbrak." +msgstr "VU Tilläggs Hack - åtgärdar ''Tri-Ace'' spelens uppkörskrasch." #: pcsx2/gui/Panels/GameFixesPanel.cpp:39 msgid "" @@ -1937,75 +1942,78 @@ msgid "" " * Radiata Stories\n" " * Valkyrie Profile 2" msgstr "" -"Spel som behöver denna hack för att köras:\n" -" * Star Ocean 3\n" -" * Radiata Stories\n" -" * Valkyrie Profile 2" +"Spel som behöver denna hack för att köras: \n" +" * ''Star Ocean 3'' \n" +" * ''Radiata Stories'' \n" +" * ''Valkyrie Profile 2''" #: pcsx2/gui/Panels/GameFixesPanel.cpp:42 msgid "VU Clip Flag Hack - For Persona games (SuperVU recompiler only!)" -msgstr "VU Clip Flag Hack - för Persona spel (SuperVU omkompilerare endast!)" +msgstr "" +"VU Klipp Flagg Hack - för ''Persona'' spel (endast SuperVU-omkompilerare!)" #: pcsx2/gui/Panels/GameFixesPanel.cpp:46 msgid "FPU Compare Hack - For Digimon Rumble Arena 2." -msgstr "FPU Jämför Hack - för Digimon Rumble Arena 2." +msgstr "FPU Jämför Hack - för ''Digimon Rumble Arena 2''." #: pcsx2/gui/Panels/GameFixesPanel.cpp:50 msgid "FPU Multiply Hack - For Tales of Destiny." -msgstr "FPU Multiplikations Hack - för Tales of Destiny." +msgstr "FPU Multiplikations Hack - för ''Tales of Destiny''." #: pcsx2/gui/Panels/GameFixesPanel.cpp:54 msgid "FPU Negative Div Hack - For Gundam games." -msgstr "FPU Negativ Diverse Negativ Hack - för Gundam games." +msgstr "FPU Negativ Diverse Hack - för ''Gundam'' spel." #: pcsx2/gui/Panels/GameFixesPanel.cpp:58 msgid "VU XGkick Hack - For Erementar Gerad." -msgstr "VU XGkick Hack - för Erementar Gerad." +msgstr "VU XGkick Hack - för ''Erementar Gerad''." #: pcsx2/gui/Panels/GameFixesPanel.cpp:62 msgid "FFX videos fix - Fixes bad graphics overlay in FFX videos." -msgstr "FFX videor fix - Fixar dålig grafiköverdrag hos FFX videor." +msgstr "FFX videor fix - löser dåligt grafiköverdrag för FFX-videor." #: pcsx2/gui/Panels/GameFixesPanel.cpp:66 msgid "EE timing hack - Multi purpose hack. Try if all else fails." -msgstr "EE tids hack - Flersyftes hack. Försök ifall allt annat misslyckas." +msgstr "EE tids hack - en flersyftes hack. Försök ifall allt annat misslyckas." #: pcsx2/gui/Panels/GameFixesPanel.cpp:75 msgid "" "Skip MPEG hack - Skips videos/FMVs in games to avoid game hanging/freezes." msgstr "" -"Hoppa över MPEG hack - Hoppar över video/FMV i spel för att undgå att spel " +"Hoppa över MPEG hack - hoppar över videor/FMV'er i spel för att undgå att de " "hänger/fryses." #: pcsx2/gui/Panels/GameFixesPanel.cpp:79 msgid "OPH Flag hack - Try if your game freezes showing the same frame." -msgstr "OPH Flag hack - Försök ifall Ert spel fryser visandes samma bild." +msgstr "OPH Flagg hack - Försök ifall Ert spel fryser visandes samma bild." #: pcsx2/gui/Panels/GameFixesPanel.cpp:88 msgid "Ignore DMAC writes when it is busy." -msgstr "Ignorera DMAC skrivningar när den är upptagen." +msgstr "Ignorera DMAC-skrivningar när denne är upptagen." #: pcsx2/gui/Panels/GameFixesPanel.cpp:95 msgid "Simulate VIF1 FIFO read ahead. Fixes slow loading games." -msgstr "Simulerar VIF1 FIFO läs vidare. Löser långsamt laddande spel." +msgstr "Simulera VIF1 FIFO läs vidare. Löser långsamt laddande spel." #: pcsx2/gui/Panels/GameFixesPanel.cpp:103 msgid "Delay VIF1 Stalls (VIF1 FIFO) - For SOCOM 2 HUD." -msgstr "Fördröj VIF1 uppehåll (VIF1 FIFO) - för SOCOM 2 HUD." +msgstr "Fördröj VIF1 uppehåll (VIF1 FIFO) - för ''SOCOM 2'' HUD." #: pcsx2/gui/Panels/GameFixesPanel.cpp:107 msgid "Ignore Bus Direction on Path3 Transfer - Used for Hotwheels" -msgstr "Strunta i Bussriktning vid Path3 Överföring - Används för Hotwheels" +msgstr "" +"Strunta i Bussriktning vid Path3 Överföring - används för ''Hotwheels''" #: pcsx2/gui/Panels/GameFixesPanel.cpp:118 msgid "Enable manual game fixes [Not recommended]" -msgstr "Möjliggör manuella spelfixar [Rekommenderas ej]" +msgstr "Möjliggör manuella spelfixar [Avrådes]" #: pcsx2/gui/Panels/GameFixesPanel.cpp:127 msgid "" "The safest way to make sure that all game fixes are completely disabled." msgstr "" -"Det bästa sättet att försäkra om att alla spelfixar är helt förhindrade." +"Det bästa sättet att försäkra Er om att alla manuella spelfixar \n" +" är helt förhindrade är att ha denna avmarkerad." #: pcsx2/gui/Panels/LogOptionsPanels.cpp:249 msgid "Enable Trace Logging" @@ -2016,8 +2024,8 @@ msgid "" "Trace logs are all written to emulog.txt. Toggle trace logging at any time " "using F10." msgstr "" -"Spårloggar är alla tillförda emulog.txt. Växla spårloggning när som helst " -"med F10." +"Spårloggar är alla skrivna i ''emulog.txt''. Växla spårloggning när som " +"helst med ''F10''." #: pcsx2/gui/Panels/LogOptionsPanels.cpp:251 msgid "" @@ -2025,7 +2033,7 @@ msgid "" "of 'What happened to my FPS?' problems. :)" msgstr "" "Varning: Möjliggörande av spårloggar är vanligtvis mycket långsamt, och är " -"den främsta orsaken till 'Vad skedde med mina FPS?' problem. :)" +"den främsta orsaken till ''Vad skedde med mina FPS'er?'' problem. :)" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:151 msgid "Select folder with PS2 memory cards" @@ -2061,7 +2069,7 @@ msgstr "Skapa ett nytt minneskort." #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:529 msgid "Rename this memory card ..." -msgstr "Byt namn på detta minneskort ..." +msgstr "Namnbyt detta minneskort ..." #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:533 msgid "Insert ..." @@ -2081,12 +2089,12 @@ msgstr "Dubblera detta minneskort ..." #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:542 msgid "Delete" -msgstr "Ta bort" +msgstr "Kassera" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:545 msgid "Permanently delete this memory card from disk (all contents are lost)" msgstr "" -"Permanent ta bort detta minneskort från disken (allt innehåll går förlorat)" +"Ta permanent bort detta minneskort från disken (allt innehåll går förlorat)" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:547 msgid "Create a new memory card and assign it to this Port." @@ -2094,7 +2102,7 @@ msgstr "Skapa ett nytt minneskort och anvisa den till denna Sockel." #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:726 msgid "Delete memory file?" -msgstr "Radera minnesfil?" +msgstr "Kassera minnesfil?" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:750 #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:762 @@ -2105,15 +2113,15 @@ msgstr "Dubblera minneskort" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:750 msgid "Failed: Can only duplicate an existing card." -msgstr "Misslyckades: Kan endast dubblera ett befintlig kort." +msgstr "Misslyckades: Kan endast dubblera ett befintligt kort." #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:769 msgid "" "Select a name for the duplicate\n" "( '.ps2' will be added automatically)" msgstr "" -"Välj ett namn för dubbleringen\n" -"( '.ps2' läggs till automatiskt)" +"Välj ett namn för dubbleringen \n" +" (''.ps2'' läggs till automatiskt):" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:782 #, c-format @@ -2127,7 +2135,7 @@ msgstr "Kopiering misslyckades!" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:816 #, c-format msgid "Memory card '%s' duplicated to '%s'." -msgstr "Minneskorts '%s' dubblerad till '%s'." +msgstr "Minneskort ''%s'' dubblerad till ''%s''." #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:820 msgid "Success" @@ -2139,18 +2147,18 @@ msgid "" "Select a new name for the memory card '%s'\n" "( '.ps2' will be added automatically)" msgstr "" -"Välj ett nytt namn för minneskortet '%s'\n" -"( '.ps2' läggs till automatiskt)" +"Välj ett nytt namn för minneskortet ''%s'' \n" +" (''.ps2'' läggs till automatiskt):" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:844 #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:856 #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:872 msgid "Rename memory card" -msgstr "Byt namn på minneskort" +msgstr "Namnbyt minneskort" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:872 msgid "Error: Rename could not be completed.\n" -msgstr "Fel: Namnbyte kunde inte fullgöras.\n" +msgstr "Fel: Namnbyte kunde inte fullgöras. \n" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:962 #: pcsx2/gui/Panels/MemoryCardListView.cpp:139 @@ -2171,7 +2179,7 @@ msgstr "Tom" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:994 #, c-format msgid "Select a target port for '%s'" -msgstr "Välj en målsockel för %s" +msgstr "Välj en målsockel för ''%s''" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:995 msgid "Insert card" @@ -2195,7 +2203,7 @@ msgstr "Namnbyt kort ..." #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1058 msgid "Delete card" -msgstr "Radera kort" +msgstr "Kassera kort" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1061 #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1065 @@ -2252,7 +2260,7 @@ msgstr "Användarlägesval" #: pcsx2/gui/Panels/MiscPanelStuff.cpp:50 msgid "User Documents (recommended)" -msgstr "Användardokument (rekommenderas)" +msgstr "AnvändarDokument (Anrådes)" #: pcsx2/gui/Panels/MiscPanelStuff.cpp:51 msgid "Location: " @@ -2267,8 +2275,8 @@ msgid "" "This setting may require administration privileges from your operating " "system, depending on how your system is configured." msgstr "" -"Denna inställning kan kräva administratörsprivilegier av Ert operativsystem, " -"beroende av hur Ert system är konfigurerat." +"Beroende av hur Ert system är konfigurerat kan denna inställning kan kräva " +"administratörsprivilegier av Ert operativsystem." #: pcsx2/gui/Panels/MiscPanelStuff.cpp:66 #, c-format @@ -2309,11 +2317,11 @@ msgstr "Välj en mapp för loggar/dumpar" #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:230 msgid "Applying settings..." -msgstr "Tillämpar inställningar..." +msgstr "Tillämpar inställningar ..." #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:240 msgid "Shutdown PS2 virtual machine?" -msgstr "Stänga ned PS2-VM?" +msgstr "Stänga ner PS2's Virtuella Maskin?" #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:321 msgid "I'm givin' her all she's got, Captain!" @@ -2321,7 +2329,7 @@ msgstr "Jag ger henne allt hon har, Kapten!" #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:323 msgid "Enumerating available plugins..." -msgstr "Uppräknar tillgängliga insticksprogram..." +msgstr "Uppräknar tillgängliga insticksprogram ..." #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:356 msgid "Plugins Search Path:" @@ -2333,12 +2341,13 @@ msgstr "Välj en mapp med PCSX2-insticksprogram" #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:370 msgid "Configure..." -msgstr "Konfigurera..." +msgstr "Konfigurera ..." #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:379 msgid "Click the Browse button to select a different folder for PCSX2 plugins." msgstr "" -"Klicka på Bläddra för att välja en annan mapp för PCSX2's insticksprogram." +"Klicka på ''Bläddra'' för att välja en annan mapp för PCSX2's " +"insticksprogram." #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:481 #, c-format @@ -2353,14 +2362,14 @@ msgid "" "Reason: %s\n" "\n" msgstr "" -"Det valda %s insticksprogrammet misslyckades att laddas.\n" +"Det valda %s-insticksprogrammet misslyckades att laddas. \n" "\n" -"Anledning: %s\n" +"Anledning: %s \n" "\n" #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:730 msgid "Completing tasks..." -msgstr "Fullföljer uppgifter..." +msgstr "Fullföljer uppgifter ..." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:96 msgid "Enable speedhacks" @@ -2370,7 +2379,8 @@ msgstr "Möjliggör snabbhackar" msgid "" "A safe and easy way to make sure that all speedhacks are completely disabled." msgstr "" -"Ett säkert och lätt sätt att försäkra om att alla snabbhackar är förhindrade." +"Ett säkert och lätt sätt att försäkra Er om att alla snabbhackar \n" +" är helt förhindrade är att ha denna avmarkerad." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:111 msgid "" @@ -2382,11 +2392,11 @@ msgstr "" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:120 msgid "EE Cyclerate [Not Recommended]" -msgstr "EE Cykelhastighet [Rekommenderas Ej]" +msgstr "EE cykelhastighet [Avrådes]" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:141 msgid "VU Cycle Stealing [Not Recommended]" -msgstr "VU Cykelstöld [Rekommenderas Ej]" +msgstr "VU cykelstöld [Avrådes]" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:161 msgid "microVU Hacks" @@ -2394,14 +2404,14 @@ msgstr "microVU Hackisar" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:163 msgid "mVU Flag Hack" -msgstr "mVU Flag Hack" +msgstr "mVU Flagg Hack" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:164 msgid "" "Good Speedup and High Compatibility; may cause bad graphics... [Recommended]" msgstr "" -"Bra Uppsnabbning och Hög Förenlighet; kan orsaka dålig grafik... " -"[Rekommenderas]" +"Bra Uppsnabbning och Hög Förenlighet; \n" +" kan orsaka dålig grafik ... [Anrådes]" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:166 msgid "MTVU (Multi-Threaded microVU1)" @@ -2412,8 +2422,8 @@ msgid "" "Good Speedup and High Compatibility; may cause hanging... [Recommended if 3+ " "cores]" msgstr "" -"Bra Uppsnabbning och Hög Förenlighet; kan orsaka att det hänger sig... " -"[Rekommenderas för 3+ kärnor]" +"Bra Uppsnabbning och Hög Förenlighet; kan orsaka \n" +" att det hänger sig ... [Anrådes för 3+ kärnor]" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:183 msgid "Other Hacks" @@ -2428,19 +2438,19 @@ msgid "" "Huge speedup for some games, with almost no compatibility side effects. " "[Recommended]" msgstr "" -"Enorm uppsnabbning för vissa spel, med nästan inga förenlighetsbieffekter. " -"[Rekommenderas]" +"Enorm uppsnabbning för vissa spel, \n" +" nästan utan förenlighetsbieffekter. [Anrådes]" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:188 msgid "Enable Wait Loop Detection" -msgstr "Möjliggör Vänta Loop Uppfattning" +msgstr "Möjliggör VäntloopsUpptäckning" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:189 msgid "" "Moderate speedup for some games, with no known side effects. [Recommended]" msgstr "" -"Måttlig uppsnabbning för vissa spel, med inga kända bieffekter. " -"[Rekommenderas]" +"Måttlig uppsnabbning för vissa spel, \n" +" utan kända bieffekter. [Anrådes]" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 msgid "Enable fast CDVD" @@ -2448,7 +2458,7 @@ msgstr "Möjliggör snabb CDVD" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:192 msgid "Fast disc access, less loading times. [Not Recommended]" -msgstr "Snabb disktillgång, färre laddningsgånger. [Rekommenderas Ej]" +msgstr "Snabb disktillgång, färre laddningsgånger. [Avrådes]" #: pcsx2/gui/Panels/ThemeSelectorPanel.cpp:37 msgid "Themes Search Path:" @@ -2463,8 +2473,8 @@ msgid "" "Click the Browse button to select a different folder containing PCSX2 visual " "themes." msgstr "" -"Klicka på Bläddra-knappen för att välja en annan mapp som innehåller PCSX2-" -"teman." +"Klicka på ''Bläddra''-knappen för att välja en annan mapp innehållandes " +"PCSX2-teman." #: pcsx2/gui/Panels/ThemeSelectorPanel.cpp:49 msgid "Select a visual theme:" @@ -2478,24 +2488,25 @@ msgstr "Förhindra Bildbegränsning" msgid "" "Useful for running benchmarks. Toggle this option in-game by pressing F4." msgstr "" -"Användbar för att köra riktmärkning. Omkoppla denna tillämpning i aktivt " -"spel genom att trycka på F4." +"Användbar för att köra riktmärkning. \n" +"Omkoppla denna tillämpning i aktivt spel \n" +" genom att trycka på ''F4''." #: pcsx2/gui/Panels/VideoPanel.cpp:61 msgid "Base Framerate Adjust:" -msgstr "Grundbildfrekvensjustering:" +msgstr "GrundbildfrekvensReglering:" #: pcsx2/gui/Panels/VideoPanel.cpp:67 msgid "Slow Motion Adjust:" -msgstr "Ultrarapidjustering:" +msgstr "UltrarapidReglering:" #: pcsx2/gui/Panels/VideoPanel.cpp:73 msgid "Turbo Adjust:" -msgstr "Turbojustering:" +msgstr "TurboReglering:" #: pcsx2/gui/Panels/VideoPanel.cpp:88 msgid "NTSC Framerate:" -msgstr "NTSC Bildfrekvens:" +msgstr "NTSC bildfrekvens:" #: pcsx2/gui/Panels/VideoPanel.cpp:91 pcsx2/gui/Panels/VideoPanel.cpp:97 msgid "FPS" @@ -2503,23 +2514,23 @@ msgstr "FPS" #: pcsx2/gui/Panels/VideoPanel.cpp:94 msgid "PAL Framerate:" -msgstr "PAL Bildfrekvens:" +msgstr "PAL bildfrekvens:" #: pcsx2/gui/Panels/VideoPanel.cpp:166 msgid "" "Error while parsing either NTSC or PAL framerate settings. Settings must be " "valid floating point numerics." msgstr "" -"Fel under tolkning av antingen NTSC eller PAL bildfrekvensinstälningar. " +"Fel under tolkning av antingen NTSC eller PAL bildfrekvensinstälningar. " "Inställningarna måste vara giltliga flyttalsnummer." #: pcsx2/gui/Panels/VideoPanel.cpp:184 msgid "Disabled [default]" -msgstr "Förhindrad [förval]" +msgstr "Förhindrat [förval]" #: pcsx2/gui/Panels/VideoPanel.cpp:188 msgid "Skip when on Turbo only (TAB to enable)" -msgstr "Hoppa över endast vid Turbo (TAB för att möjliggöra)" +msgstr "Hoppa över endast vid Turbo (''Tab'' för att möjliggöra)" #: pcsx2/gui/Panels/VideoPanel.cpp:192 msgid "Constant skipping" @@ -2530,8 +2541,8 @@ msgid "" "Normal and Turbo limit rates skip frames. Slow motion mode will still " "disable frameskipping." msgstr "" -"Normal och Turbobegränsad beräknad bildöverhoppning. Ultrarapidsläge " -"förhindrar fortfarande bildöverhoppning." +"Normal och Turbobegränsad bildöverhoppning, \n" +" vilket dock ännu förhindras med Ultrarapidsläge." #: pcsx2/gui/Panels/VideoPanel.cpp:217 msgid "Frames to Draw" @@ -2550,12 +2561,12 @@ msgid "" "For troubleshooting potential bugs in the MTGS only, as it is potentially " "very slow." msgstr "" -"Enbart för att problemlösa eventuella fel inom \n" -"MTGS, eftersom det möjligen är mycket långsamt." +"Endast för att problemlösa eventuella fel inom \n" +" MTGS, eftersom det möjligen är mycket långsamt." #: pcsx2/gui/Panels/VideoPanel.cpp:302 msgid "Disable all GS output" -msgstr "Förhindra all GS utgång" +msgstr "Förhindra all GS-utgång" #: pcsx2/gui/Panels/VideoPanel.cpp:303 msgid "" @@ -2563,11 +2574,11 @@ msgid "" "components." msgstr "" "Förhindrar helt all GS-insticksprogramsaktivitet; \n" -"idealt som utgångspunkt för EE-kärnkomponenter." +" idealt för att utvärdera EE-kärnkomponenter." #: pcsx2/gui/Panels/VideoPanel.cpp:320 msgid "Frame Skipping" -msgstr "Bildöverhoppande" +msgstr "Bildöverhoppare" #: pcsx2/gui/Panels/VideoPanel.cpp:323 msgid "Framelimiter" @@ -2578,8 +2589,8 @@ msgid "" "Cannot load this savestate. The state is from an incompatible edition of " "PCSX2 that is either newer than this version, or is no longer supported." msgstr "" -"Kan inte ladda denna sparpunkt; den är från en oförenlig utgåva av PCSX2 som " -"antingen är nyare än denna version eller som ej längre stödjes." +"Kan inte att ladda denna sparpunkt; den är från en oförenlig utgåva av PCSX2 " +"som antingen är nyare än denna eller som inte längre stödjes." #: pcsx2/gui/SysState.cpp:290 msgid "" @@ -2591,7 +2602,8 @@ msgstr "" #: pcsx2/gui/SysState.cpp:326 msgid "There is no active virtual machine state to download or save." -msgstr "Det finns inget aktivt VM-tillstånd att nerladda eller spara." +msgstr "" +"Det finns inget aktivt Virtuellt Maskin tillstånd att nerladda eller spara." #: pcsx2/gui/SysState.cpp:520 msgid "" @@ -2600,8 +2612,8 @@ msgid "" "corrupted." msgstr "" "Denna sparpunkt kan inte laddas eftersom den inte är ett giltlig gzip-arkiv. " -"Den kan ha skapats av en äldre ostödjandes version av PCSX2, eller den kan " -"ha förstörts." +"Den kan ha skapats av en äldre ostödjandes version av PCSX2, eller så den " +"kan ha förstörts." #: pcsx2/gui/SysState.cpp:579 msgid "This file is not a valid PCSX2 savestate. See the logfile for details." @@ -2612,8 +2624,8 @@ msgid "" "This savestate cannot be loaded due to missing critical components. See the " "log file for details." msgstr "" -"Denna sparpunkt kan inte laddas till följd av saknade kritiska komponenter. " -"Se loggfil för detaljer." +"Oförmögen att ladda denna sparpunkt till följd av saknade kritiska " +"komponenter. Se loggfil för detaljer." #: pcsx2/gui/i18n.cpp:63 msgid " (default)" @@ -2621,14 +2633,14 @@ msgstr " (förval)" #: pcsx2/ps2/BiosTools.cpp:83 pcsx2/ps2/BiosTools.cpp:151 msgid "The selected BIOS file is not a valid PS2 BIOS. Please re-configure." -msgstr "Den valda BIOS-filen är inte ett giltligt PS2-BIOS. Omkonfigurera!" +msgstr "Den valda BIOS-filen är inte ett giltligt PS2 BIOS. Omkonfigurera!" #: pcsx2/ps2/BiosTools.cpp:244 msgid "" "The PS2 BIOS could not be loaded. The BIOS has not been configured, or the " "configuration has been corrupted. Please re-configure." msgstr "" -"PS2-BIOS'et kunde inte laddas eftersom det inte har konfigurerats, eller så " +"PS2 BIOS'et kunde inte laddas eftersom det inte har konfigurerats, eller så " "har konfigurationen förstörts. Omkonfigurera!" #: pcsx2/ps2/BiosTools.cpp:251 @@ -2641,8 +2653,8 @@ msgid "" "%s Extensions not found. The R5900-32 recompiler requires a host CPU with " "MMX, SSE, and SSE2 extensions." msgstr "" -"%s Förlängningar ej funna. Omkompilatorn R5900-32 kräver en värd-CPU med " -"MMX, SSE, och SSE2 förlängningar." +"%s förlängningar ej funna. Omkompilatorn R5900-32 kräver en värd-CPU med " +"instruktionsuppsättningarna MMX, SSE, och SSE2." #: pcsx2/x86/microVU.cpp:28 #, c-format @@ -2650,8 +2662,8 @@ msgid "" "%s Extensions not found. microVU requires a host CPU with MMX, SSE, and " "SSE2 extensions." msgstr "" -"%s Förlängningar ej funna. microVU kräven en värd-CPU med MMX, SSE, och SSE2 " -"förlängningar." +"%s förlängningar ej funna. microVU kräver en värd-CPU med " +"instruktionsuppsättningarna MMX, SSE, och SSE2." #~ msgid "mVU Block Hack" #~ msgstr "mVU Block Hack" @@ -2659,7 +2671,8 @@ msgstr "" #~ msgid "" #~ "Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." #~ msgstr "" -#~ "Bra Uppsnabbning och Hög Förenlighet; kan orsaka dålig grafik, SPS, etc..." +#~ "Bra Uppsnabbning och Hög Förenlighet; \n" +#~ " kan orsaka dålig grafik, SPS, etc..." #~ msgid "Enable game fixes" #~ msgstr "Möjliggör spelfixar" From 0933ee2fd55ce031658124a56159a59ac051e736 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Tue, 28 Feb 2012 20:57:07 +0000 Subject: [PATCH 17/83] A couple minor changes, including a bad looking block manager bug that wasn't really all that bad :p git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5109 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/GS.cpp | 3 ++- pcsx2/HwRead.cpp | 2 +- pcsx2/x86/BaseblockEx.h | 3 --- plugins/GSdx/GSState.cpp | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/pcsx2/GS.cpp b/pcsx2/GS.cpp index b00e8b65f..65543b513 100644 --- a/pcsx2/GS.cpp +++ b/pcsx2/GS.cpp @@ -79,7 +79,7 @@ static __fi void gsCSRwrite( const tGS_CSR& csr ) SIGNAL_IMR_Pending = false; #else GUNIT_WARN("GUNIT_WARN: csr.RESET"); - Console.Warning( "csr.RESET" ); + //Console.Warning( "csr.RESET" ); //gifUnit.Reset(true); // Don't think gif should be reset... gifUnit.gsSIGNAL.queued = false; GetMTGS().SendSimplePacket(GS_RINGTYPE_RESET, 0, 0, 0); @@ -425,6 +425,7 @@ __fi void gsFrameSkip() //We got away with it before i think due to our awful GS timing, but now we have it right (ish) void gsPostVsyncStart() { + //gifUnit.FlushToMTGS(); // Needed for some (broken?) homebrew game loaders CSRreg.SwapField(); GetMTGS().PostVsyncStart(); } diff --git a/pcsx2/HwRead.cpp b/pcsx2/HwRead.cpp index c9483d3e6..f6b34a02d 100644 --- a/pcsx2/HwRead.cpp +++ b/pcsx2/HwRead.cpp @@ -203,7 +203,7 @@ mem16_t __fastcall hwRead16_page_0F_INTC_HACK(u32 mem) u32 ret32 = _hwRead32<0x0f, true>(mem & ~0x03); u16 ret16 = ((u16*)&ret32)[(mem>>1) & 0x01]; - eeHwTraceLog( mem, ret16, "Read" ); + eeHwTraceLog( mem, ret16, true ); return ret16; } diff --git a/pcsx2/x86/BaseblockEx.h b/pcsx2/x86/BaseblockEx.h index 2fc4cd80c..89ccec31e 100644 --- a/pcsx2/x86/BaseblockEx.h +++ b/pcsx2/x86/BaseblockEx.h @@ -127,9 +127,6 @@ public: void clear() { - if(blocks) { - memset(blocks, 0, sizeof(blocks)); - } _Size = 0; } diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index da5ae9291..bc281a98f 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -184,7 +184,7 @@ void GSState::SetFrameSkip(int skip) void GSState::Reset() { - printf("GS reset\n"); + printf("GSdx info: GS reset\n"); // FIXME: memset(m_mem.m_vm8, 0, m_mem.m_vmsize); // bios logo not shown cut in half after reset, missing graphics in GoW after first FMV memset(&m_path[0], 0, sizeof(m_path[0]) * countof(m_path)); From 954e7906edd093720727ca110208f7eda4bc5aee Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Wed, 29 Feb 2012 00:29:29 +0000 Subject: [PATCH 18/83] GSdx: Added the color control functionality known as "ShadeBoost". Thanks to KrossX for initial converting / GUI work and Pseudonym for normalizing / fixing the maths. Note: Not sure if it should be shader #7 or smth else :p git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5110 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GPURenderer.cpp | 6 ++ plugins/GSdx/GPURenderer.h | 1 + plugins/GSdx/GSDevice.cpp | 24 ++++++ plugins/GSdx/GSDevice.h | 12 +++ plugins/GSdx/GSDevice11.cpp | 47 +++++++++++ plugins/GSdx/GSDevice11.h | 7 ++ plugins/GSdx/GSDevice9.cpp | 37 +++++++++ plugins/GSdx/GSDevice9.h | 6 ++ plugins/GSdx/GSRenderer.cpp | 6 ++ plugins/GSdx/GSRenderer.h | 1 + plugins/GSdx/GSSettingsDlg.cpp | 125 ++++++++++++++++++++++++++++ plugins/GSdx/GSSettingsDlg.h | 19 +++++ plugins/GSdx/GSdx.rc | 131 +++++++++++++++++++----------- plugins/GSdx/GSdx.vcxproj | 1 + plugins/GSdx/GSdx.vcxproj.filters | 3 + plugins/GSdx/GSdx_vs2008.vcproj | 4 + plugins/GSdx/res/shadeboost.fx | 71 ++++++++++++++++ plugins/GSdx/resource.h | 17 +++- 18 files changed, 466 insertions(+), 52 deletions(-) create mode 100644 plugins/GSdx/res/shadeboost.fx diff --git a/plugins/GSdx/GPURenderer.cpp b/plugins/GSdx/GPURenderer.cpp index 7b71a41d4..05500ff6f 100644 --- a/plugins/GSdx/GPURenderer.cpp +++ b/plugins/GSdx/GPURenderer.cpp @@ -38,6 +38,7 @@ GPURenderer::GPURenderer(GSDevice* dev) m_vsync = !!theApp.GetConfig("vsync", 0); m_fxaa = !!theApp.GetConfig("fxaa", 0); m_scale = m_mem.GetScale(); + m_shadeboost = !!theApp.GetConfig("ShadeBoost", 0); #ifdef _WINDOWS @@ -117,6 +118,11 @@ bool GPURenderer::Merge() m_dev->Merge(st, sr, dr, s, 1, 1, GSVector4(0, 0, 0, 1)); + if(m_shadeboost) + { + m_dev->ShadeBoost(); + } + if(m_fxaa) { m_dev->FXAA(); diff --git a/plugins/GSdx/GPURenderer.h b/plugins/GSdx/GPURenderer.h index b1c41a45d..53adfa150 100644 --- a/plugins/GSdx/GPURenderer.h +++ b/plugins/GSdx/GPURenderer.h @@ -36,6 +36,7 @@ protected: int m_aspectratio; bool m_vsync; bool m_fxaa; + bool m_shadeboost; GSVector2i m_scale; virtual void ResetDevice() {} diff --git a/plugins/GSdx/GSDevice.cpp b/plugins/GSdx/GSDevice.cpp index 8dbb1c881..bda55c561 100644 --- a/plugins/GSdx/GSDevice.cpp +++ b/plugins/GSdx/GSDevice.cpp @@ -32,6 +32,7 @@ GSDevice::GSDevice() , m_weavebob(NULL) , m_blend(NULL) , m_fxaa(NULL) + , m_shadeboost(NULL) , m_1x1(NULL) , m_frame(0) { @@ -48,6 +49,7 @@ GSDevice::~GSDevice() delete m_weavebob; delete m_blend; delete m_fxaa; + delete m_shadeboost; delete m_1x1; } @@ -69,6 +71,7 @@ bool GSDevice::Reset(int w, int h) delete m_weavebob; delete m_blend; delete m_fxaa; + delete m_shadeboost; delete m_1x1; m_backbuffer = NULL; @@ -76,6 +79,7 @@ bool GSDevice::Reset(int w, int h) m_weavebob = NULL; m_blend = NULL; m_fxaa = NULL; + m_shadeboost = NULL; m_1x1 = NULL; m_current = NULL; // current is special, points to other textures, no need to delete @@ -317,6 +321,26 @@ void GSDevice::FXAA() } } +void GSDevice::ShadeBoost() +{ + GSVector2i s = m_current->GetSize(); + + if(m_shadeboost == NULL || m_shadeboost->GetSize() != s) + { + delete m_shadeboost; + m_shadeboost = CreateRenderTarget(s.x, s.y, false); + } + + if(m_shadeboost != NULL) + { + GSVector4 sr(0, 0, 1, 1); + GSVector4 dr(0, 0, s.x, s.y); + + StretchRect(m_current, sr, m_shadeboost, dr, 7, false); + DoShadeBoost(m_shadeboost, m_current); + } +} + bool GSDevice::ResizeTexture(GSTexture** t, int w, int h) { if(t == NULL) {ASSERT(0); return false;} diff --git a/plugins/GSdx/GSDevice.h b/plugins/GSdx/GSDevice.h index 3ce8770a2..44f2d82ae 100644 --- a/plugins/GSdx/GSDevice.h +++ b/plugins/GSdx/GSDevice.h @@ -55,6 +55,15 @@ public: FXAAConstantBuffer() {memset(this, 0, sizeof(*this));} }; +class ShadeBoostConstantBuffer +{ +public: + GSVector4 rcpFrame; + GSVector4 rcpFrameOpt; + + ShadeBoostConstantBuffer() {memset(this, 0, sizeof(*this));} +}; + #pragma pack(pop) class GSDevice : public GSAlignedClass<32> @@ -70,6 +79,7 @@ protected: GSTexture* m_weavebob; GSTexture* m_blend; GSTexture* m_fxaa; + GSTexture* m_shadeboost; GSTexture* m_1x1; GSTexture* m_current; struct {size_t stride, start, count, limit;} m_vertex; @@ -82,6 +92,7 @@ protected: virtual void DoMerge(GSTexture* st[2], GSVector4* sr, GSTexture* dt, GSVector4* dr, bool slbg, bool mmod, const GSVector4& c) = 0; virtual void DoInterlace(GSTexture* st, GSTexture* dt, int shader, bool linear, float yoffset) = 0; virtual void DoFXAA(GSTexture* st, GSTexture* dt) {} + virtual void DoShadeBoost(GSTexture* st, GSTexture* dt) {} public: GSDevice(); @@ -134,6 +145,7 @@ public: void Merge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, const GSVector2i& fs, bool slbg, bool mmod, const GSVector4& c); void Interlace(const GSVector2i& ds, int field, int mode, float yoffset); void FXAA(); + void ShadeBoost(); bool ResizeTexture(GSTexture** t, int w, int h); diff --git a/plugins/GSdx/GSDevice11.cpp b/plugins/GSdx/GSDevice11.cpp index f936be407..3d355349e 100644 --- a/plugins/GSdx/GSDevice11.cpp +++ b/plugins/GSdx/GSDevice11.cpp @@ -201,6 +201,36 @@ bool GSDevice11::Create(GSWnd* wnd) hr = CompileShader(IDR_INTERLACE_FX, format("ps_main%d", i).c_str(), NULL, &m_interlace.ps[i]); } + // Shade Boost + + int ShadeBoost_Contrast = theApp.GetConfig("ShadeBoost_Contrast", 50); + int ShadeBoost_Brightness = theApp.GetConfig("ShadeBoost_Brightness", 50); + int ShadeBoost_Saturation = theApp.GetConfig("ShadeBoost_Saturation", 50); + + string str[3]; + + str[0] = format("%d", ShadeBoost_Saturation); + str[1] = format("%d", ShadeBoost_Brightness); + str[2] = format("%d", ShadeBoost_Contrast); + + D3D11_SHADER_MACRO macro[] = + { + {"SB_SATURATION", str[0].c_str()}, + {"SB_BRIGHTNESS", str[1].c_str()}, + {"SB_CONTRAST", str[2].c_str()}, + {NULL, NULL}, + }; + + memset(&bd, 0, sizeof(bd)); + + bd.ByteWidth = sizeof(ShadeBoostConstantBuffer); + bd.Usage = D3D11_USAGE_DEFAULT; + bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + + hr = m_dev->CreateBuffer(&bd, NULL, &m_shadeboost.cb); + + hr = CompileShader(IDR_SHADEBOOST_FX, "ps_main", macro, &m_shadeboost.ps); + // fxaa memset(&bd, 0, sizeof(bd)); @@ -670,6 +700,23 @@ void GSDevice11::DoFXAA(GSTexture* st, GSTexture* dt) //dt->Save("c:\\temp1\\2.bmp"); } +void GSDevice11::DoShadeBoost(GSTexture* st, GSTexture* dt) +{ + GSVector2i s = dt->GetSize(); + + GSVector4 sr(0, 0, 1, 1); + GSVector4 dr(0, 0, s.x, s.y); + + ShadeBoostConstantBuffer cb; + + cb.rcpFrame = GSVector4(1.0f / s.x, 1.0f / s.y, 0.0f, 0.0f); + cb.rcpFrameOpt = GSVector4::zero(); + + m_ctx->UpdateSubresource(m_shadeboost.cb, 0, NULL, &cb, 0, 0); + + StretchRect(st, sr, dt, dr, m_shadeboost.ps, m_shadeboost.cb, true); +} + void GSDevice11::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vertices, bool datm) { const GSVector2i& size = rt->GetSize(); diff --git a/plugins/GSdx/GSDevice11.h b/plugins/GSdx/GSDevice11.h index 8e8b4afb9..33ec350d8 100644 --- a/plugins/GSdx/GSDevice11.h +++ b/plugins/GSdx/GSDevice11.h @@ -37,6 +37,7 @@ class GSDevice11 : public GSDeviceDX void DoMerge(GSTexture* st[2], GSVector4* sr, GSTexture* dt, GSVector4* dr, bool slbg, bool mmod, const GSVector4& c); void DoInterlace(GSTexture* st, GSTexture* dt, int shader, bool linear, float yoffset = 0); void DoFXAA(GSTexture* st, GSTexture* dt); + void DoShadeBoost(GSTexture* st, GSTexture* dt); // @@ -110,6 +111,12 @@ public: // TODO CComPtr cb; } m_fxaa; + struct + { + CComPtr ps; + CComPtr cb; + } m_shadeboost; + struct { CComPtr dss; diff --git a/plugins/GSdx/GSDevice9.cpp b/plugins/GSdx/GSDevice9.cpp index b912b9019..ac3eed9ea 100644 --- a/plugins/GSdx/GSDevice9.cpp +++ b/plugins/GSdx/GSDevice9.cpp @@ -282,6 +282,28 @@ bool GSDevice9::Create(GSWnd* wnd) CompileShader(IDR_INTERLACE_FX, format("ps_main%d", i), NULL, &m_interlace.ps[i]); } + // Shade Boost + + int ShadeBoost_Contrast = theApp.GetConfig("ShadeBoost_Contrast", 50); + int ShadeBoost_Brightness = theApp.GetConfig("ShadeBoost_Brightness", 50); + int ShadeBoost_Saturation = theApp.GetConfig("ShadeBoost_Saturation", 50); + + string str[3]; + + str[0] = format("%d", ShadeBoost_Saturation); + str[1] = format("%d", ShadeBoost_Brightness); + str[2] = format("%d", ShadeBoost_Contrast); + + D3DXMACRO macro[] = + { + {"SB_SATURATION", str[0].c_str()}, + {"SB_BRIGHTNESS", str[1].c_str()}, + {"SB_CONTRAST", str[2].c_str()}, + {NULL, NULL}, + }; + + CompileShader(IDR_SHADEBOOST_FX, "ps_main", macro, &m_shadeboost.ps); + // fxaa CompileShader(IDR_FXAA_FX, "ps_main", NULL, &m_fxaa.ps); @@ -860,6 +882,21 @@ void GSDevice9::DoFXAA(GSTexture* st, GSTexture* dt) StretchRect(st, sr, dt, dr, m_fxaa.ps, (const float*)&cb, 2, true); } +void GSDevice9::DoShadeBoost(GSTexture* st, GSTexture* dt) +{ + GSVector2i s = dt->GetSize(); + + GSVector4 sr(0, 0, 1, 1); + GSVector4 dr(0, 0, s.x, s.y); + + ShadeBoostConstantBuffer cb; + + cb.rcpFrame = GSVector4(1.0f / s.x, 1.0f / s.y, 0.0f, 0.0f); + cb.rcpFrameOpt = GSVector4::zero(); + + StretchRect(st, sr, dt, dr, m_shadeboost.ps, (const float*)&cb, 1, true); +} + void GSDevice9::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vertices, bool datm) { const GSVector2i& size = rt->GetSize(); diff --git a/plugins/GSdx/GSDevice9.h b/plugins/GSdx/GSDevice9.h index 319e063d0..1c7c7d8c9 100644 --- a/plugins/GSdx/GSDevice9.h +++ b/plugins/GSdx/GSDevice9.h @@ -72,6 +72,7 @@ class GSDevice9 : public GSDeviceDX void DoMerge(GSTexture* st[2], GSVector4* sr, GSTexture* dt, GSVector4* dr, bool slbg, bool mmod, const GSVector4& c); void DoInterlace(GSTexture* st, GSTexture* dt, int shader, bool linear, float yoffset = 0); void DoFXAA(GSTexture* st, GSTexture* dt); + void DoShadeBoost(GSTexture* st, GSTexture* dt); // @@ -139,6 +140,11 @@ public: // TODO CComPtr ps; } m_fxaa; + struct + { + CComPtr ps; + } m_shadeboost; + struct { Direct3DDepthStencilState9 dss; diff --git a/plugins/GSdx/GSRenderer.cpp b/plugins/GSdx/GSRenderer.cpp index a23ad6174..2d11c33e5 100644 --- a/plugins/GSdx/GSRenderer.cpp +++ b/plugins/GSdx/GSRenderer.cpp @@ -35,6 +35,7 @@ GSRenderer::GSRenderer() m_aa1 = !!theApp.GetConfig("aa1", 0); m_mipmap = !!theApp.GetConfig("mipmap", 1); m_fxaa = !!theApp.GetConfig("fxaa", 0); + m_shadeboost = !!theApp.GetConfig("ShadeBoost", 0); } GSRenderer::~GSRenderer() @@ -254,6 +255,11 @@ bool GSRenderer::Merge(int field) m_dev->Interlace(ds, field ^ field2, mode, tex[1] ? tex[1]->GetScale().y : tex[0]->GetScale().y); } + if(m_shadeboost) + { + m_dev->ShadeBoost(); + } + if(m_fxaa) { m_dev->FXAA(); diff --git a/plugins/GSdx/GSRenderer.h b/plugins/GSdx/GSRenderer.h index 8f9db7ba1..caff24478 100644 --- a/plugins/GSdx/GSRenderer.h +++ b/plugins/GSdx/GSRenderer.h @@ -44,6 +44,7 @@ protected: bool m_mipmap; bool m_framelimit; bool m_fxaa; + bool m_shadeboost; virtual GSTexture* GetOutput(int i) = 0; diff --git a/plugins/GSdx/GSSettingsDlg.cpp b/plugins/GSdx/GSSettingsDlg.cpp index 8d723db9d..3bc1ae7b4 100644 --- a/plugins/GSdx/GSSettingsDlg.cpp +++ b/plugins/GSdx/GSSettingsDlg.cpp @@ -110,6 +110,10 @@ void GSSettingsDlg::OnInit() CheckDlgButton(m_hWnd, IDC_ALPHAHACK, theApp.GetConfig("UserHacks_AlphaHack", 0)); CheckDlgButton(m_hWnd, IDC_OFFSETHACK, theApp.GetConfig("UserHacks_HalfPixelOffset", 0)); CheckDlgButton(m_hWnd, IDC_SPRITEHACK, theApp.GetConfig("UserHacks_SpriteHack", 0)); + + // Shade Boost + CheckDlgButton(m_hWnd, IDC_SHADEBOOST, theApp.GetConfig("ShadeBoost", 0)); + SendMessage(GetDlgItem(m_hWnd, IDC_SKIPDRAWHACK), UDM_SETRANGE, 0, MAKELPARAM(1000, 0)); SendMessage(GetDlgItem(m_hWnd, IDC_SKIPDRAWHACK), UDM_SETPOS, 0, MAKELPARAM(theApp.GetConfig("UserHacks_SkipDraw", 0), 0)); @@ -220,6 +224,14 @@ bool GSSettingsDlg::OnCommand(HWND hWnd, UINT id, UINT code) { UpdateControls(); } + else if(id == IDC_SHADEBOOST && code == BN_CLICKED) + { + UpdateControls(); + } + else if(id == IDC_SHADEBUTTON && code == BN_CLICKED) + { + ShadeBoostDlg.DoModal(); + } else if(id == IDOK) { INT_PTR data; @@ -278,6 +290,9 @@ bool GSSettingsDlg::OnCommand(HWND hWnd, UINT id, UINT code) theApp.SetConfig("UserHacks_HalfPixelOffset", (int)IsDlgButtonChecked(m_hWnd, IDC_OFFSETHACK)); theApp.SetConfig("UserHacks_SpriteHack", (int)IsDlgButtonChecked(m_hWnd, IDC_SPRITEHACK)); theApp.SetConfig("UserHacks_SkipDraw", (int)SendMessage(GetDlgItem(m_hWnd, IDC_SKIPDRAWHACK), UDM_GETPOS, 0, 0)); + + // Shade Boost + theApp.SetConfig("ShadeBoost", (int)IsDlgButtonChecked(m_hWnd, IDC_SHADEBOOST)); } return __super::OnCommand(hWnd, id, code); @@ -326,6 +341,9 @@ void GSSettingsDlg::UpdateControls() EnableWindow(GetDlgItem(m_hWnd, IDC_MSAAEDIT), hw); EnableWindow(GetDlgItem(m_hWnd, IDC_MSAA), hw); + // Shade Boost + EnableWindow(GetDlgItem(m_hWnd, IDC_SHADEBUTTON), IsDlgButtonChecked(m_hWnd, IDC_SHADEBOOST) == BST_CHECKED); + //ShowWindow(GetDlgItem(m_hWnd, IDC_USERHACKS), allowHacks && hw) ? SW_SHOW : SW_HIDE; //Don't disable the "Hacks" frame ShowWindow(GetDlgItem(m_hWnd, IDC_HACKDISABLED), !(allowHacks && hw)) ? SW_SHOW : SW_HIDE; ShowWindow(GetDlgItem(m_hWnd, IDC_MSAAEDIT), allowHacks && hw) ? SW_SHOW : SW_HIDE; @@ -341,3 +359,110 @@ void GSSettingsDlg::UpdateControls() ShowWindow(GetDlgItem(m_hWnd, IDC_STATIC_TEXT_SKIPDRAW), allowHacks && hw) ? SW_SHOW : SW_HIDE; } } + + +GSShadeBostDlg::GSShadeBostDlg() : + GSDialog(IDD_SHADEBOOST) +{} + + +void GSShadeBostDlg::OnInit() +{ + contrast = theApp.GetConfig("ShadeBoost_Contrast", 50); + brightness = theApp.GetConfig("ShadeBoost_Brightness", 50); + saturation = theApp.GetConfig("ShadeBoost_Saturation", 50); + + UpdateControls(); +} + +void GSShadeBostDlg::UpdateControls() +{ + SendMessage(GetDlgItem(m_hWnd, IDC_SATURATION_SLIDER), TBM_SETRANGE, TRUE, MAKELONG(0, 100)); + SendMessage(GetDlgItem(m_hWnd, IDC_BRIGHTNESS_SLIDER), TBM_SETRANGE, TRUE, MAKELONG(0, 100)); + SendMessage(GetDlgItem(m_hWnd, IDC_CONTRAST_SLIDER), TBM_SETRANGE, TRUE, MAKELONG(0, 100)); + + SendMessage(GetDlgItem(m_hWnd, IDC_SATURATION_SLIDER), TBM_SETPOS, TRUE, saturation); + SendMessage(GetDlgItem(m_hWnd, IDC_BRIGHTNESS_SLIDER), TBM_SETPOS, TRUE, brightness); + SendMessage(GetDlgItem(m_hWnd, IDC_CONTRAST_SLIDER), TBM_SETPOS, TRUE, contrast); + + char text[8] = {0}; + + sprintf(text, "%d", saturation); + SetDlgItemText(m_hWnd, IDC_SATURATION_TEXT, text); + sprintf(text, "%d", brightness); + SetDlgItemText(m_hWnd, IDC_BRIGHTNESS_TEXT, text); + sprintf(text, "%d", contrast); + SetDlgItemText(m_hWnd, IDC_CONTRAST_TEXT, text); +} + + +bool GSShadeBostDlg::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) +{ + + switch(message) + { + case WM_HSCROLL: + { + if((HWND)lParam == GetDlgItem(m_hWnd, IDC_SATURATION_SLIDER)) + { + char text[8] = {0}; + + saturation = SendMessage(GetDlgItem(m_hWnd, IDC_SATURATION_SLIDER),TBM_GETPOS,0,0); + + sprintf(text, "%d", saturation); + SetDlgItemText(m_hWnd, IDC_SATURATION_TEXT, text); + } + else if((HWND)lParam == GetDlgItem(m_hWnd, IDC_BRIGHTNESS_SLIDER)) + { + char text[8] = {0}; + + brightness = SendMessage(GetDlgItem(m_hWnd, IDC_BRIGHTNESS_SLIDER),TBM_GETPOS,0,0); + + sprintf(text, "%d", brightness); + SetDlgItemText(m_hWnd, IDC_BRIGHTNESS_TEXT, text); + } + else if((HWND)lParam == GetDlgItem(m_hWnd, IDC_CONTRAST_SLIDER)) + { + char text[8] = {0}; + + contrast = SendMessage(GetDlgItem(m_hWnd, IDC_CONTRAST_SLIDER),TBM_GETPOS,0,0); + + sprintf(text, "%d", contrast); + SetDlgItemText(m_hWnd, IDC_CONTRAST_TEXT, text); + } + } break; + + case WM_COMMAND: + { + int id = LOWORD(wParam); + + switch(id) + { + case IDOK: + { + theApp.SetConfig("ShadeBoost_Contrast", contrast); + theApp.SetConfig("ShadeBoost_Brightness", brightness); + theApp.SetConfig("ShadeBoost_Saturation", saturation); + EndDialog(m_hWnd, id); + } break; + + case IDRESET: + { + contrast = 50; + brightness = 50; + saturation = 50; + + UpdateControls(); + } break; + } + + } break; + + case WM_CLOSE:EndDialog(m_hWnd, IDCANCEL); break; + + default: return false; + } + + + return true; +} \ No newline at end of file diff --git a/plugins/GSdx/GSSettingsDlg.h b/plugins/GSdx/GSSettingsDlg.h index 9cb7c60d5..95589dc09 100644 --- a/plugins/GSdx/GSSettingsDlg.h +++ b/plugins/GSdx/GSSettingsDlg.h @@ -24,6 +24,22 @@ #include "GSDialog.h" #include "GSSetting.h" +class GSShadeBostDlg : public GSDialog +{ + int saturation; + int brightness; + int contrast; + + void UpdateControls(); + +protected: + void OnInit(); + bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam); + +public: + GSShadeBostDlg(); +}; + class GSSettingsDlg : public GSDialog { list m_modes; @@ -37,6 +53,9 @@ protected: uint32 m_lastValidMsaa; // used to revert to previous dialog value if the user changed to invalid one, or lesser one and canceled + // Shade Boost + GSShadeBostDlg ShadeBoostDlg; + public: GSSettingsDlg(bool isOpen2); }; diff --git a/plugins/GSdx/GSdx.rc b/plugins/GSdx/GSdx.rc index dadfc1de6..a022d1a66 100644 --- a/plugins/GSdx/GSdx.rc +++ b/plugins/GSdx/GSdx.rc @@ -42,6 +42,7 @@ BEGIN "#include ""res/interlace.fx""\r\n" "#include ""res/merge.fx""\r\0" "#include ""res/fxaa.fx""\r\0" + "#include ""res/shadeboost.fx""\r\0" END #endif // APSTUDIO_INVOKED @@ -58,6 +59,7 @@ IDR_MERGE_FX RCDATA "res\\merge.fx" IDR_INTERLACE_FX RCDATA "res\\interlace.fx" IDR_FXAA_FX RCDATA "res\\fxaa.fx" IDR_CS_FX RCDATA "res\\cs.fx" +IDR_SHADEBOOST_FX RCDATA "res\\shadeboost.fx" ///////////////////////////////////////////////////////////////////////////// // @@ -72,7 +74,26 @@ IDB_LOGO10 BITMAP "res\\logo10.bmp" // Dialog // -IDD_CONFIG DIALOGEX 0, 0, 189, 327 +IDD_SHADEBOOST DIALOGEX 0, 0, 316, 129 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Shade Boost Settings" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,259,108,50,14 + PUSHBUTTON "Reset",IDRESET,7,108,50,14 + GROUPBOX "Color Adjustments",IDC_STATIC,7,7,302,95 + LTEXT "Saturation",IDC_STATIC,15,25,34,8 + CONTROL "",IDC_SATURATION_SLIDER,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,55,23,236,15 + LTEXT "Brightness",IDC_STATIC,15,50,34,8 + CONTROL "",IDC_BRIGHTNESS_SLIDER,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,55,48,236,15 + LTEXT "Contrast",IDC_STATIC,15,75,29,8 + CONTROL "",IDC_CONTRAST_SLIDER,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,55,72,236,15 + RTEXT "100",IDC_SATURATION_TEXT,288,25,15,8 + RTEXT "100",IDC_BRIGHTNESS_TEXT,288,50,15,8 + RTEXT "100",IDC_CONTRAST_TEXT,288,75,15,8 +END + +IDD_CONFIG DIALOGEX 0, 0, 189, 337 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Settings..." FONT 8, "MS Shell Dlg", 400, 0, 0x1 @@ -87,9 +108,9 @@ BEGIN COMBOBOX IDC_INTERLACE,71,86,111,98,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Aspect Ratio (F6):",IDC_STATIC,7,104,60,8 COMBOBOX IDC_ASPECTRATIO,71,101,111,98,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - DEFPUSHBUTTON "OK",IDOK,43,303,50,14 - PUSHBUTTON "Cancel",IDCANCEL,96,303,50,14 - CONTROL "Windowed",IDC_WINDOWED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,89,231,93,10 + DEFPUSHBUTTON "OK",IDOK,43,316,50,14 + PUSHBUTTON "Cancel",IDCANCEL,96,316,50,14 + CONTROL "Windowed",IDC_WINDOWED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,89,244,93,10 LTEXT "D3D internal res:",IDC_STATIC,18,135,55,8 EDITTEXT IDC_RESX_EDIT,82,132,35,13,ES_AUTOHSCROLL | ES_NUMBER CONTROL "",IDC_RESX,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,110,135,11,14 @@ -99,26 +120,28 @@ BEGIN COMBOBOX IDC_UPSCALE_MULTIPLIER,82,147,74,98,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Or use Scaling:",IDC_STATIC,18,150,49,8 LTEXT "Or use original PS2 resolution :",IDC_STATIC,18,165,99,8 - EDITTEXT IDC_MSAAEDIT,45,259,35,13,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_MSAA,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,76,261,11,14 - LTEXT "HW AA",IDC_STATIC_TEXT_HWAA,18,261,24,8 + EDITTEXT IDC_MSAAEDIT,45,272,35,13,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_MSAA,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,76,274,11,14 + LTEXT "HW AA",IDC_STATIC_TEXT_HWAA,18,274,24,8 GROUPBOX "D3D Enhancements (can cause glitches)",IDC_STATIC,7,117,175,66 - LTEXT "Extra rendering threads:",IDC_STATIC,7,189,80,8 - EDITTEXT IDC_SWTHREADS_EDIT,89,187,35,13,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_SWTHREADS,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,117,190,11,14 - CONTROL "Texture filtering",IDC_FILTER,"Button",BS_AUTO3STATE | WS_TABSTOP,7,203,67,10 - CONTROL "Logarithmic Z",IDC_LOGZ,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,89,204,58,10 - CONTROL "Allow 8-bit textures",IDC_PALTEX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,217,82,10 - CONTROL "Alpha correction (FBA)",IDC_FBA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,89,217,93,10 - CONTROL "Edge anti-aliasing",IDC_AA1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,231,72,10 - CONTROL "Alpha Hack",IDC_ALPHAHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,280,51,10 - CONTROL "Offset Hack",IDC_OFFSETHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,67,280,51,10 - GROUPBOX "Hacks",IDC_USERHACKS,7,244,175,53,BS_CENTER - EDITTEXT IDC_SKIPDRAWHACKEDIT,122,259,40,14,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_SKIPDRAWHACK,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,161,261,11,14 - LTEXT "SkipDraw:",IDC_STATIC_TEXT_SKIPDRAW,89,261,33,8 - CONTROL "Sprite Hack",IDC_SPRITEHACK,"Button",BS_AUTO3STATE | WS_TABSTOP,123,280,51,10 - LTEXT "HACKS DISABLED",IDC_HACKDISABLED,64,268,57,8,WS_DISABLED + LTEXT "Extra rendering threads:",IDC_STATIC,7,202,80,8 + EDITTEXT IDC_SWTHREADS_EDIT,89,200,35,13,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_SWTHREADS,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,117,203,11,14 + CONTROL "Texture filtering",IDC_FILTER,"Button",BS_AUTO3STATE | WS_TABSTOP,7,216,67,10 + CONTROL "Logarithmic Z",IDC_LOGZ,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,89,217,58,10 + CONTROL "Allow 8-bit textures",IDC_PALTEX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,230,82,10 + CONTROL "Alpha correction (FBA)",IDC_FBA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,89,230,93,10 + CONTROL "Edge anti-aliasing",IDC_AA1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,244,72,10 + CONTROL "Alpha Hack",IDC_ALPHAHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,293,51,10 + CONTROL "Offset Hack",IDC_OFFSETHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,67,293,51,10 + GROUPBOX "Hacks",IDC_USERHACKS,7,257,175,53,BS_CENTER + EDITTEXT IDC_SKIPDRAWHACKEDIT,122,272,40,14,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_SKIPDRAWHACK,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,161,274,11,14 + LTEXT "SkipDraw:",IDC_STATIC_TEXT_SKIPDRAW,89,274,33,8 + CONTROL "Sprite Hack",IDC_SPRITEHACK,"Button",BS_AUTO3STATE | WS_TABSTOP,123,293,51,10 + LTEXT "HACKS DISABLED",IDC_HACKDISABLED,64,281,57,8,WS_DISABLED + CONTROL "Enable Shade Boost",IDC_SHADEBOOST,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,187,79,10 + PUSHBUTTON "Settings...",IDC_SHADEBUTTON,88,184,94,14 END IDD_CAPTURE DIALOGEX 0, 0, 279, 71 @@ -165,13 +188,13 @@ BEGIN CONTROL "Windowed",IDC_WINDOWED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,129,157,49,10 END -IDD_CONFIG2 DIALOGEX 0, 0, 187, 325 +IDD_CONFIG2 DIALOGEX 0, 0, 187, 342 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Settings..." FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN CONTROL 2022,IDC_LOGO11,"Static",SS_BITMAP,6,6,173,42 - DEFPUSHBUTTON "OK",IDOK,41,301,50,14 + DEFPUSHBUTTON "OK",IDOK,41,320,50,14 LTEXT "Renderer:",IDC_STATIC,6,57,34,8 COMBOBOX IDC_RENDERER,70,55,111,118,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Interlacing (F5):",IDC_STATIC,6,73,81,8 @@ -182,33 +205,35 @@ BEGIN EDITTEXT IDC_RESY_EDIT,130,132,35,13,ES_AUTOHSCROLL | ES_NUMBER CONTROL "",IDC_RESY,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,154,130,11,14 CONTROL "Native",IDC_NATIVERES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,92,105,33,10 - LTEXT "Extra rendering threads:",IDC_STATIC,11,214,80,8 - EDITTEXT IDC_SWTHREADS_EDIT,94,212,35,13,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_SWTHREADS,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,127,215,11,14 + LTEXT "Extra rendering threads:",IDC_STATIC,11,233,80,8 + EDITTEXT IDC_SWTHREADS_EDIT,94,231,35,13,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_SWTHREADS,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,127,234,11,14 COMBOBOX IDC_UPSCALE_MULTIPLIER,92,117,74,98,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Or use Scaling:",IDC_STATIC,38,119,49,8 LTEXT "Original PS2 resolution :",IDC_STATIC,10,105,80,8 - CONTROL "Edge anti-aliasing (AA1)",IDC_AA1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,230,93,10 - PUSHBUTTON "Cancel",IDCANCEL,95,301,50,14 + CONTROL "Edge anti-aliasing (AA1)",IDC_AA1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,249,93,10 + PUSHBUTTON "Cancel",IDCANCEL,95,320,50,14 CONTROL 2021,IDC_LOGO9,"Static",SS_BITMAP,6,6,175,44 - CONTROL "Alpha Hack",IDC_ALPHAHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,279,51,10 - CONTROL "Offset Hack",IDC_OFFSETHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,65,279,51,10 - GROUPBOX "Hacks",IDC_USERHACKS,6,250,175,45,BS_CENTER - EDITTEXT IDC_SKIPDRAWHACKEDIT,125,260,40,14,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_SKIPDRAWHACK,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,164,262,11,14 - LTEXT "Skipdraw",IDC_STATIC_TEXT_SKIPDRAW,93,262,30,8 - EDITTEXT IDC_MSAAEDIT,38,260,35,13,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_MSAA,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,72,263,11,14 + CONTROL "Alpha Hack",IDC_ALPHAHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,298,51,10 + CONTROL "Offset Hack",IDC_OFFSETHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,65,298,51,10 + GROUPBOX "Hacks",IDC_USERHACKS,6,269,175,45,BS_CENTER + EDITTEXT IDC_SKIPDRAWHACKEDIT,125,279,40,14,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_SKIPDRAWHACK,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,164,281,11,14 + LTEXT "Skipdraw",IDC_STATIC_TEXT_SKIPDRAW,93,281,30,8 + EDITTEXT IDC_MSAAEDIT,38,279,35,13,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_MSAA,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,72,282,11,14 GROUPBOX "D3D Internal resolution (can cause glitches)",IDC_STATIC,6,87,175,64,BS_CENTER - GROUPBOX "Software Mode Settings",IDC_STATIC,6,198,175,50,BS_CENTER - GROUPBOX "Hardware Mode Settings",IDC_STATIC,6,152,175,45,BS_CENTER - CONTROL "Logarithmic Z",IDC_LOGZ,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,92,166,58,10 - CONTROL "Alpha correction (FBA)",IDC_FBA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,92,179,87,10 - CONTROL "Allow 8-bit textures",IDC_PALTEX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,179,82,10 - CONTROL "Texture filtering",IDC_FILTER,"Button",BS_AUTO3STATE | WS_TABSTOP,10,165,67,10 - LTEXT "HW AA",IDC_STATIC_TEXT_HWAA,11,262,24,8 - CONTROL "Sprite Hack",IDC_SPRITEHACK,"Button",BS_AUTO3STATE | WS_TABSTOP,125,279,51,10 - LTEXT "HACKS DISABLED",IDC_HACKDISABLED,62,268,57,8,WS_DISABLED + GROUPBOX "Software Mode Settings",IDC_STATIC,6,217,175,50,BS_CENTER + GROUPBOX "Hardware Mode Settings",IDC_STATIC,6,171,175,45,BS_CENTER + CONTROL "Logarithmic Z",IDC_LOGZ,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,92,185,58,10 + CONTROL "Alpha correction (FBA)",IDC_FBA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,92,198,87,10 + CONTROL "Allow 8-bit textures",IDC_PALTEX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,198,82,10 + CONTROL "Texture filtering",IDC_FILTER,"Button",BS_AUTO3STATE | WS_TABSTOP,10,184,67,10 + LTEXT "HW AA",IDC_STATIC_TEXT_HWAA,11,281,24,8 + CONTROL "Sprite Hack",IDC_SPRITEHACK,"Button",BS_AUTO3STATE | WS_TABSTOP,125,298,51,10 + LTEXT "HACKS DISABLED",IDC_HACKDISABLED,62,287,57,8,WS_DISABLED + CONTROL "Enable Shade Boost",IDC_SHADEBOOST,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,157,79,10 + PUSHBUTTON "Settings...",IDC_SHADEBUTTON,95,154,75,14 END @@ -228,7 +253,7 @@ BEGIN VERTGUIDE, 89 VERTGUIDE, 182 TOPMARGIN, 7 - BOTTOMMARGIN, 320 + BOTTOMMARGIN, 330 HORZGUIDE, 49 END @@ -256,7 +281,15 @@ BEGIN RIGHTMARGIN, 181 VERTGUIDE, 87 TOPMARGIN, 6 - BOTTOMMARGIN, 318 + BOTTOMMARGIN, 335 + END + + IDD_SHADEBOOST, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 309 + TOPMARGIN, 7 + BOTTOMMARGIN, 122 END END #endif // APSTUDIO_INVOKED diff --git a/plugins/GSdx/GSdx.vcxproj b/plugins/GSdx/GSdx.vcxproj index fb69ea004..c297ee967 100644 --- a/plugins/GSdx/GSdx.vcxproj +++ b/plugins/GSdx/GSdx.vcxproj @@ -1680,6 +1680,7 @@ + diff --git a/plugins/GSdx/GSdx.vcxproj.filters b/plugins/GSdx/GSdx.vcxproj.filters index a2bc719e2..e0bb32e28 100644 --- a/plugins/GSdx/GSdx.vcxproj.filters +++ b/plugins/GSdx/GSdx.vcxproj.filters @@ -674,6 +674,9 @@ Shaders + + Shaders + diff --git a/plugins/GSdx/GSdx_vs2008.vcproj b/plugins/GSdx/GSdx_vs2008.vcproj index 30da18704..09f70dc5f 100644 --- a/plugins/GSdx/GSdx_vs2008.vcproj +++ b/plugins/GSdx/GSdx_vs2008.vcproj @@ -1708,6 +1708,10 @@ RelativePath=".\res\merge.fx" > + + diff --git a/plugins/GSdx/res/shadeboost.fx b/plugins/GSdx/res/shadeboost.fx new file mode 100644 index 000000000..c7ce538b0 --- /dev/null +++ b/plugins/GSdx/res/shadeboost.fx @@ -0,0 +1,71 @@ +#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency + +float4 ConvertYUV(float4 color) +{ + float4 color2 = color; + + float fSat = SB_SATURATION / 100.0; + float fBrt = SB_BRIGHTNESS / 100.0; + float fCont = SB_CONTRAST / 100.0; + + float gY = color.r*0.299+color.g*0.587+color.b*0.114; + float gCr = ( color.r-gY )*0.713*(0.5+fSat); + float gCb = ( color.b-gY )*0.565*(0.5+fSat); + + gY = gY*(0.5+fCont); + + color2.r = gY + 1.40252*gCr; + color2.g = gY - 0.714403*gCr - 0.343731*gCb; + color2.b = gY + 1.76991*gCb; + + color2.r = color2.r*(0.5+fBrt); + color2.g = color2.g*(0.5+fBrt); + color2.b = color2.b*(0.5+fBrt); + + return color2; +} + +#if SHADER_MODEL >= 0x400 + +Texture2D Texture; +SamplerState Sampler; + +cbuffer cb0 +{ + float4 BGColor; +}; + +struct PS_INPUT +{ + float4 p : SV_Position; + float2 t : TEXCOORD0; +}; + +float4 ps_main(PS_INPUT input) : SV_Target0 +{ + float4 c = Texture.Sample(Sampler, input.t); + return ConvertYUV(c); +} + + +#elif SHADER_MODEL <= 0x300 + +sampler Texture : register(s0); + +float4 g_params[1]; + +#define BGColor (g_params[0]) + +struct PS_INPUT +{ + float2 t : TEXCOORD0; +}; + +float4 ps_main(PS_INPUT input) : COLOR +{ + float4 c = tex2D(Texture, input.t); + return ConvertYUV(c); +} + +#endif +#endif \ No newline at end of file diff --git a/plugins/GSdx/resource.h b/plugins/GSdx/resource.h index 884f58900..ed2799f09 100644 --- a/plugins/GSdx/resource.h +++ b/plugins/GSdx/resource.h @@ -76,6 +76,15 @@ #define IDC_STATIC10 2049 #define IDC_HACKDISABLED 2050 #define IDC_SPRITEHACK 2051 +#define IDRESET 2052 +#define IDC_SATURATION_SLIDER 2053 +#define IDC_BRIGHTNESS_SLIDER 2055 +#define IDC_CONTRAST_SLIDER 2056 +#define IDC_SHADEBUTTON 2058 +#define IDC_SHADEBOOST 2059 +#define IDC_SATURATION_TEXT 2061 +#define IDC_BRIGHTNESS_TEXT 2062 +#define IDC_CONTRAST_TEXT 2063 #define IDC_COLORSPACE 3000 #define IDR_CONVERT_FX 10000 #define IDR_TFX_FX 10001 @@ -83,15 +92,17 @@ #define IDR_INTERLACE_FX 10003 #define IDD_CONFIG2 10004 #define IDR_FXAA_FX 10005 -#define IDR_CS_FX 10006 +#define IDR_CS_FX 10006 +#define IDD_SHADEBOOST 10007 +#define IDR_SHADEBOOST_FX 10009 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 10007 +#define _APS_NEXT_RESOURCE_VALUE 10011 #define _APS_NEXT_COMMAND_VALUE 32771 -#define _APS_NEXT_CONTROL_VALUE 2052 +#define _APS_NEXT_CONTROL_VALUE 2064 #define _APS_NEXT_SYMED_VALUE 5000 #endif #endif From be4b7b1768447eecf621cd96399af072ab74dc24 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Wed, 29 Feb 2012 13:19:36 +0000 Subject: [PATCH 19/83] GSdx: Use the simpler psmain0 shader in convert.fx for ShadeBoost. Thanks KrossX :) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5111 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSDevice.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/GSdx/GSDevice.cpp b/plugins/GSdx/GSDevice.cpp index bda55c561..348af8b68 100644 --- a/plugins/GSdx/GSDevice.cpp +++ b/plugins/GSdx/GSDevice.cpp @@ -336,7 +336,7 @@ void GSDevice::ShadeBoost() GSVector4 sr(0, 0, 1, 1); GSVector4 dr(0, 0, s.x, s.y); - StretchRect(m_current, sr, m_shadeboost, dr, 7, false); + StretchRect(m_current, sr, m_shadeboost, dr, 0, false); DoShadeBoost(m_shadeboost, m_current); } } From 52a54fda62e4dc51322f4b4f61cae91805d30363 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Wed, 29 Feb 2012 14:51:55 +0000 Subject: [PATCH 20/83] Null pointer protection and warning in LilyPad and SPU2-X savestates and a small init fix in SPU2-X. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5112 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/LilyPad/LilyPad.cpp | 8 +++++++- plugins/spu2-x/src/PS2E-spu2.cpp | 15 +++++++++++++-- plugins/spu2-x/src/spu2sys.cpp | 2 +- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/plugins/LilyPad/LilyPad.cpp b/plugins/LilyPad/LilyPad.cpp index 7a52f656e..72bf53b5d 100644 --- a/plugins/LilyPad/LilyPad.cpp +++ b/plugins/LilyPad/LilyPad.cpp @@ -1428,7 +1428,13 @@ struct PadPluginFreezeData { }; s32 CALLBACK PADfreeze(int mode, freezeData *data) { - if (mode == FREEZE_SIZE) { + if (!data) + { + printf("LilyPad savestate null pointer!\n"); + return -1; + } + + if (mode == FREEZE_SIZE) { data->size = sizeof(PadPluginFreezeData); } else if (mode == FREEZE_LOAD) { diff --git a/plugins/spu2-x/src/PS2E-spu2.cpp b/plugins/spu2-x/src/PS2E-spu2.cpp index bfdb9e848..eeba13ebf 100644 --- a/plugins/spu2-x/src/PS2E-spu2.cpp +++ b/plugins/spu2-x/src/PS2E-spu2.cpp @@ -656,6 +656,13 @@ EXPORT_C_(int) SPU2setupRecording(int start, void* pData) EXPORT_C_(s32) SPU2freeze(int mode, freezeData *data) { + jASSUME( data != NULL ); + if ( !data ) + { + printf("SPU2-X savestate null pointer!\n"); + return -1; + } + if( mode == FREEZE_SIZE ) { data->size = Savestate::SizeIt(); @@ -663,9 +670,13 @@ EXPORT_C_(s32) SPU2freeze(int mode, freezeData *data) } jASSUME( mode == FREEZE_LOAD || mode == FREEZE_SAVE ); - jASSUME( data != NULL ); - if( data->data == NULL ) return -1; + if( data->data == NULL ) + { + printf("SPU2-X savestate null pointer!\n"); + return -1; + } + Savestate::DataBlock& spud = (Savestate::DataBlock&)*(data->data); switch( mode ) diff --git a/plugins/spu2-x/src/spu2sys.cpp b/plugins/spu2-x/src/spu2sys.cpp index ce9b10bd7..84e3c37f7 100644 --- a/plugins/spu2-x/src/spu2sys.cpp +++ b/plugins/spu2-x/src/spu2sys.cpp @@ -134,7 +134,7 @@ void V_Core::Init( int index ) if (!c) { WetGate.ExtL = 0; - WetGate.ExtL = 0; + WetGate.ExtR = 0; } Regs.MMIX = c ? 0xFFC : 0xFF0; // PS2 confirmed (f3c and f30 after BIOS ran, ffc and ff0 after sdinit) From 886c23a4ee0715b64b65b0d2850ae7d3948a216f Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Wed, 29 Feb 2012 15:49:01 +0000 Subject: [PATCH 21/83] GSdx: Better working shader for the new color settings. Taken from "TGM's shader pack" on http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=21057 git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5113 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/res/shadeboost.fx | 51 +++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/plugins/GSdx/res/shadeboost.fx b/plugins/GSdx/res/shadeboost.fx index c7ce538b0..929038ade 100644 --- a/plugins/GSdx/res/shadeboost.fx +++ b/plugins/GSdx/res/shadeboost.fx @@ -1,28 +1,33 @@ #ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency -float4 ConvertYUV(float4 color) +/* +** Contrast, saturation, brightness +** Code of this function is from TGM's shader pack +** http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=21057 +*/ + +// For all settings: 1.0 = 100% 0.5=50% 1.5 = 150% +float4 ContrastSaturationBrightness(float4 color) // Ported to HLSL { - float4 color2 = color; + const float sat = SB_SATURATION / 50.0; + const float brt = SB_BRIGHTNESS / 50.0; + const float con = SB_CONTRAST / 50.0; + + // Increase or decrease theese values to adjust r, g and b color channels seperately + const float AvgLumR = 0.5; + const float AvgLumG = 0.5; + const float AvgLumB = 0.5; + + const float3 LumCoeff = float3(0.2125, 0.7154, 0.0721); + + float3 AvgLumin = float3(AvgLumR, AvgLumG, AvgLumB); + float3 brtColor = color.rgb * brt; + float3 intensity = dot(brtColor, LumCoeff); + float3 satColor = lerp(intensity, brtColor, sat); + float3 conColor = lerp(AvgLumin, satColor, con); - float fSat = SB_SATURATION / 100.0; - float fBrt = SB_BRIGHTNESS / 100.0; - float fCont = SB_CONTRAST / 100.0; - - float gY = color.r*0.299+color.g*0.587+color.b*0.114; - float gCr = ( color.r-gY )*0.713*(0.5+fSat); - float gCb = ( color.b-gY )*0.565*(0.5+fSat); - - gY = gY*(0.5+fCont); - - color2.r = gY + 1.40252*gCr; - color2.g = gY - 0.714403*gCr - 0.343731*gCb; - color2.b = gY + 1.76991*gCb; - - color2.r = color2.r*(0.5+fBrt); - color2.g = color2.g*(0.5+fBrt); - color2.b = color2.b*(0.5+fBrt); - - return color2; + color.rgb = conColor; + return color; } #if SHADER_MODEL >= 0x400 @@ -44,7 +49,7 @@ struct PS_INPUT float4 ps_main(PS_INPUT input) : SV_Target0 { float4 c = Texture.Sample(Sampler, input.t); - return ConvertYUV(c); + return ContrastSaturationBrightness(c); } @@ -64,7 +69,7 @@ struct PS_INPUT float4 ps_main(PS_INPUT input) : COLOR { float4 c = tex2D(Texture, input.t); - return ConvertYUV(c); + return ContrastSaturationBrightness(c); } #endif From 2c96d8cf446c5a9c1c8da85c5dafa4a71b196037 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Tue, 6 Mar 2012 18:28:59 +0000 Subject: [PATCH 22/83] GSdx: Attempt to fix the resource files so MSVC likes them again. There's still line ending inconsistencies in the .rc though. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5115 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSdx.rc | 20 ++++++++++---------- plugins/GSdx/resource.h | 8 ++++---- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/plugins/GSdx/GSdx.rc b/plugins/GSdx/GSdx.rc index a022d1a66..e21e66578 100644 --- a/plugins/GSdx/GSdx.rc +++ b/plugins/GSdx/GSdx.rc @@ -42,7 +42,7 @@ BEGIN "#include ""res/interlace.fx""\r\n" "#include ""res/merge.fx""\r\0" "#include ""res/fxaa.fx""\r\0" - "#include ""res/shadeboost.fx""\r\0" + "#include ""res/shadeboost.fx""\r\0" END #endif // APSTUDIO_INVOKED @@ -58,7 +58,7 @@ IDR_TFX_FX RCDATA "res\\tfx.fx" IDR_MERGE_FX RCDATA "res\\merge.fx" IDR_INTERLACE_FX RCDATA "res\\interlace.fx" IDR_FXAA_FX RCDATA "res\\fxaa.fx" -IDR_CS_FX RCDATA "res\\cs.fx" +IDR_CS_FX RCDATA "res\\cs.fx" IDR_SHADEBOOST_FX RCDATA "res\\shadeboost.fx" ///////////////////////////////////////////////////////////////////////////// @@ -245,6 +245,14 @@ END #ifdef APSTUDIO_INVOKED GUIDELINES DESIGNINFO BEGIN + IDD_SHADEBOOST, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 309 + TOPMARGIN, 7 + BOTTOMMARGIN, 122 + END + IDD_CONFIG, DIALOG BEGIN LEFTMARGIN, 7 @@ -283,14 +291,6 @@ BEGIN TOPMARGIN, 6 BOTTOMMARGIN, 335 END - - IDD_SHADEBOOST, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 309 - TOPMARGIN, 7 - BOTTOMMARGIN, 122 - END END #endif // APSTUDIO_INVOKED diff --git a/plugins/GSdx/resource.h b/plugins/GSdx/resource.h index ed2799f09..9c31d6fbf 100644 --- a/plugins/GSdx/resource.h +++ b/plugins/GSdx/resource.h @@ -1,3 +1,7 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by GSdx.rc +// /* * Copyright (C) 2007-2009 Gabest * http://www.gabest.org @@ -19,10 +23,6 @@ * */ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by GSdx.rc -// #define IDC_NATIVERES 2001 #define IDC_VSYNC 2002 #define IDC_PALTEX 2003 From 30e538a3c6444c119bbb8a4d8a22566277559731 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Tue, 6 Mar 2012 19:39:05 +0000 Subject: [PATCH 23/83] GSdx: Team effort of KrossX and myself: Finally adding that special game fixes / hack dialog I talked about for a while. Committing this in several steps to clean up any issues easier. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5116 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSDevice9.cpp | 4 +- plugins/GSdx/GSDeviceDX.cpp | 2 +- plugins/GSdx/GSSettingsDlg.cpp | 231 ++++++++++++++++----------------- plugins/GSdx/GSSettingsDlg.h | 18 +++ plugins/GSdx/GSdx.rc | 142 +++++++++++--------- plugins/GSdx/resource.h | 8 +- 6 files changed, 218 insertions(+), 187 deletions(-) diff --git a/plugins/GSdx/GSDevice9.cpp b/plugins/GSdx/GSDevice9.cpp index ac3eed9ea..f9fc212a4 100644 --- a/plugins/GSdx/GSDevice9.cpp +++ b/plugins/GSdx/GSDevice9.cpp @@ -137,9 +137,9 @@ uint32 GSDevice9::GetMaxDepth(uint32 msaa = 0) void GSDevice9::ForceValidMsaaConfig() { - if(0 == GetMaxDepth(theApp.GetConfig("msaa", 0))) + if(0 == GetMaxDepth(theApp.GetConfig("UserHacks_MSAA", 0))) { - theApp.SetConfig("msaa", 0); // replace invalid msaa value in ini file with 0. + theApp.SetConfig("UserHacks_MSAA", 0); // replace invalid msaa value in ini file with 0. } }; diff --git a/plugins/GSdx/GSDeviceDX.cpp b/plugins/GSdx/GSDeviceDX.cpp index 160e3130d..1165c4671 100644 --- a/plugins/GSdx/GSDeviceDX.cpp +++ b/plugins/GSdx/GSDeviceDX.cpp @@ -25,7 +25,7 @@ GSDeviceDX::GSDeviceDX() { - m_msaa = theApp.GetConfig("msaa", 0); + m_msaa = theApp.GetConfig("UserHacks_MSAA", 0); m_msaa_desc.Count = 1; m_msaa_desc.Quality = 0; diff --git a/plugins/GSdx/GSSettingsDlg.cpp b/plugins/GSdx/GSSettingsDlg.cpp index 3bc1ae7b4..18d65a9f5 100644 --- a/plugins/GSdx/GSSettingsDlg.cpp +++ b/plugins/GSdx/GSSettingsDlg.cpp @@ -106,16 +106,13 @@ void GSSettingsDlg::OnInit() CheckDlgButton(m_hWnd, IDC_FBA, theApp.GetConfig("fba", 1)); CheckDlgButton(m_hWnd, IDC_AA1, theApp.GetConfig("aa1", 0)); CheckDlgButton(m_hWnd, IDC_NATIVERES, theApp.GetConfig("nativeres", 0)); - // Hacks - CheckDlgButton(m_hWnd, IDC_ALPHAHACK, theApp.GetConfig("UserHacks_AlphaHack", 0)); - CheckDlgButton(m_hWnd, IDC_OFFSETHACK, theApp.GetConfig("UserHacks_HalfPixelOffset", 0)); - CheckDlgButton(m_hWnd, IDC_SPRITEHACK, theApp.GetConfig("UserHacks_SpriteHack", 0)); // Shade Boost CheckDlgButton(m_hWnd, IDC_SHADEBOOST, theApp.GetConfig("ShadeBoost", 0)); - - SendMessage(GetDlgItem(m_hWnd, IDC_SKIPDRAWHACK), UDM_SETRANGE, 0, MAKELPARAM(1000, 0)); - SendMessage(GetDlgItem(m_hWnd, IDC_SKIPDRAWHACK), UDM_SETPOS, 0, MAKELPARAM(theApp.GetConfig("UserHacks_SkipDraw", 0), 0)); + + // Hacks + CheckDlgButton(m_hWnd, IDC_HACKS_ENABLED, theApp.GetConfig("UserHacks", 0)); + SendMessage(GetDlgItem(m_hWnd, IDC_RESX), UDM_SETRANGE, 0, MAKELPARAM(8192, 256)); SendMessage(GetDlgItem(m_hWnd, IDC_RESX), UDM_SETPOS, 0, MAKELPARAM(theApp.GetConfig("resx", 1024), 0)); @@ -123,17 +120,6 @@ void GSSettingsDlg::OnInit() SendMessage(GetDlgItem(m_hWnd, IDC_RESY), UDM_SETRANGE, 0, MAKELPARAM(8192, 256)); SendMessage(GetDlgItem(m_hWnd, IDC_RESY), UDM_SETPOS, 0, MAKELPARAM(theApp.GetConfig("resy", 1024), 0)); - int r = theApp.GetConfig("Renderer", 0); - - if(r >= 0 && r <= 2) // DX9 - { - GSDevice9::ForceValidMsaaConfig(); - - m_lastValidMsaa = theApp.GetConfig("msaa", 0); - } - - SendMessage(GetDlgItem(m_hWnd, IDC_MSAA), UDM_SETRANGE, 0, MAKELPARAM(16, 0)); - SendMessage(GetDlgItem(m_hWnd, IDC_MSAA), UDM_SETPOS, 0, MAKELPARAM(theApp.GetConfig("msaa", 0), 0)); SendMessage(GetDlgItem(m_hWnd, IDC_SWTHREADS), UDM_SETRANGE, 0, MAKELPARAM(16, 0)); SendMessage(GetDlgItem(m_hWnd, IDC_SWTHREADS), UDM_SETPOS, 0, MAKELPARAM(theApp.GetConfig("extrathreads", 0), 0)); @@ -143,76 +129,7 @@ void GSSettingsDlg::OnInit() bool GSSettingsDlg::OnCommand(HWND hWnd, UINT id, UINT code) { - if(id == IDC_MSAAEDIT && code == EN_CHANGE) // validate and possibly warn user when changing msaa - { - //post change - - bool dx9 = false; - - INT_PTR i; - - if(ComboBoxGetSelData(IDC_RENDERER, i)) - { - dx9 = i >= 0 && i <= 2; - } - - if(dx9) - { - uint32 requestedMsaa = (int)SendMessage(GetDlgItem(m_hWnd, IDC_MSAA), UDM_GETPOS, 0, 0); // valid from OnCommand? - uint32 derivedDepth = GSDevice9::GetMaxDepth(requestedMsaa); - - if(derivedDepth == 0) - { - //FIXME: Ugly UI: HW AA is currently a uint spinbox but usually only some values are supported (e.g. only 2/4/8 or a similar set). - // Better solution would be to use a drop-down with only valid msaa values such that we don't need this. Maybe some day. - // Known bad behavior: When manually deleting a HW AA value to put another instead (e.g. 2 -> delete -> 4) - // it's registered as 0 after the deletion (with possible higher derived z bits), and might issue - // a warning when the new value is registered (i.e. 4 in our example) since it might result in fewer - // z bits than 0, even if it's not different than the previous value (i.e. 2 in our example) z bits. - - //Find valid msaa values, regardless of derived z buffer bits - - string supportedAa = ""; - - for(int i = 2; i <= 16; i++) - { - if(GSDevice9::GetMaxDepth(i)) - { - if(supportedAa.length()) supportedAa += "/"; - - supportedAa += format("%d", i); - } - } - - if(!supportedAa.length()) - { - supportedAa = "None"; - } - - string s = format("AA=%d is not supported.\nSupported AA values: %s.", (int)requestedMsaa, supportedAa.c_str()); - - MessageBox(hWnd, s.c_str(),"Warning", MB_OK | MB_ICONWARNING); - - SendMessage(GetDlgItem(m_hWnd, IDC_MSAA), UDM_SETPOS, 0, requestedMsaa = m_lastValidMsaa); // revert value from inside OnCommand? is this OK? - } - else if(derivedDepth < GSDevice9::GetMaxDepth(m_lastValidMsaa)) - { - string s = format("AA=%d will force GSdx to degrade Z buffer\nfrom 32 to 24 bit, which will probably cause glitches\n(changing 'Logarithmic Z' might help some).\n\nContinue?", (int)requestedMsaa); - - //s+= format("\nlastMsaa=%d, lastDepth=%d, newMsaa=%d, newDepth=%d", (int)m_lastValidMsaa, (int)GSDevice9::GetMaxDepth(m_lastValidMsaa), (int)requestedMsaa, (int)GSDevice9::GetMaxDepth(requestedMsaa)); - - if(IDOK != MessageBox(hWnd, s.c_str(), "Warning", MB_OKCANCEL|MB_ICONWARNING)) - { - SendMessage(GetDlgItem(m_hWnd, IDC_MSAA), UDM_SETPOS, 0, requestedMsaa=m_lastValidMsaa); // revert value from inside OnCommand? is this OK? - } - } - - m_lastValidMsaa = requestedMsaa; - - UpdateControls(); - } - } - else if(id == IDC_UPSCALE_MULTIPLIER && code == CBN_SELCHANGE) + if(id == IDC_UPSCALE_MULTIPLIER && code == CBN_SELCHANGE) { UpdateControls(); } @@ -232,6 +149,14 @@ bool GSSettingsDlg::OnCommand(HWND hWnd, UINT id, UINT code) { ShadeBoostDlg.DoModal(); } + else if(id == IDC_HACKS_ENABLED && code == BN_CLICKED) + { + UpdateControls(); + } + else if(id == IDC_HACKSBUTTON && code == BN_CLICKED) + { + HacksDlg.DoModal(); + } else if(id == IDOK) { INT_PTR data; @@ -284,28 +209,21 @@ bool GSSettingsDlg::OnCommand(HWND hWnd, UINT id, UINT code) theApp.SetConfig("resx", (int)SendMessage(GetDlgItem(m_hWnd, IDC_RESX), UDM_GETPOS, 0, 0)); theApp.SetConfig("resy", (int)SendMessage(GetDlgItem(m_hWnd, IDC_RESY), UDM_GETPOS, 0, 0)); theApp.SetConfig("extrathreads", (int)SendMessage(GetDlgItem(m_hWnd, IDC_SWTHREADS), UDM_GETPOS, 0, 0)); - theApp.SetConfig("msaa", (int)SendMessage(GetDlgItem(m_hWnd, IDC_MSAA), UDM_GETPOS, 0, 0)); - // Hacks - theApp.SetConfig("UserHacks_AlphaHack", (int)IsDlgButtonChecked(m_hWnd, IDC_ALPHAHACK)); - theApp.SetConfig("UserHacks_HalfPixelOffset", (int)IsDlgButtonChecked(m_hWnd, IDC_OFFSETHACK)); - theApp.SetConfig("UserHacks_SpriteHack", (int)IsDlgButtonChecked(m_hWnd, IDC_SPRITEHACK)); - theApp.SetConfig("UserHacks_SkipDraw", (int)SendMessage(GetDlgItem(m_hWnd, IDC_SKIPDRAWHACK), UDM_GETPOS, 0, 0)); // Shade Boost theApp.SetConfig("ShadeBoost", (int)IsDlgButtonChecked(m_hWnd, IDC_SHADEBOOST)); + + // Hacks + theApp.SetConfig("UserHacks", (int)IsDlgButtonChecked(m_hWnd, IDC_HACKS_ENABLED)); } return __super::OnCommand(hWnd, id, code); } - void GSSettingsDlg::UpdateControls() { INT_PTR i; - bool allowHacks = !!theApp.GetConfig("allowHacks", 0); - theApp.SetConfig("allowHacks", (int)allowHacks); - int scaling = 1; // in case reading the combo doesn't work, enable the custom res control anyway if(ComboBoxGetSelData(IDC_UPSCALE_MULTIPLIER, i)) @@ -338,34 +256,23 @@ void GSSettingsDlg::UpdateControls() //EnableWindow(GetDlgItem(m_hWnd, IDC_AA1), sw); // Let uers set software params regardless of renderer used //EnableWindow(GetDlgItem(m_hWnd, IDC_SWTHREADS_EDIT), sw); //EnableWindow(GetDlgItem(m_hWnd, IDC_SWTHREADS), sw); - EnableWindow(GetDlgItem(m_hWnd, IDC_MSAAEDIT), hw); - EnableWindow(GetDlgItem(m_hWnd, IDC_MSAA), hw); + // Shade Boost - EnableWindow(GetDlgItem(m_hWnd, IDC_SHADEBUTTON), IsDlgButtonChecked(m_hWnd, IDC_SHADEBOOST) == BST_CHECKED); + EnableWindow(GetDlgItem(m_hWnd, IDC_SHADEBUTTON), IsDlgButtonChecked(m_hWnd, IDC_SHADEBOOST) == BST_CHECKED); - //ShowWindow(GetDlgItem(m_hWnd, IDC_USERHACKS), allowHacks && hw) ? SW_SHOW : SW_HIDE; //Don't disable the "Hacks" frame - ShowWindow(GetDlgItem(m_hWnd, IDC_HACKDISABLED), !(allowHacks && hw)) ? SW_SHOW : SW_HIDE; - ShowWindow(GetDlgItem(m_hWnd, IDC_MSAAEDIT), allowHacks && hw) ? SW_SHOW : SW_HIDE; - ShowWindow(GetDlgItem(m_hWnd, IDC_MSAA), allowHacks && hw) ? SW_SHOW : SW_HIDE; - ShowWindow(GetDlgItem(m_hWnd, IDC_STATIC_TEXT_HWAA), allowHacks && hw) ? SW_SHOW : SW_HIDE; - - ShowWindow(GetDlgItem(m_hWnd, IDC_ALPHAHACK), allowHacks && hw) ? SW_SHOW : SW_HIDE; - ShowWindow(GetDlgItem(m_hWnd, IDC_OFFSETHACK), allowHacks && hw) ? SW_SHOW : SW_HIDE; - ShowWindow(GetDlgItem(m_hWnd, IDC_SPRITEHACK), allowHacks && hw) ? SW_SHOW : SW_HIDE; - - ShowWindow(GetDlgItem(m_hWnd, IDC_SKIPDRAWHACKEDIT), allowHacks && hw) ? SW_SHOW : SW_HIDE; - ShowWindow(GetDlgItem(m_hWnd, IDC_SKIPDRAWHACK), allowHacks && hw) ? SW_SHOW : SW_HIDE; - ShowWindow(GetDlgItem(m_hWnd, IDC_STATIC_TEXT_SKIPDRAW), allowHacks && hw) ? SW_SHOW : SW_HIDE; + // Hacks + EnableWindow(GetDlgItem(m_hWnd, IDC_HACKS_ENABLED), hw); + EnableWindow(GetDlgItem(m_hWnd, IDC_HACKSBUTTON), hw && IsDlgButtonChecked(m_hWnd, IDC_HACKS_ENABLED) == BST_CHECKED); } } +// Shade Boost Dialog GSShadeBostDlg::GSShadeBostDlg() : - GSDialog(IDD_SHADEBOOST) + GSDialog(IDD_SHADEBOOST) {} - void GSShadeBostDlg::OnInit() { contrast = theApp.GetConfig("ShadeBoost_Contrast", 50); @@ -395,10 +302,8 @@ void GSShadeBostDlg::UpdateControls() SetDlgItemText(m_hWnd, IDC_CONTRAST_TEXT, text); } - bool GSShadeBostDlg::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) { - switch(message) { case WM_HSCROLL: @@ -465,4 +370,92 @@ bool GSShadeBostDlg::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) return true; -} \ No newline at end of file +} + +// Hacks Dialog + +GSHacksDlg::GSHacksDlg() : + GSDialog(IDD_HACKS) +{ + memset(msaa2cb, 0, sizeof(msaa2cb)); + memset(cb2msaa, 0, sizeof(cb2msaa)); +} + +void GSHacksDlg::OnInit() +{ + bool dx9 = (int)SendMessage(GetDlgItem(GetParent(m_hWnd), IDC_RENDERER), CB_GETCURSEL, 0, 0) / 3 == 0; + unsigned short cb = 0; + + if(dx9) for(unsigned short i = 0; i < 17; i++) + { + if( i == 1) continue; + + int depth = GSDevice9::GetMaxDepth(i); + + if(depth) + { + char text[32] = {0}; + sprintf(text, depth == 32 ? "%dx Z-32" : "%dx Z-24", i); + SendMessage(GetDlgItem(m_hWnd, IDC_MSAACB), CB_ADDSTRING, 0, (LPARAM)text); + + msaa2cb[i] = cb; + cb2msaa[cb] = i; + cb++; + } + } + else for(unsigned short j = 0; j < 5; j++) // TODO: Make the same kind of check for d3d11, eventually.... + { + unsigned short i = j == 0 ? 0 : 1 << j; + + msaa2cb[i] = j; + cb2msaa[j] = i; + + char text[32] = {0}; + sprintf(text, "%dx ????", i); + + SendMessage(GetDlgItem(m_hWnd, IDC_MSAACB), CB_ADDSTRING, 0, (LPARAM)text); + } + + SendMessage(GetDlgItem(m_hWnd, IDC_MSAACB), CB_SETCURSEL, msaa2cb[min(theApp.GetConfig("UserHacks_MSAA", 0), 16)], 0); + + CheckDlgButton(m_hWnd, IDC_ALPHAHACK, theApp.GetConfig("UserHacks_AlphaHack", 0)); + CheckDlgButton(m_hWnd, IDC_OFFSETHACK, theApp.GetConfig("UserHacks_HalfPixelOffset", 0)); + CheckDlgButton(m_hWnd, IDC_SPRITEHACK, theApp.GetConfig("UserHacks_SpriteHack", 0)); + + SendMessage(GetDlgItem(m_hWnd, IDC_SKIPDRAWHACK), UDM_SETRANGE, 0, MAKELPARAM(1000, 0)); + SendMessage(GetDlgItem(m_hWnd, IDC_SKIPDRAWHACK), UDM_SETPOS, 0, MAKELPARAM(theApp.GetConfig("UserHacks_SkipDraw", 0), 0)); +} + +void GSHacksDlg::UpdateControls() +{} + +bool GSHacksDlg::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_COMMAND: + { + int id = LOWORD(wParam); + + switch(id) + { + case IDOK: + { + theApp.SetConfig("UserHacks_MSAA", cb2msaa[(int)SendMessage(GetDlgItem(m_hWnd, IDC_MSAACB), CB_GETCURSEL, 0, 0)]); + theApp.SetConfig("UserHacks_AlphaHack", (int)IsDlgButtonChecked(m_hWnd, IDC_ALPHAHACK)); + theApp.SetConfig("UserHacks_HalfPixelOffset", (int)IsDlgButtonChecked(m_hWnd, IDC_OFFSETHACK)); + theApp.SetConfig("UserHacks_SpriteHack", (int)IsDlgButtonChecked(m_hWnd, IDC_SPRITEHACK)); + theApp.SetConfig("UserHacks_SkipDraw", (int)SendMessage(GetDlgItem(m_hWnd, IDC_SKIPDRAWHACK), UDM_GETPOS, 0, 0)); + EndDialog(m_hWnd, id); + } break; + } + + } break; + + case WM_CLOSE:EndDialog(m_hWnd, IDCANCEL); break; + + default: return false; + } + + return true; +} diff --git a/plugins/GSdx/GSSettingsDlg.h b/plugins/GSdx/GSSettingsDlg.h index 95589dc09..5cd394530 100644 --- a/plugins/GSdx/GSSettingsDlg.h +++ b/plugins/GSdx/GSSettingsDlg.h @@ -40,6 +40,23 @@ public: GSShadeBostDlg(); }; +class GSHacksDlg : public GSDialog +{ + unsigned short cb2msaa[17]; + unsigned short msaa2cb[17]; + + bool isdx9; + + void UpdateControls(); + +protected: + void OnInit(); + bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam); + +public: + GSHacksDlg(); +}; + class GSSettingsDlg : public GSDialog { list m_modes; @@ -55,6 +72,7 @@ protected: // Shade Boost GSShadeBostDlg ShadeBoostDlg; + GSHacksDlg HacksDlg; public: GSSettingsDlg(bool isOpen2); diff --git a/plugins/GSdx/GSdx.rc b/plugins/GSdx/GSdx.rc index e21e66578..59a114c1a 100644 --- a/plugins/GSdx/GSdx.rc +++ b/plugins/GSdx/GSdx.rc @@ -74,6 +74,30 @@ IDB_LOGO10 BITMAP "res\\logo10.bmp" // Dialog // +IDD_HACKS DIALOGEX 0, 0, 316, 133 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Hacks Configuration" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,259,112,50,14 + GROUPBOX "Hack",IDC_STATIC,7,7,76,100 + GROUPBOX "Description",IDC_STATIC,86,7,223,100 + LTEXT "MSAA",IDC_STATIC,14,20,20,8 + LTEXT "Skipdraw",IDC_STATIC,14,37,30,8 + EDITTEXT IDC_SKIPDRAWHACKEDIT,45,35,24,14,ES_RIGHT | ES_AUTOHSCROLL + CONTROL "",IDC_SKIPDRAWHACK,"msctls_updown32",UDS_SETBUDDYINT | UDS_AUTOBUDDY | UDS_ARROWKEYS,68,35,10,14 + CONTROL "Alpha",IDC_ALPHAHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,54,34,10 + CONTROL "Half-pixel Offset",IDC_OFFSETHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,71,65,10 + CONTROL "Sprite",IDC_SPRITEHACK,"Button",BS_AUTO3STATE | WS_TABSTOP,14,88,35,10 + LTEXT "It tickles your GPU's fancy",IDC_STATIC,92,20,84,8 + LTEXT "Makes Kratos a sad panda. Don't try with values over 9000.",IDC_STATIC,92,37,193,8 + LTEXT "Static",IDC_STATIC,92,54,19,8 + LTEXT "Static",IDC_STATIC,92,71,19,8 + LTEXT "Yup, another Static",IDC_STATIC,92,88,63,8 + LTEXT "USE AT YOUR OWN RISK!",IDC_STATIC,7,115,84,8,WS_DISABLED + COMBOBOX IDC_MSAACB,35,18,44,63,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP +END + IDD_SHADEBOOST DIALOGEX 0, 0, 316, 129 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Shade Boost Settings" @@ -93,7 +117,7 @@ BEGIN RTEXT "100",IDC_CONTRAST_TEXT,288,75,15,8 END -IDD_CONFIG DIALOGEX 0, 0, 189, 337 +IDD_CONFIG DIALOGEX 0, 0, 189, 330 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Settings..." FONT 8, "MS Shell Dlg", 400, 0, 0x1 @@ -101,47 +125,40 @@ BEGIN CONTROL 2022,IDC_LOGO11,"Static",SS_BITMAP,7,7,175,42 CONTROL 2021,IDC_LOGO9,"Static",SS_BITMAP,7,7,175,44 LTEXT "Resolution:",IDC_STATIC,7,58,37,8 - COMBOBOX IDC_RESOLUTION,71,56,111,125,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_RESOLUTION,71,56,72,125,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Renderer:",IDC_STATIC,7,73,34,8 COMBOBOX IDC_RENDERER,71,71,111,118,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Interlacing (F5):",IDC_STATIC,7,89,53,8 COMBOBOX IDC_INTERLACE,71,86,111,98,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Aspect Ratio (F6):",IDC_STATIC,7,104,60,8 COMBOBOX IDC_ASPECTRATIO,71,101,111,98,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - DEFPUSHBUTTON "OK",IDOK,43,316,50,14 - PUSHBUTTON "Cancel",IDCANCEL,96,316,50,14 - CONTROL "Windowed",IDC_WINDOWED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,89,244,93,10 - LTEXT "D3D internal res:",IDC_STATIC,18,135,55,8 - EDITTEXT IDC_RESX_EDIT,82,132,35,13,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_RESX,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,110,135,11,14 - EDITTEXT IDC_RESY_EDIT,120,132,35,13,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_RESY,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,144,135,11,14 - CONTROL "Native",IDC_NATIVERES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,123,165,33,10 - COMBOBOX IDC_UPSCALE_MULTIPLIER,82,147,74,98,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "Or use Scaling:",IDC_STATIC,18,150,49,8 - LTEXT "Or use original PS2 resolution :",IDC_STATIC,18,165,99,8 - EDITTEXT IDC_MSAAEDIT,45,272,35,13,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_MSAA,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,76,274,11,14 - LTEXT "HW AA",IDC_STATIC_TEXT_HWAA,18,274,24,8 - GROUPBOX "D3D Enhancements (can cause glitches)",IDC_STATIC,7,117,175,66 - LTEXT "Extra rendering threads:",IDC_STATIC,7,202,80,8 - EDITTEXT IDC_SWTHREADS_EDIT,89,200,35,13,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_SWTHREADS,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,117,203,11,14 - CONTROL "Texture filtering",IDC_FILTER,"Button",BS_AUTO3STATE | WS_TABSTOP,7,216,67,10 - CONTROL "Logarithmic Z",IDC_LOGZ,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,89,217,58,10 - CONTROL "Allow 8-bit textures",IDC_PALTEX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,230,82,10 - CONTROL "Alpha correction (FBA)",IDC_FBA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,89,230,93,10 - CONTROL "Edge anti-aliasing",IDC_AA1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,244,72,10 - CONTROL "Alpha Hack",IDC_ALPHAHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,293,51,10 - CONTROL "Offset Hack",IDC_OFFSETHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,67,293,51,10 - GROUPBOX "Hacks",IDC_USERHACKS,7,257,175,53,BS_CENTER - EDITTEXT IDC_SKIPDRAWHACKEDIT,122,272,40,14,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_SKIPDRAWHACK,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,161,274,11,14 - LTEXT "SkipDraw:",IDC_STATIC_TEXT_SKIPDRAW,89,274,33,8 - CONTROL "Sprite Hack",IDC_SPRITEHACK,"Button",BS_AUTO3STATE | WS_TABSTOP,123,293,51,10 - LTEXT "HACKS DISABLED",IDC_HACKDISABLED,64,281,57,8,WS_DISABLED - CONTROL "Enable Shade Boost",IDC_SHADEBOOST,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,187,79,10 - PUSHBUTTON "Settings...",IDC_SHADEBUTTON,88,184,94,14 + DEFPUSHBUTTON "OK",IDOK,43,309,50,14 + PUSHBUTTON "Cancel",IDCANCEL,96,309,50,14 + CONTROL "Window",IDC_WINDOWED,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | WS_TABSTOP,146,58,36,10 + LTEXT "D3D internal res:",IDC_STATIC,18,137,55,8 + EDITTEXT IDC_RESX_EDIT,82,134,35,13,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_RESX,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,110,133,11,14 + EDITTEXT IDC_RESY_EDIT,120,134,35,13,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_RESY,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,146,133,11,14 + CONTROL "Native",IDC_NATIVERES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,123,167,33,10 + COMBOBOX IDC_UPSCALE_MULTIPLIER,82,149,74,98,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Or use Scaling:",IDC_STATIC,18,152,49,8 + LTEXT "Or use original PS2 resolution :",IDC_STATIC,18,167,99,8 + GROUPBOX "D3D Enhancements (can cause glitches)",IDC_STATIC,7,119,175,66,BS_CENTER + LTEXT "Extra rendering threads:",IDC_STATIC,11,277,80,8 + EDITTEXT IDC_SWTHREADS_EDIT,93,276,35,13,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_SWTHREADS,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,124,275,11,14 + CONTROL "Texture filtering",IDC_FILTER,"Button",BS_AUTO3STATE | WS_TABSTOP,11,215,67,10 + CONTROL "Logarithmic Z",IDC_LOGZ,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,89,216,58,10 + CONTROL "Allow 8-bit textures",IDC_PALTEX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,231,78,10 + CONTROL "Alpha correction (FBA)",IDC_FBA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,89,231,85,10 + CONTROL "Edge anti-aliasing (AA1)",IDC_AA1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,292,93,10 + CONTROL "Enable Shade Boost",IDC_SHADEBOOST,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,189,79,10 + PUSHBUTTON "Settings...",IDC_SHADEBUTTON,88,186,87,14 + GROUPBOX "Software Mode Settings",IDC_STATIC,7,265,175,42,BS_CENTER + GROUPBOX "Hardware Mode Settings",IDC_STATIC,7,203,175,61,BS_CENTER + CONTROL "Enable HW Hacks",IDC_HACKS_ENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,247,71,10 + PUSHBUTTON "Configuration...",IDC_HACKSBUTTON,88,244,87,14 END IDD_CAPTURE DIALOGEX 0, 0, 279, 71 @@ -188,52 +205,43 @@ BEGIN CONTROL "Windowed",IDC_WINDOWED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,129,157,49,10 END -IDD_CONFIG2 DIALOGEX 0, 0, 187, 342 +IDD_CONFIG2 DIALOGEX 0, 0, 187, 311 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Settings..." FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN CONTROL 2022,IDC_LOGO11,"Static",SS_BITMAP,6,6,173,42 - DEFPUSHBUTTON "OK",IDOK,41,320,50,14 + DEFPUSHBUTTON "OK",IDOK,35,290,50,14 LTEXT "Renderer:",IDC_STATIC,6,57,34,8 COMBOBOX IDC_RENDERER,70,55,111,118,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Interlacing (F5):",IDC_STATIC,6,73,81,8 COMBOBOX IDC_INTERLACE,70,70,111,98,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Custom resolution:",IDC_STATIC,26,134,65,8 EDITTEXT IDC_RESX_EDIT,92,132,35,13,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_RESX,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,120,135,11,14 + CONTROL "",IDC_RESX,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,120,132,11,14 EDITTEXT IDC_RESY_EDIT,130,132,35,13,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_RESY,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,154,130,11,14 + CONTROL "",IDC_RESY,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,154,132,11,14 CONTROL "Native",IDC_NATIVERES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,92,105,33,10 - LTEXT "Extra rendering threads:",IDC_STATIC,11,233,80,8 - EDITTEXT IDC_SWTHREADS_EDIT,94,231,35,13,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_SWTHREADS,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,127,234,11,14 + LTEXT "Extra rendering threads:",IDC_STATIC,11,252,80,8 + EDITTEXT IDC_SWTHREADS_EDIT,94,250,35,13,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_SWTHREADS,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,129,249,11,14 COMBOBOX IDC_UPSCALE_MULTIPLIER,92,117,74,98,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Or use Scaling:",IDC_STATIC,38,119,49,8 LTEXT "Original PS2 resolution :",IDC_STATIC,10,105,80,8 - CONTROL "Edge anti-aliasing (AA1)",IDC_AA1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,249,93,10 - PUSHBUTTON "Cancel",IDCANCEL,95,320,50,14 + CONTROL "Edge anti-aliasing (AA1)",IDC_AA1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,268,93,10 + PUSHBUTTON "Cancel",IDCANCEL,89,290,50,14 CONTROL 2021,IDC_LOGO9,"Static",SS_BITMAP,6,6,175,44 - CONTROL "Alpha Hack",IDC_ALPHAHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,298,51,10 - CONTROL "Offset Hack",IDC_OFFSETHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,65,298,51,10 - GROUPBOX "Hacks",IDC_USERHACKS,6,269,175,45,BS_CENTER - EDITTEXT IDC_SKIPDRAWHACKEDIT,125,279,40,14,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_SKIPDRAWHACK,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,164,281,11,14 - LTEXT "Skipdraw",IDC_STATIC_TEXT_SKIPDRAW,93,281,30,8 - EDITTEXT IDC_MSAAEDIT,38,279,35,13,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_MSAA,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,72,282,11,14 GROUPBOX "D3D Internal resolution (can cause glitches)",IDC_STATIC,6,87,175,64,BS_CENTER - GROUPBOX "Software Mode Settings",IDC_STATIC,6,217,175,50,BS_CENTER - GROUPBOX "Hardware Mode Settings",IDC_STATIC,6,171,175,45,BS_CENTER - CONTROL "Logarithmic Z",IDC_LOGZ,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,92,185,58,10 - CONTROL "Alpha correction (FBA)",IDC_FBA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,92,198,87,10 - CONTROL "Allow 8-bit textures",IDC_PALTEX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,198,82,10 + GROUPBOX "Software Mode Settings",IDC_STATIC,6,236,175,50,BS_CENTER + GROUPBOX "Hardware Mode Settings",IDC_STATIC,6,171,175,63,BS_CENTER + CONTROL "Logarithmic Z",IDC_LOGZ,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,92,184,58,10 + CONTROL "Alpha correction (FBA)",IDC_FBA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,92,200,87,10 + CONTROL "Allow 8-bit textures",IDC_PALTEX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,200,82,10 CONTROL "Texture filtering",IDC_FILTER,"Button",BS_AUTO3STATE | WS_TABSTOP,10,184,67,10 - LTEXT "HW AA",IDC_STATIC_TEXT_HWAA,11,281,24,8 - CONTROL "Sprite Hack",IDC_SPRITEHACK,"Button",BS_AUTO3STATE | WS_TABSTOP,125,298,51,10 - LTEXT "HACKS DISABLED",IDC_HACKDISABLED,62,287,57,8,WS_DISABLED CONTROL "Enable Shade Boost",IDC_SHADEBOOST,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,157,79,10 PUSHBUTTON "Settings...",IDC_SHADEBUTTON,95,154,75,14 + CONTROL "Enable HW Hacks",IDC_HACKS_ENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,216,71,10 + PUSHBUTTON "Configuration...",IDC_HACKSBUTTON,95,213,75,14 END @@ -245,6 +253,14 @@ END #ifdef APSTUDIO_INVOKED GUIDELINES DESIGNINFO BEGIN + IDD_HACKS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 309 + TOPMARGIN, 7 + BOTTOMMARGIN, 126 + END + IDD_SHADEBOOST, DIALOG BEGIN LEFTMARGIN, 7 @@ -261,7 +277,7 @@ BEGIN VERTGUIDE, 89 VERTGUIDE, 182 TOPMARGIN, 7 - BOTTOMMARGIN, 330 + BOTTOMMARGIN, 323 HORZGUIDE, 49 END @@ -289,7 +305,7 @@ BEGIN RIGHTMARGIN, 181 VERTGUIDE, 87 TOPMARGIN, 6 - BOTTOMMARGIN, 335 + BOTTOMMARGIN, 304 END END #endif // APSTUDIO_INVOKED diff --git a/plugins/GSdx/resource.h b/plugins/GSdx/resource.h index 9c31d6fbf..766ba8365 100644 --- a/plugins/GSdx/resource.h +++ b/plugins/GSdx/resource.h @@ -82,9 +82,12 @@ #define IDC_CONTRAST_SLIDER 2056 #define IDC_SHADEBUTTON 2058 #define IDC_SHADEBOOST 2059 +#define IDC_HACKS_ENABLED 2060 #define IDC_SATURATION_TEXT 2061 #define IDC_BRIGHTNESS_TEXT 2062 #define IDC_CONTRAST_TEXT 2063 +#define IDC_MSAACB 2070 +#define IDC_HACKSBUTTON 2071 #define IDC_COLORSPACE 3000 #define IDR_CONVERT_FX 10000 #define IDR_TFX_FX 10001 @@ -95,14 +98,15 @@ #define IDR_CS_FX 10006 #define IDD_SHADEBOOST 10007 #define IDR_SHADEBOOST_FX 10009 +#define IDD_HACKS 10011 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 10011 +#define _APS_NEXT_RESOURCE_VALUE 10012 #define _APS_NEXT_COMMAND_VALUE 32771 -#define _APS_NEXT_CONTROL_VALUE 2064 +#define _APS_NEXT_CONTROL_VALUE 2072 #define _APS_NEXT_SYMED_VALUE 5000 #endif #endif From 6a0953ab94a35e150a212d2b709b5bf569b6cce8 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Tue, 6 Mar 2012 19:42:59 +0000 Subject: [PATCH 24/83] cmake: sparsehash moves header file in newer version! Detect the 2 include pathes and add a define. Fix issue 1222 git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5117 96395faa-99c1-11dd-bbfe-3dabce05a288 --- cmake/FindSparseHash_NEW.cmake | 18 ++++++++++++++++++ cmake/SearchForStuff.cmake | 6 ++++++ common/include/Utilities/HashMap.h | 8 ++++++++ common/src/Utilities/CMakeLists.txt | 4 ++++ pcsx2/CMakeLists.txt | 4 ++++ 5 files changed, 40 insertions(+) create mode 100644 cmake/FindSparseHash_NEW.cmake diff --git a/cmake/FindSparseHash_NEW.cmake b/cmake/FindSparseHash_NEW.cmake new file mode 100644 index 000000000..070999f7d --- /dev/null +++ b/cmake/FindSparseHash_NEW.cmake @@ -0,0 +1,18 @@ +# Try to find SparseHash +# Once done, this will define +# +# SPARSEHASE_NEW_FOUND - system has SparseHash +# SPARSEHASE_NEW_INCLUDE_DIR - the SparseHash include directories + +if(SPARSEHASE_NEW_INCLUDE_DIR) + set(SPARSEHASE_NEW_FIND_QUIETLY TRUE) +endif(SPARSEHASE_NEW_INCLUDE_DIR) + +find_path(SPARSEHASE_NEW_INCLUDE_DIR sparsehash/internal/densehashtable.h) + +# handle the QUIETLY and REQUIRED arguments and set SPARSEHASE_NEW_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(SparseHash_new DEFAULT_MSG SPARSEHASE_NEW_INCLUDE_DIR) + +mark_as_advanced(SPARSEHASE_NEW_INCLUDE_DIR) diff --git a/cmake/SearchForStuff.cmake b/cmake/SearchForStuff.cmake index 052729964..6c776f100 100644 --- a/cmake/SearchForStuff.cmake +++ b/cmake/SearchForStuff.cmake @@ -61,6 +61,7 @@ if(NOT FORCE_INTERNAL_SOUNDTOUCH) include(FindSoundTouch) endif(NOT FORCE_INTERNAL_SOUNDTOUCH) include(FindSparseHash) +include(FindSparseHash_NEW) # Note for include_directory: The order is important to avoid a mess between include file from your system and the one of pcsx2 # If you include first 3rdparty, all 3rdpary include will have a higer priority... @@ -166,6 +167,11 @@ endif(SOUNDTOUCH_FOUND AND NOT projectSoundTouch) if(SPARSEHASH_FOUND) include_directories(${SPARSEHASH_INCLUDE_DIR}) endif(SPARSEHASH_FOUND) +if(SPARSEHASH_NEW_FOUND) + include_directories(${SPARSEHASH_NEW_INCLUDE_DIR}) + # allow to build parts that depend on sparsehash + set(SPARSEHASH_FOUND TRUE) +endif(SPARSEHASH_NEW_FOUND) # Wx if(wxWidgets_FOUND) diff --git a/common/include/Utilities/HashMap.h b/common/include/Utilities/HashMap.h index 91500026e..44da83fbd 100644 --- a/common/include/Utilities/HashMap.h +++ b/common/include/Utilities/HashMap.h @@ -15,10 +15,18 @@ #pragma once +// They move include file in version 2.0.2 of google sparsehash... +#ifdef SPARSEHASH_NEW_INCLUDE_DIR +#include +#include +#include +#include +#else #include #include #include #include +#endif #include diff --git a/common/src/Utilities/CMakeLists.txt b/common/src/Utilities/CMakeLists.txt index b5d9040d3..68fb33fc5 100644 --- a/common/src/Utilities/CMakeLists.txt +++ b/common/src/Utilities/CMakeLists.txt @@ -20,6 +20,10 @@ set(CommonFlags -pipe -Wunused-variable) +if (SPARSEHASH_NEW_FOUND) + set(CommonFlags "${CommonFlags} -DSPARSEHASH_NEW_INCLUDE_DIR ") +endif (SPARSEHASH_NEW_FOUND) + # set warning flags set(DebugFlags -g diff --git a/pcsx2/CMakeLists.txt b/pcsx2/CMakeLists.txt index c87ab6fa9..9bef3c82d 100644 --- a/pcsx2/CMakeLists.txt +++ b/pcsx2/CMakeLists.txt @@ -22,6 +22,10 @@ set(CommonFlags -Wstrict-aliasing # Allow to track strict aliasing issue. -pipe) +if (SPARSEHASH_NEW_FOUND) + set(CommonFlags "${CommonFlags} -DSPARSEHASH_NEW_INCLUDE_DIR ") +endif (SPARSEHASH_NEW_FOUND) + # set warning flags set(DebugFlags -W From d2665e9bc4d4031cd73aa471cd1918cc9ba9cec4 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Tue, 6 Mar 2012 20:01:27 +0000 Subject: [PATCH 25/83] GSdx: The "enable hacks" checkbox works to toggle all hacks. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5118 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSDeviceDX.cpp | 2 +- plugins/GSdx/GSRendererDX.cpp | 4 ++-- plugins/GSdx/GSRendererDX.h | 2 +- plugins/GSdx/GSRendererHW.cpp | 2 +- plugins/GSdx/GSTextureCache.cpp | 6 +++--- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/GSdx/GSDeviceDX.cpp b/plugins/GSdx/GSDeviceDX.cpp index 1165c4671..eca5e6905 100644 --- a/plugins/GSdx/GSDeviceDX.cpp +++ b/plugins/GSdx/GSDeviceDX.cpp @@ -25,7 +25,7 @@ GSDeviceDX::GSDeviceDX() { - m_msaa = theApp.GetConfig("UserHacks_MSAA", 0); + m_msaa = !!theApp.GetConfig("UserHacks", 0) ? theApp.GetConfig("UserHacks_MSAA", 0) : 0; m_msaa_desc.Count = 1; m_msaa_desc.Quality = 0; diff --git a/plugins/GSdx/GSRendererDX.cpp b/plugins/GSdx/GSRendererDX.cpp index e3117dcd6..88c183082 100644 --- a/plugins/GSdx/GSRendererDX.cpp +++ b/plugins/GSdx/GSRendererDX.cpp @@ -29,8 +29,8 @@ GSRendererDX::GSRendererDX(GSTextureCache* tc, const GSVector2& pixelcenter) { m_logz = !!theApp.GetConfig("logz", 0); m_fba = !!theApp.GetConfig("fba", 1); - //UserHacks_HalfPixelOffset = !!theApp.GetConfig("UserHacks_HalfPixelOffset", 0); - UserHacks_AlphaHack = !!theApp.GetConfig("UserHacks_AlphaHack", 0); + + UserHacks_AlphaHack = !!theApp.GetConfig("UserHacks_AlphaHack", 0) && !!theApp.GetConfig("UserHacks", 0); } GSRendererDX::~GSRendererDX() diff --git a/plugins/GSdx/GSRendererDX.h b/plugins/GSdx/GSRendererDX.h index 13dfbc48c..b01e46d1d 100644 --- a/plugins/GSdx/GSRendererDX.h +++ b/plugins/GSdx/GSRendererDX.h @@ -28,7 +28,7 @@ class GSRendererDX : public GSRendererHW GSVector2 m_pixelcenter; bool m_logz; bool m_fba; - //bool UserHacks_HalfPixelOffset; + bool UserHacks_AlphaHack; protected: diff --git a/plugins/GSdx/GSRendererHW.cpp b/plugins/GSdx/GSRendererHW.cpp index c773999d5..c5d7acce7 100644 --- a/plugins/GSdx/GSRendererHW.cpp +++ b/plugins/GSdx/GSRendererHW.cpp @@ -31,7 +31,7 @@ GSRendererHW::GSRendererHW(GSTextureCache* tc) , m_upscale_multiplier(1) { m_upscale_multiplier = theApp.GetConfig("upscale_multiplier", 1); - m_userhacks_skipdraw = theApp.GetConfig("UserHacks_SkipDraw", 0); + m_userhacks_skipdraw = !!theApp.GetConfig("UserHacks", 0) ? theApp.GetConfig("UserHacks_SkipDraw", 0) : 0; if(!m_nativeres) { diff --git a/plugins/GSdx/GSTextureCache.cpp b/plugins/GSdx/GSTextureCache.cpp index 8ca4952f1..9e4f52890 100644 --- a/plugins/GSdx/GSTextureCache.cpp +++ b/plugins/GSdx/GSTextureCache.cpp @@ -25,12 +25,12 @@ GSTextureCache::GSTextureCache(GSRenderer* r) : m_renderer(r) { - m_spritehack = theApp.GetConfig("UserHacks_SpriteHack", 0); + m_spritehack = !!theApp.GetConfig("UserHacks", 0) ? theApp.GetConfig("UserHacks_SpriteHack", 0) : 0; + UserHacks_HalfPixelOffset = !!theApp.GetConfig("UserHacks", 0) && !!theApp.GetConfig("UserHacks_HalfPixelOffset", 0); + m_paltex = !!theApp.GetConfig("paltex", 0); m_temp = (uint8*)_aligned_malloc(1024 * 1024 * sizeof(uint32), 32); - - UserHacks_HalfPixelOffset = !!theApp.GetConfig("UserHacks_HalfPixelOffset", 0); } GSTextureCache::~GSTextureCache() From 0d5e312bdbfb5e8e88d1c001120c6a808f05e457 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Tue, 6 Mar 2012 20:14:35 +0000 Subject: [PATCH 26/83] GSdx: Some descriptions and making the hack configure button always visible (for now). git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5119 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSSettingsDlg.cpp | 2 +- plugins/GSdx/GSdx.rc | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/GSdx/GSSettingsDlg.cpp b/plugins/GSdx/GSSettingsDlg.cpp index 18d65a9f5..f71465218 100644 --- a/plugins/GSdx/GSSettingsDlg.cpp +++ b/plugins/GSdx/GSSettingsDlg.cpp @@ -263,7 +263,7 @@ void GSSettingsDlg::UpdateControls() // Hacks EnableWindow(GetDlgItem(m_hWnd, IDC_HACKS_ENABLED), hw); - EnableWindow(GetDlgItem(m_hWnd, IDC_HACKSBUTTON), hw && IsDlgButtonChecked(m_hWnd, IDC_HACKS_ENABLED) == BST_CHECKED); + //EnableWindow(GetDlgItem(m_hWnd, IDC_HACKSBUTTON), hw && IsDlgButtonChecked(m_hWnd, IDC_HACKS_ENABLED) == BST_CHECKED); } } diff --git a/plugins/GSdx/GSdx.rc b/plugins/GSdx/GSdx.rc index 59a114c1a..eb8c3ee18 100644 --- a/plugins/GSdx/GSdx.rc +++ b/plugins/GSdx/GSdx.rc @@ -89,11 +89,11 @@ BEGIN CONTROL "Alpha",IDC_ALPHAHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,54,34,10 CONTROL "Half-pixel Offset",IDC_OFFSETHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,71,65,10 CONTROL "Sprite",IDC_SPRITEHACK,"Button",BS_AUTO3STATE | WS_TABSTOP,14,88,35,10 - LTEXT "It tickles your GPU's fancy",IDC_STATIC,92,20,84,8 - LTEXT "Makes Kratos a sad panda. Don't try with values over 9000.",IDC_STATIC,92,37,193,8 - LTEXT "Static",IDC_STATIC,92,54,19,8 - LTEXT "Static",IDC_STATIC,92,71,19,8 - LTEXT "Yup, another Static",IDC_STATIC,92,88,63,8 + LTEXT "It tickles your GPU's fancy",IDC_STATIC,92,20,82,8 + LTEXT "Makes Kratos a sad panda. Don't try with values over 9000.",IDC_STATIC,92,37,187,8 + LTEXT "Works around some shadow problems",IDC_STATIC,92,54,120,8 + LTEXT "May fix displaced fog or blend effects",IDC_STATIC,92,71,117,8 + LTEXT "Fixes character sprites in some 2D games",IDC_STATIC,92,88,129,8 LTEXT "USE AT YOUR OWN RISK!",IDC_STATIC,7,115,84,8,WS_DISABLED COMBOBOX IDC_MSAACB,35,18,44,63,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP END @@ -158,7 +158,7 @@ BEGIN GROUPBOX "Software Mode Settings",IDC_STATIC,7,265,175,42,BS_CENTER GROUPBOX "Hardware Mode Settings",IDC_STATIC,7,203,175,61,BS_CENTER CONTROL "Enable HW Hacks",IDC_HACKS_ENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,247,71,10 - PUSHBUTTON "Configuration...",IDC_HACKSBUTTON,88,244,87,14 + PUSHBUTTON "Configure...",IDC_HACKSBUTTON,88,244,87,14 END IDD_CAPTURE DIALOGEX 0, 0, 279, 71 @@ -241,7 +241,7 @@ BEGIN CONTROL "Enable Shade Boost",IDC_SHADEBOOST,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,157,79,10 PUSHBUTTON "Settings...",IDC_SHADEBUTTON,95,154,75,14 CONTROL "Enable HW Hacks",IDC_HACKS_ENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,216,71,10 - PUSHBUTTON "Configuration...",IDC_HACKSBUTTON,95,213,75,14 + PUSHBUTTON "Configure...",IDC_HACKSBUTTON,95,213,75,14 END From b25aec19c15192dbf8cd37e5bb5eb761d027c441 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Tue, 6 Mar 2012 21:36:59 +0000 Subject: [PATCH 27/83] GSdx: Adding KrossX's Wild Arms text alignment hack to the new dialog box. This hack is actually very interesting for a number of games. It should work well in cases where game designers adjusted everything pixel perfect for the GS, that usually breaks with upscaling. It should be generalized and renamed later. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5120 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSDeviceDX.h | 1 + plugins/GSdx/GSRendererDX.cpp | 3 +++ plugins/GSdx/GSSettingsDlg.cpp | 2 ++ plugins/GSdx/GSTextureCache.cpp | 3 +++ plugins/GSdx/GSTextureCache.h | 2 ++ plugins/GSdx/GSTextureFX11.cpp | 4 +++- plugins/GSdx/GSTextureFX9.cpp | 4 +++- plugins/GSdx/GSdx.rc | 16 +++++++++------- plugins/GSdx/res/tfx.fx | 13 +++++++++++++ plugins/GSdx/resource.h | 3 ++- 10 files changed, 41 insertions(+), 10 deletions(-) diff --git a/plugins/GSdx/GSDeviceDX.h b/plugins/GSdx/GSDeviceDX.h index 76edd6939..84b76b019 100644 --- a/plugins/GSdx/GSDeviceDX.h +++ b/plugins/GSdx/GSDeviceDX.h @@ -76,6 +76,7 @@ public: uint32 fst:1; uint32 logz:1; uint32 rtcopy:1; + uint32 wildhack:2; }; uint32 key; diff --git a/plugins/GSdx/GSRendererDX.cpp b/plugins/GSdx/GSRendererDX.cpp index 88c183082..e4cf03905 100644 --- a/plugins/GSdx/GSRendererDX.cpp +++ b/plugins/GSdx/GSRendererDX.cpp @@ -145,6 +145,9 @@ void GSRendererDX::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sourc vs_sel.logz = dev->HasDepth32() ? 0 : m_logz ? 1 : 0; vs_sel.rtcopy = !!rtcopy; + if(tex) vs_sel.wildhack = tex->m_wildhack_t; + else vs_sel.wildhack = 0; + // The real GS appears to do no masking based on the Z buffer format and writing larger Z values // than the buffer supports seems to be an error condition on the real GS, causing it to crash. // We are probably receiving bad coordinates from VU1 in these cases. diff --git a/plugins/GSdx/GSSettingsDlg.cpp b/plugins/GSdx/GSSettingsDlg.cpp index f71465218..1cd476990 100644 --- a/plugins/GSdx/GSSettingsDlg.cpp +++ b/plugins/GSdx/GSSettingsDlg.cpp @@ -421,6 +421,7 @@ void GSHacksDlg::OnInit() CheckDlgButton(m_hWnd, IDC_ALPHAHACK, theApp.GetConfig("UserHacks_AlphaHack", 0)); CheckDlgButton(m_hWnd, IDC_OFFSETHACK, theApp.GetConfig("UserHacks_HalfPixelOffset", 0)); CheckDlgButton(m_hWnd, IDC_SPRITEHACK, theApp.GetConfig("UserHacks_SpriteHack", 0)); + CheckDlgButton(m_hWnd, IDC_WILDHACK, theApp.GetConfig("UserHacks_WildHack", 0)); SendMessage(GetDlgItem(m_hWnd, IDC_SKIPDRAWHACK), UDM_SETRANGE, 0, MAKELPARAM(1000, 0)); SendMessage(GetDlgItem(m_hWnd, IDC_SKIPDRAWHACK), UDM_SETPOS, 0, MAKELPARAM(theApp.GetConfig("UserHacks_SkipDraw", 0), 0)); @@ -446,6 +447,7 @@ bool GSHacksDlg::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) theApp.SetConfig("UserHacks_HalfPixelOffset", (int)IsDlgButtonChecked(m_hWnd, IDC_OFFSETHACK)); theApp.SetConfig("UserHacks_SpriteHack", (int)IsDlgButtonChecked(m_hWnd, IDC_SPRITEHACK)); theApp.SetConfig("UserHacks_SkipDraw", (int)SendMessage(GetDlgItem(m_hWnd, IDC_SKIPDRAWHACK), UDM_GETPOS, 0, 0)); + theApp.SetConfig("UserHacks_WildHack", (int)IsDlgButtonChecked(m_hWnd, IDC_WILDHACK)); EndDialog(m_hWnd, id); } break; } diff --git a/plugins/GSdx/GSTextureCache.cpp b/plugins/GSdx/GSTextureCache.cpp index 9e4f52890..2270a5c28 100644 --- a/plugins/GSdx/GSTextureCache.cpp +++ b/plugins/GSdx/GSTextureCache.cpp @@ -26,6 +26,7 @@ GSTextureCache::GSTextureCache(GSRenderer* r) : m_renderer(r) { m_spritehack = !!theApp.GetConfig("UserHacks", 0) ? theApp.GetConfig("UserHacks_SpriteHack", 0) : 0; + m_wildhack = !!theApp.GetConfig("UserHacks", 0) ? theApp.GetConfig("UserHacks_WildHack", 0) : 0; UserHacks_HalfPixelOffset = !!theApp.GetConfig("UserHacks", 0) && !!theApp.GetConfig("UserHacks_HalfPixelOffset", 0); m_paltex = !!theApp.GetConfig("paltex", 0); @@ -583,6 +584,8 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con bool hack = false; + src->m_wildhack_t = m_wildhack; // dunno where to put it really, but works fine here. + if(dst == NULL) { if(m_spritehack && (TEX0.PSM == PSM_PSMT8 || TEX0.PSM == PSM_PSMT8H)) diff --git a/plugins/GSdx/GSTextureCache.h b/plugins/GSdx/GSTextureCache.h index 726917048..7303f94a2 100644 --- a/plugins/GSdx/GSTextureCache.h +++ b/plugins/GSdx/GSTextureCache.h @@ -76,6 +76,7 @@ public: bool m_complete; bool m_repeating; bool m_spritehack_t; + int m_wildhack_t; vector* m_p2t; public: @@ -120,6 +121,7 @@ protected: list m_dst[2]; bool m_paltex; int m_spritehack; + int m_wildhack; uint8* m_temp; virtual Source* CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* t = NULL); diff --git a/plugins/GSdx/GSTextureFX11.cpp b/plugins/GSdx/GSTextureFX11.cpp index 84189a7d8..7227c877d 100644 --- a/plugins/GSdx/GSTextureFX11.cpp +++ b/plugins/GSdx/GSTextureFX11.cpp @@ -88,12 +88,13 @@ void GSDevice11::SetupVS(VSSelector sel, const VSConstantBuffer* cb) if(i == m_vs.end()) { - string str[4]; + string str[5]; str[0] = format("%d", sel.bppz); str[1] = format("%d", sel.tme); str[2] = format("%d", sel.fst); str[3] = format("%d", sel.rtcopy); + str[4] = format("%d", sel.wildhack); D3D11_SHADER_MACRO macro[] = { @@ -101,6 +102,7 @@ void GSDevice11::SetupVS(VSSelector sel, const VSConstantBuffer* cb) {"VS_TME", str[1].c_str()}, {"VS_FST", str[2].c_str()}, {"VS_RTCOPY", str[3].c_str()}, + {"VS_WILDHACK", str[4].c_str()}, {NULL, NULL}, }; diff --git a/plugins/GSdx/GSTextureFX9.cpp b/plugins/GSdx/GSTextureFX9.cpp index a8e0d913b..fa86ccaca 100644 --- a/plugins/GSdx/GSTextureFX9.cpp +++ b/plugins/GSdx/GSTextureFX9.cpp @@ -67,13 +67,14 @@ void GSDevice9::SetupVS(VSSelector sel, const VSConstantBuffer* cb) if(i == m_vs.end()) { - string str[5]; + string str[6]; str[0] = format("%d", sel.bppz); str[1] = format("%d", sel.tme); str[2] = format("%d", sel.fst); str[3] = format("%d", sel.logz); str[4] = format("%d", sel.rtcopy); + str[5] = format("%d", sel.wildhack); D3DXMACRO macro[] = { @@ -82,6 +83,7 @@ void GSDevice9::SetupVS(VSSelector sel, const VSConstantBuffer* cb) {"VS_FST", str[2].c_str()}, {"VS_LOGZ", str[3].c_str()}, {"VS_RTCOPY", str[4].c_str()}, + {"VS_WILDHACK", str[5].c_str()}, {NULL, NULL}, }; diff --git a/plugins/GSdx/GSdx.rc b/plugins/GSdx/GSdx.rc index eb8c3ee18..40adf9b42 100644 --- a/plugins/GSdx/GSdx.rc +++ b/plugins/GSdx/GSdx.rc @@ -74,14 +74,14 @@ IDB_LOGO10 BITMAP "res\\logo10.bmp" // Dialog // -IDD_HACKS DIALOGEX 0, 0, 316, 133 +IDD_HACKS DIALOGEX 0, 0, 315, 203 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Hacks Configuration" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - DEFPUSHBUTTON "OK",IDOK,259,112,50,14 - GROUPBOX "Hack",IDC_STATIC,7,7,76,100 - GROUPBOX "Description",IDC_STATIC,86,7,223,100 + DEFPUSHBUTTON "OK",IDOK,258,182,50,14 + GROUPBOX "Hack",IDC_STATIC,7,7,76,165 + GROUPBOX "Description",IDC_STATIC,85,7,223,165 LTEXT "MSAA",IDC_STATIC,14,20,20,8 LTEXT "Skipdraw",IDC_STATIC,14,37,30,8 EDITTEXT IDC_SKIPDRAWHACKEDIT,45,35,24,14,ES_RIGHT | ES_AUTOHSCROLL @@ -94,8 +94,10 @@ BEGIN LTEXT "Works around some shadow problems",IDC_STATIC,92,54,120,8 LTEXT "May fix displaced fog or blend effects",IDC_STATIC,92,71,117,8 LTEXT "Fixes character sprites in some 2D games",IDC_STATIC,92,88,129,8 - LTEXT "USE AT YOUR OWN RISK!",IDC_STATIC,7,115,84,8,WS_DISABLED + LTEXT "USE AT YOUR OWN RISK!",IDC_STATIC,7,182,84,8,WS_DISABLED COMBOBOX IDC_MSAACB,35,18,44,63,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CONTROL "WildArmsOffset",IDC_WILDHACK,"Button",BS_AUTO3STATE | WS_TABSTOP,14,105,64,10 + LTEXT "Lowers GS precission. Can fix text in Wild Arms and others.",IDC_STATIC,92,105,200,11 END IDD_SHADEBOOST DIALOGEX 0, 0, 316, 129 @@ -256,9 +258,9 @@ BEGIN IDD_HACKS, DIALOG BEGIN LEFTMARGIN, 7 - RIGHTMARGIN, 309 + RIGHTMARGIN, 308 TOPMARGIN, 7 - BOTTOMMARGIN, 126 + BOTTOMMARGIN, 196 END IDD_SHADEBOOST, DIALOG diff --git a/plugins/GSdx/res/tfx.fx b/plugins/GSdx/res/tfx.fx index 96f4354ff..67da6f3ca 100644 --- a/plugins/GSdx/res/tfx.fx +++ b/plugins/GSdx/res/tfx.fx @@ -13,6 +13,7 @@ #define VS_BPPZ 0 #define VS_TME 1 #define VS_FST 1 +#define VS_WILDHACK 0 #endif #ifndef GS_IIP @@ -620,7 +621,13 @@ VS_OUTPUT vs_main(VS_INPUT input) { if(VS_FST) { + #if VS_WILDHACK == 1 + output.t.xy = (input.uv & 0x3FEF) * TextureScale; + #elif VS_WILDHACK == 2 + output.t.xy = (input.uv & 0x3FF7) * TextureScale; + #else output.t.xy = input.uv * TextureScale; + #endif output.t.w = 1.0f; } else @@ -767,7 +774,13 @@ VS_OUTPUT vs_main(VS_INPUT input) { if(VS_FST) { + #if VS_WILDHACK == 1 + output.t.xy = (input.t & 0x3FEF) * TextureScale; + #elif VS_WILDHACK == 2 + output.t.xy = (input.t & 0x3FF7) * TextureScale; + #else output.t.xy = input.t * TextureScale; + #endif output.t.w = 1.0f; } else diff --git a/plugins/GSdx/resource.h b/plugins/GSdx/resource.h index 766ba8365..8bcb3fcb2 100644 --- a/plugins/GSdx/resource.h +++ b/plugins/GSdx/resource.h @@ -88,6 +88,7 @@ #define IDC_CONTRAST_TEXT 2063 #define IDC_MSAACB 2070 #define IDC_HACKSBUTTON 2071 +#define IDC_WILDHACK 2072 #define IDC_COLORSPACE 3000 #define IDR_CONVERT_FX 10000 #define IDR_TFX_FX 10001 @@ -106,7 +107,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 10012 #define _APS_NEXT_COMMAND_VALUE 32771 -#define _APS_NEXT_CONTROL_VALUE 2072 +#define _APS_NEXT_CONTROL_VALUE 2073 #define _APS_NEXT_SYMED_VALUE 5000 #endif #endif From ac97331388ddccbed54c5909dcf5020a6322d00c Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Tue, 6 Mar 2012 22:36:24 +0000 Subject: [PATCH 28/83] GSdx: Fix for DX9 mode with the Wild Arms hack enabled. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5121 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSState.cpp | 11 ----------- plugins/GSdx/res/tfx.fx | 6 ++++-- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index bc281a98f..cf9d0ab92 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -24,7 +24,6 @@ #include "GSdx.h" //#define Offset_ST // Fixes Persona3 mini map alignment which is off even in software rendering -//#define Offset_UV // Fixes / breaks various titles GSState::GSState() : m_version(6) @@ -465,11 +464,6 @@ void GSState::GIFPackedRegHandlerUV(const GIFPackedReg* RESTRICT r) GSVector4i v = GSVector4i::loadl(r) & GSVector4i::x00003fff(); m_v.UV = (uint32)GSVector4i::store(v.ps32(v)); - -#ifdef Offset_UV - m_v.U = min((uint16)m_v.U, (uint16)(m_v.U - 4U)); - m_v.V = min((uint16)m_v.V, (uint16)(m_v.V - 4U)); -#endif } template @@ -659,11 +653,6 @@ void GSState::GIFRegHandlerST(const GIFReg* RESTRICT r) void GSState::GIFRegHandlerUV(const GIFReg* RESTRICT r) { m_v.UV = r->UV.u32[0] & 0x3fff3fff; - -#ifdef Offset_UV - m_v.U = min((uint16)m_v.U, (uint16)(m_v.U - 4U)); - m_v.V = min((uint16)m_v.V, (uint16)(m_v.V - 4U)); -#endif } template diff --git a/plugins/GSdx/res/tfx.fx b/plugins/GSdx/res/tfx.fx index 67da6f3ca..8ac4741bb 100644 --- a/plugins/GSdx/res/tfx.fx +++ b/plugins/GSdx/res/tfx.fx @@ -775,9 +775,11 @@ VS_OUTPUT vs_main(VS_INPUT input) if(VS_FST) { #if VS_WILDHACK == 1 - output.t.xy = (input.t & 0x3FEF) * TextureScale; + output.t.x = (input.t.x >= 16.0 ? input.t.x - 16.0 : input.t.x) * TextureScale.x; + output.t.y = (input.t.y >= 16.0 ? input.t.y - 16.0 : input.t.y) * TextureScale.y; #elif VS_WILDHACK == 2 - output.t.xy = (input.t & 0x3FF7) * TextureScale; + output.t.x = (input.t.x >= 8.0 ? input.t.x - 8.0 : input.t.x) * TextureScale.x; + output.t.y = (input.t.y >= 8.0 ? input.t.y - 8.0 : input.t.y) * TextureScale.y; #else output.t.xy = input.t * TextureScale; #endif From 144a7a13fb97cad66e6a3e123e920718c05e172f Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Wed, 7 Mar 2012 09:31:10 +0000 Subject: [PATCH 29/83] GSdx: Better DX9 implementation of the Wild Arms Hack. Thanks, KrossX :p git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5122 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSSettingsDlg.cpp | 2 +- plugins/GSdx/res/tfx.fx | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/GSdx/GSSettingsDlg.cpp b/plugins/GSdx/GSSettingsDlg.cpp index 1cd476990..bd035c0f8 100644 --- a/plugins/GSdx/GSSettingsDlg.cpp +++ b/plugins/GSdx/GSSettingsDlg.cpp @@ -263,7 +263,7 @@ void GSSettingsDlg::UpdateControls() // Hacks EnableWindow(GetDlgItem(m_hWnd, IDC_HACKS_ENABLED), hw); - //EnableWindow(GetDlgItem(m_hWnd, IDC_HACKSBUTTON), hw && IsDlgButtonChecked(m_hWnd, IDC_HACKS_ENABLED) == BST_CHECKED); + EnableWindow(GetDlgItem(m_hWnd, IDC_HACKSBUTTON), hw /*&& IsDlgButtonChecked(m_hWnd, IDC_HACKS_ENABLED) == BST_CHECKED*/); } } diff --git a/plugins/GSdx/res/tfx.fx b/plugins/GSdx/res/tfx.fx index 8ac4741bb..f75732f53 100644 --- a/plugins/GSdx/res/tfx.fx +++ b/plugins/GSdx/res/tfx.fx @@ -775,13 +775,13 @@ VS_OUTPUT vs_main(VS_INPUT input) if(VS_FST) { #if VS_WILDHACK == 1 - output.t.x = (input.t.x >= 16.0 ? input.t.x - 16.0 : input.t.x) * TextureScale.x; - output.t.y = (input.t.y >= 16.0 ? input.t.y - 16.0 : input.t.y) * TextureScale.y; + output.t.x = (frac(floor(input.t.x / 16.0)/2.0) > 0.4 ? input.t.x - 16.0 : input.t.x) * TextureScale.x; + output.t.y = (frac(floor(input.t.y / 16.0)/2.0) > 0.4 ? input.t.y - 16.0 : input.t.y) * TextureScale.y; #elif VS_WILDHACK == 2 - output.t.x = (input.t.x >= 8.0 ? input.t.x - 8.0 : input.t.x) * TextureScale.x; - output.t.y = (input.t.y >= 8.0 ? input.t.y - 8.0 : input.t.y) * TextureScale.y; + output.t.x = (frac(floor(input.t.x / 8.0)/2.0) > 0.4 ? input.t.x - 8.0 : input.t.x) * TextureScale.x; + output.t.y = (frac(floor(input.t.y / 8.0)/2.0) > 0.4 ? input.t.y - 8.0 : input.t.y) * TextureScale.y; #else - output.t.xy = input.t * TextureScale; + output.t.xy = input.t * TextureScale; #endif output.t.w = 1.0f; } From 9aa9808c2ff2b939effc755c372ce1d98b0028ab Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Wed, 7 Mar 2012 09:58:38 +0000 Subject: [PATCH 30/83] GSdx: Mouse over descriptions for the hacks. Thanks to KrossX again, these are great :) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5123 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSSettingsDlg.cpp | 61 ++++++++++++++++++++++++++++++++-- plugins/GSdx/GSSettingsDlg.h | 18 ++++++++++ plugins/GSdx/GSdx.rc | 7 +--- plugins/GSdx/resource.h | 3 +- 4 files changed, 79 insertions(+), 10 deletions(-) diff --git a/plugins/GSdx/GSSettingsDlg.cpp b/plugins/GSdx/GSSettingsDlg.cpp index bd035c0f8..b6bccc52a 100644 --- a/plugins/GSdx/GSSettingsDlg.cpp +++ b/plugins/GSdx/GSSettingsDlg.cpp @@ -411,7 +411,7 @@ void GSHacksDlg::OnInit() cb2msaa[j] = i; char text[32] = {0}; - sprintf(text, "%dx ????", i); + sprintf(text, "%dx ", i); SendMessage(GetDlgItem(m_hWnd, IDC_MSAACB), CB_ADDSTRING, 0, (LPARAM)text); } @@ -425,15 +425,70 @@ void GSHacksDlg::OnInit() SendMessage(GetDlgItem(m_hWnd, IDC_SKIPDRAWHACK), UDM_SETRANGE, 0, MAKELPARAM(1000, 0)); SendMessage(GetDlgItem(m_hWnd, IDC_SKIPDRAWHACK), UDM_SETPOS, 0, MAKELPARAM(theApp.GetConfig("UserHacks_SkipDraw", 0), 0)); + + + // Hacks descriptions + SetWindowText(GetDlgItem(m_hWnd, IDC_HACK_DESCRIPTION), ""); // Blank it + + sprintf(Hack[HK_MSAA].description, "Multisample Anti-Aliasing\n\nEnables hardware Anti-Aliasing. Needs lots of memory." + " The Z-24 modes might need to have LogarithmicZ to compensate for the bits lost (DX9 mode)."); + sprintf(Hack[HK_SKIPDRAW].description, "Skipdraw\n\nSkips drawing n surfaces completely. " + "Use it, for example, to try and get rid of messed up post processing effects." + " Try values between 1 and 100."); + sprintf(Hack[HK_ALPHA].description, "Alpha Hack\n\nDifferent alpha handling. Works around some shadow problems."); + sprintf(Hack[HK_OFFSET].description, "Halfpixel\n\nMight fix some misaligned fog, bloom, or blend effect."); + sprintf(Hack[HK_SPRITE].description, "Sprite Hack\n\nHelps getting rid of black inner lines in some filtered sprites." + " Half option should be the preferred one, for Mana Khemia and ArTonelico for example." + " Full should be used for Tales of Destiny."); + sprintf(Hack[HK_WILD].description, "WildArms\n\nLowers the GS precission to avoid gaps between pixels when" + " upscaling. Full option fixes the text on WildArms games, while Half option might improve portraits" + " in ArTonelico for example."); + + SetNotHover(-1); } void GSHacksDlg::UpdateControls() {} -bool GSHacksDlg::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) +void GSHacksDlg::SetNotHover(int skip) { - switch(message) + for(int i=0; i= 20 && pos.x <= 120) + { + int isHovering = -1; + + if(pos.y >= 28 && pos.y <= 52) isHovering = HK_MSAA; + else if(pos.y >= 54 && pos.y <= 82) isHovering = HK_SKIPDRAW; + else if(pos.y >= 84 && pos.y <= 106) isHovering = HK_ALPHA; + else if(pos.y >= 112 && pos.y <= 134) isHovering = HK_OFFSET; + else if(pos.y >= 140 && pos.y <= 164) isHovering = HK_SPRITE; + else if (pos.y >= 168 && pos.y <= 190) isHovering = HK_WILD; + + if(isHovering > -1 && !Hack[isHovering].isHovered) + { + Hack[isHovering].isHovered = true; + SetWindowText(GetDlgItem(m_hWnd, IDC_HACK_DESCRIPTION), Hack[isHovering].description); + SetNotHover(isHovering); + } + } + + + } break; + case WM_COMMAND: { int id = LOWORD(wParam); diff --git a/plugins/GSdx/GSSettingsDlg.h b/plugins/GSdx/GSSettingsDlg.h index 5cd394530..76eb3729e 100644 --- a/plugins/GSdx/GSSettingsDlg.h +++ b/plugins/GSdx/GSSettingsDlg.h @@ -47,7 +47,25 @@ class GSHacksDlg : public GSDialog bool isdx9; + enum + { + HK_MSAA, + HK_SKIPDRAW, + HK_ALPHA, + HK_OFFSET, + HK_SPRITE, + HK_WILD, + HK_SIZE + }; + + struct + { + bool isHovered; + char description[1024]; + } Hack[HK_SIZE]; + void UpdateControls(); + void SetNotHover(int i); protected: void OnInit(); diff --git a/plugins/GSdx/GSdx.rc b/plugins/GSdx/GSdx.rc index 40adf9b42..c54234815 100644 --- a/plugins/GSdx/GSdx.rc +++ b/plugins/GSdx/GSdx.rc @@ -89,15 +89,10 @@ BEGIN CONTROL "Alpha",IDC_ALPHAHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,54,34,10 CONTROL "Half-pixel Offset",IDC_OFFSETHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,71,65,10 CONTROL "Sprite",IDC_SPRITEHACK,"Button",BS_AUTO3STATE | WS_TABSTOP,14,88,35,10 - LTEXT "It tickles your GPU's fancy",IDC_STATIC,92,20,82,8 - LTEXT "Makes Kratos a sad panda. Don't try with values over 9000.",IDC_STATIC,92,37,187,8 - LTEXT "Works around some shadow problems",IDC_STATIC,92,54,120,8 - LTEXT "May fix displaced fog or blend effects",IDC_STATIC,92,71,117,8 - LTEXT "Fixes character sprites in some 2D games",IDC_STATIC,92,88,129,8 LTEXT "USE AT YOUR OWN RISK!",IDC_STATIC,7,182,84,8,WS_DISABLED COMBOBOX IDC_MSAACB,35,18,44,63,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP CONTROL "WildArmsOffset",IDC_WILDHACK,"Button",BS_AUTO3STATE | WS_TABSTOP,14,105,64,10 - LTEXT "Lowers GS precission. Can fix text in Wild Arms and others.",IDC_STATIC,92,105,200,11 + LTEXT "TEXT_GOES_HERE",IDC_HACK_DESCRIPTION,92,20,209,145 END IDD_SHADEBOOST DIALOGEX 0, 0, 316, 129 diff --git a/plugins/GSdx/resource.h b/plugins/GSdx/resource.h index 8bcb3fcb2..eea77d33f 100644 --- a/plugins/GSdx/resource.h +++ b/plugins/GSdx/resource.h @@ -89,6 +89,7 @@ #define IDC_MSAACB 2070 #define IDC_HACKSBUTTON 2071 #define IDC_WILDHACK 2072 +#define IDC_HACK_DESCRIPTION 2073 #define IDC_COLORSPACE 3000 #define IDR_CONVERT_FX 10000 #define IDR_TFX_FX 10001 @@ -107,7 +108,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 10012 #define _APS_NEXT_COMMAND_VALUE 32771 -#define _APS_NEXT_CONTROL_VALUE 2073 +#define _APS_NEXT_CONTROL_VALUE 2074 #define _APS_NEXT_SYMED_VALUE 5000 #endif #endif From 1595136a9de0c2e42600c99eab71e8b31dcae544 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Thu, 8 Mar 2012 17:18:22 +0000 Subject: [PATCH 31/83] GSdx: Another refinement to the Wild Arms hack by KrossX. The hack now only applies to one kind of geometry (sent using the unpacked UV handler). This works nicer in Wild Arms as it fixes "jumpy" characters. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5124 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSCrc.cpp | 1 + plugins/GSdx/GSRendererDX.cpp | 4 +--- plugins/GSdx/GSRendererDX.h | 2 ++ plugins/GSdx/GSRendererDX11.cpp | 13 +++++++++++-- plugins/GSdx/GSRendererDX9.cpp | 10 +++++++++- plugins/GSdx/GSState.cpp | 6 +++++- plugins/GSdx/GSState.h | 2 ++ plugins/GSdx/GSTextureCache.cpp | 4 +--- plugins/GSdx/GSTextureCache.h | 2 -- plugins/GSdx/GSTextureFX11.cpp | 4 +--- plugins/GSdx/GSTextureFX9.cpp | 4 +--- plugins/GSdx/res/tfx.fx | 17 +---------------- 12 files changed, 35 insertions(+), 34 deletions(-) diff --git a/plugins/GSdx/GSCrc.cpp b/plugins/GSdx/GSCrc.cpp index 09d727613..cf4565f8e 100644 --- a/plugins/GSdx/GSCrc.cpp +++ b/plugins/GSdx/GSCrc.cpp @@ -308,6 +308,7 @@ CRC::Game CRC::m_games[] = {0x60A42FF5, MidnightClub3, US, 0}, //remix {0x4B1A0FFA, XmenOriginsWolverine, US, 0}, {0xBFF3DBCB, CallofDutyFinalFronts, US, 0}, + {0xB78A5F5A, CallofDutyFinalFronts, EU, 0}, {0xD03D4C77, SpyroNewBeginning, US, 0}, {0x0EE5646B, SpyroNewBeginning, EU, 0}, {0x7ACF7E03, SpyroNewBeginning, NoRegion, 0}, diff --git a/plugins/GSdx/GSRendererDX.cpp b/plugins/GSdx/GSRendererDX.cpp index e4cf03905..1f853ed3f 100644 --- a/plugins/GSdx/GSRendererDX.cpp +++ b/plugins/GSdx/GSRendererDX.cpp @@ -31,6 +31,7 @@ GSRendererDX::GSRendererDX(GSTextureCache* tc, const GSVector2& pixelcenter) m_fba = !!theApp.GetConfig("fba", 1); UserHacks_AlphaHack = !!theApp.GetConfig("UserHacks_AlphaHack", 0) && !!theApp.GetConfig("UserHacks", 0); + UserHacks_WildHack = !!theApp.GetConfig("UserHacks", 0) ? theApp.GetConfig("UserHacks_WildHack", 0) : 0; } GSRendererDX::~GSRendererDX() @@ -145,9 +146,6 @@ void GSRendererDX::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sourc vs_sel.logz = dev->HasDepth32() ? 0 : m_logz ? 1 : 0; vs_sel.rtcopy = !!rtcopy; - if(tex) vs_sel.wildhack = tex->m_wildhack_t; - else vs_sel.wildhack = 0; - // The real GS appears to do no masking based on the Z buffer format and writing larger Z values // than the buffer supports seems to be an error condition on the real GS, causing it to crash. // We are probably receiving bad coordinates from VU1 in these cases. diff --git a/plugins/GSdx/GSRendererDX.h b/plugins/GSdx/GSRendererDX.h index b01e46d1d..c3dc63127 100644 --- a/plugins/GSdx/GSRendererDX.h +++ b/plugins/GSdx/GSRendererDX.h @@ -36,6 +36,8 @@ protected: virtual void SetupIA() = 0; virtual void UpdateFBA(GSTexture* rt) {} + int UserHacks_WildHack; + public: GSRendererDX(GSTextureCache* tc, const GSVector2& pixelcenter = GSVector2(0, 0)); virtual ~GSRendererDX(); diff --git a/plugins/GSdx/GSRendererDX11.cpp b/plugins/GSdx/GSRendererDX11.cpp index 2feb6c7ec..a6e48d836 100644 --- a/plugins/GSdx/GSRendererDX11.cpp +++ b/plugins/GSdx/GSRendererDX11.cpp @@ -45,8 +45,17 @@ void GSRendererDX11::SetupIA() if(dev->IAMapVertexBuffer(&ptr, sizeof(GSVertex), m_vertex.next)) { - GSVector4i::storent(ptr, m_vertex.buff, sizeof(GSVertex) * m_vertex.next); - + GSVector4i::storent(ptr, m_vertex.buff, sizeof(GSVertex) * m_vertex.next); + + if(UserHacks_WildHack && !isPackedUV_HackFlag) + { + GSVertex* RESTRICT d = (GSVertex*)ptr; + + for(unsigned int i = 0; i < m_vertex.next; i++, d++) + if(PRIM->TME && PRIM->FST) + d->UV &= UserHacks_WildHack == 1 ? 0x3FEF3FEF : 0x3FF73FF7; + } + dev->IAUnmapVertexBuffer(); } diff --git a/plugins/GSdx/GSRendererDX9.cpp b/plugins/GSdx/GSRendererDX9.cpp index ab0143e17..d33d7b32e 100644 --- a/plugins/GSdx/GSRendererDX9.cpp +++ b/plugins/GSdx/GSRendererDX9.cpp @@ -199,7 +199,15 @@ void GSRendererDX9::SetupIA() { if(PRIM->FST) { - t = GSVector4(GSVector4i::load(s->UV).upl16()); + if(UserHacks_WildHack && !isPackedUV_HackFlag) + { + t = GSVector4(GSVector4i::load(UserHacks_WildHack == 1? + s->UV & 0x3FEF3FEF : s->UV & 0x3FF73FF7).upl16()); + + //printf("GSDX: %08X | D3D9(%d) %s\n", s->UV & 0x3FEF3FEF, m_vertex.next, i == 0 ? "*" : ""); + } + else + t = GSVector4(GSVector4i::load(s->UV).upl16()); } else { diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index cf9d0ab92..4cf8f26e6 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -464,6 +464,8 @@ void GSState::GIFPackedRegHandlerUV(const GIFPackedReg* RESTRICT r) GSVector4i v = GSVector4i::loadl(r) & GSVector4i::x00003fff(); m_v.UV = (uint32)GSVector4i::store(v.ps32(v)); + + isPackedUV_HackFlag = true; } template @@ -652,7 +654,9 @@ void GSState::GIFRegHandlerST(const GIFReg* RESTRICT r) void GSState::GIFRegHandlerUV(const GIFReg* RESTRICT r) { - m_v.UV = r->UV.u32[0] & 0x3fff3fff; + m_v.UV = r->UV.u32[0] & 0x3fff3fff; + + isPackedUV_HackFlag = false; } template diff --git a/plugins/GSdx/GSState.h b/plugins/GSdx/GSState.h index 8e4431d7b..6a16caba8 100644 --- a/plugins/GSdx/GSState.h +++ b/plugins/GSdx/GSState.h @@ -194,6 +194,8 @@ public: GSDump m_dump; bool m_nativeres; + bool isPackedUV_HackFlag; + int s_n; bool s_dump; bool s_save; diff --git a/plugins/GSdx/GSTextureCache.cpp b/plugins/GSdx/GSTextureCache.cpp index 2270a5c28..73be0b69a 100644 --- a/plugins/GSdx/GSTextureCache.cpp +++ b/plugins/GSdx/GSTextureCache.cpp @@ -26,7 +26,7 @@ GSTextureCache::GSTextureCache(GSRenderer* r) : m_renderer(r) { m_spritehack = !!theApp.GetConfig("UserHacks", 0) ? theApp.GetConfig("UserHacks_SpriteHack", 0) : 0; - m_wildhack = !!theApp.GetConfig("UserHacks", 0) ? theApp.GetConfig("UserHacks_WildHack", 0) : 0; + UserHacks_HalfPixelOffset = !!theApp.GetConfig("UserHacks", 0) && !!theApp.GetConfig("UserHacks_HalfPixelOffset", 0); m_paltex = !!theApp.GetConfig("paltex", 0); @@ -584,8 +584,6 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con bool hack = false; - src->m_wildhack_t = m_wildhack; // dunno where to put it really, but works fine here. - if(dst == NULL) { if(m_spritehack && (TEX0.PSM == PSM_PSMT8 || TEX0.PSM == PSM_PSMT8H)) diff --git a/plugins/GSdx/GSTextureCache.h b/plugins/GSdx/GSTextureCache.h index 7303f94a2..726917048 100644 --- a/plugins/GSdx/GSTextureCache.h +++ b/plugins/GSdx/GSTextureCache.h @@ -76,7 +76,6 @@ public: bool m_complete; bool m_repeating; bool m_spritehack_t; - int m_wildhack_t; vector* m_p2t; public: @@ -121,7 +120,6 @@ protected: list m_dst[2]; bool m_paltex; int m_spritehack; - int m_wildhack; uint8* m_temp; virtual Source* CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* t = NULL); diff --git a/plugins/GSdx/GSTextureFX11.cpp b/plugins/GSdx/GSTextureFX11.cpp index 7227c877d..84189a7d8 100644 --- a/plugins/GSdx/GSTextureFX11.cpp +++ b/plugins/GSdx/GSTextureFX11.cpp @@ -88,13 +88,12 @@ void GSDevice11::SetupVS(VSSelector sel, const VSConstantBuffer* cb) if(i == m_vs.end()) { - string str[5]; + string str[4]; str[0] = format("%d", sel.bppz); str[1] = format("%d", sel.tme); str[2] = format("%d", sel.fst); str[3] = format("%d", sel.rtcopy); - str[4] = format("%d", sel.wildhack); D3D11_SHADER_MACRO macro[] = { @@ -102,7 +101,6 @@ void GSDevice11::SetupVS(VSSelector sel, const VSConstantBuffer* cb) {"VS_TME", str[1].c_str()}, {"VS_FST", str[2].c_str()}, {"VS_RTCOPY", str[3].c_str()}, - {"VS_WILDHACK", str[4].c_str()}, {NULL, NULL}, }; diff --git a/plugins/GSdx/GSTextureFX9.cpp b/plugins/GSdx/GSTextureFX9.cpp index fa86ccaca..a8e0d913b 100644 --- a/plugins/GSdx/GSTextureFX9.cpp +++ b/plugins/GSdx/GSTextureFX9.cpp @@ -67,14 +67,13 @@ void GSDevice9::SetupVS(VSSelector sel, const VSConstantBuffer* cb) if(i == m_vs.end()) { - string str[6]; + string str[5]; str[0] = format("%d", sel.bppz); str[1] = format("%d", sel.tme); str[2] = format("%d", sel.fst); str[3] = format("%d", sel.logz); str[4] = format("%d", sel.rtcopy); - str[5] = format("%d", sel.wildhack); D3DXMACRO macro[] = { @@ -83,7 +82,6 @@ void GSDevice9::SetupVS(VSSelector sel, const VSConstantBuffer* cb) {"VS_FST", str[2].c_str()}, {"VS_LOGZ", str[3].c_str()}, {"VS_RTCOPY", str[4].c_str()}, - {"VS_WILDHACK", str[5].c_str()}, {NULL, NULL}, }; diff --git a/plugins/GSdx/res/tfx.fx b/plugins/GSdx/res/tfx.fx index f75732f53..b308fe999 100644 --- a/plugins/GSdx/res/tfx.fx +++ b/plugins/GSdx/res/tfx.fx @@ -13,7 +13,6 @@ #define VS_BPPZ 0 #define VS_TME 1 #define VS_FST 1 -#define VS_WILDHACK 0 #endif #ifndef GS_IIP @@ -621,13 +620,7 @@ VS_OUTPUT vs_main(VS_INPUT input) { if(VS_FST) { - #if VS_WILDHACK == 1 - output.t.xy = (input.uv & 0x3FEF) * TextureScale; - #elif VS_WILDHACK == 2 - output.t.xy = (input.uv & 0x3FF7) * TextureScale; - #else output.t.xy = input.uv * TextureScale; - #endif output.t.w = 1.0f; } else @@ -774,15 +767,7 @@ VS_OUTPUT vs_main(VS_INPUT input) { if(VS_FST) { - #if VS_WILDHACK == 1 - output.t.x = (frac(floor(input.t.x / 16.0)/2.0) > 0.4 ? input.t.x - 16.0 : input.t.x) * TextureScale.x; - output.t.y = (frac(floor(input.t.y / 16.0)/2.0) > 0.4 ? input.t.y - 16.0 : input.t.y) * TextureScale.y; - #elif VS_WILDHACK == 2 - output.t.x = (frac(floor(input.t.x / 8.0)/2.0) > 0.4 ? input.t.x - 8.0 : input.t.x) * TextureScale.x; - output.t.y = (frac(floor(input.t.y / 8.0)/2.0) > 0.4 ? input.t.y - 8.0 : input.t.y) * TextureScale.y; - #else - output.t.xy = input.t * TextureScale; - #endif + output.t.xy = input.t * TextureScale; output.t.w = 1.0f; } else From 1b7bbcdb3dd5103afccbd3aa6e16c4fb0ba428e0 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Thu, 8 Mar 2012 17:43:21 +0000 Subject: [PATCH 32/83] GSdx: Sprite hack update. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5125 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/res/tfx.fx | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/plugins/GSdx/res/tfx.fx b/plugins/GSdx/res/tfx.fx index b308fe999..a1ba306cd 100644 --- a/plugins/GSdx/res/tfx.fx +++ b/plugins/GSdx/res/tfx.fx @@ -412,20 +412,8 @@ float4 sample(float2 st, float q) } if(PS_LTF) - { - #if PS_SPRITEHACK - c[0].rgb *= c[0].a; - c[1].rgb *= c[1].a; - c[2].rgb *= c[2].a; - c[3].rgb *= c[3].a; - #endif - + { t = lerp(lerp(c[0], c[1], dd.x), lerp(c[2], c[3], dd.x), dd.y); - - #if PS_SPRITEHACK - t.rgb /= t.a; - if(t.a < 0.25) t.a = 0; - #endif } else { @@ -435,10 +423,6 @@ float4 sample(float2 st, float q) if(PS_FMT == FMT_32) { - #if PS_SPRITEHACK - if(t.a < 0.25) t.a = 0; - #endif - #if SHADER_MODEL <= 0x300 if(PS_RT) t.a *= 128.0f / 255; #endif @@ -532,14 +516,19 @@ void atst(float4 c) { // nothing to do } - else if(PS_ATST == 2 || PS_ATST == 3) // l, le + else if(PS_ATST == 2) // l + { + #if PS_SPRITEHACK == 0 + clip(AREF - a); + #endif + } + else if(PS_ATST == 3) // le { clip(AREF - a); } else if(PS_ATST == 4) // e { - clip(0.5f - abs(a - AREF)); - } + clip(0.5f - abs(a - AREF)); } else if(PS_ATST == 5 || PS_ATST == 6) // ge, g { clip(a - AREF); From 4079af2ed71c62ba12e59925a76301c79be89d53 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Sat, 10 Mar 2012 20:11:21 +0000 Subject: [PATCH 33/83] i18n: update japan. Add french. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5126 96395faa-99c1-11dd-bbfe-3dabce05a288 --- bin/Langs/fr_FR/pcsx2_Iconized.mo | Bin 0 -> 19737 bytes bin/Langs/fr_FR/pcsx2_Main.mo | Bin 0 -> 56326 bytes bin/Langs/ja_JP/pcsx2_Iconized.mo | Bin 20499 -> 21698 bytes bin/Langs/ja_JP/pcsx2_Main.mo | Bin 59238 -> 61070 bytes locales/fr_FR/pcsx2_Iconized.po | 593 +++++++ locales/fr_FR/pcsx2_Main.po | 2708 +++++++++++++++++++++++++++++ locales/ja_JP/pcsx2_Iconized.po | 575 +++--- locales/ja_JP/pcsx2_Main.po | 1350 ++++++-------- pcsx2/gui/i18n.cpp | 8 +- 9 files changed, 4116 insertions(+), 1118 deletions(-) create mode 100644 bin/Langs/fr_FR/pcsx2_Iconized.mo create mode 100644 bin/Langs/fr_FR/pcsx2_Main.mo create mode 100644 locales/fr_FR/pcsx2_Iconized.po create mode 100644 locales/fr_FR/pcsx2_Main.po diff --git a/bin/Langs/fr_FR/pcsx2_Iconized.mo b/bin/Langs/fr_FR/pcsx2_Iconized.mo new file mode 100644 index 0000000000000000000000000000000000000000..f460efb09cd4374b7c83086a4faf4c602761eda4 GIT binary patch literal 19737 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�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 J=4O-S{{R?7BisN0 literal 0 HcmV?d00001 diff --git a/bin/Langs/fr_FR/pcsx2_Main.mo b/bin/Langs/fr_FR/pcsx2_Main.mo new file mode 100644 index 0000000000000000000000000000000000000000..21fe742d8990c85d308e616e602082cdcdf57b57 GIT binary patch literal 56326 zcmb`Q2Yj7ZdH-J^35hev-s822E!nZ;6*80rN7itZSeCFnG6>=N>Pot?bg#I>wgP33 zhR`w!DZ8vf9Lf$92!w)4!Y&2MXrV3er>s&|D75MLe}B(&&U@c0DS@=r$FG0yIPZDS zc+RuVbI$$y6Aybu!r%HwCdt|0Yfng$pX&Uvx|<|l?@p3U;5Wb_@Yr=pvK-t4E(7Pl z$AHfT&jMc#o(jGjB&*~;unc|!ybkPJ@9AC#-oW*Tz^&jZ82&p7%z>~o1!CtTesy*Kgo&dfd)cf~= z>i@q1RsL^+YLB0S`tEN)^~Yl_^?IKL9?$g!0WSwt|6x%1JSSYg5IlWhAVs=Js-T0>o0&^;95F=4R}4c3w$1^cKti> zZ1AVx8Q?LSz5J`dbGY6N9s}M8?geiKuLD01o(Xnb>FKwC>W>>hwd+i{embc4UlQgt^#S&WDKOKl9z$1&zC@@|3SFEA5{A4!3Q~pS-$3>E zWf0d!uom!7LACqW!E?bMg8J@}gHC@}f#-AmB2eXj52*Tn5>$TQ1J&+lZ-pm;TS1Mh z{h-SATu|lzWAIAw9iYDRFQCeI>{Z?#L*NlyPlJbpbx`dw2a2Aa8}7deR5|VdPXj*! z>U&=S)!*L%HEtgOMQ0}>bi^;ZKwWPEmG6z9>OBRj{Bxk_@GYR~_W>{kzX~e-ufcub zBd>P)tAH9OuK?GAzXVe-y(UQ>3-*GCfhAD&xfxVD%z_N%kA!w@-qr!TSTA zyN$APeHFM2ybaWMZUQ{XYoPl51>mE>4}&Yg zPkgCy*ojb`(vQ!;4|U* zw?LKm`=I#JVIwYwo(zt0{SHviA2I6vdoHN&T?Fm|F9TPBF9nYWKL|of$)`cl#R*SH zlBa;sPlp91Rp z&j`= zey;#K!Mnh2@LS;d;4yo=KR1ACuYT}q@K#Xoe+9e(JpWp!qrITY@sxm11J%AS0M#CU z42n+w1RMhI0FMWM0gApJMPn)55#T29IPhX{3#fFr1iTFtoxB!QzrPXG_`CyDK1W>d z^*stajq9ty4sb81d|n8y178EGJw6MHp1%ej2Ywqo9sC)Xf=5BTYNs`z`e_Kf0NevE z2cH9;0sbkdbRP@Xe-A#1>)(LNch3{O{u7|STLn)7p9-oTF9t;qw}Yai*Mbb4;gXzo&r7q>iZ|$c){E6Xb_T3&I48M{h<2!>7cbMxQgrBLFN0= zfS&@XQu1X``EK0n{kR=eKTm-gZ~H;z^L9|}`(9A(b`Pk2|0bw<|0}5ck1V>pJPFkM zSA%-*8Q|IAZJ_eI1JwKP0#(0H2mB_e{C^6b2Oc}_*InSbTwepO0B;7>AAbOjf?o#p z-ub1#XF%n99k>>p2KD_{fhqU_@Uh_6K=u0rp!(sk39ruyp!nQlLG|M>C_0$}F9M$h zYJ7eW)cZdJ_5FVXF9A=R^!ks2S9AS5umk)e_-ODqpy)rD^8P#-RQsI?sy$bR>x)5+ zpDm!?djhEOdL5|m6~pzjK=s>gpxWbAU=R2s@Hybha*|vQ9s(}_{|S6Dc;d~jht)xq z`@P^s@W<71x)43Esl>?y9%vUxUYTeblVe^=V))*A;LJ_-+u^oBR?~x@(@|^5;5G_iqF> zZr%@yPCf~Cfjj!&&6$qsNWsP=ybsPg|2sP_33sCph=cRsxx6y3ZMJP~|9sP_95 zsC@4SuLM^#oSur{O0HiJ@Ezczxc)LY3VsdzGqAJi^#3>DNnHOFJQ;k{e*gaIApepA z|1AT*4xRvh7gYQIDqLTAz{|A*ypa1PP~UrXxPCpjf$J}W7lVf%^nShq?BjYrcsTfB z@HFr*K$YX`0e=Es%Jn1X{JqP;$8y~SmHt)WI`BQ9+V|Vw8t~Vk+H(b+tNS;BonRAO z3%(vy|9v*#H$b)T_d&Jmzk^EO`BdjmPXJHldInU!&jnS^kAoLK68;E^{*HUP)9X%f zIoIz1HD3M-6kU7+JPZ6Gcm{a*GrS(>fluT5Vi1;?+y!cUo%&4I-!24)xPA$^3H)1- zu1}78R+78{d^V_ldhD~E-*tl;uRY+A;FfTG4XE)v2CCopf_iU1sB%6FRDawC>b;i+ zd^LDH*KY=u?_HqY`v`a#cps>K{~V}(`674>_ybV&{uQYF4u6h+=QvQ$PY3n>N>I<& zfcpL>@LKTFaQ(7?uLRX@uLo6+4}xmX`@j+KyWnHNO)!TigL^<&P4YodoxYv~D&14St>C?&+Woj&oxh(B>Usls9(Wn3`rZJlznY-N;jQ3x;A_JDUx6ym zQ7`oN90Ju}+d+^_};I`yT=y&Go&Y+V>0KYH-DioUXTlH*$Rk_)PGKKR{OnUjV8c z=l!AQw+>W37l91T{0gXc`!RR{c=U_Cy)Ooz$n}fB?cfi=A@Guy zxIBF}*va*WK$Yh^pxXV)mpVON4=UfMgDb(;gDLoz;4<)g;12L-;PqhN%RK$-LDAzq zpz{9?cp`Z8A9;VD3yP0i45r{VP~V*a*Mlzr)t(;&^_`D}`=0^DA07Z#fM>ki`~PxK z-+LN(68HvC`P~KT{V#x`=Wl@O@1KLJ*8`y5JL?tR@0-DMxxOA$`_6&N?**W~_Zo05 zcn_$4`7wAr_)AdbI_!4W`&NLuKLj2IUJpJ7ya`l4RKa2J9#Hgk44tp^gP`bd52${u zfv14457&2rgIxb3xCQKZW$=H27jgZ0a1(ggt6ZPB1XR241Favy64$Q>_bT11U0<05 z&*u6~;Kks_zze}&gDJT7H7;+4LAA^8fv1AEfoFkl0tdi*z;5uc*E*eV0@ZFW25o$R zM{@lk@C5J^;BxRQpxWtQ!85=IK(*&7uk-vjf$EnL@Jz4*o(ixHd=br*KKE4m8 z;QinR@RZkkdAEWcTt5j^J3Svf8vHPL9e6LO{L(*hdfo!69bN}&{C)`(J^u%&{$Ke9 z=i6PN`e_rm0~`WHXRig-FK-1^j&FgR!N|={x}4x zUU!3!1n0r?z(fl4yu2C1@?oFxDy!$4uX#YKM1Nl zKLV;ep9Ra{mqFFP_Gp@Z+G`<(~td^Dgi2 z?chz^uYi-_7r-mQi{9<+asX62zaLx%-V^ZC;OSg{1w0D;38-|x25$tD_jo@(2~_(X z1XZ7>fuh$Jg6i*kLDBgc?{&V|4XWKXgGYb^Ucry6;fZqYtFTVy= z?!)f(_s#@Wug8HZ-yU!!H~~Hld=aR2J?bM~-c!KixxNs595?{#drt-Rz2}4D;A_CM z!Q`XnDK9?+u{( z`<i=)xrQouUdp`Z3=yw`i1HKkix$gr{0>2Ed2fq(q1fKp0*FQ!AJ{8=;{kMUA z;EzCkr+ePV!)8$YaU4`WhrlO-e+#PI7yqUA-!ynG*G~mS_pb)6oj}#&ouJz3bD-$z zYvB3dzkq7DlRoL~xe^p#832`TJ9r~l0#(m>@P*(n!QJ4~?{&HIH{cGgkGs$Hr~=r} z^&Ozb+fP8H@A(vE1YZh{g2#T^{TxpM4{`kgQ1txd&-gev1giW$2OkeU=Ce*`+rejW z{XURK$)?Y_{Q56&fa@21-uc#-K=s4fU-0Ma!6B~i0j~y+{44+d7^v~_cJNW)$3d0j zlc3%|?u)K(tpG(w1EA=94phBv2i2ZG3C~abYnK;;py=x9;2!XEpx!(GOU?&-!Hrz+ z1uq9*0V>^>!1dsoFZ;N-0bI%Tt)R;HF7Qd<`#^?va^hEOdhz*m61-~-@A;1%C+`fY%^{v+@_@H655k3gkA>Ti8qUjtsj zbrI|V-w2A{zZvjH;E7!S2D}(N`tQ7b`as=(4ygQZ2RDKr0M#!)1RnuDng9NXW1TMe z`yO}{M-Rshek=KRJ$ocN82Bbm&jbHL_xL-5(n|sd<=f{Azh4aU7|M?u> z;(9#Xdpg(p+r#k*jx8L|>uUbozS_M};(x4cEH2f$PIKj^kb(oaY$i zh=1bkZ{+$BJpVNa+cbZ|A8`IQ&R2q;1z!N30R9Wd`#4^~aVqy39H(-wzkZHQ953Mb zXO8&y`=m)jna<+;RXlhuSPu#Ql=Dp-w{WZo=|0B!G|x`~PX-$te-hFk8Pe#o$n(>< zehqjZNBryL{3P!GbMD@FINt(F27H>Mn>1@Uz7w83k9$?l-xscT28{XsBPTD(-4kz% zf5yMLcnpVldj9W^dFOlFIGSSv$4b7La_`=d*H-R5A)LR4bNwAf8vUIEPV(%{9Df_q z{8zwrJo|7szZCpD$349BN{+3ZKLPw#aGGNy=U)XM!#k@(-sf}gV;s-n{!79C$051( zhg?6NWeSND3uv#;mUtP6=xCfzEXhiAobU+`@1T?dYE+{AG@Y5y41 z-%5@j@ceZgzu~x=>u-U-AuhT@f??N{G5A|?cV_ZK0N$TNmN)dY)g)`T3+d1iqTHdl1T8I=l65IhGPZCzj3{hV_SIs*POqc^MB9Dl{JmwR8~nB@3-j@NSU zRMNf&%>SLp#T&wn>%m`#^CQ4J!ueWoIQQOb!~OpNH*^2@z%$5Oe_amApMyOdtHXN- zI6sl|3pifF`B^bN*Ee(h4UTVe9Le?n<9I9Qp8#LXae!kL$G>xLJNQ8k{aplBz~jIj z;1I`ubG{nX--Qmz#oSxQF~$-9zRJnV!u5V|hU=5SlR|=>0lO&YZ#X{@e1PYBIBw_q z=NzBncqZ5H0QL7N&h_`%fI9Eyd{wCHPdPuFdrk1dkmjdcpA*h+1aISbN4WkPcr5S! zO}JKm|HAoOz?X-6uLN)8x`X3Pj$6b1UEnu4{*mKL9RJNT{hdO7gMONnx&M0{KhX8E zWuvuHy`GNjOB>a6va0_ZQ>Aotx;a^{qTa0N;+Dol%~6rW!tNbQcv37 zoSiNg3yspc9i>WPrnIiFR?<~}X}Z)Xr3cE>)9Ln+o$20ES}W}@)f%O7ZZ@XUj=n;r zSeowWPSX6}aC5p*ZWLy_RyMo3Mys_3CrR2lUYaQIWOcH#o~A3uyX{}Pvfg&hT^@JV z_g7Yv$e#68XJ!hO@#%7MuZcys!bf8wN)|AP>!A7Z4*YmVeZKM;`W@WrP zO?T1?J05rG`t@C#Hd29Nb!N6aU8-^VlxCSWOAF~#wcbekMt6C&hKH|Rn~seQtWEi> zPBx~cEbH!v_|id^}oq^uw0`kJIgbr_Ab*`LsyQ_1-0^c$t%9xD>zY|o~|A! zS0>X5DwmE|sh1j|bg)c*)mmEi>q5G}FkK#}Y13JwjGkr7lsAv-jY6$qIn=5%G)kp( zKrc2c`zqA~6`FH;oK{nlR7$1sx(E!4C{r9_WiS8dkP`dqzHnn`C0bLmuJe@S^XCnn0pa;eftXG$~G z+MJ3<2a>v|>QbsuibdI1XG@isu?V2qpejpeon^SznysSbjGDc)>QtdNexOh*tsAeE z>4bWBvZ{A>c6ttIj+d)x=h*13jjNMYTMET}$toWl;B>WK0<5778#Q{1_tVbN-hR^e zm-aR%lU0K>LVYS(byaD4mjA0WytS>$gJG|2k?pB zZp+ZfSUSeQEjAbwtHx+K|G&GN(vEpkabk^|tlAA7QSPl{l;XNlJ?W%}XvEdYhKthS zE&5;m&A1uflG^9JFKX51F_=0W11j)FDo>Xib9Ae|-ksQc$we0`t4ox{4Ko^O zG4XWi#^mzUTdNo9E>I}vPaD&LndWpsRp`x8Sfs&r>ZV`ErmD?pBkBfJ0XY?ogQexh zW-_o5QM42q5+YiA48``Q^}*;u@QuaX;MuD>INtZ2KS!XQw78^}QT>o%y3a@6U z%+{)UP2*90IbLWK(nhUNsZTHjrmK_sl)tn1(b{xxv!2$aW z*QTXLk=G|DC3+YVxl^$h%1+A-GR7hGHQj4g+x6C=!A4;+rB&**e6dm956xW0H4>#< z8801No9a1DS&APZm$ByTETV*pcdo2^M!Sawi!hX24KGu_NLY9l^~T&Zd6X-R_F8kc zp{kOV^RqaZ;UJUnNE)MH?W?jfxaZP340ZYH%Z!bdE5&JsIBi&O?iE2Pebt2#1Vzf< zE$g)la+8E6$1cyYp3f@gE@~4cDQU4;tEo@xYHs9swF3RAS4~C-;;u91$Gf2fs+#Nk za%F#YnkO^|^1m^)DIG4<_faJhLiY7^N-|}p+N4+bPF-WqAMl}_)!BHZ=Zz`&ycaMn zPo#6zCL@P(S#=mt404r9BZ$)+nNmTRd0EV%x02E;RIFOGYEg+Pi7rNPkR4*$mZb)8 zPXeng6(HOqWR{(-L%K6u(k>e*#*B?6TUV7Dl4o@rJB;6ABi$kTC98TJHAXEshy>C& z?@E(isSJ{FJyK?p-e#lPRk~SkSIz`gE15Ws(s8}lFwLwpT zNTDi;_o4_MdP5k@b%(dqqkXHUX_2I_f7R}O{^w&bb>w3ZyMV@n+I-GbnR=iG#5#&( zb;5}?+?4*q0Fi1$&iPm4YxYThpw3SRwhg9x%asC*qC8WWl-dF*x~!36VXBdFot7FQ zfstizxu}zjet3PTp;AyVnjB8L1qWsq&jJWv)W)T4Fb) zAB_6>*l6F_wHs**#2l$hsP%9*R6qXbrp6z)!*^XHk|N0fs7#V1E80UBsjWm-z3jzS z-qYoM5~o2nr+XPNp&$#3tB=(X1mX*;Q<*G&LsHkydeWqi!cU4*l~RVlWRos(b{Y7U zv_%G9_cAM+>zctriE^1PoRHBW?rV}6h9m(fDPS)kPx_{+v+26@`ckc$^i3BqEqFSN zRMHhpx|r^rW^^K#rpcvV6t}VrXG>KS2)Ic#Emdx=nv$z`8`A6QP_}VuI0H2(yR0eF z95v{LuZr|tEy?jXziTzFP9hR2Z(Cz)>sfu zt9TeX30Hm1!8Tdz+00jFXbpP0gg2#>*2Z6B?(%NYF1%(vF0F)Y zOt<+TWvXuQ++4l4cK9C@4h9Z;^qfp?PFJh@tWQSAHm0UPGiEGz6nDzZ06DUmV=C!eq&#}RY#j?mSxzlNDARDN z``%KeI5ktKNoJ=514S`;jcM2!{Yy`Iu0}*ib`yKL=g-qdEc#$(U#bS&r2P-t+osqeys;~&RHkV+2;*j>9 zY8<{d9@{O;|NkQA+Kh|8AiavlQT(Gk8X6mM&Yv!LAS&7cRWy{eUX@ByO~)D-h<2kP zMG3`gR;)sI8nrTGs#;@+R%c~A!PUl>b3y+?5o7rgo*6O0z$xT)lgtL_GxH{KNUby6 z9%86QUyn;b+AF8rv?rDQFVkZ2-P|kjBknH9Jun4O9B>lZgJvj3#@FNyqT^z5^o`t0 z*%Rj@n`6RUl5lGrW}ft+!{DmekpB(E0?yP(dtYu>38oJs?bEE3kIsO+Y$-g*>f6d z0_Cbs2cu`oVM0yOwM!L}U?QhjJsTh=_&6iaE(V7NM^>Z34l;7aM*2pE(~ap>yZV)< zG>!n)m+?F_s08R{?!m0(hk?uCE1VQ*m_ijzB;~Y!-R@FtuRIx?U#kDGdXR_pq#q|* zOG(a*C@RvX#mu0J@r{9j*x~irLJ@W7;k`aIGP>w}GrwKAoi5Ly*)Xp9-6)s1%b#mN zVOHb+$?gU@2_KiuzPDP#0*DXC(;I?LaAUmXoLcfAu!Uf{sUlVokp_f5Tb)IUnr((| zCATSJwhl8!q{vioN=%e8MDhuv$@N4iskP$SIngg2#n=;HSupsM{u;gzbwhs*P1Akd zcF!G2j4}#rNCLgS@JN$V6r5eZ)k~^)~!6N@1H}rmp=`&pkeKk?yk>O zinzewhh~7QO0sHGGiy6#0+O`K1jOv})d|eT*tI>pVLQFLL;n96UM`K_sK*T$2DOr7 z4-RTG7wK%XHY?3fH@nlFvhXm<(3?xs+?9Mr+Zq^H2gPDY?>7V6GxmvvI7vYgXg3*< z55fO;9&9&^zD&GY=LMcoBjL1YTaVfGFi8HL0cZz@bZJR-hoQf92@G&!hSl) z8YG$tI16mtxLd7=B+ zYiIcb2g}g$LA=HOe|kZx$w}Es=@<%OGB|i`x?fWd@VoLssV+tedl|fwwZbgUariJI zQ~C}R*-GA>433U*>`G$NG>kcnC_ zjtED?Mc~7#joWF=o3jL7CO$dm8T0k*K}ozvBLEgEF9__Y^$@+OE*CKk7N$;_O)%XL z&s<0chxKV!u4|nVXz2>zZ!Hn9&4kv09Hzzdj?jOE)8O z2F)U*v=k3-g*g{$g##wd%n>Kos+WfuIi+HnO#+sBRD-r5PY7xNvl^4~_Zbf!-YK0B zM>^BJ+%z}XEc4=)5`v+7eJ(&nkQimmCgw>^$D$Qym!^A`YW~b@e&qCl+@+EygDCgO z)-nF2Bc_PTCJw42Rv)*$r4o6O(|)AwUb$`u@Yvyzx0^Ot{8ZA|o}2$$PmQVC!&ydC zoL-R)A%$jaXr$X7N=wD%=Uy=Bt0n;2{Zu>=8b()A9=OLIqKl!K<$ zt=)y`eREtex~s;iHYQuE)p5iK&b6TZUd7~*4_4+-ZF=xB^N$n@nn=ixc(_Y?LmS0D z%*W9dO+a6DW@w!stmP$UuL{%VCd54|?hY663a2(~O8Cf%_-Pi@ai{~H!W3AgBbDb> z^j@DTq3}*t8*5<*vvQ;@Plh^Vj>;q~RW$jU48f{m@AlApJ~K_td@>8Ye;ifEbtHFN zVkNA#c|rMxgJIB}WKu?Q$;K`p(~xv-65Yp{w}Y8AkxR*@Zla^xTFE@Na$UE4yV+Yd znYEdR31j1>UYfVy_#vD$?|Kn{_ z9VL*%GwT(*$sjIZerB&SRaub?w;%#b;jse2(J@8-mGr!MhtQfv@VRI* zUphaN#<;`lOb%<3W1l*imTWNW4u~xdF`b3xEbc&sQAscvYUyNi4l8L0$yF(%5WDBR zFfLuQJJ}W|8C)TQS8prS;2PT`t(g$8CP=o~R66-GWwA}uNN`y+2cNm~I~tw-Q1mD* zESQZsbylxRe(n$Y8AiDDvoPxu3<{b$P8TC*DWScz^ecPOq5@Z2_!5C(3_WI4f&n0! z;}jO4@B&ID$d@j5itN_|Jm>NVBU?HMXYYq}NrMC6K0$rnf zyR@3I)+@tW@i)QLph0qy6Uho>v*8T-t{RRqMG9ohFrOeerPeYG-6ds?XM7OS$D!K% zi$TNE=+qb1nT6cLx#m^!9G<8kDI`59K{V(P(2=PPd&`pwpA@jc0QP59Ltpc@~Y97uPQD_nM$++$`SyL-V@jhQB~0FW%~m`b$~V|SWUqPi`o zoZZK_s{E7eDhhLrWvmFQ-Rn)-L}S>zo*3u$o^vqM zEl{e+2=b{T2ho2B&*Mg=#D9$G=>WzDb~f=lr>0$-mxswq6lpim%_zsefur1!V$gepZX%@triqB!Z&oe(fLGI~`yIE`=36yL7s=CNry_fFt|zlG5(5284+sK#R5 zEHCnyVnmmaR;ck(CB2Q8CnJhlF{^DB|2|?P&=K;;#<0&!@V?R^00$0wI=kVc7pdh< z1s^Fy2UAAN?#LtqN`%$}=dLH3+_OQL$aj$=ELXF-Jc>0(7l}Uzo(Cz#3T(s@_6W=3 zTu6|MM~$utlLz7PFqS7gAzY1Ed?vca*nX_=5>7N3Er^CjiYkwLQ{h?*)9xwlC7FxU z!D_8JQx7Suv`+F?%uZrbywuJk<76TO2e-O3-SBu<#cwGhji3zisPJS8VYOFEwEPw5 zats~rxVB_;Vj(&%@r-W=a>m|-Iod>?$bc?{=0p^xgVcKxi8`A(wvyVVX1bD53v#nm zoMR%ihc4PZMC+&&X#bxW>^kEm8FleiPZg-sRjzcI))FF4@T^qo!9NJ;ZQ9sHY+gD% zG&&J+s1SM5TcrGOsnU$+8dj}PYxlN>WYHBUbtvAF&?SVZju+N%Wr!M^ zi{27x5ED<_NR$q(Q27mso*FS4Gc(!=U)Fe1l%+Y-h~5&`4Dfvn68JW>k9d{EmX`s=0ihj)lD#BQYXY&Agggr*n_ z?5Iu{x66O!h`<%mGK^uvsy9lY-a%OHfM;MNtV;)bpOALK*A(EeZnS@JHIHn1$TX=C z7}tKwLgT_MkBT!d_?D58olGMkx{xWDjdkLG%^3z;Yq2^`C+Lx>bQ@%pU5KW*FfXzQ zE;^K@mF2E;gD)mAk(0Y0k|Rt=!T;`X2yX4oeh-c)FGLJ@jw+AHidG^RDbR-$KZ|3A zPUb`l)ow*_wOCy$ELS zNf9G+3#0{*Vyk*BoX5^x{zu}Os$zo?$EJo*%4y~}Gfqp7iFdZ1&`BspOzl`&H#K!C zAy}^zW>I!bnK81V`Zn=Fxmhk`3??1jzSXkyuX&jlDA2(Qb!u5)gW9)LJ!B@X-~tOp za8sh@3@eBs-+sm~6Sw~JW(!i^E9=2$3d2+tt^R(iki~HEjd*LkT7=Lf9W=Kq?!U6$ zdg?k^xShH0mwY}JT50LGY5n>-i=kcgvZ?J(h|WxNIoQCCA}RCzFY8P@x@YSfJ6xkx zfPfZfw1){mT(ORt0cy)BKkjACJ=_c#vy-q0^ChWt%A@tUd`w@~(&`H<1X@ifSZG`k zB@Q34TW^K@`&nD$dZI-u3v%+7j2f3>^&Tuit^t(B$vGKQOaNj@u~~jmu(cLGuXL}Kw4Z=Vf@Kb)WlvieRGFCR8gcn@VMK%__*vu)jhR&zw zBr_?bJBC$ybf@^DCJ-_gwB$-~t}p2W(nLr)JUXy78eh7ByvDIut*;v#-i;Q3Rj4l* z*V$iX#hNu&aPhB0M#?zj`^w5(_1KYaDViIob7$`sy^GAmJx5n*s%ho8@Bk9TjKvrP zKZe0Mon!+WT6RTF5~9L-pGH-8!s?%7i~zoI3Es{Ndp41A(^icnV~QZ@mr*?iePW#R z@m*3&`vd2J$I1H1be`5(+B-X&?1Un0Dym@y3oRp41;buy2_iy~L$YUFK|a9jyGByv z8B7~FQ_*J?EY@uqVq?lHQJL%-^UxE7jeG6f6xCogZ{gmOazh<~HILh?nMKn!YpvdA z%GzVyO}$e&eM%d%iZO1hOiL`l2?}<+dg%0p5=*A+0=W(`@d?d(flc+EypQ81au-6qd+{Rt|cG>Y$hkbUcMeW?t-e zHH0y*2Ce%lqX%EFXY9fzL#=G`kS$uT=NW|+7`Y~NDv$HQ?))=Oq~>+P6?yxT3SZRG zo>inU7%?Ld&99D*#jsH-nP^o}sp&05pw(lS(Rjv76avNq65L8{V{gV>eT;9-owG0j zKMQ=p*Z}5)yx>*{(+1EIGAB}Qo<|kyUbYPD2Dh6c4_GkR_EL*DGwOG1ebgQFmMwmB>ws zab3NJ3~i&e1#M02owB%%<1kh|f~keV$~*wZtNF$&C??EwPnQ&=X~Wz2iiU^@sW8!{ znQJ+ZC6N&7Qr0Y8m_PlcJ)ut=Vw8xyIzVNT4{y)Dj_sx?-f#*mA?Y+5)xpw+UKsJ<$;EeC0K|FbL zN3FW}G#p<@yV^GOdt?HRd6SKQ?tP?3htA;BR0>H&fqZHeM>Eg0h ztB(7bZ2nlG8VEFZT{3yBVny#-7%z6uJVYLLOyHGt+TaMVwOC?2?JgsG$tpn4+Is|2 zhebw_$C3j^g)yu+V5~E(6v!A;9%&P&e-M_YErt6 zHM~?OW)wrRvQVC_N|#Ayrs2F>`0(I`mQ!9;?oV&j-=lqd{p3({1KzHOe9Lidi3XR&-1YPhpj?&@U#J7>2R#2rze>P|>aeC4c9 z4&|Z+@l_)<3*n8)}nIPRmL?IdI1hRr=7?wJy1r3rttl_&5E+eReaiNzwT3LYJf(5Sf=)t*?n zdDvi4oZLi8oxf+EwLLz8PsO68WUNMJElg95XHwbu5KO?85LE+VTdtT4QFBvS4^1w&Jv8Tzeu-hzeLZYY4rdMN5;! zP(nREhY4Nm!A1{jlR7tC)N?6c4y&(%cg0$`Jgd=()PpPe@MML!X=@s^Ff*JHgipy5 z@NrAd+I|G0@&;E(k5&t*uq_)Vzvf!(Ze?A&*Zh{3S|Mh}B6+9vMm;La?cZ7OinU_+ zl850bB*}ZjH@jKLb6kwBG@C&)Og31;yd1=vSyJ#tjEKUlu_H{{)peuY-?ixGu8RDDCQd`x%Z-V6owH60_8s3( zE7uBaz#%?Bqr!pkTBt!x1i9Y;zSInFW_FqJ*uZu>Q7vqytge;(CfJG2=G)}8njg2) zT5RXcZKBBa1K8125@zb1Y_hqBdh0$36l@nAOOwrV@P))iGgjV8pNUk)pzi8r6@fO_ zbc*tkh!HtzawpDmB>j^Rd1^kUsmIyNz`hKhY|)7 zj87IB?Q6=ZwXe;s`@HTRTWuW^s_{{Z6nCbfx{fxB>qy}?VWcJ!#umXK5t4*(p%4!c zuW}Phw5f#zc{e!!TB0*3A%u{4YM(1Jy~^*0Xs?!WnP4lK9Bh3ly#WosP@KClG0Djbk2#Lks#;{zH8kF} z8y1Ly&=WZH`tD1+FU8t@%@ z7V8H$u3I)bva_pCE-~`!A`+Xe(l)N&u(50XrmhX^IqlhW$pz~-tY1&Ut{q4_eRn~+ z^_Qd@HuPM`JNzwEEMONlfz91(VaTNHIz+_f)$zifIBy$CKE1E$G^b z=KQ-QWdZQ;(C|R34K{SIU)JZ-?p-_CPp8MW7g)zoC|6j>4j)1Zy<*qS!LCbM=|X62 z*8s}846B~>5~2&1UCUN(+K8d+n$jF$Y~yv!Q1+xZT{e4g+hsS61O1K5ZffW_Z<`2<%)#iRxM$NF~UVD}KLl*hRG&~cx+G!6SO4aY6Dbz-}%;WBR z>@8(cOSWHJ?l}R&`42`;_rLnWD4KWK3bU}AbB(f`J*e>4Xikh^plERPP=3T1ejKD` zrNi8-bU1B;F2gmFMiY`v!>1a?AmH1}*1`9xxZ{P&k2ig6i}qGt+6jqs^eVefbi4t5vE>2Z2x&m8tPM zi9Hw{t-U+lT@}g7|1y6EilqXLOSZ&H$&J)C(E$a?&<+Ya8t2UXp_wX6fEZi^hSk~k zKr=QE_D!#ms?81o;ghf#g^`LR`Dpl(74mob7^X&34G`+6hIXH=+dqT|l#1zos~kRq z`9myanGSpUi7ROTJPG`;tKW`NgSxTTpN~)W>%%HlA~Sn%R>Tz}mgfutV27wB&nZE;p#_}{$PvDTVHXvCvI<)`@I>+>5jV7c4J=nW#n*>fn zhio2~y%hEd9EGHfF;{T!RA4_!cBhKAZKe*7(kbNEm>m)8O02+Om9_!V>Z|9Q{s0m1y?H-0vlB$P0!!K1c5an1K3=epp6=|NT^iq8CZfd=S5wjiLFXk z)%VH7zlXIgMvE<8EBMBlaye5FBYiI^in@2$&86l+7I;?VfM?u#CrB{TILnjyXG$lf zkI79$1l`WxfdqI1%*!bwqga{W%{u*@?MQ-xCjL)jt6_=Dr48l}?VrD+VwGjOeVF|U zDMqydo8zH{@Z%cC9w1UDs3cxY7Kmz`&?x;`YGtZ+RlZqjT@o?usn@1z0zB@vi=ne{ zRs!Ld$ZcgvwFcC7xOTIXwDW@1$xhLUJ`gB@fo=O4a$h4tPlEfI-jZ|(tLD)|&`01p zOKfY%#};QBrXG}wZNiqNpzT8ol6zce@0tuI3?cV~GB35?Vb)8HScS+Ja&{E#Fl4n~;=j!i(!tw_ZS;OkyN!3^CQ!>aFT5 z?A|yACOE^60cCVIj&d%MAvLnKLn1HU4DZ))v(ZBWmdVs5mmo0}g{S4ZKH%vJO>3ZL z?p6@aC|7t&qPgh`r}L8f{M}^N!LY#gVQWsRot0m04kLp>;E}~!N_${$>-%+AF>2Lu z3vw(FbM73CGDfzguv?s7%G{Js7qY2ssmOE(?W!FW{S1fW&MAq6+@6Xq42Oeip&DAp z=M^m~;?Bp=L=%j$GH(iZhC9s-+3~>_Qp^<#qu2GvYijZ=5v#-sD7a;LsSz{5h zh4>V|L_oH&N%_^2J{EEjsltdfH#@rzxit3cBrNM1l%$g^39GD#OoTomoL0$e$pCy> z;S2MJl3s;;2O(h8mBsVxrM=ipw5fJ(?1J|+l7;&=_9Gb!5Qj*}9pRlYL3EAP$r6uD z=&+?p_DpYOs-84S#Dii!o2hN+h)PPCI^-gARgWNDWQyp&#(bAZOI6i#Ngk9+QC4C8 zojxLce0AW3ArREspBih6$6PidrtPa3CDpl-Hh5gehfy0DO&_e&-(7Xe2_dB5PUu*48be|KHlLw#wb)@ z{jMlgnMH9hN()67MoNeqWy4ykY8Ft?UW#1aaGH$TyVC(Ny_SuU$qq5>$Y)Te<(E+Z z;Y!l>*{HZnm)sds{sY@O2v$&RfsG7A(0)@Q#%2El(?a753@nbfZ)%94bhTf|o9}6sAdp0gM8&V>>bD z=*Do8oy>O-B-kg#mqEAP%8D=Z7BPK{HgtNEM)fjw1S$fmBbwDMuI2c0LM906Y;)AT z3>wJBmHH=`?wQvBR<@VMf=EsOB?(Ld<%ceS<-=KQqe)6yWv{{fPLs~B(-mzyPOgvw zL(k#Lje>sx`ECy*OamU_ijZJz8n2WhD2 zRnFy@=Ud9Srb;>A3uOrYkI~3YTs9WrsCD>{#%-{L`Cuc6D4cGH{wxNQeJE)k<0k)$ z%-vjMfIi&pPtVtA{2|SrN~TLf$=8PT*hjBQ<%#+0{D680p5` z2YdtPwmfoHHO7LbXBnf)#kZZb_w#8M??cHV?9BS7}4zIgT0sj~C75zaG#%ZJLqh&z$SrRsXw3N!i zwhTjo^R|loiyTb7UXYJo2=D4EQ4)pEJ@nI9n1{$9CJ`5O?l&n8U|J(xX?~E0DnNWc zmnP$O+641Kn#Z1qN)b^msePE^q|khgreVNgmI&6 zWR){@t$0s&NwMyA;iKGp4B9B9v?b<>c!flYVo*L58F-?6A~jj?XhU9^W@!>!a2RtW zYK5t@0SI1CD-e5Ls{XbGCfhy*`4>@S??OEaM&61_S?mDZJ;4p9a-r`}I~W=rHoVS}WwRyQjnZlIZV`W&3Pqf(vO%gD|6 zg1JNB6Rp?tLI-sNU5TF$XuuhWqH6mJ+rQw`l^#!SY;hg832`@2D=m$F1Nm!egPk{9 zA8KhJ(QDvFND!fPOO`e;f@~--G@)C$gQSBZTqyx00dXs|9=>6U2EiP~a(A+>e`u_C zY?w5fq0d%?vDi`@Z?^W@RHir{#Whi$W(po$*xika+sXo#P-+*OZCO$d{niD%lxFFq z7nQutL6S`?@pZA7xFcul6AMa7VOo1-%1f}j88+%17|4~ZNhApyPYe>(Vi7T;wjHPT z8(6J)MV3Pb6Fm3M!UkFNDQ(mV(TT@n{Y#6&P^V)0Ndfd{^X#(u4F*^=QDPSnb(HhU zVoyoOQ8$Gw7!1%vux;DexLI6X@k?~62|eaQg3N_-Itlds1BZ=T1h#B7# zl!~}>bEyQ%uH~tOON(5Cw^He&g}y+5M+fqQ+>RU*hl({{+y&HDeTcYdR*6CRsu|Lz zz1UU};$n3fYl>{KO+j&NvX7>%{~6G3VG!oP!0Ps0LKQxSW{T=VQ!TMeD4h#`S9gln zVTRkp!7W{U1v{`{(+@B%M)MSr8Sc9zI0jdk&o$9Nd-3yYQ;awh`{28YCSe!R=pAdh z$ufBsA7v6wMI%;`Y6s0@w`Q91+Sn@j8RIh4wkP=qzU;ggiw03;l%QA%5sef)6#pc9 z)-f=^LUeAWoi@VdMCMm|vRB!i3r$*qK^lprneYf+x75a?t@oG-fMd(upLf*ZzKb~* zQj7juuoEecSR%4LO)G6j!Nsw=!^rSpa3{sgM7{3%qw~$DZ0a}hn-w+{%F#sjdERKv zNp4$v1#KcL>}67r^gUzT!g84b40t8wt3% z6$`DcO`Ep0sq9Rfgf=AwLSZRXp$V(O%@A_NFl>2f5J}k73dgPaW~GuS%kw@hdHYZ? za>kJMQzbT){!B^k&k_~Ve4^Wufld8(r9n=|~1)p^EJwE>(VW$zK+< z;(F81frYr*xMAuJi^N4sM8yyKxJD>b67FQfw+k`JZP&5^Xl_*4wXIezx7Aj4UX5|w%d3X_70G%D*WL<@nNR2F{Oy_KU(hqU5S^TDkv_3$}4bvXwA|al%U` zRYWDJD-vG>g|?7|kFir7W8EUUMI3F@hSG+kBqJb;ZeicJptUaOC8i{x9?H)$jj$_j zX!aG^ma%MJM)4JAzr>cYE7H#51Pee!TRUr|ef&I+O%?Ce61bZ?h=tG>VZV%*7Hw-= z*&f8bhYqzu1Xw=@Efc1y$O$U0UkNaS!2&3P0Zb4_G=MYaCeBkRo?ZEhPCBe>1lq8%Of#r3&DC_EQ(_Som#Td?i$S0n>_9bNVEhZ%4{kh5b z;7Z%QqnGgD?K?9Tz*jxMBcsx`pd9A;w7Z*GI}poEv!WM5V4yP|wJA+tGXO&sX$Lfp zl&$OnrNP~9i|#C)E|X%xda+d7D1@oS8g1k_?8}n+@X3j~6c>^WtVQvQl!X*H>eRYp z(j!c(_pS?7RJKIBWa%tYMTE{mYcqJlLb--qB1wPrTiGMZ6I~b-#^;f7{w?YU%4kZ8 zq9)}?=XYE!*a0OEeHhUrg4Q=t3nsJ+6wCD4a+BBCl3AYp)>N1-!$J$WGb})c`e^D= zxd+dIIa|u6ZMBz?0YKU~}de_Z3Fm_aF)DNS{MRV9(hP9I{Rx%n*ryR?V6e`Ne>3y0I$TDizQ=PNMuiHdr-4 zG5b6CbrLx`C4}&%dDNf2s*biOKr@Hf4KD7zE9qsnuF+m*ZX>G9G}F>e2_knMSs#aJ zc8?N7-^>d#$hS=)Xvr~j$kyPK@XS7yX^n~k^top}jzZ``-wS?i2-I{$slv)vGy3i^ z_aJO8DIt!04SV=v{6zKztc2)fSeN>*;NZH?%|&j5hqWtF;@v^NCNRLHyvC~wCXb_I z>70g+bSy?3>S~`(qSJ zuF>&wo5M3Cp%k+fBT^)a-SC#PS=2(`1*fS@FCl^_?#kzOKi+f2k6&H6yZm8nhRAf>_RG*>oMtJsZz;T;MFCn%(%M0IL+f;-n^NZGfmhH7!Q0cL zh&Aap1&oRAv|NWWcN9Rk;L4nryh$wxY$vaW?ju&u#7}q>oXP%|ttA zW^zg!7W=9UU;GPa@3qhp)zU(T@`)@b%RSRGs8w_qy1-LNBy-GsD_dBDE<&eZ6xPF< z#sTvzh2K|cBll7EJZ65|g3#KwIyQ?b_M$)UAvd4M#ig-yWRe=)5+}nL?*$ZKzhXGi zu?<_&q8*N7n7uz{Z%>#^YoBAb2E*=;+G%4QW(s>7XD@}ArBJv!n;Wa{UdGm1N;qgs zr3z0WeAo+4Q1)I(HGW1Yq2M7*Sls-F~#079L&nxbjJUYY%%)6sv?K>}L(FTir+VppvvSg&jbp)C731^HngK~|MGcGYef_Fr+ zicNd;lYLS5x48n%bV-j;pV%;0moP3pg3HVuxPKVb!5~OGX9y^jjv^)xz0yFYHu(77 ztZ$TvOlGl+e7~~Eg3pF_4BRp-XN#t=2CggOi}VA3AzNnH#(%PbZ;@aSNj`MQUz7?w zhB6v<1MvVD?` z;}s8@pV|m9$?lvI-!LDk+mt~7O?R|Z=}g?AcIDzA;{*vl28DsCEth&6&3$Q>?VL2H z0$Nm?m{MEOeoM}pB0Kb37QcFUJM4LOwmB!l;2S$BFtaYK8j?pu(hmvCUd~3ij6mr% z*wQj9RjD1sifUTX^&LIz(W9(ht=I$IRyQtXh>JLVk7u|fbfJ=CSL5hrGN8*{KWZVf zu3ZV221^q0cnvy~06wMBkN;M4#a%2}gt6GZ&oFq~8lWqi3kW+v2QCPYv`rAQ_2!w$uI#41Bh`6jJupR(`hP$shc?VS#kvfUB_BP{r*f&IP55( z8_d5GJJp<+Hid{Ov((Kne;2lY_Q^aW9*eirz}gX$sKM-RR0dj)9yGQNj+w<7mTF?g zxl1*)n%y+wY*Z6zl}}~QeUl*PV6ACYb48dJ15RU@BXWzFVSg4VPb!a>FgMKf**48e zg|TJ~{js>X3rb4$GmX)_!rZWKhIVp&HVvK19cPAEohL+(VPe3&??mk4;M>vKy}G|e z3ebR72+#piCv)qZ$HoTCl^LzW{B&^81Z*b?{YDhLIIgJokWh6(#PRZH#?o z9a31J2E@4hpa3jt1Kx=_(<_Tohh6Zsk@-WW%iKl8IO&&)v&8gi%v1vqE!E~zB~)xE z2l?+xe6A#LL6=tIcoxXKOs>o@pAfd*hLQ{NOIY|69L5Az0keuh&6J9@7@-sLx_ekL z#&ui9ZLHM%CJ*x~Vt@58D?&&O(}@HZ+xMb}+#23D=U&)1zEFa`-QGSUo$KsY>&g1p zSh7VvYPuztS!C_LWM^h$t*w6|0WQ@)TSR=a5MtNl`cs3?gi*`u6K#k%AX}!Vb))a< zE#uYI_r2Bmcl!A8?Y)r^ovP=4`c&M2*^60*aj;*FU@}4z_48{Fws1de2u`$^3^JKp z+Fm>Vnoq$~U<6Ap2$+%Ul$WJ#xgBg+%h(S=JkcP?7HzH?_G)?SKU#X~B4>|EQ zz9gSL6JyB8lLhgd##i;REXIcy7Hujnw~KXX2)0=VOOxQWIUH9qY`VT6y;S_(7v8e0 zR6cYWzKD4_ae`#Tc+O1^yQfEfV0n=y_>G&qHr%^KafYq6b8J1nXj!K@f5Kkm7$@vb z+R%?8@cTsi83ytH9W)0sFWxAULc|<2r->QSiq!n30-x-E}{lp?G) zyxkTwWQ|SDjOXYXYhSqs6AkK_3@yf?8+uwjg3T+_B2%1M$}oQ?BG9y1)zW5AcqNMe zZOrHf7L%VNbn75^`phF|sp9m!J4>Q%HGjyBDMoi*7ob`eJ}0Z&tY9>sZYC$`GaK6S zHpVQpUnWI~oDjAUpJXKtm0St&Ws_^lTE0%(+PtjTE8px~%B~yU4AR%t8Lc}SB8U7&m2pfNE!BkD~oK=7!8wAYNybp5P{t9 zEKm|N4zW+sJ0%@kv591qP0h%3wM87p1;R{)#TCV%G|Ma!Aso?GE?XD0?;ax`vjk_@ z^)lGADovhLvW2>`?rlCN^NcE4Sf^(T05wvO|BNp-kSenmkLr{s!B~H>!LaGoI z&!Q=UUQ*LHHKKA3GhSJgTjV{U0Fni*48+sM!I+@r07-1{60x`WwCiTtqj zjzX|Ab;}6PWCLAHS8DkcBZM+Sjr=lj(3Wgf7N3ZFxqBx=w@iM@M`BZZE&5`H5x1Y@ zo)Tn~Y?8mTfQ4K($3gbMTHAPpqEyjD7$xoWmifcmL7jIK)yT8Xa8PHgu3tB#_AbgB2eLF9Seg?4xLW%Yi89*xq*S@B;5e*Du6H{77 z-Wp-quv%1=MKRT3c#2tA1^5D-M**&y2GR)C+?v{j@hOJ{s)|K{F%S6gJGRfdB=9%N>-X3h+Hu0Q=tnEOD(IiFA z+A|T75oqoKgWKKnM8kTVf|z`WUC4yIe(5W29B;0ANL(>G5)nxMI=_L2Vx^HLSL6)4 z_QF`@OVOOTg){JL)m47#wUpX^@}m}2pOI=?{Ko(h>>@J?sX4Q3Y7@^J;pe*3%mq9= zR8BGi9!6FJzWjwxGm~yR4#a>Gs}8gsdBlRf=AkkuJeyK$-=U6<&259y3=^w8iT0V_ zmiME#79anv+ialHGMg^}IO?og0V9zaCqb2NDUi082}xX+BRHU?A4@UQn1~?^w&T39 zG07A+fy{i(y@OR`DzT9ydqg56l3s%N2zarTa;DfwZx{1hVkLyKw|HG9zMvsG+ozV} zEL@zdhI8ih_ytM>oC*f3IFY2^eUY-1a!R!}0c%=txoEZB2~E4%{I+S_`MvKn0*!sb zDtt0}fsLjD1qCA?Pv>LZ;*Ep;WR{n?{K(SQ;6c5McAszMrb1?W7tm}Yj3KEW*?dCu z3!8Dk2-7V2WX-nTlzP<~W*5?IZPt!9{FOFgbIDBVW*!#R)~utpDYMw<@&^TdUQS&F zDDqirQR$7E9q5W1=&+G*ZiD*PN)jXrzXVCm&E0IH$vB}3A2zVZ99m+(`ccinWNgAj z9bJa@TwsOkr~QIu6N~n=w^ES5io0lU z`?&J$A@{haau2b${Wjy4#9TtRbGin{Kr+Nbky^)34ZD!^%6x&z+QN`lWfv6dA3)2fkD( zBTrW#pgwlSx8DwN0gqA==4}zXg+nUDBzR|P*|ZPdNNWw>48L=M z=#%D(7ongZMayP(gZ+((ir;wYyS+Pi5;;6HvfWpHW#+fJ$Bm83f^~=_+|GJ$|MIKT1tL0LR-;j`I+YSq_@EQYSwalq_sA z#@?AWuy{}Q;*U?KMlLaS>=snnD-1z6Cl+f znx^F^OWA&Z9oz4Z=B6ehLkh3ZvYG~OkyQvZU!Az( zWSW8-!csTgjmUSSmZ!$ZYX$mn+>t1gNv+x4{9}xbY>Og@dF!sBxL^VnDlsCDfrKGC zQ!ZCJE>uqZ8>UfaxwGeFyxb-h3#kQv5VPd{2su22EJUI8J0?aFj$+mq;e;kVHWjT3Ju=5V(@dwGUJKbljQ#cx<64c literal 0 HcmV?d00001 diff --git a/bin/Langs/ja_JP/pcsx2_Iconized.mo b/bin/Langs/ja_JP/pcsx2_Iconized.mo index d9bdf9c8bca03633ae68180a8427efa8fc153f20..4a05c59aed8cd897a1d7312ec57be1599be0da0b 100644 GIT binary patch literal 21698 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 diff --git a/locales/fr_FR/pcsx2_Iconized.po b/locales/fr_FR/pcsx2_Iconized.po new file mode 100644 index 000000000..c4f1f83a6 --- /dev/null +++ b/locales/fr_FR/pcsx2_Iconized.po @@ -0,0 +1,593 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR PCSX2 Dev Team +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: PCSX2 0.9.9\n" +"Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" +"POT-Creation-Date: 2012-03-10 20:38+0100\n" +"PO-Revision-Date: 2012-03-08 11:33-0000\n" +"Last-Translator: goldeng \n" +"Language-Team: goldeng \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-KeywordsList: pxE;pxEt\n" +"X-Poedit-SourceCharset: utf-8\n" +"X-Poedit-Basepath: trunk\\\n" +"X-Poedit-Language: French\n" +"X-Poedit-Country: France\n" +"X-Poedit-SearchPath-0: pcsx2\n" +"X-Poedit-SearchPath-1: common\n" + +#: common/src/Utilities/Exceptions.cpp:254 +msgid "!Notice:VirtualMemoryMap" +msgstr "" +"La mémoire virtuelle disponible est insuffisante, ou l'espace-mémoire a déjà " +"été réservé par d'autres processus, services ou DLL." + +#: pcsx2/CDVD/CDVD.cpp:390 +msgid "!Notice:PsxDisc" +msgstr "" +"L'émulation des jeux Playstation1 n'est pas supportée par PCSX2. Si vous " +"voulez émuler des jeux PSX, veuillez télécharger un émulateur PS1 dédié (par " +"exemple, ePSXe ou PCSX) !" + +#: pcsx2/System.cpp:114 +msgid "!Notice:Recompiler:VirtualMemoryAlloc" +msgstr "" +"Le recompiler n'a pas été en mesure d'allouer la mémoire virtuelle " +"nécessaire. Cette erreur peut être causée par une insuffisance en " +"ressources, notamment du fait qu'un autre programme utilise trop d'espace. " +"Vous pouvez également essayer de réduire la taille du cache par défaut " +"allouée au recompiler PCSX2." + +#: pcsx2/System.cpp:348 +msgid "!Notice:EmuCore::MemoryForVM" +msgstr "" +"PCSX2 est incapable d'affecter les ressources en mémoire requises pour " +"l'émulation d'une machine virtuelle PS2. Mettez fin aux processus en cours " +"qui nécessitent beaucoup de mémoire (CTRL + ALT + Suppr) puis réessayez." + +#: pcsx2/gui/AppInit.cpp:43 +msgid "!Notice:Startup:NoSSE2" +msgstr "" +"Attention ! Votre ordinateur ne prend pas en charge les instructions de type " +"SSE2, nécessaires pour la prise en charge d'un grand nombre de plugins et du " +"recompiler PCSX2 : vos options seront limitées et l'émulation (très) lente." + +#: pcsx2/gui/AppInit.cpp:162 +msgid "!Notice:RecompilerInit:Header" +msgstr "" +"Attention ! Certaines fonctions du recompiler PCSX2 n'ont pas pu être " +"initialisées et ont, par conséquent, été désactivées :" + +#: pcsx2/gui/AppInit.cpp:211 +msgid "!Notice:RecompilerInit:Footer" +msgstr "" +"Attention : le recompiler n'est pas indispensable au fonctionnement de " +"l'émulateur, il permet néanmoins d'améliorer sensisblement les performances " +"globales. Si vous êtes parvenus à résoudre des problèmes en désactivant le " +"recompiler, vous devrez le réactiver manuellement." + +#: pcsx2/gui/AppMain.cpp:546 +msgid "!Notice:BiosDumpRequired" +msgstr "" +" \n" +"\n" +"PCSX2 nécessite un BIOS PS2 valide. D'un point de vue légal, vous DEVEZ " +"obtenir votre BIOS \n" +"à partir de votre propre PS2 (emprunter une console ne satisfait pas ces " +"exigences).\n" +"Veuillez consulter la FAQ ou les guides disponibles pour plus de " +"renseignements." + +#: pcsx2/gui/AppMain.cpp:629 +msgid "!Notice Error:Thread Deadlock Actions" +msgstr "" +"Cliquez sur Ignorer pour attendre jusqu'à ce que le processus réponde.\n" +"Cliquez Annuler pour mettre fin au processus.\n" +"Cliquez sur Terminer pour fermer immédiatement PCSX2." + +#: pcsx2/gui/AppUserMode.cpp:57 +msgid "!Notice:PortableModeRights" +msgstr "" +"Merci de vous assurer que les dossiers spécifiés sont présents et que votre " +"compte d'utilisateur possède les permissions d'écriture - ou redémarrer " +"PCSX2 en tant qu'administrateur du système, ce qui devrait garantir au " +"programme la capacité à créer ses propres dossiers. Si vous ne disposez pas " +"d'un accès au compte administrateur, vous aurez besoin de faire appel au " +"mode User Documents (cliquez sur le bouton ci-dessous)." + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:181 +msgid "!ContextTip:ChangingNTFS" +msgstr "" +"La compression NTFS peut être modifiée manuellement depuis l'explorateur " +"Windows (clic droit sur le fichier, puis \"Propriétés\")." + +#: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:49 +msgid "!ContextTip:Folders:Settings" +msgstr "" +"Ce dossier contient les paramètres relatifs à PCSX2, y compris ceux créés " +"par les plugins externes (sauf s'ils sont dépassés techniquement)." + +#: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:54 +msgid "!Panel:Folders:Settings" +msgstr "" +"Vous pouvez spécifier un chemin d'accès pour les paramètres PCSX2. Si un " +"fichier de paramétrage existe déjà dans le dossier choisi, vous aurez la " +"possibilité de les importer ou de les écraser." + +#: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:94 +msgid "!Wizard:Welcome" +msgstr "" +"Cette aide à la configuration vous permettra de paramétrer les plugins, les " +"cartes mémoire et le BIOS. Il est recommandé à tout utilisateur de " +"l'utiliser, mais également de prendre connaissance du Lisez-moi et des " +"guides de configuration traduits dans votre langue (FR : goldeng)." + +#: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:140 +msgid "!Wizard:Bios:Tutorial" +msgstr "" +"PCSX2 nécessite l'utilisation d'une copie LÉGALE d'un BIOS PS2 pour que " +"l'émulation des jeux fonctionne.\n" +"Vous ne pouvez pas avoir recours à une copie obtenue auprès d'un ami ou " +"grâce à internet.\n" +"Vous devez faire un dump du BIOS de VOTRE console Playstation 2." + +#: pcsx2/gui/Dialogs/ImportSettingsDialog.cpp:31 +msgid "!Notice:ImportExistingSettings" +msgstr "" +"Un historique de paramètres PCSX2 a été trouvé dans le dossier de " +"configuration. Voulez-vous que le logiciel importe ces données ou les " +"remplace avec les valeurs par défaut ?\n" +"\n" +"(ou appuyez sur le bouton Annuler pour modifier le dossier d'installation)" + +#: pcsx2/gui/Dialogs/McdConfigDialog.cpp:30 +msgid "!Panel:Mcd:NtfsCompress" +msgstr "" +"La compression NTFS est sûre et rapide : c'est le format le plus adapté pour " +"les cartes mémoires !" + +#: pcsx2/gui/Dialogs/McdConfigDialog.cpp:41 +msgid "!Panel:Mcd:EnableEjection" +msgstr "" +"Permet d'éviter d'endommager la carte mémoire (fichiers corrompus) en " +"obligeant les jeux à ré-indexer le contenu présent sur la carte.\n" +"Cette option peut être incompatible avec certains jeux (Guitar Hero, par " +"exemple) !" + +#: pcsx2/gui/Dialogs/StuckThreadDialog.cpp:33 +msgid "!Panel:StuckThread:Heading" +msgstr "" +"Le processus '%s' ne répond pas. Il est peut-être bloqué ou s'exécute d'une " +"manière anormalement lente." + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:38 +msgid "!Panel:HasHacksOverrides" +msgstr "" +"Attention ! Les lignes de commande se substituent aux paramètres établis.\n" +"Ces commandes ne sont pas disponibles dans la fenêtre de configuration des " +"paramètres habituels, \n" +"et seront désactivées si vous cliquez sur le bouton Appliquer." + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:58 +msgid "!Panel:HasPluginsOverrides" +msgstr "" +"Attention ! Les lignes de commande se substituent aux paramètres plugins " +"établis.\n" +"Ces commandes ne sont pas disponibles dans la fenêtre de configuration des " +"paramètres habituels, \n" +"et seront désactivées si vous cliquez sur le bouton Appliquer." + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:135 +msgid "!Notice:Tooltip:Presets:Slider" +msgstr "" +"Les préréglages appliquent des speedhacks, des options spécifiques du " +"recompiler et des patchs spécifiques à certains jeux afin d'en améliorer les " +"performances.\n" +"Toute correction disponible à un problème connu sera automatiquement " +"appliquée.\n" +"\n" +"Informations :\n" +"1 - Le mode d'émulation le plus stable, mais aussi le plus lent.\n" +"3 --> Une tentative d'équilibre entre compatibilité et performances.\n" +"4 - Utilisation de certains speedhacks.\n" +"5 - Utilisation d'un si grand nombre de speedhacks que les performances s'en " +"ressentiront sûrement." + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:149 +msgid "!Notice:Tooltip:Presets:Checkbox" +msgstr "" +"Les préréglages appliquent des speedhacks, des options spécifiques du " +"recompiler et des patchs particuliers à certains jeux afin d'en améliorer " +"les performances. Toute correction disponible à un problème connu sera " +"automatiquement appliquée.\n" +"--> Décochez la case si vous désirez modifier les paramètres manuellement " +"(en utilisant les préréglages actuels comme base)" + +#: pcsx2/gui/IsoDropTarget.cpp:28 +msgid "!Notice:ConfirmSysReset" +msgstr "" +"Une telle opération entraînera la réinitialisation complète de la machine " +"virtuelle PS2 : toutes les données en cours seront perdues.\n" +"Êtes-vous sûr de vouloir réaliser cette opération ?" + +#: pcsx2/gui/MainMenuClicks.cpp:106 +msgid "!Notice:DeleteSettings" +msgstr "" +"Cette opération vise à supprimer les paramètres de %s et à relancer " +"l'assistant de première configuration. \n" +"%s doit être relancé manuellement après que l'opération ait été réalisée " +"avec succès. \n" +"\n" +" ATTENTION ! Cliquez sur OK pour supprimer TOUS les paramètres de %s et " +"forcer la fermeture de l'application, provoquant la perte de toutes les " +"données en cours d'exécution.\n" +"Êtes-vous sûr de vouloir procéder à cette manipulation ?\n" +"PS. Les paramètres des plugins individuels ne seront pas affectés." + +#: pcsx2/gui/MemoryCardFile.cpp:78 +msgid "!Notice:Mcd:HasBeenDisabled" +msgstr "" +"La carte mémoire présente dans le lecteur %d a été automatiquement " +"désactivée. Vous pouvez corriger ce problème\n" +"et relancer la carte mémoire à l'aide du menu principal (Configuration -> " +"Cartes mémoire)." + +#: pcsx2/gui/Panels/BiosSelectorPanel.cpp:138 +msgid "!Notice:BIOS:InvalidSelection" +msgstr "" +"Veuillez choisir un BIOS valide. Si vous ne possédez pas un tel fichier, " +"cliquez sur Annuler pour fermer le panneau de configuration." + +#: pcsx2/gui/Panels/CpuPanel.cpp:111 +msgid "!Panel:EE/IOP:Heading" +msgstr "" +"Rappel : La plupart des jeux fonctionneront correctement à l'aide du " +"paramétrage par défaut." + +#: pcsx2/gui/Panels/CpuPanel.cpp:178 +msgid "!Panel:VUs:Heading" +msgstr "" +"Rappel : La plupart des jeux fonctionneront correctement à l'aide du " +"paramétrage par défaut." + +#: pcsx2/gui/Panels/DirPickerPanel.cpp:69 +msgid "!Notice:DirPicker:CreatePath" +msgstr "" +"Le chemin d'accès ou le dossier spécifiés n'existent pas. Voulez-vous le " +"créer ?" + +#: pcsx2/gui/Panels/DirPickerPanel.cpp:158 +msgid "!ContextTip:DirPicker:UseDefault" +msgstr "" +"Erreur ! Impossible de copier la carte mémoire dans le lecteur %u. Ce " +"dernier est en cours d'utilisation." + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:55 +msgid "!ContextTip:Window:Zoom" +msgstr "" +"Zoom = 100 : les éléments graphiques occupent tout l'écran.\n" +"+/- 100 : augmente ou réduit le zoom.\n" +"0 : zoom automatique qui supprime les bordures noires.\n" +"\n" +"Attention : certains jeux utilisent volontairement les bordures noires, " +"celles-ci ne seront pas supprimées avec la valeur 0 !\n" +"\n" +"Raccourcis clavier : CTRL + Plus (augmente le zoom) ; CTRL + Moins (diminue " +"le zoom) ; CTRL + * (intevertit les valeurs 100 et 0)" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:63 +msgid "!ContextTip:Window:Vsync" +msgstr "" +"La synchronisation verticale permet d'éliminer les secousses (tremblements) " +"de l'écran, mais occasionne également des pertes en termes de performances. " +"Il vaut mieux ne l'utiliser qu'en mode plein-écran.\n" +"\n" +"Attention : Certains plugins vidéo ne fonctionnent pas avec cette option !" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:68 +msgid "!ContextTip:Window:ManagedVsync" +msgstr "" +"Active la Vsync (synchronisation verticale) lorsque la framerate atteint sa " +"vitesse maximum. Si cette dernière venait à diminuer, la Vsync se " +"désactivera automatiquement.\n" +"\n" +"Attention : En l'état actuel, cette option ne fonctionne qu'avec le plugin " +"GSdx dans sa configuration DX10/11 (hardware) ! Tout autre plugin ou mode de " +"rendu occasionnera l'affichage d'un fond noir à la place des éléments " +"graphiques du jeu.\n" +"De plus, cette option nécessite que la Vsync soit activée sur votre PC." + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:76 +msgid "!ContextTip:Window:HideMouse" +msgstr "" +"Cochez cette case pour obliger le curseur de la souris à ne pas apparaître " +"dans la fenêtre de jeu.\n" +"Cette option est utile si vous utilisez la souris comme contrôleur principal " +"pour les jeux.\n" +"Par défaut, le curseur s'efface automatiquement après deux secondes " +"d'inactivité." + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:82 +msgid "!ContextTip:Window:Fullscreen" +msgstr "" +"Lorsque cette option est activée, le jeu se lance automatiquement en mode " +"plein-écran (au démarrage ou après une pause).\n" +"Vous pouvez néanmoins modifier le mode d'affichage en jeu grâce à la " +"combinaison de touches ALT + Entrée." + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:93 +msgid "!ContextTip:Window:HideGS" +msgstr "" +"Ferme complètement la fenêtre de jeu lorsque la touche ESC ou la fonction " +"Pause est utilisée." + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:67 +msgid "!ContextTip:Gamefixes:EE Timing Hack" +msgstr "" +"Les jeux suivants nécessitent l'utilisation du hack :\n" +"* Shin Mega Tensei : Digital Devil Saga (cinématiques, crashs)\n" +"* SSX (bugs graphiques, crashs)\n" +"* Resident Evil : Dead Aim (textures)" + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:80 +msgid "!ContextTip:Gamefixes:OPH Flag hack" +msgstr "" +"Les jeux suivants nécessitent l'utilisation du hack :\n" +"* Bleach : Blade Battlers\n" +"* Growlanser II : The Sense of Justice\n" +"* Growlanser III : The Dual Darkness\n" +"* Wizardry" + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:89 +msgid "!ContextTip:Gamefixes:DMA Busy hack" +msgstr "" +"Les jeu suivant nécessite l'utilisation du hack :\n" +"* Mana Khemia : Alchemists of Al-Revis (sortir du campus)" + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:96 +msgid "!ContextTip:Gamefixes:VIF1 FIFO hack" +msgstr "" +"Les jeux suivants nécessitent l'utilisation du hack:\n" +"* Test Drive Unlimited\n" +"* Transformers" + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:119 +msgid "!Panel:Gamefixes:Compat Warning" +msgstr "" +"Les patchs peuvent corriger des problèmes liés à l'émulation de titres " +"spécifiques.\n" +"Néanmoins, ils peuvent aussi avoir un impact sur la compatibilité ou les " +"performances globales.\n" +"\n" +"Il est conseillé de préférer l'option \"Patchs automatiques\" disponible " +"dans le menu \"Système\" de l'émulateur plutôt que d'utiliser celle-ci.\n" +"(\"Patchs automatiques\" : utilise uniquement le patch associé au jeu émulé)" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:720 +msgid "!Notice:Mcd:Delete" +msgstr "" +"Vous êtes sur le point de supprimer la carte mémoire du lecteur %u. Toutes " +"les données présentes sur la carte seront perdues !\n" +"Êtes-vous sûr de réaliser cette manipulation ?" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:758 +msgid "!Notice:Mcd:CantDuplicate" +msgstr "" +"Erreur : Le port-PS2 concerné est occupé par un autre service, empêchant la " +"copie." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:801 +msgid "!Notice:Mcd:Copy Failed" +msgstr "" +"Erreur : Impossible de copier la carte mémoire du lecteur %u. Les données " +"concernées sont en cours d'utilisation." + +#: pcsx2/gui/Panels/MiscPanelStuff.cpp:35 +msgid "!Panel:Usermode:Explained" +msgstr "" +"Veuillez sélectionner le répertoire par défaut des fichiers utilisateur " +"PCSX2 (cartes mémoire, screenshots, paramètres d'affichage, etc...). Ce " +"réglage pourra être modifié plus tard via le panneau de configuration." + +#: pcsx2/gui/Panels/MiscPanelStuff.cpp:41 +msgid "!Panel:Usermode:Warning" +msgstr "" +"Vous pouvez modifier le répertoire par défaut du fichier utilisateu PCSX2 " +"(cartes mémoire, paramètres d'affichage, etc...). Cette option prévaut sur " +"tous les autres chemins d'accès spécifiés auparavant." + +#: pcsx2/gui/Panels/PathsPanel.cpp:40 +msgid "!ContextTip:Folders:Savestates" +msgstr "" +"Ce dossier contient les sauvegardes PCSX2. Vous pouvez enregistrer votre " +"partie en utilisant le menu ou en pressant les touches F1/F3 (sauver/" +"charger)." + +#: pcsx2/gui/Panels/PathsPanel.cpp:50 +msgid "!ContextTip:Folders:Snapshots" +msgstr "" +"Ce dossier contient les screenshots que vous avez pris lors de l'émulation " +"d'un jeu via PCSX2. Le format de l'image et sa qualité dépendent grandement " +"du plugin vidéo GS utilisé." + +#: pcsx2/gui/Panels/PathsPanel.cpp:60 +msgid "!ContextTip:Folders:Logs" +msgstr "" +"Ce dossier contient les rapports de diagnostique. La plupart des plugins " +"utilisent également le dossier ci-dessous pour enregistrer leurs rapports " +"d'erreurs." + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:242 +msgid "!Notice:PluginSelector:ConfirmShutdown" +msgstr "" +"Attention ! Il est conseillé de réinitialiser complètement l'émulateur PS2 " +"après avoir remplacé un plugin. PCSX2 va maintenant tenter de réaliser une " +"sauvegarde puis de restaurer la session, mais vous pourriez perdre les " +"données en cours si le programme échoue (incompatibilité des plugins).\n" +"\n" +"Êtes-vous sûr de vouloir appliquer ces paramètres ?" + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:457 +msgid "!Notice:PluginSelector:ApplyFailed" +msgstr "" +"Votre ordinateur ne dispose pas des ressources nécessaires pour lancer " +"l'émulateur. Essayez de libérer de l'espace-mémoire." + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:27 +msgid "!Panel:Speedhacks:EECycleX1" +msgstr "" +"1 - Cyclerate par défaut : la vitesse d'émulation est équivalente à celle " +"d'une véritable console Playstation 2." + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:32 +msgid "!Panel:Speedhacks:EECycleX2" +msgstr "" +"2 - Diminue l'EE Cyclerate d'envion 33% : amélioration sensible des " +"performances et compatibilité élevée." + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:37 +msgid "!Panel:Speedhacks:EECycleX3" +msgstr "" +"3 - Diminue l'EE Cyclerate d'environ 50% : amélioration modérée des " +"performances, mais le son de certaines cinématiques sera insupportable." + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:54 +msgid "!Panel:Speedhacks:VUCycleStealOff" +msgstr "" +"0 - Désactive le VU Cycle Stealing : compatibilité maximale, évidemment !" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:59 +msgid "!Panel:Speedhacks:VUCycleSteal1" +msgstr "" +"1 - VU Cycle Stealing léger : faible compatibilité mais une amélioration " +"sensible des performances pour certains jeux." + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:64 +msgid "!Panel:Speedhacks:VUCycleSteal2" +msgstr "" +"2 - VU Cycle Stealing modéré : très faible compatibilité, mais une " +"amélioration significative des performances pour certains jeux." + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:70 +msgid "!Panel:Speedhacks:VUCycleSteal3" +msgstr "" +"3 - VU Cycle Stealing maximal : relativement inutile puisqu'il engendre des " +"ralentissements et des bugs graphiques dans la plupart des jeux." + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:97 +msgid "!Panel:Speedhacks:Overview" +msgstr "" +"Les speedhacks améliorent généralement les performances mais peuvent " +"également générer des bugs, empêcher l'émulation du son et fausser la mesure " +"des FPS. Si vous rencontrez des soucis lors de l'émulation d'un jeu, cette " +"option est la première à désactiver." + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:129 +msgid "!ContextTip:Speedhacks:EECycleRate Slider" +msgstr "" +"Les valeurs définissent la vitesse de l'horlogue du CPU core R5900 de " +"l'EmotionEngine, et entraînent une amélioration des performances conséquente " +"pour les jeux incapables d'utiliser tout le potentiel des composants de la " +"Playstation 2." + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:150 +msgid "!ContextTip:Speedhacks:VUCycleStealing Slider" +msgstr "" +"Les valeurs définissent le nombre de cycles que le Vector Unit \"emprunte\" " +"au système EmotionEngine. Une valeur élevée augmente le nombre emprunté à " +"l'EE pour chaque microprogramme VU que le jeu utilise." + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 +msgid "!ContextTip:Speedhacks:vuFlagHack" +msgstr "" +"Met à jour les Status Flags uniquement pour les blocs qui les liront, plutôt " +"qu'ils ne soient lus en permanence. Cette option n'occasionne aucun problème " +"en général, et le Super VU fait la même chose par défaut." + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:174 +msgid "!ContextTip:Speedhacks:vuThread" +msgstr "" +"Transfère le VU 1 dans un processus individuel (microVU1 seulement). En " +"général, cela permet une amélioration des performances sur les processeurs 3 " +"coeurs ou plus.\n" +"La plupart des jeux supportent bien l'opération, mais certains d'entre eux " +"pourraient tout de même planter.\n" +"De plus, les processeurs dual-core souffriront de ralentissements " +"conséquents." + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:195 +msgid "!ContextTip:Speedhacks:INTC" +msgstr "" +"Ce hack fonctionne mieux avec les jeux utilisant le registre INTC Status " +"dans l'attente d'une synchronisation verticale, notamment dans les RPG en " +"2D. Les jeux qui n'utilisent pas cette méthode connaîtront une légère " +"amélioration des performances." + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 +msgid "!ContextTip:Speedhacks:BIFC0" +msgstr "Vise surtout l'EE idle loop à l'adresse 0x81FC0 du kernel." + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:207 +msgid "!ContextTip:Speedhacks:fastCDVD" +msgstr "" +"Vérifie les listes de compatibilité du HDLoader pour les jeux qui " +"rencontrent habituellement des problèmes avec lui (le plus souvent, " +"repérables par l'indication \"mode 1\" ou \"slow DVD\")." + +#: pcsx2/gui/Panels/VideoPanel.cpp:37 +msgid "!ContextTip:Framelimiter:Disable" +msgstr "" +"Si le Famelimiting est désactivé, les modes Turbo et Slow Motion ne seront " +"plus disponibles." + +#: pcsx2/gui/Panels/VideoPanel.cpp:227 +msgid "!Panel:Frameskip:Heading" +msgstr "" +"Attention : L'hardware de la PS2 rend impossible un saut de frames cohérent. " +"L'activation de cette option pourrait entraîner des bugs graphiques " +"conséquents dans certains jeux." + +#: pcsx2/gui/Panels/VideoPanel.cpp:306 +msgid "!ContextTip:GS:SyncMTGS" +msgstr "" +"Activez cette option si vous pensez que le processus SyncMTGS cause des bugs " +"graphiques ou crashs récurents." + +#: pcsx2/gui/Panels/VideoPanel.cpp:310 +msgid "!ContextTip:GS:DisableOutput" +msgstr "" +"Supprime les problèmes de benchmark liés au processus MTGS ou à une " +"surexploitation du GPU. Cette option est plus efficace losqu'elle est " +"utilisée avec une sauvegarde : réalisez votre sauvegarde au moment propice, " +"activez cette option puis chargez à nouveau la partie.\n" +"\n" +"Attention : Cette option peut être activée alors que le jeu a été mis en " +"pause, mais entraînera des bugs graphiques si elle est ensuite désactivée au " +"cours de la même partie." + +#: pcsx2/vtlb.cpp:710 +msgid "!Notice:HostVmReserve" +msgstr "" +"Votre système manque de ressources pour exécuter l'émulateur PCSX2. Cela " +"peut être dû à un autre programme qui occupe trop d'espace-mémoire." + +#: pcsx2/x86/sVU_zerorec.cpp:363 +msgid "!Notice:superVU:VirtualMemoryAlloc" +msgstr "" +"Out of Memory (ou presque) : le SuperVU recompiler n'est pas parvu à allouer " +"suffisamment de mémoire virtuelle, ce qui rend impossible son utilisation. " +"Ceci n'est pas une erreur critique, puisque le SVU recompiler est obsolète " +"et que vous devriez utiliser Microvu ! :p" + +#~ msgid "!ContextTip:Speedhacks:vuBlockHack" +#~ msgstr "" +#~ "Prévoit à l'avance que les futurs blocs n'auront pas besoin des anciennes " +#~ "données. L'option présente peu de risques et jusque là, aucun jeu n'a " +#~ "connu de bugs par sa faute." diff --git a/locales/fr_FR/pcsx2_Main.po b/locales/fr_FR/pcsx2_Main.po new file mode 100644 index 000000000..09e18e141 --- /dev/null +++ b/locales/fr_FR/pcsx2_Main.po @@ -0,0 +1,2708 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR PCSX2 Dev Team +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: PCSX2 0.9.9\n" +"Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" +"POT-Creation-Date: 2012-03-10 20:38+0100\n" +"PO-Revision-Date: 2012-03-08 11:42-0000\n" +"Last-Translator: goldeng \n" +"Language-Team: goldeng \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-KeywordsList: _;pxL;_d;pxDt;_t;pxLt\n" +"X-Poedit-SourceCharset: utf-8\n" +"X-Poedit-Basepath: trunk\\\n" +"X-Poedit-Language: French\n" +"X-Poedit-Country: France\n" +"X-Poedit-SearchPath-0: pcsx2\n" +"X-Poedit-SearchPath-1: common\n" + +#: common/include/Utilities/Exceptions.h:187 +msgid "No reason given." +msgstr "Erreur critique." + +#: common/include/Utilities/Exceptions.h:226 +msgid "Parse error" +msgstr "Parse error" + +#: common/include/Utilities/Exceptions.h:250 +msgid "Your machine's hardware is incapable of running PCSX2. Sorry dood." +msgstr "" +"Le matériel de votre ordinateur rend impossible le fonctionnement de PCSX2. " +"Bien essayé !" + +#: common/src/Utilities/Exceptions.cpp:219 +msgid "Oh noes! Out of memory!" +msgstr "Oups ! Surcharge de la mémoire !" + +#: common/src/Utilities/Exceptions.cpp:234 +msgid "" +"Virtual memory mapping failure! Your system may have conflicting device " +"drivers, services, or may simply have insufficient memory or resources to " +"meet PCSX2's lofty needs." +msgstr "" +"Echec du mappage de la mémoire virtuelle ! Votre système a dû entrer en " +"conflit avec un driver, un autre service ou peut être la victime d'une " +"insuffisance en ressources disponibles." + +#: common/src/Utilities/Exceptions.cpp:309 +msgid "Path: " +msgstr "Chemin d'accès :" + +#: common/src/Utilities/Exceptions.cpp:313 +msgid "[Unnamed or unknown]" +msgstr "[Inconnu]" + +#: common/src/Utilities/Exceptions.cpp:333 +msgid "A file could not be created." +msgstr "Un fichier n'a pas pu être créé." + +#: common/src/Utilities/Exceptions.cpp:353 +msgid "File not found." +msgstr "Fichier introuvable." + +#: common/src/Utilities/Exceptions.cpp:373 +msgid "" +"Permission denied while trying to open file, likely due to insufficient user " +"account rights." +msgstr "" +"Vous ne disposez pas des droits suffisants pour ouvrir ce fichier (mauvais " +"compte d'utilisateur ?)." + +#: common/src/Utilities/Exceptions.cpp:393 +msgid "" +"Unexpected end of file or stream encountered. File is probably truncated or " +"corrupted." +msgstr "L'opération a échoué. Le fichier est sans doute corrompu ou modifié." + +#: common/src/Utilities/ThreadTools.cpp:41 +msgid "Threading activity: start, detach, sync, deletion, etc." +msgstr "" +"Activité du processus : démarrage, synchronisation, suppression, etc..." + +#: common/src/Utilities/ThreadingDialogs.cpp:30 +msgid "Waiting for tasks..." +msgstr "Veuillez patienter..." + +#: common/src/Utilities/ThreadingDialogs.cpp:41 +msgid "Waiting for task..." +msgstr "Veuillez patienter..." + +#: common/src/Utilities/wxAppWithHelpers.cpp:36 +msgid "Includes idle event processing and some other uncommon event usages." +msgstr "Inclue certains évènements d'usage peu commun." + +#: pcsx2/CDVD/IsoFileFormats.cpp:416 +msgid "Unrecognized ISO image file format" +msgstr "Format du fichier ISO non reconnu." + +#: pcsx2/Elfheader.cpp:266 +msgid "Cannot load ELF binary image. The file may be corrupt or incomplete." +msgstr "" +"Impossible de charger l'image binaire ELF. Le fichier est sans doute " +"corrompu ou incomplet." + +#: pcsx2/Elfheader.cpp:268 +msgid "" +"If loading from an ISO image, this error may be caused by an unsupported ISO " +"image type or a bug in PCSX2 ISO image support." +msgstr "" +"Si cette erreur se produit à la suite du montage d'une image ISO, c'est que " +"le format utilisé ne semble pas être pris en charge par PCSX2." + +#: pcsx2/MTGS.cpp:859 +msgid "" +"The MTGS thread has become unresponsive while waiting for the GS plugin to " +"open." +msgstr "" +"Le processus MTGS ne répondait plus alors qu'il patientait jusqu'au " +"démarrage du plugin GS." + +#: pcsx2/PluginManager.cpp:709 +msgid "" +"The savestate cannot be loaded, as it appears to be corrupt or incomplete." +msgstr "" +"La sauvegarde ne peut pas être chargée, elle est sans doute corrompue ou " +"incomplète." + +#: pcsx2/PluginManager.cpp:719 +#, c-format +msgid "" +"%s plugin failed to open. Your computer may have insufficient resources, or " +"incompatible hardware/drivers." +msgstr "" +"Le plugin %s n'a pas pu être ouvert. Votre ordinateur ne dispose pas de " +"ressources en mémoire suffisantes, ou le plugin est incompatible avec votre " +"matériel." + +#: pcsx2/PluginManager.cpp:726 +#, c-format +msgid "" +"%s plugin failed to initialize. Your system may have insufficient memory or " +"resources needed." +msgstr "" +"Le plugin %s n'a pas pu s'initialiser. Votre système ne semble pas disposer " +"de ressources en mémoire suffisantes." + +#: pcsx2/PluginManager.cpp:832 +#, c-format +msgid "The configured %s plugin file was not found" +msgstr "Le fichier de configuration du plugin %s est introuvable" + +#: pcsx2/PluginManager.cpp:836 +#, c-format +msgid "The configured %s plugin file is not a valid dynamic library" +msgstr "" +"Le fichier de configuration du plugin %s n'utilise pas une librairie " +"dynamique valide." + +#: pcsx2/PluginManager.cpp:854 +#, c-format +msgid "" +"The configured %s plugin is not a PCSX2 plugin, or is for an older " +"unsupported version of PCSX2." +msgstr "" +"Le plugin %s n'est pas un plugin PCSX2, ou la version utilisée est trop " +"ancienne." + +#: pcsx2/PluginManager.cpp:879 +msgid "" +"The plugin reports that your hardware or software/drivers are not supported." +msgstr "" +"Le plugin indique que votre matériel ou les drivers utilisés ne sont pas " +"supportés." + +#: pcsx2/PluginManager.cpp:900 +msgid "" +"Configured plugin is not a PCSX2 plugin, or is for an older unsupported " +"version of PCSX2." +msgstr "" +"Le plugin configuré n'est pas un plugin PCSX2, ou la version utilisée est " +"trop ancienne." + +#: pcsx2/PluginManager.cpp:926 +#, c-format +msgid "" +"Configured %s plugin is not a valid PCSX2 plugin, or is for an older " +"unsupported version of PCSX2." +msgstr "" +"Le plugin %s n'est pas un plugin PCSX2, ou la version utilisée est trop " +"ancienne." + +#: pcsx2/PluginManager.cpp:1355 +msgid "Internal Memorycard Plugin failed to initialize." +msgstr "Le plugin de la Memory Card interne n'a pas pu s'initialiser." + +#: pcsx2/PluginManager.cpp:1752 +msgid "Unloaded Plugin" +msgstr "Plugin non-chargé." + +#: pcsx2/SaveState.cpp:342 +msgid "Cannot load savestate. It is of an unknown or unsupported version." +msgstr "" +"Impossible de charger la sauvegarde. Elle n'est pas supportée par cette " +"version du logiciel." + +#: pcsx2/SourceLog.cpp:96 +msgid "Dumps detailed information for PS2 executables (ELFs)." +msgstr "Infomations détaillées des exécutables PS2 (ELF)." + +#: pcsx2/SourceLog.cpp:101 +msgid "" +"Logs manual protection, split blocks, and other things that might impact " +"performance." +msgstr "" +"Protection manuelle des rapports et autres opérations qui peuvent avoir un " +"impact sur les performances générales." + +#: pcsx2/SourceLog.cpp:106 +msgid "Shows the game developer's logging text (EE processor)" +msgstr "Affiche le rapport textuel des développeurs du jeu (EE processor)" + +#: pcsx2/SourceLog.cpp:111 +msgid "Shows the game developer's logging text (IOP processor)" +msgstr "Affiche le rapport textuel des développeurs du jeu (IOP processor)" + +#: pcsx2/SourceLog.cpp:116 +msgid "Shows DECI2 debugging logs (EE processor)" +msgstr "Affiche les rapports du debogueur DECI2 (EE processor)" + +#: pcsx2/SourceLog.cpp:145 +msgid "SYSCALL and DECI2 activity." +msgstr "Activités SYSCALL et DECI2." + +#: pcsx2/SourceLog.cpp:151 +msgid "Direct memory accesses to unknown or unmapped EE memory space." +msgstr "" +"Accès direct de la mémoire vers un espace mémoire EE inconnu ou non-mappé." + +#: pcsx2/SourceLog.cpp:157 pcsx2/SourceLog.cpp:276 +msgid "Disasm of executing core instructions (excluding COPs and CACHE)." +msgstr "" +"/DISASM de l'exécution des instructions de type core (à l'exception des " +"fonctions COP et CACHE)." + +#: pcsx2/SourceLog.cpp:163 +msgid "Disasm of COP0 instructions (MMU, cpu and dma status, etc)." +msgstr "/DISASM des instructions COP0 (MMU, cpu et statut du dma, etc...)." + +#: pcsx2/SourceLog.cpp:169 +msgid "Disasm of the EE's floating point unit (FPU) only." +msgstr "/DISASM du FPU (Floating Point Unit) EE uniquement." + +#: pcsx2/SourceLog.cpp:175 +msgid "Disasm of the EE's VU0macro co-processor instructions." +msgstr "/DISASM des instructions du co-processeur Vu0macro EE." + +#: pcsx2/SourceLog.cpp:181 +msgid "Execution of EE cache instructions." +msgstr "Exécution des instructions EE en cache." + +#: pcsx2/SourceLog.cpp:187 +msgid "" +"All known hardware register accesses (very slow!); not including sub filter " +"options below." +msgstr "" +"Accès à tous les registres hardware connu (très lent !) : n'inclue pas les " +"filtres ci-dessous." + +#: pcsx2/SourceLog.cpp:193 pcsx2/SourceLog.cpp:294 +msgid "Logs only unknown, unmapped, or unimplemented register accesses." +msgstr "" +"Seulement les rapports inconnus, ignorant les non-mappés ou non-implémentés " +"dans le registre." + +#: pcsx2/SourceLog.cpp:199 pcsx2/SourceLog.cpp:300 +msgid "Logs only DMA-related registers." +msgstr "Seulement les rapports liés au DMA dans les registres." + +#: pcsx2/SourceLog.cpp:205 +msgid "IPU activity: hardware registers, decoding operations, DMA status, etc." +msgstr "" +"Activité IPU : registres hardware, décodage des variables, statut du DMA, " +"etc..." + +#: pcsx2/SourceLog.cpp:211 +msgid "All GIFtag parse activity; path index, tag type, etc." +msgstr "Toutes les activités du GIFtag : path index, tag type, etc..." + +#: pcsx2/SourceLog.cpp:217 +msgid "All VIFcode processing; command, tag style, interrupts." +msgstr "Tous les processus du VIFcode : command, tag style, interrupts." + +#: pcsx2/SourceLog.cpp:223 +msgid "All processing involved in Path3 Masking" +msgstr "Toutes les opérations impliquées dans le Path3 Masking" + +#: pcsx2/SourceLog.cpp:229 +msgid "Scratchpad's MFIFO activity." +msgstr "Bloc-note de l'activité MFIFO." + +#: pcsx2/SourceLog.cpp:235 +msgid "Actual data transfer logs, bus right arbitration, stalls, etc." +msgstr "" +"Données réelles des transferts de rapports, vrai arbitrage du bus, stalls, " +"etc..." + +#: pcsx2/SourceLog.cpp:241 +msgid "Tracks all EE counters events and some counter register activity." +msgstr "Piste tous les évènements EE et d'autres activités liées au registre." + +#: pcsx2/SourceLog.cpp:247 +msgid "Dumps various VIF and VIFcode processing data." +msgstr "Dump les données des processus VIF et VIFcode." + +#: pcsx2/SourceLog.cpp:253 +msgid "Dumps various GIF and GIFtag parsing data." +msgstr "Dump les données GIF et GIFtag." + +#: pcsx2/SourceLog.cpp:264 +msgid "SYSCALL and IRX activity." +msgstr "Activités SYSCALL et IRX." + +#: pcsx2/SourceLog.cpp:270 +msgid "Direct memory accesses to unknown or unmapped IOP memory space." +msgstr "" +"Accès direct de la mémoire à un espace mémoire IOP inconnu ou non-mappé." + +#: pcsx2/SourceLog.cpp:282 +msgid "Disasm of the IOP's GPU co-processor instructions." +msgstr "/DISASM des instructions du co-processeur GPU IOP." + +#: pcsx2/SourceLog.cpp:288 +msgid "" +"All known hardware register accesses, not including the sub-filters below." +msgstr "" +"Accès à tous les registres hardware connus, à l'exception des filtres ci-" +"dessous." + +#: pcsx2/SourceLog.cpp:306 +msgid "Memorycard reads, writes, erases, terminators, and other processing." +msgstr "" +"Lecture, écriture, écrasement, suppression et autres fonctions relatives aux " +"cartes mémoire." + +#: pcsx2/SourceLog.cpp:312 +msgid "Gamepad activity on the SIO." +msgstr "Activité du joystick sur le SIO." + +#: pcsx2/SourceLog.cpp:318 +msgid "Actual DMA event processing and data transfer logs." +msgstr "" +"Processus réel des évènements DMA et données relatives au transfert des " +"rapports." + +#: pcsx2/SourceLog.cpp:324 +msgid "Tracks all IOP counters events and some counter register activity." +msgstr "Piste tous les évènements IOP et d'autres activités liées au registre." + +#: pcsx2/SourceLog.cpp:330 +msgid "Detailed logging of CDVD hardware." +msgstr "Rapport détaillé de l'hardware CDVD." + +#: pcsx2/System.h:206 pcsx2/System.h:207 pcsx2/System.h:208 +msgid "PCSX2 Message" +msgstr "Message PCSX2" + +#: pcsx2/ZipTools/thread_gzip.cpp:82 +msgid "" +"The savestate was not properly saved. The temporary file was created " +"successfully but could not be moved to its final resting place." +msgstr "" +"Le processus de sauvegarde ne s'est pas déroulé comme prévu. Un fichier " +"temporaire a été créé avec succès mais n'a pas pu être acheminé vers le " +"dossier choisi." + +#: pcsx2/gui/AppConfig.cpp:842 +msgid "Safest" +msgstr "Le plus sûr" + +#: pcsx2/gui/AppConfig.cpp:843 +msgid "Safe (faster)" +msgstr "Sûr (rapide)" + +#: pcsx2/gui/AppConfig.cpp:844 +msgid "Balanced" +msgstr "Equilibré" + +#: pcsx2/gui/AppConfig.cpp:845 +msgid "Aggressive" +msgstr "Efficace" + +#: pcsx2/gui/AppConfig.cpp:846 +msgid "Aggressive plus" +msgstr "Efficace (+)" + +#: pcsx2/gui/AppConfig.cpp:847 +msgid "Mostly Harmful" +msgstr "Nuisible" + +#: pcsx2/gui/AppConfig.cpp:1007 pcsx2/gui/AppConfig.cpp:1013 +msgid "Failed to overwrite existing settings file; permission was denied." +msgstr "" +"Erreur lors de l'écrasement des paramètres pré-existants : autorisation " +"refusée." + +#: pcsx2/gui/AppCorePlugins.cpp:404 +msgid "Loading PS2 system plugins..." +msgstr "Plugins du système en cours de chargement..." + +#: pcsx2/gui/AppInit.cpp:41 +msgid "PCSX2 - SSE2 Recommended" +msgstr "PCSX2 - SSE2 Recommandé" + +#: pcsx2/gui/AppInit.cpp:71 +msgid "" +"SSE extensions are not available. PCSX2 requires a cpu that supports the " +"SSE instruction set." +msgstr "" +"Les extensions SSE ne sont pas disponibles. PCSX2 requiert un CPU qui " +"supporte les instructions SSE." + +#: pcsx2/gui/AppInit.cpp:154 +msgid "PCSX2 Recompiler Error(s)" +msgstr "Erreurs(s) du PCSX2 Recompiler" + +#: pcsx2/gui/AppInit.cpp:227 +msgid "All options are for the current session only and will not be saved.\n" +msgstr "" +"Les paramètres ne concernent que la session actuelle et ne seront pas " +"sauvegardés.\n" + +#: pcsx2/gui/AppInit.cpp:237 pcsx2/gui/AppMain.cpp:299 +msgid "IsoFile" +msgstr "IsoFile" + +#: pcsx2/gui/AppInit.cpp:238 +msgid "displays this list of command line options" +msgstr "affiche la liste des commandes" + +#: pcsx2/gui/AppInit.cpp:239 +msgid "forces the program log/console to be visible" +msgstr "oblige le rapport ou la console du programme à s'afficher" + +#: pcsx2/gui/AppInit.cpp:240 +msgid "use fullscreen GS mode" +msgstr "utilise le mode plein-écran GS" + +#: pcsx2/gui/AppInit.cpp:241 +msgid "use windowed GS mode" +msgstr "utilise le mode fenêtré GS" + +#: pcsx2/gui/AppInit.cpp:243 +msgid "disables display of the gui while running games" +msgstr "désactive l'affichage du GUI lorsqu'un jeu est lancé" + +#: pcsx2/gui/AppInit.cpp:244 +msgid "executes an ELF image" +msgstr "exécute un fichier ELF" + +#: pcsx2/gui/AppInit.cpp:245 +msgid "boots an empty dvd tray; use to enter the PS2 system menu" +msgstr "" +"démarre à partir d'un DVD vierge : à utiliser pour accéder directement au " +"menu système de la PS2" + +#: pcsx2/gui/AppInit.cpp:246 +msgid "boots from the CDVD plugin (overrides IsoFile parameter)" +msgstr "démarre depuis le plugin CDVD (remplace les paramètres IsoFile)" + +#: pcsx2/gui/AppInit.cpp:248 +msgid "disables all speedhacks" +msgstr "désactive tous les speedhacks" + +#: pcsx2/gui/AppInit.cpp:249 +msgid "use the specified comma or pipe-delimited list of gamefixes." +msgstr "utilisent les patchs sélectionnés dans la liste." + +#: pcsx2/gui/AppInit.cpp:250 +msgid "disables fast booting" +msgstr "désactive le démarrage rapide" + +#: pcsx2/gui/AppInit.cpp:252 +msgid "changes the configuration file path" +msgstr "modifie le chemin d'accès au fichier de configuration" + +#: pcsx2/gui/AppInit.cpp:253 +msgid "specifies the PCSX2 configuration file to use" +msgstr "spécifie le fichier de configuration PCSX2 à utiliser" + +#: pcsx2/gui/AppInit.cpp:254 +#, c-format +msgid "forces %s to start the First-time Wizard" +msgstr "oblige %s à démarrer l'assistant de première configuration" + +#: pcsx2/gui/AppInit.cpp:255 +msgid "enables portable mode operation (requires admin/root access)" +msgstr "active le mode portable (requiert les droits d'un administrateur)" + +#: pcsx2/gui/AppInit.cpp:259 +#, c-format +msgid "specify the file to use as the %s plugin" +msgstr "spécifie que le fichier doit être utilisé comme le plugin %s" + +#: pcsx2/gui/AppInit.cpp:307 +#, c-format +msgid "Plugin Override Error - %s" +msgstr "Erreur ! Surcharge du plugin - %s" + +#: pcsx2/gui/AppInit.cpp:310 +#, c-format +msgid "" +"%s Plugin Override Error! The following file does not exist or is not a " +"valid %s plugin:\n" +"\n" +msgstr "" +"Erreur ! Surcharge du plugin : le fichier n'existe pas ou n'est pas un " +"plugin %s valide :\n" +"\n" + +#: pcsx2/gui/AppInit.cpp:317 +#, c-format +msgid "Press OK to use the default configured plugin, or Cancel to close %s." +msgstr "" +"Cliquez sur OK pour utiliser la configuration par défaut, ou sur Annuler " +"pour fermer %s." + +#: pcsx2/gui/AppInit.cpp:496 +msgid "PCSX2 Error: Hardware Deficiency" +msgstr "Erreur PCSX2 : Hardware." + +#: pcsx2/gui/AppInit.cpp:496 pcsx2/gui/AppInit.cpp:508 +#, c-format +msgid "Press OK to close %s." +msgstr "Cliquez sur OK pour fermer %s." + +#: pcsx2/gui/AppInit.cpp:509 +#, c-format +msgid "%s Critical Error" +msgstr "Erreur critique de %s !" + +#: pcsx2/gui/AppInit.cpp:679 +msgid "OK" +msgstr "OK" + +#: pcsx2/gui/AppInit.cpp:680 +msgid "&OK" +msgstr "&OK" + +#: pcsx2/gui/AppInit.cpp:681 +msgid "Cancel" +msgstr "Annuler" + +#: pcsx2/gui/AppInit.cpp:682 +msgid "&Cancel" +msgstr "&Annuler" + +#: pcsx2/gui/AppInit.cpp:683 +msgid "&Apply" +msgstr "&Appliquer" + +#: pcsx2/gui/AppInit.cpp:684 +msgid "&Next >" +msgstr "&Suivant >" + +#: pcsx2/gui/AppInit.cpp:685 +msgid "< &Back" +msgstr "< &Précédent" + +#: pcsx2/gui/AppInit.cpp:686 +msgid "&Back" +msgstr "&Retour" + +#: pcsx2/gui/AppInit.cpp:687 +msgid "&Finish" +msgstr "&Terminer" + +#: pcsx2/gui/AppInit.cpp:688 +msgid "&Yes" +msgstr "&Oui" + +#: pcsx2/gui/AppInit.cpp:689 +msgid "&No" +msgstr "&Non" + +#: pcsx2/gui/AppInit.cpp:690 +msgid "Browse" +msgstr "Parcourir" + +#: pcsx2/gui/AppInit.cpp:691 +msgid "&Save" +msgstr "&Enregistrer" + +#: pcsx2/gui/AppInit.cpp:692 +msgid "Save &As..." +msgstr "Enregistrer &sous..." + +#: pcsx2/gui/AppInit.cpp:693 +msgid "&Help" +msgstr "&Aide" + +#: pcsx2/gui/AppInit.cpp:694 +msgid "&Home" +msgstr "&Accueil" + +#: pcsx2/gui/AppInit.cpp:696 +msgid "Show about dialog" +msgstr "Ouvre une boîte de dialogue (qui vaut le coup)." + +#: pcsx2/gui/AppMain.cpp:87 +msgid "" +"\n" +"\n" +"Press Ok to go to the Plugin Configuration Panel." +msgstr "" +"\n" +"\n" +"Cliquez sur OK pour accéder au panel de configuration des plugins." + +#: pcsx2/gui/AppMain.cpp:140 pcsx2/gui/AppMain.cpp:154 +msgid "" +"Warning! System plugins have not been loaded. PCSX2 may be inoperable." +msgstr "" +"ATTENTION ! Le système des plugins n'a pas été chargé. PCSX2 ne peut pas " +"être utilisé." + +#: pcsx2/gui/AppMain.cpp:309 +#, c-format +msgid "%s Commandline Options" +msgstr "Options de commande de %s" + +#: pcsx2/gui/AppMain.cpp:573 +msgid "PS2 BIOS Error" +msgstr "Erreur ! BIOS PS2" + +#: pcsx2/gui/AppMain.cpp:574 +msgid "Press Ok to go to the BIOS Configuration Panel." +msgstr "Cliquez sur OK pour accéder au panel de configuration du BIOS." + +#: pcsx2/gui/AppMain.cpp:626 +msgid "PCSX2 Unresponsive Thread" +msgstr "Le processus PCSX2 ne répond pas" + +#: pcsx2/gui/AppMain.cpp:636 +msgid "Terminate" +msgstr "Terminer" + +#: pcsx2/gui/AppMain.cpp:963 +msgid "Executing PS2 Virtual Machine..." +msgstr "Exécution de la machine virtuelle PS2..." + +#: pcsx2/gui/AppRes.cpp:72 +msgid "Browse for an Iso that is not in your recent history." +msgstr "Trouve un ISO qui n'apparaît pas dans l'historique récent." + +#: pcsx2/gui/AppRes.cpp:72 +msgid "Browse..." +msgstr "Parcourir..." + +#: pcsx2/gui/AppUserMode.cpp:99 +msgid "The following folders exist, but are not writable:" +msgstr "" +"Les dossiers suivants existent mais la permission d'écriture est refusée :" + +#: pcsx2/gui/AppUserMode.cpp:104 +msgid "The following folders are missing and cannot be created:" +msgstr "Les dossiers suivants sont absents et ne peuvent pas être créés :" + +#: pcsx2/gui/AppUserMode.cpp:144 +#, c-format +msgid "Portable mode error - %s" +msgstr "Erreur ! Mode portable %s -" + +#: pcsx2/gui/AppUserMode.cpp:157 +msgid "" +"PCSX2 has been installed as a portable application but cannot run due to the " +"following errors:" +msgstr "" +"PCSX2 a été installée comme une application portable mais ne peut pas se " +"lancer à cause des erreurs suivantes :" + +#: pcsx2/gui/AppUserMode.cpp:165 +msgid "Switch to User Documents Mode" +msgstr "Utiliser le mode User Documents" + +#: pcsx2/gui/AppUserMode.cpp:178 +#, c-format +msgid "%s is switching to local install mode." +msgstr "%s utilise à présent le mode d'installation local" + +#: pcsx2/gui/AppUserMode.cpp:179 +msgid "" +"Try to remove the file called \"portable.ini\" from your installation " +"directory manually." +msgstr "" +"Essayez d'effacer manuellement le fichier \"portable.ini\" du répertoire " +"d'installation." + +#: pcsx2/gui/ApplyState.h:55 +msgid "Cannot apply new settings, one of the settings is invalid." +msgstr "" +"Impossible d'appliquer les nouveaux paramètres, l'un d'entre eux n'est pas " +"valide." + +#: pcsx2/gui/ConsoleLogger.cpp:120 +msgid "Save log question" +msgstr "Sauvegarder le log" + +#: pcsx2/gui/ConsoleLogger.cpp:413 +msgid "Fits a lot of log in a microcosmically small area." +msgstr "Regroupe un nombre important de logs dans un espace réduit." + +#: pcsx2/gui/ConsoleLogger.cpp:413 +msgid "Small" +msgstr "Petit" + +#: pcsx2/gui/ConsoleLogger.cpp:415 +msgid "It's what I use (the programmer guy)." +msgstr "C'est ce que j'utilise (le mec qui programme)." + +#: pcsx2/gui/ConsoleLogger.cpp:415 pcsx2/gui/Panels/CpuPanel.cpp:38 +msgid "Normal" +msgstr "Normal" + +#: pcsx2/gui/ConsoleLogger.cpp:417 +msgid "Its nice and readable." +msgstr "C'est sympa et lisible." + +#: pcsx2/gui/ConsoleLogger.cpp:417 +msgid "Large" +msgstr "Moyen" + +#: pcsx2/gui/ConsoleLogger.cpp:419 +msgid "Huge" +msgstr "Grand" + +#: pcsx2/gui/ConsoleLogger.cpp:419 +msgid "In case you have a really high res display." +msgstr "Au cas où vous utiliseriez une résolution d'écran VRAIMENT élevée." + +#: pcsx2/gui/ConsoleLogger.cpp:423 +msgid "Default soft-tone color scheme." +msgstr "Thème par défaut." + +#: pcsx2/gui/ConsoleLogger.cpp:423 +msgid "Light theme" +msgstr "Thème \"Light\"" + +#: pcsx2/gui/ConsoleLogger.cpp:424 +msgid "" +"Classic black color scheme for people who enjoy having text seared into " +"their optic nerves." +msgstr "Thème \"Classic black\"" + +#: pcsx2/gui/ConsoleLogger.cpp:424 +msgid "Dark theme" +msgstr "Thème \"Dark\"" + +#: pcsx2/gui/ConsoleLogger.cpp:427 +msgid "Always on Top" +msgstr "Toujours au-dessus" + +#: pcsx2/gui/ConsoleLogger.cpp:428 +msgid "" +"When checked the log window will be visible over other foreground windows." +msgstr "" +"Une fois cochée, la fenêtre de dialogue restera toujours par-dessus les " +"autres fenêtres." + +#: pcsx2/gui/ConsoleLogger.cpp:430 +msgid "&Save..." +msgstr "&Enregistrer..." + +#: pcsx2/gui/ConsoleLogger.cpp:430 +msgid "Save log contents to file" +msgstr "Sauvegarder le contenu du log dans un fichier" + +#: pcsx2/gui/ConsoleLogger.cpp:431 +msgid "C&lear" +msgstr "N&ettoyer" + +#: pcsx2/gui/ConsoleLogger.cpp:431 +msgid "Clear the log window contents" +msgstr "Nettoyer le contenu du log dans la fenêtre" + +#: pcsx2/gui/ConsoleLogger.cpp:433 pcsx2/gui/Dialogs/SysConfigDialog.cpp:280 +msgid "Appearance" +msgstr "Apparence" + +#: pcsx2/gui/ConsoleLogger.cpp:435 +msgid "&Close" +msgstr "&Fermer" + +#: pcsx2/gui/ConsoleLogger.cpp:435 +msgid "Close this log window; contents are preserved" +msgstr "Fermer la fenêtre du log : le contenu sera préservé" + +#: pcsx2/gui/ConsoleLogger.cpp:439 +msgid "Dev/Verbose" +msgstr "Dev / Impression" + +#: pcsx2/gui/ConsoleLogger.cpp:439 +msgid "Shows PCSX2 developer logs" +msgstr "Affiche les logs des développeurs de PCSX2" + +#: pcsx2/gui/ConsoleLogger.cpp:440 +msgid "CDVD reads" +msgstr "Lecture CDVD" + +#: pcsx2/gui/ConsoleLogger.cpp:440 +msgid "Shows disk read activity" +msgstr "Affiche l'activité de la lecture du disque" + +#: pcsx2/gui/ConsoleLogger.cpp:457 +msgid "Enable all" +msgstr "Tout activer" + +#: pcsx2/gui/ConsoleLogger.cpp:457 +msgid "Enables all log source filters." +msgstr "Activer tous les filtres source du log." + +#: pcsx2/gui/ConsoleLogger.cpp:458 +msgid "Disable all" +msgstr "Tout désactiver" + +#: pcsx2/gui/ConsoleLogger.cpp:458 +msgid "Disables all log source filters." +msgstr "Désactiver tous les filtres source du log." + +#: pcsx2/gui/ConsoleLogger.cpp:460 +msgid "&Log" +msgstr "&Rapport" + +#: pcsx2/gui/ConsoleLogger.cpp:461 +msgid "&Sources" +msgstr "&Sources" + +#: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:35 +#, c-format +msgid "About %s" +msgstr "En savoir plus sur %s !" + +#: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:55 +msgid "Betatesting" +msgstr "Beta-test" + +#: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:55 +msgid "Previous versions" +msgstr "Versions précédentes" + +#: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:55 +msgid "Webmasters" +msgstr "Webmestres" + +#: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:66 +msgid "Plugin Specialists" +msgstr "Spécialistes plugins" + +#: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:66 +msgid "Special thanks to" +msgstr "Remerciements particuliers à" + +#: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:82 +msgid "Developers" +msgstr "Développeurs :" + +#: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:84 +msgid "Contributors" +msgstr "Ils ont contribué :" + +#: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:98 +msgid "A Playstation 2 Emulator" +msgstr "Un émulateur Playstation 2" + +#: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:102 +msgid "PCSX2 Official Website and Forums" +msgstr "Site internet/forums officiels PCSX2" + +#: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:106 +msgid "PCSX2 Official Svn Repository at Googlecode" +msgstr "Répertoire Svn officiel PCSX2 (sur Googlecode)" + +#: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:110 +msgid "I've seen enough" +msgstr "C'est bon, j'ai compris !" + +#: pcsx2/gui/Dialogs/AssertionDialog.cpp:23 +msgid "Assertion Failure - " +msgstr "Assertion Failure -" + +#: pcsx2/gui/Dialogs/BaseConfigurationDialog.cpp:193 +msgid "Saves a snapshot of this settings panel to a PNG file." +msgstr "Sauvegarder une image d'écran des paramètres (fichier PNG)." + +#: pcsx2/gui/Dialogs/BaseConfigurationDialog.cpp:308 +msgid "Save dialog screenshots to..." +msgstr "Sauvegarder les images vers..." + +#: pcsx2/gui/Dialogs/BiosSelectorDialog.cpp:31 +msgid "BIOS Selector" +msgstr "Choix du BIOS" + +#: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:193 +msgid "Do not show this dialog again." +msgstr "Ne plus montrer cette fenêtre." + +#: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:199 +msgid "" +"Disables this popup and whatever response you select here will be " +"automatically used from now on." +msgstr "Désactive cette fenêtre et se rappellera de la réponse choisie ici." + +#: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:201 +msgid "" +"The popup will not be shown again. This setting can be undone from the " +"settings panels." +msgstr "" +"Cette fenêtre ne s'affichera plus à l'avenir. Les paramètres peuvent être " +"réinitialisés à partir du panel concerné." + +#: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:247 +#: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:292 +msgid "Ignore" +msgstr "Ignorer" + +#: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:278 +msgid "Reset" +msgstr "Réinitialiser" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:40 +msgid "Create a new memory card" +msgstr "Créer une nouvelle carte mémoire" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:59 +#: pcsx2/gui/Panels/DirPickerPanel.cpp:74 +#: pcsx2/gui/Panels/DirPickerPanel.cpp:273 +msgid "Create" +msgstr "Créer" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:71 +msgid "New memory card:" +msgstr "Nouvelle carte mémoire :" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:72 +msgid "At folder: " +msgstr "Dans le dossier :" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:75 +msgid "Select file name: " +msgstr "Nom du fichier :" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:149 +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:855 +#, c-format +msgid "Error (%s)" +msgstr "Erreur (%s)" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:150 +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:164 +msgid "Create memory card" +msgstr "Créer une carte mémoire" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:163 +msgid "Error: The memory card could not be created." +msgstr "Erreur ! La carte mémoire n'a pas pu être créée." + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:177 +msgid "Use NTFS compression when creating this card." +msgstr "Utiliser une compression NTFS pour créer la carte." + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:195 +msgid "8 MB [most compatible]" +msgstr "8 MB [la plus compatible]" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:195 +msgid "" +"This is the standard Sony-provisioned size, and is supported by all games " +"and BIOS versions." +msgstr "" +"Il s'agit de la taille standard prévue par Sony, et elle est supportée par " +"tous les jeux (ainsi que tous les BIOS existants)." + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:196 +msgid "" +"Always use this option if you want the safest and surest memory card " +"behavior." +msgstr "" +"Toujours utiliser cette option pour être sûr d'éviter les sauvegardes " +"corrompues." + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:199 +msgid "16 MB" +msgstr "16 MB" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:199 +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:203 +msgid "" +"A typical size for 3rd-party memory cards which should work with most games." +msgstr "" +"Le format classique des cartes mémoires non-officielles, qui devraient " +"marcher avec la plupart des jeux." + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:200 +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:204 +msgid "16 and 32 MB cards have roughly the same compatibility factor." +msgstr "" +"Les cartes mémoire de 16 et 32 MB possèdent des facteurs de compatibilité " +"similaires." + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:203 +msgid "32 MB" +msgstr "32 MB" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:207 +msgid "64 MB" +msgstr "64 MB" + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:207 +msgid "" +"Low compatibility warning: Yes it's very big, but may not work with many " +"games." +msgstr "" +"Attention ! La compatibilité est réduite : certes, c'est très gros, mais la " +"plupart des jeux ne marcheront pas avec." + +#: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:208 +msgid "" +"Use at your own risk. Erratic memory card behavior is possible (though " +"unlikely)." +msgstr "" +"A vos risques et périls. La carte mémoire pourrait rencontrer des erreurs " +"critiques." + +#: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:47 +#, c-format +msgid "Select a folder for %s settings" +msgstr "Sélectionner un dossier pour les paramètres de %s" + +#: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:47 +msgid "Settings" +msgstr "Paramètres" + +#: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:81 +msgid "Language selector" +msgstr "Choix de la langue" + +#: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:84 +msgid "" +"Change the language only if you need to.\n" +"The system default should be fine for most operating systems." +msgstr "" +"Ne changez la langue que si vous en avez réellement besoin.\n" +"Le système par défaut fonctionne bien, la plupart du temps." + +#: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:90 +msgid "Welcome to PCSX2!" +msgstr "Bienvenue dans PCSX2 !" + +#: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:104 +msgid "Configuration Guides (online)" +msgstr "Guides de configuration (online)" + +#: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:108 +msgid "Readme / FAQ (Offline/PDF)" +msgstr "Lisez-moi / FAQ (offline - fichier PDF)" + +#: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:117 +#, c-format +msgid "%s First Time Configuration" +msgstr "Première configuration de %s" + +#: pcsx2/gui/Dialogs/GameDatabaseDialog.cpp:24 +#, c-format +msgid "Game database - %s" +msgstr "Base de données - %s" + +#: pcsx2/gui/Dialogs/ImportSettingsDialog.cpp:24 +msgid "Import Existing Settings?" +msgstr "Importer les paramètres existants ?" + +#: pcsx2/gui/Dialogs/ImportSettingsDialog.cpp:39 +msgid "Import" +msgstr "Importer" + +#: pcsx2/gui/Dialogs/ImportSettingsDialog.cpp:40 +msgid "Overwrite" +msgstr "Ecraser" + +#: pcsx2/gui/Dialogs/LogOptionsDialog.cpp:27 +msgid "Trace Logging" +msgstr "Rapport automatique" + +#: pcsx2/gui/Dialogs/McdConfigDialog.cpp:40 +msgid "Auto-eject memory cards when loading savestates" +msgstr "" +"Éjecter automatiquement les cartes mémoire lorsqu'une sauvegarde virtuelle " +"est chargée" + +#: pcsx2/gui/Dialogs/McdConfigDialog.cpp:96 +msgid "MemoryCard Manager" +msgstr "Gestionnaire de cartes mémoire" + +#: pcsx2/gui/Dialogs/McdConfigDialog.cpp:112 +msgid "Drag cards to or from PS2-ports" +msgstr "Lecture des cartes mémoire vers / depuis les ports PS2" + +#: pcsx2/gui/Dialogs/McdConfigDialog.cpp:113 +msgid "" +"\n" +"Note: Duplicate/Rename/Create/Delete will NOT be reverted with 'Cancel'." +msgstr "" +"\n" +"PS. Les fonctions disponibles ne peuvent PAS être annulées gâce au bouton " +"\"Annuler\"." + +#: pcsx2/gui/Dialogs/PickUserModeDialog.cpp:24 +msgid "PCSX2 First Time configuration" +msgstr "Première configuration de PCSX2" + +#: pcsx2/gui/Dialogs/PickUserModeDialog.cpp:29 +#, c-format +msgid "%s is starting from a new or unknown folder and needs to be configured." +msgstr "%s est lancé depuis un nouveau dossier et nécessite d'être configuré." + +#: pcsx2/gui/Dialogs/StuckThreadDialog.cpp:28 +msgid "PCSX2 Thread is not responding" +msgstr "Le programme PCSX2 ne répond pas" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:36 +msgid "Config Overrides Warning" +msgstr "Attention ! Configuration écrasée !" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:56 +msgid "Components Overrides Warning" +msgstr "Attention ! Composants remplacés !" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:147 +msgid "Preset:" +msgstr "Préréglage :" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:228 +#, c-format +msgid "Emulation Settings - %s" +msgstr "Paramètres d'émulation - %s" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:237 +msgid "EE/IOP" +msgstr "EE/IOP" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:238 +msgid "VUs" +msgstr "VUs" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:239 +msgid "GS" +msgstr "GS" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:240 +msgid "GS Window" +msgstr "Mode fenêtré (GS)" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:241 +msgid "Speedhacks" +msgstr "Speedhacks" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:242 +msgid "Game Fixes" +msgstr "Patchs" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:253 +#, c-format +msgid "Components Selectors - %s" +msgstr "Gestionnaire de composants - %s" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:260 +msgid "Plugins" +msgstr "Plugins" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:261 +msgid "BIOS" +msgstr "BIOS" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:262 +msgid "Folders" +msgstr "Dossiers" + +#: pcsx2/gui/Dialogs/SysConfigDialog.cpp:273 +#, c-format +msgid "Appearance/Themes - %s" +msgstr "Apparence / Thèmes - %s" + +#: pcsx2/gui/ExecutorThread.cpp:40 +msgid "Logs events as they are passed to the PS2 virtual machine." +msgstr "" +"Enregistre les évènements comme s'ils se déroulaient sur une vraie PS2." + +#: pcsx2/gui/ExecutorThread.cpp:430 +msgid "Press Cancel to attempt to cancel the action." +msgstr "Cliquez sur Annuler pour essayer d'interrompre l'opération en cours." + +#: pcsx2/gui/ExecutorThread.cpp:431 +#, c-format +msgid "Press Terminate to kill %s immediately." +msgstr "Appuyez sur Terminer pour mettre immédiatement fin à %s." + +#: pcsx2/gui/ExecutorThread.cpp:434 +msgid "Terminate App" +msgstr "Terminer l'application" + +#: pcsx2/gui/FrameForGS.cpp:384 +msgid "GS Output is Disabled!" +msgstr "La sortie GS est désactivée !" + +#: pcsx2/gui/GlobalCommands.cpp:387 pcsx2/gui/MainFrame.cpp:414 +msgid "Save state" +msgstr "Sauvegarder" + +#: pcsx2/gui/GlobalCommands.cpp:388 +msgid "Saves the virtual machine state to the current slot." +msgstr "" +"Sauvegarder les paramètres de la machine virtuelle vers l'emplacement actuel." + +#: pcsx2/gui/GlobalCommands.cpp:393 pcsx2/gui/MainFrame.cpp:413 +msgid "Load state" +msgstr "Charger" + +#: pcsx2/gui/GlobalCommands.cpp:394 +msgid "Loads a virtual machine state from the current slot." +msgstr "" +"Charger les paramètres de la machine virtuelle vers l'emplacement actuel." + +#: pcsx2/gui/GlobalCommands.cpp:399 +msgid "Load State Backup" +msgstr "Charger le backup." + +#: pcsx2/gui/GlobalCommands.cpp:400 +msgid "Loads virtual machine state backup for current slot." +msgstr "Charger le backup de la machine vituelle sur l'emplacement actuel." + +#: pcsx2/gui/GlobalCommands.cpp:405 +msgid "Cycle to next slot" +msgstr "Passer à l'emplacement suivant" + +#: pcsx2/gui/GlobalCommands.cpp:406 +msgid "Cycles the current save slot in +1 fashion!" +msgstr "On passe au slot suivant !" + +#: pcsx2/gui/GlobalCommands.cpp:411 +msgid "Cycle to prev slot" +msgstr "Passer à l'emplacement précédent" + +#: pcsx2/gui/GlobalCommands.cpp:412 +msgid "Cycles the current save slot in -1 fashion!" +msgstr "On passe au slot précédent !" + +#: pcsx2/gui/IsoDropTarget.cpp:57 +msgid "Drag and Drop Error" +msgstr "Erreur du glisser-déposer !" + +#: pcsx2/gui/IsoDropTarget.cpp:58 +#, c-format +msgid "" +"It is an error to drop multiple files onto a %s window. One at a time " +"please, thank you." +msgstr "" +"Vous ne pouvez pas glisser plusieurs fichiers à la fois vers une fenêtre %s. " +"Un seul à la fois, merci." + +#: pcsx2/gui/IsoDropTarget.cpp:89 pcsx2/gui/MainMenuClicks.cpp:342 +msgid "Confirm PS2 Reset" +msgstr "Confirmer la réinitialisation de la PS2" + +#: pcsx2/gui/IsoDropTarget.cpp:91 +#, c-format +msgid "" +"You have dropped the following ELF binary into %s:\n" +"\n" +msgstr "" +"Vous avez déposé le fichier ELF dans %s:\n" +"\n" + +#: pcsx2/gui/IsoDropTarget.cpp:135 +#, c-format +msgid "You have dropped the following ISO image into %s:" +msgstr "Vous avez déposé l'image ISO dans %s :" + +#: pcsx2/gui/MainFrame.cpp:38 +#, c-format +msgid "Slot %d" +msgstr "Emplacement %d" + +#: pcsx2/gui/MainFrame.cpp:44 pcsx2/gui/Saveslots.cpp:150 +msgid "Backup" +msgstr "Backup" + +#: pcsx2/gui/MainFrame.cpp:324 +msgid "Show Console" +msgstr "Afficher la console" + +#: pcsx2/gui/MainFrame.cpp:325 +msgid "Console to Stdio" +msgstr "Console vers Stdio" + +#: pcsx2/gui/MainFrame.cpp:338 +msgid "&System" +msgstr "&Système" + +#: pcsx2/gui/MainFrame.cpp:339 +msgid "CD&VD" +msgstr "CD/DVD" + +#: pcsx2/gui/MainFrame.cpp:340 +msgid "&Config" +msgstr "&Configuration" + +#: pcsx2/gui/MainFrame.cpp:341 +msgid "&Misc" +msgstr "&Autres" + +#: pcsx2/gui/MainFrame.cpp:343 +msgid "&Debug" +msgstr "&Debogueur" + +#: pcsx2/gui/MainFrame.cpp:355 +#, c-format +msgid "%s %d.%d.%d.%d%s (svn) %s" +msgstr "%s %d.%d.%d.%d%s (svn) %s" + +#: pcsx2/gui/MainFrame.cpp:361 +#, c-format +msgid "%s %d.%d.%d %s" +msgstr "%s %d.%d.%d %s" + +#: pcsx2/gui/MainFrame.cpp:362 +msgid "(modded)" +msgstr "(modded)" + +#: pcsx2/gui/MainFrame.cpp:399 pcsx2/gui/MainFrame.cpp:401 +#: pcsx2/gui/MainFrame.cpp:407 +msgid "Initializing..." +msgstr "Initialisation en cours..." + +#: pcsx2/gui/MainFrame.cpp:403 +msgid "Run ELF..." +msgstr "Démarrage du ELF..." + +#: pcsx2/gui/MainFrame.cpp:404 +msgid "For running raw PS2 binaries directly" +msgstr "Pour lancer directement des fichiers exécutables binaires." + +#: pcsx2/gui/MainFrame.cpp:416 +msgid "Backup before save" +msgstr "Faire un backup avant de sauvegarder" + +#: pcsx2/gui/MainFrame.cpp:421 +msgid "Automatic Gamefixes" +msgstr "Patchs automatiques" + +#: pcsx2/gui/MainFrame.cpp:422 +msgid "Automatically applies needed Gamefixes to known problematic games" +msgstr "Applique automatiquement les patchs associés à certains jeux." + +#: pcsx2/gui/MainFrame.cpp:424 +msgid "Enable Cheats" +msgstr "Activer les codes de triche" + +#: pcsx2/gui/MainFrame.cpp:427 +msgid "Enable Host Filesystem" +msgstr "Activer le Host Filesystem" + +#: pcsx2/gui/MainFrame.cpp:432 +msgid "Shutdown" +msgstr "Éteindre le jeu" + +#: pcsx2/gui/MainFrame.cpp:433 +msgid "Wipes all internal VM states and shuts down plugins." +msgstr "Coupe toutes les opérations en cours et réinitialise les plugins." + +#: pcsx2/gui/MainFrame.cpp:435 +msgid "Exit" +msgstr "Quitter" + +#: pcsx2/gui/MainFrame.cpp:436 +#, c-format +msgid "Closing %s may be hazardous to your health" +msgstr "Fermer %s est dangereux pour la santé !" + +#: pcsx2/gui/MainFrame.cpp:443 +msgid "Iso Selector" +msgstr "Choisir un ISO" + +#: pcsx2/gui/MainFrame.cpp:444 +msgid "Plugin Menu" +msgstr "Gestionnaire de plugins" + +#: pcsx2/gui/MainFrame.cpp:447 +msgid "Iso" +msgstr "ISO" + +#: pcsx2/gui/MainFrame.cpp:447 +msgid "Makes the specified ISO image the CDVD source." +msgstr "Utilise l'image ISO choisie comme un disque PS2." + +#: pcsx2/gui/MainFrame.cpp:448 +msgid "Plugin" +msgstr "Plugin" + +#: pcsx2/gui/MainFrame.cpp:448 +msgid "Uses an external plugin as the CDVD source." +msgstr "Utilise un plugin externe en tant que CDVD-source." + +#: pcsx2/gui/MainFrame.cpp:449 +msgid "No disc" +msgstr "Pas de disque" + +#: pcsx2/gui/MainFrame.cpp:449 +msgid "Use this to boot into your virtual PS2's BIOS configuration." +msgstr "Permet la configuration du BIOS de votre PS2 virtuelle." + +#: pcsx2/gui/MainFrame.cpp:457 +msgid "Emulation &Settings" +msgstr "Paramètres &d'émulation" + +#: pcsx2/gui/MainFrame.cpp:458 +msgid "&Memory cards" +msgstr "&Cartes mémoire" + +#: pcsx2/gui/MainFrame.cpp:459 +msgid "&Plugin/BIOS Selector" +msgstr "&Choix des Plugins/BIOS" + +#: pcsx2/gui/MainFrame.cpp:460 pcsx2/gui/Panels/GameDatabasePanel.cpp:346 +msgid "Game Database Editor" +msgstr "Editeur de base de données" + +#: pcsx2/gui/MainFrame.cpp:466 +msgid "&Video (GS)" +msgstr "&Vidéo (GS)" + +#: pcsx2/gui/MainFrame.cpp:467 +msgid "&Audio (SPU2)" +msgstr "&Son (SPU2)" + +#: pcsx2/gui/MainFrame.cpp:468 +msgid "&Controllers (PAD)" +msgstr "&Contrôleurs (PAD)" + +#: pcsx2/gui/MainFrame.cpp:469 +msgid "Dev9" +msgstr "Dev9" + +#: pcsx2/gui/MainFrame.cpp:470 +msgid "USB" +msgstr "USB" + +#: pcsx2/gui/MainFrame.cpp:471 +msgid "Firewire" +msgstr "Sans-fil" + +#: pcsx2/gui/MainFrame.cpp:477 +msgid "Multitap 1" +msgstr "Multitap 1" + +#: pcsx2/gui/MainFrame.cpp:478 +msgid "Multitap 2" +msgstr "Multitap 2" + +#: pcsx2/gui/MainFrame.cpp:481 +msgid "Clear all settings..." +msgstr "Effacer tous les paramètres..." + +#: pcsx2/gui/MainFrame.cpp:482 +#, c-format +msgid "Clears all %s settings and re-runs the startup wizard." +msgstr "" +"Efface tous les paramètres de %s et relance l'assistant de première " +"configuration." + +#: pcsx2/gui/MainFrame.cpp:504 +msgid "About..." +msgstr "À propos de..." + +#: pcsx2/gui/MainFrame.cpp:508 +msgid "Logging..." +msgstr "Connexion en cours..." + +#: pcsx2/gui/MainFrame.cpp:585 +msgid "Pause" +msgstr "Pause" + +#: pcsx2/gui/MainFrame.cpp:586 +msgid "Safely pauses emulation and preserves the PS2 state." +msgstr "Met l'émulation en pause et préserve son bon fonctionnement." + +#: pcsx2/gui/MainFrame.cpp:593 +msgid "Resume" +msgstr "Reprendre le jeu" + +#: pcsx2/gui/MainFrame.cpp:594 +msgid "Resumes the suspended emulation state." +msgstr "Relance l'émulation là où elle s'était arrêtée." + +#: pcsx2/gui/MainFrame.cpp:598 +msgid "Pause/Resume" +msgstr "Pause / Reprendre" + +#: pcsx2/gui/MainFrame.cpp:599 +msgid "No emulation state is active; cannot suspend or resume." +msgstr "" +"Aucune émulation en cours : impossible d'interrompre ou de reprendre " +"l'activité." + +#: pcsx2/gui/MainFrame.cpp:608 +msgid "Restart" +msgstr "Redémarrer" + +#: pcsx2/gui/MainFrame.cpp:609 +msgid "Simulates hardware reset of the PS2 virtual machine." +msgstr "Simule une réinitilisation de la PS2 virtuelle." + +#: pcsx2/gui/MainFrame.cpp:614 +msgid "No emulation state is active; boot something first." +msgstr "Pas d'émulation en cours : lancez quelque chose, d'abord !" + +#: pcsx2/gui/MainFrame.cpp:622 +msgid "Reboot CDVD (full)" +msgstr "Relancer le CDVD (complet)" + +#: pcsx2/gui/MainFrame.cpp:623 +msgid "Hard reset of the active VM." +msgstr "Redémarrage intégral du système d'émulation." + +#: pcsx2/gui/MainFrame.cpp:627 +msgid "Boot CDVD (full)" +msgstr "Démarrer le CDVD (complet)" + +#: pcsx2/gui/MainFrame.cpp:628 +msgid "Boot the VM using the current DVD or Iso source media" +msgstr "Démarre le système à partir du DVD ou de l'ISO source." + +#: pcsx2/gui/MainFrame.cpp:636 +msgid "Reboot CDVD (fast)" +msgstr "Relancer le CDVD (rapide)" + +#: pcsx2/gui/MainFrame.cpp:637 +msgid "Reboot using fast BOOT (skips splash screens)" +msgstr "Redémarrage rapide du système d'émulation (saute les logos PS2/Sony)." + +#: pcsx2/gui/MainFrame.cpp:641 +msgid "Boot CDVD (fast)" +msgstr "Démarrer le CDVD (rapide)" + +#: pcsx2/gui/MainFrame.cpp:642 +msgid "Use fast boot to skip PS2 startup and splash screens" +msgstr "Démarre le système en sautant les logos PS2/Sony." + +#: pcsx2/gui/MainFrame.cpp:703 pcsx2/gui/MainFrame.cpp:738 +msgid "No plugin loaded" +msgstr "Aucun plugin chargé" + +#: pcsx2/gui/MainFrame.cpp:708 +msgid "Core GS Settings..." +msgstr "Paramètres du Core GS..." + +#: pcsx2/gui/MainFrame.cpp:709 +msgid "" +"Modify hardware emulation settings regulated by the PCSX2 core virtual " +"machine." +msgstr "Modifie les paramètres d'émulation hardware gérés par PCSX2." + +#: pcsx2/gui/MainFrame.cpp:711 +msgid "Window Settings..." +msgstr "Paramètres du mode fenêtré..." + +#: pcsx2/gui/MainFrame.cpp:712 +msgid "Modify window and appearance options, including aspect ratio." +msgstr "Modifie la fenêtre et l'apparence, notamment l'aspect ratio." + +#: pcsx2/gui/MainFrame.cpp:719 +msgid "Plugin Settings..." +msgstr "Paramètres du plugin..." + +#: pcsx2/gui/MainFrame.cpp:720 +#, c-format +msgid "Opens the %s plugin's advanced settings dialog." +msgstr "Ouvre la fenêtre de configuration avancée du plugin %s." + +#: pcsx2/gui/MainMenuClicks.cpp:112 +msgid "Reset all settings?" +msgstr "Réinitialiser tous les paramètres ?" + +#: pcsx2/gui/MainMenuClicks.cpp:140 +msgid "Confirm ISO image change" +msgstr "Confirmer le changement d'image ISO" + +#: pcsx2/gui/MainMenuClicks.cpp:146 +msgid "Do you want to swap discs or boot the new image (via system reset)?" +msgstr "" +"Voulez-vous changer de disque ou lancer une nouvelle image-disque " +"(réinitilisation du système) ?" + +#: pcsx2/gui/MainMenuClicks.cpp:148 pcsx2/gui/MainMenuClicks.cpp:194 +msgid "Swap Disc" +msgstr "Changer de disque" + +#: pcsx2/gui/MainMenuClicks.cpp:184 +msgid "Confirm CDVD source change" +msgstr "Confirmer le changement de CDVD" + +#: pcsx2/gui/MainMenuClicks.cpp:187 +#, c-format +msgid "You've selected to switch the CDVD source from %s to %s." +msgstr "Vous avez choisi de changer le CDVD %s pour %s." + +#: pcsx2/gui/MainMenuClicks.cpp:191 +msgid "Do you want to swap discs or boot the new image (system reset)?" +msgstr "" +"Voulez-vous changer de disque ou démarrer une nouvelle image-disque " +"(réinitilisation du système) ?" + +#: pcsx2/gui/MainMenuClicks.cpp:261 +#, c-format +msgid "All Supported (%s)" +msgstr "Tous les fichiers supportés (%s)" + +#: pcsx2/gui/MainMenuClicks.cpp:264 +#, c-format +msgid "Disc Images (%s)" +msgstr "Images disque (%s)" + +#: pcsx2/gui/MainMenuClicks.cpp:267 +#, c-format +msgid "Blockdumps (%s)" +msgstr "Blockdumps (%s)" + +#: pcsx2/gui/MainMenuClicks.cpp:270 pcsx2/gui/MainMenuClicks.cpp:291 +msgid "All Files (*.*)" +msgstr "Tous les fichiers (*.*)" + +#: pcsx2/gui/MainMenuClicks.cpp:273 +msgid "Select CDVD source iso..." +msgstr "Choisir un ISO..." + +#: pcsx2/gui/MainMenuClicks.cpp:290 +msgid "Select ELF file..." +msgstr "Choisir un fichier ELF..." + +#: pcsx2/gui/MainMenuClicks.cpp:316 +msgid "ISO file not found!" +msgstr "Fichier ISO introuvable !" + +#: pcsx2/gui/MainMenuClicks.cpp:318 +msgid "An error occurred while trying to open the file:" +msgstr "Une erreur s'est produite alors que le fichier tentait d'être ouvert :" + +#: pcsx2/gui/MainMenuClicks.cpp:319 +msgid "" +"Error: The configured ISO file does not exist. Click OK to select a new ISO " +"source for CDVD." +msgstr "" +"Erreur ! Le fichier ISO configuré n'existe pas. Cliquez sur OK pour choisir " +"un autre ISO." + +#: pcsx2/gui/MainMenuClicks.cpp:390 +msgid "" +"You have selected the following ISO image into PCSX2:\n" +"\n" +msgstr "" +"Vous avez choisi l'image ISO suivante : \n" +"\n" + +#: pcsx2/gui/MemoryCardFile.cpp:183 +#, c-format +msgid "" +"Could not create a memory card: \n" +"\n" +"%s\n" +"\n" +msgstr "" +"Impossible de créer une carte mémoire : \n" +"\n" +"%s\n" +"\n" + +#: pcsx2/gui/MemoryCardFile.cpp:201 +#, c-format +msgid "" +"Access denied to memory card: \n" +"\n" +"%s\n" +"\n" +msgstr "" +"Accès à la carte mémoire refusé : \n" +"\n" +"%s\n" +"\n" + +#: pcsx2/gui/MemoryCardFile.cpp:525 +msgid "File name empty or too short" +msgstr "Nom du fichier absent ou trop court" + +#: pcsx2/gui/MemoryCardFile.cpp:530 +msgid "File name outside of required directory" +msgstr "Nom du fichier extérieur au dossier" + +#: pcsx2/gui/MemoryCardFile.cpp:536 +msgid "File name already exists" +msgstr "Nom du fichier déjà existant" + +#: pcsx2/gui/MemoryCardFile.cpp:543 +msgid "The Operating-System prevents this file from being created" +msgstr "Votre système empêche la création du fichier" + +#: pcsx2/gui/Panels/BaseApplicableConfigPanel.cpp:103 +msgid "Cannot apply settings..." +msgstr "Impossible d'appliquer les paramètres..." + +#: pcsx2/gui/Panels/BiosSelectorPanel.cpp:103 +msgid "BIOS Search Path:" +msgstr "Chemin du BIOS :" + +#: pcsx2/gui/Panels/BiosSelectorPanel.cpp:104 +msgid "Select folder with PS2 BIOS roms" +msgstr "Choisir le fichier où se trouvent les BIOS PS2" + +#: pcsx2/gui/Panels/BiosSelectorPanel.cpp:111 +msgid "" +"Click the Browse button to select a different folder where PCSX2 will look " +"for PS2 BIOS roms." +msgstr "" +"Cliquez sur le bouton Parcourir pour sélectionner un dossier différent." + +#: pcsx2/gui/Panels/BiosSelectorPanel.cpp:113 +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:156 +#: pcsx2/gui/Panels/ThemeSelectorPanel.cpp:47 +msgid "Refresh list" +msgstr "Rafraîchir la liste" + +#: pcsx2/gui/Panels/BiosSelectorPanel.cpp:115 +msgid "Select a BIOS rom:" +msgstr "Sélectionner un BIOS :" + +#: pcsx2/gui/Panels/CpuPanel.cpp:24 +msgid "Round Mode" +msgstr "Round Mode" + +#: pcsx2/gui/Panels/CpuPanel.cpp:25 +msgid "Clamping Mode" +msgstr "Clamping Mode" + +#: pcsx2/gui/Panels/CpuPanel.cpp:29 +msgid "Nearest" +msgstr "Réaliste" + +#: pcsx2/gui/Panels/CpuPanel.cpp:30 +msgid "Negative" +msgstr "Négatif" + +#: pcsx2/gui/Panels/CpuPanel.cpp:31 +msgid "Positive" +msgstr "Positif" + +#: pcsx2/gui/Panels/CpuPanel.cpp:32 +msgid "Chop / Zero" +msgstr "Chop / Zéro" + +#: pcsx2/gui/Panels/CpuPanel.cpp:37 +msgid "None" +msgstr "Aucun" + +#: pcsx2/gui/Panels/CpuPanel.cpp:85 +msgid "EE/FPU Advanced Recompiler Options" +msgstr "Options EE/FPU Advanced Recompiler" + +#: pcsx2/gui/Panels/CpuPanel.cpp:87 pcsx2/gui/Panels/CpuPanel.cpp:102 +msgid "Extra + Preserve Sign" +msgstr "Extra + Preserve Sign" + +#: pcsx2/gui/Panels/CpuPanel.cpp:88 +msgid "Full" +msgstr "Complet" + +#: pcsx2/gui/Panels/CpuPanel.cpp:99 +msgid "VU0 / VU1 Advanced Recompiler Options" +msgstr "Options VU0 / VU1 Advanced Recompiler" + +#: pcsx2/gui/Panels/CpuPanel.cpp:101 +msgid "Extra" +msgstr "Extra" + +#: pcsx2/gui/Panels/CpuPanel.cpp:117 pcsx2/gui/Panels/CpuPanel.cpp:126 +#: pcsx2/gui/Panels/CpuPanel.cpp:184 +msgid "Interpreter" +msgstr "Interpreter" + +#: pcsx2/gui/Panels/CpuPanel.cpp:118 +msgid "Quite possibly the slowest thing in the universe." +msgstr "Peut-être la chose la plus lente de tout l'univers." + +#: pcsx2/gui/Panels/CpuPanel.cpp:120 pcsx2/gui/Panels/CpuPanel.cpp:129 +msgid "Recompiler" +msgstr "Recompiler" + +#: pcsx2/gui/Panels/CpuPanel.cpp:121 +msgid "" +"Performs just-in-time binary translation of 64-bit MIPS-IV machine code to " +"x86." +msgstr "" +"Réalise une traduction en temps réel d'un code 64-bit MPIS-IV vers un x86." + +#: pcsx2/gui/Panels/CpuPanel.cpp:127 +msgid "Pretty slow; provided for diagnostic purposes only." +msgstr "Relativement lent : à utiliser uniquement à des fins de diagnostique." + +#: pcsx2/gui/Panels/CpuPanel.cpp:130 +msgid "" +"Performs just-in-time binary translation of 32-bit MIPS-I machine code to " +"x86." +msgstr "" +"Réalise une traduction en temps réel d'un code 32-bit MIPS-I vers un x86." + +#: pcsx2/gui/Panels/CpuPanel.cpp:154 +msgid "Enable EE Cache (Slower)" +msgstr "Activer l'EE Cache (plus lent)" + +#: pcsx2/gui/Panels/CpuPanel.cpp:154 +msgid "Interpreter only; provided for diagnostic" +msgstr "Seulement pour l'usage de l'interpreter, à des fins de diagnostique" + +#: pcsx2/gui/Panels/CpuPanel.cpp:170 pcsx2/gui/Panels/CpuPanel.cpp:223 +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:110 +msgid "Restore Defaults" +msgstr "Réinitialiser les paramètres" + +#: pcsx2/gui/Panels/CpuPanel.cpp:185 +msgid "" +"Vector Unit Interpreter. Slow and not very compatible. Only use for " +"diagnostics." +msgstr "" +"Vector Unit Interpreter. Lent et rarement compatible. A n'utiliser que pour " +"des diagnostiques." + +#: pcsx2/gui/Panels/CpuPanel.cpp:187 +msgid "microVU Recompiler" +msgstr "microVU Recompiler" + +#: pcsx2/gui/Panels/CpuPanel.cpp:188 +msgid "" +"New Vector Unit recompiler with much improved compatibility. Recommended." +msgstr "" +"Nouveau Vector Unit recompiler qui bénéficie d'une compatibilité améliorée. " +"Recommandé." + +#: pcsx2/gui/Panels/CpuPanel.cpp:190 +msgid "superVU Recompiler [legacy]" +msgstr "superVU Recompiler" + +#: pcsx2/gui/Panels/CpuPanel.cpp:191 +msgid "" +"Useful for diagnosing bugs or clamping issues in the new mVU recompiler." +msgstr "" +"Utile pour diagnostiquer les bugs ou les plantages du nouveau mVU recompiler." + +#: pcsx2/gui/Panels/DirPickerPanel.cpp:64 +msgid "Path does not exist" +msgstr "Le chemin d'accès n'existe pas" + +#: pcsx2/gui/Panels/DirPickerPanel.cpp:156 +msgid "Use default setting" +msgstr "Utiliser les paramètres par défaut" + +#: pcsx2/gui/Panels/DirPickerPanel.cpp:176 +msgid "Open in Explorer" +msgstr "Afficher dans l'explorateur" + +#: pcsx2/gui/Panels/DirPickerPanel.cpp:177 +msgid "Open an explorer window to this folder." +msgstr "Ouvrir ce dossier dans l'explorateur Windows." + +#: pcsx2/gui/Panels/DirPickerPanel.cpp:268 +msgid "Create folder?" +msgstr "Créer un dossier ?" + +#: pcsx2/gui/Panels/DirPickerPanel.cpp:269 +#, c-format +msgid "A configured folder does not exist. Should %s try to create it?" +msgstr "" +"Aucun dossier correspondant trouvé. Voulez-vous que %s essaye d'en créer un ?" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:30 +msgid "Fit to Window/Screen" +msgstr "Window/Screen" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:31 +msgid "Standard (4:3)" +msgstr "Format classique (4/3)" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:32 +msgid "Widescreen (16:9)" +msgstr "Format large (16/9)" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:46 +msgid "Disable window resize border" +msgstr "Désactiver la bordure de redimensionnement" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:47 +msgid "Always hide mouse cursor" +msgstr "Toujours cacher le curseur de la souris" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:48 +msgid "Hide window when paused" +msgstr "Cacher la fenêtre lorsque le jeu est en pause" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:49 +msgid "Default to fullscreen mode on open" +msgstr "Lancer le plein-écran par défaut" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:50 +msgid "Wait for Vsync on refresh" +msgstr "Attendre le rafraîchissement Vsync (synchronisation verticale)" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:51 +msgid "Dynamically toggle Vsync depending on frame rate (read tooltip!)" +msgstr "Bascule Vsync dynamique basée sur la frame rate (lisez le tooltip !)" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:52 +msgid "Double-click toggles fullscreen mode" +msgstr "Un double-clic pemet de basculer vers le mode plein-écran" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:110 +msgid "Aspect Ratio:" +msgstr "Résolution d'affichage :" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:112 +msgid "Custom Window Size:" +msgstr "Taille de la fenêtre :" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:115 +msgid "Zoom:" +msgstr "Zoom :" + +#: pcsx2/gui/Panels/GSWindowPanel.cpp:196 +msgid "" +"Invalid window dimensions specified: Size cannot contain non-numeric digits! " +">_<" +msgstr "" +"Dimensions de la fenêtre invalides : une résolution ne peut pas contenir " +"autre chose que des chiffres, banane !" + +#: pcsx2/gui/Panels/GameDatabasePanel.cpp:334 +msgid "Search" +msgstr "Rechercher" + +#: pcsx2/gui/Panels/GameDatabasePanel.cpp:368 +#: pcsx2/gui/Panels/GameFixesPanel.cpp:25 +msgid "Gamefixes" +msgstr "Patchs" + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:38 +msgid "VU Add Hack - Fixes Tri-Ace games boot crash." +msgstr "VU Add Hack - Corrige le cash au lancement d'un jeu Tri-Ace." + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:39 +msgid "" +"Games that need this hack to boot:\n" +" * Star Ocean 3\n" +" * Radiata Stories\n" +" * Valkyrie Profile 2" +msgstr "" +"Les jeux suivants nécessitent l'utilisation du hack :\n" +"* Star Ocean 3\n" +"* Radiata Stories\n" +"* Valkyrie Profile 2" + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:42 +msgid "VU Clip Flag Hack - For Persona games (SuperVU recompiler only!)" +msgstr "" +"VU Clip Flag Hack - Pour tous les jeux Persona (seulement avec le SuperVU " +"recompiler !)" + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:46 +msgid "FPU Compare Hack - For Digimon Rumble Arena 2." +msgstr "FPU Compare Hack - Pour le jeu Digimon Rumble Arena 2." + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:50 +msgid "FPU Multiply Hack - For Tales of Destiny." +msgstr "FPU Multiply Hack - Pour le jeu Tales of Destiny." + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:54 +msgid "FPU Negative Div Hack - For Gundam games." +msgstr "FPU Negative Div Hack - Pour tous les jeux de la série Gundam." + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:58 +msgid "VU XGkick Hack - For Erementar Gerad." +msgstr "VU XGkick Hack - Pour le jeu Erementar Gerad." + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:62 +msgid "FFX videos fix - Fixes bad graphics overlay in FFX videos." +msgstr "" +"FFX video fix - Corrige les bugs graphiques liés à certaines vidéos du jeu " +"FFX." + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:66 +msgid "EE timing hack - Multi purpose hack. Try if all else fails." +msgstr "" +"EE timing hack - Un peu de tout. Essayez-le si aucun autre hack ne corrige " +"votre problème." + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:75 +msgid "" +"Skip MPEG hack - Skips videos/FMVs in games to avoid game hanging/freezes." +msgstr "" +"Skip MPEG hack - Saute les vidéos/cinématiques des jeux afin d'éviter qu'ils " +"ne plantent." + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:79 +msgid "OPH Flag hack - Try if your game freezes showing the same frame." +msgstr "" +"OPH Flag hack - Essayez-le si votre jeu bloque toujours au même endroit." + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:88 +msgid "Ignore DMAC writes when it is busy." +msgstr "Ignorer l'écriture DMAC lorsqu'elle est occupée." + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:95 +msgid "Simulate VIF1 FIFO read ahead. Fixes slow loading games." +msgstr "Simuler la lecture VIF1 FIFO (permet d'accélérer les chargements)." + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:103 +msgid "Delay VIF1 Stalls (VIF1 FIFO) - For SOCOM 2 HUD." +msgstr "Retarder VIF1 FIFO - Utile au HUD de SOCOM2." + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:107 +msgid "Ignore Bus Direction on Path3 Transfer - Used for Hotwheels" +msgstr "" +"Ignorer le Bus Direction sur le Path3 Transfer - Utile pour le jeu Hot Wheels" + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:118 +msgid "Enable manual game fixes [Not recommended]" +msgstr "Activer les patchs manuellement [Non-recommandé]" + +#: pcsx2/gui/Panels/GameFixesPanel.cpp:127 +msgid "" +"The safest way to make sure that all game fixes are completely disabled." +msgstr "" +"La meilleure méthode pour s'assurer que tous les patchs ont été désactivés." + +#: pcsx2/gui/Panels/LogOptionsPanels.cpp:249 +msgid "Enable Trace Logging" +msgstr "Activer les rapports automatiques" + +#: pcsx2/gui/Panels/LogOptionsPanels.cpp:250 +msgid "" +"Trace logs are all written to emulog.txt. Toggle trace logging at any time " +"using F10." +msgstr "" +"Les rapports automatiques seront enregistrés dans le fichier emulog.txt. " +"Vous pouvez les consulter à tout moment en pressant la touche F10." + +#: pcsx2/gui/Panels/LogOptionsPanels.cpp:251 +msgid "" +"Warning: Enabling trace logs is typically very slow, and is a leading cause " +"of 'What happened to my FPS?' problems. :)" +msgstr "" +"Attention ! Activer les rapports automatiques ralentira beaucoup l'émulation " +"et reste l'une des principales réponses à la question : \"Où sont passés mes " +"FPS !?\" :p" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:151 +msgid "Select folder with PS2 memory cards" +msgstr "Choisir le dossier des cartes mémoire PS2" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:448 +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:533 +msgid "Eject" +msgstr "Éjecter" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:449 +msgid "Duplicate ..." +msgstr "Dupliquer ..." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:450 +msgid "Rename ..." +msgstr "Renommer ..." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:451 +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:515 +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:542 +msgid "Create ..." +msgstr "Créer ..." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:463 +msgid "Card: " +msgstr "Carte :" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:516 +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:549 +msgid "Create a new memory card." +msgstr "Créer une nouvelle carte mémoire." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:529 +msgid "Rename this memory card ..." +msgstr "Renommer cette carte mémoire ..." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:533 +msgid "Insert ..." +msgstr "Insérer ..." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:534 +msgid "Eject the card from this port" +msgstr "Éjecter la carte de son lecteur." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:534 +msgid "Insert this card to a port ..." +msgstr "Insérer la carte dans un lecteur ..." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:538 +msgid "Create a duplicate of this memory card ..." +msgstr "Dupliquer le contenu de cette carte mémoire ..." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:542 +msgid "Delete" +msgstr "Effacer" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:545 +msgid "Permanently delete this memory card from disk (all contents are lost)" +msgstr "" +"Effacer la carte mémoire du disque (toutes les données seront " +"irrémédiablement perdues)." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:547 +msgid "Create a new memory card and assign it to this Port." +msgstr "Créer une nouvelle carte mémoire et l'assigner à ce lecteur." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:726 +msgid "Delete memory file?" +msgstr "Effacer le fichier mémoire ?" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:750 +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:762 +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:769 +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:783 +msgid "Duplicate memory card" +msgstr "Dupliquer la carte mémoire" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:750 +msgid "Failed: Can only duplicate an existing card." +msgstr "Échec : seule une carte déjà existante peut être dupliquée." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:769 +msgid "" +"Select a name for the duplicate\n" +"( '.ps2' will be added automatically)" +msgstr "" +"Choisir un nom pour la copie \n" +"(le format '.ps2' sera automatiquement ajouté)" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:782 +#, c-format +msgid "Failed: %s" +msgstr "Échec : %s" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:808 +msgid "Copy failed!" +msgstr "La copie a échoué ! (bad trip)" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:816 +#, c-format +msgid "Memory card '%s' duplicated to '%s'." +msgstr "Carte mémoire '%s' dupliquée sous le nom '%s'." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:820 +msgid "Success" +msgstr "Opération réalisée avec succès !" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:841 +#, c-format +msgid "" +"Select a new name for the memory card '%s'\n" +"( '.ps2' will be added automatically)" +msgstr "" +"Choisissez un nouveau nom pour la carte mémoire '%s'\n" +"(le format '.ps2' sera automatiquement ajouté à sa suite)" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:844 +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:856 +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:872 +msgid "Rename memory card" +msgstr "Renommer la carte mémoire" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:872 +msgid "Error: Rename could not be completed.\n" +msgstr "Erreur : impossible à renommer.\n" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:962 +#: pcsx2/gui/Panels/MemoryCardListView.cpp:139 +#, c-format +msgid "Port-%u / Multitap-%u--Port-1" +msgstr "Port-%u / Multitap-%u--Port-1" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:963 +#: pcsx2/gui/Panels/MemoryCardListView.cpp:140 +#, c-format +msgid " Multitap-%u--Port-%u" +msgstr " Multitap-%u--Port-%u" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:988 +msgid "Empty" +msgstr "Vide" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:994 +#, c-format +msgid "Select a target port for '%s'" +msgstr "Assignez un lecteur pour '%s'" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:995 +msgid "Insert card" +msgstr "Insérer la carte" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1055 +msgid "Eject card" +msgstr "Éjecter la carte" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1055 +msgid "Insert card ..." +msgstr "Insérer la carte ..." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1056 +msgid "Duplicate card ..." +msgstr "Dupliquer la carte ..." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1057 +msgid "Rename card ..." +msgstr "Renommer la carte ..." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1058 +msgid "Delete card" +msgstr "Effacer la carte" + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1061 +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1065 +msgid "Create a new card ..." +msgstr "Créer une nouvelle carte ..." + +#: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1069 +msgid "Refresh List" +msgstr "Rafraîchir la liste" + +#: pcsx2/gui/Panels/MemoryCardListView.cpp:105 +msgid "PS2 Port" +msgstr "Port PS2" + +#: pcsx2/gui/Panels/MemoryCardListView.cpp:107 +msgid "Card (file) name" +msgstr "Nom de la carte" + +#: pcsx2/gui/Panels/MemoryCardListView.cpp:108 +msgid "Card size" +msgstr "Taille" + +#: pcsx2/gui/Panels/MemoryCardListView.cpp:109 +msgid "Formatted" +msgstr "Formatée ?" + +#: pcsx2/gui/Panels/MemoryCardListView.cpp:110 +msgid "Last Modified" +msgstr "Dernière modification" + +#: pcsx2/gui/Panels/MemoryCardListView.cpp:111 +msgid "Created on" +msgstr "Créée le" + +#: pcsx2/gui/Panels/MemoryCardListView.cpp:156 +msgid "No" +msgstr "Non" + +#: pcsx2/gui/Panels/MemoryCardListView.cpp:156 +msgid "Yes" +msgstr "Oui" + +#: pcsx2/gui/Panels/MemoryCardListView.cpp:169 +msgid "[-- Unused cards --]" +msgstr "[-- Cartes inutilisées --]" + +#: pcsx2/gui/Panels/MemoryCardListView.cpp:171 +msgid "[-- No unused cards --]" +msgstr "[-- Pas de carte inutilisée --]" + +#: pcsx2/gui/Panels/MiscPanelStuff.cpp:33 +msgid "Usermode Selection" +msgstr "Sélection du mode d'utilisateur" + +#: pcsx2/gui/Panels/MiscPanelStuff.cpp:50 +msgid "User Documents (recommended)" +msgstr "User Documents (recommandé)" + +#: pcsx2/gui/Panels/MiscPanelStuff.cpp:51 +msgid "Location: " +msgstr "Destination :" + +#: pcsx2/gui/Panels/MiscPanelStuff.cpp:55 +msgid "Custom folder:" +msgstr "Dossier :" + +#: pcsx2/gui/Panels/MiscPanelStuff.cpp:57 +msgid "" +"This setting may require administration privileges from your operating " +"system, depending on how your system is configured." +msgstr "Ce paramètre peut nécessiter les droits d'un compte administrateur." + +#: pcsx2/gui/Panels/MiscPanelStuff.cpp:66 +#, c-format +msgid "Select a document root for %s" +msgstr "Choisir la racine du document pour %s" + +#: pcsx2/gui/Panels/MiscPanelStuff.cpp:124 +msgid "Apply" +msgstr "Appliquer" + +#: pcsx2/gui/Panels/MiscPanelStuff.cpp:125 +msgid "Make this language my default right now!" +msgstr "Cette langue deviendra celle par défaut !" + +#: pcsx2/gui/Panels/PathsPanel.cpp:38 +msgid "Savestates:" +msgstr "Sauvegardes :" + +#: pcsx2/gui/Panels/PathsPanel.cpp:39 +msgid "Select folder for Savestates" +msgstr "Choisir un dossier pour les sauvegardes" + +#: pcsx2/gui/Panels/PathsPanel.cpp:48 +msgid "Snapshots:" +msgstr "Screenshots :" + +#: pcsx2/gui/Panels/PathsPanel.cpp:49 +msgid "Select a folder for Snapshots" +msgstr "Choisir un dossier pour les screenshots" + +#: pcsx2/gui/Panels/PathsPanel.cpp:58 +msgid "Logs/Dumps:" +msgstr "Rapports / Dumps :" + +#: pcsx2/gui/Panels/PathsPanel.cpp:59 +msgid "Select a folder for logs/dumps" +msgstr "Choisir un dossier pour les rapports / dumps" + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:230 +msgid "Applying settings..." +msgstr "Mise à jour des paramètres..." + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:240 +msgid "Shutdown PS2 virtual machine?" +msgstr "Éteindre la machine virtuelle PS2 ?" + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:321 +msgid "I'm givin' her all she's got, Captain!" +msgstr "\"I'm giving her all she's got, Captain!\" (cf. Star Trek)" + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:323 +msgid "Enumerating available plugins..." +msgstr "Mise à jour de la liste des plugins disponibles..." + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:356 +msgid "Plugins Search Path:" +msgstr "Chemin d'accès des plugins :" + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:357 +msgid "Select a folder with PCSX2 plugins" +msgstr "Choisir le dossier où se trouvent les plugins PCSX2" + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:370 +msgid "Configure..." +msgstr "Configurer" + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:379 +msgid "Click the Browse button to select a different folder for PCSX2 plugins." +msgstr "" +"Cliquez sur le bouton Parcourir pour choisir un dossier de plugins différent." + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:481 +#, c-format +msgid "Please select a valid plugin for the %s." +msgstr "Veuillez sélectionner un plugin valide pour le %s." + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:519 +#, c-format +msgid "" +"The selected %s plugin failed to load.\n" +"\n" +"Reason: %s\n" +"\n" +msgstr "" +"Le plugin %s sélectionné n'a pas pu être chargé.\n" +"\n" +"Explication : %s\n" +"\n" + +#: pcsx2/gui/Panels/PluginSelectorPanel.cpp:730 +msgid "Completing tasks..." +msgstr "Exécution des tâches..." + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:96 +msgid "Enable speedhacks" +msgstr "Activer les speedhacks" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:102 +msgid "" +"A safe and easy way to make sure that all speedhacks are completely disabled." +msgstr "" +"La manière la plus simple de s'assurer que les speedhacks ont été " +"complètement désactivés." + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:111 +msgid "" +"Resets all speedhack options to their defaults, which consequently turns " +"them all OFF." +msgstr "" +"Réinitialise les options des speedhacks à leurs valeurs par défaut (à noter " +"que cette opération les désactivera tous)." + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:120 +msgid "EE Cyclerate [Not Recommended]" +msgstr "EmotionEngine (EE) Cyclerate [Non recommandé]" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:141 +msgid "VU Cycle Stealing [Not Recommended]" +msgstr "VectorUnit (VU) Cycle Stealing [Non recommandé]" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:161 +msgid "microVU Hacks" +msgstr "microVU Hacks" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:163 +msgid "mVU Flag Hack" +msgstr "mVU Flag Hack" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:164 +msgid "" +"Good Speedup and High Compatibility; may cause bad graphics... [Recommended]" +msgstr "" +"Amélioration sensible des performances et compatibilité élevée, mais " +"pourrait causer quelques bugs graphiques... [Recommandé]" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:166 +msgid "MTVU (Multi-Threaded microVU1)" +msgstr "MTVU (Multi-Threaded microVU1)" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 +msgid "" +"Good Speedup and High Compatibility; may cause hanging... [Recommended if 3+ " +"cores]" +msgstr "" +"Bonnes performances et compatibilité élevée, mais pourrait occasionner des " +"\"tremblements\" à l'écran... [Recommandé pour Proc. 3/+ coeurs]" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:183 +msgid "Other Hacks" +msgstr "Autres Hacks" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:185 +msgid "Enable INTC Spin Detection" +msgstr "Active l'INTC Spin Detection" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:186 +msgid "" +"Huge speedup for some games, with almost no compatibility side effects. " +"[Recommended]" +msgstr "" +"Augmente les FPS de manière considérable sur certains jeux et n'a pas " +"d'impact sur la compatibilité générale. [Recommandé]" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:188 +msgid "Enable Wait Loop Detection" +msgstr "Activer la Wait Loop Detection" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:189 +msgid "" +"Moderate speedup for some games, with no known side effects. [Recommended]" +msgstr "" +"Amélioration modérée des performances sur certains jeux, et aucun effet " +"pervers connu. [Recommandé]" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 +msgid "Enable fast CDVD" +msgstr "Activer l'accès rapide aux CDVD" + +#: pcsx2/gui/Panels/SpeedhacksPanel.cpp:192 +msgid "Fast disc access, less loading times. [Not Recommended]" +msgstr "Réduit les temps de chargement. [Non recommandé]" + +#: pcsx2/gui/Panels/ThemeSelectorPanel.cpp:37 +msgid "Themes Search Path:" +msgstr "Chemin d'accès des thèmes :" + +#: pcsx2/gui/Panels/ThemeSelectorPanel.cpp:38 +msgid "Select folder containing PCSX2 visual themes" +msgstr "Choisir le dossier qui contient les thèmes visuels PCSX2" + +#: pcsx2/gui/Panels/ThemeSelectorPanel.cpp:45 +msgid "" +"Click the Browse button to select a different folder containing PCSX2 visual " +"themes." +msgstr "" +"Cliquez sur le bouton Parcourir pour choisir un dossier de thèmes visuels " +"PCSX2 différent." + +#: pcsx2/gui/Panels/ThemeSelectorPanel.cpp:49 +msgid "Select a visual theme:" +msgstr "Sélectionner un thème :" + +#: pcsx2/gui/Panels/VideoPanel.cpp:34 +msgid "Disable Framelimiting" +msgstr "Désactiver le Framelimiting (limite le nombre de frames)" + +#: pcsx2/gui/Panels/VideoPanel.cpp:35 +msgid "" +"Useful for running benchmarks. Toggle this option in-game by pressing F4." +msgstr "" +"Utile pour les benchmarks. On peut utiliser cette option en jeu grâce à la " +"touche F4." + +#: pcsx2/gui/Panels/VideoPanel.cpp:61 +msgid "Base Framerate Adjust:" +msgstr "Ajustement de la Framerate de base :" + +#: pcsx2/gui/Panels/VideoPanel.cpp:67 +msgid "Slow Motion Adjust:" +msgstr "Ajustement de la Slow Motion :" + +#: pcsx2/gui/Panels/VideoPanel.cpp:73 +msgid "Turbo Adjust:" +msgstr "Ajustement du Turbo :" + +#: pcsx2/gui/Panels/VideoPanel.cpp:88 +msgid "NTSC Framerate:" +msgstr "Framerate en mode NTSC :" + +#: pcsx2/gui/Panels/VideoPanel.cpp:91 pcsx2/gui/Panels/VideoPanel.cpp:97 +msgid "FPS" +msgstr "FPS (IPS)" + +#: pcsx2/gui/Panels/VideoPanel.cpp:94 +msgid "PAL Framerate:" +msgstr "Framerate en mode PAL :" + +#: pcsx2/gui/Panels/VideoPanel.cpp:166 +msgid "" +"Error while parsing either NTSC or PAL framerate settings. Settings must be " +"valid floating point numerics." +msgstr "" +"Erreur de lecture des paramètres de la framerate NTSC ou PAL : les valeurs " +"sont fausses." + +#: pcsx2/gui/Panels/VideoPanel.cpp:184 +msgid "Disabled [default]" +msgstr "Désactivé [défaut]" + +#: pcsx2/gui/Panels/VideoPanel.cpp:188 +msgid "Skip when on Turbo only (TAB to enable)" +msgstr "Activé lorsque le Turbo est actif (appuyez sur TAB)" + +#: pcsx2/gui/Panels/VideoPanel.cpp:192 +msgid "Constant skipping" +msgstr "Saut de frames permanent" + +#: pcsx2/gui/Panels/VideoPanel.cpp:194 +msgid "" +"Normal and Turbo limit rates skip frames. Slow motion mode will still " +"disable frameskipping." +msgstr "" +"Les modes Normal et Turbo permettent de sauter des frames. Le mode Slow " +"motion désactivera le saut de frames." + +#: pcsx2/gui/Panels/VideoPanel.cpp:217 +msgid "Frames to Draw" +msgstr "frames à afficher" + +#: pcsx2/gui/Panels/VideoPanel.cpp:222 +msgid "Frames to Skip" +msgstr "frames à ignorer" + +#: pcsx2/gui/Panels/VideoPanel.cpp:298 +msgid "Use Synchronized MTGS" +msgstr "Utiliser la MTGS synchonisé" + +#: pcsx2/gui/Panels/VideoPanel.cpp:299 +msgid "" +"For troubleshooting potential bugs in the MTGS only, as it is potentially " +"very slow." +msgstr "Permet d'enrayer des bugs potentiels liés au MTGS." + +#: pcsx2/gui/Panels/VideoPanel.cpp:302 +msgid "Disable all GS output" +msgstr "Désactive toute sortie GS" + +#: pcsx2/gui/Panels/VideoPanel.cpp:303 +msgid "" +"Completely disables all GS plugin activity; ideal for benchmarking EEcore " +"components." +msgstr "" +"Désactive complètement l'affichage vidéo : idéal pour un benchmark des " +"composants EEcore." + +#: pcsx2/gui/Panels/VideoPanel.cpp:320 +msgid "Frame Skipping" +msgstr "Saut de frames" + +#: pcsx2/gui/Panels/VideoPanel.cpp:323 +msgid "Framelimiter" +msgstr "Framelimiter" + +#: pcsx2/gui/SysState.cpp:283 +msgid "" +"Cannot load this savestate. The state is from an incompatible edition of " +"PCSX2 that is either newer than this version, or is no longer supported." +msgstr "" +"Impossible de charger cette sauvegarde. L'emplacement provient d'une version " +"de PCSX2 incompatible (trop ancienne, ou nouvelle)." + +#: pcsx2/gui/SysState.cpp:290 +msgid "" +"Cannot load this savestate. The state is an unsupported version, likely " +"created by a newer edition of PCSX2." +msgstr "" +"Impossible de charger cette sauvegarde. L'emplacement n'est pas supporté car " +"il a sûrement été créé à partir d'une version de PCSX2 non-gérée." + +#: pcsx2/gui/SysState.cpp:326 +msgid "There is no active virtual machine state to download or save." +msgstr "Il n'y a pas d'emplacement à télécharger ou à sauvegarder." + +#: pcsx2/gui/SysState.cpp:520 +msgid "" +"This savestate cannot be loaded because it is not a valid gzip archive. It " +"may have been created by an older unsupported version of PCSX2, or it may be " +"corrupted." +msgstr "" +"La sauvegarde ne peut pas être chargée car elle ne fait pas l'objet d'une " +"archive gzip valide. Elle a peut-être été créée à partir d'une version de " +"PCSX2 antérieure, ou bien elle est corrompue." + +#: pcsx2/gui/SysState.cpp:579 +msgid "This file is not a valid PCSX2 savestate. See the logfile for details." +msgstr "" +"Le fichier n'est pas une sauvegarde PCSX2 valide. Référez-vous aux rapports " +"pour plus de détails." + +#: pcsx2/gui/SysState.cpp:598 +msgid "" +"This savestate cannot be loaded due to missing critical components. See the " +"log file for details." +msgstr "" +"La sauvegarde n'a pas pu être chargée du fait de l'absence de composants " +"indispensables. Référez-vous aux rapports pour plus de détails." + +#: pcsx2/gui/i18n.cpp:63 +msgid " (default)" +msgstr "(défaut)" + +#: pcsx2/ps2/BiosTools.cpp:83 pcsx2/ps2/BiosTools.cpp:151 +msgid "The selected BIOS file is not a valid PS2 BIOS. Please re-configure." +msgstr "" +"Le fichier BIOS n'est pas un BIOS PS2 valide. Merci de le reconfigurer." + +#: pcsx2/ps2/BiosTools.cpp:244 +msgid "" +"The PS2 BIOS could not be loaded. The BIOS has not been configured, or the " +"configuration has been corrupted. Please re-configure." +msgstr "" +"Le BIOS PS2 n'a pas pu être chargé. Le BIOS n'a pas été configuré, ou ses " +"paramètres ne sont pas validés. Merci de le reconfigurer." + +#: pcsx2/ps2/BiosTools.cpp:251 +msgid "The configured BIOS file does not exist. Please re-configure." +msgstr "Le fichier de configuation du BIOS n'existe pas. Merci d'en créer un." + +#: pcsx2/x86/ix86-32/iR5900-32.cpp:578 +#, c-format +msgid "" +"%s Extensions not found. The R5900-32 recompiler requires a host CPU with " +"MMX, SSE, and SSE2 extensions." +msgstr "" +"%s extensions n'ont pas été trouvées. Le R5900-32 recompiler nécessite un " +"CPU qui gère les extensions MMX, SSE et SSE2." + +#: pcsx2/x86/microVU.cpp:28 +#, c-format +msgid "" +"%s Extensions not found. microVU requires a host CPU with MMX, SSE, and " +"SSE2 extensions." +msgstr "" +"%s extensions non trouvées. microVU nécessite un CPU qui gère les extensions " +"MMX, SSE et SSE2." + +#~ msgid "mVU Block Hack" +#~ msgstr "mVU Block Hack" + +#~ msgid "" +#~ "Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." +#~ msgstr "" +#~ "Amélioration sensible des performances et compatibilité élevée, mais " +#~ "pourrait causer quelques bugs graphiques, SPS, etc..." diff --git a/locales/ja_JP/pcsx2_Iconized.po b/locales/ja_JP/pcsx2_Iconized.po index 2461a90a1..a38a9a6db 100644 --- a/locales/ja_JP/pcsx2_Iconized.po +++ b/locales/ja_JP/pcsx2_Iconized.po @@ -1,21 +1,21 @@ # SOME DESCRIPTIVE TITLE. -# Copyright (C) 2011 PCSX2_Dev_Team -# This file is distributed under the same license as the PCSX2 package. +# Copyright (C) YEAR PCSX2 Dev Team +# This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2012-02-28 12:20+0100\n" -"PO-Revision-Date: 2011-04-30 10:48+0900\n" -"Last-Translator: oreore\n" -"Language-Team: \n" +"POT-Creation-Date: 2012-03-10 20:38+0100\n" +"PO-Revision-Date: 2012-03-05 08:12+0900\n" +"Last-Translator: DeltaHF\n" +"Language-Team: DeltaHF\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Poedit-KeywordsList: pxE\n" +"X-Poedit-KeywordsList: pxE;pxEt\n" "X-Poedit-SourceCharset: utf-8\n" "X-Poedit-Basepath: trunk\\\n" "X-Poedit-Language: Japanese\n" @@ -26,620 +26,521 @@ msgstr "" #: common/src/Utilities/Exceptions.cpp:254 msgid "!Notice:VirtualMemoryMap" msgstr "" -"十分な仮想メモリがありません。もしくは他のプロセスやDLLによって予約済みです。" +"仮想メモリが不足しているか、必要な仮想メモリは既に他のプロセス、サービス、DLL" +"に割り当てられています。" #: pcsx2/CDVD/CDVD.cpp:390 msgid "!Notice:PsxDisc" msgstr "" -"PCSX2 は Playstation のゲームをサポートしていません。プレイしたい場合は " -"ePSXe や PCSX などのPS1エミュレータを入手して下さい。" +"プレイステーション1のディスクはPCSX2でサポートされていません。 \n" +"ePSXeやPCSX等のPS1専用のエミュレータをお使い下さい。" #: pcsx2/System.cpp:114 msgid "!Notice:Recompiler:VirtualMemoryAlloc" msgstr "" -"リコンパイラは連続したメモリの予約に失敗しました。このエラーは仮想メモリの不" -"足か無効になっている、\n" -"別プログラムが専有中などの原因で発生します。\n" -"Hostの設定で全てのPCSX2リコンパイラのキャッシュサイズを減らすことができます。" +"このリコンパイラは内部キャッシュ用の連続メモリを確保する事ができませんでし" +"た。このエラーは仮想メモリの\n" +"リソースが不足していると発生します。スワップファイルが小さすぎるか、無効にさ" +"れている場合や他のプログラムが\n" +"メモリの多くを消費している時に発生します。ホスト設定でPCSX2のリコンパイラのデ" +"フォルトキャッシュサイズを\n" +"で小さく設定する事で問題を解決できる事があります。" #: pcsx2/System.cpp:348 msgid "!Notice:EmuCore::MemoryForVM" msgstr "" -"PCSX2はPS2仮想マシンに必要なメモリを割り当てることが出来ませんでした。\n" -"メモリを占有している他のタスクを終了してもう一度やり直してください。" +"PCSX2はPS2バーチャルマシンに必要なメモリーを割り当てる事ができませんでし" +"た。 \n" +"バックグラウンドタスクを終了させ、メモリーを解放してから再試行して下さい。" #: pcsx2/gui/AppInit.cpp:43 msgid "!Notice:Startup:NoSSE2" msgstr "" -"警告:お使いのコンピュータは多くのPCSX2リコンパイラやプラグインが必要とする" -"SSE2をサポートしていません。\n" -"設定は制限され、エミュレーションの速度が*非常に*遅くなります。" +"警告: お使いのCPUはPCSX2のリコンパイラやプラグインが必要とするSSE2を" +"サポートしていません。 \n" +"選択できるオプションが限られ、エミュレーション速度は*非常に*遅くなります。" #: pcsx2/gui/AppInit.cpp:162 msgid "!Notice:RecompilerInit:Header" -msgstr "警告: あるPS2リコンパイラが初期化が失敗で、無効にされました:" +msgstr "" +"警告: 設定されたいくつかのPS2リコンパイラが初期化に失敗し、無効にされまし" +"た。" #: pcsx2/gui/AppInit.cpp:211 msgid "!Notice:RecompilerInit:Footer" msgstr "" -"インフォ: PCSX2が動作するにはリコンパイラが必要ではありません、しかしなが" -"ら、\n" -"リコンパイラはかなりエミュレーション速度を上げます。\n" -"エラーを解決したら、上に記載されたリコンパイラ手動で再有効にしなければならな" -"いかもしれません。" +"メモ:PCSX2の実行にリコンパイラは必要ではありませんが、エミュレーション速度を" +"大幅に改善します。\n" +"エラーを解決した後に、上記リストのリコンパイラを手動で有効化しなおす必要があ" +"るかもしれません。" #: pcsx2/gui/AppMain.cpp:546 msgid "!Notice:BiosDumpRequired" msgstr "" -"PCSX2が動作するにはPS2 BIOSが必要です。 著作権法律上の理由によってあなた\n" -"自身が所有している実際のPS2ユニットからBIOSをダンプしなければなりません。\n" -"(借物ではいけません)。 ダンプするのやり方ならFAQとガイドを参照してくださ" -"い。" +"PCSX2を実行するにはPS2のBIOSが必要です。あなた自身が所有する(借物はダメです)" +"PS2の実機から \n" +"「合法的に」手に入れて下さい。詳しい吸出し方法はFAQやガイドを参照して下さい。" #: pcsx2/gui/AppMain.cpp:629 msgid "!Notice Error:Thread Deadlock Actions" msgstr "" -"「無視」スレッドが反応するまで待機する。\n" -"「キャンセル」 スレッドを取り消すのを試行する。\n" -"「終止」 すぐにPCSX2を終了します'。" +"[無視] スレッドの応答を待ちます。\n" +"[キャンセル] スレッドのキャンセルを試行します。\n" +"[終了] PCSX2をただちに終了させます。" #: pcsx2/gui/AppUserMode.cpp:57 msgid "!Notice:PortableModeRights" msgstr "" -"これらのフォルダーがもはや作成されていて、ユーザアカウントはフォルダーに書き" -"込み権限があることをチェックしてください。\n" -"あるいは、管理者権限でPCSX2を再運行してみてください。こうすればPCSX2自体に必" -"要なフォルダーを作成する権限を与えられます。\n" -"もしこのコンピュータで管理者権限を持っていないというなら、ユーザ・ドキュメン" -"ト・モードに切り替わってください。\n" -"(以下のボタンをクリックするとモードが切り替われる)" +"これらのフォルダが作成され、使用中のユーザアカウントに書き込み権限がある事を" +"確認して下さい。 \n" +"また、PCSX2を上位権限(管理者)で再度起動すると、PCSX2が必要なフォルダを自動的" +"に作成されます。\n" +"このマシンでの上位権限が無い場合、ユーザドキュメントモードに切り替える必要が" +"あります\n" +"(下のボタンをクリック)" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:181 msgid "!ContextTip:ChangingNTFS" msgstr "" -"NTFS 圧縮の設定は、Windowsのエクスプローラーでファイルのプロパティを開くこと" -"でいつでも変更できます。" +"NTFS圧縮はウィンドウズエクスプローラのファイルプロパティから手動でいつでも設" +"定変更できます。" #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:49 msgid "!ContextTip:Folders:Settings" msgstr "" -"このフォルダはプラグインを含む PCSX2 のほとんどの設定ファイルを保存するフォル" -"ダです。\n" -"(一部の古いプラグインはこの設定を利用しない可能性があります)" +"このフォルダにはPCSX2とプラグインが生成した設定が保存されています\n" +"(古いプラグインはこの値を使用しない事があります)" #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:54 msgid "!Panel:Folders:Settings" msgstr "" -"ここでPCSX2の設定ファイルの場所を指定することができます。\n" -"既存の設定がすでにあった場合、インポートするか上書きするか選択することができ" -"ます。" +"PCSX2の設定を保存するディレクトリを任意に指定する事ができます。指定先のディレ" +"クトリに\n" +"PCSX2設定が既にある場合はインポート又は上書きをするオプションが表示されます。" #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:94 msgid "!Wizard:Welcome" msgstr "" -"このウィザードではプラグイン、メモリーカード、BIOSの設定の手助けします。 ま" -"た、初めて PCSX2 をインストールされる場合は以下の Readme や構成ガイドを一読す" -"ることをおすすめします。" +"このウィザードではプラグイン、メモリーカード、BIOSの初期設定を行います。\n" +"%sを初めてインストールした方はReadmeと設定ガイドを始めにお読み下さい。" #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:140 msgid "!Wizard:Bios:Tutorial" msgstr "" -"PCSX2 でゲームをプレイするためには *合法な* PS2 の BIOS のコピーが必要です。" -"友人やインターネットを通じてコピーして使用しないでください。あなたは*自分の* " -"Playstation 2 コンソールから BIOS をダンプしなければなりません。" +"PCSX2を実行するには「合法的」に入手したPS2 BIOSが必要です。 \n" +"友人やインターネットから入手したものは使用してはいけません。 \n" +"「あなた自身が所有する」プレイステーション2本体からBIOSをダンプして下さい。" #: pcsx2/gui/Dialogs/ImportSettingsDialog.cpp:31 msgid "!Notice:ImportExistingSettings" msgstr "" -"指定したフォルダに既に %s の設定ファイルがあります。\n" -"これらの設定をインポートするか、%s の初期値で上書きしてください。\n" -"\n" -"(別のフォルダを選択したい場合にはキャンセルを押します)" +"設定フォルダに既存の%s設定が見つかりました。\n" +"この設定をインポート、又は%sのデフォルト値で上書きしますか?\n" +"(若しくはキャンセルを押して、別の設定フォルダを選択して下さい)" #: pcsx2/gui/Dialogs/McdConfigDialog.cpp:30 msgid "!Panel:Mcd:NtfsCompress" msgstr "" -"NTFS 圧縮はビルドインで高速かつ完璧な信頼性があり、多くの場合で高い圧縮率を誇" -"ります (このオプションを強く推奨します)。" +"NTFS圧縮は内蔵された機能で完全な信頼が置ける高速な圧縮方法です。\n" +"メモリーカードの圧縮に優れています。(このオプションは強くお勧めします)" #: pcsx2/gui/Dialogs/McdConfigDialog.cpp:41 msgid "!Panel:Mcd:EnableEjection" msgstr "" -"メモリーカードの破損を防ぐために、ステートセーブを読み込んだ後に強制的にメモ" -"リーカードの着脱を行います。ただしいくつかのゲームで互換性が失われます(ギター" -"ヒーローなど)。" +"セーブステートをロードした際にメモリーカードデータの再インデックスをゲームに" +"強制する事によって、\n" +"メモリーカードデータの破壊を回避します。全てのゲームに互換性があるわけではあ" +"りません(ギターヒーロー)。" #: pcsx2/gui/Dialogs/StuckThreadDialog.cpp:33 msgid "!Panel:StuckThread:Heading" msgstr "" -"スレッド「%s」は応じていません。デッドロックしているかもしれないか、ただもの" -"凄く遅くて執行しているかもしれません。" +"%sスレッドの応答がありません。デッドロック状態か \n" +"「非常に低速」で動作している可能性があります。" #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:38 msgid "!Panel:HasHacksOverrides" msgstr "" -"警告!コマンドラインオプションを使用して PCSX2 の設定上書きして実行していま" -"す。コマンドラインオプションは設定ダイアログには反映されず、設定を変更しても" -"無効になります。" +"警告:通常の設定を無効化するコマンドラインでPCSX2を実行しています。コマンドラ" +"インで変更されたオプションは設定ダイアログに反映されず、ここで設定を変更して" +"も無効化されます。" #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:58 msgid "!Panel:HasPluginsOverrides" msgstr "" -"警告!コマンドラインオプションを使用して PCSX2 のプラグイン設定上書きして実行" -"しています。コマンドラインオプションは設定ダイアログには反映されず、設定を変" -"更しても無効になります。" +"警告:通常のプラグイン・フォルダー設定を無効化するコマンドラインでPCSX2を実行" +"しています。コマンドラインで変更されたオプションは設定ダイアログに反映され" +"ず、ここで設定を変更しても無効化されます。" #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:135 msgid "!Notice:Tooltip:Presets:Slider" msgstr "" -"プリセットを有効にするといくつかのSpeedhack、コンパイラオプション、既知の " -"Gamefix を適用して速度を向上させます。\n" -"既知の重要な Gamefix は自動で有効になります。\n" +"プリセットは各種スピードハック、リコンパイラ設定及び速度を向上させるゲーム修" +"正を適用させます。\n" +"既知のゲーム修正は自動的に適用されます。\n" "\n" -"プリセットの内容\n" -"1 - 最も精密にエミュレーションを行います。\n" -"3 --> 互換性とスピードのバランスを取ってエミュレーションを行います。\n" -"4 - より積極的に hack を行います。\n" -"6 - hack のしすぎで多くの場合は速度の低下が起きてしまいます。" +"プリセットについて:\n" +"1 - 最も高精度なエミュレーションですが、最も低速です。\n" +"3 --> 速度と互換性のバランス型。\n" +"4 - 能動的なハックを付け足します。\n" +"6 - ハック数が多すぎてほとんどのゲームでは遅くなります。" #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:149 msgid "!Notice:Tooltip:Presets:Checkbox" msgstr "" -"プリセットを有効にするといくつかのSpeedhack、コンパイラオプション、既知の " -"Gamefix を適用して速度を向上させます。\n" -"既知の重要な Gamefix は自動で有効になります。\n" +"プリセットは各種スピードハック、リコンパイラ設定及び速度を向上させるゲーム修" +"正を適用させます。\n" +"既知のゲーム修正は自動的に適用されます。\n" "\n" -"-->チェックを外すと、手動で(現在のプリセットを元にして)設定することができま" -"す。" +"チェックをはずすと現在のプリセットを基に手動で設定を変更できます。" #: pcsx2/gui/IsoDropTarget.cpp:28 msgid "!Notice:ConfirmSysReset" msgstr "" -"この操作はPS2仮想マシンをリセットするため、現在作業中のデータは失われます。よ" -"ろしいですか?" +"この操作は既存するPS2の仮想マシンステートをリセットします。\n" +"進行中の全ての作業が失われます。本当にリセットしてもよろしいですか?" #: pcsx2/gui/MainMenuClicks.cpp:106 msgid "!Notice:DeleteSettings" msgstr "" -"このコマンドは %s の設定を全て消去してスタートアップウィザードからやり直しま" -"す。この操作のあと手動で %s を再起動する必要があります。\n" +"この操作は%sの設定を全て削除してリセットします。\n" +"次回起動時に初期設定ウィザードを再実行させる事ができます。\n" +" この操作を実行した後に手動で%sを再起動する必要があります。\n" "\n" -"警告!! OK を押すと %s の設定は*全て*消えてしまい、強制的にアプリケーションが" -"終了し、エミュレーション中のデータも失われます。本当にいいですか?\n" +"警告: OKをクリックすると%s設定を「全て削除」します。\n" +"プログラムは強制終了し、進行中のエミュレーション作業は失われます。\n" +"本当によろしいですか?\n" "\n" -"(注:プラグインの設定は残ります)" +"(注意: プラグインの設定に影響はありません)" #: pcsx2/gui/MemoryCardFile.cpp:78 msgid "!Notice:Mcd:HasBeenDisabled" msgstr "" -"PS2-スロット%dは自動的に無効にされました。問題を修正したら、 いつでも、\n" -"コンフィグを利用して再可能にすることができます。\n" -"(メインメニューからコンフィグ⇒メモリカード)" +"PS2スロット[%d]は自動的に無効にされました。この問題を解決するには\n" +"メインメニューから [設定→メモリーカード] で再度有効化して下さい。" #: pcsx2/gui/Panels/BiosSelectorPanel.cpp:138 msgid "!Notice:BIOS:InvalidSelection" msgstr "" -"有効な BIOS を指定してください。もし有効なものを用意できないのであればキャン" -"セルを押してウィザードを閉じてください。" +"有効なBIOSイメージファイルを選択して下さい。\n" +"選択できない場合はキャンセルを押して設定パネルを閉じてください。" #: pcsx2/gui/Panels/CpuPanel.cpp:111 msgid "!Panel:EE/IOP:Heading" -msgstr "注意: ほとんどのゲームはデフォルト設定のままで構いません。" +msgstr "メモ: ほとんどのゲームはデフォルトオプションのままで動作します。" #: pcsx2/gui/Panels/CpuPanel.cpp:178 msgid "!Panel:VUs:Heading" -msgstr "注意: ほとんどのゲームはデフォルト設定のままで構いません。" +msgstr "メモ: ほとんどのゲームはデフォルトオプションのままで動作します。" #: pcsx2/gui/Panels/DirPickerPanel.cpp:69 msgid "!Notice:DirPicker:CreatePath" -msgstr "" -"指定されたパスやフォルダーは存在していません。 それを作成してよろしいでしょう" -"か?" +msgstr "指定されたディレクトリは存在しません。作成しますか?" #: pcsx2/gui/Panels/DirPickerPanel.cpp:158 msgid "!ContextTip:DirPicker:UseDefault" msgstr "" -"チェックをすると、このフォルダをPCSX2の現在のユーザーモードのデフォルト設定が" -"自動的に反映されます。" +"チェックを入れるとこのフォルダは現在のPCSX2のユーザモード設定に関するデフォル" +"トを自動的に反映されます。" #: pcsx2/gui/Panels/GSWindowPanel.cpp:55 -#, fuzzy msgid "!ContextTip:Window:Zoom" msgstr "" -"VSYNC を同期させるとティアリング現象を解消できますが、パフォーマンスに重大な" -"問題が発生します。\n" -"通常はフルスクリーンモードでのみ使用します。また一部の GS プラグインでは機能" -"しない可能性があります。" +"ズーム=100 : 映像を出力をクロッピング(トリミング)せず画面に合わせて伸縮しま" +"す。\n" +"基本値100以上はズームイン、以下はズームアウト。値0 : 自動ズームインで黒い枠" +"を消します(アスペクト比を保ちますが、多少外にでる事があります)。\n" +"メモ:一部のゲームでは黒枠を描画する事があり、「値を0」に設定しても消えませ" +"ん。\n" +"\n" +"ショートカットキー: [CTRL] + [+]でズームイン、[CTRL] + [-]でズームアウト、" +"[CTRL] + [*]でズーム値100/0切り替え(+-*はテンキーを使用)" #: pcsx2/gui/Panels/GSWindowPanel.cpp:63 msgid "!ContextTip:Window:Vsync" msgstr "" -"VSYNC を同期させるとティアリング現象を解消できますが、パフォーマンスに重大な" -"問題が発生します。\n" -"通常はフルスクリーンモードでのみ使用します。また一部の GS プラグインでは機能" -"しない可能性があります。" +"Vsync (垂直同期)は画面の水平な乱れ(テアリング)を除去しますが、パフォーマ" +"ンスに悪影響します。\n" +"フルスクリーン時に適用され、全てのGSプラグインで動作しない事があります。" #: pcsx2/gui/Panels/GSWindowPanel.cpp:68 msgid "!ContextTip:Window:ManagedVsync" msgstr "" -"フレームレートが最速の時に VSYNC を有効にします。最速でない場合は速度の低下を" -"防ぐために無効にします。\n" -"注意:現時点ではDX10/11ハードウェアレンダリングで GSdx を使用している時のみ動" -"作します。\n" -"他のプラグインやレンダリングモードでは無視されるか、黒いフレームが挿入され点" -"滅が起こります。\n" -"またVSYNCと同期する設定を有効にする必要があります。" +"フレームレートがフルスピードに達している時は自動で垂直同期を有効にし、スピー" +"ドが落ちるとパフォーマンスを保全する為に自動で無効になります。\n" +"メモ:現時点ではGSdxプラグインをDX 10/11のハードウェア設定にしている場合のみ" +"正常に動作します。他のプラグインやレンダリングモードで使うと\n" +"認識しなかったり垂直同期の有効無効が切り替わる際に黒画面になったりします。垂" +"直同期も有効にしなければなりません​。" #: pcsx2/gui/Panels/GSWindowPanel.cpp:76 msgid "!ContextTip:Window:HideMouse" msgstr "" -"GS ウィンドウ上でマウスを強制的に非表示にします。マウス操作がメインのゲームで" -"有効にすると便利です。\n" -"デフォルトでは操作をしないで2秒経過するとマウスを自動で非表示にします。" +"映像出力画面内に入ったマウスポインタを非表示にします。\n" +"マウスをゲームで主にコントローラとして利用している時に便利です。\n" +"デフォルトでマウスは2秒間動作が無いと自動的に隠れます。" #: pcsx2/gui/Panels/GSWindowPanel.cpp:82 msgid "!ContextTip:Window:Fullscreen" msgstr "" -"ゲームを始めた時や再開した時に自動的にフルスクリーンになります。\n" -"フルスクリーンにはAlt+Enterキーでいつでも切り替えができます。" +"エミュレーション実行時とレジュームする時に自動でフルスクリーンにする機能を有" +"効にします。[ALT] + [Enter]のショートカットでいつでも切り替える事ができます。" #: pcsx2/gui/Panels/GSWindowPanel.cpp:93 msgid "!ContextTip:Window:HideGS" -msgstr "ESC を押したりしてゲームを一時停止した時にGSウィンドウを閉じます。" +msgstr "" +"ESCを押すか、エミューレータをポーズした時にGSウィンドウを非表示にする機能で" +"す。\n" +"大きな画面だったりして作業の邪魔になりやすいので、このオプションは便利です。" #: pcsx2/gui/Panels/GameFixesPanel.cpp:67 msgid "!ContextTip:Gamefixes:EE Timing Hack" msgstr "" -"以下のゲームに効果があります。\n" -" * デジタルデビルサーガ (FMVでのクラッシュの問題)\n" -" * SSX (グラフィックの不具合やクラッシュの問題)\n" -" * バイオハザード ガンサバイバー4 (テクスチャの問題)" +"以下のゲームに役立ちます:\n" +" * デジタルデビルサーガ(ゲーム内ムービーとクラッシュを修正します)\n" +" * SSX(グラフィックとクラッシュを修正します)\n" +" * ガンサバイバー4 バイオハザードヒーローズネバーダイ(グラフィックがおかし" +"くなります)" #: pcsx2/gui/Panels/GameFixesPanel.cpp:80 msgid "!ContextTip:Gamefixes:OPH Flag hack" msgstr "" -"以下のゲームに効果があります。\n" -" * BLEACH~ブレイド・バトラーズ~\n" -" * グローランサー2&3\n" -" * Wizardry" +"以下のゲームに役立ちます:\n" +" * ブリーチブレイドバトラーズ\n" +" * グローランサー3作\n" +" * ウィザードリィ" #: pcsx2/gui/Panels/GameFixesPanel.cpp:89 msgid "!ContextTip:Gamefixes:DMA Busy hack" msgstr "" -"以下のゲームに効果があります。\n" -" * マナケミア~学園の錬金術士たち~" +"以下のゲームに役立ちます:\n" +" * マナケミア~学園の錬金術士たち~\n" +" * メタルサーガ" #: pcsx2/gui/Panels/GameFixesPanel.cpp:96 -#, fuzzy msgid "!ContextTip:Gamefixes:VIF1 FIFO hack" -msgstr "" -"以下のゲームに効果があります。\n" -" * BLEACH~ブレイド・バトラーズ~\n" -" * グローランサー2&3\n" -" * Wizardry" +msgstr "ContextTip String Not Found" #: pcsx2/gui/Panels/GameFixesPanel.cpp:119 msgid "!Panel:Gamefixes:Compat Warning" msgstr "" -"Gamefix は一部タイトルのエミュレーションの不具合を回避することができます。し" -"かし互換性やパフォーマンスの問題を引き起こす可能性があります。\n" +"ゲーム修正はいくつかのゲームタイトルでの不正なエミュレーションを補正します" +"が、\n" +"互換性やパフォーマンスに悪影響を引き起こすことがあります。\n" "\n" -"ここの設定は無効のままで、代わりに自動Gamefixを有効にする事を推奨します。\n" -"(自動Gamefix とはテスト済みの特定のゲームにのみ、特定の修正を適用するという機" -"能です)" +"以下の項目を空欄のままにし、[自動ゲーム修正]を有効にする事を推奨します。\n" +"([自動ゲーム修正]は特定のゲームに対し選択的にテスト済みの修正を適用させます)" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:720 msgid "!Notice:Mcd:Delete" msgstr "" -"あなたはフォーマット済みメモリーカード '%s' を削除しようとしています。この" -"カード内のデータは全て失われます!本当によろしいですか?" +"フォーマットされたメモリーカード[%s]を削除しようとしています。\n" +"メモリーカードのデータは全て失われます。本当に削除してもよろしいですか?" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:758 msgid "!Notice:Mcd:CantDuplicate" msgstr "" -"失敗エラー: 複写は空のPS2-ポートに、または、ファイルシステムに書き込むしかで" -"きません。" +"複製に失敗しました。複製は空PS2ポート又はファイルシステムに対してのみ許可され" +"ています。" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:801 msgid "!Notice:Mcd:Copy Failed" -msgstr "失敗エラー: 目的地メモリカード%sは使用中です。" +msgstr "コピーに失敗しました。コピー先のメモリーカード[%s]は使用中です。" #: pcsx2/gui/Panels/MiscPanelStuff.cpp:35 msgid "!Panel:Usermode:Explained" msgstr "" -"以下のPCSX2ユーザレベルドキュメントのデフォルト・フォルダー・パスを設置してく" -"ださい。\n" -"(メモリカード、スクリーン・ショット、設定、セーブ・ステートを含んで)\n" -"いつでも、コア設定パネルを利用してこれらのフォルダー・パスをくつがえすことが" -"できます。" +"PCSX2がユーザレベルドキュメントを保存するディレクトリを指定して下さい\n" +"(メモリーカード、スクリーンショット、各種設定、セーブステート)。\n" +"保存するディレクトリはコア設定パネルでいつでも変更する事ができます。" #: pcsx2/gui/Panels/MiscPanelStuff.cpp:41 msgid "!Panel:Usermode:Warning" msgstr "" -"以下のPCSX2ユーザレベルドキュメントのデフォルト・フォルダー・パスを設置してく" -"ださい。\n" -"(メモリカード、スクリーン・ショット、設定、セーブ・ステートを含んで)\n" -"このオプションはインストール・デフォルト値を使用するように設定された標準のパ" -"スだけに影響します。" +"PCSX2がユーザレベルドキュメントを保存するディレクトリを変更する事ができます\n" +"(メモリーカード、スクリーンショット、各種設定、セーブステート)。\n" +"インストール時のディレクトリを標準ディレクトリとして指定するものにのみ効果が" +"あります。" #: pcsx2/gui/Panels/PathsPanel.cpp:40 msgid "!ContextTip:Folders:Savestates" msgstr "" -"このフォルダは PCSX2 のステートセーブの保存場所です。\n" -"メニューまたはツールバーを使うか、F1/F3(セーブ/ロード)キーで操作します。" +"PCSX2のセーブステートはこのフォルダに保存されます。\n" +"メインメニューのシステムから、又は「F1(セーブ)」と「F3(ロード)」の\n" +"ショートカットキーでステート操作を行う事ができます。" #: pcsx2/gui/Panels/PathsPanel.cpp:50 msgid "!ContextTip:Folders:Snapshots" msgstr "" -"このフォルダは PCSX2 のスナップショットの保存場所です。ご使用の GS プラグイン" -"によってはサイズや形式が違うかもしれません。" +"PCSX2で保存されたスクリーンショットはこのフォルダに保存されます。\n" +"実際のスクリーンショットのイメージ形式とスタイルは使用しているGSプラグイン" +"にって変わります。" #: pcsx2/gui/Panels/PathsPanel.cpp:60 msgid "!ContextTip:Folders:Logs" msgstr "" -"このフォルダは PCSX2 のログとダンプデータの保存場所です。一部の古いプラグイン" -"はこの設定を利用しない可能性があります。" +"PCSX2のログ及びダンプファイルはこのフォルダに保存されます。\n" +"プラグインは通常この設定を利用しますが、古いものはこの限りではありません。" #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:242 msgid "!Notice:PluginSelector:ConfirmShutdown" msgstr "" -"警告! プラグインを変えるのはPS2仮想機械の完全な停止して、リセットを必要とし" -"ます。\n" -"PCSX2は、状態をセーブして、リロードするのを試みるが、新たに選択されたプラグイ" -"ンが両立しないなら、\n" -"リロードは失敗するかもしれません。そうならば、現在の進行ステートはなくなって" -"しまいます。\n" +"警告:プラグインの変更はPS2仮想マシンの完全なシャットダウンとリセットが必要で" +"す。\n" +"PCSX2はステートセーブを行い、変更されたプラグインでステートの復帰を試行します" +"が、\n" +"互換性が無かった場合は復帰に失敗し、進行中の作業が失われる可能性がありま" +"す。\n" "\n" -"それでも現在設定を適用してもよろしいですか?" +"本当に設定を適用してもよろしいですか?" #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:457 msgid "!Notice:PluginSelector:ApplyFailed" msgstr "" -"%sが正常動作するため、すべてのプラグイン有効な選択をしなければなりません。\n" -"プラグインの不具合や%sが不完全なインストールの場合なら、キャンセル・ボタンを" -"押すと、コンフィグ・パネルが閉まります。" +"%sを実行するには有効なプラグインを全てについて選択していなければいけませ" +"ん。\n" +"プラグインが無かったり、不完全な%sのインストールで、有効な選択ができない場合" +"は\n" +"キャンセルを押して設定パネルを閉じて下さい。" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:27 msgid "!Panel:Speedhacks:EECycleX1" msgstr "" -"1 - 通常のサイクルレート。これは実機のPS2の EmotionEngine の速度に近いもので" -"す。" +"1 - [デフォルト] PS2実機のEEと同サイクル数(ほぼ同速度)でエミュレーションし" +"ます。" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:32 msgid "!Panel:Speedhacks:EECycleX2" msgstr "" -"2 - EEのサイクルレートを約33%低下。多くのゲームで互換性を維持したままある程度" -"のスピードアップ出来ます。" +"2 - EEのサイクルレートを33%低下させます。そこそこ速度上昇、互換性も高いです。" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:37 msgid "!Panel:Speedhacks:EECycleX3" msgstr "" -"2 - EEのサイクルレートを約50%低下。中々の高速化が期待できますが *恐らく* FMV" -"で音声の途切れる原因にもなります。" +"3 - EEのサイクルレートを50%低下させます。大きく速度上昇、そこそこ互換性が" +"損なわれます。ゲーム内ムービーのオーディオが乱れる事があります。" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:54 msgid "!Panel:Speedhacks:VUCycleStealOff" -msgstr "0 - VU サイクルスティーリング無効。最も互換性の高い設定!" +msgstr "0 - VU Cycle Stealingを無効にします。最も互換性があります。" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:59 msgid "!Panel:Speedhacks:VUCycleSteal1" -msgstr "" -"1 - 少しだけVU サイクルスティーリング実行。互換性は下がりますがほとんどのゲームで若干の" -"高速化します。" +msgstr "1 - 穏やかな設定です。そこそこ速度上昇、互換性が少し損なわれます。" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:64 msgid "!Panel:Speedhacks:VUCycleSteal2" -msgstr "" -"2 - 適度にVU サイクルスティーリング実行。より互換性は下がりますがいくつかのゲームで大幅" -"に高速化します。" +msgstr "2 - 適度な設定です。大きく速度上昇、そこそこ互換性が損なわれます。" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:70 msgid "!Panel:Speedhacks:VUCycleSteal3" msgstr "" -"3 - 限界までVU サイクルスティーリング実行。画面のちらつきが発生し多くのゲームで速度の低" -"下かが起こるため有用性は限定的。" +"3 - 最大限の設定です。利用価値は低く、ほとんどのゲームでは画面のチラつき、速" +"度低下等が発生します。" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:97 msgid "!Panel:Speedhacks:Overview" msgstr "" -"Speedhack はエミュレーション速度を向上させる事ができますが、不具合やサウンド" -"の問題、FPS値の異常を引き起こす可能性があります。エミュレーションに不具合が発" -"生した場合は無効にしてください。" +"スピードハックはエミュレーション速度を向上させますが、不具合、オーディオの乱" +"れや不正確なFPSを表示する事があります。\n" +"エミュレーションについて問題が発生した時は、まずはこのパネルの設定を無効にし" +"てみて下さい。" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:129 msgid "!ContextTip:Speedhacks:EECycleRate Slider" msgstr "" -"このスライドバーを上げるとEmotionEngineのR5900コアCPUのクロックを下げる代わり" -"に大きな高速化を行い、\n" -"PS2ハードウェアの機能を最大限利用していないゲームの高速化に有用です。" +"設定値を高くする程EEのR5900 CPUのクロックを低下させます。実機PS2のハード" +"ウェア能力を\n" +"最大限に利用できていないゲームに大幅な速度の向上をもたらします。" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:150 msgid "!ContextTip:Speedhacks:VUCycleStealing Slider" msgstr "" -"このスライドバーを上げるとEmotionEngineのVUユニットからスティーリングを行いま" -"す。\n" -"高い設定にするほどサイクルスティーリングを行う量が増加します。" +"VUがEEから奪うサイクルを増減させます。高い値ほどVUプログラム数に応じてEEから" +"奪うサイクルが増加します。" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:169 msgid "!ContextTip:Speedhacks:vuFlagHack" msgstr "" -"常時ではなくブロックされた時のみフラグステータスを更新します。\n" -"ほとんどの安全であり、SuperVUにも同様の動作をさせます。" +"常に読み込むのでは無く、読み込まれるブロックのステータスフラグのみをアップ" +"デートします。\n" +"ほぼ安全に使う事ができ、Super VUもデフォルトで同じような動作をします。" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:174 -#, fuzzy msgid "!ContextTip:Speedhacks:vuThread" -msgstr "" -"このhackは主に非3D系RPGにある INTC ステータスレジスタを使用しVSYNC待ちをする" -"ゲームに最適です。\n" -"効果がなかった場合には使用しないでください。" +msgstr "ContextTip String Not Found" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:195 msgid "!ContextTip:Speedhacks:INTC" msgstr "" -"このhackは主に非3D系RPGにある INTC ステータスレジスタを使用しVSYNC待ちをする" -"ゲームに最適です。\n" -"効果がなかった場合には使用しないでください。" +"垂直同期を待つ為にINTCステータスレジスタを使用する、主に非3D RPGゲームで使う" +"と効果が得られます。\n" +"垂直同期にこの手法を使用しないゲームでは速度アップはあるか無いかぐらいです。" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:200 msgid "!ContextTip:Speedhacks:BIFC0" msgstr "" -"主にEEのカーネル空間のアドレス 0x81FC0 のアイドルループ処理を対象にしていま" -"す。\n" -"このhackは別ユニットによるエミュレーションのイベントトリガまでの間に、状態が" -"同じである事を検出します。\n" -"このようなループを1度だけ繰り返したあと、次のイベントかタイムスライスの終りのいずれ" -"か早いほうに進みます。" +"カーネルの 0X81FC0 アドレスにあるEEアイドルループを主に監視し、別ユニットのエ" +"ミュレーションが発動するイベントまで、\n" +"全ての反復でマシンステートが同一である保証があるループの探知を試みます。検出" +"ループに対し1度の反復後に次のイベントへ、\n" +"若しくはプロセッサのタイムスライスの末尾へ、どちらか近いほうへ飛びます。" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:207 msgid "!ContextTip:Speedhacks:fastCDVD" msgstr "" -"この問題を抱えている既知のゲーム用の設定。\n" -"HDLoader互換性リストを参照してください(主に'MODE 1'や'低速DVD'など)" +"「HDLoader compatibility list」を参照し、この機能を《使用できない》ゲームを調" +"べて下さい(mode 1/slow DVDと表記されています)。" #: pcsx2/gui/Panels/VideoPanel.cpp:37 msgid "!ContextTip:Framelimiter:Disable" msgstr "" -"フレームリミットを無効にした場合、スローモーションモードとターボモードは使用" -"できません。" +"フレームレート制限が無効になっている場合、ターボ及びスローモーションモードは" +"使用できません。" #: pcsx2/gui/Panels/VideoPanel.cpp:227 msgid "!Panel:Frameskip:Heading" msgstr "" -"注意!PS2はハードの設計上正確なフレームスキップはできません。よって一部のゲー" -"ムでは深刻なグラフィックのエラーが発生します。" +"メモ:PS2のハードウェア設計により、         \n" +"正確なフレームスキップは不可能です。 \n" +"有効にすると、ゲームによってグラフィックの\n" +"深刻なエラーを発生させる事があります。" #: pcsx2/gui/Panels/VideoPanel.cpp:306 msgid "!ContextTip:GS:SyncMTGS" msgstr "" -"映像の不具合の原因が MTGS スレッドの同期によるものだと思われる場合有効にして" -"ください。" +"クラッシュやグラフィックエラーの発生原因として、\n" +"MTGSスレッドの同期が疑わしい場合は有効にして下さい。" #: pcsx2/gui/Panels/VideoPanel.cpp:310 msgid "!ContextTip:GS:DisableOutput" msgstr "" -"MTGSスレッドかGPUオーバーヘッドによって発生されたベンチマークノイズを除去しま" -"す。このオプションはステートセーブと併用するのが最良です。; 最適な場面でス" -"テートセーブを行い、このオプションを有効にしてリロードします。\n" +"MTGSスレッド又はGPUオーバーヘッドにより発生されるベンチマークノイズを除去しま" +"す。このオプションはセーブステートと併用して利用する事が適切です。\n" +"都合のつく所でセーブステートを行い、オプションを有効にした後に、セーブステー" +"トをロードしてください。\n" "\n" -"警告:このオプションはいつでも有効にすることができますが、動作中に無効にでき" -"ません(映像に悪影響を与えます)。" +"警告: このオプションはゲーム実行中に有効化できますが、無効化する事はできま" +"せん(映像出力内容の判別ができなくなります)。" #: pcsx2/vtlb.cpp:710 msgid "!Notice:HostVmReserve" msgstr "" -"システムの仮想記憶リソースは少ないため、PCSX2正常操作が確保できません。これは" -"スワップファイルが少ない、\n" -"あるいは無効化されているとか、いくつかのメモリ使用量高いバックグラウンド・タ" -"スクがあることなどの原因で、\n" -"仮想記憶リソース少ないによって起こされているかもしれません。 " +"PCSX2を実行する為の仮想メモリリソースが不足しています。スワップファイルが小さ" +"すぎるか、\n" +"無効にされている場合や他のプログラムがメモリの多くを消費している時に発生しま" +"す。" #: pcsx2/x86/sVU_zerorec.cpp:363 msgid "!Notice:superVU:VirtualMemoryAlloc" msgstr "" -"メモリがたりなかった(似たい状況)。 SuperVU リコンパイラは必要の特定メモリ範囲" -"を予約できないで、\n" -"利用不可能になるでしょう。致命的なエラーではありませんが、sVU リコンパイラは" -"もう廃れたため、\n" -"お代わりにとにかくmicroVUを使用するべきでしょう。(笑)" +"メモリー不足(多少):重大なエラーではありません。SuperVUリコンパイラが\n" +"必要とする特定のメモリ領域を確保する事ができなかったので使用不可となりまし" +"た。\n" +"sVU rec は旧式なので、変わりに microVU を使用した方が良いでしょう。 (^-^)" #~ msgid "!ContextTip:Speedhacks:vuBlockHack" #~ msgstr "" -#~ "遠い将来にインスタンスデータの古いフラグを必要としないと仮定しています。\n" -#~ "かなり安全なはずです。どんなゲームに不具合が起きるかは不明ですが..." - -#~ msgid "No reason given." -#~ msgstr "不明な理由" - -#~ msgid "Threading activity: start, detach, sync, deletion, etc." -#~ msgstr "スレッドのアクティビティ; 開始、分離、同期、削除など" - -#~ msgid "Includes idle event processing and some other uncommon event usages." -#~ msgstr "アイドル状態のイベント処理と、いくつかの他の珍しいイベント" - -#~ msgid "" -#~ "The MTGS thread has become unresponsive while waiting for the GS plugin " -#~ "to open." -#~ msgstr "GS プラグインを開くまで MTGS スレッドはしなくなる事があります。" - -#~ msgid "Internal Memorycard Plugin failed to initialize." -#~ msgstr "内蔵メモリーカードプラグインの初期化に失敗しました。" - -#~ msgid "Safest" -#~ msgstr "最も安定" - -#~ msgid "Safe (faster)" -#~ msgstr "最も安定(高速)" - -#~ msgid "Balanced" -#~ msgstr "バランス" - -#~ msgid "Aggressive" -#~ msgstr "アグレッシブ" - -#~ msgid "Aggressive plus" -#~ msgstr "アグレッシブ+" - -#~ msgid "Mostly Harmful" -#~ msgstr "害にしかならない" - -#~ msgid "Fits a lot of log in a microcosmically small area." -#~ msgstr "小スペースに大量のログを表示します。" - -#~ msgid "It's what I use (the programmer guy)." -#~ msgstr "それは私(プログラマたち)が使用します。" - -#~ msgid "Its nice and readable." -#~ msgstr "読みやすくてナイスです。" - -#~ msgid "In case you have a really high res display." -#~ msgstr "非常に高い解像度にした場合。" - -#~ msgid "Default soft-tone color scheme." -#~ msgstr "デフォルトのソフトな配色。" - -#~ msgid "" -#~ "Classic black color scheme for people who enjoy having text seared into " -#~ "their optic nerves." -#~ msgstr "クラシックな黒い配色。文字を見えやすくしたい場合などに。" - -#~ msgid "" -#~ "When checked the log window will be visible over other foreground windows." -#~ msgstr "チェックするとログウィンドウを常に手前に表示します。" - -#~ msgid "" -#~ "Always use this option if you want the safest and surest memory card " -#~ "behavior." -#~ msgstr "" -#~ "メモリカードの最も安全で確実な動作を望むなら、このオプションを使用してくだ" -#~ "さい。" - -#~ msgid "16 and 32 MB cards have roughly the same compatibility factor." -#~ msgstr "16 MB と 32 MB のメモリーカードの互換性は同等程度です。" - -#~ msgid "" -#~ "Use at your own risk. Erratic memory card behavior is possible (though " -#~ "unlikely)." -#~ msgstr "" -#~ "不安定なメモリーカードの使用は自己責任でお願いします(運がよければ大丈夫)。" - -#~ msgid "Logs events as they are passed to the PS2 virtual machine." -#~ msgstr "PS2 仮想マシンに渡されてからイベントを記録します。" - -#~ msgid "" -#~ "Error while parsing either NTSC or PAL framerate settings. Settings must " -#~ "be valid floating point numerics." -#~ msgstr "" -#~ "NTSC または PAL のフレームレートの設定の解析中にエラーが発生しました。有効" -#~ "な浮動小数点値を入力してください。" - -#~ msgid "" -#~ "For troubleshooting potential bugs in the MTGS only, as it is potentially " -#~ "very slow." -#~ msgstr "MTGSに潜在的なバグがあった場合のみ有効に。非常に低速になります。" - -#~ msgid "" -#~ "Completely disables all GS plugin activity; ideal for benchmarking EEcore " -#~ "components." -#~ msgstr "" -#~ "GSプラグインを無効にします。EEコアコンポーネントのベンチマークに最適です。" +#~ "将来読み込まれるであろうブロックで、古いフラグのインスタンスデータは不必要" +#~ "と判断します。\n" +#~ "安全に使えるはずですが、ゲームに不具合を及ぼすかは知られていませ​ん。" diff --git a/locales/ja_JP/pcsx2_Main.po b/locales/ja_JP/pcsx2_Main.po index 3c013fde0..a0b3e5b5a 100644 --- a/locales/ja_JP/pcsx2_Main.po +++ b/locales/ja_JP/pcsx2_Main.po @@ -1,21 +1,21 @@ # SOME DESCRIPTIVE TITLE. -# Copyright (C) 2011 PCSX2_Dev_Team -# This file is distributed under the same license as the PCSX2 package. +# Copyright (C) YEAR PCSX2 Dev Team +# This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2012-02-28 12:20+0100\n" -"PO-Revision-Date: 2011-04-30 09:01+0900\n" -"Last-Translator: oreore\n" -"Language-Team: \n" +"POT-Creation-Date: 2012-03-10 20:38+0100\n" +"PO-Revision-Date: 2011-12-17 01:36+0900\n" +"Last-Translator: DeltaHF\n" +"Language-Team: DeltaHF\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Poedit-KeywordsList: _;pxL\n" +"X-Poedit-KeywordsList: _;pxL;_d;pxDt;_t;pxLt\n" "X-Poedit-SourceCharset: utf-8\n" "X-Poedit-Basepath: trunk\\\n" "X-Poedit-Language: Japanese\n" @@ -25,19 +25,19 @@ msgstr "" #: common/include/Utilities/Exceptions.h:187 msgid "No reason given." -msgstr "不明な理由" +msgstr "原因不明なエラー" #: common/include/Utilities/Exceptions.h:226 msgid "Parse error" -msgstr "解析エラー" +msgstr "構文エラー" #: common/include/Utilities/Exceptions.h:250 msgid "Your machine's hardware is incapable of running PCSX2. Sorry dood." -msgstr "申し訳ありません。ご使用のPCではPCSX2を実行できません。" +msgstr "このマシンのハードウェア構成ではPCSX2は実行できません。ごめんなさい。" #: common/src/Utilities/Exceptions.cpp:219 msgid "Oh noes! Out of memory!" -msgstr "あわわ!メモリ不足です。" +msgstr "おっと、メモリー不足です!" #: common/src/Utilities/Exceptions.cpp:234 msgid "" @@ -45,83 +45,83 @@ msgid "" "drivers, services, or may simply have insufficient memory or resources to " "meet PCSX2's lofty needs." msgstr "" -"仮想メモリのマッピングエラーです。デバイスドライバやサービスが競合している" -"か、単純にPCSX2を実行するためのメモリが不足しています。" +"仮想メモリマッピングエラー。システムに競合しているドライバやサービス或いは" +"PCSX2の高レベルな要求に応えられるメモリーやリソースが不足しています。" #: common/src/Utilities/Exceptions.cpp:309 msgid "Path: " -msgstr "ファイル名:" +msgstr "パス:" #: common/src/Utilities/Exceptions.cpp:313 msgid "[Unnamed or unknown]" -msgstr "解析エラー" +msgstr "[不明又は未知]" #: common/src/Utilities/Exceptions.cpp:333 msgid "A file could not be created." -msgstr "ファイルを作成できません。" +msgstr "ファイルを作成できませんでした。" #: common/src/Utilities/Exceptions.cpp:353 msgid "File not found." -msgstr "ファイルがありません。" +msgstr "ファイルが見つかりません。" #: common/src/Utilities/Exceptions.cpp:373 msgid "" "Permission denied while trying to open file, likely due to insufficient user " "account rights." msgstr "" -"恐らくユーザアカウントの権限が不足しているため、ファイルを開けませんでした。" +"ファイルのアクセス権がありません。ユーザーアカウント権限が不足していると思わ" +"れます。" #: common/src/Utilities/Exceptions.cpp:393 msgid "" "Unexpected end of file or stream encountered. File is probably truncated or " "corrupted." msgstr "" -"ファイルやストリームが予期せず終了しました。恐らくファイルが破損しています。" +"予期しないEOF又はストリームを検出しました。切り詰められているか、破損したファ" +"イルです。" #: common/src/Utilities/ThreadTools.cpp:41 msgid "Threading activity: start, detach, sync, deletion, etc." -msgstr "スレッドのアクティビティ; 開始、分離、同期、削除など" +msgstr "スレッドアクティビティ:start、detach、sync、deletion、等。" #: common/src/Utilities/ThreadingDialogs.cpp:30 msgid "Waiting for tasks..." -msgstr "タスク待機中…" +msgstr "タスク待機状態..." #: common/src/Utilities/ThreadingDialogs.cpp:41 msgid "Waiting for task..." -msgstr "タスク待機中…" +msgstr "タスク待機状態..." #: common/src/Utilities/wxAppWithHelpers.cpp:36 msgid "Includes idle event processing and some other uncommon event usages." -msgstr "アイドル状態のイベント処理と、いくつかの他の珍しいイベント" +msgstr "アイドルイベント処理及びその他例外イベントを用途に含みます。" #: pcsx2/CDVD/IsoFileFormats.cpp:416 msgid "Unrecognized ISO image file format" -msgstr "認識できないISOイメージです。" +msgstr "認識できないISOイメージファイル形式です。" #: pcsx2/Elfheader.cpp:266 msgid "Cannot load ELF binary image. The file may be corrupt or incomplete." -msgstr "" -"ELFバイナリイメージを読み込めませんでした。ファイルが破損または不完全な可能性" -"があります。" +msgstr "ELFバイナリイメージを読み込めません。破損又は不完全なファイルです。" #: pcsx2/Elfheader.cpp:268 msgid "" "If loading from an ISO image, this error may be caused by an unsupported ISO " "image type or a bug in PCSX2 ISO image support." msgstr "" -"ISOイメージから読み込んだ場合、このエラーはISOイメージが未サポートか、PCSX2の" -"ISOイメージ読み込み機能のバグの可能性があります。" +"ISOイメージから読み込んでいる場合、このエラーはサポートしないISOイメージ形" +"式、或いはPCSX2側のISOイメージサポートのバグが原因と考えられます。" #: pcsx2/MTGS.cpp:859 msgid "" "The MTGS thread has become unresponsive while waiting for the GS plugin to " "open." -msgstr "GS プラグインを開くまで MTGS スレッドはしなくなる事があります。" +msgstr "GSプラグインのロード待機中にMTGSスレッドの応答が停止しました。" #: pcsx2/PluginManager.cpp:709 msgid "" "The savestate cannot be loaded, as it appears to be corrupt or incomplete." -msgstr "データが破損または不完全なため、ステートセーブはロードできません。" +msgstr "セーブステートをロードできませんでした。破損しているか不完全です。" #: pcsx2/PluginManager.cpp:719 #, c-format @@ -129,8 +129,8 @@ msgid "" "%s plugin failed to open. Your computer may have insufficient resources, or " "incompatible hardware/drivers." msgstr "" -"%s プラグインを開くのに失敗しました。リソース不足か、ハードウェアやデバイスの" -"競合が原因です。" +"[%s]プラグインがロードに失敗しました。システムのリソースが不足しているか、互" +"換性の無いハードウェア又はドライバーがあります。" #: pcsx2/PluginManager.cpp:726 #, c-format @@ -138,18 +138,18 @@ msgid "" "%s plugin failed to initialize. Your system may have insufficient memory or " "resources needed." msgstr "" -"%s プラグインの初期化に失敗しました。ご使用のPCのメモリやリソース不足の可能性" -"があります。" +"[%s]プラグインが初期化に失敗しました。システムのメモリー又はリソースが不足し" +"ています。" #: pcsx2/PluginManager.cpp:832 #, c-format msgid "The configured %s plugin file was not found" -msgstr "設定した %s プラグインが見つかりませんでした。" +msgstr "設定された[%s]プラグインファイルが見つかりませんでした。" #: pcsx2/PluginManager.cpp:836 #, c-format msgid "The configured %s plugin file is not a valid dynamic library" -msgstr "設定した %s プラグインは有効なダイナミックライブラリではありません。" +msgstr "設定された[%s]プラグインファイルは無効なDLLです。" #: pcsx2/PluginManager.cpp:854 #, c-format @@ -157,23 +157,23 @@ msgid "" "The configured %s plugin is not a PCSX2 plugin, or is for an older " "unsupported version of PCSX2." msgstr "" -"設定した %s プラグインは有効なPCSX2プラグインではありません。古いバージョン" -"か、未サポートのプラグインです。" +"設定された[%s]プラグインはPCSX2のプラグインではないか、サポートされていない古" +"いバージョンのPCSX2用のプラグインです。" #: pcsx2/PluginManager.cpp:879 msgid "" "The plugin reports that your hardware or software/drivers are not supported." msgstr "" -"このプラグインはあなたのハードウェア、またはソフトウェア/ドライバでは動作しま" -"せん。" +"ハードウェア又はソフトウェア/ドライバーがプラグインではサポートされていませ" +"ん。" #: pcsx2/PluginManager.cpp:900 msgid "" "Configured plugin is not a PCSX2 plugin, or is for an older unsupported " "version of PCSX2." msgstr "" -"Configured plugin is not a PCSX2 plugin, or is for an older unsupported " -"version of PCSX2." +"設定されたプラグインはPCSX2のプラグインではないか、サポートされていない古い" +"バージョンのPCSX2用のプラグインです。" #: pcsx2/PluginManager.cpp:926 #, c-format @@ -181,170 +181,170 @@ msgid "" "Configured %s plugin is not a valid PCSX2 plugin, or is for an older " "unsupported version of PCSX2." msgstr "" -"設定した %s プラグインは有効なPCSX2プラグインではありません。古いバージョン" -"か、未サポートのプラグインです。" +"設定された[%s]プラグインはPCSX2のプラグインではないか、サポートされていない古" +"いバージョンのPCSX2用のプラグインです。" #: pcsx2/PluginManager.cpp:1355 msgid "Internal Memorycard Plugin failed to initialize." -msgstr "内蔵メモリーカードプラグインの初期化に失敗しました。" +msgstr "内部メモリーカードプラグインが初期化に失敗しました。" #: pcsx2/PluginManager.cpp:1752 msgid "Unloaded Plugin" -msgstr "プラグインのアンインストール" +msgstr "プラグインがロードされていません。" #: pcsx2/SaveState.cpp:342 msgid "Cannot load savestate. It is of an unknown or unsupported version." msgstr "" -"ステートセーブを読み込めません。未知のバージョン、または未サポートのデータで" -"す。" +"セーブステートをロードできません。未知又はサポートされないバージョンです。" #: pcsx2/SourceLog.cpp:96 msgid "Dumps detailed information for PS2 executables (ELFs)." -msgstr "PS2実行 (ELF) ファイルの詳細情報をダンプ表示します。" +msgstr "PS2実行ファイル(ELF)の詳細情報をダンプします。" #: pcsx2/SourceLog.cpp:101 msgid "" "Logs manual protection, split blocks, and other things that might impact " "performance." msgstr "" -"手動プロテクション、分割ブロック、およびパフォーマンスに影響を及ぼす可能性の" -"ある他のソースについての情報を表示する。" +"マニュアルプロテクト、ブロック暗号などパフォーマンスに影響する事物のログを取" +"ります。" #: pcsx2/SourceLog.cpp:106 msgid "Shows the game developer's logging text (EE processor)" -msgstr "開発者向けのログ (EEプロセッサ) を表示する。" +msgstr "ゲーム開発者のロギングテキストを表示(EEプロセッサ)" #: pcsx2/SourceLog.cpp:111 msgid "Shows the game developer's logging text (IOP processor)" -msgstr "開発者向けのログ (IOPプロセッサ) を表示する。" +msgstr "ゲーム開発者のロギングテキストを表示(IOPプロセッサ)" #: pcsx2/SourceLog.cpp:116 msgid "Shows DECI2 debugging logs (EE processor)" -msgstr "DECI2 デバッグログ (EEプロセッサ) を表示" +msgstr "DECI2デバッグログを表示(EEプロセッサ)" #: pcsx2/SourceLog.cpp:145 msgid "SYSCALL and DECI2 activity." -msgstr "SYSCALL と DECI2 の動作" +msgstr "SYSCALLとDECI2のアクティビティ。" #: pcsx2/SourceLog.cpp:151 msgid "Direct memory accesses to unknown or unmapped EE memory space." -msgstr "" -"EE メモリマップの未知の領域、またはマッピングされていないアドレスへのダイレク" -"トメモリアクセス。" +msgstr "未知又はマップされていないEEメモリに対するDMA。" #: pcsx2/SourceLog.cpp:157 pcsx2/SourceLog.cpp:276 msgid "Disasm of executing core instructions (excluding COPs and CACHE)." -msgstr "コア命令を逆アセンブルする(COPSとキャッシュを除く)。" +msgstr "実行コア命令ディスアセンブラ(COPやキャッシュ以外)。" #: pcsx2/SourceLog.cpp:163 msgid "Disasm of COP0 instructions (MMU, cpu and dma status, etc)." -msgstr "COP 命令を逆アセンブル (MMU、CPU、DMAステータスなど)" +msgstr "COP0命令のディスアセンブラ(MMU、CPU、DMAステータス等)。" #: pcsx2/SourceLog.cpp:169 msgid "Disasm of the EE's floating point unit (FPU) only." -msgstr "EEの浮動小数点演算ユニット (FPU) のみ逆アセンブルする。" +msgstr "EEの浮動小数点演算装置(FPU)のディスアセンブラ。" #: pcsx2/SourceLog.cpp:175 msgid "Disasm of the EE's VU0macro co-processor instructions." -msgstr "EE の VU0 コプロセッサ命令を逆アセンブル" +msgstr "EEのVU0macro コプロセッサ命令のディスアセンブラ。" #: pcsx2/SourceLog.cpp:181 msgid "Execution of EE cache instructions." -msgstr "EE キャッシュ命令を実行。" +msgstr "EEキャッシュの命令実行。" #: pcsx2/SourceLog.cpp:187 msgid "" "All known hardware register accesses (very slow!); not including sub filter " "options below." msgstr "" -"全ての既知ハードウェアレジスタにアクセス(非常に低速!) ; サブフィルタオプショ" -"ン以降は含まれません。" +"既知の全てのハードウェアレジスタアクセス(鈍速!)下のサブフィルタオプションは" +"含まない。" #: pcsx2/SourceLog.cpp:193 pcsx2/SourceLog.cpp:294 msgid "Logs only unknown, unmapped, or unimplemented register accesses." -msgstr "未知か、未実装か、レジスタアクセスが実装されていない物のログ。" +msgstr "" +"マップされていない、導入されていない、不明なレジスタアクセスのみログをとる。" #: pcsx2/SourceLog.cpp:199 pcsx2/SourceLog.cpp:300 msgid "Logs only DMA-related registers." -msgstr "DMA関連のレジスタのみログ。" +msgstr "DMA関係のレジスタのみログをとる。" #: pcsx2/SourceLog.cpp:205 msgid "IPU activity: hardware registers, decoding operations, DMA status, etc." msgstr "" -"IPUアクティビティ:ハードウェアレジスタ、デコード操作、DMAステータスなど" +"IPUアクティビティ:ハードウェアレジスタ、デコードオペレーション、DMAステータ" +"ス等。" #: pcsx2/SourceLog.cpp:211 msgid "All GIFtag parse activity; path index, tag type, etc." -msgstr "全ての GIFtag 解析アクティビティ ; パス、インデックス、タグタイプなど" +msgstr "全てのGIFtag parseアクティビティ(path index、tag type、等)。" #: pcsx2/SourceLog.cpp:217 msgid "All VIFcode processing; command, tag style, interrupts." -msgstr "全ての VIFコード処理 ; コマンド、タグスタイル、割り込みなど" +msgstr "全てのVIFcode プロセシング(command, tag style, interrupts)。" #: pcsx2/SourceLog.cpp:223 msgid "All processing involved in Path3 Masking" -msgstr "Path3 マスキング関係する全ての処理" +msgstr "Path3 Maskingに携わる全てのプロセシング。" #: pcsx2/SourceLog.cpp:229 msgid "Scratchpad's MFIFO activity." -msgstr "スクラッチパッドの MFIFO アクティビティ" +msgstr "Scratchpad's MFIFO アクティビティ。" #: pcsx2/SourceLog.cpp:235 msgid "Actual data transfer logs, bus right arbitration, stalls, etc." -msgstr "バス調停権やストールなどの実際のデータ転送ログ" +msgstr "実データ転送ログ、バス使用権アービトレーション、ストール、等。" #: pcsx2/SourceLog.cpp:241 msgid "Tracks all EE counters events and some counter register activity." -msgstr "全ての EE カウンタイベントと、一部カウンタレジスタの動作を追跡" +msgstr "" +"EE countersイベント、Counter registerアクティビティをトラッキングする。" #: pcsx2/SourceLog.cpp:247 msgid "Dumps various VIF and VIFcode processing data." -msgstr "VIF と VIFコード処理データのダンプ " +msgstr "VIFとVIFcode プロセシングデータをダンプする。" #: pcsx2/SourceLog.cpp:253 msgid "Dumps various GIF and GIFtag parsing data." -msgstr "様々な GIF や GIFtag 解析データのダンプ" +msgstr "GIFとGIFtag パーシングのデータをダンプする。" #: pcsx2/SourceLog.cpp:264 msgid "SYSCALL and IRX activity." -msgstr "SYSCALL と IRX アクティビティ" +msgstr "SYSCALLとIRXのアクティビティ。" #: pcsx2/SourceLog.cpp:270 msgid "Direct memory accesses to unknown or unmapped IOP memory space." -msgstr "" -"IOP メモリマップの未知の領域、またはマッピングされていないアドレスへのダイレ" -"クトメモリアクセス。" +msgstr "未知又はマップされていないIOPメモリに対するDMA。" #: pcsx2/SourceLog.cpp:282 msgid "Disasm of the IOP's GPU co-processor instructions." -msgstr "IOP の GPU コプロセッサ命令の逆アセンブル。" +msgstr "IOPのGPUコプロセッサ命令のディスアセンブラ。" #: pcsx2/SourceLog.cpp:288 msgid "" "All known hardware register accesses, not including the sub-filters below." msgstr "" -"サブフィルタオプション以降は含めない、全ての既知ハードウェアレジスタにアクセ" -"ス" +"既知の全てのハードウェアレジスタアクセス(下のサブフィルタオプションは含まな" +"い)。" #: pcsx2/SourceLog.cpp:306 msgid "Memorycard reads, writes, erases, terminators, and other processing." -msgstr "メモリーカードの読み込み、書き込み、消去、ターミネイトその他の処理" +msgstr "" +"メモリーカードの読み込み、書き込み、消去、終止、及びその他プロセシング。" #: pcsx2/SourceLog.cpp:312 msgid "Gamepad activity on the SIO." -msgstr "SIO上でゲームパッドの有効化" +msgstr "SIOにおけるゲームパッドアクティビティ。" #: pcsx2/SourceLog.cpp:318 msgid "Actual DMA event processing and data transfer logs." -msgstr "実際の DMA イベント処理とデータ転送ログを表示" +msgstr "実DMAイベントプロセシングとデータ転送ログ。" #: pcsx2/SourceLog.cpp:324 msgid "Tracks all IOP counters events and some counter register activity." -msgstr "全ての IOP カウンタイベントと、一部カウンタレジスタの動作を追跡" +msgstr "" +"全てのIOP countersイベントとCounter registerアクティビティのトラッキング。" #: pcsx2/SourceLog.cpp:330 msgid "Detailed logging of CDVD hardware." -msgstr "CDVDハードウェアの詳細ログを表示" +msgstr "CDVDハードウェアの詳細ログ。" #: pcsx2/System.h:206 pcsx2/System.h:207 pcsx2/System.h:208 msgid "PCSX2 Message" @@ -355,16 +355,16 @@ msgid "" "The savestate was not properly saved. The temporary file was created " "successfully but could not be moved to its final resting place." msgstr "" -"ステートセーブを保存できませんでした。一時ファイルは正常に作成されましたが、" -"データの保存ができませんでした。" +"セーブステートが正常に保存されませんでした。一時ファイルの作成は成功しました" +"が保存先に移動できませんでした。" #: pcsx2/gui/AppConfig.cpp:842 msgid "Safest" -msgstr "最も安定" +msgstr "最も安全" #: pcsx2/gui/AppConfig.cpp:843 msgid "Safe (faster)" -msgstr "最も安定(高速)" +msgstr "安全(速め)" #: pcsx2/gui/AppConfig.cpp:844 msgid "Balanced" @@ -372,91 +372,91 @@ msgstr "バランス" #: pcsx2/gui/AppConfig.cpp:845 msgid "Aggressive" -msgstr "アグレッシブ" +msgstr "アクティブ" #: pcsx2/gui/AppConfig.cpp:846 msgid "Aggressive plus" -msgstr "アグレッシブ+" +msgstr "アクティブプラス" #: pcsx2/gui/AppConfig.cpp:847 msgid "Mostly Harmful" -msgstr "害にしかならない" +msgstr "ほぼ無益" #: pcsx2/gui/AppConfig.cpp:1007 pcsx2/gui/AppConfig.cpp:1013 msgid "Failed to overwrite existing settings file; permission was denied." -msgstr "設定ファイルの更新に失敗しました。アクセスが拒否されました。" +msgstr "既存の設定ファイルの上書きに失敗しました。権限がありません。" #: pcsx2/gui/AppCorePlugins.cpp:404 msgid "Loading PS2 system plugins..." -msgstr "PS2のシステムプラグインをロード中..." +msgstr "PS2システムのプラグインをロード中..." #: pcsx2/gui/AppInit.cpp:41 msgid "PCSX2 - SSE2 Recommended" -msgstr "PCSX2 - SSE2 を推奨" +msgstr "PCSX2 - SSE2を推奨します。" #: pcsx2/gui/AppInit.cpp:71 msgid "" "SSE extensions are not available. PCSX2 requires a cpu that supports the " "SSE instruction set." msgstr "" -"SSE拡張命令が利用できません。PCSX2はSSE命令セットをサポートするCPUが必要で" +"SSE拡張命令が存在しません。PCSX2はSSE拡張命令セットをサポートするCPUが必要で" "す。" #: pcsx2/gui/AppInit.cpp:154 msgid "PCSX2 Recompiler Error(s)" -msgstr "PCSX2 リコンパイラ エラー" +msgstr "PCSX2 リコンパイラエラー" #: pcsx2/gui/AppInit.cpp:227 msgid "All options are for the current session only and will not be saved.\n" -msgstr "全てのオプションは現在のセッション中のみ有効で保存はされません。\n" +msgstr "全てのオプションは現在のセッション中にのみ適用され、保存されません。\n" #: pcsx2/gui/AppInit.cpp:237 pcsx2/gui/AppMain.cpp:299 msgid "IsoFile" -msgstr "IsoFile" +msgstr "ISOファイル" #: pcsx2/gui/AppInit.cpp:238 msgid "displays this list of command line options" -msgstr "このリストのコマンドラインオプションを表示する" +msgstr "このリストのコマンドラインオプションを表示" #: pcsx2/gui/AppInit.cpp:239 msgid "forces the program log/console to be visible" -msgstr "ログ/コンソールを強制的に表示" +msgstr "プログラムログ/コンソールの表示を強制" #: pcsx2/gui/AppInit.cpp:240 msgid "use fullscreen GS mode" -msgstr "フルスクリーンGSモードを使用" +msgstr "GS フルスクリーンモード" #: pcsx2/gui/AppInit.cpp:241 msgid "use windowed GS mode" -msgstr "ウィンドウGSモードを使用" +msgstr "GS ウィンドウモード" #: pcsx2/gui/AppInit.cpp:243 msgid "disables display of the gui while running games" -msgstr "ゲーム実行中はGUI表示を無効化" +msgstr "ゲーム実行中はGUI非表示" #: pcsx2/gui/AppInit.cpp:244 msgid "executes an ELF image" -msgstr "ELF イメージを実行" +msgstr "ELFイメージの実行" #: pcsx2/gui/AppInit.cpp:245 msgid "boots an empty dvd tray; use to enter the PS2 system menu" -msgstr "DVD が入っていないまま起動します;PS2システムメニューを開始" +msgstr "空ディスクドライブ起動。PS2のBIOSのシステムメニューに入れる。" #: pcsx2/gui/AppInit.cpp:246 msgid "boots from the CDVD plugin (overrides IsoFile parameter)" -msgstr "CDVD プラグインから起動します(IsoFileパラメータを無視)" +msgstr "CDVDプラグインから起動する(IsoFileパラメータを無視します)" #: pcsx2/gui/AppInit.cpp:248 msgid "disables all speedhacks" -msgstr "全ての Speedhack を無効" +msgstr "スピードハックを全て無効にする" #: pcsx2/gui/AppInit.cpp:249 msgid "use the specified comma or pipe-delimited list of gamefixes." -msgstr "Gamefix をパイプやカンマで区切った範囲で使用する。" +msgstr "カンマ又はハイフンで仕分けられたゲーム修正リストを使用する。" #: pcsx2/gui/AppInit.cpp:250 msgid "disables fast booting" -msgstr "高速起動を無効" +msgstr "急速起動を無効" #: pcsx2/gui/AppInit.cpp:252 msgid "changes the configuration file path" @@ -464,26 +464,26 @@ msgstr "設定ファイルのパスを変更" #: pcsx2/gui/AppInit.cpp:253 msgid "specifies the PCSX2 configuration file to use" -msgstr "PCSX2の設定ファイルは以下を使用します。" +msgstr "PCSX2設定ファイルを指定する" #: pcsx2/gui/AppInit.cpp:254 #, c-format msgid "forces %s to start the First-time Wizard" -msgstr "強制 %s はスタートアップウィザードを実行させます。" +msgstr "初回設定ウィザードの開始を%sに強制する" #: pcsx2/gui/AppInit.cpp:255 msgid "enables portable mode operation (requires admin/root access)" -msgstr "ポータブルモードの操作を有効にする(管理者/rootの権限が必要)。" +msgstr "ポータブルモード操作を有効化(要:管理者権限/ルート権限)" #: pcsx2/gui/AppInit.cpp:259 #, c-format msgid "specify the file to use as the %s plugin" -msgstr "%s プラグインを使用するように指定する" +msgstr "[%s]プラグインとして使用するファイルを指定" #: pcsx2/gui/AppInit.cpp:307 #, c-format msgid "Plugin Override Error - %s" -msgstr "プラグインの上書きエラー - %s" +msgstr "プラグイン上書きエラー - [%s]" #: pcsx2/gui/AppInit.cpp:310 #, c-format @@ -492,30 +492,30 @@ msgid "" "valid %s plugin:\n" "\n" msgstr "" -"%s プラグインの上書きエラー! %s プラグインは存在しないか、有効なプラグインで" -"はありません。\n" +"[%s]プラグイン上書きエラー。次のファイルは存在しないか無効な[%s]プラグインで" +"す:\n" "\n" #: pcsx2/gui/AppInit.cpp:317 #, c-format msgid "Press OK to use the default configured plugin, or Cancel to close %s." msgstr "" -"OK を押してデフォルトのプラグインを使用するか、キャンセルを押して%sを閉じてく" -"ださい。" +"OKを押してデフォルトプラグインを使用するか、キャンセルを押して%sを閉じて下さ" +"い。" #: pcsx2/gui/AppInit.cpp:496 msgid "PCSX2 Error: Hardware Deficiency" -msgstr "PCSX2 エラー:要求するハードウェアの基準を満たしていません" +msgstr "PCSX2エラー: ハードウェア構成は最低基準を満たしていません。" #: pcsx2/gui/AppInit.cpp:496 pcsx2/gui/AppInit.cpp:508 #, c-format msgid "Press OK to close %s." -msgstr "OKを押して%sを閉じます。" +msgstr "OKを押して%sを閉じて下さい。" #: pcsx2/gui/AppInit.cpp:509 #, c-format msgid "%s Critical Error" -msgstr "%s の重大なエラー" +msgstr "%s 重大なエラー" #: pcsx2/gui/AppInit.cpp:679 msgid "OK" @@ -523,7 +523,7 @@ msgstr "OK" #: pcsx2/gui/AppInit.cpp:680 msgid "&OK" -msgstr "OK(&O)" +msgstr "OK" #: pcsx2/gui/AppInit.cpp:681 msgid "Cancel" @@ -531,7 +531,7 @@ msgstr "キャンセル" #: pcsx2/gui/AppInit.cpp:682 msgid "&Cancel" -msgstr "キャンセル(&C)" +msgstr "キャンセル" #: pcsx2/gui/AppInit.cpp:683 msgid "&Apply" @@ -539,7 +539,7 @@ msgstr "適用(&A)" #: pcsx2/gui/AppInit.cpp:684 msgid "&Next >" -msgstr "次へ>(&N)" +msgstr "次へ(&N)>" #: pcsx2/gui/AppInit.cpp:685 msgid "< &Back" @@ -547,19 +547,19 @@ msgstr "<戻る(&B)" #: pcsx2/gui/AppInit.cpp:686 msgid "&Back" -msgstr "戻る(&B)" +msgstr "戻る" #: pcsx2/gui/AppInit.cpp:687 msgid "&Finish" -msgstr "完了(&F)" +msgstr "完了" #: pcsx2/gui/AppInit.cpp:688 msgid "&Yes" -msgstr "はい(&Y)" +msgstr "はい" #: pcsx2/gui/AppInit.cpp:689 msgid "&No" -msgstr "いいえ(&N)" +msgstr "いいえ" #: pcsx2/gui/AppInit.cpp:690 msgid "Browse" @@ -567,11 +567,11 @@ msgstr "参照" #: pcsx2/gui/AppInit.cpp:691 msgid "&Save" -msgstr "保存(&S)" +msgstr "セーブ(S)" #: pcsx2/gui/AppInit.cpp:692 msgid "Save &As..." -msgstr "名前を付けて保存(&A)..." +msgstr "名前をつけて保存(&A)..." #: pcsx2/gui/AppInit.cpp:693 msgid "&Help" @@ -583,7 +583,7 @@ msgstr "ホーム(&H)" #: pcsx2/gui/AppInit.cpp:696 msgid "Show about dialog" -msgstr "アバウトダイアログを表示します" +msgstr "PCSX2についてを表示する" #: pcsx2/gui/AppMain.cpp:87 msgid "" @@ -593,31 +593,31 @@ msgid "" msgstr "" "\n" "\n" -"OK を押してプラグイン設定パネルを開いてください。" +"OKを押してプラグイン設定画面に移動します。" #: pcsx2/gui/AppMain.cpp:140 pcsx2/gui/AppMain.cpp:154 msgid "" "Warning! System plugins have not been loaded. PCSX2 may be inoperable." msgstr "" -"警告!システムプラグインが読み込まれていないため、PCSX2が動作しなくなる可能性" -"があります。" +"警告: システムプラグインがロードされませんでした。PCSX2を実行できないかもし" +"れません。" #: pcsx2/gui/AppMain.cpp:309 #, c-format msgid "%s Commandline Options" -msgstr "%s コマンドラインオプション" +msgstr "%s コマンドラインオプション" #: pcsx2/gui/AppMain.cpp:573 msgid "PS2 BIOS Error" -msgstr "PS2 BIOS エラー" +msgstr "PS2BIOSエラー" #: pcsx2/gui/AppMain.cpp:574 msgid "Press Ok to go to the BIOS Configuration Panel." -msgstr "OK を押してBIOS設定に移動してください。" +msgstr "OKを押してBIOS設定画面に移動します。" #: pcsx2/gui/AppMain.cpp:626 msgid "PCSX2 Unresponsive Thread" -msgstr "PCSX2 スレッドが応答しません" +msgstr "PCSX2 スレッドの応答がありません" #: pcsx2/gui/AppMain.cpp:636 msgid "Terminate" @@ -625,11 +625,11 @@ msgstr "終了" #: pcsx2/gui/AppMain.cpp:963 msgid "Executing PS2 Virtual Machine..." -msgstr "PS2仮想マシンを実行します..." +msgstr "PS2仮想マシン実行中..." #: pcsx2/gui/AppRes.cpp:72 msgid "Browse for an Iso that is not in your recent history." -msgstr "最近使ったISOファイルを参照します。" +msgstr "ISOイメージを参照します。" #: pcsx2/gui/AppRes.cpp:72 msgid "Browse..." @@ -637,11 +637,11 @@ msgstr "参照..." #: pcsx2/gui/AppUserMode.cpp:99 msgid "The following folders exist, but are not writable:" -msgstr "以下のフォルダは存在していますが、書き込みができません:" +msgstr "次のフォルダはありましたが、書き込み権限が不足しています:" #: pcsx2/gui/AppUserMode.cpp:104 msgid "The following folders are missing and cannot be created:" -msgstr "以下のフォルダは見つからず、作成することができません:" +msgstr "次のフォルダがありません、作成する事もできません:" #: pcsx2/gui/AppUserMode.cpp:144 #, c-format @@ -653,167 +653,170 @@ msgid "" "PCSX2 has been installed as a portable application but cannot run due to the " "following errors:" msgstr "" -"PCSX2はポータブルモードでインストールされていますが、以下のエラーのため実行す" -"ることができません:" +"PCSX2はポータブルアプリケーションとしてインストールされましたが、次に掲げる理" +"由により実行する事ができません:" #: pcsx2/gui/AppUserMode.cpp:165 msgid "Switch to User Documents Mode" -msgstr "ユーザードキュメントモードに切り替え" +msgstr "ユーザドキュメントモードに切り替える" #: pcsx2/gui/AppUserMode.cpp:178 #, c-format msgid "%s is switching to local install mode." -msgstr "%s をローカルインストールモードに切り替えます。" +msgstr "%sはローカルインストールモードに切り替ります。" #: pcsx2/gui/AppUserMode.cpp:179 msgid "" "Try to remove the file called \"portable.ini\" from your installation " "directory manually." -msgstr "\"portable.ini\" というファイルを手動で削除してみてください。" +msgstr "" +"インストールした場所から\"portable.ini\"ファイルを手動で除去してみて下さい。" #: pcsx2/gui/ApplyState.h:55 msgid "Cannot apply new settings, one of the settings is invalid." -msgstr "設定を適用できません。いくつかの設定が無効です。" +msgstr "新規の設定を適用する事ができません、無効な設定があります。" #: pcsx2/gui/ConsoleLogger.cpp:120 msgid "Save log question" -msgstr "ログの問題を保存" +msgstr "ログのセーブ" #: pcsx2/gui/ConsoleLogger.cpp:413 msgid "Fits a lot of log in a microcosmically small area." -msgstr "小スペースに大量のログを表示します。" +msgstr "沢山のログを蚤より果てしなく小さなエリアに収められる。" #: pcsx2/gui/ConsoleLogger.cpp:413 msgid "Small" -msgstr "小さく" +msgstr "小" #: pcsx2/gui/ConsoleLogger.cpp:415 msgid "It's what I use (the programmer guy)." -msgstr "それは私(プログラマたち)が使用します。" +msgstr "私が使ってる奴だ(byプログラマの人)。" #: pcsx2/gui/ConsoleLogger.cpp:415 pcsx2/gui/Panels/CpuPanel.cpp:38 msgid "Normal" -msgstr "通常" +msgstr "Normal" #: pcsx2/gui/ConsoleLogger.cpp:417 msgid "Its nice and readable." -msgstr "読みやすくてナイスです。" +msgstr "きれいで読みやすい。" #: pcsx2/gui/ConsoleLogger.cpp:417 msgid "Large" -msgstr "大きく" +msgstr "大" #: pcsx2/gui/ConsoleLogger.cpp:419 msgid "Huge" -msgstr "巨大に" +msgstr "特大" #: pcsx2/gui/ConsoleLogger.cpp:419 msgid "In case you have a really high res display." -msgstr "非常に高い解像度にした場合。" +msgstr "メガ高解像度なディスプレイを持っている人用。" #: pcsx2/gui/ConsoleLogger.cpp:423 msgid "Default soft-tone color scheme." -msgstr "デフォルトのソフトな配色。" +msgstr "デフォルトのソフトトーンカラースキーム。" #: pcsx2/gui/ConsoleLogger.cpp:423 msgid "Light theme" -msgstr "明るいテーマ" +msgstr "ライトテーマ" #: pcsx2/gui/ConsoleLogger.cpp:424 msgid "" "Classic black color scheme for people who enjoy having text seared into " "their optic nerves." -msgstr "クラシックな黒い配色。文字を見えやすくしたい場合などに。" +msgstr "" +"クラシックブラックカラースキーム、テキストを視神経に焼き付けられるのが大好き" +"な人用。" #: pcsx2/gui/ConsoleLogger.cpp:424 msgid "Dark theme" -msgstr "暗いテーマ" +msgstr "ダークテーマ" #: pcsx2/gui/ConsoleLogger.cpp:427 msgid "Always on Top" -msgstr "常に前面に表示" +msgstr "常に最前面" #: pcsx2/gui/ConsoleLogger.cpp:428 msgid "" "When checked the log window will be visible over other foreground windows." -msgstr "チェックするとログウィンドウを常に手前に表示します。" +msgstr "チェックを入れるとログウィンドウは最前面に表示されます。" #: pcsx2/gui/ConsoleLogger.cpp:430 msgid "&Save..." -msgstr "保存(&S)..." +msgstr "保存..." #: pcsx2/gui/ConsoleLogger.cpp:430 msgid "Save log contents to file" -msgstr "ログの内容を保存" +msgstr "ログ内容をファイルに保存" #: pcsx2/gui/ConsoleLogger.cpp:431 msgid "C&lear" -msgstr "クリア(&L)" +msgstr "クリア" #: pcsx2/gui/ConsoleLogger.cpp:431 msgid "Clear the log window contents" -msgstr "ログウィンドウの内容を消去" +msgstr "ログウィンドウの内容をクリア" #: pcsx2/gui/ConsoleLogger.cpp:433 pcsx2/gui/Dialogs/SysConfigDialog.cpp:280 msgid "Appearance" -msgstr "アピアランス" +msgstr "外観テーマ" #: pcsx2/gui/ConsoleLogger.cpp:435 msgid "&Close" -msgstr "閉じる(&C)" +msgstr "閉じる" #: pcsx2/gui/ConsoleLogger.cpp:435 msgid "Close this log window; contents are preserved" -msgstr "ログウィンドウを閉じます。内容は保持されます。" +msgstr "ログウィンドウを閉じる(内容は保たれます)。" #: pcsx2/gui/ConsoleLogger.cpp:439 msgid "Dev/Verbose" -msgstr "開発用/詳細" +msgstr "開発者詳細表示" #: pcsx2/gui/ConsoleLogger.cpp:439 msgid "Shows PCSX2 developer logs" -msgstr "PCSX2開発者向けログを表示" +msgstr "PCSX2開発者のログを表示" #: pcsx2/gui/ConsoleLogger.cpp:440 msgid "CDVD reads" -msgstr "CDVDのリード" +msgstr "CDVD読み込み" #: pcsx2/gui/ConsoleLogger.cpp:440 msgid "Shows disk read activity" -msgstr "ディスク読み込み動作を表示" +msgstr "ディスク読み込みアクティビティを表示" #: pcsx2/gui/ConsoleLogger.cpp:457 msgid "Enable all" -msgstr "すべてを有効" +msgstr "全て有効化" #: pcsx2/gui/ConsoleLogger.cpp:457 msgid "Enables all log source filters." -msgstr "全てのログソースフィルタを有効" +msgstr "全てのログソースフィルタを有効にします。" #: pcsx2/gui/ConsoleLogger.cpp:458 msgid "Disable all" -msgstr "すべてを無効" +msgstr "全て無効化" #: pcsx2/gui/ConsoleLogger.cpp:458 msgid "Disables all log source filters." -msgstr "全てのログソースフィルタを無効" +msgstr "全てのログソースフィルタを無効にします。" #: pcsx2/gui/ConsoleLogger.cpp:460 msgid "&Log" -msgstr "ログ(&L)" +msgstr "ログ" #: pcsx2/gui/ConsoleLogger.cpp:461 msgid "&Sources" -msgstr "ソース(&S)" +msgstr "ソース" #: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:35 #, c-format msgid "About %s" -msgstr "%s について" +msgstr "%sについて" #: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:55 msgid "Betatesting" -msgstr "ベータテスタ" +msgstr "ベータテスター" #: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:55 msgid "Previous versions" @@ -825,15 +828,15 @@ msgstr "ウェブマスター" #: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:66 msgid "Plugin Specialists" -msgstr "プラグインのスペシャリスト" +msgstr "プラグインスペシャリスト" #: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:66 msgid "Special thanks to" -msgstr "スペシャルサンクス" +msgstr "多謝" #: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:82 msgid "Developers" -msgstr "開発者" +msgstr "開発陣" #: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:84 msgid "Contributors" @@ -841,52 +844,53 @@ msgstr "貢献者" #: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:98 msgid "A Playstation 2 Emulator" -msgstr "Playstation 2 エミュレータ" +msgstr "プレイステーション2 エミュレータ" #: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:102 msgid "PCSX2 Official Website and Forums" -msgstr "PCSX2 公式サイト & フォーラム" +msgstr "PCSX2公式ウェブサイトとフォーラム" #: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:106 msgid "PCSX2 Official Svn Repository at Googlecode" -msgstr "PCSX2 公式 SVN リポジトリ (Googlecode)" +msgstr "PCSX2公式SVNレポジトリ - グーグルコード" #: pcsx2/gui/Dialogs/AboutBoxDialog.cpp:110 msgid "I've seen enough" -msgstr "十分に見たよ" +msgstr "十分にみました" #: pcsx2/gui/Dialogs/AssertionDialog.cpp:23 msgid "Assertion Failure - " -msgstr "アサーションの失敗 -" +msgstr "表明違反 - " #: pcsx2/gui/Dialogs/BaseConfigurationDialog.cpp:193 msgid "Saves a snapshot of this settings panel to a PNG file." -msgstr "この設定画面のスナップショットをPNGファイルで保存" +msgstr "表示している設定画面のスナップショットをPNG形式で保存します。" #: pcsx2/gui/Dialogs/BaseConfigurationDialog.cpp:308 msgid "Save dialog screenshots to..." -msgstr "スナップショットの保存ダイアログ..." +msgstr "スナップショットを保存する..." #: pcsx2/gui/Dialogs/BiosSelectorDialog.cpp:31 msgid "BIOS Selector" -msgstr "BIOS セレクタ" +msgstr "BIOS選択" #: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:193 msgid "Do not show this dialog again." -msgstr "再びこのダイアログを表示しない" +msgstr "今後、このメッセージを表示しない。" #: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:199 msgid "" "Disables this popup and whatever response you select here will be " "automatically used from now on." -msgstr "このポップアップを無効にして、どのような動作にするか指定してください。" +msgstr "" +"このポップアップを無効にし、ここで選択したオプションは今後自動的に適用されま" +"す。" #: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:201 msgid "" "The popup will not be shown again. This setting can be undone from the " "settings panels." -msgstr "" -"このポップアップは表示されなくなります。この設定は設定パネルで元に戻せます。" +msgstr "ポップアップは今後表示されません。設定パネルで元に戻す事ができます。" #: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:247 #: pcsx2/gui/Dialogs/ConfirmationDialogs.cpp:292 @@ -899,7 +903,7 @@ msgstr "リセット" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:40 msgid "Create a new memory card" -msgstr "メモリカードの新規作成" +msgstr "メモリーカードを新規作成" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:59 #: pcsx2/gui/Panels/DirPickerPanel.cpp:74 @@ -909,101 +913,100 @@ msgstr "作成" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:71 msgid "New memory card:" -msgstr "新規メモリカード名:" +msgstr "新規メモリーカード:" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:72 msgid "At folder: " -msgstr "フォルダ:" +msgstr "保存先:" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:75 msgid "Select file name: " -msgstr "メモリカード名:" +msgstr "ファイル名:" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:149 #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:855 #, c-format msgid "Error (%s)" -msgstr "エラーです (%s)" +msgstr "エラー (%s)" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:150 #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:164 msgid "Create memory card" -msgstr "メモリーカードの新規作成" +msgstr "メモリーカードの作成" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:163 msgid "Error: The memory card could not be created." -msgstr "エラー:メモリーカードは作成できませんでした。" +msgstr "エラー: メモリーカードの作成ができませんでした。" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:177 msgid "Use NTFS compression when creating this card." -msgstr "このカードにNTFS圧縮を利用する" +msgstr "NTFS圧縮を利用して作成する。" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:195 msgid "8 MB [most compatible]" -msgstr "8 MB [最も互換性が高い]" +msgstr "8MB [最上位の互換性]" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:195 msgid "" "This is the standard Sony-provisioned size, and is supported by all games " "and BIOS versions." -msgstr "" -"SONY製の標準的なメモリサイズ。全てのゲームとBIOSでサポートされています。" +msgstr "ソニー純正サイズで全てのゲームとBIOSバージョンでサポートされています。" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:196 msgid "" "Always use this option if you want the safest and surest memory card " "behavior." msgstr "" -"メモリカードの最も安全で確実な動作を望むなら、このオプションを使用してくださ" -"い。" +"最も確実で安全なメモリーカードの挙動を求めるならば、このオプションを必ず選択" +"して下さい。" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:199 msgid "16 MB" -msgstr "16 MB" +msgstr "16MB" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:199 #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:203 msgid "" "A typical size for 3rd-party memory cards which should work with most games." msgstr "" -"サードパーティ製の一般的なメモリサイズ。ほとんどのゲームで動作するはずです。" +"サードパーティー製メモリーカードでよくあるサイズです、ほとんどのゲームで問題" +"無く動作します。" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:200 #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:204 msgid "16 and 32 MB cards have roughly the same compatibility factor." -msgstr "16 MB と 32 MB のメモリーカードの互換性は同等程度です。" +msgstr "16MB、32MBカードは同程度の互換性能を有します。" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:203 msgid "32 MB" -msgstr "32 MB" +msgstr "32MB" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:207 msgid "64 MB" -msgstr "64 MB" +msgstr "64MB" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:207 msgid "" "Low compatibility warning: Yes it's very big, but may not work with many " "games." -msgstr "" -"低互換性の警告:とても大きいメモリサイズですが、多くのゲームで動作しない可能" -"性があります。" +msgstr "互換性警告:確かに大容量ですが、一部のゲームにしか使用できません。" #: pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp:208 msgid "" "Use at your own risk. Erratic memory card behavior is possible (though " "unlikely)." msgstr "" -"不安定なメモリーカードの使用は自己責任でお願いします(運がよければ大丈夫)。" +"自己責任で使用して下さい。メモリーカードの誤作動は可能性としてあります(ほと" +"んど無いですが)。" #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:47 #, c-format msgid "Select a folder for %s settings" -msgstr "%s の設定用のフォルダを選択" +msgstr "%s設定の保存先フォルダを指定して下さい" #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:47 msgid "Settings" -msgstr "設定" +msgstr "フォルダ設定" #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:81 msgid "Language selector" @@ -1014,25 +1017,25 @@ msgid "" "Change the language only if you need to.\n" "The system default should be fine for most operating systems." msgstr "" -"必要であれば言語を変更してください。\n" -"通常であれば System Default で構いません。" +"言語の変更が必要な場合は選択して下さい。\n" +"通常は「System Default」のままでかまいません。" #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:90 msgid "Welcome to PCSX2!" -msgstr "PCSX2にようこそ!" +msgstr "PCSX2へようこそ!" #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:104 msgid "Configuration Guides (online)" -msgstr "構成ガイド(オンライン)" +msgstr "設定ガイド集(オンライン)" #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:108 msgid "Readme / FAQ (Offline/PDF)" -msgstr "Readme / FAQ (オフライン/PDF)" +msgstr "Readme / FAQ (オフライン / PDF)" #: pcsx2/gui/Dialogs/FirstTimeWizard.cpp:117 #, c-format msgid "%s First Time Configuration" -msgstr "%s スタートアップウィザード" +msgstr "%s初回起動設定" #: pcsx2/gui/Dialogs/GameDatabaseDialog.cpp:24 #, c-format @@ -1041,7 +1044,7 @@ msgstr "ゲームデータベース - %s" #: pcsx2/gui/Dialogs/ImportSettingsDialog.cpp:24 msgid "Import Existing Settings?" -msgstr "既存の設定を読み込みますか?" +msgstr "既存の設定をインポートしますか?" #: pcsx2/gui/Dialogs/ImportSettingsDialog.cpp:39 msgid "Import" @@ -1057,15 +1060,15 @@ msgstr "トレースログ" #: pcsx2/gui/Dialogs/McdConfigDialog.cpp:40 msgid "Auto-eject memory cards when loading savestates" -msgstr "ステートセーブ読み込み時にメモリカードを自動で取り出す" +msgstr "セーブステートをロードする時にメモリーカードを自動的に取り出す" #: pcsx2/gui/Dialogs/McdConfigDialog.cpp:96 msgid "MemoryCard Manager" -msgstr "メモリカードマネージャ" +msgstr "メモリーカードマネージャ" #: pcsx2/gui/Dialogs/McdConfigDialog.cpp:112 msgid "Drag cards to or from PS2-ports" -msgstr "カードをPS2ポートにドラッグしてください。" +msgstr "メモリーカードをドラッグ&ドロップで操作できます。" #: pcsx2/gui/Dialogs/McdConfigDialog.cpp:113 msgid "" @@ -1073,28 +1076,29 @@ msgid "" "Note: Duplicate/Rename/Create/Delete will NOT be reverted with 'Cancel'." msgstr "" "\n" -"注意:複製/名称変更/作成/削除はキャンセルで戻せません。" +"メモ: 複製、名前の変更、作成、削除などの操作は「キャンセル」を押しても復旧し" +"ません。" #: pcsx2/gui/Dialogs/PickUserModeDialog.cpp:24 msgid "PCSX2 First Time configuration" -msgstr "PCSX2 初期設定" +msgstr "PCSX2初回起動設定" #: pcsx2/gui/Dialogs/PickUserModeDialog.cpp:29 #, c-format msgid "%s is starting from a new or unknown folder and needs to be configured." -msgstr "%s を新規/未知のフォルダで始める場合、設定をする必要があります。" +msgstr "%sは別の又は未知のフォルダから起動しています、設定する必要があります。" #: pcsx2/gui/Dialogs/StuckThreadDialog.cpp:28 msgid "PCSX2 Thread is not responding" -msgstr "PCSX2 スレッドが応答しません。" +msgstr "PCSX2スレッドの応答がありません。" #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:36 msgid "Config Overrides Warning" -msgstr "上書きの警告を設定" +msgstr "通常設定無効化警告" #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:56 msgid "Components Overrides Warning" -msgstr "コンポーネントの上書き警告" +msgstr "コンポーネント設定無視状態警告" #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:147 msgid "Preset:" @@ -1103,7 +1107,7 @@ msgstr "プリセット:" #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:228 #, c-format msgid "Emulation Settings - %s" -msgstr "エミュレーション設定 - %s" +msgstr "エムレーション設定 - %s" #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:237 msgid "EE/IOP" @@ -1111,7 +1115,7 @@ msgstr "EE/IOP" #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:238 msgid "VUs" -msgstr "VUs" +msgstr "VU" #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:239 msgid "GS" @@ -1119,20 +1123,20 @@ msgstr "GS" #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:240 msgid "GS Window" -msgstr "GS ウィンドウ" +msgstr "GSウィンドウ" #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:241 msgid "Speedhacks" -msgstr "Speedhack" +msgstr "スピードハック" #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:242 msgid "Game Fixes" -msgstr "Gamefix" +msgstr "ゲーム修正" #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:253 #, c-format msgid "Components Selectors - %s" -msgstr "コンポーネントの選択 - %s" +msgstr "コンポーネント選択 - %s" #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:260 msgid "Plugins" @@ -1144,77 +1148,77 @@ msgstr "BIOS" #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:262 msgid "Folders" -msgstr "フォルダ" +msgstr "フォルダ管理" #: pcsx2/gui/Dialogs/SysConfigDialog.cpp:273 #, c-format msgid "Appearance/Themes - %s" -msgstr "アピアランス/テーマ - %s" +msgstr "外観テーマ - %s" #: pcsx2/gui/ExecutorThread.cpp:40 msgid "Logs events as they are passed to the PS2 virtual machine." -msgstr "PS2 仮想マシンに渡されてからイベントを記録します。" +msgstr "PS2仮想マシンに送られるイベントのログ" #: pcsx2/gui/ExecutorThread.cpp:430 msgid "Press Cancel to attempt to cancel the action." -msgstr "キャンセルを押して操作をキャンセルします。" +msgstr "キャンセルを押して現在のこの操作をキャンセルします" #: pcsx2/gui/ExecutorThread.cpp:431 #, c-format msgid "Press Terminate to kill %s immediately." -msgstr "終了を押して%sを終わらせます。" +msgstr "終了を押して%sを強制終了します。" #: pcsx2/gui/ExecutorThread.cpp:434 msgid "Terminate App" -msgstr "終了させるアプリケーション" +msgstr "アプリケーションの終了" #: pcsx2/gui/FrameForGS.cpp:384 msgid "GS Output is Disabled!" -msgstr "GS出力が無効です!" +msgstr "GS出力は無効です!" #: pcsx2/gui/GlobalCommands.cpp:387 pcsx2/gui/MainFrame.cpp:414 msgid "Save state" -msgstr "ステートセーブ" +msgstr "セーブステート" #: pcsx2/gui/GlobalCommands.cpp:388 msgid "Saves the virtual machine state to the current slot." -msgstr "現在のスロットにステートセーブを保存します。" +msgstr "仮想マシンステートを選択スロットにセーブします" #: pcsx2/gui/GlobalCommands.cpp:393 pcsx2/gui/MainFrame.cpp:413 msgid "Load state" -msgstr "ステートロード" +msgstr "ロードステート" #: pcsx2/gui/GlobalCommands.cpp:394 msgid "Loads a virtual machine state from the current slot." -msgstr "現在のスロットからステートセーブを読み込みます。" +msgstr "仮想マシンステートを選択スロットからロードします。" #: pcsx2/gui/GlobalCommands.cpp:399 msgid "Load State Backup" -msgstr "ステートセーブ(バックアップ)をロード" +msgstr "ロードバックアップステート" #: pcsx2/gui/GlobalCommands.cpp:400 msgid "Loads virtual machine state backup for current slot." -msgstr "現在のスロットからバックアップのステートセーブをロードする。" +msgstr "仮想マシンステートを選択スロットのバックアップからロードします。" #: pcsx2/gui/GlobalCommands.cpp:405 msgid "Cycle to next slot" -msgstr "次のスロットへ" +msgstr "次のスロットへ進む" #: pcsx2/gui/GlobalCommands.cpp:406 msgid "Cycles the current save slot in +1 fashion!" -msgstr "ステートセーブの場所を1つ次のスロットへ移します。" +msgstr "現在のセーブスロットから+1サイクル移動します。" #: pcsx2/gui/GlobalCommands.cpp:411 msgid "Cycle to prev slot" -msgstr "前のスロットへ" +msgstr "前のスロットへ戻る" #: pcsx2/gui/GlobalCommands.cpp:412 msgid "Cycles the current save slot in -1 fashion!" -msgstr "ステートセーブの場所を1つ前のスロットへ移します。" +msgstr "現在のセーブスロットから-1サイクル移動します。" #: pcsx2/gui/IsoDropTarget.cpp:57 msgid "Drag and Drop Error" -msgstr "ドラッグ&ドロップエラー" +msgstr "ドラッグ&ドロップエラー" #: pcsx2/gui/IsoDropTarget.cpp:58 #, c-format @@ -1222,12 +1226,12 @@ msgid "" "It is an error to drop multiple files onto a %s window. One at a time " "please, thank you." msgstr "" -"%s ウィンドウに複数のファイルをドロップすることはできません。1つずつお願いし" -"ます。" +"いくつも%sウィンドウにドロップするとエラーになります。1つずつでお願いします" +"ね。" #: pcsx2/gui/IsoDropTarget.cpp:89 pcsx2/gui/MainMenuClicks.cpp:342 msgid "Confirm PS2 Reset" -msgstr "PS2 リセットの確認" +msgstr "PS2リセット確認" #: pcsx2/gui/IsoDropTarget.cpp:91 #, c-format @@ -1235,18 +1239,18 @@ msgid "" "You have dropped the following ELF binary into %s:\n" "\n" msgstr "" -"以下の ELF バイナリは欠落しています %s\n" +"次のEFLバイナリを%sにドロップしました:\n" "\n" #: pcsx2/gui/IsoDropTarget.cpp:135 #, c-format msgid "You have dropped the following ISO image into %s:" -msgstr "ISO イメージ %s は欠落しています。" +msgstr "次のISOイメージを%sにドロップしました:" #: pcsx2/gui/MainFrame.cpp:38 #, c-format msgid "Slot %d" -msgstr "スロット%d" +msgstr "スロット %d" #: pcsx2/gui/MainFrame.cpp:44 pcsx2/gui/Saveslots.cpp:150 msgid "Backup" @@ -1258,7 +1262,7 @@ msgstr "コンソールを表示" #: pcsx2/gui/MainFrame.cpp:325 msgid "Console to Stdio" -msgstr "コンソールはStdioに" +msgstr "コンソールから標準IOへ" #: pcsx2/gui/MainFrame.cpp:338 msgid "&System" @@ -1266,7 +1270,7 @@ msgstr "システム(&S)" #: pcsx2/gui/MainFrame.cpp:339 msgid "CD&VD" -msgstr "CDVD(&V)" +msgstr "CD&VD" #: pcsx2/gui/MainFrame.cpp:340 msgid "&Config" @@ -1292,7 +1296,7 @@ msgstr "%s %d.%d.%d %s" #: pcsx2/gui/MainFrame.cpp:362 msgid "(modded)" -msgstr "(修正済)" +msgstr "(改変済)" #: pcsx2/gui/MainFrame.cpp:399 pcsx2/gui/MainFrame.cpp:401 #: pcsx2/gui/MainFrame.cpp:407 @@ -1301,31 +1305,31 @@ msgstr "初期化中..." #: pcsx2/gui/MainFrame.cpp:403 msgid "Run ELF..." -msgstr "ELFファイルを開く..." +msgstr "ELF実行..." #: pcsx2/gui/MainFrame.cpp:404 msgid "For running raw PS2 binaries directly" -msgstr "PS2のrawバイナリを実行します。" +msgstr "PS2のバイナリを直接実行します" #: pcsx2/gui/MainFrame.cpp:416 msgid "Backup before save" -msgstr "バックアップしてからセーブ" +msgstr "バックアップしてセーブ" #: pcsx2/gui/MainFrame.cpp:421 msgid "Automatic Gamefixes" -msgstr "自動Gamefix" +msgstr "自動ゲーム修正" #: pcsx2/gui/MainFrame.cpp:422 msgid "Automatically applies needed Gamefixes to known problematic games" -msgstr "fixが必要なゲームに自動的に適用されます。" +msgstr "既知のゲーム修正を自動的に適用します" #: pcsx2/gui/MainFrame.cpp:424 msgid "Enable Cheats" -msgstr "チートを有効" +msgstr "チート有効化" #: pcsx2/gui/MainFrame.cpp:427 msgid "Enable Host Filesystem" -msgstr "Host Filesystemを有効" +msgstr "Host Filesystem有効化" #: pcsx2/gui/MainFrame.cpp:432 msgid "Shutdown" @@ -1333,7 +1337,7 @@ msgstr "シャットダウン" #: pcsx2/gui/MainFrame.cpp:433 msgid "Wipes all internal VM states and shuts down plugins." -msgstr "VMのデータを削除しプラグインを終了して、エミュレーションを終了します。" +msgstr "内部仮想マシンステートをクリアにしプラグインを終了します。" #: pcsx2/gui/MainFrame.cpp:435 msgid "Exit" @@ -1342,11 +1346,11 @@ msgstr "終了" #: pcsx2/gui/MainFrame.cpp:436 #, c-format msgid "Closing %s may be hazardous to your health" -msgstr "%s を終了します。" +msgstr "%sを閉じる事はあなたの健康を損なうおそれがあります" #: pcsx2/gui/MainFrame.cpp:443 msgid "Iso Selector" -msgstr "ISOファイルの選択" +msgstr "ISO選択" #: pcsx2/gui/MainFrame.cpp:444 msgid "Plugin Menu" @@ -1354,55 +1358,55 @@ msgstr "プラグインメニュー" #: pcsx2/gui/MainFrame.cpp:447 msgid "Iso" -msgstr "ISOイメージ" +msgstr "ISO" #: pcsx2/gui/MainFrame.cpp:447 msgid "Makes the specified ISO image the CDVD source." -msgstr "CDVDのISOイメージを参照します。" +msgstr "指定されたISOイメージをCDVDのソースにします。" #: pcsx2/gui/MainFrame.cpp:448 msgid "Plugin" -msgstr "プラグイン使用" +msgstr "プラグイン" #: pcsx2/gui/MainFrame.cpp:448 msgid "Uses an external plugin as the CDVD source." -msgstr "外部プラグインを使用してCDVDを参照します。" +msgstr "CDVDソースに外部プラグインを使用する。" #: pcsx2/gui/MainFrame.cpp:449 msgid "No disc" -msgstr "ディスクなし" +msgstr "ディスク無し" #: pcsx2/gui/MainFrame.cpp:449 msgid "Use this to boot into your virtual PS2's BIOS configuration." -msgstr "ディスクなしで起動して、PS2のBIOS設定を行う事ができます。" +msgstr "PS2のBIOS設定に入る時に使います。" #: pcsx2/gui/MainFrame.cpp:457 msgid "Emulation &Settings" -msgstr "エミュレーション&設定" +msgstr "エミュレーション設定(&S)" #: pcsx2/gui/MainFrame.cpp:458 msgid "&Memory cards" -msgstr "メモリカード(&M)" +msgstr "メモリーカード(&M)" #: pcsx2/gui/MainFrame.cpp:459 msgid "&Plugin/BIOS Selector" -msgstr "プラグイン/BIOS (&P)" +msgstr "プラグイン/BIOS選択(&P)" #: pcsx2/gui/MainFrame.cpp:460 pcsx2/gui/Panels/GameDatabasePanel.cpp:346 msgid "Game Database Editor" -msgstr "ゲームデーターベースエディタ" +msgstr "ゲームデータベース編集" #: pcsx2/gui/MainFrame.cpp:466 msgid "&Video (GS)" -msgstr "グラフィックス (GS)(&V)" +msgstr "ビデオ (GS) (&V)" #: pcsx2/gui/MainFrame.cpp:467 msgid "&Audio (SPU2)" -msgstr "サウンド (SPU2)(&A)" +msgstr "オーディオ (SPU2) (&A)" #: pcsx2/gui/MainFrame.cpp:468 msgid "&Controllers (PAD)" -msgstr "コントローラー (PAD)(&C)" +msgstr "コントローラ (PAD) (&C)" #: pcsx2/gui/MainFrame.cpp:469 msgid "Dev9" @@ -1418,122 +1422,121 @@ msgstr "Firewire" #: pcsx2/gui/MainFrame.cpp:477 msgid "Multitap 1" -msgstr "マルチタップ 1" +msgstr "マルチタップ 1" #: pcsx2/gui/MainFrame.cpp:478 msgid "Multitap 2" -msgstr "マルチタップ 2" +msgstr "マルチタップ 2" #: pcsx2/gui/MainFrame.cpp:481 msgid "Clear all settings..." -msgstr "全ての設定の初期化..." +msgstr "全ての設定を初期化..." #: pcsx2/gui/MainFrame.cpp:482 #, c-format msgid "Clears all %s settings and re-runs the startup wizard." -msgstr "" -"%s の全ての設定を初期化して、スタートアップウィザードからやり直します。" +msgstr "全ての%s設定を初期化し、次回起動時に初回設定ウィザードを実行します。" #: pcsx2/gui/MainFrame.cpp:504 msgid "About..." -msgstr "アバウト..." +msgstr "PCSX2について" #: pcsx2/gui/MainFrame.cpp:508 msgid "Logging..." -msgstr "ロード中..." +msgstr "ログ開始..." #: pcsx2/gui/MainFrame.cpp:585 msgid "Pause" -msgstr "一時停止" +msgstr "ポーズ" #: pcsx2/gui/MainFrame.cpp:586 msgid "Safely pauses emulation and preserves the PS2 state." -msgstr "エミュレーションを安全に一時停止しPS2の状態を保持します。" +msgstr "エミュレーションを安全に一時停止しPS2ステートを保持します。" #: pcsx2/gui/MainFrame.cpp:593 msgid "Resume" -msgstr "再開" +msgstr "レジューム" #: pcsx2/gui/MainFrame.cpp:594 msgid "Resumes the suspended emulation state." -msgstr "エミュレーションを再開します。" +msgstr "中断されたエミュレーションステートを再開します。" #: pcsx2/gui/MainFrame.cpp:598 msgid "Pause/Resume" -msgstr "一時停止/再開" +msgstr "ポーズ/レジューム" #: pcsx2/gui/MainFrame.cpp:599 msgid "No emulation state is active; cannot suspend or resume." -msgstr "エミュレータが実行されていないため、一時停止/再開はできません。" +msgstr "" +"アクティブなエミュレーションステートがありません。中断、再開ができません。" #: pcsx2/gui/MainFrame.cpp:608 msgid "Restart" -msgstr "再起動" +msgstr "リスタート" #: pcsx2/gui/MainFrame.cpp:609 msgid "Simulates hardware reset of the PS2 virtual machine." -msgstr "エミュレーションハードウェアはPS2仮想マシンをリセットします。" +msgstr "PS2仮想マシンでハードウェアリセットをシミュレートします。" #: pcsx2/gui/MainFrame.cpp:614 msgid "No emulation state is active; boot something first." msgstr "" -"エミュレーションしていないのでステートセーブはアクティブではありません。まず" -"何かを起動してください。" +"アクティブなエミュレーションステートがありません。先に何か起動して下さい。" #: pcsx2/gui/MainFrame.cpp:622 msgid "Reboot CDVD (full)" -msgstr "CDVDから再起動" +msgstr "CDVD再起動 (フル)" #: pcsx2/gui/MainFrame.cpp:623 msgid "Hard reset of the active VM." -msgstr "アクティブなVMをハードリセットを行います。" +msgstr "仮想マシンのハードリセットを行います。" #: pcsx2/gui/MainFrame.cpp:627 msgid "Boot CDVD (full)" -msgstr "CDVDから起動" +msgstr "CDVD起動 (フル)" #: pcsx2/gui/MainFrame.cpp:628 msgid "Boot the VM using the current DVD or Iso source media" -msgstr "ISOファイルまたはDVDからVMを起動します。" +msgstr "仮想マシンをDVD/ISOソースから起動します" #: pcsx2/gui/MainFrame.cpp:636 msgid "Reboot CDVD (fast)" -msgstr "CDVDから再起動(高速)" +msgstr "CDVD再起動 (急速)" #: pcsx2/gui/MainFrame.cpp:637 msgid "Reboot using fast BOOT (skips splash screens)" -msgstr "" -"高速起動でPS2仮想マシンのハードリセットを行います。(PS2のロゴをスキップ)" +msgstr "急速再起動します (スプラッシュ画面をスキップします)" #: pcsx2/gui/MainFrame.cpp:641 msgid "Boot CDVD (fast)" -msgstr "CDVDから起動(高速)" +msgstr "CDVD起動 (急速)" #: pcsx2/gui/MainFrame.cpp:642 msgid "Use fast boot to skip PS2 startup and splash screens" -msgstr "PS2のロゴをスキップして高速起動します。" +msgstr "急速起動でPS2スタートアップとスプラッシュ画面をスキップします" #: pcsx2/gui/MainFrame.cpp:703 pcsx2/gui/MainFrame.cpp:738 msgid "No plugin loaded" -msgstr "プラグインが読み込まれていません。" +msgstr "プラグインがロードされていません" #: pcsx2/gui/MainFrame.cpp:708 msgid "Core GS Settings..." -msgstr "Core GS 設定..." +msgstr "GSコア設定..." #: pcsx2/gui/MainFrame.cpp:709 msgid "" "Modify hardware emulation settings regulated by the PCSX2 core virtual " "machine." -msgstr "PCSX2のコア仮想マシンが制御しているエミュレーション設定を変更します。" +msgstr "" +"PCSX2コア仮想マシンで制御されるハードウェアエミュレーション設定の変更。" #: pcsx2/gui/MainFrame.cpp:711 msgid "Window Settings..." -msgstr "ウィンドウ設定..." +msgstr "GSウィンドウ設定..." #: pcsx2/gui/MainFrame.cpp:712 msgid "Modify window and appearance options, including aspect ratio." -msgstr "アスペクト比を含むウィンドウやアピアランスの設定を変更します。" +msgstr "アスペクト比など、ウィンドウの外観オプションを変更します。" #: pcsx2/gui/MainFrame.cpp:719 msgid "Plugin Settings..." @@ -1542,11 +1545,11 @@ msgstr "プラグイン設定..." #: pcsx2/gui/MainFrame.cpp:720 #, c-format msgid "Opens the %s plugin's advanced settings dialog." -msgstr "%s プラグインの設定ダイアログを開きます。" +msgstr "%sプラグインの詳細設定を開きます。" #: pcsx2/gui/MainMenuClicks.cpp:112 msgid "Reset all settings?" -msgstr "設定を全て初期化しますか?" +msgstr "全ての設定をリセットしますか?" #: pcsx2/gui/MainMenuClicks.cpp:140 msgid "Confirm ISO image change" @@ -1555,30 +1558,32 @@ msgstr "ISOイメージ変更の確認" #: pcsx2/gui/MainMenuClicks.cpp:146 msgid "Do you want to swap discs or boot the new image (via system reset)?" msgstr "" -"ディスクを交換または新しいイメージで起動(システムのリセットを介して)します" -"か?" +"ディスクをスワップするか、別のイメージを起動(システムはリセットされます)させ" +"ますか?" #: pcsx2/gui/MainMenuClicks.cpp:148 pcsx2/gui/MainMenuClicks.cpp:194 msgid "Swap Disc" -msgstr "ディスクの交換" +msgstr "ディスクスワップ" #: pcsx2/gui/MainMenuClicks.cpp:184 msgid "Confirm CDVD source change" -msgstr "CDVDソースの変更の確認" +msgstr "CDVDソースの変更確認" #: pcsx2/gui/MainMenuClicks.cpp:187 #, c-format msgid "You've selected to switch the CDVD source from %s to %s." -msgstr "CDVD のソースを %s から %s に切り替えます。" +msgstr "CDVDソースを[%s]から[%s]に変更されました。" #: pcsx2/gui/MainMenuClicks.cpp:191 msgid "Do you want to swap discs or boot the new image (system reset)?" -msgstr "ディスクを交換または新しいイメージで起動(システムのリセット)しますか?" +msgstr "" +"ディスクをスワップするか、別のイメージを起動(システムはリセットされます)させ" +"ますか?" #: pcsx2/gui/MainMenuClicks.cpp:261 #, c-format msgid "All Supported (%s)" -msgstr "サポートされているファイル (%s)" +msgstr "全サポート形式 (%s)" #: pcsx2/gui/MainMenuClicks.cpp:264 #, c-format @@ -1588,7 +1593,7 @@ msgstr "ディスクイメージ (%s)" #: pcsx2/gui/MainMenuClicks.cpp:267 #, c-format msgid "Blockdumps (%s)" -msgstr "ダンプファイル (%s)" +msgstr "ブロックダンプ (%s)" #: pcsx2/gui/MainMenuClicks.cpp:270 pcsx2/gui/MainMenuClicks.cpp:291 msgid "All Files (*.*)" @@ -1596,34 +1601,34 @@ msgstr "全てのファイル (*.*)" #: pcsx2/gui/MainMenuClicks.cpp:273 msgid "Select CDVD source iso..." -msgstr "ISOイメージファイルを選択してください..." +msgstr "CDVDのISOソースを選択してください..." #: pcsx2/gui/MainMenuClicks.cpp:290 msgid "Select ELF file..." -msgstr "ELFファイルを選択..." +msgstr "EFLファイルを選択して下さい..." #: pcsx2/gui/MainMenuClicks.cpp:316 msgid "ISO file not found!" -msgstr "ISOファイルが見つかりませんでした。" +msgstr "ISOファイルが見つかりません!" #: pcsx2/gui/MainMenuClicks.cpp:318 msgid "An error occurred while trying to open the file:" -msgstr "以下のファイルを開く際にエラーが発生しました:" +msgstr "ファイルを開くときに、エラーが発生しました:" #: pcsx2/gui/MainMenuClicks.cpp:319 msgid "" "Error: The configured ISO file does not exist. Click OK to select a new ISO " "source for CDVD." msgstr "" -"エラー:指定したISOファイルがみつかりません。OKを押して新たにISOファイルを指" -"定してください。" +"エラー: 指定されたISOファイルがみつかりません。OKをクリックし、CDVDのISOソー" +"スを選択して下さい。" #: pcsx2/gui/MainMenuClicks.cpp:390 msgid "" "You have selected the following ISO image into PCSX2:\n" "\n" msgstr "" -"あなたはPCSX2に以下のISOイメージを指定しています:\n" +"次のISOイメージが選択されました:\n" "\n" #: pcsx2/gui/MemoryCardFile.cpp:183 @@ -1634,7 +1639,7 @@ msgid "" "%s\n" "\n" msgstr "" -"メモリーカードを作成できませんでした:\n" +"メモリーカードの作成に失敗しました:\n" "\n" "%s\n" "\n" @@ -1647,60 +1652,58 @@ msgid "" "%s\n" "\n" msgstr "" -"メモリカードへのアクセスが拒否されました \n" -"\n" +"メモリーカードのアクセスが拒否されました:(このセッションではメモリーカードは" +"無効となります)\n" "%s\n" "\n" #: pcsx2/gui/MemoryCardFile.cpp:525 msgid "File name empty or too short" -msgstr "ファイル名が無いか小さすぎます" +msgstr "ファイル名が無いか短すぎます" #: pcsx2/gui/MemoryCardFile.cpp:530 msgid "File name outside of required directory" -msgstr "ファイル名はディレクトリの外にあります" +msgstr "ファイル名は要求されるディレクトリ外です" #: pcsx2/gui/MemoryCardFile.cpp:536 msgid "File name already exists" -msgstr "そのファイル名は既にあります" +msgstr "同じ名前のファイルが既にあります" #: pcsx2/gui/MemoryCardFile.cpp:543 msgid "The Operating-System prevents this file from being created" -msgstr "OSがこのファイルを作ることを阻止しています。" +msgstr "OSによりこのファイルを作成する事ができません" #: pcsx2/gui/Panels/BaseApplicableConfigPanel.cpp:103 msgid "Cannot apply settings..." -msgstr "設定を適用できません..." +msgstr "設定を適用する事ができません..." #: pcsx2/gui/Panels/BiosSelectorPanel.cpp:103 msgid "BIOS Search Path:" -msgstr "BIOS の場所:" +msgstr "BIOS参照パス:" #: pcsx2/gui/Panels/BiosSelectorPanel.cpp:104 msgid "Select folder with PS2 BIOS roms" -msgstr "PS2のBIOSがあるフォルダを選択してください。" +msgstr "PS2のBIOSがあるフォルダを選択して下さい" #: pcsx2/gui/Panels/BiosSelectorPanel.cpp:111 msgid "" "Click the Browse button to select a different folder where PCSX2 will look " "for PS2 BIOS roms." -msgstr "" -"PS2のBIOS romファイルが別の場所にある場合、参照ボタンを押してフォルダを指定し" -"てください。" +msgstr "参照を押してPCSX2がBIOS ROMをロードするフォルダを指定して下さい。" #: pcsx2/gui/Panels/BiosSelectorPanel.cpp:113 #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:156 #: pcsx2/gui/Panels/ThemeSelectorPanel.cpp:47 msgid "Refresh list" -msgstr "リストを更新" +msgstr "リスト更新" #: pcsx2/gui/Panels/BiosSelectorPanel.cpp:115 msgid "Select a BIOS rom:" -msgstr "BIOS を選択してください:" +msgstr "BIOS ROMを選択して下さい:" #: pcsx2/gui/Panels/CpuPanel.cpp:24 msgid "Round Mode" -msgstr "丸めモード" +msgstr "Round Mode" #: pcsx2/gui/Panels/CpuPanel.cpp:25 msgid "Clamping Mode" @@ -1708,52 +1711,52 @@ msgstr "クランプモード" #: pcsx2/gui/Panels/CpuPanel.cpp:29 msgid "Nearest" -msgstr "最も近い正規化数に" +msgstr "Nearest" #: pcsx2/gui/Panels/CpuPanel.cpp:30 msgid "Negative" -msgstr "切り捨て" +msgstr "Negative" #: pcsx2/gui/Panels/CpuPanel.cpp:31 msgid "Positive" -msgstr "切り上げ" +msgstr "Positive" #: pcsx2/gui/Panels/CpuPanel.cpp:32 msgid "Chop / Zero" -msgstr "正数切り上げ/負数切り捨て" +msgstr "Chop / Zero" #: pcsx2/gui/Panels/CpuPanel.cpp:37 msgid "None" -msgstr "なし" +msgstr "無し" #: pcsx2/gui/Panels/CpuPanel.cpp:85 msgid "EE/FPU Advanced Recompiler Options" -msgstr "EE/FPU 拡張リコンパイラオプション" +msgstr "EE/FPU リコンパイラ詳細設定" #: pcsx2/gui/Panels/CpuPanel.cpp:87 pcsx2/gui/Panels/CpuPanel.cpp:102 msgid "Extra + Preserve Sign" -msgstr "拡張+予約済み" +msgstr "Extra + Preserve Sign" #: pcsx2/gui/Panels/CpuPanel.cpp:88 msgid "Full" -msgstr "全て" +msgstr "フル" #: pcsx2/gui/Panels/CpuPanel.cpp:99 msgid "VU0 / VU1 Advanced Recompiler Options" -msgstr "VU0 / VU1 拡張リコンパイラオプション" +msgstr "VU0/VU1 リコンパイラ詳細設定" #: pcsx2/gui/Panels/CpuPanel.cpp:101 msgid "Extra" -msgstr "拡張" +msgstr "Extra" #: pcsx2/gui/Panels/CpuPanel.cpp:117 pcsx2/gui/Panels/CpuPanel.cpp:126 #: pcsx2/gui/Panels/CpuPanel.cpp:184 msgid "Interpreter" -msgstr "インタプリタ" +msgstr "インタープリタ" #: pcsx2/gui/Panels/CpuPanel.cpp:118 msgid "Quite possibly the slowest thing in the universe." -msgstr "恐らく最も低速の設定です。" +msgstr "おそらくこの宇宙の中で一番遅いものです。" #: pcsx2/gui/Panels/CpuPanel.cpp:120 pcsx2/gui/Panels/CpuPanel.cpp:129 msgid "Recompiler" @@ -1763,39 +1766,41 @@ msgstr "リコンパイラ" msgid "" "Performs just-in-time binary translation of 64-bit MIPS-IV machine code to " "x86." -msgstr "64bit MIPS-IVコードをjust-in-timeでx86コードに変換して実行。" +msgstr "" +"64-bit MIPS-IV マシンコードを x86 にバイナリトランスレーションする操作を丁度" +"間に合わせる具合に行う。" #: pcsx2/gui/Panels/CpuPanel.cpp:127 msgid "Pretty slow; provided for diagnostic purposes only." -msgstr "非常に遅い。診断用としてのみの用途。" +msgstr "結構遅い、デバッグ診断用。" #: pcsx2/gui/Panels/CpuPanel.cpp:130 msgid "" "Performs just-in-time binary translation of 32-bit MIPS-I machine code to " "x86." -msgstr "32bit MIPS-Iコードをjust-in-timeでx86コードに変換して実行。" +msgstr "" +"32-bit MIPS-I マシンコードを x86 にバイナリトランスレーションする操作を丁度間" +"に合わせる具合に行う。" #: pcsx2/gui/Panels/CpuPanel.cpp:154 -#, fuzzy msgid "Enable EE Cache (Slower)" -msgstr "EE キャッシュを有効 - インタプリタのみ(非常に低速)" +msgstr "EEキャッシュを有効にする(遅くなる)" #: pcsx2/gui/Panels/CpuPanel.cpp:154 -#, fuzzy msgid "Interpreter only; provided for diagnostic" -msgstr "非常に遅い。診断用としてのみの用途。" +msgstr "インタープリタモード専用、デバッグ用" #: pcsx2/gui/Panels/CpuPanel.cpp:170 pcsx2/gui/Panels/CpuPanel.cpp:223 #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:110 msgid "Restore Defaults" -msgstr "デフォルト設定に戻す" +msgstr "デフォルトに戻す" #: pcsx2/gui/Panels/CpuPanel.cpp:185 msgid "" "Vector Unit Interpreter. Slow and not very compatible. Only use for " "diagnostics." msgstr "" -"ベクターユニットインタプリタ。遅い上に互換性が非常に低いです。診断用途。" +"ヴェクターユニットインタープリタ。低速であまり互換性が無い。デバッグ診断用。" #: pcsx2/gui/Panels/CpuPanel.cpp:187 msgid "microVU Recompiler" @@ -1804,25 +1809,24 @@ msgstr "microVU リコンパイラ" #: pcsx2/gui/Panels/CpuPanel.cpp:188 msgid "" "New Vector Unit recompiler with much improved compatibility. Recommended." -msgstr "" -"新しいベクターユニットリコンパイラ。多くの互換性を向上させてある。推奨。" +msgstr "最新のVUリコンパイラです。互換性が改善されています。お勧め。" #: pcsx2/gui/Panels/CpuPanel.cpp:190 msgid "superVU Recompiler [legacy]" -msgstr "superVU リコンパイラ [従来の方式]" +msgstr "superVU リコンパイラ [legacy]" #: pcsx2/gui/Panels/CpuPanel.cpp:191 msgid "" "Useful for diagnosing bugs or clamping issues in the new mVU recompiler." -msgstr "バグ診断用やクランプの問題用の新しい mVU リコンパイラ。" +msgstr "microVUにおけるバグの診断やクランプ問題に役立ちます。" #: pcsx2/gui/Panels/DirPickerPanel.cpp:64 msgid "Path does not exist" -msgstr "パスが存在しません。" +msgstr "指定されたパスが見つかりません" #: pcsx2/gui/Panels/DirPickerPanel.cpp:156 msgid "Use default setting" -msgstr "デフォルトの設定を使用する" +msgstr "デフォルト設定を使う" #: pcsx2/gui/Panels/DirPickerPanel.cpp:176 msgid "Open in Explorer" @@ -1830,7 +1834,7 @@ msgstr "エクスプローラで開く" #: pcsx2/gui/Panels/DirPickerPanel.cpp:177 msgid "Open an explorer window to this folder." -msgstr "フォルダをエクスプローラで開きます" +msgstr "このフォルダをエクスプローラウィンドウで開きます。" #: pcsx2/gui/Panels/DirPickerPanel.cpp:268 msgid "Create folder?" @@ -1839,48 +1843,47 @@ msgstr "フォルダを作成しますか?" #: pcsx2/gui/Panels/DirPickerPanel.cpp:269 #, c-format msgid "A configured folder does not exist. Should %s try to create it?" -msgstr "設定したフォルダは存在しません。%s を作成しますか?" +msgstr "設定フォルダが見つかりません。%sに作成させますか?" #: pcsx2/gui/Panels/GSWindowPanel.cpp:30 msgid "Fit to Window/Screen" -msgstr "ウィンドウ/スクリーンのサイズに合わせる" +msgstr "ウィンドウに合わせて伸縮" #: pcsx2/gui/Panels/GSWindowPanel.cpp:31 msgid "Standard (4:3)" -msgstr "標準 (4:3)" +msgstr "スタンダード (4:3)" #: pcsx2/gui/Panels/GSWindowPanel.cpp:32 msgid "Widescreen (16:9)" -msgstr "ワイドスクリーン (16:9)" +msgstr "ワイドスクリーン (16:9)" #: pcsx2/gui/Panels/GSWindowPanel.cpp:46 msgid "Disable window resize border" -msgstr "ウィンドウのリサイズを無効" +msgstr "ウィンドウのリサイズを無効にする" #: pcsx2/gui/Panels/GSWindowPanel.cpp:47 msgid "Always hide mouse cursor" -msgstr "マウスカーソルを常に隠す" +msgstr "マウスポインタを非表示にする" #: pcsx2/gui/Panels/GSWindowPanel.cpp:48 msgid "Hide window when paused" -msgstr "一時停止した時にウィンドウを隠す" +msgstr "ポーズ中にウィンドウを隠す" #: pcsx2/gui/Panels/GSWindowPanel.cpp:49 msgid "Default to fullscreen mode on open" -msgstr "デフォルトでフルスクリーンで開く" +msgstr "ゲーム起動時フルスクリーン" #: pcsx2/gui/Panels/GSWindowPanel.cpp:50 msgid "Wait for Vsync on refresh" -msgstr "VSYNCと同期する" +msgstr "垂直同期 (垂直同期信号まで画面の書き換え待機します)" #: pcsx2/gui/Panels/GSWindowPanel.cpp:51 msgid "Dynamically toggle Vsync depending on frame rate (read tooltip!)" -msgstr "" -"フレームレートに応じてVSYNCを動的に切り替え(ツールTipsを読んでください)" +msgstr "動的垂直同期 (ツールチップを読んでください)" #: pcsx2/gui/Panels/GSWindowPanel.cpp:52 msgid "Double-click toggles fullscreen mode" -msgstr "ダブルクリックでフルスクリーンモードに切り替え" +msgstr "ダブルクリックでフルスクリーン切り替え" #: pcsx2/gui/Panels/GSWindowPanel.cpp:110 msgid "Aspect Ratio:" @@ -1888,17 +1891,19 @@ msgstr "アスペクト比:" #: pcsx2/gui/Panels/GSWindowPanel.cpp:112 msgid "Custom Window Size:" -msgstr "カスタムウィンドウサイズ:" +msgstr "ウィンドウサイズ指定:" #: pcsx2/gui/Panels/GSWindowPanel.cpp:115 msgid "Zoom:" -msgstr "拡大率:" +msgstr "ズーム率:" #: pcsx2/gui/Panels/GSWindowPanel.cpp:196 msgid "" "Invalid window dimensions specified: Size cannot contain non-numeric digits! " ">_<" -msgstr "無効なウィンドウサイズ:数字以外はダメです!>_<" +msgstr "" +"無効なサイズ指定です:\n" +"整数以外は入力しないで下さい! >_<" #: pcsx2/gui/Panels/GameDatabasePanel.cpp:334 msgid "Search" @@ -1907,11 +1912,11 @@ msgstr "検索" #: pcsx2/gui/Panels/GameDatabasePanel.cpp:368 #: pcsx2/gui/Panels/GameFixesPanel.cpp:25 msgid "Gamefixes" -msgstr "Gamefix" +msgstr "ゲーム修正" #: pcsx2/gui/Panels/GameFixesPanel.cpp:38 msgid "VU Add Hack - Fixes Tri-Ace games boot crash." -msgstr "VU 追加Hack - tri-Ace社のゲームの起動時のクラッシュをfix" +msgstr "VU Add Hack - トライエースブランドゲームの起動クラッシュを修正" #: pcsx2/gui/Panels/GameFixesPanel.cpp:39 msgid "" @@ -1920,27 +1925,28 @@ msgid "" " * Radiata Stories\n" " * Valkyrie Profile 2" msgstr "" -"以下のゲームの起動時に有効にしておく必要があります:\n" -" * スターオーシャン3\n" -" * ラジアータ ストーリーズ\n" -" * ヴァルキリープロファイル2" +"このハックが必要なゲーム:\n" +" * スターオーシャン3\n" +" * ヴァルキュリープロファイル2\n" +" * ラジアータストーリーズ" #: pcsx2/gui/Panels/GameFixesPanel.cpp:42 msgid "VU Clip Flag Hack - For Persona games (SuperVU recompiler only!)" msgstr "" -"VU Clip Flag の Hack - ペルソナシリーズ用 (SuperVU リコンパイラ使用時のみ)" +"VU Clip Flag Hack - ペルソナ系のゲーム用(SuperVU リコンパイラ使用の場合の" +"み)" #: pcsx2/gui/Panels/GameFixesPanel.cpp:46 msgid "FPU Compare Hack - For Digimon Rumble Arena 2." -msgstr "FPU Compare Hack - デジモンアリーナ2用" +msgstr "FPU Compare Hack - デジモンランブルアリーナ2用" #: pcsx2/gui/Panels/GameFixesPanel.cpp:50 msgid "FPU Multiply Hack - For Tales of Destiny." -msgstr "FPU Multiply Hack - テイルズ オブ デスティニー用" +msgstr "FPU Multiply Hack - テイルズオブデスティニー用" #: pcsx2/gui/Panels/GameFixesPanel.cpp:54 msgid "FPU Negative Div Hack - For Gundam games." -msgstr "FPU Negative Div Hack - ガンダム作品用(ガンダム無双2のムービーなど)" +msgstr "FPU Negative Div Hack - ガンダム系ゲーム用" #: pcsx2/gui/Panels/GameFixesPanel.cpp:58 msgid "VU XGkick Hack - For Erementar Gerad." @@ -1948,72 +1954,74 @@ msgstr "VU XGkick Hack - エレメンタルジェレイド用" #: pcsx2/gui/Panels/GameFixesPanel.cpp:62 msgid "FFX videos fix - Fixes bad graphics overlay in FFX videos." -msgstr "FFX 映像 fix - FFXの映像のオーバーレイの不具合をfix" +msgstr "FFX videos fix - FFXのムービーを修正します" #: pcsx2/gui/Panels/GameFixesPanel.cpp:66 msgid "EE timing hack - Multi purpose hack. Try if all else fails." msgstr "" -"EE timing hack - 汎用hack 。他のhackで上手く動作しなかった場合に試してくださ" -"い。" +"EE timing hack - 汎用ハック。他に手が無い場合はこれを使ってみましょう。" #: pcsx2/gui/Panels/GameFixesPanel.cpp:75 msgid "" "Skip MPEG hack - Skips videos/FMVs in games to avoid game hanging/freezes." msgstr "" -"MPEG をスキップする hack - 動画をスキップします。FMVでゲームがフリーズやハン" -"グするのを防ぎます。" +"Skip MPEG hack - ムービーをスキップします。イントロムービーがフリーズ、ハング" +"する場合に使って下さい。" #: pcsx2/gui/Panels/GameFixesPanel.cpp:79 msgid "OPH Flag hack - Try if your game freezes showing the same frame." -msgstr "OPH Flag hack - 同じフレームでいつもフリーズする場合に試してください。" +msgstr "" +"OPH Flag hack - 毎回同じフレーム/シーンでフリーズする時に使ってみて下さい。" #: pcsx2/gui/Panels/GameFixesPanel.cpp:88 msgid "Ignore DMAC writes when it is busy." -msgstr "ビジー状態の時にDMACの書き込みを無視" +msgstr "ビジー状態の時、DMAC書き出しを無視します。" #: pcsx2/gui/Panels/GameFixesPanel.cpp:95 msgid "Simulate VIF1 FIFO read ahead. Fixes slow loading games." msgstr "" +"VIF1 FIFO の先読みをシミュレートします。ロードが遅いゲームを修正します。" #: pcsx2/gui/Panels/GameFixesPanel.cpp:103 msgid "Delay VIF1 Stalls (VIF1 FIFO) - For SOCOM 2 HUD." -msgstr "" +msgstr "VIF1ストールにディレイをかけます (VIF1 FIFO) - SOCOM 2のHUD修正。" #: pcsx2/gui/Panels/GameFixesPanel.cpp:107 msgid "Ignore Bus Direction on Path3 Transfer - Used for Hotwheels" -msgstr "" +msgstr "Path3転送のBus Directionを無視する - Hotwheels用" #: pcsx2/gui/Panels/GameFixesPanel.cpp:118 msgid "Enable manual game fixes [Not recommended]" -msgstr "Gamefixを手動で有効化 [非推奨]" +msgstr "ゲーム修正の手動設定有効化[推奨されません]" #: pcsx2/gui/Panels/GameFixesPanel.cpp:127 msgid "" "The safest way to make sure that all game fixes are completely disabled." -msgstr "全ての Gamefix を無効にするのが一番安定します。" +msgstr "ゲーム修正が全て無効化されている事を確認する為の最善な方法です。" #: pcsx2/gui/Panels/LogOptionsPanels.cpp:249 msgid "Enable Trace Logging" -msgstr "トレースログを有効" +msgstr "トレースログを有効化" #: pcsx2/gui/Panels/LogOptionsPanels.cpp:250 msgid "" "Trace logs are all written to emulog.txt. Toggle trace logging at any time " "using F10." msgstr "" -"トレースログは emulog.txt に保存されます。F10キーでいつでも切り替えられます。" +"トレースログは全て emulog.txt に書き込まれます。「F10」でいつでも切り替え" +"られます。" #: pcsx2/gui/Panels/LogOptionsPanels.cpp:251 msgid "" "Warning: Enabling trace logs is typically very slow, and is a leading cause " "of 'What happened to my FPS?' problems. :)" msgstr "" -"注意:トレースログを有効にすると非常に遅くなります。「俺のFPSゲーのどこがバ" -"グってんの?」とかいう時に使います(’▽’)" +"警告: トレースログを有効にすると遅くなります。「俺のFPSどうなっちまった」現" +"象に繋がります。 (^-^)" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:151 msgid "Select folder with PS2 memory cards" -msgstr "PS2メモリカードのファイルがあるフォルダを指定してください。" +msgstr "PS2メモリーカードが保存されるフォルダを選択して下さい" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:448 #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:533 @@ -2022,46 +2030,46 @@ msgstr "取り出し" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:449 msgid "Duplicate ..." -msgstr "複製..." +msgstr "複製 ..." #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:450 msgid "Rename ..." -msgstr "名称変更..." +msgstr "名前の変更 ..." #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:451 #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:515 #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:542 msgid "Create ..." -msgstr "作成..." +msgstr "作成 ..." #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:463 msgid "Card: " -msgstr "カード:" +msgstr "メモリーカード:" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:516 #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:549 msgid "Create a new memory card." -msgstr "メモリカードを新規作成します" +msgstr "メモリーカードの新規作成をする。" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:529 msgid "Rename this memory card ..." -msgstr "このメモリカードの名称を変更します..." +msgstr "メモリーカードの名前を変更 ..." #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:533 msgid "Insert ..." -msgstr "挿入 ..." +msgstr "差し込む ..." #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:534 msgid "Eject the card from this port" -msgstr "以下のポートのカードを取り出します" +msgstr "ポートからメモリーカードを取り出す" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:534 msgid "Insert this card to a port ..." -msgstr "このメモリカードを挿入します..." +msgstr "ポートにメモリーカードを差し込む" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:538 msgid "Create a duplicate of this memory card ..." -msgstr "このメモリカードの複製を作成します..." +msgstr "メモリーカードの複製を作成 ..." #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:542 msgid "Delete" @@ -2069,34 +2077,36 @@ msgstr "削除" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:545 msgid "Permanently delete this memory card from disk (all contents are lost)" -msgstr "このメモリカードをディスク上から削除します(内容は永久に失われます)" +msgstr "" +"このメモリーカードをハードディスクから完全に消去する(全てのデータは失われま" +"す)" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:547 msgid "Create a new memory card and assign it to this Port." -msgstr "新しいメモリカードを作成し、このポートに割り当てます。" +msgstr "メモリーカードを新規作成し、このポートに割り当てる" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:726 msgid "Delete memory file?" -msgstr "メモリカードを削除しますか?" +msgstr "メモリーカードファイルを削除しますか?" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:750 #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:762 #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:769 #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:783 msgid "Duplicate memory card" -msgstr "メモリカードの複製" +msgstr "メモリーカードの複製" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:750 msgid "Failed: Can only duplicate an existing card." -msgstr "失敗:既存のカードのみ複製ができます。" +msgstr "失敗: 複製元のメモリーカードがありません。" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:769 msgid "" "Select a name for the duplicate\n" "( '.ps2' will be added automatically)" msgstr "" -"新しい名前を付けてください。\n" -"(拡張子'.ps2' は自動て付けられます)" +"複製されるメモリーカードに名前を付けて下さい\n" +"( 「.ps2」 ファイル形式は自動的に付与)" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:782 #, c-format @@ -2105,12 +2115,12 @@ msgstr "失敗: %s" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:808 msgid "Copy failed!" -msgstr "コピーが失敗しました!" +msgstr "コピーに失敗しました!" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:816 #, c-format msgid "Memory card '%s' duplicated to '%s'." -msgstr "メモリカード '%s' を '%s' という名前で複製しました。" +msgstr "メモリーカード '%s' は '%s' に複製されました。" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:820 msgid "Success" @@ -2122,72 +2132,72 @@ msgid "" "Select a new name for the memory card '%s'\n" "( '.ps2' will be added automatically)" msgstr "" -"'%s'に新しい名前を付けてください。\n" -"(拡張子'.ps2' は自動て付けられます)" +"'%s' メモリーカードに名前を付けて下さい\n" +"( 「.ps2」 ファイル形式は自動的に付与)" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:844 #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:856 #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:872 msgid "Rename memory card" -msgstr "メモリカードの名称変更" +msgstr "メモリーカードの名前を変更" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:872 msgid "Error: Rename could not be completed.\n" -msgstr "エラー:名称の変更ができませんでした\n" +msgstr "エラー:名前の変更を完了できませんでした。\n" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:962 #: pcsx2/gui/Panels/MemoryCardListView.cpp:139 #, c-format msgid "Port-%u / Multitap-%u--Port-1" -msgstr "ポート%u / マルチタップ%u--ポート1" +msgstr "ポート-%u / マルチタップ-%u--ポート-1" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:963 #: pcsx2/gui/Panels/MemoryCardListView.cpp:140 #, c-format msgid " Multitap-%u--Port-%u" -msgstr " マルチタップ%u--ポート%u" +msgstr " マルチタップ-%u--ポート-%u" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:988 msgid "Empty" -msgstr "なし" +msgstr "空" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:994 #, c-format msgid "Select a target port for '%s'" -msgstr "どのポートに '%s' を挿入しますか?" +msgstr "'%s' を差し込むポートを指定して下さい" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:995 msgid "Insert card" -msgstr "カードの挿入" +msgstr "メモリーカードを差し込む" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1055 msgid "Eject card" -msgstr "カードの取り出し" +msgstr "メモリーカードを取り出す" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1055 msgid "Insert card ..." -msgstr "カードの挿入..." +msgstr "メモリーカードを差し込む ..." #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1056 msgid "Duplicate card ..." -msgstr "カードの複製..." +msgstr "メモリーカードを複製 ..." #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1057 msgid "Rename card ..." -msgstr "カードの名称変更..." +msgstr "メモリーカードの名前を変更する ..." #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1058 msgid "Delete card" -msgstr "カードを削除" +msgstr "メモリーカードを削除" #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1061 #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1065 msgid "Create a new card ..." -msgstr "カードを新規作成..." +msgstr "メモリーカードを新規作成 ..." #: pcsx2/gui/Panels/MemoryCardListPanel.cpp:1069 msgid "Refresh List" -msgstr "リストを更新" +msgstr "リスト更新" #: pcsx2/gui/Panels/MemoryCardListView.cpp:105 msgid "PS2 Port" @@ -2195,15 +2205,15 @@ msgstr "PS2ポート" #: pcsx2/gui/Panels/MemoryCardListView.cpp:107 msgid "Card (file) name" -msgstr "カード(ファイル)名" +msgstr "カード (ファイル) 名" #: pcsx2/gui/Panels/MemoryCardListView.cpp:108 msgid "Card size" -msgstr "容量" +msgstr "カードサイズ" #: pcsx2/gui/Panels/MemoryCardListView.cpp:109 msgid "Formatted" -msgstr "フォーマット済" +msgstr "フォーマットされた" #: pcsx2/gui/Panels/MemoryCardListView.cpp:110 msgid "Last Modified" @@ -2211,7 +2221,7 @@ msgstr "更新日時" #: pcsx2/gui/Panels/MemoryCardListView.cpp:111 msgid "Created on" -msgstr "作成日" +msgstr "作成日時" #: pcsx2/gui/Panels/MemoryCardListView.cpp:156 msgid "No" @@ -2223,23 +2233,23 @@ msgstr "はい" #: pcsx2/gui/Panels/MemoryCardListView.cpp:169 msgid "[-- Unused cards --]" -msgstr "[-- 未使用のカード --]" +msgstr "[-- メモリーカードバンク --]" #: pcsx2/gui/Panels/MemoryCardListView.cpp:171 msgid "[-- No unused cards --]" -msgstr "[-- 未使用のカードはありません --]" +msgstr "[-- カードバンクは空です --]" #: pcsx2/gui/Panels/MiscPanelStuff.cpp:33 msgid "Usermode Selection" -msgstr "ユーザーモード" +msgstr "ユーザーモード選択" #: pcsx2/gui/Panels/MiscPanelStuff.cpp:50 msgid "User Documents (recommended)" -msgstr "ユーザドキュメント (推奨)" +msgstr "ユーザードキュメント (推奨)" #: pcsx2/gui/Panels/MiscPanelStuff.cpp:51 msgid "Location: " -msgstr "場所:" +msgstr "フォルダの場所:" #: pcsx2/gui/Panels/MiscPanelStuff.cpp:55 msgid "Custom folder:" @@ -2249,14 +2259,12 @@ msgstr "カスタムフォルダ:" msgid "" "This setting may require administration privileges from your operating " "system, depending on how your system is configured." -msgstr "" -"この設定は、お使いのシステム構成によっては管理者権限が要求される場合はありま" -"す。" +msgstr "この設定はOSの管理者権限が必要な可能性があります。" #: pcsx2/gui/Panels/MiscPanelStuff.cpp:66 #, c-format msgid "Select a document root for %s" -msgstr "%s のドキュメントのルートを選択" +msgstr "%sを設置するドキュメントのルートを選択して下さい" #: pcsx2/gui/Panels/MiscPanelStuff.cpp:124 msgid "Apply" @@ -2264,70 +2272,68 @@ msgstr "適用" #: pcsx2/gui/Panels/MiscPanelStuff.cpp:125 msgid "Make this language my default right now!" -msgstr "今すぐあなたのデフォルトの言語を作ろう!" +msgstr "この言語をデフォルトに設定してくれ!" #: pcsx2/gui/Panels/PathsPanel.cpp:38 msgid "Savestates:" -msgstr "ステートセーブの保存先:" +msgstr "セーブステート:" #: pcsx2/gui/Panels/PathsPanel.cpp:39 msgid "Select folder for Savestates" -msgstr "ステートセーブのフォルダを指定してください" +msgstr "セーブステートの保存先を指定する" #: pcsx2/gui/Panels/PathsPanel.cpp:48 msgid "Snapshots:" -msgstr "スナップショットの保存先:" +msgstr "スクリーンショット:" #: pcsx2/gui/Panels/PathsPanel.cpp:49 msgid "Select a folder for Snapshots" -msgstr "スナップショットの保存先フォルダを指定してください" +msgstr "スクリーンショットの保存先を指定する" #: pcsx2/gui/Panels/PathsPanel.cpp:58 msgid "Logs/Dumps:" -msgstr "ログ/ダンプの保存先:" +msgstr "ログ / ダンプ:" #: pcsx2/gui/Panels/PathsPanel.cpp:59 msgid "Select a folder for logs/dumps" -msgstr "ログ/ダンプの保存先フォルダを指定してください" +msgstr "ログ / ダンプの保存先を指定する" #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:230 msgid "Applying settings..." -msgstr "設定を適用中..." +msgstr "設定を適用中 ..." #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:240 msgid "Shutdown PS2 virtual machine?" -msgstr "PS2仮想マシンを終了させますか?" +msgstr "PS2仮想マシンをシャットダウンしますか?" #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:321 msgid "I'm givin' her all she's got, Captain!" -msgstr "I'm givin' her all she's got, Captain!" +msgstr "全力でやってます、船長!" #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:323 msgid "Enumerating available plugins..." -msgstr "エミュレート可能なプラグイン..." +msgstr "利用可能なプラグインをマップ中..." #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:356 msgid "Plugins Search Path:" -msgstr "プラグインのフォルダパス:" +msgstr "プラグイン参照パス:" #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:357 msgid "Select a folder with PCSX2 plugins" -msgstr "PCSX2のプラグインフォルダを指定してください" +msgstr "PCSX2プラグインフォルダを選択" #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:370 msgid "Configure..." -msgstr "設定..." +msgstr "設定する..." #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:379 msgid "Click the Browse button to select a different folder for PCSX2 plugins." -msgstr "" -"PCSX2のプラグインが別の場所にある場合、参照ボタンを押してフォルダを指定してく" -"ださい。" +msgstr "参照ボタンをクリックしてPCSX2プラグインフォルダを指定して下さい。" #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:481 #, c-format msgid "Please select a valid plugin for the %s." -msgstr "%sの有効なプラグインを選択してください。" +msgstr "%sの有効なプラグインを選択して下さい。" #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:519 #, c-format @@ -2337,37 +2343,38 @@ msgid "" "Reason: %s\n" "\n" msgstr "" -"選択した %s プラグインのロードに失敗しました \n" +"選択された[%s]プラグインはロードに失敗しました。\n" "\n" -"原因:%s\n" +"理由: %s\n" "\n" #: pcsx2/gui/Panels/PluginSelectorPanel.cpp:730 msgid "Completing tasks..." -msgstr "タスクの完了中..." +msgstr "タスク処理中..." #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:96 msgid "Enable speedhacks" -msgstr "Speedhackを有効" +msgstr "スピードハック有効化" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:102 msgid "" "A safe and easy way to make sure that all speedhacks are completely disabled." -msgstr "全ての Speedhack が無効になっているのが、最も安定かつ簡単な設定です。" +msgstr "ゲーム修正が全て無効化されている事を確認する為の最善な方法です。" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:111 msgid "" "Resets all speedhack options to their defaults, which consequently turns " "them all OFF." -msgstr "全てのオプションをデフォルトに戻し、SpeedhackをOFFにします。" +msgstr "" +"スピードハックを全てデフォルト値にします。結果として全て無効化されます。" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:120 msgid "EE Cyclerate [Not Recommended]" -msgstr "EE サイクルレートの設定 [非推奨]" +msgstr "EE Cyclerate [推奨されません]" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:141 msgid "VU Cycle Stealing [Not Recommended]" -msgstr "VU サイクルスティーリングの設定 [非推奨]" +msgstr "VU Cycle Stealing [推奨されません]" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:161 msgid "microVU Hacks" @@ -2378,101 +2385,91 @@ msgid "mVU Flag Hack" msgstr "mVU Flag Hack" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:164 -#, fuzzy msgid "" "Good Speedup and High Compatibility; may cause bad graphics... [Recommended]" -msgstr "" -"良いスピードアップと高い互換性があります;映像や音声に多少の出るが出る可能性" -"がありますが...[推奨]" +msgstr "速度の向上と高い互換性、グラフィック不具合の可能性有り... [推奨]" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:166 msgid "MTVU (Multi-Threaded microVU1)" -msgstr "" +msgstr "MTVU (Multi-Threaded microVU1)" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:167 -#, fuzzy msgid "" "Good Speedup and High Compatibility; may cause hanging... [Recommended if 3+ " "cores]" -msgstr "" -"良いスピードアップと高い互換性があります;映像や音声に多少の出るが出る可能性" -"がありますが...[推奨]" +msgstr "速度の向上と高い互換性、ハングを起こす事があります... [3コア以上推奨]" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:183 msgid "Other Hacks" -msgstr "その他のHack" +msgstr "その他のハック" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:185 msgid "Enable INTC Spin Detection" -msgstr "INTCのSpin検出を有効" +msgstr "INTC Spin Detection 有効化" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:186 msgid "" "Huge speedup for some games, with almost no compatibility side effects. " "[Recommended]" -msgstr "" -"多少の互換性と引き換えに、一部のゲームで大幅なスピードアップを図れます[推奨]" +msgstr "一部のゲームでは速度が大幅に向上し、互換問題もほぼありません。 [推奨]" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:188 msgid "Enable Wait Loop Detection" -msgstr "ループ検出を有効" +msgstr "Wait Loop Detection 有効化" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:189 msgid "" "Moderate speedup for some games, with no known side effects. [Recommended]" -msgstr "" -"互換性と引き換えに、一部のゲームである程度のスピードアップを図れます[推奨]" +msgstr "一部のゲームでそこそこの速度向上、互換問題は無いと思われます。 [推奨]" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:191 msgid "Enable fast CDVD" -msgstr "CDVDの高速読み込みを有効" +msgstr "Fast CDVD 有効化" #: pcsx2/gui/Panels/SpeedhacksPanel.cpp:192 msgid "Fast disc access, less loading times. [Not Recommended]" -msgstr "高速でディスクにアクセスしてロード時間を短縮[非推奨]" +msgstr "高速ディスクアクセスで読み込み時間を現象させます。 [非推奨]" #: pcsx2/gui/Panels/ThemeSelectorPanel.cpp:37 msgid "Themes Search Path:" -msgstr "テーマがあるフォルダ:" +msgstr "テーマ参照パス:" #: pcsx2/gui/Panels/ThemeSelectorPanel.cpp:38 msgid "Select folder containing PCSX2 visual themes" -msgstr "PCSX2の視覚テーマがあるフォルダを選択" +msgstr "PCSX2の視覚テーマがあるフォルダの選択" #: pcsx2/gui/Panels/ThemeSelectorPanel.cpp:45 msgid "" "Click the Browse button to select a different folder containing PCSX2 visual " "themes." msgstr "" -"PCSX2の視覚テーマが別の場所にある場合、参照ボタンを押してフォルダを指定してく" -"ださい。" +"参照ボタンをクリックしてPCSX2視覚テーマがあるフォルダを指定して下さい。" #: pcsx2/gui/Panels/ThemeSelectorPanel.cpp:49 msgid "Select a visual theme:" -msgstr "視覚テーマを選択:" +msgstr "視覚テーマの選択:" #: pcsx2/gui/Panels/VideoPanel.cpp:34 msgid "Disable Framelimiting" -msgstr "フレームリミットを無効" +msgstr "フレームリミッタ無効化" #: pcsx2/gui/Panels/VideoPanel.cpp:35 msgid "" "Useful for running benchmarks. Toggle this option in-game by pressing F4." msgstr "" -"ベンチマーク用などで使用してください。このオプションはゲーム中でもF4キーで切" -"り替えができます。" +"ベーンチマークをする時に便利です。ゲーム実行中は「F4」で切り替えられます。" #: pcsx2/gui/Panels/VideoPanel.cpp:61 msgid "Base Framerate Adjust:" -msgstr "通常のフレームレート:" +msgstr "基本フレームレート調整:" #: pcsx2/gui/Panels/VideoPanel.cpp:67 msgid "Slow Motion Adjust:" -msgstr "スローモーションモードのフレームレート:" +msgstr "スローモーション調整:" #: pcsx2/gui/Panels/VideoPanel.cpp:73 msgid "Turbo Adjust:" -msgstr "ターボモードのフレームレート:" +msgstr "ターボ調整:" #: pcsx2/gui/Panels/VideoPanel.cpp:88 msgid "NTSC Framerate:" @@ -2491,8 +2488,8 @@ msgid "" "Error while parsing either NTSC or PAL framerate settings. Settings must be " "valid floating point numerics." msgstr "" -"NTSC または PAL のフレームレートの設定の解析中にエラーが発生しました。有効な" -"浮動小数点値を入力してください。" +"NTSC又はPAL方式のフレームレート設定のパースエラー。設定は有効な浮動小数点数で" +"なければいけません。" #: pcsx2/gui/Panels/VideoPanel.cpp:184 msgid "Disabled [default]" @@ -2500,77 +2497,81 @@ msgstr "無効 [デフォルト]" #: pcsx2/gui/Panels/VideoPanel.cpp:188 msgid "Skip when on Turbo only (TAB to enable)" -msgstr "ターボの時のみスキップ(Tabキーで有効)" +msgstr "ターボ時のみスキップ (タブキーで有効)" #: pcsx2/gui/Panels/VideoPanel.cpp:192 msgid "Constant skipping" -msgstr "常にフレームをスキップする" +msgstr "常にスキップ" #: pcsx2/gui/Panels/VideoPanel.cpp:194 msgid "" "Normal and Turbo limit rates skip frames. Slow motion mode will still " "disable frameskipping." msgstr "" -"通常、ターボモードの場合はフレームスキップを有効にしてください。スローモー" -"ションモードでは無効にされます。" +"平常及びターボ時にフレームスキップします。\n" +"スローモーション時にはフレームスキップは無効になります。" #: pcsx2/gui/Panels/VideoPanel.cpp:217 msgid "Frames to Draw" -msgstr "フレーム描写" +msgstr "描画フレーム数" #: pcsx2/gui/Panels/VideoPanel.cpp:222 msgid "Frames to Skip" -msgstr "フレームスキップ" +msgstr "フレームスキップ数" #: pcsx2/gui/Panels/VideoPanel.cpp:298 msgid "Use Synchronized MTGS" -msgstr "MTGSと同期" +msgstr "MTGS同期を有効化" #: pcsx2/gui/Panels/VideoPanel.cpp:299 msgid "" "For troubleshooting potential bugs in the MTGS only, as it is potentially " "very slow." -msgstr "MTGSに潜在的なバグがあった場合のみ有効に。非常に低速になります。" +msgstr "" +"クラッシュやグラフィックエラーの発生原因として、\n" +"MTGSスレッドの同期が疑わしい場合は有効にして下さい。" #: pcsx2/gui/Panels/VideoPanel.cpp:302 msgid "Disable all GS output" -msgstr "GS出力を無効" +msgstr "GS出力を無効化" #: pcsx2/gui/Panels/VideoPanel.cpp:303 msgid "" "Completely disables all GS plugin activity; ideal for benchmarking EEcore " "components." msgstr "" -"GSプラグインを無効にします。EEコアコンポーネントのベンチマークに最適です。" +"GSプラグインの動作を完全に無効にします。エモーションエンジンのコンポーネント" +"自体の処理速度計測とデバッグ目的に最適です。" #: pcsx2/gui/Panels/VideoPanel.cpp:320 msgid "Frame Skipping" -msgstr "フレームスキップの設定" +msgstr "フレームスキップ" #: pcsx2/gui/Panels/VideoPanel.cpp:323 msgid "Framelimiter" -msgstr "フレームリミットの設定" +msgstr "フレームリミッタ" #: pcsx2/gui/SysState.cpp:283 msgid "" "Cannot load this savestate. The state is from an incompatible edition of " "PCSX2 that is either newer than this version, or is no longer supported." msgstr "" -"このステートセーブをロードすることができません。新しいバージョンか、またはサ" -"ポート外となった古いバージョンのPCSX2のデータです。" +"セーブステートをロードできませんでした。ステートは、互換性の無いPCSX2のもの" +"で、バージョンが新しいか、サポートされていません。" #: pcsx2/gui/SysState.cpp:290 msgid "" "Cannot load this savestate. The state is an unsupported version, likely " "created by a newer edition of PCSX2." msgstr "" -"ステートセーブをロードできません。未サポートのデータです。恐らく新しいバー" -"ジョンのPCSX2のデータです。" +"セーブステートをロードできませんでした。ステートは、サポートされていません。" +"より新しいバージョンのPCSX2で作成されたようです。" #: pcsx2/gui/SysState.cpp:326 msgid "There is no active virtual machine state to download or save." msgstr "" -"仮想マシンが起動していなければステートセーブのセーブ、ロードはできません。" +"エラー: メモリバッファへダウンロード又保存できるアクティブな仮想マシンステー" +"トがありません。" #: pcsx2/gui/SysState.cpp:520 msgid "" @@ -2578,42 +2579,42 @@ msgid "" "may have been created by an older unsupported version of PCSX2, or it may be " "corrupted." msgstr "" -"有効なgzipファイルではないため、ステートセーブをロードすることができません。" -"未サポートのデータ、または破損している可能性もあります。" +"セーブステートが無効なgzipアーカイブなのでロードできませんでした。旧バージョ" +"ンのPCSX2で作成されたか、破損したファイルです。" #: pcsx2/gui/SysState.cpp:579 msgid "This file is not a valid PCSX2 savestate. See the logfile for details." msgstr "" -"このファイルは有効なPCSX2クックセーブではありません。詳細はログファイルをを参" -"照してください。" +"このファイルは無効なPCSX2のセーブステートです。詳細はログファイルを参照して下" +"さい。" #: pcsx2/gui/SysState.cpp:598 msgid "" "This savestate cannot be loaded due to missing critical components. See the " "log file for details." msgstr "" -"このステートセーブは重要なコンポーネントが見つからないためロードできません。" -"詳細はログファイルを参照してください。" +"セーブステートは重要な構成に欠けている為、ロードできませんでした。詳細はログ" +"ファイルを参照して下さい。" #: pcsx2/gui/i18n.cpp:63 msgid " (default)" -msgstr "" +msgstr "(デフォルト)" #: pcsx2/ps2/BiosTools.cpp:83 pcsx2/ps2/BiosTools.cpp:151 msgid "The selected BIOS file is not a valid PS2 BIOS. Please re-configure." -msgstr "指定されたBIOSは有効なPS2 BIOSではありません。設定しなおしてください。" +msgstr "選択されたBIOSファイルは無効です。再度設定して下さい。" #: pcsx2/ps2/BiosTools.cpp:244 msgid "" "The PS2 BIOS could not be loaded. The BIOS has not been configured, or the " "configuration has been corrupted. Please re-configure." msgstr "" -"PS2 BIOSが読み込まれませんでした。BIOSが設定されていないか、破損しています。" -"設定しなおしてください。" +"PS2のBIOSをロードできませんでした。設定されてない若しくは設定が破損してます。" +"再度設定して下さい。" #: pcsx2/ps2/BiosTools.cpp:251 msgid "The configured BIOS file does not exist. Please re-configure." -msgstr "設定されたBIOSが見つかりません。設定しなおしてください。" +msgstr "指定されたBIOSファイルが見つかりません。再度設定して下さい。" #: pcsx2/x86/ix86-32/iR5900-32.cpp:578 #, c-format @@ -2621,8 +2622,8 @@ msgid "" "%s Extensions not found. The R5900-32 recompiler requires a host CPU with " "MMX, SSE, and SSE2 extensions." msgstr "" -"%s 拡張命令が見つかりませんでした。R5900-32 リコンパイラにはMMX, SSE, SSE2 拡" -"張命令が必要です。" +"%s 拡張命令がみつかりません。 R5900-32 リコンパイラは MMX、SSE、及びSSE2 拡張" +"命令を最低限備えたCPUが必要です。" #: pcsx2/x86/microVU.cpp:28 #, c-format @@ -2630,223 +2631,12 @@ msgid "" "%s Extensions not found. microVU requires a host CPU with MMX, SSE, and " "SSE2 extensions." msgstr "" -"%s 拡張命令が見つかりませんでした。microVU にはMMX, SSE, SSE2 拡張命令が必要" -"です。" +"%s 拡張命令がみつかりません。 microVUは MMX、SSE、及びSSE2 拡張命令を最低限備" +"えたCPUが必要です。" #~ msgid "mVU Block Hack" #~ msgstr "mVU Block Hack" -#, fuzzy #~ msgid "" #~ "Good Speedup and High Compatibility; may cause bad graphics, SPS, etc..." -#~ msgstr "" -#~ "良いスピードアップと高い互換性があります;映像や音声に多少のゴミがデル可能" -#~ "性がありますが..." - -#~ msgid "!ContextTip:ChangingNTFS" -#~ msgstr "" -#~ "NTFS 圧縮の設定は、Windowsのエクスプローラーでファイルのプロパティを開くこ" -#~ "とでいつでも変更できます。" - -#~ msgid "!ContextTip:Folders:Settings" -#~ msgstr "" -#~ "このフォルダはプラグインを含む PCSX2 のほとんどの設定ファイルを保存する" -#~ "フォルダです。\n" -#~ "(一部の古いプラグインはこの設定を利用しない可能性があります)" - -#~ msgid "!Panel:HasHacksOverrides" -#~ msgstr "" -#~ "警告!コマンドラインオプションを使用して PCSX2 の設定上書きして実行してい" -#~ "ます。コマンドラインオプションは設定ダイアログには反映されず、設定を変更し" -#~ "ても無効になります。" - -#~ msgid "!Panel:HasPluginsOverrides" -#~ msgstr "" -#~ "警告!コマンドラインオプションを使用して PCSX2 のプラグイン設定上書きして" -#~ "実行しています。コマンドラインオプションは設定ダイアログには反映されず、設" -#~ "定を変更しても無効になります。" - -#~ msgid "!Notice:Tooltip:Presets:Slider" -#~ msgstr "" -#~ "プリセットを有効にするといくつかのSpeedhack、コンパイラオプション、既知の " -#~ "Gamefix を適用して速度を向上させます。\n" -#~ "既知の重要な Gamefix は自動で有効になります。\n" -#~ "\n" -#~ "プリセットの内容\n" -#~ "1 - 最も精密にエミュレーションを行います。\n" -#~ "3 --> 互換性とスピードのバランスを取ってエミュレーションを行います。\n" -#~ "4 - より積極的に hack を行います。\n" -#~ "6 - hack のしすぎで多くの場合は速度の低下が起きてしまいます。" - -#~ msgid "!Notice:Tooltip:Presets:Checkbox" -#~ msgstr "" -#~ "プリセットを有効にするといくつかのSpeedhack、コンパイラオプション、既知の " -#~ "Gamefix を適用して速度を向上させます。\n" -#~ "既知の重要な Gamefix は自動で有効になります。\n" -#~ "\n" -#~ "-->チェックを外すと、手動で(現在のプリセットを元にして)設定することができ" -#~ "ます。" - -#~ msgid "!ContextTip:DirPicker:UseDefault" -#~ msgstr "" -#~ "チェックをすると、このフォルダをPCSX2の現在のユーザーモードのデフォルト設" -#~ "定が自動的に反映されます。" - -#~ msgid "!ContextTip:Window:Vsync" -#~ msgstr "" -#~ "VSYNC を同期させるとティアリング現象を解消できますが、パフォーマンスに重大" -#~ "な問題が発生します。\n" -#~ "通常はフルスクリーンモードでのみ使用します。また一部の GS プラグインでは機" -#~ "能しない可能性があります。" - -#~ msgid "!ContextTip:Window:ManagedVsync" -#~ msgstr "" -#~ "フレームレートが最速の時に VSYNC を有効にします。最速でない場合は速度の低" -#~ "下を防ぐために無効にします。\n" -#~ "注意:現時点ではDX10/11ハードウェアレンダリングで GSdx を使用している時の" -#~ "み動作します。\n" -#~ "他のプラグインやレンダリングモードでは無視されるか、黒いフレームが挿入され" -#~ "点滅が起こります。\n" -#~ "またVSYNCと同期する設定を有効にする必要があります。" - -#~ msgid "!ContextTip:Window:HideMouse" -#~ msgstr "" -#~ "GS ウィンドウ上でマウスを強制的に非表示にします。マウス操作がメインのゲー" -#~ "ムで有効にすると便利です。\n" -#~ "デフォルトでは操作をしないで2秒経過するとマウスを自動で非表示にします。" - -#~ msgid "!ContextTip:Window:Fullscreen" -#~ msgstr "" -#~ "ゲームを始めた時や再開した時に自動的にフルスクリーンになります。\n" -#~ "フルスクリーンにはAlt+Enterキーでいつでも切り替えができます。" - -#~ msgid "!ContextTip:Window:HideGS" -#~ msgstr "ESC を押したりしてゲームを一時停止した時にGSウィンドウを閉じます。" - -#~ msgid "!ContextTip:Gamefixes:EE Timing Hack" -#~ msgstr "" -#~ "以下のゲームに効果があります。\n" -#~ " * デジタルデビルサーガ (FMVでのクラッシュの問題)\n" -#~ " * SSX (グラフィックの不具合やクラッシュの問題)\n" -#~ " * バイオハザード ガンサバイバー4 (テクスチャの問題)" - -#~ msgid "!ContextTip:Gamefixes:OPH Flag hack" -#~ msgstr "" -#~ "以下のゲームに効果があります。\n" -#~ " * BLEACH~ブレイド・バトラーズ~\n" -#~ " * グローランサー2&3\n" -#~ " * Wizardry" - -#~ msgid "!ContextTip:Gamefixes:DMA Busy hack" -#~ msgstr "" -#~ "以下のゲームに効果があります。\n" -#~ " * マナケミア~学園の錬金術士たち~" - -#~ msgid "!ContextTip:Folders:Savestates" -#~ msgstr "" -#~ "このフォルダは PCSX2 のステートセーブの保存場所です。\n" -#~ "メニューまたはツールバーを使うか、F1/F3(セーブ/ロード)キーで操作します。" - -#~ msgid "!ContextTip:Folders:Snapshots" -#~ msgstr "" -#~ "このフォルダは PCSX2 のスナップショットの保存場所です。ご使用の GS プラグ" -#~ "インによってはサイズや形式が違うかもしれません。" - -#~ msgid "!ContextTip:Folders:Logs" -#~ msgstr "" -#~ "このフォルダは PCSX2 のログとダンプデータの保存場所です。一部の古いプラグ" -#~ "インはこの設定を利用しない可能性があります。" - -#~ msgid "!Panel:Speedhacks:EECycleX1" -#~ msgstr "" -#~ "1 - 通常のサイクルレート。これは実機のPS2の EmotionEngine の速度に近いもの" -#~ "です。" - -#~ msgid "!Panel:Speedhacks:EECycleX2" -#~ msgstr "" -#~ "2 - EEのサイクルレートを約33%低下。多くのゲームで互換性を維持したままある" -#~ "程度のスピードアップ出来ます。" - -#~ msgid "!Panel:Speedhacks:EECycleX3" -#~ msgstr "" -#~ "2 - EEのサイクルレートを約50%低下。中々の高速化が期待できますが *恐らく* " -#~ "FMVで音声の途切れる原因にもなります。" - -#~ msgid "!Panel:Speedhacks:VUCycleStealOff" -#~ msgstr "0 - VU サイクルスティーリング無効。最も互換性の高い設定!" - -#~ msgid "!Panel:Speedhacks:VUCycleSteal1" -#~ msgstr "" -#~ "1 - 少しだけVU サイクルスティーリング実行。互換性は下がりますがほとんどのゲームで若" -#~ "干の高速化します。" - -#~ msgid "!Panel:Speedhacks:VUCycleSteal2" -#~ msgstr "" -#~ "2 - 適度にVU サイクルスティーリング実行。より互換性は下がりますがいくつかのゲームで" -#~ "大幅に高速化します。" - -#~ msgid "!Panel:Speedhacks:VUCycleSteal3" -#~ msgstr "" -#~ "3 - 限界までVU サイクルスティーリング実行。画面のちらつきが発生し多くのゲームで速度" -#~ "の低下かが起こるため有用性は限定的。" - -#~ msgid "!ContextTip:Speedhacks:EECycleRate Slider" -#~ msgstr "" -#~ "このスライドバーを上げるとEmotionEngineのR5900コアCPUのクロックを下げる代" -#~ "わりに大きな高速化を行い、\n" -#~ "PS2ハードウェアの機能を最大限利用していないゲームの高速化に有用です。" - -#~ msgid "!ContextTip:Speedhacks:VUCycleStealing Slider" -#~ msgstr "" -#~ "このスライドバーを上げるとEmotionEngineのVUユニットからスティーリングを行" -#~ "います。\n" -#~ "高い設定にするほどサイクルスティーリングを行う量が増加します。" - -#~ msgid "!ContextTip:Speedhacks:vuFlagHack" -#~ msgstr "" -#~ "常時ではなくブロックされた時のみフラグステータスを更新します。\n" -#~ "ほとんどの安全であり、SuperVUにも同様の動作をさせます。" - -#~ msgid "!ContextTip:Speedhacks:vuBlockHack" -#~ msgstr "" -#~ "遠い将来にインスタンスデータの古いフラグを必要としないと仮定しています。\n" -#~ "かなり安全なはずです。どんなゲームに不具合が起きるかは不明ですが..." - -#~ msgid "!ContextTip:Speedhacks:INTC" -#~ msgstr "" -#~ "このhackは主に非3D系RPGにある INTC ステータスレジスタを使用しVSYNC待ちをす" -#~ "るゲームに最適です。\n" -#~ "効果がなかった場合には使用しないでください。" - -#~ msgid "!ContextTip:Speedhacks:BIFC0" -#~ msgstr "" -#~ "主にEEのカーネル空間のアドレス 0x81FC0 のアイドルループ処理を対象にしてい" -#~ "ます。\n" -#~ "このhackは別ユニットによるエミュレーションのイベントトリガまでの間に、状態" -#~ "が同じである事を検出します。\n" -#~ "このようなループを1度だけ繰り返したあと、次のイベントかタイムスライスの終りのいず" -#~ "れか早いほうに進みます。" - -#~ msgid "!ContextTip:Speedhacks:fastCDVD" -#~ msgstr "" -#~ "この問題を抱えている既知のゲーム用の設定。\n" -#~ "HDLoader互換性リストを参照してください(主に'MODE 1'や'低速DVD'など)" - -#~ msgid "!ContextTip:Framelimiter:Disable" -#~ msgstr "" -#~ "フレームリミットを無効にした場合、スローモーションモードとターボモードは使" -#~ "用できません。" - -#~ msgid "!ContextTip:GS:SyncMTGS" -#~ msgstr "" -#~ "映像の不具合の原因が MTGS スレッドの同期によるものだと思われる場合有効にし" -#~ "てください。" - -#~ msgid "!ContextTip:GS:DisableOutput" -#~ msgstr "" -#~ "MTGSスレッドかGPUオーバーヘッドによって発生されたベンチマークノイズを除去" -#~ "します。このオプションはステートセーブと併用するのが最良です。; 最適な場" -#~ "面でステートセーブを行い、このオプションを有効にしてリロードします。\n" -#~ "\n" -#~ "警告:このオプションはいつでも有効にすることができますが、動作中に無効にで" -#~ "きません(映像に悪影響を与えます)。" +#~ msgstr "速度の向上と高い互換性、グラフィック不具合(SPS等)の可能性有り..." diff --git a/pcsx2/gui/i18n.cpp b/pcsx2/gui/i18n.cpp index 88d9b00b9..4f530ee1e 100644 --- a/pcsx2/gui/i18n.cpp +++ b/pcsx2/gui/i18n.cpp @@ -208,7 +208,13 @@ static wxLanguage i18n_FallbackToAnotherLang( wxLanguage wxLangId ) case wxLANGUAGE_SPANISH_VENEZUELA: return wxLANGUAGE_SPANISH_MODERN; case wxLANGUAGE_ITALIAN_SWISS : return wxLANGUAGE_ITALIAN; - + + case LANGUAGE_FRENCH_BELGIAN: + case LANGUAGE_FRENCH_CANADIAN: + case LANGUAGE_FRENCH_LUXEMBOURG: + case LANGUAGE_FRENCH_MONACO: + case LANGUAGE_FRENCH_SWISS: return LANGUAGE_FRENCH; + default : break; } return wxLangId; From ef37720cb9960a598fa5015d975b0598a22cb721 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Sun, 11 Mar 2012 08:35:40 +0000 Subject: [PATCH 34/83] i18n: nothing to see... Close issue 1237. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5127 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/gui/i18n.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pcsx2/gui/i18n.cpp b/pcsx2/gui/i18n.cpp index 4f530ee1e..9e856b93c 100644 --- a/pcsx2/gui/i18n.cpp +++ b/pcsx2/gui/i18n.cpp @@ -209,11 +209,11 @@ static wxLanguage i18n_FallbackToAnotherLang( wxLanguage wxLangId ) case wxLANGUAGE_ITALIAN_SWISS : return wxLANGUAGE_ITALIAN; - case LANGUAGE_FRENCH_BELGIAN: - case LANGUAGE_FRENCH_CANADIAN: - case LANGUAGE_FRENCH_LUXEMBOURG: - case LANGUAGE_FRENCH_MONACO: - case LANGUAGE_FRENCH_SWISS: return LANGUAGE_FRENCH; + case wxLANGUAGE_FRENCH_BELGIAN: + case wxLANGUAGE_FRENCH_CANADIAN: + case wxLANGUAGE_FRENCH_LUXEMBOURG: + case wxLANGUAGE_FRENCH_MONACO: + case wxLANGUAGE_FRENCH_SWISS: return wxLANGUAGE_FRENCH; default : break; } From 406ea42c43ef508f10687b0916a1371a6255b023 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Wed, 14 Mar 2012 13:10:14 +0000 Subject: [PATCH 35/83] Tests with Grandia Extreme's debugger suggest that SBUS interrupts *never* fire. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5128 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/CDVD/CDVD.cpp | 3 --- pcsx2/IopIrq.cpp | 4 ---- pcsx2/Sif0.cpp | 3 +-- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/pcsx2/CDVD/CDVD.cpp b/pcsx2/CDVD/CDVD.cpp index 63550938b..3a8ab4892 100644 --- a/pcsx2/CDVD/CDVD.cpp +++ b/pcsx2/CDVD/CDVD.cpp @@ -70,7 +70,6 @@ static void cdvdSetIrq( uint id = (1< Date: Thu, 15 Mar 2012 12:44:18 +0000 Subject: [PATCH 36/83] GSdx: Fix Grandia Xtreme flicker :) Could help other games as well, please test. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5129 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSState.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index 4cf8f26e6..9d6490c6b 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -1149,8 +1149,8 @@ template void GSState::GIFRegHandlerZBUF(const GIFReg* RESTRICT r) if(ZBUF.u32[0] == 0) { // during startup all regs are cleared to 0 (by the bios or something), so we mask z until this register becomes valid - - ZBUF.ZMSK = 1; + // edit: breaks Grandia Xtreme and sounds like a bad idea generally. What was the intend? + //ZBUF.ZMSK = 1; } ZBUF.PSM |= 0x30; From f9e4ba405cacccd48a139b69d3c452d0514ba3c6 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Thu, 15 Mar 2012 16:16:51 +0000 Subject: [PATCH 37/83] Gsdx: Change a texture cache hack to fix half the flickering FMV games. It could have issues though, or randomly fix other stuff. Please test :p git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5130 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSTextureCache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/GSdx/GSTextureCache.cpp b/plugins/GSdx/GSTextureCache.cpp index 73be0b69a..ed5a49fdb 100644 --- a/plugins/GSdx/GSTextureCache.cpp +++ b/plugins/GSdx/GSTextureCache.cpp @@ -268,7 +268,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, int { // HACK: try to find something close to the base pointer - if(t->m_TEX0.TBP0 <= bp && bp < t->m_TEX0.TBP0 + 0x700 && (!dst || t->m_TEX0.TBP0 >= dst->m_TEX0.TBP0)) + if(t->m_TEX0.TBP0 <= bp && bp < t->m_TEX0.TBP0 + 0xe00 && (!dst || t->m_TEX0.TBP0 >= dst->m_TEX0.TBP0)) { dst = t; } From 79b9c1cb87346f4b3d0d36e29a6e5dce070649b1 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Thu, 15 Mar 2012 20:25:36 +0000 Subject: [PATCH 38/83] debian: update control file to support multiarch in latest ubuntu git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5131 96395faa-99c1-11dd-bbfe-3dabce05a288 --- debian-unstable-upstream/control | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/debian-unstable-upstream/control b/debian-unstable-upstream/control index 7f5afa787..9fe07dd28 100644 --- a/debian-unstable-upstream/control +++ b/debian-unstable-upstream/control @@ -6,18 +6,12 @@ Maintainer: Gregory Hainaut Build-Depends: cmake (>= 2.8), debhelper (>= 7.0.50), dpkg-dev (>= 1.15.7), - gcc-multilib [amd64], - g++-multilib [amd64], - ia32-libs-dev [amd64], - lib32asound2-dev [amd64], - lib32bz2-dev [amd64], - lib32z1-dev (>= 1:1.2.3.3) [amd64], libasound2-dev, libbz2-dev, libgl1-mesa-dev, # Future GSdx version will need glew1.6. Only Oneiric have it... # libglew1.6-dev, - libglew1.5-dev, + libglew-dev (>= 1.6)| libglew1.5-dev, libglu1-mesa-dev, libgtk2.0-dev (>= 2.16), libjpeg-dev, @@ -28,7 +22,8 @@ Build-Depends: cmake (>= 2.8), libwxgtk2.8-dev, libx11-dev, locales | locales-all, - nvidia-cg-toolkit (>= 3), +# package was split in precise to allow multiarch support + libcg |nvidia-cg-toolkit (>= 3), portaudio19-dev, zlib1g-dev (>= 1:1.2.3.3) Standards-Version: 3.9.2 From 9264b7725cf354c04c9ddf224a596c8836dfd66f Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Sat, 17 Mar 2012 11:21:51 +0000 Subject: [PATCH 39/83] pcsx2: gcc 4.7 compilation fix git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5132 96395faa-99c1-11dd-bbfe-3dabce05a288 --- common/include/Utilities/HashMap.h | 6 +++--- common/src/Utilities/Linux/LnxHostSys.cpp | 1 + common/src/Utilities/Linux/LnxMisc.cpp | 1 + common/src/Utilities/Linux/LnxThreads.cpp | 1 + plugins/GSdx/stdafx.cpp | 1 + 5 files changed, 7 insertions(+), 3 deletions(-) diff --git a/common/include/Utilities/HashMap.h b/common/include/Utilities/HashMap.h index 44da83fbd..6d2a0ca32 100644 --- a/common/include/Utilities/HashMap.h +++ b/common/include/Utilities/HashMap.h @@ -602,8 +602,8 @@ public: HashMap( const Key& emptyKey, const Key& deletedKey, int initialCapacity=33 ) : google::dense_hash_map( initialCapacity ) { - set_empty_key( emptyKey ); - set_deleted_key( deletedKey ); + this->set_empty_key( emptyKey ); + this->set_deleted_key( deletedKey ); } ///

@@ -616,7 +616,7 @@ public: /// bool TryGetValue( const Key& key, T& outval ) const { - const_iterator iter( find(key) ); + const_iterator iter( this->find(key) ); if( iter != end() ) { outval = iter->second; diff --git a/common/src/Utilities/Linux/LnxHostSys.cpp b/common/src/Utilities/Linux/LnxHostSys.cpp index c2804862b..7f49e326a 100644 --- a/common/src/Utilities/Linux/LnxHostSys.cpp +++ b/common/src/Utilities/Linux/LnxHostSys.cpp @@ -22,6 +22,7 @@ #include #include #include +#include extern void SignalExit(int sig); diff --git a/common/src/Utilities/Linux/LnxMisc.cpp b/common/src/Utilities/Linux/LnxMisc.cpp index f2e11f442..4059bb14e 100644 --- a/common/src/Utilities/Linux/LnxMisc.cpp +++ b/common/src/Utilities/Linux/LnxMisc.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include diff --git a/common/src/Utilities/Linux/LnxThreads.cpp b/common/src/Utilities/Linux/LnxThreads.cpp index c5c990805..c3921caac 100644 --- a/common/src/Utilities/Linux/LnxThreads.cpp +++ b/common/src/Utilities/Linux/LnxThreads.cpp @@ -17,6 +17,7 @@ #include "../PrecompiledHeader.h" #include "PersistentThread.h" #include +#include // We wont need this until we actually have this more then just stubbed out, so I'm commenting this out // to remove an unneeded dependency. diff --git a/plugins/GSdx/stdafx.cpp b/plugins/GSdx/stdafx.cpp index 9e45478e6..425f0d196 100644 --- a/plugins/GSdx/stdafx.cpp +++ b/plugins/GSdx/stdafx.cpp @@ -74,6 +74,7 @@ void vmfree(void* ptr, size_t size) #else #include +#include void* vmalloc(size_t size, bool code) { From 1b883ab9eec52a30c42d00fcc37dcec88d9f4223 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Sat, 17 Mar 2012 12:55:02 +0000 Subject: [PATCH 40/83] GSdx: Quick and sloppy fix for a sloppy hack, fixing FF12 pal. Thanks, pseudonym. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5133 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSRendererHW.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/GSdx/GSRendererHW.cpp b/plugins/GSdx/GSRendererHW.cpp index c5d7acce7..5968b7a76 100644 --- a/plugins/GSdx/GSRendererHW.cpp +++ b/plugins/GSdx/GSRendererHW.cpp @@ -433,7 +433,9 @@ bool GSRendererHW::OI_FFXII(GSTexture* rt, GSTexture* ds, GSTextureCache::Source { int x = (v->XYZ.X - ox) >> 4; int y = (v->XYZ.Y - oy) >> 4; - + + if (x >= 448 || y >= (int)lines) return false; // sigh + video[(y << 8) + (y << 7) + (y << 6) + x] = v->RGBAQ.u32[0]; } From e8b96f51cbe4322afcdd832d8d3f5d3e1c4d4fac Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Fri, 23 Mar 2012 19:37:43 +0000 Subject: [PATCH 41/83] GSdx: Updating the CRC list with some Korean titles. Thanks for the list, 99skull. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5134 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSCrc.cpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/plugins/GSdx/GSCrc.cpp b/plugins/GSdx/GSCrc.cpp index cf4565f8e..002f8be42 100644 --- a/plugins/GSdx/GSCrc.cpp +++ b/plugins/GSdx/GSCrc.cpp @@ -55,6 +55,7 @@ CRC::Game CRC::m_games[] = {0x48FE0C71, FFX2, US, 0}, {0x8A6D7F14, FFX2, JP, 0}, {0xE1FD9A2D, FFX2, JP, 0}, // int. + {0x11624CD6, FFX2, KO, 0}, {0x78DA0252, FFXII, EU, 0}, {0xC1274668, FFXII, EU, 0}, {0xDC2A467E, FFXII, EU, 0}, @@ -85,16 +86,21 @@ CRC::Game CRC::m_games[] = {0xAA31B5BF, MetalGearSolid3, US, 0}, {0x86BC3040, MetalGearSolid3, US, 0}, //Subsistance disc 1 {0x0481AD8A, MetalGearSolid3, JP, 0}, + {0xC69ACB6F, MetalGearSolid3, KO, 0}, //MetalGearSolid 3 SnakeEater + {0xB0D195EF, MetalGearSolid3, KO, 0}, //MetalGearSolid 3 Substance disc1 + {0x3EBABC9C, MetalGearSolid3, KO, 0}, //MetalGearSolid3Substance disc2 {0x278722BF, DBZBT2, US, 0}, {0xFE961D28, DBZBT2, US, 0}, {0x0393B6BE, DBZBT2, EU, 0}, {0xE2F289ED, DBZBT2, JP, 0}, // Sparking Neo! + {0xE29C09A3, DBZBT2, KO, 0}, //DragonBall Z Sparking Neo {0x35AA84D1, DBZBT2, NoRegion, 0}, {0x428113C2, DBZBT3, US, 0}, {0xA422BB13, DBZBT3, EU, 0}, {0xF28D21F1, DBZBT3, JP, 0}, {0x983C53D2, DBZBT3, NoRegion, 0}, {0x983C53D3, DBZBT3, NoRegion, 0}, + {0x9B0E119F, DBZBT3, KO, 0}, //DragonBall Z Sparking Meteo {0x72B3802A, SFEX3, US, 0}, {0x71521863, SFEX3, US, 0}, {0x28703748, Bully, US, 0}, @@ -103,8 +109,11 @@ CRC::Game CRC::m_games[] = {0x7D8F539A, SoTC, EU, 0}, {0x0F0C4A9C, SoTC, EU, 0}, {0x877F3436, SoTC, JP, 0}, + {0xA17D6AAA, SoTC, KO, 0}, {0x3122B508, OnePieceGrandAdventure, US, 0}, {0x8DF14A24, OnePieceGrandAdventure, EU, 0}, + {0xE446C9F9, OnePieceGrandAdventure, KO, 0}, + {0xCA2073B3, OnePieceGrandBattle, KO, 0}, {0xB049DD5E, OnePieceGrandBattle, US, 0}, {0x5D02CC5B, OnePieceGrandBattle, NoRegion, 0}, {0x6F8545DB, ICO, US, 0}, @@ -157,6 +166,8 @@ CRC::Game CRC::m_games[] = {0xEB001875, GodOfWar, EU, 0}, {0xCA052D22, GodOfWar, JP, 0}, {0xBFCC1795, GodOfWar, KO, 0}, + {0x9567B7D6, GodOfWar, KO, 0}, + {0x9B5C97BA, GodOfWar, KO, 0}, {0xA61A4C6D, GodOfWar, NoRegion, 0}, {0xE23D532B, GodOfWar, NoRegion, 0}, {0xDF1AF973, GodOfWar, NoRegion, 0}, @@ -176,6 +187,7 @@ CRC::Game CRC::m_games[] = {0xBF6F101F, GiTS, US, 0}, {0x95CC86EF, GiTS, US, 0}, {0xA5768F53, GiTS, JP, 0}, + {0xA3643EB1, GiTS, KO, 0}, {0x6BF11378, Onimusha3, US, 0}, {0x71320CA8, Onimusha3, JP, 0}, {0xDAFFFB0D, Onimusha3, KO, 0}, @@ -194,6 +206,7 @@ CRC::Game CRC::m_games[] = {0xD71B57F4, Genji, US, 0}, {0xFADEBC45, Genji, EU, 0}, {0xB4776FC1, Genji, JP, 0}, + {0x56242EC9, Genji, KO, 0}, {0x7D4EA48F, Genji, NoRegion, 0}, {0xE04EA200, StarOcean3, EU, 0}, {0x23A97857, StarOcean3, US, 0}, @@ -213,9 +226,12 @@ CRC::Game CRC::m_games[] = {0xD60DA6D4, SMTNocturne, JP, ZWriteMustNotClear}, // SMTNocturne {0x0E762E8D, SMTNocturne, JP, ZWriteMustNotClear}, // SMTNocturne Maniacs {0x47BA9034, SMTNocturne, JP, ZWriteMustNotClear}, // SMTNocturne Maniacs Chronicle + {0xD3FFC263, SMTNocturne, KO, ZWriteMustNotClear}, {0xD7273511, SMTDDS1, US, ZWriteMustNotClear}, // SMT Digital Devil Saga {0x1683A6BE, SMTDDS1, EU, ZWriteMustNotClear}, // SMT Digital Devil Saga {0x44865CE1, SMTDDS1, JP, ZWriteMustNotClear}, // SMT Digital Devil Saga + {0xF2E397C0, SMTDDS1, KO, ZWriteMustNotClear}, // SMT Digital Devil Saga + {0x43202D1A, SMTDDS2, KO, ZWriteMustNotClear}, // SMT Digital Devil Saga 2 {0xD382C164, SMTDDS2, US, ZWriteMustNotClear}, // SMT Digital Devil Saga 2 {0xD568B684, SMTDDS2, EU, ZWriteMustNotClear}, // SMT Digital Devil Saga 2 {0xE47C1A9C, SMTDDS2, JP, ZWriteMustNotClear}, // SMT Digital Devil Saga 2 @@ -228,17 +244,22 @@ CRC::Game CRC::m_games[] = {0x1969B19A, TenchuFS, ES, 0}, //PAL Spanish {0x696BBEC3, TenchuFS, KO, 0}, {0x525C1994, TenchuFS, ASIA, 0}, + {0x0D73BBCD, TenchuFS, KO, 0}, + {0xAFBFB287, TenchuWoH, KO, 0}, {0x767E383D, TenchuWoH, US, 0}, {0x83261085, TenchuWoH, EU, 0}, //PAL German {0x7FA1510D, TenchuWoH, EU, 0}, //PAL ES, IT {0x13DD9957, TenchuWoH, JP, 0}, {0x8BC95883, Sly3, US, 0}, {0x8164C614, Sly3, EU, 0}, + {0xA8CC1583, Sly3, KO, 0}, + {0x518DD841, Sly2, KO, 0}, {0x07652DD9, Sly2, US, 0}, {0xFDA1CBF6, Sly2, EU, 0}, {0x15DD1F6F, Sly2, NoRegion, 0}, {0xA9C82AB9, DemonStone, US, 0}, {0x7C7578F3, DemonStone, EU, 0}, + {0x22425C19, DemonStone, KO, 0}, {0x506644B3, BigMuthaTruckers, EU, 0}, {0x90F0D852, BigMuthaTruckers, US, 0}, {0x5CC9BF81, TimeSplitters2, EU, 0}, @@ -250,8 +271,10 @@ CRC::Game CRC::m_games[] = {0xDC43F2B8, LordOfTheRingsTwoTowers, EU, 0}, {0x9ABF90FB, LordOfTheRingsTwoTowers, ES, 0}, {0xC0E909E9, LordOfTheRingsTwoTowers, JP, 0}, + {0x6898435D, LordOfTheRingsTwoTowers, KO, 0}, {0xEB198738, LordOfTheRingsThirdAge, US, 0}, {0x614F4CF4, LordOfTheRingsThirdAge, EU, 0}, + {0x37CD4279, LordOfTheRingsThirdAge, KO, 0}, {0xE169BAF8, RedDeadRevolver, US, 0}, {0xE2E67E23, RedDeadRevolver, EU, 0}, {0xEDDD6573, SpidermanWoS, US, 0}, //Web of Shadows @@ -260,6 +283,7 @@ CRC::Game CRC::m_games[] = {0x2498951B, SilentHill3, US, 0}, {0x5088CCDB, SilentHill3, EU, 0}, {0x8CFE667F, SilentHill3, JP, 0}, + {0xC6CBDE91, SilentHill3, KO, 0}, {0x8E8E384B, SilentHill2, US, 0}, {0xFE06A030, SilentHill2, US, 0}, //greatest hits {0xE36E16C9, SilentHill2, JP, 0}, @@ -268,9 +292,11 @@ CRC::Game CRC::m_games[] = {0x6EB71AB0, BleachBladeBattlers, JP, 0}, //2nd {0x3A446111, CastlevaniaCoD, US, 0}, {0xF321BC38, CastlevaniaCoD, EU, 0}, + {0x950876FA, CastlevaniaCoD, KO, 0}, {0x28270F7D, CastlevaniaLoI, US, 0}, {0x306CDADA, CastlevaniaLoI, EU, 0}, {0xA36CFF6C, CastlevaniaLoI, JP, 0}, + {0x9A93FE5D, CastlevaniaLoI, KO, 0}, {0x5C891FF1, Black, US, 0}, {0xCAA04879, Black, EU, 0}, {0xADDFF505, Black, EU, 0}, //? @@ -284,6 +310,7 @@ CRC::Game CRC::m_games[] = {0x568A5C78, DigimonRumbleArena2, US, 0}, {0x785E22BB, DigimonRumbleArena2, EU, 0}, {0x4C5CE4C3, DigimonRumbleArena2, EU, 0}, + {0x115A184D, DigimonRumbleArena2, KO, 0}, {0x879CDA5E, StarWarsForceUnleashed, US, 0}, {0x137C792E, StarWarsForceUnleashed, US, 0}, {0x503BF9E1, StarWarsBattlefront, NoRegion, 0}, //EU and US versions have same CRC @@ -296,11 +323,13 @@ CRC::Game CRC::m_games[] = {0x7ADCB24A, DevilMayCry3, EU, 0}, {0x79C952B0, DevilMayCry3, JP, 0}, //SE {0x7F3DDEAB, DevilMayCry3, JP, 0}, + {0x05931990, DevilMayCry3, KO, 0}, {0xBEBF8793, BurnoutTakedown, US, 0}, {0x75BECC18, BurnoutTakedown, EU, 0}, {0xCE49B0DE, BurnoutTakedown, EU, 0}, {0xD224D348, BurnoutRevenge, US, 0}, {0x7E83CC5B, BurnoutRevenge, EU, 0}, + {0xEEA60511, BurnoutRevenge, KO, 0}, {0x8C9576A1, BurnoutDominator, US, 0}, {0x8C9576B4, BurnoutDominator, EU, 0}, {0x4A0E5B3A, MidnightClub3, US, 0}, //dub @@ -317,12 +346,14 @@ CRC::Game CRC::m_games[] = {0xC95F0198, SpyroEternalNight, NoRegion, 0}, {0x43AB7214, TalesOfLegendia, US, 0}, {0x1F8640E0, TalesOfLegendia, JP, 0}, + {0xE4F5DA2B, TalesOfLegendia, KO, 0}, {0x98C7B76D, NanoBreaker, US, 0}, {0x7098BE76, NanoBreaker, KO, 0}, {0x9B89F425, NanoBreaker, EU, 0}, {0x519E816B, Kunoichi, US, 0}, //Nightshade {0x3FB419FD, Kunoichi, JP, 0}, {0x3B470BBD, Kunoichi, EU, 0}, + {0x6BA65DD8, Kunoichi, KO, 0}, {0XD3F182A3, Yakuza, EU, 0}, {0x6F9F99F8, Yakuza, EU, 0}, {0x388F687B, Yakuza, US, 0}, From e017ccaa5d15819e2bf394c6304a7ac225119921 Mon Sep 17 00:00:00 2001 From: "sudonim1@gmail.com" Date: Fri, 23 Mar 2012 21:00:22 +0000 Subject: [PATCH 42/83] GSDx: Found the likely actual cause for the FFXII hack problems, probably introduced with index buffers. Also made the hack a little more crash proof and maybe fixed an off by one pixel error. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5135 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSRendererHW.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/GSdx/GSRendererHW.cpp b/plugins/GSdx/GSRendererHW.cpp index 5968b7a76..cb27133ca 100644 --- a/plugins/GSdx/GSRendererHW.cpp +++ b/plugins/GSdx/GSRendererHW.cpp @@ -424,17 +424,17 @@ bool GSRendererHW::OI_FFXII(GSTexture* rt, GSTexture* ds, GSTextureCache::Source if(!video) video = new uint32[512 * 512]; - int ox = m_context->XYOFFSET.OFX; - int oy = m_context->XYOFFSET.OFY; + int ox = m_context->XYOFFSET.OFX - 8; + int oy = m_context->XYOFFSET.OFY - 8; const GSVertex* RESTRICT v = m_vertex.buff; - for(int i = (int)m_vertex.next; i >= 0; i--, v++) + for(int i = (int)m_vertex.next; i > 0; i--, v++) { int x = (v->XYZ.X - ox) >> 4; int y = (v->XYZ.Y - oy) >> 4; - if (x >= 448 || y >= (int)lines) return false; // sigh + if (x < 0 || x >= 448 || y < 0 || y >= (int)lines) return false; // le sigh video[(y << 8) + (y << 7) + (y << 6) + x] = v->RGBAQ.u32[0]; } @@ -506,7 +506,7 @@ bool GSRendererHW::OI_MetalSlug6(GSTexture* rt, GSTexture* ds, GSTextureCache::S GSVertex* RESTRICT v = m_vertex.buff; - for(int i = (int)m_vertex.next; i >= 0; i--, v++) + for(int i = (int)m_vertex.next; i > 0; i--, v++) { uint32 c = v->RGBAQ.u32[0]; From 176e1de80c2b65da4e618a12a154020e98487dbe Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Fri, 30 Mar 2012 07:28:14 +0000 Subject: [PATCH 43/83] Game database update. Lots of Korean titles added by 99skull. Thanks :) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5136 96395faa-99c1-11dd-bbfe-3dabce05a288 --- bin/GameIndex.dbf | 521 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 521 insertions(+) diff --git a/bin/GameIndex.dbf b/bin/GameIndex.dbf index c86f951c8..00ae3f18e 100644 --- a/bin/GameIndex.dbf +++ b/bin/GameIndex.dbf @@ -83,6 +83,10 @@ --------------------------------------------- -- Game List --------------------------------------------- +Serial = PBPX-95201 +Name = Underwater Unit +Region = NTSC-K +--------------------------------------------- Serial = PBPX-95503 Name = Gran Turismo 3 - A-Spec [PS2 Bundle] Region = NTSC-U @@ -11854,6 +11858,20 @@ Serial = SCAJ-30011 Name = God of War II Region = NTSC-E --------------------------------------------- +Serial = SCKA-10006 +Name = Come on Baby +Region = NTSC-K +--------------------------------------------- +Serial = SCKA-20004 +Name = Sly Cooper and the Thievius Raccoonus +Region = NTSC-K +Compat = 5 +--------------------------------------------- +Serial = SCKA-20008 +Name = Tales of Destiny 2 +Region = NTSC-K +Compat = 5 +--------------------------------------------- Serial = SCKA-20009 Name = R-Type Final Region = NTSC-K @@ -11864,16 +11882,53 @@ Serial = SCKA-20010 Name = Jak II Region = NTSC-K --------------------------------------------- +Serial = SCKA-20011 +Name = Ratchet and Clank 2 +Region = NTSC-K +--------------------------------------------- Serial = SCKA-20012 Name = Ark the Lad - jeongryeongui Hwanghon Region = NTSC-K --------------------------------------------- +Serial = SCKA-20014 +Name = Dark Claud 2 +Region = NTSC-K +Compat = 5 +--------------------------------------------- +Serial = SCKA-20015 +Name = Time Crisis 3 +Region = NTSC-K +Compat = 5 +--------------------------------------------- +Serial = SCKA-20016 +Name = Soul Calibur 2 +Region = NTSC-K +Compat = 5 +vuClampMode = 2 //SPS(Spikey Polygon Syndrome) solution +--------------------------------------------- +Serial = SCKA-20018 +Name = The Getaway +Region = NTSC-K +--------------------------------------------- +Serial = SCKA-20019 +Name = Siren +Region = NTSC-K +--------------------------------------------- Serial = SCKA-20020 Name = SOCOM II - U.S. Navy SEALs Region = NTSC-K Compat = 5 VIF1StallHack = 1 //HUD --------------------------------------------- +Serial = SCKA-20022 +Name = Gran Turismo 4 Prologue +Region = NTSC-K +--------------------------------------------- +Serial = SCKA-20023 +Name = Fatal Frame 2 +Region = NTSC-K +Compat = 5 +--------------------------------------------- Serial = SCKA-20025 Name = Katamari Damacy Region = NTSC-K @@ -11883,6 +11938,11 @@ Serial = SCKA-20026 Name = Gungrave O.D. Region = NTSC-K --------------------------------------------- +Serial = SCKA-20027 +Name = Ghost in the Shell - Stand Alone Complex +Region = NTSC-K +Compat = 5 +--------------------------------------------- Serial = SCKA-20028 Name = Ico [PlayStation2 Big Hit Series] Region = NTSC-K @@ -11915,6 +11975,10 @@ Serial = SCKA-20038 Name = Time Crisis - Crisis Zone Region = NTSC-K --------------------------------------------- +Serial = SCKA-20039 +Name = Tekken Nina Williams In Death By Degree +Region = NTSC-K +--------------------------------------------- Serial = SCKA-20040 Name = Jak 3 Region = NTSC-K @@ -11923,6 +11987,15 @@ Serial = SCKA-20043 Name = Magna Carta Region = NTSC-K --------------------------------------------- +Serial = SCKA-20044 +Name = Sly Cooper 2 Band of Thieves +Region = NTSC-K +Compat = 5 +--------------------------------------------- +Serial = SCKA-20047 +Name = Armored Core Nine Breaker +Region = NTSC-K +--------------------------------------------- Serial = SCKA-20048 Name = Killzone Region = NTSC-K @@ -11935,12 +12008,18 @@ eeClampMode = 1 Serial = SCKA-20050 Name = Tales of Legendia Region = NTSC-K +Compat = 5 --------------------------------------------- Serial = SCKA-20051 Name = Minna Daisuki Katamari Damacy Region = NTSC-K SkipMPEGHack = 1 --------------------------------------------- +Serial = SCKA-20052 +Name = Genji +Region = NTSC-K +Compat = 5 +--------------------------------------------- Serial = SCKA-20053 Name = SOCOM II - U.S. Navy SEALs [PlayStation 2 Big Hit Series] Region = NTSC-K @@ -11966,6 +12045,7 @@ Region = NTSC-K Serial = SCKA-20059 Name = Soul Calibur III Region = NTSC-K +Compat = 5 --------------------------------------------- Serial = SCKA-20060 Name = Ratchet - Deadlocked @@ -11974,15 +12054,25 @@ Region = NTSC-K Serial = SCKA-20061 Name = Wanda to Kyozou (Shadow of the Colossus) Region = NTSC-K +Compat = 5 --------------------------------------------- Serial = SCKA-20062 Name = Ape Escape 3 Region = NTSC-K --------------------------------------------- +Serial = SCKA-20063 +Name = Sly Cooper 3 Honor Among Thieves +Region = NTSC-K +Compat = 5 +--------------------------------------------- Serial = SCKA-20064 Name = SOCOM 3 - U.S. Navy SEALs Region = NTSC-K --------------------------------------------- +Serial = SCKA-20069 +Name = Siren 2 +Region = NTSC-K +--------------------------------------------- Serial = SCKA-20070 Name = Ace Combat Zero - The Belkan War Region = NTSC-K @@ -12022,10 +12112,19 @@ Serial = SCKA-20087 Name = Shin Onimusha - Dawn of Dreams [Disc2of2] Region = NTSC-K --------------------------------------------- +Serial = SCKA-20090 +Name = God Hand +Region = NTSC-K +Compat = 5 +--------------------------------------------- Serial = SCKA-20092 Name = K-1 World Grand Prix 2006 Region = NTSC-K --------------------------------------------- +Serial = SCKA-20096 +Name = Barnyard +Region = NTSC-K +--------------------------------------------- Serial = SCKA-20099 Name = Persona 3 Region = NTSC-K @@ -12053,10 +12152,34 @@ Serial = SCKA-20117 Name = Super Robot Taisen OG - Original Generations Gaiden Region = NTSC-K --------------------------------------------- +Serial = SCKA-20120 +Name = Ratchet and Clank +Region = NTSC-K +--------------------------------------------- +Serial = SCKA-20132 +Name = Shin Megami Tensei - Persona 4 +Region = NTSC-K +Compat = 5 +VuClipFlagHack = 1 +--------------------------------------------- Serial = SCKA-24008 Name = SOCOM - U.S. Navy SEALs Region = NTSC-K --------------------------------------------- +Serial = SCKA-30001 +Name = Gran Turismo 4 +Region = NTSC-K +--------------------------------------------- +Serial = SCKA-30002 +Name = God of War +Region = NTSC-K +Compat = 5 +--------------------------------------------- +Serial = SCKA-30006 +Name = God of War 2 +Region = NTSC-K +Compat = 5 +--------------------------------------------- Serial = SCPS-11001 Name = I.Q. Remix Region = NTSC-J @@ -13229,10 +13352,51 @@ Serial = SCPS-55903 Name = Gran Turismo - Concept 2002 Tokyo-Geneva Region = NTSC-J --------------------------------------------- +Serial = SCPS-56001 +Name = Ico +Region = NTSC-K +Compat = 5 +eeClampMode = 2 // Otherwise freezes in various spots, check full intro +vuClampMode = 1 // Otherwise camera gets stuck off the player in various spots. +--------------------------------------------- +Serial = SCPS-56002 +Name = Tekken Tag Tournament +Region = NTSC-K +Compat = 5 +--------------------------------------------- +Serial = SCPS-56005 +Name = Gran Turismo Concept 2002 Tokyo-Seoul +Region = NTSC-K +--------------------------------------------- +Serial = SCPS-56006 +Name = Tekken 4 +Region = NTSC-K +Compat = 5 +[patches = 35B4028B] + comment=patches by Shadow Lady + //IPU BUSY! fix... + patch=0,EE,00290b24,word,24200001 + patch=0,EE,00290d24,word,00000000 +[/patches] +--------------------------------------------- +Serial = SCPS-56008 +Name = Fatal Frame +Region = NTSC-K +Compat = 5 +--------------------------------------------- Serial = SCPS-56011 Name = U - Underwater Unit Region = NTSC-J --------------------------------------------- +Serial = SCPS-56012 +Name = Raw Danger +Region = NTSC-K +--------------------------------------------- +Serial = SCPS-56014 +Name = Gungrave +Region = NTSC-K +Compat = 5 +--------------------------------------------- Serial = SCPS-56015 Name = Ninja Assault Region = NTSC-J @@ -13491,6 +13655,10 @@ Serial = SLAJ-35003 Name = Sakura Taisen - Atsuki Chishioni Ni Region = NTSC-Unk --------------------------------------------- +Serial = SLKA-15003 +Name = Shikigami no Shiro II +Region = NTSC-K +--------------------------------------------- Serial = SLKA-15004 Name = Gunbird - Premium Package Region = NTSC-J @@ -13500,10 +13668,37 @@ Name = Strikers 1945 III Region = NTSC-J Compat = 5 --------------------------------------------- +Serial = SLKA-15007 +Name = GrowLanser2 +Region = NTSC-K +Compat = 5 +OPHFLagHack = 1 +--------------------------------------------- Serial = SLKA-15008 Name = Choro Q HG2 Region = NTSC-E-F-G --------------------------------------------- +Serial = SLKA-15021 +Name = GrowLanser3 +Region = NTSC-K +Compat = 5 +OPHFLagHack = 1 +--------------------------------------------- +Serial = SLKA-15032 +Name = Gradius V +Region = NTSC-K +Compat = 5 +--------------------------------------------- +Serial = SLKA-25012 +Name = Davil May Cry 2 Dante +Region = NTSC-K +Compat = 5 +--------------------------------------------- +Serial = SLKA-25013 +Name = Davil May Cry 2 Lucia +Region = NTSC-K +Compat = 5 +--------------------------------------------- Serial = SLKA-25015 Name = Evolution Skateboarding Region = NTSC-K @@ -13511,11 +13706,21 @@ Region = NTSC-K Serial = SLKA-25021 Name = Shinobi Region = NTSC-M3 +Compat = 5 +--------------------------------------------- +Serial = SLKA-25024 +Name = Lilo & Stitch Experiment +Region = NTSC-K --------------------------------------------- Serial = SLKA-25026 Name = Chaos Legion Region = NTSC-K --------------------------------------------- +Serial = SLKA-25033 +Name = Gregory Horror Show +Region = NTSC-K +Compat = 1 +--------------------------------------------- Serial = SLKA-25035 Name = Mobile Suit Gundam - Lost War Chronicles Region = NTSC-K @@ -13524,14 +13729,37 @@ Serial = SLKA-25038 Name = Gun Survivor 4 - Biohazard - Heroes Never Die Region = NTSC-K --------------------------------------------- +Serial = SLKA-25041 +Name = Armored Core 3 Silent Line +Region = NTSC-K +--------------------------------------------- +Serial = SLKA-25042 +Name = Tamamayu Monogatari 2 Horobi no Mushi +Region = NTSC-K +--------------------------------------------- Serial = SLKA-25043 Name = Virtua Fighter 4 - Evolution Region = NTSC-K +Compat = 5 +--------------------------------------------- +Serial = SLKA-25046 +Name = Dragonball Z +Region = NTSC-K +--------------------------------------------- +Serial = SLKA-25048 +Name = Makai Senki Disgaea +Region = NTSC-K +Compat = 5 --------------------------------------------- Serial = SLKA-25049 Name = Metal Slug 3 Region = NTSC-K --------------------------------------------- +Serial = SLKA-25051 +Name = Clock Tower 3 +Region = NTSC-K +Compat = 5 +--------------------------------------------- Serial = SLKA-25052 Name = Air Ranger 2 - Rescue Helicopter Region = NTSC-K @@ -13540,18 +13768,51 @@ Serial = SLKA-25060 Name = I.Q. Remix+ - Intelligent Qube Region = NTSC-K --------------------------------------------- +Serial = SLKA-25062 +Name = Dragonball Z 2 +Region = NTSC-K +Compat = 5 +--------------------------------------------- Serial = SLKA-25063 Name = Kaido Battle Region = NTSC-K --------------------------------------------- +Serial = SLKA-25064 +Name = Tenchu 3 Wrath of Heaven +Region = NTSC-K +Compat = 5 +--------------------------------------------- +Serial = SLKA-25066 +Name = Zone of The Enders 2nd Runner SE +Region = NTSC-K +Compat = 5 +--------------------------------------------- +Serial = SLKA-25067 +Name = Unlimited Saga +Region = NTSC-K +--------------------------------------------- Serial = SLKA-25070 Name = Guity Gear XX Reload - The Midnight Carnival Region = NTSC-J-K --------------------------------------------- +Serial = SLKA-25071 +Name = Tantei Jinguji Saburo 8 Inocent Black +Region = NTSC-K +Compat = 5 +--------------------------------------------- Serial = SLKA-25077 Name = Culdicept II - Expansion Region = NTSC-K --------------------------------------------- +Serial = SLKA-25081 +Name = SD Gundam G Generation Neo +Region = NTSC-K +--------------------------------------------- +Serial = SLKA-25082 +Name = Castlevania Lament of Innocence +Region = NTSC-K +Compat = 5 +--------------------------------------------- Serial = SLKA-25087 Name = FIFA Soccer 2004 Region = NTSC-J @@ -13561,6 +13822,19 @@ Serial = SLKA-25091 Name = Hanjuku Hero vs. 3D Region = NTSC-K --------------------------------------------- +Serial = SLKA-25092 +Name = Onimusha Buraiden +Region = NTSC-K +--------------------------------------------- +Serial = SLKA-25093 +Name = Onimusha 3 Demon Siege +Region = NTSC-K +--------------------------------------------- +Serial = SLKA-25100 +Name = Dragon Quest V Dragon Quarter +Region = NTSC-K +Compat = 5 +--------------------------------------------- Serial = SLKA-25103 Name = Neon Genesis Evangelion 2 Region = NTSC-K @@ -13569,6 +13843,10 @@ Serial = SLKA-25112 Name = King of Fighters 2001, The Region = NTSC-K --------------------------------------------- +Serial = SLKA-25115 +Name = Rockman X7 +Region = NTSC-K +--------------------------------------------- Serial = SLKA-25125 Name = SNK vs. Capcom - Chaos Region = NTSC-K @@ -13581,6 +13859,10 @@ Serial = SLKA-25131 Name = Project Altered Beast Region = NTSC-K --------------------------------------------- +Serial = SLKA-25132 +Name = Mobile Suit Gundam Encounters in Space +Region = NTSC-K +--------------------------------------------- Serial = SLKA-25133 Name = AirForce Delta Strike Region = NTSC-K @@ -13590,6 +13872,11 @@ Serial = SLKA-25134 Name = NBA Street v3 Region = NTSC-K --------------------------------------------- +Serial = SLKA-25135 +Name = Kunoichi +Region = NTSC-K +Compat = 5 +--------------------------------------------- Serial = SLKA-25139 Name = Fu-un Shinsengumi Region = NTSC-K @@ -13597,6 +13884,12 @@ Region = NTSC-K Serial = SLKA-25144 Name = Final Fantasy X-2 Region = NTSC-K +Compat = 5 +--------------------------------------------- +Serial = SLKA-25149 +Name = Silent Hill 4 The Room +Region = NTSC-K +Compat = 5 --------------------------------------------- Serial = SLKA-25150 Name = Bujingai @@ -13610,6 +13903,10 @@ Serial = SLKA-25153 Name = Winning Eleven 10 - Liveware Edition Region = NTSC-K --------------------------------------------- +Serial = SLKA-25159 +Name = Astro Boy +Region = NTSC-K +--------------------------------------------- Serial = SLKA-25160 Name = Shin Megami Tensei III - Nocturne Maniax Region = NTSC-K @@ -13629,10 +13926,27 @@ Serial = SLKA-25167 Name = King of Fighters XI, The Region = NTSC-K --------------------------------------------- +Serial = SLKA-25170 +Name = SD Gundam G Generation Seed +Region = NTSC-K +--------------------------------------------- +Serial = SLKA-25171 +Name = Guon +Region = NTSC-K +Compat = 5 +--------------------------------------------- Serial = SLKA-25175 Name = Transformers Region = NTSC-K --------------------------------------------- +Serial = SLKA-25181 +Name = Energy Airforce Aim Strike +Region = NTSC-K +--------------------------------------------- +Serial = SLKA-25182 +Name = Hajime no Ippo2 Victorious Road +Region = NTSC-K +--------------------------------------------- Serial = SLKA-25183 Name = Street Fighter - Anniversary Collection Region = NTSC-K @@ -13641,14 +13955,28 @@ Serial = SLKA-25186 Name = King of Fighters, The - Maximum Impact [Limited Edition] Region = NTSC-K --------------------------------------------- +Serial = SLKA-25198 +Name = Tenchu Kurenai +Region = NTSC-K +Compat = 5 +--------------------------------------------- Serial = SLKA-25199 Name = Kengo 3 Region = NTSC-K +Compat = 5 --------------------------------------------- Serial = SLKA-25200 Name = SSX 3 [PlayStation 2 - Big Hit Series] Region = NTSC-K --------------------------------------------- +Serial = SLKA-25201 +Name = Armored Core Nexus Evolution DISC1 +Region = NTSC-K +--------------------------------------------- +Serial = SLKA-25202 +Name = Armored Core Nexus Revolution DISC2 +Region = NTSC-K +--------------------------------------------- Serial = SLKA-25204 Name = Showdown - Legends of Wrestling Region = NTSC-K @@ -13660,6 +13988,7 @@ Region = NTSC-K Serial = SLKA-25207 Name = Sakura Taisen V - Episode 0 - Samurai Girl of Wild Region = NTSC-K +Compat = 5 --------------------------------------------- Serial = SLKA-25208 Name = From TV Animation - One Piece - Round the Land! @@ -13668,6 +13997,7 @@ Region = NTSC-K Serial = SLKA-25213 Name = Berserk Region = NTSC-K +Compat = 5 --------------------------------------------- Serial = SLKA-25214 Name = Final Fantasy X - International [PlayStation 2 - Big Hit Series] @@ -13690,10 +14020,38 @@ Serial = SLKA-25218 Name = Hitman - Contracts Region = NTSC-K --------------------------------------------- +Serial = SLKA-25219 +Name = Monster Hunter G +Region = NTSC-K +Compat = 5 +--------------------------------------------- +Serial = SLKA-25221 +Name = Busin Zero +Region = NTSC-K +Compat = 5 +--------------------------------------------- +Serial = SLKA-25222 +Name = Rockman X8 +Region = NTSC-K +--------------------------------------------- Serial = SLKA-25224 Name = Detective Saburou Jinguji 9 - Kind of Blue Region = NTSC-K --------------------------------------------- +Serial = SLKA-25225 +Name = Dororo +Region = NTSC-K +Compat = 5 +--------------------------------------------- +Serial = SLKA-25227 +Name = Neo Contra +Region = NTSC-K +--------------------------------------------- +Serial = SLKA-25232 +Name = Naruto Naruthimetto Hero International +Region = NTSC-K +Compat = 5 +--------------------------------------------- Serial = SLKA-25233 Name = Sonic - Mega Collection Plus Region = NTSC-K @@ -13706,6 +14064,10 @@ Serial = SLKA-25244 Name = WWE SmackDown! vs. Raw Region = NTSC-K --------------------------------------------- +Serial = SLKA-25246 +Name = Bard's Tale +Region = NTSC-K +--------------------------------------------- Serial = SLKA-25249 Name = Ys - The Ark of Napishtim [with Guide Book] Region = NTSC-K @@ -13718,6 +14080,12 @@ Serial = SLKA-25252 Name = Forgotten Realms - Demon Stone Region = NTSC-K --------------------------------------------- +Serial = SLKA-25254 +Name = Digimon Rumble Arena 2 +Region = NTSC-K +Compat = 5 +FpuCompareHack = 1 +--------------------------------------------- Serial = SLKA-25255 Name = Mobile Suit Gundam - Seed - Never Ending Tomorrow Region = NTSC-K @@ -13726,6 +14094,11 @@ Serial = SLKA-25257 Name = Fu-un Bakumatsu Den Region = NTSC-K --------------------------------------------- +Serial = SLKA-25258 +Name = The Story of the Hero Yoshitsune +Region = NTSC-K +Compat = 5 +--------------------------------------------- Serial = SLKA-25259 Name = Swords of Destiny Region = NTSC-K @@ -13775,6 +14148,7 @@ Region = NTSC-K Serial = SLKA-25284 Name = Sakura Taisen 3 Region = NTSC-K +Compat = 1 --------------------------------------------- Serial = SLKA-25287 Name = Metal Slug 4&5 @@ -13811,12 +14185,30 @@ Region = NTSC-K Serial = SLKA-25300 Name = Digital Devil Saga [Special Package] Region = NTSC-J-K +Compat = 5 EETimingHack = 1 --------------------------------------------- +Serial = SLKA-25301 +Name = Digital Devil Saga - Avatar Tuner 2 +Region = NTSC-K +Compat = 5 +EETimingHack = 1 +--------------------------------------------- +Serial = SLKA-25307 +Name = Dragonball Z Sparking +Region = NTSC-K +Compat = 5 +--------------------------------------------- Serial = SLKA-25311 Name = Marvel Nemesis - Rise of the Imperfects Region = NTSC-K --------------------------------------------- +Serial = SLKA-25313 +Name = Naruto - Uzumaki Chronicles +Region = NTSC-K +Compat = 5 +OPHFLagHack = 1 +--------------------------------------------- Serial = SLKA-25317 Name = Shin Sangoku Musou 3 [PlayStation 2 - Big Hit Series] Region = NTSC-K @@ -13839,6 +14231,12 @@ Serial = SLKA-25323 Name = SSX On Tour Region = NTSC-J-K --------------------------------------------- +Serial = SLKA-25328 +Name = Castlevania - Curse of Dakness +Region = NTSC-K +Compat = 5 +vuClampMode = 0 //SPS with microVU +--------------------------------------------- Serial = SLKA-25329 Name = Shin Sangoku Musou 4 - Moushouden Region = NTSC-K @@ -13859,6 +14257,10 @@ Serial = SLKA-25342 Name = Ryu ga Gotoku Region = NTSC-K --------------------------------------------- +Serial = SLKA-25351 +Name = One Piece Pirates Carnival +Region = NTSC-K +--------------------------------------------- Serial = SLKA-25352 Name = Full Metal Alchemist - Dream Carnival Region = NTSC-K @@ -13866,19 +14268,35 @@ Region = NTSC-K Serial = SLKA-25353 Name = Metal Gear Solid 3 - Subsistance [Limited Edition] [Disc1of2] Region = NTSC-K +Compat = 5 --------------------------------------------- Serial = SLKA-25354 Name = Metal Gear Solid 3 - Subsistance [Limited Edition] [Disc2of2] Region = NTSC-K +Compat = 5 --------------------------------------------- Serial = SLKA-25359 Name = Winning Eleven 9 - Liveware Edition Region = NTSC-K --------------------------------------------- +Serial = SLKA-25361 +Name = Keroro Gunsou MeroMero Battle Royale Z +Region = NTSC-K +--------------------------------------------- Serial = SLKA-25364 Name = Mobile Suit Gundam - Climax U.C. Region = NTSC-K --------------------------------------------- +Serial = SLKA-25365 +Name = WWE Smack Down Vs RAW 2008 +Region = NTSC-K +--------------------------------------------- +Serial = SLKA-25366 +Name = Naruto - Uzumaki Chronicles 2 +Region = NTSC-K +Compat = 5 +OPHFLagHack = 1 +--------------------------------------------- Serial = SLKA-25375 Name = Transformers - The Game Region = NTSC-K @@ -13887,13 +14305,20 @@ Serial = SLKA-25381 Name = Winning Eleven 10 Region = NTSC-K --------------------------------------------- +Serial = SLKA-25384 +Name = Blazing Souls +Region = NTSC-K +--------------------------------------------- Serial = SLKA-25388 Name = One Piece - Grand Adventure Region = NTSC-K +Compat = 5 --------------------------------------------- Serial = SLKA-25389 Name = Shinobido Imashime Region = NTSC-K +Compat = 5 +eeClampMode = 3 //Otherwise freezes in some spot --------------------------------------------- Serial = SLKA-25390 Name = Shin Sangoku Musou 4 - Empires @@ -13903,6 +14328,11 @@ Serial = SLKA-25396 Name = FIFA '07 Region = NTSC-K --------------------------------------------- +Serial = SLKA-25397 +Name = Dragon Ball Z Sparking NEO +Region = NTSC-K +Compat = 5 +--------------------------------------------- Serial = SLKA-25406 Name = King of Fighters, The - Maximum Impact - Regulation A Region = NTSC-K @@ -13910,6 +14340,7 @@ Region = NTSC-K Serial = SLKA-25407 Name = DragonBall Z - Sparkling! Meteor Region = NTSC-K +Compat = 5 --------------------------------------------- Serial = SLKA-25413 Name = SD Gundam G - Generation Spirits @@ -13924,9 +14355,37 @@ Serial = SLKA-25424 Name = SNK Arcade Classics Vol.1 Region = NTSC-K --------------------------------------------- +Serial = SLKA-25443 +Name = Musou Orochi Maou Sairin +Region = NTSC-K +Compat = 5 +--------------------------------------------- +Serial = SLKA-25477 +Name = World Soccer Winning Eleven 2011 +Region = NTSC-K +--------------------------------------------- +Serial = SLKA-25480 +Name = World Soccer Winning Eleven 2012 +Region = NTSC-K +--------------------------------------------- +Serial = SLKA-35001 +Name = Metal Gear Solid 2 Substance +Region = NTSC-K +Compat = 5 +--------------------------------------------- Serial = SLKA-35003 Name = Sakura Taisen - Atsuki Chishioni Region = NTSC-K +Compat = 5 +--------------------------------------------- +Serial = SLKA-35004 +Name = Sakura Wars 5 So Long My Love +Region = NTSC-K +Compat = 5 +--------------------------------------------- +Serial = SLKA-35005 +Name = Shin Sangoku Musou 5 Special +Region = NTSC-K --------------------------------------------- Serial = SLPM-55005 Name = Mana Khemia 2: Ochita Gakuen to Renkinjutsushi Tachi @@ -16510,6 +16969,19 @@ Name = Fantasy Zone Complete Collection Region = NTSC-J Compat = 5 --------------------------------------------- +Serial = SLPM-64504 +Name = Maximo +Region = NTSC-K +--------------------------------------------- +Serial = SLPM-64522 +Name = La Pucelle +Region = NTSC-K +Compat = 5 +--------------------------------------------- +Serial = SLPM-64523 +Name = Marvel Vs Capcom 2 +Region = NTSC-K +--------------------------------------------- Serial = SLPM-64525 Name = Guilty Gear X Plus "By Your Side" Region = NTSC-K @@ -23603,23 +24075,72 @@ Serial = SLPM-67015 Name = School Days LxH Region = NTSC-J --------------------------------------------- +Serial = SLPM-67502 +Name = Devil May Cry +Region = NTSC-K +Compat = 5 +--------------------------------------------- +Serial = SLPM-67507 +Name = Onimusha Warlords +Region = NTSC-K +--------------------------------------------- +Serial = SLPM-67508 +Name = Gitaroo Man +Region = NTSC-K +Compat = 5 +eeRoundMode = 1 +vuRoundMode = 3 +--------------------------------------------- Serial = SLPM-67513 Name = Final Fantasy X International Region = NTSC-K IPUWaitHack = 1 --------------------------------------------- +Serial = SLPM-67514 +Name = Kessen +Region = NTSC-K +--------------------------------------------- +Serial = SLPM-67518 +Name = Onimusha 2 Samurai's Destiny +Region = NTSC-K +--------------------------------------------- +Serial = SLPM-67524 +Name = Armored Core 3 +Region = NTSC-K +--------------------------------------------- Serial = SLPM-67528 Name = Hajime no Ippo - Victorious Boxers [Championship Edition] Region = NTSC-K --------------------------------------------- +Serial = SLPM-67529 +Name = Gun Survivor 3 Dino Crisis +Region = NTSC-K +--------------------------------------------- +Serial = SLPM-67531 +Name = Kessen 2 +Region = NTSC-K +--------------------------------------------- Serial = SLPM-67535 Name = Memories Of Region = NTSC-J-K --------------------------------------------- +Serial = SLPM-67536 +Name = Senkaiden Hoshin Engi +Region = NTSC-K +--------------------------------------------- +Serial = SLPM-67540 +Name = Auto Modellista +Region = NTSC-K +Compat = 5 +--------------------------------------------- Serial = SLPM-67546 Name = Lord of the Rings - The Two Towers Region = NTSC-K --------------------------------------------- +Serial = SLPM-64549 +Name = Shikigami no Shiro +Region = NTSC-K +--------------------------------------------- Serial = SLPM-67552 Name = Tomak - Save the Earth Again [Complete Edition] Region = NTSC-K From b6954701e84b0fddd0bcd650c5a7eae90eeff10a Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Fri, 30 Mar 2012 19:04:26 +0000 Subject: [PATCH 44/83] cmake linux: don't build zerospu2. Too much issue on linux, uses spu2x instead. debian: fix nvidia cg dependency for latest Ubuntu git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5138 96395faa-99c1-11dd-bbfe-3dabce05a288 --- cmake/SelectPcsx2Plugins.cmake | 19 ++++--------------- debian-unstable-upstream/control | 4 ++-- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/cmake/SelectPcsx2Plugins.cmake b/cmake/SelectPcsx2Plugins.cmake index b4cf72779..060bf0681 100644 --- a/cmake/SelectPcsx2Plugins.cmake +++ b/cmake/SelectPcsx2Plugins.cmake @@ -188,20 +188,6 @@ else(SDL_FOUND) endif(SDL_FOUND) #--------------------------------------- -#--------------------------------------- -# zeropad -#--------------------------------------- -# requires: -SDL -#--------------------------------------- -if(SDL_FOUND) - set(zeropad TRUE) -else(SDL_FOUND) - set(zeropad FALSE) - message(STATUS "Skip build of zeropad: miss some dependencies") - message(STATUS "${msg_dep_zeropad}") -endif(SDL_FOUND) -#--------------------------------------- - #--------------------------------------- # SPU2null #--------------------------------------- @@ -235,7 +221,10 @@ endif(ALSA_FOUND AND PORTAUDIO_FOUND AND SOUNDTOUCH_FOUND AND common_libs) # -PortAudio #--------------------------------------- if(SOUNDTOUCH_FOUND AND ALSA_FOUND) - set(zerospu2 TRUE) + set(zerospu2 TRUE) + # Comment the next line, if you want to compile spu2x + set(zerospu2 FALSE) + message(STATUS "Don't build zerospu2. It is super-seeded by spu2x") else(SOUNDTOUCH_FOUND AND ALSA_FOUND) set(zerospu2 FALSE) message(STATUS "Skip build of zerospu2: miss some dependencies") diff --git a/debian-unstable-upstream/control b/debian-unstable-upstream/control index 9fe07dd28..b33dfba21 100644 --- a/debian-unstable-upstream/control +++ b/debian-unstable-upstream/control @@ -23,7 +23,7 @@ Build-Depends: cmake (>= 2.8), libx11-dev, locales | locales-all, # package was split in precise to allow multiarch support - libcg |nvidia-cg-toolkit (>= 3), + libcg, nvidia-cg-toolkit (>= 3), portaudio19-dev, zlib1g-dev (>= 1:1.2.3.3) Standards-Version: 3.9.2 @@ -49,7 +49,7 @@ Package: pcsx2-plugins-unstable Architecture: i386 # manually add nvidia-cg-toolkit for zzogl (cg pacakge does not provide symbol or shlibs files) Depends: ${shlibs:Depends}, ${misc:Depends}, - nvidia-cg-toolkit-pcsx2 | nvidia-cg-toolkit (>= 2.1) + libcg | nvidia-cg-toolkit (>= 2.1) Recommends: pcsx2-unstable (>= ${binary:Version}), Conflicts: pcsx2-plugins, pcsx2-data-unstable From 03db2fcf4e82ace156577fbb7bf242357a7ee645 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Sun, 1 Apr 2012 14:09:24 +0000 Subject: [PATCH 45/83] SPU2-X: Some games use volume slides combined with reversed phase. Gigaherz tweaked the code to handle this nicer (fixes Mashed Drive to Survive noises). git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5139 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/spu2-x/src/ADSR.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/plugins/spu2-x/src/ADSR.cpp b/plugins/spu2-x/src/ADSR.cpp index c4eb4b00d..0e902bd53 100644 --- a/plugins/spu2-x/src/ADSR.cpp +++ b/plugins/spu2-x/src/ADSR.cpp @@ -196,21 +196,23 @@ void V_VolumeSlide::Update() if( Increment == 0x7f ) return; + s32 value = abs(Value); + if (Mode & VOLFLAG_DECREMENT) { // Decrement if(Mode & VOLFLAG_EXPONENTIAL) { - u32 off = InvExpOffsets[(Value>>28)&7]; - Value -= PsxRates[(Increment^0x7f)-0x1b+off+32]; + u32 off = InvExpOffsets[(value>>28)&7]; + value -= PsxRates[(Increment^0x7f)-0x1b+off+32]; } else - Value -= PsxRates[(Increment^0x7f)-0xf+32]; + value -= PsxRates[(Increment^0x7f)-0xf+32]; - if (Value < 0) + if (value < 0) { - Value = 0; + value = 0; Mode = 0; // disable slide } } @@ -220,16 +222,18 @@ void V_VolumeSlide::Update() // Pseudo-exponential increments, as done by the SPU2 (really!) // Above 75% slides slow, below 75% slides fast. It's exponential, pseudo'ly speaking. - if( (Mode & VOLFLAG_EXPONENTIAL) && (Value>=0x60000000)) - Value += PsxRates[(Increment^0x7f)-0x18+32]; + if( (Mode & VOLFLAG_EXPONENTIAL) && (value>=0x60000000)) + value += PsxRates[(Increment^0x7f)-0x18+32]; else // linear / Pseudo below 75% (they're the same) - Value += PsxRates[(Increment^0x7f)-0x10+32]; + value += PsxRates[(Increment^0x7f)-0x10+32]; - if( Value < 0 ) // wrapped around the "top"? + if( value < 0 ) // wrapped around the "top"? { - Value = 0x7fffffff; + value = 0x7fffffff; Mode = 0; // disable slide } } + + Value = (Value < 0) ? -value : value; } From 4512a3cad02de607f3bb60e5e3334a5f3e606c9f Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Thu, 5 Apr 2012 19:49:49 +0000 Subject: [PATCH 46/83] A recently added fix for warnings under Linux is creating an assert on Windows. The problem only affects debug builds but it should get a review. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5141 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/gui/RecentIsoList.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pcsx2/gui/RecentIsoList.cpp b/pcsx2/gui/RecentIsoList.cpp index eecd7e718..34a2c284c 100644 --- a/pcsx2/gui/RecentIsoList.cpp +++ b/pcsx2/gui/RecentIsoList.cpp @@ -122,6 +122,12 @@ void RecentIsoManager::Repopulate() m_Separator = m_Menu->AppendSeparator(); // The following line is important + // Update: It also makes debug WX assert on Windows. Can we review wether this is needed in Linux at all? + // Below is a version that doesn't trigger the assert (WX on Windows complains about an empty string), but + // ideally this line should get removed. + + //wxString temp = L"isupresswarnings"; + //m_Menu->Remove( m_Menu->Append( -1, temp ) ); m_Menu->Remove( m_Menu->Append( -1, wxEmptyString ) ); //Note: the internal recent iso list (m_Items) has the most recent item last (also at the INI file) From 5561415088860601a138485a41837c66a0fe3d85 Mon Sep 17 00:00:00 2001 From: "sudonim1@gmail.com" Date: Thu, 5 Apr 2012 19:55:44 +0000 Subject: [PATCH 47/83] Workaround for the MTVU deadlock on exit issue. There are actually several issues which deserve closer examination here but this fixes the symptom of zombie pcsx2 instances. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5142 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/System/SysCoreThread.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pcsx2/System/SysCoreThread.cpp b/pcsx2/System/SysCoreThread.cpp index 0a9a600b6..8248252cf 100644 --- a/pcsx2/System/SysCoreThread.cpp +++ b/pcsx2/System/SysCoreThread.cpp @@ -23,6 +23,7 @@ #include "Elfheader.h" #include "Patch.h" #include "SysThreads.h" +#include "MTVU.h" #include "Utilities/PageFaultSource.h" #include "Utilities/TlsVariable.inl" @@ -278,6 +279,8 @@ void SysCoreThread::OnCleanupInThread() m_hasActiveMachine = false; m_resetVirtualMachine = true; + // FIXME: temporary workaround for deadlock on exit, which actually should be a crash + vu1Thread.WaitVU(); GetCorePlugins().Close(); GetCorePlugins().Shutdown(); From 0ecca4b7de6806679049e6acb7cc7435200d8714 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Fri, 6 Apr 2012 09:52:18 +0000 Subject: [PATCH 48/83] Workaround for the debug build assertion problem discussed in r5141. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5143 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/gui/RecentIsoList.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/pcsx2/gui/RecentIsoList.cpp b/pcsx2/gui/RecentIsoList.cpp index 34a2c284c..492a08fd1 100644 --- a/pcsx2/gui/RecentIsoList.cpp +++ b/pcsx2/gui/RecentIsoList.cpp @@ -121,15 +121,14 @@ void RecentIsoManager::Repopulate() m_Separator = m_Menu->AppendSeparator(); - // The following line is important - // Update: It also makes debug WX assert on Windows. Can we review wether this is needed in Linux at all? - // Below is a version that doesn't trigger the assert (WX on Windows complains about an empty string), but - // ideally this line should get removed. - - //wxString temp = L"isupresswarnings"; - //m_Menu->Remove( m_Menu->Append( -1, temp ) ); + // From arcum's comment on r5141 + // What was happening is that when all the radio button menu items in a group are deleted, + // wxwidgets deletes the group, but when you start adding radio menu items again, + // it trys to add them to a group that doesn't exist. Since the group doesn't exist, + // it starts a new group, but it also spews a couple warnings about it in Linux. +#ifdef __LINUX__ m_Menu->Remove( m_Menu->Append( -1, wxEmptyString ) ); - +#endif //Note: the internal recent iso list (m_Items) has the most recent item last (also at the INI file) // but the menu is composed in reverse order such that the most recent item appears at the top. for( int i=cnt-1; i>=0; --i ) From 20b0627e8e670c6985cb6bce6bd511ef41759225 Mon Sep 17 00:00:00 2001 From: "sudonim1@gmail.com" Date: Fri, 6 Apr 2012 11:34:02 +0000 Subject: [PATCH 49/83] MTVU: Move code out of header. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5144 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/MTVU.cpp | 324 +++++++++++++++++++++++++++++++++++++++++- pcsx2/MTVU.h | 321 ++++++----------------------------------- pcsx2/x86/microVU.cpp | 2 +- 3 files changed, 366 insertions(+), 281 deletions(-) diff --git a/pcsx2/MTVU.cpp b/pcsx2/MTVU.cpp index 5e7de0446..43d40f7ba 100644 --- a/pcsx2/MTVU.cpp +++ b/pcsx2/MTVU.cpp @@ -17,21 +17,341 @@ #include "Common.h" #include "MTVU.h" #include "newVif.h" +#include "Gif_Unit.h" __aligned16 VU_Thread vu1Thread(CpuVU1, VU1); +#define volatize(x) (*reinterpret_cast(&(x))) +#define size_u32(x) (((u32)x+3u)>>2) // Rounds up a size in bytes for size in u32's +#define MTVU_ALWAYS_KICK 0 +#define MTVU_SYNC_MODE 0 + +enum MTVU_EVENT { + MTVU_VU_EXECUTE, // Execute VU program + MTVU_VU_WRITE_MICRO, // Write to VU micro-mem + MTVU_VU_WRITE_DATA, // Write to VU data-mem + MTVU_VIF_WRITE_COL, // Write to Vif col reg + MTVU_VIF_WRITE_ROW, // Write to Vif row reg + MTVU_VIF_UNPACK, // Execute Vif Unpack + MTVU_NULL_PACKET, // Go back to beginning of buffer + MTVU_RESET +}; + // Calls the vif unpack functions from the MTVU thread -void MTVU_Unpack(void* data, VIFregisters& vifRegs) { +static void MTVU_Unpack(void* data, VIFregisters& vifRegs) +{ bool isFill = vifRegs.cycle.cl < vifRegs.cycle.wl; if (newVifDynaRec) dVifUnpack<1>((u8*)data, isFill); else _nVifUnpack(1, (u8*)data, vifRegs.mode, isFill); } // Called on Saving/Loading states... -void SaveStateBase::mtvuFreeze() { +void SaveStateBase::mtvuFreeze() +{ FreezeTag("MTVU"); pxAssert(vu1Thread.IsDone()); if (!IsSaving()) vu1Thread.Reset(); Freeze(vu1Thread.vuCycles); Freeze(vu1Thread.vuCycleIdx); } + +VU_Thread::VU_Thread(BaseVUmicroCPU*& _vuCPU, VURegs& _vuRegs) : + vuCPU(_vuCPU), vuRegs(_vuRegs) +{ + m_name = L"MTVU"; + Reset(); +} + +VU_Thread::~VU_Thread() throw() +{ + pxThread::Cancel(); +} + +void VU_Thread::Reset() +{ + read_pos = 0; + write_pos = 0; + write_offset = 0; + vuCycleIdx = 0; + isBusy = false; + memzero(vif); + memzero(vifRegs); + memzero(vuCycles); +} + +void VU_Thread::ExecuteTaskInThread() +{ + PCSX2_PAGEFAULT_PROTECT { + ExecuteRingBuffer(); + } PCSX2_PAGEFAULT_EXCEPT; +} + +void VU_Thread::ExecuteRingBuffer() +{ + for(;;) { + semaEvent.WaitWithoutYield(); + ScopedLockBool lock(mtxBusy, isBusy); + while (read_pos != GetWritePos()) { + u32 tag = Read(); + switch (tag) { + case MTVU_VU_EXECUTE: { + vuRegs.cycle = 0; + s32 addr = Read(); + vifRegs.top = Read(); + vifRegs.itop = Read(); + if (addr != -1) vuRegs.VI[REG_TPC].UL = addr; + vuCPU->Execute(vu1RunCycles); + gifUnit.gifPath[GIF_PATH_1].FinishGSPacketMTVU(); + semaXGkick.Post(); // Tell MTGS a path1 packet is complete + AtomicExchange(vuCycles[vuCycleIdx], vuRegs.cycle); + vuCycleIdx = (vuCycleIdx + 1) & 3; + break; + } + case MTVU_VU_WRITE_MICRO: { + u32 vu_micro_addr = Read(); + u32 size = Read(); + vuCPU->Clear(vu_micro_addr, size); + Read(&vuRegs.Micro[vu_micro_addr], size); + break; + } + case MTVU_VU_WRITE_DATA: { + u32 vu_data_addr = Read(); + u32 size = Read(); + Read(&vuRegs.Mem[vu_data_addr], size); + break; + } + case MTVU_VIF_WRITE_COL: + Read(&vif.MaskCol, sizeof(vif.MaskCol)); + break; + case MTVU_VIF_WRITE_ROW: + Read(&vif.MaskRow, sizeof(vif.MaskRow)); + break; + case MTVU_VIF_UNPACK: { + u32 vif_copy_size = (uptr)&vif.StructEnd - (uptr)&vif.tag; + Read(&vif.tag, vif_copy_size); + ReadRegs(&vifRegs); + u32 size = Read(); + MTVU_Unpack(&buffer[read_pos], vifRegs); + incReadPos(size_u32(size)); + break; + } + case MTVU_NULL_PACKET: + AtomicExchange(read_pos, 0); + break; + jNO_DEFAULT; + } + } + } +} + + +// Should only be called by ReserveSpace() +__ri void VU_Thread::WaitOnSize(s32 size) +{ + for(;;) { + s32 readPos = GetReadPos(); + if (readPos <= write_pos) break; // MTVU is reading in back of write_pos + if (readPos > write_pos + size) break; // Enough free front space + if (1) { // Let MTVU run to free up buffer space + KickStart(); + if (IsDevBuild) DevCon.WriteLn("WaitOnSize()"); + ScopedLock lock(mtxBusy); + } + } +} + +// Makes sure theres enough room in the ring buffer +// to write a continuous 'size * sizeof(u32)' bytes +void VU_Thread::ReserveSpace(s32 size) +{ + pxAssert(write_pos < buffer_size); + pxAssert(size < buffer_size); + pxAssert(size > 0); + pxAssert(write_offset == 0); + if (write_pos + size > buffer_size) { + pxAssert(write_pos > 0); + WaitOnSize(1); // Size of MTVU_NULL_PACKET + Write(MTVU_NULL_PACKET); + write_offset = 0; + AtomicExchange(volatize(write_pos), 0); + } + WaitOnSize(size); +} + +// Use this when reading read_pos from ee thread +__fi volatile s32 VU_Thread::GetReadPos() +{ + return AtomicRead(read_pos); +} +// Use this when reading write_pos from vu thread +__fi volatile s32 VU_Thread::GetWritePos() +{ + return AtomicRead(volatize(write_pos)); +} +// Gets the effective write pointer after adding write_offset +__fi u32* VU_Thread::GetWritePtr() +{ + return &buffer[(write_pos + write_offset) & buffer_mask]; +} + +__fi void VU_Thread::incReadPos(s32 offset) +{ // Offset in u32 sizes + s32 temp = (read_pos + offset) & buffer_mask; + AtomicExchange(read_pos, temp); +} +__fi void VU_Thread::incWritePos() +{ // Adds write_offset + s32 temp = (write_pos + write_offset) & buffer_mask; + write_offset = 0; + AtomicExchange(volatize(write_pos), temp); + if (MTVU_ALWAYS_KICK) KickStart(); + if (MTVU_SYNC_MODE) WaitVU(); +} + +__fi u32 VU_Thread::Read() +{ + u32 ret = buffer[read_pos]; + incReadPos(1); + return ret; +} + +__fi void VU_Thread::Read(void* dest, u32 size) +{ + memcpy_fast(dest, &buffer[read_pos], size); + incReadPos(size_u32(size)); +} + +__fi void VU_Thread::ReadRegs(VIFregisters* dest) +{ + VIFregistersMTVU* src = (VIFregistersMTVU*)&buffer[read_pos]; + dest->cycle = src->cycle; + dest->mode = src->mode; + dest->num = src->num; + dest->mask = src->mask; + dest->itop = src->itop; + dest->top = src->top; + incReadPos(size_u32(sizeof(VIFregistersMTVU))); +} + +__fi void VU_Thread::Write(u32 val) +{ + GetWritePtr()[0] = val; + write_offset += 1; +} +__fi void VU_Thread::Write(void* src, u32 size) +{ + memcpy_fast(GetWritePtr(), src, size); + write_offset += size_u32(size); +} + +__fi void VU_Thread::WriteRegs(VIFregisters* src) +{ + VIFregistersMTVU* dest = (VIFregistersMTVU*)GetWritePtr(); + dest->cycle = src->cycle; + dest->mode = src->mode; + dest->num = src->num; + dest->mask = src->mask; + dest->top = src->top; + dest->itop = src->itop; + write_offset += size_u32(sizeof(VIFregistersMTVU)); +} + +// Returns Average number of vu Cycles from last 4 runs +// Used for vu cycle stealing hack +u32 VU_Thread::Get_vuCycles() +{ + return (AtomicRead(vuCycles[0]) + AtomicRead(vuCycles[1]) + + AtomicRead(vuCycles[2]) + AtomicRead(vuCycles[3])) >> 2; +} + +void VU_Thread::KickStart(bool forceKick) +{ + if ((forceKick && !semaEvent.Count()) + || (!isBusy && GetReadPos() != write_pos)) semaEvent.Post(); +} + +bool VU_Thread::IsDone() +{ + return !isBusy && GetReadPos() == GetWritePos(); +} + +void VU_Thread::WaitVU() +{ + MTVU_LOG("MTVU - WaitVU!"); + for(;;) { + if (IsDone()) break; + //DevCon.WriteLn("WaitVU()"); + pxAssert(THREAD_VU1); + KickStart(); + ScopedLock lock(mtxBusy); + } +} + +void VU_Thread::ExecuteVU(u32 vu_addr, u32 vif_top, u32 vif_itop) +{ + MTVU_LOG("MTVU - ExecuteVU!"); + ReserveSpace(4); + Write(MTVU_VU_EXECUTE); + Write(vu_addr); + Write(vif_top); + Write(vif_itop); + incWritePos(); + gifUnit.TransferGSPacketData(GIF_TRANS_MTVU, NULL, 0); + KickStart(); + u32 cycles = std::min(Get_vuCycles(), 3000u); + cpuRegs.cycle += cycles * EmuConfig.Speedhacks.VUCycleSteal; +} + +void VU_Thread::VifUnpack(vifStruct& _vif, VIFregisters& _vifRegs, u8* data, u32 size) +{ + MTVU_LOG("MTVU - VifUnpack!"); + u32 vif_copy_size = (uptr)&_vif.StructEnd - (uptr)&_vif.tag; + ReserveSpace(1 + size_u32(vif_copy_size) + size_u32(sizeof(VIFregistersMTVU)) + 1 + size_u32(size)); + Write(MTVU_VIF_UNPACK); + Write(&_vif.tag, vif_copy_size); + WriteRegs(&_vifRegs); + Write(size); + Write(data, size); + incWritePos(); + KickStart(); +} + +void VU_Thread::WriteMicroMem(u32 vu_micro_addr, void* data, u32 size) +{ + MTVU_LOG("MTVU - WriteMicroMem!"); + ReserveSpace(3 + size_u32(size)); + Write(MTVU_VU_WRITE_MICRO); + Write(vu_micro_addr); + Write(size); + Write(data, size); + incWritePos(); +} + +void VU_Thread::WriteDataMem(u32 vu_data_addr, void* data, u32 size) +{ + MTVU_LOG("MTVU - WriteDataMem!"); + ReserveSpace(3 + size_u32(size)); + Write(MTVU_VU_WRITE_DATA); + Write(vu_data_addr); + Write(size); + Write(data, size); + incWritePos(); +} + +void VU_Thread::WriteCol(vifStruct& _vif) +{ + MTVU_LOG("MTVU - WriteCol!"); + ReserveSpace(1 + size_u32(sizeof(_vif.MaskCol))); + Write(MTVU_VIF_WRITE_COL); + Write(&_vif.MaskCol, sizeof(_vif.MaskCol)); + incWritePos(); +} + +void VU_Thread::WriteRow(vifStruct& _vif) +{ + MTVU_LOG("MTVU - WriteRow!"); + ReserveSpace(1 + size_u32(sizeof(_vif.MaskRow))); + Write(MTVU_VIF_WRITE_ROW); + Write(&_vif.MaskRow, sizeof(_vif.MaskRow)); + incWritePos(); +} \ No newline at end of file diff --git a/pcsx2/MTVU.h b/pcsx2/MTVU.h index a2fe81ff4..052bfdac5 100644 --- a/pcsx2/MTVU.h +++ b/pcsx2/MTVU.h @@ -4,32 +4,15 @@ #include "Vif.h" #include "Vif_Dma.h" #include "VUmicro.h" -#include "Gif_Unit.h" -extern void MTVU_Unpack(void* data, VIFregisters& vifRegs); -#define volatize(x) (*reinterpret_cast(&(x))) -#define size_u32(x) (((u32)x+3u)>>2) // Rounds up a size in bytes for size in u32's -#define MTVU_ALWAYS_KICK 0 -#define MTVU_SYNC_MODE 0 #define MTVU_LOG(...) do{} while(0) //#define MTVU_LOG DevCon.WriteLn -enum MTVU_EVENT { - MTVU_VU_EXECUTE, // Execute VU program - MTVU_VU_WRITE_MICRO, // Write to VU micro-mem - MTVU_VU_WRITE_DATA, // Write to VU data-mem - MTVU_VIF_WRITE_COL, // Write to Vif col reg - MTVU_VIF_WRITE_ROW, // Write to Vif row reg - MTVU_VIF_UNPACK, // Execute Vif Unpack - MTVU_NULL_PACKET, // Go back to beginning of buffer - MTVU_RESET -}; - // Notes: // - This class should only be accessed from the EE thread... // - buffer_size must be power of 2 // - ring-buffer has no complete pending packets when read_pos==write_pos -struct VU_Thread : public pxThread { +class VU_Thread : public pxThread { static const u32 buffer_size = (_1mb * 16) / sizeof(u32); static const u32 buffer_mask = buffer_size - 1; __aligned(4) u32 buffer[buffer_size]; @@ -39,287 +22,69 @@ struct VU_Thread : public pxThread { __aligned(4) s32 write_offset; // Only modified by EE thread __aligned(4) Mutex mtxBusy; __aligned(4) Semaphore semaEvent; - __aligned(4) Semaphore semaXGkick; __aligned(4) BaseVUmicroCPU*& vuCPU; __aligned(4) VURegs& vuRegs; + +public: __aligned16 vifStruct vif; __aligned16 VIFregisters vifRegs; + __aligned(4) Semaphore semaXGkick; __aligned(4) u32 vuCycles[4]; // Used for VU cycle stealing hack __aligned(4) u32 vuCycleIdx; // Used for VU cycle stealing hack - VU_Thread(BaseVUmicroCPU*& _vuCPU, VURegs& _vuRegs) : - vuCPU(_vuCPU), vuRegs(_vuRegs) { - m_name = L"MTVU"; - Reset(); - } - virtual ~VU_Thread() throw() { - pxThread::Cancel(); - } - void InitThread() { - Start(); // Starts the pxThread - } - void Reset() { - read_pos = 0; - write_pos = 0; - write_offset = 0; - vuCycleIdx = 0; - isBusy = false; - memzero(vif); - memzero(vifRegs); - memzero(vuCycles); - } -protected: - // Should only be called by ReserveSpace() - __ri void WaitOnSize(s32 size) { - for(;;) { - s32 readPos = GetReadPos(); - if (readPos <= write_pos) break; // MTVU is reading in back of write_pos - if (readPos > write_pos + size) break; // Enough free front space - if (1) { // Let MTVU run to free up buffer space - KickStart(); - if (IsDevBuild) DevCon.WriteLn("WaitOnSize()"); - ScopedLock lock(mtxBusy); - } - } - } + VU_Thread(BaseVUmicroCPU*& _vuCPU, VURegs& _vuRegs); + virtual ~VU_Thread() throw(); - // Makes sure theres enough room in the ring buffer - // to write a continuous 'size * sizeof(u32)' bytes - void ReserveSpace(s32 size) { - pxAssert(write_pos < buffer_size); - pxAssert(size < buffer_size); - pxAssert(size > 0); - pxAssert(write_offset == 0); - if (write_pos + size > buffer_size) { - pxAssert(write_pos > 0); - WaitOnSize(1); // Size of MTVU_NULL_PACKET - Write(MTVU_NULL_PACKET); - write_offset = 0; - AtomicExchange(volatize(write_pos), 0); - } - WaitOnSize(size); - } + void Reset(); - // Use this when reading read_pos from ee thread - __fi volatile s32 GetReadPos() { - return AtomicRead(read_pos); - } - // Use this when reading write_pos from vu thread - __fi volatile s32 GetWritePos() { - return AtomicRead(volatize(write_pos)); - } - // Gets the effective write pointer after adding write_offset - __fi u32* GetWritePtr() { - return &buffer[(write_pos + write_offset) & buffer_mask]; - } - - __fi void incReadPos(s32 offset) { // Offset in u32 sizes - s32 temp = (read_pos + offset) & buffer_mask; - AtomicExchange(read_pos, temp); - } - __fi void incWritePos() { // Adds write_offset - s32 temp = (write_pos + write_offset) & buffer_mask; - write_offset = 0; - AtomicExchange(volatize(write_pos), temp); - if (MTVU_ALWAYS_KICK) KickStart(); - if (MTVU_SYNC_MODE) WaitVU(); - } - - __fi u32 Read() { - u32 ret = buffer[read_pos]; - incReadPos(1); - return ret; - } - __fi void Read(void* dest, u32 size) { // Size in bytes - memcpy_fast(dest, &buffer[read_pos], size); - incReadPos(size_u32(size)); - } - __fi void ReadRegs(VIFregisters* dest) { - VIFregistersMTVU* src = (VIFregistersMTVU*)&buffer[read_pos]; - dest->cycle = src->cycle; - dest->mode = src->mode; - dest->num = src->num; - dest->mask = src->mask; - dest->itop = src->itop; - dest->top = src->top; - incReadPos(size_u32(sizeof(VIFregistersMTVU))); - } - - __fi void Write(u32 val) { - GetWritePtr()[0] = val; - write_offset += 1; - } - __fi void Write(void* src, u32 size) { // Size in bytes - memcpy_fast(GetWritePtr(), src, size); - write_offset += size_u32(size); - } - __fi void WriteRegs(VIFregisters* src) { - VIFregistersMTVU* dest = (VIFregistersMTVU*)GetWritePtr(); - dest->cycle = src->cycle; - dest->mode = src->mode; - dest->num = src->num; - dest->mask = src->mask; - dest->top = src->top; - dest->itop = src->itop; - write_offset += size_u32(sizeof(VIFregistersMTVU)); - } - - void ExecuteTaskInThread() { - PCSX2_PAGEFAULT_PROTECT { - ExecuteRingBuffer(); - } PCSX2_PAGEFAULT_EXCEPT; - } - - void ExecuteRingBuffer() { - for(;;) { - semaEvent.WaitWithoutYield(); - ScopedLockBool lock(mtxBusy, isBusy); - while (read_pos != GetWritePos()) { - u32 tag = Read(); - switch (tag) { - case MTVU_VU_EXECUTE: { - vuRegs.cycle = 0; - s32 addr = Read(); - vifRegs.top = Read(); - vifRegs.itop = Read(); - if (addr != -1) vuRegs.VI[REG_TPC].UL = addr; - vuCPU->Execute(vu1RunCycles); - gifUnit.gifPath[GIF_PATH_1].FinishGSPacketMTVU(); - semaXGkick.Post(); // Tell MTGS a path1 packet is complete - AtomicExchange(vuCycles[vuCycleIdx], vuRegs.cycle); - vuCycleIdx = (vuCycleIdx + 1) & 3; - break; - } - case MTVU_VU_WRITE_MICRO: { - u32 vu_micro_addr = Read(); - u32 size = Read(); - vuCPU->Clear(vu_micro_addr, size); - Read(&vuRegs.Micro[vu_micro_addr], size); - break; - } - case MTVU_VU_WRITE_DATA: { - u32 vu_data_addr = Read(); - u32 size = Read(); - Read(&vuRegs.Mem[vu_data_addr], size); - break; - } - case MTVU_VIF_WRITE_COL: - Read(&vif.MaskCol, sizeof(vif.MaskCol)); - break; - case MTVU_VIF_WRITE_ROW: - Read(&vif.MaskRow, sizeof(vif.MaskRow)); - break; - case MTVU_VIF_UNPACK: { - u32 vif_copy_size = (uptr)&vif.StructEnd - (uptr)&vif.tag; - Read(&vif.tag, vif_copy_size); - ReadRegs(&vifRegs); - u32 size = Read(); - MTVU_Unpack(&buffer[read_pos], vifRegs); - incReadPos(size_u32(size)); - break; - } - case MTVU_NULL_PACKET: - AtomicExchange(read_pos, 0); - break; - jNO_DEFAULT; - } - } - } - } - - // Returns Average number of vu Cycles from last 4 runs - u32 Get_vuCycles() { // Used for vu cycle stealing hack - return (AtomicRead(vuCycles[0]) + AtomicRead(vuCycles[1]) - + AtomicRead(vuCycles[2]) + AtomicRead(vuCycles[3])) >> 2; - } -public: - // Get MTVU to start processing its packets if it isn't already - void KickStart(bool forceKick = false) { - if ((forceKick && !semaEvent.Count()) - || (!isBusy && GetReadPos() != write_pos)) semaEvent.Post(); - } + void KickStart(bool forceKick = false); // Used for assertions... - bool IsDone() { return !isBusy && GetReadPos() == GetWritePos(); } + bool IsDone(); // Waits till MTVU is done processing - void WaitVU() { - MTVU_LOG("MTVU - WaitVU!"); - for(;;) { - if (IsDone()) break; - //DevCon.WriteLn("WaitVU()"); - pxAssert(THREAD_VU1); - KickStart(); - ScopedLock lock(mtxBusy); - } - } + void WaitVU(); - void ExecuteVU(u32 vu_addr, u32 vif_top, u32 vif_itop) { - MTVU_LOG("MTVU - ExecuteVU!"); - ReserveSpace(4); - Write(MTVU_VU_EXECUTE); - Write(vu_addr); - Write(vif_top); - Write(vif_itop); - incWritePos(); - gifUnit.TransferGSPacketData(GIF_TRANS_MTVU, NULL, 0); - KickStart(); - u32 cycles = std::min(Get_vuCycles(), 3000u); - cpuRegs.cycle += cycles * EmuConfig.Speedhacks.VUCycleSteal; - } + void ExecuteVU(u32 vu_addr, u32 vif_top, u32 vif_itop); - void VifUnpack(vifStruct& _vif, VIFregisters& _vifRegs, u8* data, u32 size) { - MTVU_LOG("MTVU - VifUnpack!"); - u32 vif_copy_size = (uptr)&_vif.StructEnd - (uptr)&_vif.tag; - ReserveSpace(1 + size_u32(vif_copy_size) + size_u32(sizeof(VIFregistersMTVU)) + 1 + size_u32(size)); - Write(MTVU_VIF_UNPACK); - Write(&_vif.tag, vif_copy_size); - WriteRegs(&_vifRegs); - Write(size); - Write(data, size); - incWritePos(); - KickStart(); - } + void VifUnpack(vifStruct& _vif, VIFregisters& _vifRegs, u8* data, u32 size); // Writes to VU's Micro Memory (size in bytes) - void WriteMicroMem(u32 vu_micro_addr, void* data, u32 size) { - MTVU_LOG("MTVU - WriteMicroMem!"); - ReserveSpace(3 + size_u32(size)); - Write(MTVU_VU_WRITE_MICRO); - Write(vu_micro_addr); - Write(size); - Write(data, size); - incWritePos(); - } + void WriteMicroMem(u32 vu_micro_addr, void* data, u32 size); // Writes to VU's Data Memory (size in bytes) - void WriteDataMem(u32 vu_data_addr, void* data, u32 size) { - MTVU_LOG("MTVU - WriteDataMem!"); - ReserveSpace(3 + size_u32(size)); - Write(MTVU_VU_WRITE_DATA); - Write(vu_data_addr); - Write(size); - Write(data, size); - incWritePos(); - } + void WriteDataMem(u32 vu_data_addr, void* data, u32 size); - void WriteCol(vifStruct& _vif) { - MTVU_LOG("MTVU - WriteCol!"); - ReserveSpace(1 + size_u32(sizeof(_vif.MaskCol))); - Write(MTVU_VIF_WRITE_COL); - Write(&_vif.MaskCol, sizeof(_vif.MaskCol)); - incWritePos(); - } + void WriteCol(vifStruct& _vif); - void WriteRow(vifStruct& _vif) { - MTVU_LOG("MTVU - WriteRow!"); - ReserveSpace(1 + size_u32(sizeof(_vif.MaskRow))); - Write(MTVU_VIF_WRITE_ROW); - Write(&_vif.MaskRow, sizeof(_vif.MaskRow)); - incWritePos(); - } + void WriteRow(vifStruct& _vif); + +protected: + void ExecuteTaskInThread(); + +private: + void ExecuteRingBuffer(); + + void WaitOnSize(s32 size); + void ReserveSpace(s32 size); + + volatile s32 GetReadPos(); + volatile s32 GetWritePos(); + u32* GetWritePtr(); + + void incReadPos(s32 offset); + void incWritePos(); + + u32 Read(); + void Read(void* dest, u32 size); + void ReadRegs(VIFregisters* dest); + + void Write(u32 val); + void Write(void* src, u32 size); + void WriteRegs(VIFregisters* src); + + u32 Get_vuCycles(); }; -extern __aligned16 VU_Thread vu1Thread; - +extern __aligned16 VU_Thread vu1Thread; \ No newline at end of file diff --git a/pcsx2/x86/microVU.cpp b/pcsx2/x86/microVU.cpp index b953e6567..8ec9b1f0f 100644 --- a/pcsx2/x86/microVU.cpp +++ b/pcsx2/x86/microVU.cpp @@ -293,7 +293,7 @@ void recMicroVU0::Reserve() { void recMicroVU1::Reserve() { if (AtomicExchange(m_Reserved, 1) == 0) { mVUinit(microVU1, 1); - vu1Thread.InitThread(); + vu1Thread.Start(); } } From 8b563888f83a81f1941b4d9cc55d28cff2f4cd50 Mon Sep 17 00:00:00 2001 From: refraction Date: Fri, 6 Apr 2012 14:00:12 +0000 Subject: [PATCH 50/83] Fix for Issue 1145 - Issue introduced with VSync changed broke Dynasty Warrior games, this should resolve it. Id swapped the VSync order around but still swapped which Field first, so it started out of sync, silly me! git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5145 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/Counters.cpp | 2 ++ pcsx2/GS.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pcsx2/Counters.cpp b/pcsx2/Counters.cpp index 623f99d36..415cd0b57 100644 --- a/pcsx2/Counters.cpp +++ b/pcsx2/Counters.cpp @@ -406,6 +406,8 @@ static __fi void VSyncEnd(u32 sCycle) if (gates) rcntEndGate(true, sCycle); // Counters End Gate Code frameLimit(); // limit FPS + //Do this here, breaks Dynasty Warriors otherwise. + CSRreg.SwapField(); // This doesn't seem to be needed here. Games only seem to break with regard to the // vsyncstart irq. //cpuRegs.eCycle[30] = 2; diff --git a/pcsx2/GS.cpp b/pcsx2/GS.cpp index 65543b513..c43c79787 100644 --- a/pcsx2/GS.cpp +++ b/pcsx2/GS.cpp @@ -426,7 +426,7 @@ __fi void gsFrameSkip() void gsPostVsyncStart() { //gifUnit.FlushToMTGS(); // Needed for some (broken?) homebrew game loaders - CSRreg.SwapField(); + GetMTGS().PostVsyncStart(); } From 2e22e56b48b3440b2df843e1e7b645cc85a1eec4 Mon Sep 17 00:00:00 2001 From: "sudonim1@gmail.com" Date: Fri, 6 Apr 2012 18:41:20 +0000 Subject: [PATCH 51/83] Fixed PGO builds, MSVC does not like inline asm for function calls. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5146 96395faa-99c1-11dd-bbfe-3dabce05a288 --- common/include/x86emitter/x86emitter.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/common/include/x86emitter/x86emitter.h b/common/include/x86emitter/x86emitter.h index cf09e8acd..2de3d3a88 100644 --- a/common/include/x86emitter/x86emitter.h +++ b/common/include/x86emitter/x86emitter.h @@ -57,8 +57,10 @@ // insisting on "mov eax, immaddr; call eax". Likewise, GCC fails to optimize it also, unless // the typecast is explicitly inlined. These macros account for these problems. // +// But it turns out that MSVC is quite capable of optimising important code out of existance +// if we use these macros in our PGO builds, so it's better just to live with the inefficient call. -#ifdef _MSC_VER +#ifdef _MSC_HAS_FIXED_INLINE_ASM_PGO # define CallAddress( ptr ) \ __asm{ call offset ptr } From d29a30c26526708652fe9a4d74757583508ed566 Mon Sep 17 00:00:00 2001 From: refraction Date: Sat, 7 Apr 2012 01:48:34 +0000 Subject: [PATCH 52/83] VIF: Reworked the VU delays in to scheduled events to simulate VU run time without killing Metal Saga or Fahrenheit. Adjusted the COP checks on the VU's to use the same method as the VPU_STAT is never set essentially so the VU is never "running". Path3 Masking: Fixed a bug which caused persona 3 not to boot, previous a hack had been put in place to get around this. VIF: Fixed a VIF error with the rare game Realta Nua, now goes through the prologue correctly. Game requires the EE timing hack to get rid of most of the noise (Path3 masking problem with new GIF unit, unfixable). Expecting bugs, I will be monitoring this. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5147 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/COP2.cpp | 7 ++- pcsx2/Gif_Unit.h | 3 +- pcsx2/R5900.cpp | 5 ++- pcsx2/R5900.h | 6 ++- pcsx2/VU0micro.cpp | 1 + pcsx2/VU1micro.cpp | 4 +- pcsx2/Vif.cpp | 4 -- pcsx2/Vif0_Dma.cpp | 52 ++++++++++++---------- pcsx2/Vif1_Dma.cpp | 86 ++++++++++++++++++++---------------- pcsx2/Vif1_MFIFO.cpp | 10 +++-- pcsx2/Vif_Codes.cpp | 54 +++++++++++++++++----- pcsx2/Vif_Dma.h | 9 ++-- pcsx2/Vif_Transfer.cpp | 18 ++++---- pcsx2/x86/microVU_Branch.inl | 2 +- pcsx2/x86/microVU_Macro.inl | 3 +- pcsx2/x86/sVU_zerorec.cpp | 4 +- 16 files changed, 162 insertions(+), 106 deletions(-) diff --git a/pcsx2/COP2.cpp b/pcsx2/COP2.cpp index 670bb8d69..5ec8be4c5 100644 --- a/pcsx2/COP2.cpp +++ b/pcsx2/COP2.cpp @@ -22,17 +22,20 @@ using namespace R5900; using namespace R5900::Interpreter; +//#define CP2COND (((VU0.VI[REG_VPU_STAT].US[0] >> 8) & 1)) +#define CP2COND (vif1Regs.stat.VEW) -#define CP2COND (((VU0.VI[REG_VPU_STAT].US[0] >> 8) & 1)) - +//Run the FINISH either side of the VCALL's as we have no control over it past here. void VCALLMS() { vu0Finish(); vu0ExecMicro(((cpuRegs.code >> 6) & 0x7FFF) * 8); + vif0Regs.stat.VEW = false; } void VCALLMSR() { vu0Finish(); vu0ExecMicro(VU0.VI[REG_CMSAR0].US[0] * 8); + vif0Regs.stat.VEW = false; } void BC2F() diff --git a/pcsx2/Gif_Unit.h b/pcsx2/Gif_Unit.h index 33cbc1b56..b86772013 100644 --- a/pcsx2/Gif_Unit.h +++ b/pcsx2/Gif_Unit.h @@ -583,7 +583,8 @@ struct Gif_Unit { bool CanDoP3Slice() { return stat.IMT == 1 && gifPath[GIF_PATH_3].state == GIF_PATH_IMAGE; } bool CanDoGif() { return stat.PSE == 0 && (CHECK_GIFREVERSEHACK ? 1 : stat.DIR == 0) && gsSIGNAL.queued == 0; } - bool Path3Masked() { return stat.M3R || stat.M3P; } + //Mask stops the next packet which hasnt started from transferring + bool Path3Masked() { return ((stat.M3R || stat.M3P) && (gifPath[GIF_PATH_3].state == GIF_PATH_IDLE)); } void PrintInfo(bool printP1=1, bool printP2=1, bool printP3=1) { u32 a = checkPaths(1,1,1), b = checkQueued(1,1,1); diff --git a/pcsx2/R5900.cpp b/pcsx2/R5900.cpp index db32ba281..f65eb032e 100644 --- a/pcsx2/R5900.cpp +++ b/pcsx2/R5900.cpp @@ -292,7 +292,7 @@ static __fi void _cpuTestInterrupts() // The following ints are rarely called. Encasing them in a conditional // as follows helps speed up most games. - if( cpuRegs.interrupt & 0xF19 ) // Bits 0 3 4 8 9 10 11 ( 111100011001 ) + if( cpuRegs.interrupt & 0x60F19 ) // Bits 0 3 4 8 9 10 11 17 18( 1100000111100011001 ) { TESTINT(DMAC_VIF0, vif0Interrupt); @@ -304,6 +304,9 @@ static __fi void _cpuTestInterrupts() TESTINT(DMAC_MFIFO_VIF, vifMFIFOInterrupt); TESTINT(DMAC_MFIFO_GIF, gifMFIFOInterrupt); + + TESTINT(VIF_VU0_FINISH, vif0VUFinish); + TESTINT(VIF_VU1_FINISH, vif1VUFinish); } } diff --git a/pcsx2/R5900.h b/pcsx2/R5900.h index b57952bd8..0bc2ecf32 100644 --- a/pcsx2/R5900.h +++ b/pcsx2/R5900.h @@ -405,8 +405,10 @@ enum EE_EventType DMAC_STALL_SIS = 13, // SIS DMAC_MFIFO_EMPTY = 14, // MEIS DMAC_BUS_ERROR = 15, // BEIS - - DMAC_GIF_UNIT + + DMAC_GIF_UNIT, + VIF_VU0_FINISH, + VIF_VU1_FINISH }; extern void CPU_INT( EE_EventType n, s32 ecycle ); diff --git a/pcsx2/VU0micro.cpp b/pcsx2/VU0micro.cpp index d9e5d853f..d8cd35cd9 100644 --- a/pcsx2/VU0micro.cpp +++ b/pcsx2/VU0micro.cpp @@ -46,6 +46,7 @@ void __fastcall vu0ExecMicro(u32 addr) { VU0.VI[REG_VPU_STAT].UL &= ~0xFF; VU0.VI[REG_VPU_STAT].UL |= 0x01; + vif0Regs.stat.VEW = true; if ((s32)addr != -1) VU0.VI[REG_TPC].UL = addr; _vuExecMicroDebug(VU0); diff --git a/pcsx2/VU1micro.cpp b/pcsx2/VU1micro.cpp index c1cec190d..740daf6ae 100644 --- a/pcsx2/VU1micro.cpp +++ b/pcsx2/VU1micro.cpp @@ -50,9 +50,10 @@ void vu1Finish() { void __fastcall vu1ExecMicro(u32 addr) { + vif1Regs.stat.VEW = true; + if (THREAD_VU1) { vu1Thread.ExecuteVU(addr, vif1Regs.top, vif1Regs.itop); - vif1Regs.stat.VEW = false; VU0.VI[REG_VPU_STAT].UL &= ~0xFF00; return; } @@ -64,7 +65,6 @@ void __fastcall vu1ExecMicro(u32 addr) VU0.VI[REG_VPU_STAT].UL &= ~0xFF00; VU0.VI[REG_VPU_STAT].UL |= 0x0100; - vif1Regs.stat.VEW = true; if ((s32)addr != -1) VU1.VI[REG_TPC].UL = addr; _vuExecMicroDebug(VU1); diff --git a/pcsx2/Vif.cpp b/pcsx2/Vif.cpp index 2a3a8c822..83d435b08 100644 --- a/pcsx2/Vif.cpp +++ b/pcsx2/Vif.cpp @@ -47,8 +47,6 @@ void SaveStateBase::vif0Freeze() FreezeTag("VIF0dma"); Freeze(g_vif0Cycles); - Freeze(g_vu0Cycles); - Freeze(g_packetsizeonvu0); Freeze(vif0); @@ -61,8 +59,6 @@ void SaveStateBase::vif1Freeze() FreezeTag("VIF1dma"); Freeze(g_vif1Cycles); - Freeze(g_vu1Cycles); - Freeze(g_packetsizeonvu1); Freeze(vif1); diff --git a/pcsx2/Vif0_Dma.cpp b/pcsx2/Vif0_Dma.cpp index b378021a6..0c8f73c4f 100644 --- a/pcsx2/Vif0_Dma.cpp +++ b/pcsx2/Vif0_Dma.cpp @@ -25,31 +25,11 @@ u32 g_vif0Cycles = 0; // because its vif stalling not the EE core... __fi void vif0FLUSH() { - if(g_packetsizeonvu0 > vif0.vifpacketsize && g_vu0Cycles > 0) - { - //DevCon.Warning("Adding on same packet"); - if( ((g_packetsizeonvu0 - vif0.vifpacketsize) >> 1) > g_vu0Cycles) - g_vu0Cycles -= (g_packetsizeonvu0 - vif0.vifpacketsize) >> 1; - else g_vu0Cycles = 0; - } - if(g_vu0Cycles > 0) - { - //DevCon.Warning("Adding %x cycles to VIF0", g_vu0Cycles * BIAS); - g_vif0Cycles += g_vu0Cycles; - g_vu0Cycles = 0; - } - g_vu0Cycles = 0; - - if (!(VU0.VI[REG_VPU_STAT].UL & 1)) return; - if(VU0.flags & VUFLAG_MFLAGSET) + if(vif0Regs.stat.VEW == true) { + vif0.waitforvu = true; vif0.vifstalled = true; - return; } - int _cycles = VU0.cycle; - vu0Finish(); - //DevCon.Warning("VIF0 adding %x cycles", (VU0.cycle - _cycles) * BIAS); - g_vif0Cycles += (VU0.cycle - _cycles) * BIAS; return; } @@ -160,6 +140,27 @@ __fi void vif0SetupTransfer() } } +__fi void vif0VUFinish() +{ + if ((VU0.VI[REG_VPU_STAT].UL & 1)) + { + int _cycles = VU0.cycle; + //DevCon.Warning("Finishing VU0"); + vu0Finish(); + _cycles = VU0.cycle - _cycles; + //DevCon.Warning("Finishing VU0 %d cycles", _cycles); + CPU_INT(VIF_VU0_FINISH, _cycles * BIAS); + return; + } + vif0Regs.stat.VEW = false; + if(vif0.waitforvu == true) + { + vif0.waitforvu = false; + ExecuteVU(0); + } + //DevCon.Warning("VU0 state cleared"); +} + __fi void vif0Interrupt() { VIF_LOG("vif0Interrupt: %8.8x", cpuRegs.cycle); @@ -190,6 +191,12 @@ __fi void vif0Interrupt() } } + if(vif0.waitforvu == true) + { + //DevCon.Warning("Waiting on VU0"); + CPU_INT(DMAC_VIF0, 16); + return; + } //Must go after the Stall, incase it's still in progress, GTC africa likes to see it still transferring. if (vif0.cmd) { @@ -250,7 +257,6 @@ void dmaVIF0() vif0ch.tadr, vif0ch.asr0, vif0ch.asr1); g_vif0Cycles = 0; - g_vu0Cycles = 0; //if(vif0.irqoffset != 0 && vif0.vifstalled == true) DevCon.Warning("Offset on VIF0 start! offset %x, Progress %x", vif0.irqoffset, vif0.vifstalled); /*vif0.irqoffset = 0; vif0.vifstalled = false; diff --git a/pcsx2/Vif1_Dma.cpp b/pcsx2/Vif1_Dma.cpp index c588411ae..59a7e5d14 100644 --- a/pcsx2/Vif1_Dma.cpp +++ b/pcsx2/Vif1_Dma.cpp @@ -25,27 +25,10 @@ u32 g_vif1Cycles = 0; __fi void vif1FLUSH() { - if(g_packetsizeonvu1 > vif1.vifpacketsize && g_vu1Cycles > 0) + if(vif1Regs.stat.VEW == true) { - //DevCon.Warning("Adding on same packet"); - if( ((g_packetsizeonvu1 - vif1.vifpacketsize) >> 1) > g_vu1Cycles) - g_vu1Cycles -= (g_packetsizeonvu1 - vif1.vifpacketsize) >> 1; - else g_vu1Cycles = 0; - } - if(g_vu1Cycles > 0) - { - //DevCon.Warning("Adding %x cycles to VIF1", g_vu1Cycles * BIAS); - g_vif1Cycles += g_vu1Cycles; - g_vu1Cycles = 0; - } - g_vu1Cycles = 0;//else DevCon.Warning("VIF1 Different Packet, how can i work this out :/"); - - if (VU0.VI[REG_VPU_STAT].UL & 0x100) - { - int _cycles = VU1.cycle; - vu1Finish(); - //DevCon.Warning("VIF1 adding %x cycles", (VU1.cycle - _cycles) * BIAS); - g_vif1Cycles += (VU1.cycle - _cycles) * BIAS; + vif1.waitforvu = true; + vif1.vifstalled = true; } } @@ -230,9 +213,30 @@ __fi void vif1SetupTransfer() } } +__fi void vif1VUFinish() +{ + if (VU0.VI[REG_VPU_STAT].UL & 0x100) + { + int _cycles = VU1.cycle; + //DevCon.Warning("Finishing VU1"); + vu1Finish(); + CPU_INT(VIF_VU1_FINISH, (VU1.cycle - _cycles) * BIAS); + return; + } + + vif1Regs.stat.VEW = false; + if(vif1.waitforvu == true) + { + vif1.waitforvu = false; + ExecuteVU(1); + } + + //DevCon.Warning("VU1 state cleared"); +} + __fi void vif1Interrupt() { - VIF_LOG("vif1Interrupt: %8.8x", cpuRegs.cycle); + VIF_LOG("vif1Interrupt: %8.8x chcr %x, done %x, qwc %x", cpuRegs.cycle, vif1ch.chcr._u32, vif1.done, vif1ch.qwc); g_vif1Cycles = 0; @@ -262,6 +266,12 @@ __fi void vif1Interrupt() //Simulated GS transfer time done, clear the flags } + if(vif1.waitforvu == true) + { + //DevCon.Warning("Waiting on VU1"); + CPU_INT(DMAC_VIF1, 16); + return; + } if (!vif1ch.chcr.STR) Console.WriteLn("Vif1 running when CHCR == %x", vif1ch.chcr._u32); if (vif1.irq && vif1.tag.size == 0) @@ -294,19 +304,7 @@ __fi void vif1Interrupt() { vif1Regs.stat.VPS = VPS_IDLE; } - - if (vif1.inprogress & 0x1) - { - _VIF1chain(); - // VIF_NORMAL_FROM_MEM_MODE is a very slow operation. - // Timesplitters 2 depends on this beeing a bit higher than 128. - if (vif1ch.chcr.DIR) vif1Regs.stat.FQC = min(vif1ch.qwc, (u16)16); - // Refraction - Removing voodoo timings for now, completely messes a lot of Path3 masked games. - /*if (vif1.dmamode == VIF_NORMAL_FROM_MEM_MODE ) CPU_INT(DMAC_VIF1, 1024); - else */CPU_INT(DMAC_VIF1, g_vif1Cycles /*VifCycleVoodoo*/); - return; - } - + if (!vif1.done) { @@ -318,9 +316,23 @@ __fi void vif1Interrupt() if ((vif1.inprogress & 0x1) == 0) vif1SetupTransfer(); if (vif1ch.chcr.DIR) vif1Regs.stat.FQC = min(vif1ch.qwc, (u16)16); - CPU_INT(DMAC_VIF1, g_vif1Cycles); + } + + + if (vif1.inprogress & 0x1) + { + _VIF1chain(); + // VIF_NORMAL_FROM_MEM_MODE is a very slow operation. + // Timesplitters 2 depends on this being a bit higher than 128. + if (vif1ch.chcr.DIR) vif1Regs.stat.FQC = min(vif1ch.qwc, (u16)16); + } + + if(g_vif1Cycles > 0 || vif1ch.qwc) + { + CPU_INT(DMAC_VIF1, max((int)g_vif1Cycles, 8)); return; } + else if(vif1Regs.stat.VPS == VPS_TRANSFERRING) DevCon.Warning("Cycles %x, cmd %x, qwc %x, waitonvu %x", g_vif1Cycles, vif1.cmd, vif1ch.qwc, vif1.waitforvu); if (vif1.vifstalled && vif1.irq) { @@ -344,7 +356,6 @@ __fi void vif1Interrupt() vif1ch.chcr.STR = false; vif1.vifstalled = false; g_vif1Cycles = 0; - g_vu1Cycles = 0; DMA_LOG("VIF1 DMA End"); hwDmacIrq(DMAC_VIF1); @@ -364,7 +375,6 @@ void dmaVIF1() vif1.vifstalled = false; vif1.inprogress = 0;*/ g_vif1Cycles = 0; - g_vu1Cycles = 0; #ifdef PCSX2_DEVBUILD if (dmacRegs.ctrl.STD == STD_VIF1) @@ -410,7 +420,7 @@ void dmaVIF1() { vif1.dmamode = VIF_CHAIN_MODE; vif1.done = false; - vif1.inprogress = 0; + vif1.inprogress &= ~0x1; } if (vif1ch.chcr.DIR) vif1Regs.stat.FQC = min((u16)0x10, vif1ch.qwc); diff --git a/pcsx2/Vif1_MFIFO.cpp b/pcsx2/Vif1_MFIFO.cpp index 816b4267c..27ad93251 100644 --- a/pcsx2/Vif1_MFIFO.cpp +++ b/pcsx2/Vif1_MFIFO.cpp @@ -20,10 +20,6 @@ #include "Vif_Dma.h" u16 vifqwc = 0; -u32 g_vu0Cycles = 0; -u32 g_vu1Cycles = 0; -u32 g_packetsizeonvu0 = 0; -u32 g_packetsizeonvu1 = 0; static u32 qwctag(u32 mask) { @@ -267,6 +263,12 @@ void vifMFIFOInterrupt() return; } } + if(vif1.waitforvu == true) + { + // DevCon.Warning("Waiting on VU1 MFIFO"); + CPU_INT(DMAC_MFIFO_VIF, 16); + return; + } // We need to check the direction, if it is downloading from the GS, // we handle that separately (KH2 for testing) diff --git a/pcsx2/Vif_Codes.cpp b/pcsx2/Vif_Codes.cpp index cd31b538d..218e5c662 100644 --- a/pcsx2/Vif_Codes.cpp +++ b/pcsx2/Vif_Codes.cpp @@ -76,12 +76,28 @@ static __fi void vuExecMicro(int idx, u32 addr) { if (!idx) vu0ExecMicro(addr); else vu1ExecMicro(addr); - if (!idx || !THREAD_VU1) { - if (!idx) { g_vu0Cycles += (VU0.cycle-startcycles); g_packetsizeonvu0 = vif0.vifpacketsize; } - else { g_vu1Cycles += (VU1.cycle-startcycles); g_packetsizeonvu1 = vif1.vifpacketsize; } - } + if (!idx) { startcycles = ((VU0.cycle-startcycles) + ( vif0ch.qwc - (vif0.vifpacketsize >> 2) )); CPU_INT(VIF_VU0_FINISH, startcycles * BIAS); } + else { startcycles = ((VU1.cycle-startcycles) + ( vif1ch.qwc - (vif1.vifpacketsize >> 2) )); CPU_INT(VIF_VU1_FINISH, startcycles * BIAS); } + + //DevCon.Warning("Ran VU%x, VU0 Cycles %x, VU1 Cycles %x, start %x cycle %x", idx, g_vu0Cycles, g_vu1Cycles, startcycles, VU1.cycle); - GetVifX.vifstalled = true; + //GetVifX.vifstalled = true; +} + +void ExecuteVU(int idx) +{ + vifStruct& vifX = GetVifX; + + if((vifX.cmd & 0x7f) == 0x17) + { + vuExecMicro(idx, -1); + vifX.cmd = 0; + } + else if((vifX.cmd & 0x7f) == 0x14 || (vifX.cmd & 0x7f) == 0x15) + { + vuExecMicro(idx, (u16)(vifXRegs.code) << 3); + vifX.cmd = 0; + } } //------------------------------------------------------------------ @@ -174,14 +190,14 @@ vifOp(vifCode_FlushA) { //p3.state= GIF_PATH_IDLE; // Does any game need this anymore? DevCon.Warning("Vif FlushA - path3 has no more data, but didn't EOP"); } - else { // Path 3 hasn't finished its current gs packet + /*else { // Path 3 hasn't finished its current gs packet if (gifUnit.stat.APATH != 3 && gifUnit.Path3Masked()) { gifUnit.stat.APATH = 3; // Hack: Force path 3 to finish (persona 3 needs this) //DevCon.Warning("Vif FlushA - Forcing path3 to finish current packet"); } gifInterrupt(); // Feed path3 some gif dma data gifUnit.Execute(); // Execute path3 in-case gifInterrupt() didn't... - } + }*/ if (p3.state != GIF_PATH_IDLE) { doStall = true; // If path3 still isn't finished... } @@ -245,7 +261,7 @@ vifOp(vifCode_MPG) { int vifNum = (u8)(vifXRegs.code >> 16); vifX.tag.addr = (u16)(vifXRegs.code << 3) & (idx ? 0x3fff : 0xfff); vifX.tag.size = vifNum ? (vifNum*2) : 512; - //vifFlush(idx); + vifFlush(idx); return 1; } pass2 { @@ -275,7 +291,15 @@ vifOp(vifCode_MPG) { vifOp(vifCode_MSCAL) { vifStruct& vifX = GetVifX; - pass1 { vifFlush(idx); vuExecMicro(idx, (u16)(vifXRegs.code) << 3); vifX.cmd = 0;} + pass1 { + vifFlush(idx); + + if(vifX.waitforvu == false) + { + vuExecMicro(idx, (u16)(vifXRegs.code) << 3); + vifX.cmd = 0; + } + } pass3 { VifCodeLog("MSCAL"); } return 0; } @@ -290,7 +314,8 @@ vifOp(vifCode_MSCALF) { vif1Regs.stat.VGW = true; vifX.vifstalled = true; } - else { + if(vifX.waitforvu == false) + { vuExecMicro(idx, (u16)(vifXRegs.code) << 3); vifX.cmd = 0; } @@ -301,7 +326,14 @@ vifOp(vifCode_MSCALF) { vifOp(vifCode_MSCNT) { vifStruct& vifX = GetVifX; - pass1 { vifFlush(idx); vuExecMicro(idx, -1); vifX.cmd = 0; } + pass1 { + vifFlush(idx); + if(vifX.waitforvu == false) + { + vuExecMicro(idx, -1); + vifX.cmd = 0; + } + } pass3 { VifCodeLog("MSCNT"); } return 0; } diff --git a/pcsx2/Vif_Dma.h b/pcsx2/Vif_Dma.h index d655c440d..b4797a299 100644 --- a/pcsx2/Vif_Dma.h +++ b/pcsx2/Vif_Dma.h @@ -72,6 +72,7 @@ struct vifStruct { bool done; bool vifstalled; bool stallontag; + bool waitforvu; // GS registers used for calculating the size of the last local->host transfer initiated on the GS // Transfer size calculation should be restricted to GS emulation in the future @@ -89,11 +90,13 @@ extern __aligned16 vifStruct vif0, vif1; _vifT extern u32 vifRead32(u32 mem); _vifT extern bool vifWrite32(u32 mem, u32 value); - +void ExecuteVU(int idx); extern void vif0Interrupt(); +extern void vif0VUFinish(); extern void vif0Reset(); extern void vif1Interrupt(); +extern void vif1VUFinish(); extern void vif1Reset(); typedef int __fastcall FnType_VifCmdHandler(int pass, const u32 *data); @@ -119,10 +122,6 @@ static const unsigned int VIF1intc = 5; extern u32 g_vif0Cycles; extern u32 g_vif1Cycles; -extern u32 g_vu0Cycles; -extern u32 g_vu1Cycles; -extern u32 g_packetsizeonvu0; -extern u32 g_packetsizeonvu1; extern void vif0FLUSH(); extern void vif1FLUSH(); diff --git a/pcsx2/Vif_Transfer.cpp b/pcsx2/Vif_Transfer.cpp index f9c67bcfa..90562af10 100644 --- a/pcsx2/Vif_Transfer.cpp +++ b/pcsx2/Vif_Transfer.cpp @@ -122,14 +122,13 @@ _vifT static __fi bool vifTransfer(u32 *data, int size, bool TTE) { transferred += size - vifX.vifpacketsize; - if (!idx) { - g_packetsizeonvu0 = size; - g_vif0Cycles +=((transferred * BIAS) >> 2) ; /* guessing */ - } - else { - g_packetsizeonvu1 = size; - g_vif1Cycles +=((transferred * BIAS) >> 2) ; /* guessing */ - } + //Make this a minimum of 1 cycle so if it's the end of the packet it doesnt just fall through. + //Metal Saga can do this, just to be safe :) + if (!idx) g_vif0Cycles += max(1, (int)((transferred * BIAS) >> 2)); + else g_vif1Cycles += max(1, (int)((transferred * BIAS) >> 2)); + + + /* if(!idx && g_vu0Cycles > 0) { if (g_vif0Cycles < g_vu0Cycles) g_vu0Cycles -= g_vif0Cycles; elif(g_vif0Cycles >= g_vu0Cycles) g_vu0Cycles = 0; @@ -138,7 +137,8 @@ _vifT static __fi bool vifTransfer(u32 *data, int size, bool TTE) { if (g_vif1Cycles < g_vu1Cycles) g_vu1Cycles -= g_vif1Cycles; elif(g_vif1Cycles >= g_vu1Cycles) g_vu1Cycles = 0; } - + */ + vifX.irqoffset = transferred % 4; // cannot lose the offset if (!TTE) {// *WARNING* - Tags CAN have interrupts! so lets just ignore the dma modifying stuffs (GT4) diff --git a/pcsx2/x86/microVU_Branch.inl b/pcsx2/x86/microVU_Branch.inl index 4e75c8173..02eb27484 100644 --- a/pcsx2/x86/microVU_Branch.inl +++ b/pcsx2/x86/microVU_Branch.inl @@ -79,7 +79,7 @@ void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) { if (isEbit || isVU1) { // Clear 'is busy' Flags if (!mVU.index || !THREAD_VU1) { xAND(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? ~0x100 : ~0x001)); // VBS0/VBS1 flag - xAND(ptr32[&mVU.getVifRegs().stat], ~VIF1_STAT_VEW); // Clear VU 'is busy' signal for vif + //xAND(ptr32[&mVU.getVifRegs().stat], ~VIF1_STAT_VEW); // Clear VU 'is busy' signal for vif } } diff --git a/pcsx2/x86/microVU_Macro.inl b/pcsx2/x86/microVU_Macro.inl index ffba4bde6..8da5a0beb 100644 --- a/pcsx2/x86/microVU_Macro.inl +++ b/pcsx2/x86/microVU_Macro.inl @@ -232,7 +232,8 @@ INTERPRETATE_COP2_FUNC(CALLMSR); void _setupBranchTest(u32*(jmpType)(u32), bool isLikely) { printCOP2("COP2 Branch"); _eeFlushAllUnused(); - TEST32ItoM((uptr)&VU0.VI[REG_VPU_STAT].UL, 0x100); + TEST32ItoM((uptr)&vif1Regs.stat._u32, 0x4); + //TEST32ItoM((uptr)&VU0.VI[REG_VPU_STAT].UL, 0x100); recDoBranchImm(jmpType(0), isLikely); } diff --git a/pcsx2/x86/sVU_zerorec.cpp b/pcsx2/x86/sVU_zerorec.cpp index 7bd57dee8..bcfc1aaa1 100644 --- a/pcsx2/x86/sVU_zerorec.cpp +++ b/pcsx2/x86/sVU_zerorec.cpp @@ -2721,7 +2721,7 @@ static void SuperVURecompile() pxAssert(pchild->blocks.size() == 0); AND32ItoM((uptr)&VU0.VI[ REG_VPU_STAT ].UL, s_vu ? ~0x100 : ~0x001); // E flag - AND32ItoM((uptr)&VU->GetVifRegs().stat, ~VIF1_STAT_VEW); + //AND32ItoM((uptr)&VU->GetVifRegs().stat, ~VIF1_STAT_VEW); MOV32ItoM((uptr)&VU->VI[REG_TPC], pchild->endpc); JMP32((uptr)SuperVUEndProgram - ((uptr)x86Ptr + 5)); @@ -2994,7 +2994,7 @@ void VuBaseBlock::Recompile() _freeXMMregs(); _freeX86regs(); AND32ItoM((uptr)&VU0.VI[ REG_VPU_STAT ].UL, s_vu ? ~0x100 : ~0x001); // E flag - AND32ItoM((uptr)&VU->GetVifRegs().stat, ~VIF1_STAT_VEW); + //AND32ItoM((uptr)&VU->GetVifRegs().stat, ~VIF1_STAT_VEW); if (!branch) MOV32ItoM((uptr)&VU->VI[REG_TPC], endpc); From c2bd8375251c87c080a9cd257f02cca90a61b440 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Sat, 7 Apr 2012 09:47:24 +0000 Subject: [PATCH 53/83] l10n: realigned translation with latest trunk. Current (unfinished) translation status: locales/de_DE/pcsx2_Main.po - 522/ 4/560 ( 93%) -38 locales/hu_HU/pcsx2_Main.po - 522/ 4/560 ( 93%) -38 locales/id_ID/pcsx2_Iconized.po - 49/ 12/74 ( 66%) -25 locales/id_ID/pcsx2_Main.po - 498/ 5/560 ( 88%) -62 locales/ru_RU/pcsx2_Main.po - 554/ 4/560 ( 98%) -6 locales/tr_TR/pcsx2_Main.po - 555/ 4/560 ( 99%) -5 git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5148 96395faa-99c1-11dd-bbfe-3dabce05a288 --- bin/Langs/cs_CZ/pcsx2_Iconized.mo | Bin 18311 -> 18311 bytes bin/Langs/de_DE/pcsx2_Iconized.mo | Bin 11717 -> 11717 bytes bin/Langs/es_ES/pcsx2_Iconized.mo | Bin 19494 -> 19494 bytes bin/Langs/fr_FR/pcsx2_Iconized.mo | Bin 19737 -> 19737 bytes bin/Langs/hu_HU/pcsx2_Iconized.mo | Bin 18941 -> 18941 bytes bin/Langs/id_ID/pcsx2_Iconized.mo | Bin 3540 -> 3540 bytes bin/Langs/it_IT/pcsx2_Iconized.mo | Bin 19750 -> 19750 bytes bin/Langs/ja_JP/pcsx2_Iconized.mo | Bin 21698 -> 21698 bytes bin/Langs/pl_PL/pcsx2_Iconized.mo | Bin 17914 -> 17914 bytes bin/Langs/pt_BR/pcsx2_Iconized.mo | Bin 19013 -> 19013 bytes bin/Langs/ru_RU/pcsx2_Iconized.mo | Bin 28339 -> 28339 bytes bin/Langs/sv_SE/pcsx2_Iconized.mo | Bin 19153 -> 19153 bytes bin/Langs/tr_TR/pcsx2_Iconized.mo | Bin 6156 -> 6156 bytes bin/Langs/zh_CN/pcsx2_Iconized.mo | Bin 15304 -> 15304 bytes bin/Langs/zh_TW/pcsx2_Iconized.mo | Bin 16888 -> 16888 bytes locales/cs_CZ/pcsx2_Iconized.po | 4 ++-- locales/de_DE/pcsx2_Iconized.po | 4 ++-- locales/es_ES/pcsx2_Iconized.po | 4 ++-- locales/fr_FR/pcsx2_Iconized.po | 4 ++-- locales/hu_HU/pcsx2_Iconized.po | 4 ++-- locales/id_ID/pcsx2_Iconized.po | 4 ++-- locales/it_IT/pcsx2_Iconized.po | 4 ++-- locales/ja_JP/pcsx2_Iconized.po | 4 ++-- locales/pl_PL/pcsx2_Iconized.po | 4 ++-- locales/pt_BR/pcsx2_Iconized.po | 4 ++-- locales/ru_RU/pcsx2_Iconized.po | 4 ++-- locales/sv_SE/pcsx2_Iconized.po | 4 ++-- locales/templates/pcsx2_Iconized.pot | 4 ++-- locales/templates/pcsx2_Main.pot | 2 +- locales/tr_TR/pcsx2_Iconized.po | 4 ++-- locales/zh_CN/pcsx2_Iconized.po | 4 ++-- locales/zh_TW/pcsx2_Iconized.po | 4 ++-- 32 files changed, 33 insertions(+), 33 deletions(-) diff --git a/bin/Langs/cs_CZ/pcsx2_Iconized.mo b/bin/Langs/cs_CZ/pcsx2_Iconized.mo index 8cebe24e3e8ad0f441116f050ddc82839193b1de..c13a7a98f326a78a947d92de8fe87a9566ecab9c 100644 GIT binary patch delta 28 jcmZqgXKe3h-0*{s*F@LAT*1)L%EU<9z-Tiof0G3OfWrss delta 28 jcmZqgXKe3h-0*{s*GSjMLc!3;%E&<5z;H7wf0G3OfUXDU diff --git a/bin/Langs/de_DE/pcsx2_Iconized.mo b/bin/Langs/de_DE/pcsx2_Iconized.mo index 2726f669aaacf0e9dae3178f457d3d5e3093a9f0..f2a44c628c3ecf2a2f5ac9dd324d95ff5e3050e1 100644 GIT binary patch delta 26 hcmX>aeKdMQ1s|`8u7SCNp`n$Dk+y-+=2kujc>s2b2cQ4| delta 26 hcmX>aeKdMQ1s|`Gu91a;p^=r5fwqC+=2kujc>s2G2b}-_ diff --git a/bin/Langs/es_ES/pcsx2_Iconized.mo b/bin/Langs/es_ES/pcsx2_Iconized.mo index 2960121a08f77e9491163aad208b485148db11c4..3157aac2d338de172e2ef362afab132554fed7a6 100644 GIT binary patch delta 28 kcmZ2BgK^mm#tlFCcujN-%oPj`txSxx4U9Ik@+;Z`0Ej#X-T(jq delta 28 kcmZ2BgK^mm#tlFCc#U+8EEEiltc(n_4GcH4@+;Z`0Ej0C+W-In diff --git a/bin/Langs/fr_FR/pcsx2_Iconized.mo b/bin/Langs/fr_FR/pcsx2_Iconized.mo index f460efb09cd4374b7c83086a4faf4c602761eda4..49c71291d6692fcd6a7737aec718a2576ef56abf 100644 GIT binary patch delta 28 kcmbO^i*e>G#tlFCcujN-%oPj`txSxx4U9Ik@{8C30EO5GyZ`_I delta 28 kcmbO^i*e>G#tlFCc#U-p4HS$Ftc)$R4GcH4@{8C30ELtXxc~qF diff --git a/bin/Langs/hu_HU/pcsx2_Iconized.mo b/bin/Langs/hu_HU/pcsx2_Iconized.mo index bb3932f03da8b5e052a4ecb6169a1eab88d465de..ec6b9eb12d6eb20e1b7d0d3d75c26b2f737f2b68 100644 GIT binary patch delta 28 kcmex6nep#r#tqSYye7H^<_d;}RwhQ;21c7R_@-I|0FKTGxc~qF delta 28 kcmex6nep#r#tqSYyhgf477B(&Rz?Qe28Nq6_@-I|0FJo`wg3PC diff --git a/bin/Langs/id_ID/pcsx2_Iconized.mo b/bin/Langs/id_ID/pcsx2_Iconized.mo index 312f559cada4db901bf66af0d0eee560e54f7f8e..84b6c7c37f3a0ed86f8cffc403a28700737b0353 100644 GIT binary patch delta 26 hcmca2eMNdh89T3uu7SCNp`n$Dk+y-+=4SRlHUMm{2P6Oh delta 26 hcmca2eMNdh89T3$u91a;p^=r5skVXP=4SRlHUMnK2POaj diff --git a/bin/Langs/it_IT/pcsx2_Iconized.mo b/bin/Langs/it_IT/pcsx2_Iconized.mo index ad8ae9cec5b75f8e3a25b6b3fe35cca56d069e20..32ba4ff622553b72be0dbf1329f0aee72f14e5b5 100644 GIT binary patch delta 28 kcmZ2Bi*ea3#tlFCcujN-%oPj`txSxx4U9Ik@+;Z_0EnXp;{X5v delta 28 kcmZ2Bi*ea3#tlFCc#U+8EEEiltc(n_4GcH4@+;Z_0EmtU-~a#s diff --git a/bin/Langs/ja_JP/pcsx2_Iconized.mo b/bin/Langs/ja_JP/pcsx2_Iconized.mo index 4a05c59aed8cd897a1d7312ec57be1599be0da0b..e6e74785e5fb84556e5a2c13d063ea128dc91d23 100644 GIT binary patch delta 28 kcmX@KlJU?=#tlFCcujN-%oPj`txSxx4U9Ik^6zy80FtW++yDRo delta 28 kcmX@KlJU?=#tlFCc#U-p4HS$Ftc)$R4GcH4^6zy80Fq}2*#H0l diff --git a/bin/Langs/pl_PL/pcsx2_Iconized.mo b/bin/Langs/pl_PL/pcsx2_Iconized.mo index ece1605b1ecc4792eacc535dde53287368dee8f3..ae76d26c6c3ba398dcd14642fef73768ee97752f 100644 GIT binary patch delta 28 jcmey>&G@UEal;QjUK3pda|J^~D-$Da1EbBX{9nxgn5qdm delta 28 jcmey>&G@UEal;QjUL##23k5?XD)h4JVV#tlFCcujN-%oPj`txSxx4U9Ik@;g`q0FD<3F#rGn delta 28 kcmX>)h4JVV#tlFCc#U+8EEEiltc(n_4GcH4@;g`q0FD9(E&u=k diff --git a/bin/Langs/ru_RU/pcsx2_Iconized.mo b/bin/Langs/ru_RU/pcsx2_Iconized.mo index 17ea4528678b72fc8a67b284cb4a84140ecde401..a8f7165f39460876939ef3e51fefb11cdea45214 100644 GIT binary patch delta 28 jcmdmdmvQr5#tqSYye7H^<_d;}RwhQ;21c7R_`DMUjmrp> delta 28 jcmdmdmvQr5#tqSYyhgf477B(&Rz?Qe28Nq6_`DMUjkXAp diff --git a/bin/Langs/sv_SE/pcsx2_Iconized.mo b/bin/Langs/sv_SE/pcsx2_Iconized.mo index 8aba6c8f320a8f7337ec65878df6db4bf1404c37..4b6eab05294ac0f11ceb807af578d4aaa27d6025 100644 GIT binary patch delta 28 kcmcaOmGRu^U?%m}wgrZf4~_V+{a=BM5;2 diff --git a/bin/Langs/tr_TR/pcsx2_Iconized.mo b/bin/Langs/tr_TR/pcsx2_Iconized.mo index 0fb0a71b2679e2f2048f1fb565af5b2a1edcbd8b..cbb07870c3cec28d9102e98dbde1fcbd5439fbec 100644 GIT binary patch delta 26 hcmeA%=rPz3&Btq^YhbQmXlP|(q-|idIfHKrCjenJ2J8R; delta 26 hcmeA%=rPz3&Btq`Yh\n" "Language-Team: Zbyněk Schwarz\n" @@ -27,7 +27,7 @@ msgstr "" "Není dostatek virtuální paměti, nebo potřebná mapování virtuální paměti již " "byly vyhrazeny jinými procesy, službami, nebo DLL." -#: pcsx2/CDVD/CDVD.cpp:390 +#: pcsx2/CDVD/CDVD.cpp:389 msgid "!Notice:PsxDisc" msgstr "" "Herní disky Playstation nejsou PCSX2 podporovány. Pokud chcete emulovat hry " diff --git a/locales/de_DE/pcsx2_Iconized.po b/locales/de_DE/pcsx2_Iconized.po index dc474314c..81ee6a88d 100644 --- a/locales/de_DE/pcsx2_Iconized.po +++ b/locales/de_DE/pcsx2_Iconized.po @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2012-02-28 12:20+0100\n" +"POT-Creation-Date: 2012-04-07 11:42+0200\n" "PO-Revision-Date: 2011-04-09 01:11+0100\n" "Last-Translator: \n" "Language-Team: PCSX2\n" @@ -24,7 +24,7 @@ msgstr "" "Es steht nicht genügend virtueller Speicher zur Verfügung bzw. der Speicher " "wird von anderen Programmen / DLLs belegt." -#: pcsx2/CDVD/CDVD.cpp:390 +#: pcsx2/CDVD/CDVD.cpp:389 msgid "!Notice:PsxDisc" msgstr "PlayStation 1 (PSX) Spiele werden von PCSX2 noch nicht unterstützt!" diff --git a/locales/es_ES/pcsx2_Iconized.po b/locales/es_ES/pcsx2_Iconized.po index f19f2c716..ecd8851b1 100644 --- a/locales/es_ES/pcsx2_Iconized.po +++ b/locales/es_ES/pcsx2_Iconized.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.7\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2012-02-28 12:20+0100\n" +"POT-Creation-Date: 2012-04-07 11:42+0200\n" "PO-Revision-Date: 2011-09-28 21:51+0100\n" "Last-Translator: Víctor González \n" "Language-Team: \n" @@ -31,7 +31,7 @@ msgstr "" "memoria virtual necesarias ya las han reservado otros procesos, servicios o " "DLLs." -#: pcsx2/CDVD/CDVD.cpp:390 +#: pcsx2/CDVD/CDVD.cpp:389 msgid "!Notice:PsxDisc" msgstr "" "PCSX2 no admite discos de juego de PlayStation 1. Si quieres emular juegos " diff --git a/locales/fr_FR/pcsx2_Iconized.po b/locales/fr_FR/pcsx2_Iconized.po index c4f1f83a6..15aa76a84 100644 --- a/locales/fr_FR/pcsx2_Iconized.po +++ b/locales/fr_FR/pcsx2_Iconized.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2012-03-10 20:38+0100\n" +"POT-Creation-Date: 2012-04-07 11:42+0200\n" "PO-Revision-Date: 2012-03-08 11:33-0000\n" "Last-Translator: goldeng \n" "Language-Team: goldeng \n" @@ -29,7 +29,7 @@ msgstr "" "La mémoire virtuelle disponible est insuffisante, ou l'espace-mémoire a déjà " "été réservé par d'autres processus, services ou DLL." -#: pcsx2/CDVD/CDVD.cpp:390 +#: pcsx2/CDVD/CDVD.cpp:389 msgid "!Notice:PsxDisc" msgstr "" "L'émulation des jeux Playstation1 n'est pas supportée par PCSX2. Si vous " diff --git a/locales/hu_HU/pcsx2_Iconized.po b/locales/hu_HU/pcsx2_Iconized.po index 472267667..b1328567b 100644 --- a/locales/hu_HU/pcsx2_Iconized.po +++ b/locales/hu_HU/pcsx2_Iconized.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.8\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2012-02-28 12:20+0100\n" +"POT-Creation-Date: 2012-04-07 11:42+0200\n" "PO-Revision-Date: 2011-04-17 17:56+0100\n" "Last-Translator: Delirious \n" "Language-Team: Delirious \n" @@ -24,7 +24,7 @@ msgstr "" "Nincs elegendő szabad virtuális memória, vagy a szükséges virtuális memória " "kiosztás más folyamatok, szolgáltatások vagy DLL-ek számára van fenntartva." -#: pcsx2/CDVD/CDVD.cpp:390 +#: pcsx2/CDVD/CDVD.cpp:389 msgid "!Notice:PsxDisc" msgstr "" "A PlayStation játék lemezeket nem támogatja a PCSX2. Ha PSX játékokat akarsz " diff --git a/locales/id_ID/pcsx2_Iconized.po b/locales/id_ID/pcsx2_Iconized.po index f2b745003..0e22b13a6 100644 --- a/locales/id_ID/pcsx2_Iconized.po +++ b/locales/id_ID/pcsx2_Iconized.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.8 r4560\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2012-02-28 12:25+0100\n" +"POT-Creation-Date: 2012-04-07 11:42+0200\n" "PO-Revision-Date: 2012-01-13 16:56+0700\n" "Last-Translator: \n" "Language-Team: ikazu \n" @@ -27,7 +27,7 @@ msgstr "" msgid "!Notice:VirtualMemoryMap" msgstr "!Pemberitahuan:MapVirtualMemory" -#: pcsx2/CDVD/CDVD.cpp:390 +#: pcsx2/CDVD/CDVD.cpp:389 msgid "!Notice:PsxDisc" msgstr "!Pemberitahuan:DiscPsx" diff --git a/locales/it_IT/pcsx2_Iconized.po b/locales/it_IT/pcsx2_Iconized.po index 83a059d78..82343a8a7 100644 --- a/locales/it_IT/pcsx2_Iconized.po +++ b/locales/it_IT/pcsx2_Iconized.po @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2012-02-28 12:20+0100\n" +"POT-Creation-Date: 2012-04-07 11:42+0200\n" "PO-Revision-Date: 2011-10-05 21:01+0100\n" "Last-Translator: Leucos\n" "Language-Team: \n" @@ -26,7 +26,7 @@ msgstr "" "Non c'è abbastanza memoria virtuale disponibile o gli spazi della memoria " "virtuale necessari sono già stati riservati ad altri processi, servizi o DLL." -#: pcsx2/CDVD/CDVD.cpp:390 +#: pcsx2/CDVD/CDVD.cpp:389 msgid "!Notice:PsxDisc" msgstr "" "I dischi di gioco per PlayStation non sono supportati in PCSX2. Se desideri " diff --git a/locales/ja_JP/pcsx2_Iconized.po b/locales/ja_JP/pcsx2_Iconized.po index a38a9a6db..c37488047 100644 --- a/locales/ja_JP/pcsx2_Iconized.po +++ b/locales/ja_JP/pcsx2_Iconized.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2012-03-10 20:38+0100\n" +"POT-Creation-Date: 2012-04-07 11:42+0200\n" "PO-Revision-Date: 2012-03-05 08:12+0900\n" "Last-Translator: DeltaHF\n" "Language-Team: DeltaHF\n" @@ -29,7 +29,7 @@ msgstr "" "仮想メモリが不足しているか、必要な仮想メモリは既に他のプロセス、サービス、DLL" "に割り当てられています。" -#: pcsx2/CDVD/CDVD.cpp:390 +#: pcsx2/CDVD/CDVD.cpp:389 msgid "!Notice:PsxDisc" msgstr "" "プレイステーション1のディスクはPCSX2でサポートされていません。 \n" diff --git a/locales/pl_PL/pcsx2_Iconized.po b/locales/pl_PL/pcsx2_Iconized.po index e4a3c0475..6c1df04f5 100644 --- a/locales/pl_PL/pcsx2_Iconized.po +++ b/locales/pl_PL/pcsx2_Iconized.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2012-02-28 12:20+0100\n" +"POT-Creation-Date: 2012-04-07 11:42+0200\n" "PO-Revision-Date: 2011-09-28 21:55+0100\n" "Last-Translator: Miseru99 \n" "Language-Team: Miseru99 \n" @@ -30,7 +30,7 @@ msgstr "" "została\n" "już zarezerwowana przez inny process, usługę lub DLL." -#: pcsx2/CDVD/CDVD.cpp:390 +#: pcsx2/CDVD/CDVD.cpp:389 msgid "!Notice:PsxDisc" msgstr "" "Gry z Playstation nie są obsługiwane przez PCSX2. Jeśli chcesz emulować gry " diff --git a/locales/pt_BR/pcsx2_Iconized.po b/locales/pt_BR/pcsx2_Iconized.po index 2284086e7..4388add8e 100644 --- a/locales/pt_BR/pcsx2_Iconized.po +++ b/locales/pt_BR/pcsx2_Iconized.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.7\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2012-02-28 12:20+0100\n" +"POT-Creation-Date: 2012-04-07 11:42+0200\n" "PO-Revision-Date: 2011-09-11 23:09-0300\n" "Last-Translator: Rafael Ferreira \n" "Language-Team: \n" @@ -31,7 +31,7 @@ msgstr "" "virtual necessários já foram reservados para outros processos, serviços ou " "DLLs." -#: pcsx2/CDVD/CDVD.cpp:390 +#: pcsx2/CDVD/CDVD.cpp:389 msgid "!Notice:PsxDisc" msgstr "" "Discos de jogos de Playstation não têm suporte no PCSX2. Se você quiser " diff --git a/locales/ru_RU/pcsx2_Iconized.po b/locales/ru_RU/pcsx2_Iconized.po index c06daf708..0526aae8b 100644 --- a/locales/ru_RU/pcsx2_Iconized.po +++ b/locales/ru_RU/pcsx2_Iconized.po @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2012-02-28 12:20+0100\n" +"POT-Creation-Date: 2012-04-07 11:42+0200\n" "PO-Revision-Date: 2011-04-25 01:25+0100\n" "Last-Translator: Bukhartsev Dmitriy \n" "Language-Team: Kein \n" @@ -26,7 +26,7 @@ msgstr "" "В вашей системе недостаточно виртуальной памяти, либо же, доступное адресное " "пространство уже занято другим процессом, службой или библиотеками." -#: pcsx2/CDVD/CDVD.cpp:390 +#: pcsx2/CDVD/CDVD.cpp:389 msgid "!Notice:PsxDisc" msgstr "" "Эмулятор PCSX2 не поддерживает игры от PlayStation. Если вы желаете " diff --git a/locales/sv_SE/pcsx2_Iconized.po b/locales/sv_SE/pcsx2_Iconized.po index bfafd1c67..bbd5ea229 100644 --- a/locales/sv_SE/pcsx2_Iconized.po +++ b/locales/sv_SE/pcsx2_Iconized.po @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2012-02-28 13:06+0100\n" +"POT-Creation-Date: 2012-04-07 11:42+0200\n" "PO-Revision-Date: 2012-02-28 12:54+0100\n" "Last-Translator: Georg Ronnert \n" "Language-Team: \n" @@ -28,7 +28,7 @@ msgstr "" " virtuella minnestilldelningen redan blivit reserverat av andra processer, " "tjänster, eller DLL'er." -#: pcsx2/CDVD/CDVD.cpp:390 +#: pcsx2/CDVD/CDVD.cpp:389 msgid "!Notice:PsxDisc" msgstr "" "PlayStation®One speldiskar stödjes inte av PCSX2. Om Ni vill emulera PSX-" diff --git a/locales/templates/pcsx2_Iconized.pot b/locales/templates/pcsx2_Iconized.pot index c02324794..3e7325c1c 100644 --- a/locales/templates/pcsx2_Iconized.pot +++ b/locales/templates/pcsx2_Iconized.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2012-02-28 12:20+0100\n" +"POT-Creation-Date: 2012-04-07 11:42+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -26,7 +26,7 @@ msgstr "" msgid "!Notice:VirtualMemoryMap" msgstr "" -#: pcsx2/CDVD/CDVD.cpp:390 +#: pcsx2/CDVD/CDVD.cpp:389 msgid "!Notice:PsxDisc" msgstr "" diff --git a/locales/templates/pcsx2_Main.pot b/locales/templates/pcsx2_Main.pot index eb4e0a280..91e5fb7d0 100644 --- a/locales/templates/pcsx2_Main.pot +++ b/locales/templates/pcsx2_Main.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2012-02-28 12:20+0100\n" +"POT-Creation-Date: 2012-04-07 11:42+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/locales/tr_TR/pcsx2_Iconized.po b/locales/tr_TR/pcsx2_Iconized.po index 5f0a7c44c..9ced83dab 100644 --- a/locales/tr_TR/pcsx2_Iconized.po +++ b/locales/tr_TR/pcsx2_Iconized.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2012-02-28 12:20+0100\n" +"POT-Creation-Date: 2012-04-07 11:42+0200\n" "PO-Revision-Date: 2011-04-08 19:53+0200\n" "Last-Translator: PyramidHead \n" "Language-Team: Ceyhun Özgöç (PyramidHead) \n" @@ -27,7 +27,7 @@ msgstr "" msgid "!Notice:VirtualMemoryMap" msgstr "!Notice:VirtualMemoryMap" -#: pcsx2/CDVD/CDVD.cpp:390 +#: pcsx2/CDVD/CDVD.cpp:389 msgid "!Notice:PsxDisc" msgstr "!Notice:PsxDisc" diff --git a/locales/zh_CN/pcsx2_Iconized.po b/locales/zh_CN/pcsx2_Iconized.po index f2f491f59..5fa134236 100644 --- a/locales/zh_CN/pcsx2_Iconized.po +++ b/locales/zh_CN/pcsx2_Iconized.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2012-02-28 12:20+0100\n" +"POT-Creation-Date: 2012-04-07 11:42+0200\n" "PO-Revision-Date: 2011-08-13 16:51+0700\n" "Last-Translator: Wei Mingzhi \n" "Language-Team: \n" @@ -26,7 +26,7 @@ msgid "!Notice:VirtualMemoryMap" msgstr "" "没有足够的虚拟内存可用,或所需的虚拟内存映射已经被其它进程、服务或 DLL 保留。" -#: pcsx2/CDVD/CDVD.cpp:390 +#: pcsx2/CDVD/CDVD.cpp:389 msgid "!Notice:PsxDisc" msgstr "" "PCSX2 不支持 Playstation 1 游戏。如果您想模拟 PS1 游戏请下载一个 PS1 模拟器," diff --git a/locales/zh_TW/pcsx2_Iconized.po b/locales/zh_TW/pcsx2_Iconized.po index 1e11e38a3..43bf661ea 100644 --- a/locales/zh_TW/pcsx2_Iconized.po +++ b/locales/zh_TW/pcsx2_Iconized.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: PCSX2 0.9.9\n" "Report-Msgid-Bugs-To: http://code.google.com/p/pcsx2/\n" -"POT-Creation-Date: 2012-02-28 12:20+0100\n" +"POT-Creation-Date: 2012-04-07 11:42+0200\n" "PO-Revision-Date: 2011-09-09 11:52+0800\n" "Last-Translator: 呆丸北拜\n" "Language-Team: pcsx2fan\n" @@ -24,7 +24,7 @@ msgstr "" "可用的虛擬記憶體不足,\n" "或必備的虛擬記憶體映射已經被其他處理程序、服務,或 DLL 保留。" -#: pcsx2/CDVD/CDVD.cpp:390 +#: pcsx2/CDVD/CDVD.cpp:389 msgid "!Notice:PsxDisc" msgstr "" "PCSX2 不支援 Playstation 遊戲光碟。\n" From b3f8c59cf48bb5eb70e27e54a875754464472bb6 Mon Sep 17 00:00:00 2001 From: refraction Date: Sat, 7 Apr 2012 12:27:19 +0000 Subject: [PATCH 54/83] -Bumped savestate version, forgot to do that in my last commit. -Fixed a bug stopping GT4 running. -VIF now waits if the VU is busy rather than spinning, causing huge slowdowns. -Filled in some bits i missed git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5149 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/SaveState.h | 2 +- pcsx2/VU0.cpp | 2 ++ pcsx2/Vif0_Dma.cpp | 5 ++++- pcsx2/Vif1_Dma.cpp | 15 ++++++++++++++- pcsx2/Vif1_MFIFO.cpp | 2 +- pcsx2/Vif_Codes.cpp | 2 +- pcsx2/x86/microVU_Macro.inl | 1 + 7 files changed, 24 insertions(+), 5 deletions(-) diff --git a/pcsx2/SaveState.h b/pcsx2/SaveState.h index 11b8745e9..485176b32 100644 --- a/pcsx2/SaveState.h +++ b/pcsx2/SaveState.h @@ -24,7 +24,7 @@ // the lower 16 bit value. IF the change is breaking of all compatibility with old // states, increment the upper 16 bit value, and clear the lower 16 bits to 0. -static const u32 g_SaveVersion = (0x9A06 << 16) | 0x0000; +static const u32 g_SaveVersion = (0x9A07 << 16) | 0x0000; // this function is meant to be used in the place of GSfreeze, and provides a safe layer // between the GS saving function and the MTGS's needs. :) diff --git a/pcsx2/VU0.cpp b/pcsx2/VU0.cpp index 9ece6dd2d..40bd817cc 100644 --- a/pcsx2/VU0.cpp +++ b/pcsx2/VU0.cpp @@ -29,6 +29,7 @@ #include "R5900OpcodeTables.h" #include "VUmicro.h" +#include "Vif_Dma.h" #define _Ft_ _Rt_ #define _Fs_ _Rd_ @@ -164,6 +165,7 @@ void CTC2() { case REG_CMSAR1: // REG_CMSAR1 if (!(VU0.VI[REG_VPU_STAT].UL & 0x100) ) { vu1ExecMicro(cpuRegs.GPR.r[_Rt_].US[0]); // Execute VU1 Micro SubRoutine + vif1VUFinish(); } break; default: diff --git a/pcsx2/Vif0_Dma.cpp b/pcsx2/Vif0_Dma.cpp index 0c8f73c4f..85b720115 100644 --- a/pcsx2/Vif0_Dma.cpp +++ b/pcsx2/Vif0_Dma.cpp @@ -157,6 +157,9 @@ __fi void vif0VUFinish() { vif0.waitforvu = false; ExecuteVU(0); + //Make sure VIF0 isnt already scheduled to spin. + if(!(cpuRegs.interrupt & 0x1)) + vif0Interrupt(); } //DevCon.Warning("VU0 state cleared"); } @@ -194,7 +197,7 @@ __fi void vif0Interrupt() if(vif0.waitforvu == true) { //DevCon.Warning("Waiting on VU0"); - CPU_INT(DMAC_VIF0, 16); + //CPU_INT(DMAC_VIF0, 16); return; } //Must go after the Stall, incase it's still in progress, GTC africa likes to see it still transferring. diff --git a/pcsx2/Vif1_Dma.cpp b/pcsx2/Vif1_Dma.cpp index 59a7e5d14..79c4c8cd0 100644 --- a/pcsx2/Vif1_Dma.cpp +++ b/pcsx2/Vif1_Dma.cpp @@ -229,6 +229,14 @@ __fi void vif1VUFinish() { vif1.waitforvu = false; ExecuteVU(1); + //Check if VIF is already scheduled to interrupt, if it's waiting, kick it :P + if((cpuRegs.interrupt & (1< Date: Sat, 7 Apr 2012 15:35:53 +0000 Subject: [PATCH 55/83] Handle exceptions raised inside the access violation exception filter which we use for various emulation tasks. This was what made the MTVU shutdown issue undebuggable. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5150 96395faa-99c1-11dd-bbfe-3dabce05a288 --- common/src/Utilities/Windows/WinHostSys.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/common/src/Utilities/Windows/WinHostSys.cpp b/common/src/Utilities/Windows/WinHostSys.cpp index 965e6ae28..82b936e1f 100644 --- a/common/src/Utilities/Windows/WinHostSys.cpp +++ b/common/src/Utilities/Windows/WinHostSys.cpp @@ -19,8 +19,7 @@ #include - -int SysPageFaultExceptionFilter( EXCEPTION_POINTERS* eps ) +static int DoSysPageFaultExceptionFilter( EXCEPTION_POINTERS* eps ) { if( eps->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION ) return EXCEPTION_CONTINUE_SEARCH; @@ -33,6 +32,21 @@ int SysPageFaultExceptionFilter( EXCEPTION_POINTERS* eps ) return Source_PageFault->WasHandled() ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH; } +int SysPageFaultExceptionFilter( EXCEPTION_POINTERS* eps ) +{ + // Prevent recursive exception filtering by catching the exception from the filter here. + // In the event that the filter causes an access violation (happened during shutdown + // because Source_PageFault was deallocated), this will allow the debugger to catch the + // exception. + // TODO: find a reliable way to debug the filter itself, I've come up with a few ways that + // work but I don't fully understand why some do and some don't. + __try { + return DoSysPageFaultExceptionFilter(eps); + } __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { + return EXCEPTION_CONTINUE_SEARCH; + } +} + void _platform_InstallSignalHandler() { // NOP on Win32 systems -- we use __try{} __except{} instead. From 6c878aa2eb1e90d0245ab3141d7107fb46b98daa Mon Sep 17 00:00:00 2001 From: refraction Date: Sat, 7 Apr 2012 16:55:42 +0000 Subject: [PATCH 56/83] Removed the cycle counting from the new changes for now as there is a considerable speed hit, possibly later we can put a speed hack in there or game fix to emulate the timings correctly, unfortunately it can be a little too heavy. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5151 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/Vif_Codes.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pcsx2/Vif_Codes.cpp b/pcsx2/Vif_Codes.cpp index 5119dfc7f..b7678bd82 100644 --- a/pcsx2/Vif_Codes.cpp +++ b/pcsx2/Vif_Codes.cpp @@ -76,8 +76,8 @@ static __fi void vuExecMicro(int idx, u32 addr) { if (!idx) vu0ExecMicro(addr); else vu1ExecMicro(addr); - if (!idx) { startcycles = ((VU0.cycle-startcycles) + ( vif0ch.qwc - (vif0.vifpacketsize >> 2) )); CPU_INT(VIF_VU0_FINISH, startcycles * BIAS); } - else { startcycles = ((VU1.cycle-startcycles) + ( vif1ch.qwc - (vif1.vifpacketsize >> 2) )); CPU_INT(VIF_VU1_FINISH, startcycles * BIAS); } + if (!idx) { startcycles = ((VU0.cycle-startcycles) + ( vif0ch.qwc - (vif0.vifpacketsize >> 2) )); CPU_INT(VIF_VU0_FINISH, 1/*startcycles * BIAS*/); } + else { startcycles = ((VU1.cycle-startcycles) + ( vif1ch.qwc - (vif1.vifpacketsize >> 2) )); CPU_INT(VIF_VU1_FINISH, 1/*startcycles * BIAS*/); } //DevCon.Warning("Ran VU%x, VU0 Cycles %x, VU1 Cycles %x, start %x cycle %x", idx, g_vu0Cycles, g_vu1Cycles, startcycles, VU1.cycle); From 49f4168974bcf4437659c5de262498576560df54 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Sat, 7 Apr 2012 21:23:01 +0000 Subject: [PATCH 57/83] zzogl-pg: import GSdump feature from GSdx * Only available on debug build * ctrl F9 -> dump a couple of frames * ctrl shift F9 -> start/stop a stream of frames. * Build a replayer too, called pcsx2_ZZReplayLoader Note: dump are saved in /tmp. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5152 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/zzogl-pg/opengl/CMakeLists.txt | 47 +++++ plugins/zzogl-pg/opengl/GLWin.h | 1 - plugins/zzogl-pg/opengl/GLWinX11.cpp | 2 +- plugins/zzogl-pg/opengl/GSDump.cpp | 96 ++++++++++ plugins/zzogl-pg/opengl/GSDump.h | 65 +++++++ plugins/zzogl-pg/opengl/GSmain.cpp | 225 ++++++++++++++++++++++- plugins/zzogl-pg/opengl/GifTransfer.cpp | 2 + plugins/zzogl-pg/opengl/Util.h | 7 + plugins/zzogl-pg/opengl/ZZKeyboard.cpp | 41 +++++ plugins/zzogl-pg/opengl/linux_replay.cpp | 44 +++++ 10 files changed, 522 insertions(+), 8 deletions(-) create mode 100644 plugins/zzogl-pg/opengl/GSDump.cpp create mode 100644 plugins/zzogl-pg/opengl/GSDump.h create mode 100644 plugins/zzogl-pg/opengl/linux_replay.cpp diff --git a/plugins/zzogl-pg/opengl/CMakeLists.txt b/plugins/zzogl-pg/opengl/CMakeLists.txt index ba0fb692f..ed70bb269 100644 --- a/plugins/zzogl-pg/opengl/CMakeLists.txt +++ b/plugins/zzogl-pg/opengl/CMakeLists.txt @@ -46,6 +46,7 @@ set(zzoglSources GifTransfer.cpp GLWin32.cpp GLWinX11.cpp + GSDump.cpp GSmain.cpp HostMemory.cpp Mem.cpp @@ -82,6 +83,7 @@ set(zzoglHeaders GifTransfer.h # glprocs.h GS.h + GSDump.h HostMemory.h Mem.h Mem_Swizzle.h @@ -141,6 +143,9 @@ add_library(${Output} SHARED ${zzoglLinuxSources} ${zzoglLinuxHeaders}) +# Trick that allow to compile zzogl with GSOPEN2 and the replayer with GSOPEN +set_target_properties(${Output} PROPERTIES COMPILE_DEFINITIONS USE_GSOPEN2) + # link target with project internal libraries target_link_libraries(${Output} Utilities) @@ -171,3 +176,45 @@ else(PACKAGE_MODE) install(TARGETS ${Output} DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins) install(FILES ${PROJECT_SOURCE_DIR}/plugins/zzogl-pg/opengl/ps2hw.dat DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins) endif(PACKAGE_MODE) + +################################### Replay Loader +set(Replay pcsx2_ZZReplayLoader) +set(Static zzogl-static) + +add_library(${Static} STATIC + ${zzoglSources} + ${zzoglHeaders} + ${zzoglSSources} + ${zzoglShaderSources} + ${zzoglLinuxSources} + ${zzoglLinuxHeaders}) + +target_link_libraries(${Static} Utilities) +target_link_libraries(${Static} ${CG_LIBRARIES}) +target_link_libraries(${Static} ${GLEW_LIBRARY}) +target_link_libraries(${Static} ${OPENGL_LIBRARIES}) +target_link_libraries(${Static} ${X11_LIBRARIES}) +target_link_libraries(${Static} ${JPEG_LIBRARIES}) + +add_executable(${Replay} linux_replay.cpp) + +target_link_libraries(${Replay} ${Static}) +target_link_libraries(${Replay} Utilities) +target_link_libraries(${Replay} ${CG_LIBRARIES}) +target_link_libraries(${Replay} ${GLEW_LIBRARY}) +target_link_libraries(${Replay} ${OPENGL_LIBRARIES}) +target_link_libraries(${Replay} ${X11_LIBRARIES}) +target_link_libraries(${Replay} ${JPEG_LIBRARIES}) + +target_link_libraries(${Replay} ${GTK2_LIBRARIES}) +target_link_libraries(${Replay} ${ZLIB_LIBRARIES}) + +if(NOT USER_CMAKE_LD_FLAGS STREQUAL "") + target_link_libraries(${Replay} "${USER_CMAKE_LD_FLAGS}") +endif(NOT USER_CMAKE_LD_FLAGS STREQUAL "") + +if(PACKAGE_MODE) + install(TARGETS ${Replay} DESTINATION bin) +else(PACKAGE_MODE) + install(TARGETS ${Replay} DESTINATION ${CMAKE_SOURCE_DIR}/bin) +endif(PACKAGE_MODE) diff --git a/plugins/zzogl-pg/opengl/GLWin.h b/plugins/zzogl-pg/opengl/GLWin.h index ccd9353a3..0a314b25c 100644 --- a/plugins/zzogl-pg/opengl/GLWin.h +++ b/plugins/zzogl-pg/opengl/GLWin.h @@ -23,7 +23,6 @@ #ifdef _WIN32 #define GL_WIN32_WINDOW #else -#define USE_GSOPEN2 #define GL_X11_WINDOW #endif diff --git a/plugins/zzogl-pg/opengl/GLWinX11.cpp b/plugins/zzogl-pg/opengl/GLWinX11.cpp index 8fabfa8f7..0730acc21 100644 --- a/plugins/zzogl-pg/opengl/GLWinX11.cpp +++ b/plugins/zzogl-pg/opengl/GLWinX11.cpp @@ -339,7 +339,7 @@ void GLWindow::Force43Ratio() s32 new_width = (4*height)/3; // do not bother to resize for 5 pixels. Avoid a loop // due to round value - if ( abs(new_width - width) > 5) { + if ( ABS(new_width - width) > 5) { width = new_width; conf.width = new_width; // resize the window diff --git a/plugins/zzogl-pg/opengl/GSDump.cpp b/plugins/zzogl-pg/opengl/GSDump.cpp new file mode 100644 index 000000000..1da9a63fd --- /dev/null +++ b/plugins/zzogl-pg/opengl/GSDump.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2007-2009 Gabest + * http://www.gabest.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "GSDump.h" + +GSDump::GSDump() + : m_gs(NULL) + , m_frames(0) +{ +} + +GSDump::~GSDump() +{ + Close(); +} + +void GSDump::Open(const string& fn, u32 crc, const freezeData& fd, u8* regs) +{ + if (m_gs) return; + + m_gs = fopen(fn.c_str(), "wb"); + + m_frames = 0; + + if(m_gs) + { + fwrite(&crc, 4, 1, m_gs); + fwrite(&fd.size, 4, 1, m_gs); + fwrite(fd.data, fd.size, 1, m_gs); + fwrite(regs, 0x2000, 1, m_gs); + } +} + +void GSDump::Close() +{ + if(m_gs) { + fclose(m_gs); + m_gs = NULL; + fprintf(stderr, "Closing GS dump"); + } +} + +void GSDump::Transfer(int index, const u8* mem, size_t size) +{ + if(m_gs && size > 0) + { + fputc(0, m_gs); + fputc(index, m_gs); + fwrite(&size, 4, 1, m_gs); + fwrite(mem, size, 1, m_gs); + } +} + +void GSDump::ReadFIFO(u32 size) +{ + if(m_gs && size > 0) + { + fputc(2, m_gs); + fwrite(&size, 4, 1, m_gs); + } +} + +void GSDump::VSync(int field, bool last, u8* regs) +{ + if(m_gs) + { + fputc(3, m_gs); + fwrite(regs, 0x2000, 1, m_gs); + + fputc(1, m_gs); + fputc(field, m_gs); + + if((++m_frames & 1) == 0 && last) + { + Close(); + } + } +} diff --git a/plugins/zzogl-pg/opengl/GSDump.h b/plugins/zzogl-pg/opengl/GSDump.h new file mode 100644 index 000000000..68c2a5c19 --- /dev/null +++ b/plugins/zzogl-pg/opengl/GSDump.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2007-2009 Gabest + * http://www.gabest.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#pragma once + +#include "Util.h" + +using namespace std; + +/* + +Dump file format: +- [crc/4] [state size/4] [state data/size] [PMODE/0x2000] [id/1] [data/?] .. [id/1] [data/?] + +Transfer data (id == 0) +- [0/1] [path index/1] [size/4] [data/size] + +VSync data (id == 1) +- [1/1] [field/1] + +ReadFIFO2 data (id == 2) +- [2/1] [size/?] + +Regs data (id == 3) +- [PMODE/0x2000] + +*/ + +class GSDump +{ + FILE* m_gs; + int m_frames; + +public: + GSDump(); + virtual ~GSDump(); + + void Open(const string& fn, u32 crc, const freezeData& fd, u8* regs); + void Close(); + void ReadFIFO(u32 size); + void Transfer(int index, const u8* mem, size_t size); + void VSync(int field, bool last, u8* regs); + operator bool() {return m_gs != NULL;} +}; + +extern GSDump g_dump; + diff --git a/plugins/zzogl-pg/opengl/GSmain.cpp b/plugins/zzogl-pg/opengl/GSmain.cpp index 80798d9ca..af8a59173 100644 --- a/plugins/zzogl-pg/opengl/GSmain.cpp +++ b/plugins/zzogl-pg/opengl/GSmain.cpp @@ -35,6 +35,7 @@ extern void SaveSnapshot(const char* filename); GLWindow GLWin; GSinternal gs; GSconf conf; +GSDump g_dump; int ppf, g_GSMultiThreaded, CurrentSavestate = 0; int g_LastCRC = 0, g_TransferredToGPU = 0, s_frameskipping = 0; @@ -385,12 +386,11 @@ void CALLBACK GSchangeSaveState(int newstate, const char* filename) SaveStateExists = (access(SaveStateFile, 0) == 0); } -void CALLBACK GSmakeSnapshot(char *path) +static bool get_snapshot_filename(char *filename, char* path, const char* extension) { FUNCLOG FILE *bmpfile; - char filename[256]; u32 snapshotnr = 0; // increment snapshot value & try to get filename @@ -399,7 +399,7 @@ void CALLBACK GSmakeSnapshot(char *path) { snapshotnr++; - sprintf(filename, "%s/snap%03ld.%s", path, snapshotnr, (conf.zz_options.tga_snap) ? "bmp" : "jpg"); + sprintf(filename, "%s/snap%03ld.%s", path, snapshotnr, extension); bmpfile = fopen(filename, "rb"); @@ -420,13 +420,21 @@ void CALLBACK GSmakeSnapshot(char *path) mkdir(path, 0777); #endif - if ((bmpfile = fopen(filename, "wb")) == NULL) return; + if ((bmpfile = fopen(filename, "wb")) == NULL) return false; } fclose(bmpfile); - // get the bits - SaveSnapshot(filename); + return true; +} + +void CALLBACK GSmakeSnapshot(char *path) +{ + FUNCLOG + + char filename[256]; + if (get_snapshot_filename(filename, path, (conf.zz_options.tga_snap) ? "bmp" : "jpg")) + SaveSnapshot(filename); } // I'll probably move this somewhere else later, but it's got a ton of dependencies. @@ -474,6 +482,25 @@ void CALLBACK GSvsync(int interlace) static u32 dwTime = timeGetTime(); static int nToNextUpdate = 1; +#ifdef _DEBUG + if (conf.dump & 0x1) { + freezeData fd; + fd.size = ZZSave(NULL); + s8* payload = (s8*)malloc(fd.size); + fd.data = payload; + + ZZSave(fd.data); + + char filename[256]; + // FIXME, there is probably a better solution than /tmp ... + // A possibility will be to save the path from GSmakeSnapshot but you still need to call + // GSmakeSnapshot first. + if (get_snapshot_filename(filename, "/tmp", "gs")) + g_dump.Open(filename, g_LastCRC, fd, g_pBasePS2Mem); + conf.dump--; + } + g_dump.VSync(interlace, (conf.dump == 0), g_pBasePS2Mem); +#endif GL_REPORT_ERRORD(); @@ -529,6 +556,7 @@ void CALLBACK GSvsync(int interlace) #endif GL_REPORT_ERRORD(); + } void CALLBACK GSreadFIFO(u64 *pMem) @@ -536,6 +564,9 @@ void CALLBACK GSreadFIFO(u64 *pMem) FUNCLOG //ZZLog::GS_Log("Calling GSreadFIFO."); +#ifdef _DEBUG + g_dump.ReadFIFO(1); +#endif TransferLocalHost((u32*)pMem, 1); } @@ -545,6 +576,9 @@ void CALLBACK GSreadFIFO2(u64 *pMem, int qwc) FUNCLOG //ZZLog::GS_Log("Calling GSreadFIFO2."); +#ifdef _DEBUG + g_dump.ReadFIFO(qwc); +#endif TransferLocalHost((u32*)pMem, qwc); } @@ -586,3 +620,182 @@ s32 CALLBACK GSfreeze(int mode, freezeData *data) return 0; } + +#ifdef __LINUX__ + +struct Packet +{ + u8 type, param; + u32 size, addr; + vector buff; +}; + +EXPORT_C_(void) GSReplay(char* lpszCmdLine) +{ + if(FILE* fp = fopen(lpszCmdLine, "rb")) + { + GSinit(); + + u8 regs[0x2000]; + GSsetBaseMem(regs); + + //s_vsync = !!theApp.GetConfig("vsync", 0); + + void* hWnd = NULL; + + //_GSopen((void**)&hWnd, "", renderer); + GSopen((void**)&hWnd, "", 0); + + u32 crc; + fread(&crc, 4, 1, fp); + GSsetGameCRC(crc, 0); + + freezeData fd; + fread(&fd.size, 4, 1, fp); + fd.data = new s8[fd.size]; + fread(fd.data, fd.size, 1, fp); + GSfreeze(FREEZE_LOAD, &fd); + delete [] fd.data; + + fread(regs, 0x2000, 1, fp); + + long start = ftell(fp); + + GSvsync(1); + + list packets; + vector buff; + int type; + + while((type = fgetc(fp)) != EOF) + { + Packet* p = new Packet(); + + p->type = (u8)type; + + switch(type) + { + case 0: + + p->param = (u8)fgetc(fp); + + fread(&p->size, 4, 1, fp); + + switch(p->param) + { + case 0: + p->buff.resize(0x4000); + p->addr = 0x4000 - p->size; + fread(&p->buff[p->addr], p->size, 1, fp); + break; + case 1: + case 2: + case 3: + p->buff.resize(p->size); + fread(&p->buff[0], p->size, 1, fp); + break; + } + + break; + + case 1: + + p->param = (u8)fgetc(fp); + + break; + + case 2: + + fread(&p->size, 4, 1, fp); + + break; + + case 3: + + p->buff.resize(0x2000); + + fread(&p->buff[0], 0x2000, 1, fp); + + break; + + default: assert(0); + } + + packets.push_back(p); + } + + sleep(1); + + //while(IsWindowVisible(hWnd)) + //FIXME map? + int finished = 2; + while(finished > 0) + { + unsigned long start = timeGetTime(); + unsigned long frame_number = 0; + for(list::iterator i = packets.begin(); i != packets.end(); i++) + { + Packet* p = *i; + + switch(p->type) + { + case 0: + + switch(p->param) + { + case 0: GSgifTransfer1(&p->buff[0], p->addr); break; + case 1: GSgifTransfer2(&p->buff[0], p->size / 16); break; + case 2: GSgifTransfer3(&p->buff[0], p->size / 16); break; + case 3: GSgifTransfer(&p->buff[0], p->size / 16); break; + } + + break; + + case 1: + + GSvsync(p->param); + frame_number++; + + break; + + case 2: + + if(buff.size() < p->size) buff.resize(p->size); + + // FIXME + // GSreadFIFO2(&buff[0], p->size / 16); + + break; + + case 3: + + memcpy(regs, &p->buff[0], 0x2000); + + break; + } + } + unsigned long end = timeGetTime(); + fprintf(stderr, "The %d frames of the scene was render on %dms\n", frame_number, end - start); + fprintf(stderr, "A means of %fms by frame\n", (float)(end - start)/(float)frame_number); + + sleep(1); + finished--; + } + + + for(list::iterator i = packets.begin(); i != packets.end(); i++) + { + delete *i; + } + + packets.clear(); + + sleep(1); + + GSclose(); + GSshutdown(); + + fclose(fp); + } +} +#endif diff --git a/plugins/zzogl-pg/opengl/GifTransfer.cpp b/plugins/zzogl-pg/opengl/GifTransfer.cpp index e05cc7025..f8be40629 100644 --- a/plugins/zzogl-pg/opengl/GifTransfer.cpp +++ b/plugins/zzogl-pg/opengl/GifTransfer.cpp @@ -76,6 +76,8 @@ template void _GSgifTransfer(const u32 *pMem, u32 size) #ifdef _DEBUG gifTransferLog(index, pMem, size); + + g_dump.Transfer(index, (const u8*)pMem, size); #endif while (size > 0) diff --git a/plugins/zzogl-pg/opengl/Util.h b/plugins/zzogl-pg/opengl/Util.h index 4bec3e82d..99c98d80a 100644 --- a/plugins/zzogl-pg/opengl/Util.h +++ b/plugins/zzogl-pg/opengl/Util.h @@ -43,6 +43,11 @@ #include #include +#include +#include +#include +#include + #endif #define GSdefs @@ -60,6 +65,7 @@ extern "C" char* CALLBACK PS2EgetLibName(void); #include "ZZoglMath.h" #include "Profile.h" +#include "GSDump.h" #include "Utilities/MemcpyFast.h" #define memcpy_amd memcpy_fast @@ -133,6 +139,7 @@ typedef struct u32 SkipDraw; u32 log; u32 disableHacks; + int dump; void incAA() { aa++; if (aa > 4) aa = 0; } void decAA() { aa--; if (aa > 4) aa = 4; } // u8 is unsigned, so negative value is 255. diff --git a/plugins/zzogl-pg/opengl/ZZKeyboard.cpp b/plugins/zzogl-pg/opengl/ZZKeyboard.cpp index 7d0ec625f..138ed302f 100644 --- a/plugins/zzogl-pg/opengl/ZZKeyboard.cpp +++ b/plugins/zzogl-pg/opengl/ZZKeyboard.cpp @@ -37,6 +37,8 @@ const char* pbilinear[] = { "off", "normal", "forced" }; extern void SetAA(int mode); +extern bool dump_enable; + void ProcessBilinear() { FUNCLOG @@ -110,6 +112,37 @@ void ProcessWireFrame() ZZLog::WriteToScreen(strtitle); } +void ProcessFrameDump() +{ + FUNCLOG + + conf.dump = 1; + + char strtitle[256]; + sprintf(strtitle, "GS dump-frame"); + + ZZLog::WriteToScreen(strtitle); + SaveConfig(); +} + +void ProcessVideoDump() +{ + FUNCLOG + + char strtitle[256]; + + if (conf.dump != 0) { + sprintf(strtitle, "Stop GS dump-video"); + conf.dump = 0; + } else { + sprintf(strtitle, "Start GS dump-video"); + conf.dump = 3; + } + + ZZLog::WriteToScreen(strtitle); + SaveConfig(); +} + void ProcessHackSetting(bool reverse) { FUNCLOG @@ -168,11 +201,19 @@ void OnFKey(int key, int shift) ProcessWireFrame(); break; case 9: +#ifdef _DEBUG + // Fn keys are a bit overload... I don't have a better idea --Gregory + if (shift) + ProcessVideoDump(); + else + ProcessFrameDump(); +#else if (shift) ProcessHackSetting(true); else ProcessHackSetting(false); break; +#endif default: break; } diff --git a/plugins/zzogl-pg/opengl/linux_replay.cpp b/plugins/zzogl-pg/opengl/linux_replay.cpp new file mode 100644 index 000000000..f95b19b0a --- /dev/null +++ b/plugins/zzogl-pg/opengl/linux_replay.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 20011-2012 Hainaut gregory + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "GS.h" + +EXPORT_C_(void) GSsetLogDir(const char* dir); +EXPORT_C_(void) GSsetSettingsDir(const char* dir); +EXPORT_C_(void) GSReplay(char* lpszCmdLine); + + +void help() +{ + fprintf(stderr, "Loader gs file\n"); + fprintf(stderr, "ARG1 Ini directory\n"); + fprintf(stderr, "ARG2 .gs file\n"); + exit(1); +} + +int main ( int argc, char *argv[] ) +{ + if ( argc < 2 ) help(); + + GSsetSettingsDir(argv[1]); + GSsetLogDir("/tmp"); + GSReplay(argv[2]); +} + From 28de2a04c6b61a5db6632a48559b2554571d8e73 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Mon, 9 Apr 2012 12:36:18 +0000 Subject: [PATCH 58/83] SPU2-X: Update Portaudio to revision 1826. Hope the Linux side is fine :p git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5153 96395faa-99c1-11dd-bbfe-3dabce05a288 --- 3rdparty/portaudio/CMakeLists.txt | 344 + .../portaudio/build/msvc/portaudio.vcproj | 4 + .../portaudio/build/msvc/portaudio.vcxproj | 1 + .../build/msvc/portaudio.vcxproj.filters | 3 + .../portaudio/cmake_support/FindASIOSDK.cmake | 41 + .../portaudio/cmake_support/FindDXSDK.cmake | 59 + .../cmake_support/options_cmake.h.in | 31 + .../cmake_support/template_portaudio.def | 53 + 3rdparty/portaudio/doc/src/mainpage.dox | 118 +- .../doc/src/tutorial/blocking_read_write.dox | 68 + .../doc/src/tutorial/compile_cmake.dox | 29 + .../doc/src/tutorial/compile_linux.dox | 77 + .../src/tutorial/compile_mac_coreaudio.dox | 121 + .../doc/src/tutorial/compile_windows.dox | 97 + .../tutorial/compile_windows_asio_msvc.dox | 95 + .../src/tutorial/compile_windows_mingw.dox | 53 + .../portaudio/doc/src/tutorial/exploring.dox | 15 + .../src/tutorial/initializing_portaudio.dox | 29 + .../doc/src/tutorial/open_default_stream.dox | 48 + .../doc/src/tutorial/querying_devices.dox | 111 + .../doc/src/tutorial/start_stop_abort.dox | 35 + .../src/tutorial/terminating_portaudio.dox | 20 + .../doc/src/tutorial/tutorial_start.dox | 56 + .../doc/src/tutorial/utility_functions.dox | 69 + .../doc/src/tutorial/writing_a_callback.dox | 66 + 3rdparty/portaudio/include/pa_mac_core.h | 13 + 3rdparty/portaudio/include/pa_win_wdmks.h | 106 + 3rdparty/portaudio/src/SConscript | 440 +- 3rdparty/portaudio/src/common/pa_trace.c | 137 +- 3rdparty/portaudio/src/common/pa_trace.h | 20 +- .../src/hostapi/alsa/pa_linux_alsa.c | 1180 ++- .../portaudio/src/hostapi/asio/pa_asio.cpp | 46 +- .../src/hostapi/coreaudio/pa_mac_core.c | 41 +- .../portaudio/src/hostapi/dsound/pa_win_ds.c | 30 +- .../src/hostapi/wasapi/pa_win_wasapi.c | 20 +- .../src/hostapi/wdmks/pa_win_wdmks.c | 6498 +++++++++++++---- .../portaudio/src/hostapi/wdmks/readme.txt | 11 +- 37 files changed, 8062 insertions(+), 2123 deletions(-) create mode 100644 3rdparty/portaudio/CMakeLists.txt create mode 100644 3rdparty/portaudio/cmake_support/FindASIOSDK.cmake create mode 100644 3rdparty/portaudio/cmake_support/FindDXSDK.cmake create mode 100644 3rdparty/portaudio/cmake_support/options_cmake.h.in create mode 100644 3rdparty/portaudio/cmake_support/template_portaudio.def create mode 100644 3rdparty/portaudio/doc/src/tutorial/blocking_read_write.dox create mode 100644 3rdparty/portaudio/doc/src/tutorial/compile_cmake.dox create mode 100644 3rdparty/portaudio/doc/src/tutorial/compile_linux.dox create mode 100644 3rdparty/portaudio/doc/src/tutorial/compile_mac_coreaudio.dox create mode 100644 3rdparty/portaudio/doc/src/tutorial/compile_windows.dox create mode 100644 3rdparty/portaudio/doc/src/tutorial/compile_windows_asio_msvc.dox create mode 100644 3rdparty/portaudio/doc/src/tutorial/compile_windows_mingw.dox create mode 100644 3rdparty/portaudio/doc/src/tutorial/exploring.dox create mode 100644 3rdparty/portaudio/doc/src/tutorial/initializing_portaudio.dox create mode 100644 3rdparty/portaudio/doc/src/tutorial/open_default_stream.dox create mode 100644 3rdparty/portaudio/doc/src/tutorial/querying_devices.dox create mode 100644 3rdparty/portaudio/doc/src/tutorial/start_stop_abort.dox create mode 100644 3rdparty/portaudio/doc/src/tutorial/terminating_portaudio.dox create mode 100644 3rdparty/portaudio/doc/src/tutorial/tutorial_start.dox create mode 100644 3rdparty/portaudio/doc/src/tutorial/utility_functions.dox create mode 100644 3rdparty/portaudio/doc/src/tutorial/writing_a_callback.dox create mode 100644 3rdparty/portaudio/include/pa_win_wdmks.h diff --git a/3rdparty/portaudio/CMakeLists.txt b/3rdparty/portaudio/CMakeLists.txt new file mode 100644 index 000000000..febdf2f01 --- /dev/null +++ b/3rdparty/portaudio/CMakeLists.txt @@ -0,0 +1,344 @@ +# $Id: $ +# +# For a "How-To" please refer to the Portaudio documentation at: +# http://www.portaudio.com/trac/wiki/TutorialDir/Compile/CMake +# +PROJECT( portaudio ) + +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +OPTION(PA_CONFIG_LIB_OUTPUT_PATH "Make sure that output paths are kept neat" OFF) +IF(CMAKE_CL_64) +SET(TARGET_POSTFIX x64) +IF(PA_CONFIG_LIB_OUTPUT_PATH) +SET(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/bin/x64) +ENDIF(PA_CONFIG_LIB_OUTPUT_PATH) +ELSE(CMAKE_CL_64) +SET(TARGET_POSTFIX x86) +IF(PA_CONFIG_LIB_OUTPUT_PATH) +SET(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/bin/Win32) +ENDIF(PA_CONFIG_LIB_OUTPUT_PATH) +ENDIF(CMAKE_CL_64) + +IF(WIN32 AND MSVC) +OPTION(PA_DLL_LINK_WITH_STATIC_RUNTIME "Link with static runtime libraries (minimizes runtime dependencies)" ON) +IF(PA_DLL_LINK_WITH_STATIC_RUNTIME) + FOREACH(flag_var + CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE + CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO + CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE + CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) + IF(${flag_var} MATCHES "/MD") + STRING(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") + ENDIF(${flag_var} MATCHES "/MD") + ENDFOREACH(flag_var) +ENDIF(PA_DLL_LINK_WITH_STATIC_RUNTIME) + +ENDIF(WIN32 AND MSVC) + +IF(WIN32) +OPTION(PA_UNICODE_BUILD "Enable Portaudio Unicode build" ON) + +SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake_support) +# Try to find DirectX SDK +FIND_PACKAGE(DXSDK) +# Try to find ASIO SDK (assumes that portaudio and asiosdk folders are side-by-side, see +# http://www.portaudio.com/trac/wiki/TutorialDir/Compile/WindowsASIOMSVC) +FIND_PACKAGE(ASIOSDK) + +IF(ASIOSDK_FOUND) +OPTION(PA_USE_ASIO "Enable support for ASIO" ON) +ELSE(ASIOSDK_FOUND) +OPTION(PA_USE_ASIO "Enable support for ASIO" OFF) +ENDIF(ASIOSDK_FOUND) +IF(DXSDK_FOUND) +OPTION(PA_USE_DS "Enable support for DirectSound" ON) +ELSE(DXSDK_FOUND) +OPTION(PA_USE_DS "Enable support for DirectSound" OFF) +ENDIF(DXSDK_FOUND) +OPTION(PA_USE_WMME "Enable support for MME" ON) +OPTION(PA_USE_WASAPI "Enable support for WASAPI" ON) +OPTION(PA_USE_WDMKS "Enable support for WDMKS" ON) +OPTION(PA_USE_WDMKS_DEVICE_INFO "Use WDM/KS API for device info" ON) +MARK_AS_ADVANCED(PA_USE_WDMKS_DEVICE_INFO) +IF(PA_USE_DS) +OPTION(PA_USE_DIRECTSOUNDFULLDUPLEXCREATE "Use DirectSound full duplex create" ON) +MARK_AS_ADVANCED(PA_USE_DIRECTSOUNDFULLDUPLEXCREATE) +ENDIF(PA_USE_DS) +ENDIF(WIN32) + +# Set variables for DEF file expansion +IF(NOT PA_USE_ASIO) +SET(DEF_EXCLUDE_ASIO_SYMBOLS ";") +ENDIF(NOT PA_USE_ASIO) + +IF(NOT PA_USE_WASAPI) +SET(DEF_EXCLUDE_WASAPI_SYMBOLS ";") +ENDIF(NOT PA_USE_WASAPI) + +IF(PA_USE_WDMKS_DEVICE_INFO) +ADD_DEFINITIONS(-DPAWIN_USE_WDMKS_DEVICE_INFO) +ENDIF(PA_USE_WDMKS_DEVICE_INFO) + +IF(PA_USE_DIRECTSOUNDFULLDUPLEXCREATE) +ADD_DEFINITIONS(-DPAWIN_USE_DIRECTSOUNDFULLDUPLEXCREATE) +ENDIF(PA_USE_DIRECTSOUNDFULLDUPLEXCREATE) + +####################################### +IF(WIN32) +INCLUDE_DIRECTORIES(src/os/win) +ENDIF(WIN32) + +IF(PA_USE_ASIO) +INCLUDE_DIRECTORIES(${ASIOSDK_ROOT_DIR}/common) +INCLUDE_DIRECTORIES(${ASIOSDK_ROOT_DIR}/host) +INCLUDE_DIRECTORIES(${ASIOSDK_ROOT_DIR}/host/pc) + +SET(PA_ASIO_INCLUDES + include/pa_asio.h +) + +SET(PA_ASIO_SOURCES + src/hostapi/asio/pa_asio.cpp +) + +SET(PA_ASIOSDK_SOURCES + ${ASIOSDK_ROOT_DIR}/common/asio.cpp + ${ASIOSDK_ROOT_DIR}/host/pc/asiolist.cpp + ${ASIOSDK_ROOT_DIR}/host/asiodrivers.cpp +) + +SOURCE_GROUP("hostapi\\ASIO" FILES + ${PA_ASIO_SOURCES} +) + +SOURCE_GROUP("hostapi\\ASIO\\ASIOSDK" FILES + ${PA_ASIOSDK_SOURCES} +) +ENDIF(PA_USE_ASIO) + +IF(PA_USE_DS) +INCLUDE_DIRECTORIES(${DXSDK_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(src/os/win) + +SET(PA_DS_INCLUDES + include/pa_win_ds.h + src/hostapi/dsound/pa_win_ds_dynlink.h +) + +SET(PA_DS_SOURCES + src/hostapi/dsound/pa_win_ds.c + src/hostapi/dsound/pa_win_ds_dynlink.c +) + +SOURCE_GROUP("hostapi\\dsound" FILES + ${PA_DS_INCLUDES} + ${PA_DS_SOURCES} +) +ENDIF(PA_USE_DS) + +IF(PA_USE_WMME) + +SET(PA_WMME_INCLUDES + include/pa_win_wmme.h +) + +SET(PA_WMME_SOURCES + src/hostapi/wmme/pa_win_wmme.c +) + +SOURCE_GROUP("hostapi\\wmme" FILES + ${PA_WMME_SOURCES} +) +ENDIF(PA_USE_WMME) + +IF(PA_USE_WASAPI) + +SET(PA_WASAPI_INCLUDES + include/pa_win_wasapi.h +) + +SET(PA_WASAPI_SOURCES + src/hostapi/wasapi/pa_win_wasapi.c +) + +SOURCE_GROUP("hostapi\\wasapi" FILES + ${PA_WASAPI_SOURCES} +) +ENDIF(PA_USE_WASAPI) + +IF(PA_USE_WDMKS) + +SET(PA_WDMKS_INCLUDES + include/pa_win_wdmks.h +) + +SET(PA_WDMKS_SOURCES + src/hostapi/wdmks/pa_win_wdmks.c +) + +SOURCE_GROUP("hostapi\\wdmks" FILES + ${PA_WDMKS_SOURCES} +) +ENDIF(PA_USE_WDMKS) + +SET(PA_SKELETON_SOURCES + src/hostapi/skeleton/pa_hostapi_skeleton.c +) + +SOURCE_GROUP("hostapi\\skeleton" + ${PA_SKELETON_SOURCES}) + +####################################### +IF(WIN32) +SET(PA_INCLUDES + include/portaudio.h + ${PA_ASIO_INCLUDES} + ${PA_DS_INCLUDES} + ${PA_WMME_INCLUDES} + ${PA_WASAPI_INCLUDES} + ${PA_WDMKS_INCLUDES} +) +ENDIF(WIN32) + +SOURCE_GROUP("include" FILES + ${PA_INCLUDES} +) + +SET(PA_COMMON_INCLUDES + src/common/pa_allocation.h + src/common/pa_converters.h + src/common/pa_cpuload.h + src/common/pa_debugprint.h + src/common/pa_dither.h + src/common/pa_endianness.h + src/common/pa_hostapi.h + src/common/pa_memorybarrier.h + src/common/pa_process.h + src/common/pa_ringbuffer.h + src/common/pa_stream.h + src/common/pa_trace.h + src/common/pa_types.h + src/common/pa_util.h +) + +SET(PA_COMMON_SOURCES + src/common/pa_allocation.c + src/common/pa_converters.c + src/common/pa_cpuload.c + src/common/pa_debugprint.c + src/common/pa_dither.c + src/common/pa_front.c + src/common/pa_process.c + src/common/pa_ringbuffer.c + src/common/pa_stream.c + src/common/pa_trace.c +) + +SOURCE_GROUP("common" FILES + ${PA_COMMON_INCLUDES} + ${PA_COMMON_SOURCES} +) + +SOURCE_GROUP("cmake_generated" FILES + ${CMAKE_CURRENT_BINARY_DIR}/portaudio_cmake.def + ${CMAKE_CURRENT_BINARY_DIR}/options_cmake.h +) + +IF(WIN32) +SET(PA_PLATFORM_SOURCES + src/os/win/pa_win_hostapis.c + src/os/win/pa_win_util.c + src/os/win/pa_win_waveformat.c + src/os/win/pa_win_wdmks_utils.c + src/os/win/pa_win_coinitialize.c + src/os/win/pa_x86_plain_converters.c +) + +SOURCE_GROUP("os\\win" FILES + ${PA_PLATFORM_SOURCES} +) +ENDIF(WIN32) + +INCLUDE_DIRECTORIES( include ) +INCLUDE_DIRECTORIES( src/common ) + +IF(WIN32 AND MSVC) +ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) +ENDIF(WIN32 AND MSVC) + +ADD_DEFINITIONS(-DPORTAUDIO_CMAKE_GENERATED) +INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} ) + +SET(SOURCES_LESS_ASIO_SDK + ${PA_COMMON_SOURCES} + ${PA_ASIO_SOURCES} + ${PA_DS_SOURCES} + ${PA_WMME_SOURCES} + ${PA_WASAPI_SOURCES} + ${PA_WDMKS_SOURCES} + ${PA_SKELETON_SOURCES} + ${PA_PLATFORM_SOURCES} +) + +IF(PA_UNICODE_BUILD) +SET_SOURCE_FILES_PROPERTIES( + ${SOURCES_LESS_ASIO_SDK} + PROPERTIES + COMPILE_DEFINITIONS "UNICODE;_UNICODE" +) +ENDIF(PA_UNICODE_BUILD) + +ADD_LIBRARY(portaudio SHARED + ${PA_INCLUDES} + ${PA_COMMON_INCLUDES} + ${SOURCES_LESS_ASIO_SDK} + ${PA_ASIOSDK_SOURCES} + ${CMAKE_CURRENT_BINARY_DIR}/portaudio_cmake.def + ${CMAKE_CURRENT_BINARY_DIR}/options_cmake.h +) + +ADD_LIBRARY(portaudio_static STATIC + ${PA_INCLUDES} + ${PA_COMMON_INCLUDES} + ${SOURCES_LESS_ASIO_SDK} + ${PA_ASIOSDK_SOURCES} + ${CMAKE_CURRENT_BINARY_DIR}/options_cmake.h +) + +# Configure the exports file according to settings +SET(GENERATED_MESSAGE "CMake generated file, do NOT edit! Use CMake-GUI to change configuration instead.") +CONFIGURE_FILE( cmake_support/template_portaudio.def ${CMAKE_CURRENT_BINARY_DIR}/portaudio_cmake.def @ONLY ) +# Configure header for options (PA_USE_xxx) +CONFIGURE_FILE( cmake_support/options_cmake.h.in ${CMAKE_CURRENT_BINARY_DIR}/options_cmake.h @ONLY ) + +IF(WIN32) +# If we use DirectSound, we need this for the library to be found (if not in VS project settings) +IF(PA_USE_DS AND DXSDK_FOUND) +TARGET_LINK_LIBRARIES(portaudio ${DXSDK_DSOUND_LIBRARY}) +ENDIF(PA_USE_DS AND DXSDK_FOUND) + +# If we use WDM/KS we need setupapi.lib +IF(PA_USE_WDMKS) +TARGET_LINK_LIBRARIES(portaudio setupapi) +ENDIF(PA_USE_WDMKS) + +SET_TARGET_PROPERTIES(portaudio PROPERTIES OUTPUT_NAME portaudio_${TARGET_POSTFIX}) +SET_TARGET_PROPERTIES(portaudio_static PROPERTIES OUTPUT_NAME portaudio_static_${TARGET_POSTFIX}) +ENDIF(WIN32) + +OPTION(PA_BUILD_TESTS "Include test projects" OFF) +OPTION(PA_BUILD_EXAMPLES "Include example projects" OFF) + +# Prepared for inclusion of test files +IF(PA_BUILD_TESTS) +SUBDIRS(test) +ENDIF(PA_BUILD_TESTS) + +# Prepared for inclusion of test files +IF(PA_BUILD_EXAMPLES) +SUBDIRS(examples) +ENDIF(PA_BUILD_EXAMPLES) + +################################# + diff --git a/3rdparty/portaudio/build/msvc/portaudio.vcproj b/3rdparty/portaudio/build/msvc/portaudio.vcproj index 4a7e3525c..5c91a11f5 100644 --- a/3rdparty/portaudio/build/msvc/portaudio.vcproj +++ b/3rdparty/portaudio/build/msvc/portaudio.vcproj @@ -942,6 +942,10 @@ RelativePath="..\..\include\pa_win_waveformat.h" > + + diff --git a/3rdparty/portaudio/build/msvc/portaudio.vcxproj b/3rdparty/portaudio/build/msvc/portaudio.vcxproj index 646d1eba3..20f244010 100644 --- a/3rdparty/portaudio/build/msvc/portaudio.vcxproj +++ b/3rdparty/portaudio/build/msvc/portaudio.vcxproj @@ -639,6 +639,7 @@ + diff --git a/3rdparty/portaudio/build/msvc/portaudio.vcxproj.filters b/3rdparty/portaudio/build/msvc/portaudio.vcxproj.filters index 30203b306..29aa7178a 100644 --- a/3rdparty/portaudio/build/msvc/portaudio.vcxproj.filters +++ b/3rdparty/portaudio/build/msvc/portaudio.vcxproj.filters @@ -175,5 +175,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/3rdparty/portaudio/cmake_support/FindASIOSDK.cmake b/3rdparty/portaudio/cmake_support/FindASIOSDK.cmake new file mode 100644 index 000000000..55ad33d95 --- /dev/null +++ b/3rdparty/portaudio/cmake_support/FindASIOSDK.cmake @@ -0,0 +1,41 @@ +# $Id: $ +# +# - Try to find the ASIO SDK +# Once done this will define +# +# ASIOSDK_FOUND - system has ASIO SDK +# ASIOSDK_ROOT_DIR - path to the ASIO SDK base directory +# ASIOSDK_INCLUDE_DIR - the ASIO SDK include directory + +if(WIN32) +else(WIN32) + message(FATAL_ERROR "FindASIOSDK.cmake: Unsupported platform ${CMAKE_SYSTEM_NAME}" ) +endif(WIN32) + +file(GLOB results "${CMAKE_CURRENT_SOURCE_DIR}/../as*") +foreach(f ${results}) + if(IS_DIRECTORY ${f}) + set(ASIOSDK_PATH_HINT ${ASIOSDK_PATH_HINT} ${f}) + endif() +endforeach() + +find_path(ASIOSDK_ROOT_DIR + common/asio.h + HINTS + ${ASIOSDK_PATH_HINT} +) + +find_path(ASIOSDK_INCLUDE_DIR + asio.h + PATHS + ${ASIOSDK_ROOT_DIR}/common +) + +# handle the QUIETLY and REQUIRED arguments and set ASIOSDK_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(ASIOSDK DEFAULT_MSG ASIOSDK_ROOT_DIR ASIOSDK_INCLUDE_DIR) + +MARK_AS_ADVANCED( + ASIOSDK_ROOT_DIR ASIOSDK_INCLUDE_DIR +) diff --git a/3rdparty/portaudio/cmake_support/FindDXSDK.cmake b/3rdparty/portaudio/cmake_support/FindDXSDK.cmake new file mode 100644 index 000000000..3d2f021d8 --- /dev/null +++ b/3rdparty/portaudio/cmake_support/FindDXSDK.cmake @@ -0,0 +1,59 @@ +# $Id: $ +# +# - Try to find the DirectX SDK +# Once done this will define +# +# DXSDK_FOUND - system has DirectX SDK +# DXSDK_ROOT_DIR - path to the DirectX SDK base directory +# DXSDK_INCLUDE_DIR - the DirectX SDK include directory +# DXSDK_LIBRARY_DIR - DirectX SDK libraries path +# +# DXSDK_DSOUND_LIBRARY - Path to dsound.lib +# + +if(WIN32) +else(WIN32) + message(FATAL_ERROR "FindDXSDK.cmake: Unsupported platform ${CMAKE_SYSTEM_NAME}" ) +endif(WIN32) + +find_path(DXSDK_ROOT_DIR + include/dxsdkver.h + HINTS + $ENV{DXSDK_DIR} +) + +find_path(DXSDK_INCLUDE_DIR + dxsdkver.h + PATHS + ${DXSDK_ROOT_DIR}/include +) + +IF(CMAKE_CL_64) +find_path(DXSDK_LIBRARY_DIR + dsound.lib + PATHS + ${DXSDK_ROOT_DIR}/lib/x64 +) +ELSE(CMAKE_CL_64) +find_path(DXSDK_LIBRARY_DIR + dsound.lib + PATHS + ${DXSDK_ROOT_DIR}/lib/x86 +) +ENDIF(CMAKE_CL_64) + +find_library(DXSDK_DSOUND_LIBRARY + dsound.lib + PATHS + ${DXSDK_LIBRARY_DIR} +) + +# handle the QUIETLY and REQUIRED arguments and set DXSDK_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(DXSDK DEFAULT_MSG DXSDK_ROOT_DIR DXSDK_INCLUDE_DIR) + +MARK_AS_ADVANCED( + DXSDK_ROOT_DIR DXSDK_INCLUDE_DIR + DXSDK_LIBRARY_DIR DXSDK_DSOUND_LIBRARY +) diff --git a/3rdparty/portaudio/cmake_support/options_cmake.h.in b/3rdparty/portaudio/cmake_support/options_cmake.h.in new file mode 100644 index 000000000..cd076058e --- /dev/null +++ b/3rdparty/portaudio/cmake_support/options_cmake.h.in @@ -0,0 +1,31 @@ +/* $Id: $ + + !!! @GENERATED_MESSAGE@ !!! + + Header file configured by CMake to convert CMake options/vars to macros. It is done this way because if set via + preprocessor options, MSVC f.i. has no way of knowing when an option (or var) changes as there is no dependency chain. + + The generated "options_cmake.h" should be included like so: + + #ifdef PORTAUDIO_CMAKE_GENERATED + #include "options_cmake.h" + #endif + + so that non-CMake build environments are left intact. + + Source template: cmake_support/options_cmake.h.in +*/ + +#ifdef _WIN32 +#if defined(PA_USE_ASIO) || defined(PA_USE_DS) || defined(PA_USE_WMME) || defined(PA_USE_WASAPI) || defined(PA_USE_WDMKS) +#error "This header needs to be included before pa_hostapi.h!!" +#endif + +#cmakedefine01 PA_USE_ASIO +#cmakedefine01 PA_USE_DS +#cmakedefine01 PA_USE_WMME +#cmakedefine01 PA_USE_WASAPI +#cmakedefine01 PA_USE_WDMKS +#else +#error "Platform currently not supported by CMake script" +#endif diff --git a/3rdparty/portaudio/cmake_support/template_portaudio.def b/3rdparty/portaudio/cmake_support/template_portaudio.def new file mode 100644 index 000000000..8ce2a98bf --- /dev/null +++ b/3rdparty/portaudio/cmake_support/template_portaudio.def @@ -0,0 +1,53 @@ +; $Id: $ +; +; !!! @GENERATED_MESSAGE@ !!! +EXPORTS + +; +Pa_GetVersion @1 +Pa_GetVersionText @2 +Pa_GetErrorText @3 +Pa_Initialize @4 +Pa_Terminate @5 +Pa_GetHostApiCount @6 +Pa_GetDefaultHostApi @7 +Pa_GetHostApiInfo @8 +Pa_HostApiTypeIdToHostApiIndex @9 +Pa_HostApiDeviceIndexToDeviceIndex @10 +Pa_GetLastHostErrorInfo @11 +Pa_GetDeviceCount @12 +Pa_GetDefaultInputDevice @13 +Pa_GetDefaultOutputDevice @14 +Pa_GetDeviceInfo @15 +Pa_IsFormatSupported @16 +Pa_OpenStream @17 +Pa_OpenDefaultStream @18 +Pa_CloseStream @19 +Pa_SetStreamFinishedCallback @20 +Pa_StartStream @21 +Pa_StopStream @22 +Pa_AbortStream @23 +Pa_IsStreamStopped @24 +Pa_IsStreamActive @25 +Pa_GetStreamInfo @26 +Pa_GetStreamTime @27 +Pa_GetStreamCpuLoad @28 +Pa_ReadStream @29 +Pa_WriteStream @30 +Pa_GetStreamReadAvailable @31 +Pa_GetStreamWriteAvailable @32 +Pa_GetSampleSize @33 +Pa_Sleep @34 +@DEF_EXCLUDE_ASIO_SYMBOLS@PaAsio_GetAvailableBufferSizes @50 +@DEF_EXCLUDE_ASIO_SYMBOLS@PaAsio_ShowControlPanel @51 +PaUtil_InitializeX86PlainConverters @52 +@DEF_EXCLUDE_ASIO_SYMBOLS@PaAsio_GetInputChannelName @53 +@DEF_EXCLUDE_ASIO_SYMBOLS@PaAsio_GetOutputChannelName @54 +PaUtil_SetDebugPrintFunction @55 +@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetDeviceDefaultFormat @56 +@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetDeviceRole @57 +@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_ThreadPriorityBoost @58 +@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_ThreadPriorityRevert @59 +@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetFramesPerHostBuffer @60 +@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetJackDescription @61 +@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetJackCount @62 diff --git a/3rdparty/portaudio/doc/src/mainpage.dox b/3rdparty/portaudio/doc/src/mainpage.dox index 3b3cf8671..8f40edeb7 100644 --- a/3rdparty/portaudio/doc/src/mainpage.dox +++ b/3rdparty/portaudio/doc/src/mainpage.dox @@ -1,60 +1,60 @@ -/* doxygen index page */ -/** @mainpage - -@section overview Overview - -PortAudio is a cross-platform, open-source C language library for real-time audio input and output. The library provides functions that allow your software to acquire and output real-time audio streams from your computer's hardware audio interfaces. It is designed to simplify writing cross-platform audio applications, and also to simplify the development of audio software in general by hiding the complexities of dealing directly with each native audio API. PortAudio is used to implement sound recording, editing and mixing applications, software synthesizers, effects processors, music players, internet telephony applications, software defined radios and more. Supported platforms include MS Windows, Mac OS X and Linux. Third-party language bindings make it possible to call PortAudio from other programming languages including C++, C#, Python, PureBasic, FreePascal and Lazarus. - - -@section start_here Start here - -- @ref api_overview
-A top-down view of the PortAudio API, its capabilities, functions and data structures - --
PortAudio Tutorials
-Get started writing code with PortAudio tutorials - -- @ref examples_src "Examples"
-Simple example programs demonstrating PortAudio usage - -- @ref License
-PortAudio is licenced under the MIT Expat open source licence. We make a non-binding request for you to contribute your changes back to the project. - - -@section reference API Reference - -- portaudio.h Portable API
-Detailed documentation for each portable API function and data type - -- @ref public_header "Host API Specific Extensions"
-Documentation for non-portable platform-specific host API extensions - - -@section resources Resources - -- The PortAudio website - -- Our mailing list for users and developers
- -- The PortAudio wiki - - -@section developer_resources Developer Resources - -@if INTERNAL -- @ref srcguide -@endif - -- Our Trac wiki and issue tracking system - -- Coding guidelines - -If you're interested in helping out with PortAudio development we're more than happy for you to be involved. Just drop by the PortAudio mailing list and ask how you can help. Or check out the starter tickets in Trac. - - -@section older_api_versions Older API Versions - -This documentation covers the current API version: PortAudio V19, API version 2.0. API 2.0 differs in a number of ways from previous versions (most often encountered in PortAudio V18), please consult the enhancement proposals for details of what was added/changed for V19: -http://www.portaudio.com/docs/proposals/index.html - +/* doxygen index page */ +/** @mainpage + +@section overview Overview + +PortAudio is a cross-platform, open-source C language library for real-time audio input and output. The library provides functions that allow your software to acquire and output real-time audio streams from your computer's hardware audio interfaces. It is designed to simplify writing cross-platform audio applications, and also to simplify the development of audio software in general by hiding the complexities of dealing directly with each native audio API. PortAudio is used to implement sound recording, editing and mixing applications, software synthesizers, effects processors, music players, internet telephony applications, software defined radios and more. Supported platforms include MS Windows, Mac OS X and Linux. Third-party language bindings make it possible to call PortAudio from other programming languages including C++, C#, Python, PureBasic, FreePascal and Lazarus. + + +@section start_here Start here + +- @ref api_overview
+A top-down view of the PortAudio API, its capabilities, functions and data structures + +- @ref tutorial_start
+Get started writing code with PortAudio tutorials + +- @ref examples_src "Examples"
+Simple example programs demonstrating PortAudio usage + +- @ref License
+PortAudio is licenced under the MIT Expat open source licence. We make a non-binding request for you to contribute your changes back to the project. + + +@section reference API Reference + +- portaudio.h Portable API
+Detailed documentation for each portable API function and data type + +- @ref public_header "Host API Specific Extensions"
+Documentation for non-portable platform-specific host API extensions + + +@section resources Resources + +- The PortAudio website + +- Our mailing list for users and developers
+ +- The PortAudio wiki + + +@section developer_resources Developer Resources + +@if INTERNAL +- @ref srcguide +@endif + +- Our wiki and issue tracking system + +- Coding guidelines + +If you're interested in helping out with PortAudio development we're more than happy for you to be involved. Just drop by the PortAudio mailing list and ask how you can help. Or check out the starter tickets. + + +@section older_api_versions Older API Versions + +This documentation covers the current API version: PortAudio V19, API version 2.0. API 2.0 differs in a number of ways from previous versions (most often encountered in PortAudio V18), please consult the enhancement proposals for details of what was added/changed for V19: +http://www.portaudio.com/docs/proposals/index.html + */ \ No newline at end of file diff --git a/3rdparty/portaudio/doc/src/tutorial/blocking_read_write.dox b/3rdparty/portaudio/doc/src/tutorial/blocking_read_write.dox new file mode 100644 index 000000000..8905ee381 --- /dev/null +++ b/3rdparty/portaudio/doc/src/tutorial/blocking_read_write.dox @@ -0,0 +1,68 @@ +/** @page blocking_read_write Blocking Read/Write Functions +@ingroup tutorial + +PortAudio V19 adds a huge advance over previous versions with a feature called Blocking I/O. Although it may have lower performance that the callback method described earlier in this tutorial, blocking I/O is easier to understand and is, in some cases, more compatible with third party systems than the callback method. Most people starting audio programming also find Blocking I/O easier to learn. + +Blocking I/O works in much the same way as the callback method except that instead of providing a function to provide (or consume) audio data, you must feed data to (or consume data from) PortAudio at regular intervals, usually inside a loop. The example below, excepted from patest_read_write_wire.c, shows how to open the default device, and pass data from its input to its output for a set period of time. Note that we use the default high latency values to help avoid underruns since we are usually reading and writing audio data from a relatively low priority thread, and there is usually extra buffering required to make blocking I/O work. + +Note that not all API's implement Blocking I/O at this point, so for maximum portability or performance, you'll still want to use callbacks. + +@code + /* -- initialize PortAudio -- */ + err = Pa_Initialize(); + if( err != paNoError ) goto error; + + /* -- setup input and output -- */ + inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */ + inputParameters.channelCount = NUM_CHANNELS; + inputParameters.sampleFormat = PA_SAMPLE_TYPE; + inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultHighInputLatency ; + inputParameters.hostApiSpecificStreamInfo = NULL; + + outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ + outputParameters.channelCount = NUM_CHANNELS; + outputParameters.sampleFormat = PA_SAMPLE_TYPE; + outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency; + outputParameters.hostApiSpecificStreamInfo = NULL; + + /* -- setup stream -- */ + err = Pa_OpenStream( + &stream, + &inputParameters, + &outputParameters, + SAMPLE_RATE, + FRAMES_PER_BUFFER, + paClipOff, /* we won't output out of range samples so don't bother clipping them */ + NULL, /* no callback, use blocking API */ + NULL ); /* no callback, so no callback userData */ + if( err != paNoError ) goto error; + + /* -- start stream -- */ + err = Pa_StartStream( stream ); + if( err != paNoError ) goto error; + printf("Wire on. Will run one minute.\n"); fflush(stdout); + + /* -- Here's the loop where we pass data from input to output -- */ + for( i=0; i<(60*SAMPLE_RATE)/FRAMES_PER_BUFFER; ++i ) + { + err = Pa_WriteStream( stream, sampleBlock, FRAMES_PER_BUFFER ); + if( err ) goto xrun; + err = Pa_ReadStream( stream, sampleBlock, FRAMES_PER_BUFFER ); + if( err ) goto xrun; + } + /* -- Now we stop the stream -- */ + err = Pa_StopStream( stream ); + if( err != paNoError ) goto error; + + /* -- don't forget to cleanup! -- */ + err = Pa_CloseStream( stream ); + if( err != paNoError ) goto error; + + Pa_Terminate(); + return 0; +@endcode + + +Previous: \ref querying_devices | Next: \ref exploring + +*/ \ No newline at end of file diff --git a/3rdparty/portaudio/doc/src/tutorial/compile_cmake.dox b/3rdparty/portaudio/doc/src/tutorial/compile_cmake.dox new file mode 100644 index 000000000..ddf5eae61 --- /dev/null +++ b/3rdparty/portaudio/doc/src/tutorial/compile_cmake.dox @@ -0,0 +1,29 @@ +/** @page compile_cmake Creating MSVC Build Files via CMake +@ingroup tutorial + +This is a simple "How-to" for creating build files for Microsoft Visual C++ via CMake and the CMakeLists.txt file + +1. Install CMake if you haven't got it already ([http://www.cmake.org], minimum version required is 2.8). + +2. If you want ASIO support you need to D/L the ASIO2 SDK from Steinberg, and place it according to \ref compile_windows_asio_msvc + +3. Run the CMake GUI application and browse to source files directory and build directory: + a. The source files directory ("Where is the source code") is where the portaudio CMakeLists.txt file is located. + b. The build directory ("Where to build the binaries") is pretty much anywhere you like. A common practice though is to have the build directory located outside the + source files tree (a so called "out-of-source build") + +4. Click Configure. This will prompt you to select which build files to generate. Note Only Microsoft Visual C++ build files currently supported! + +5. In the CMake option list, enable the PORTAUDIO_xxx options you need, then click Configure again (Note that after this there are no options marked with red color) + +6. Click Generate and you'll now (hopefully) have your VS build files in your previously defined build directory. + +Both ASIO and DirectX SDK are automatically searched for by the CMake script, so if you have DirectX SDK installed and have placed the ASIO2 SDK according to point 2 above, you should be able to build portaudio with !DirectSound and ASIO support. + +Should you later on decide to change a portaudio option, just jump in at step 5 above (MSVC will then prompt you to reload projects/solutions/workspace) + +--- Robert Bielik + +Back to the Tutorial: \ref tutorial_start + +*/ \ No newline at end of file diff --git a/3rdparty/portaudio/doc/src/tutorial/compile_linux.dox b/3rdparty/portaudio/doc/src/tutorial/compile_linux.dox new file mode 100644 index 000000000..232cac67e --- /dev/null +++ b/3rdparty/portaudio/doc/src/tutorial/compile_linux.dox @@ -0,0 +1,77 @@ +/** @page compile_linux Building Portaudio for Linux +@ingroup tutorial + +Note: this page has not been reviewed, and may contain errors. + +@section comp_linux1 Installing ALSA Development Kit + +The OSS sound API is very old and not well supported. It is recommended that you use the ALSA sound API. +The PortAudio configure script will look for the ALSA SDK. You can install the ALSA SDK on Ubuntu using: + +@code +sudo apt-get install libasound-dev +@endcode + +You might need to use yum, or some other package manager, instead of apt-get on your machine. +If you do not install ALSA then you might get a message when testing that says you have no audio devices. + +You can find out more about ALSA here: http://www.alsa-project.org/ + +@section comp_linux2 Configuring and Compiling PortAudio + +You can build PortAudio in Linux Environments using the standard configure/make tools: + +@code +./configure && make +@endcode + +That will build PortAudio using Jack, ALSA and OSS in whatever combination they are found on your system. For example, if you have Jack and OSS but not ALSA, it will build using Jack and OSS but not ALSA. This step also builds a number of tests, which can be found in the bin directory of PortAudio. It's a good idea to run some of these tests to make sure PortAudio is working correctly. + +@section comp_linux3 Using PortAudio in your Projects + +To use PortAudio in your apps, you can simply install the .so files: + +@code +make install +@endcode + +Projects built this way will expect PortAudio to be installed on target systems in order to run. If you want to build a more self-contained binary, you may use the libportaudio.a file: + +@code +cp lib/.libs/libportaudio.a /YOUR/PROJECT/DIR +@endcode + +You may also need to copy portaudio.h, located in the include/ directory of PortAudio into your project. Note that you will usually need to link with the approriate libraries that you used, such as ALSA and JACK, as well as with librt and libpthread. For example: + +@code +gcc -lrt -lasound -ljack -lpthread -o YOUR_BINARY main.c libportaudio.a +@endcode + +@section comp_linux4 Linux Extensions + +Note that the ALSA PortAudio back-end adds a few extensions to the standard API that you may take advantage of. To use these functions be sure to include the pa_linux_alsa.h file found in the include file in the PortAudio folder. This file contains further documentation on the following functions: + + PaAlsaStreamInfo/PaAlsa_InitializeStreamInfo:: + Objects of the !PaAlsaStreamInfo type may be used for the !hostApiSpecificStreamInfo attribute of a !PaStreamParameters object, in order to specify the name of an ALSA device to open directly. Specify the device via !PaAlsaStreamInfo.deviceString, after initializing the object with PaAlsa_InitializeStreamInfo. + + PaAlsa_EnableRealtimeScheduling:: + PA ALSA supports real-time scheduling of the audio callback thread (using the FIFO pthread scheduling policy), via the extension PaAlsa_EnableRealtimeScheduling. Call this on the stream before starting it with the enableScheduling parameter set to true or false, to enable or disable this behaviour respectively. + + PaAlsa_GetStreamInputCard:: + Use this function to get the ALSA-lib card index of the stream's input device. + + PaAlsa_GetStreamOutputCard:: + Use this function to get the ALSA-lib card index of the stream's output device. + +Of particular importance is PaAlsa_EnableRealtimeScheduling, which allows ALSA to run at a high priority to prevent ordinary processes on the system from preempting audio playback. Without this, low latency audio playback will be irregular and will contain frequent drop-outs. + +@section comp_linux5 Linux Debugging + +Eliot Blennerhassett writes: + +On linux build, use e.g. "libtool gdb bin/patest_sine8" to debug that program. +This is because on linux bin/patest_sine8 is a libtool shell script that wraps +bin/.libs/patest_sine8 and allows it to find the appropriate libraries within +the build tree. + +*/ \ No newline at end of file diff --git a/3rdparty/portaudio/doc/src/tutorial/compile_mac_coreaudio.dox b/3rdparty/portaudio/doc/src/tutorial/compile_mac_coreaudio.dox new file mode 100644 index 000000000..6984d1e7c --- /dev/null +++ b/3rdparty/portaudio/doc/src/tutorial/compile_mac_coreaudio.dox @@ -0,0 +1,121 @@ +/** @page compile_mac_coreaudio Building Portaudio for Mac OS X +@ingroup tutorial + +@section comp_mac_ca_1 Requirements + +* OS X 10.4 or later. PortAudio v19 currently only compiles and runs on OS X version 10.4 or later. Because of its heavy reliance on memory barriers, it's not clear how easy it would be to back-port PortAudio to OS X version 10.3. Leopard support requires the 2007 snapshot or later. + +* Apple's Xcode and its related tools installed in the default location. There is no Xcode project for PortAudio. + +* Mac 10.4 SDK. Look for "/Developer/SDKs/MacOSX10.4u.sdk" folder on your system. It may be installed with XCode. If not then you can download it from Apple Developer Connection. http://connect.apple.com/ + +@section comp_mac_ca_2 Building + +To build PortAudio, simply use the Unix-style "./configure && make": + +@code + ./configure && make +@endcode + +You do not need to do "make install", and we don't recommend it; however, you may be using software that instructs you to do so, in which case you should follow those instructions. (Note from Phil: I had to do "sudo make install" after the command above, otherwise XCode complained that it could not find "/usr/local/lib/libportaudio.dylib" when I compiled an example.) + +The result of these steps will be a file named "libportaudio.dylib" in the directory "usr/local/lib/". + +By default, this will create universal binaries and therefore requires the Universal SDK from Apple, included with XCode 2.1 and higher. + +@section comp_mac_ca_3 Other Build Options + +There are a variety of other options for building PortAudio. The default described above is recommended as it is the most supported and tested; however, your needs may differ and require other options, which are described below. + +@subsection comp_mac_ca_3.1 Building Non-Universal Libraries + +By default, PortAudio is built as a universal binary. This includes 64-bit versions if you are compiling on 10.5, Leopard. If you want a "thin", or single architecture library, you have two options: + + * build a non-universal library using configure options. + * use lipo(1) on whatever part of the library you plan to use. + +Note that the first option may require an extremely recent version of PortAudio (February 5th '08 at least). + +@subsection comp_mac_ca_3.2 Building with --disable-mac-universal + +To build a non-universal library for the host architecture, simply use the --disable-mac-universal option with configure. + +@code + ./configure --disable-mac-universal && make +@endcode + +The --disable-mac-universal option may also be used in conjunction with environment variables to give you more control over the universal binary build process. For example, to build a universal binary for the i386 and ppc architectures using the 10.4u sdk (which is the default on 10.4, but not 10.5), you might specify this configure command line: + +@code + CFLAGS="-O2 -g -Wall -arch i386 -arch ppc -isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.3" \ + LDFLAGS="-arch i386 -arch ppc -isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.3" \ + ./configure --disable-mac-universal --disable-dependency-tracking +@endcode + +For more info, see Apple's documentation on the matter: + + * http://developer.apple.com/technotes/tn2005/tn2137.html + * http://developer.apple.com/documentation/Porting/Conceptual/PortingUnix/intro/chapter_1_section_1.html + +@subsection comp_mac_ca_3.3 Using lipo + +The second option is to build normally, and use lipo (1) to extract the architectures you want. For example, if you want a "thin", i386 library only: + +@code + lipo lib/.libs/libportaudio.a -thin i386 -output libportaudio.a +@endcode + +or if you want to extract a single architecture fat file: + +@code + lipo lib/.libs/libportaudio.a -extract i386 -output libportaudio.a +@endcode + +@subsection comp_mac_ca_3.4 Building With Debug Options + +By default, PortAudio on the mac is built without any debugging options. This is because asserts are generally inappropriate for a production environment and debugging information has been suspected, though not proven, to cause trouble with some interfaces. If you would like to compile with debugging, you must run configure with the appropriate flags. For example: + +@code + ./configure --enable-mac-debug && make +@endcode + +This will enable -g and disable -DNDEBUG which will effectively enable asserts. + +@section comp_mac_ca_4 Using the Library in XCode Projects + +If you are planning to follow the rest of the tutorial, several project types will work. You can create a "Standard Tool" under "Command Line Utility". If you are not following the rest of the tutorial, any type of project should work with PortAudio, but these instructions may not work perfectly. + +Once you've compiled PortAudio, the easiest and recommended way to use PortAudio in your XCode project is to add "/include/portaudio.h" and "/lib/.libs/libportaudio.a" to your project. Because "/lib/.libs/" is a hidden directory, you won't be able to navigate to it using the finder or the standard Mac OS file dialogs by clicking on files and folders. You can use command-shift-G in the finder to specify the exact path, or, from the shell, if you are in the portaudio directory, you can enter this command: + +@code + open lib/.libs +@endcode + +Then drag the "libportaudio.a" file into your XCode project and place it in the "External Frameworks and Libraries" group, if the project type has it. If not you can simply add it to the top level folder of the project. + +You will need to add the following frameworks to your XCode project: + + - CoreAudio.framework + - AudioToolbox.framework + - AudioUnit.framework + - CoreServices.framework + +@section comp_mac_ca_5 Using the Library in Other Projects + +For gcc/Make style projects, include "include/portaudio.h" and link "libportaudio.a", and use the frameworks listed in the previous section. How you do so depends on your build. + +@section comp_mac_ca_6 Using Mac-only Extensions to PortAudio + +For additional, Mac-only extensions to the PortAudio interface, you may also want to grab "include/pa_mac_core.h". This file contains some special, mac-only features relating to sample-rate conversion, channel mapping, performance and device hogging. See "src/hostapi/coreaudio/notes.txt" for more details on these features. + +@section comp_mac_ca_7 What Happened to Makefile.darwin? + +Note, there used to be a special makefile just for darwin. This is no longer supported because you can build universal binaries from the standard configure routine. If you find this file in your directory structure it means you have an outdated version of PortAudio. + +@code + make -f Makefile.darwin +@endcode + +Back to the Tutorial: \ref tutorial_start + +*/ \ No newline at end of file diff --git a/3rdparty/portaudio/doc/src/tutorial/compile_windows.dox b/3rdparty/portaudio/doc/src/tutorial/compile_windows.dox new file mode 100644 index 000000000..63f1f63f7 --- /dev/null +++ b/3rdparty/portaudio/doc/src/tutorial/compile_windows.dox @@ -0,0 +1,97 @@ +/** @page compile_windows Building Portaudio for Windows using Microsoft Visual Studio +@ingroup tutorial + +Below is a list of steps to build PortAudio into a dll and lib file. The resulting dll file may contain all five current win32 PortAudio APIs: MME, DirectSound, WASAPI, WDM/KS and ASIO, depending on the preprocessor definitions set in step 9 below. + +PortAudio can be compiled using Visual C++ Express Edition which is available free from Microsoft. If you do not already have a C++ development environment, simply download and install. These instructions have been observed to succeed using Visual Studio 2010 as well. + +1) PortAudio for Windows requires the files dsound.h and dsconf.h. Download and install the DirectX SDK from http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=3021d52b-514e-41d3-ad02-438a3ba730ba to obtain these files. If you installed the DirectX SDK then the !DirectSound libraries and header files should be found automatically by Visual !Studio/Visual C++. If you get an error saying dsound.h or dsconf.h is missing, you can declare these paths by hand. Alternatively, you can copy dsound.h and dsconf.h to portaudio\\include. There should also be a file named ''dsound.lib'' in C:\\Program Files\\Microsoft SDKs\\Windows\\v6.0A\\Lib. + +2) For ASIO support, download the ASIO SDK from Steinberg at http://www.steinberg.net/en/company/developer.html. The SDK is free but you will need to set up a developer account with Steinberg. Copy the entire ASIOSDK2 folder into src\\hostapi\\asio\\. Rename it from ASIOSDK2 to ASIOSDK. To build without ASIO (or other host API) see the "Building without ASIO support" section below. + +3) If you have Visual Studio 6.0, 7.0(VC.NET/2001) or 7.1(VC.2003), open portaudio.dsp and convert if needed. + +4) If you have Visual Studio 2005, Visual C++ 2008 Express Edition or Visual Studio 2010, double click the portaudio.sln file located in build\\msvc\\. Doing so will open Visual Studio or Visual C++. Click "Finish" if a wizard appears. The sln file contains four configurations: Win32 and Win64 in both Release and Debug variants. + +@section comp_win1 For Visual Studio 2005, Visual C++ 2008 Express Edition or Visual Studio 2010 + +5) Open Project -> portaudio Properties and select "Configuration Properties" in the tree view. + +6) Select "all configurations" in the "Configurations" combo box above. Select "All Platforms" in the "Platforms" combo box. + +7) Now set a few options: + +C/C++ -> Optimization -> Omit frame pointers = Yes + +C/C++ -> Code Generation -> Runtime library = /MT + +Optional: C/C++ -> Code Generation -> Floating point model = fast + +NOTE: For most users it is not necessary to explicitly set the structure member alignment; the default should work fine. However some languages require, for example, 4-byte alignment. If you are having problems with portaudio.h structure members not being properly read or written to, it may be necessary to explicitly set this value by going to C/C++ -> Code Generation -> Struct member alignment and setting it to an appropriate value (four is a common value). If your compiler is configurable, you should ensure that it is set to use the same structure member alignment value as used for the PortAudio build. + +Click "Ok" when you have finished setting these parameters. + +@section comp_win2 Preprocessor Definitions + +Since the preprocessor definitions are different for each configuration and platform, you'll need to edit these individually for each configuration/platform combination that you want to modify using the "Configurations" and "Platforms" combo boxes. + +8) To suppress PortAudio runtime debug console output, go to Project -> Properties -> Configuration Properties -> C/C++ -> Preprocessor. In the field 'Preprocessor Definitions', find PA_ENABLE_DEBUG_OUTPUT and remove it. The console will not output debug messages. + +9) Also in the preprocessor definitions you need to explicitly define the audio APIs you wish to use. For Windows the available API definitions are: + +PA_USE_ASIO[[BR]] +PA_USE_DS (DirectSound)[[BR]] +PA_USE_WMME (MME)[[BR]] +PA_USE_WASAPI[[BR]] +PA_USE_WDMKS[[BR]] +PA_USE_SKELETON + +For each of these, the value of 0 indicates that support for this API should not be included. The value 1 indicates that support for this API should be included. + +@section comp_win3 Building + +As when setting Preprocessor definitions, building is a per-configuration per-platform process. Follow these instructions for each configuration/platform combination that you're interested in. + +10) From the Build menu click Build -> Build solution. For 32-bit compilations, the dll file created by this process (portaudio_x86.dll) can be found in the directory build\\msvc\\Win32\\Release. For 64-bit compilations, the dll file is called portaudio_x64.dll, and is found in the directory build\\msvc\\x64\\Release. + +11) Now, any project which requires portaudio can be linked with portaudio_x86.lib (or _x64) and include the relevant headers (portaudio.h, and/or pa_asio.h , pa_x86_plain_converters.h) You may want to add/remove some DLL entry points. Right now those 6 entries are not from portaudio.h: + +(from portaudio.def) +@code +... +PaAsio_GetAvailableLatencyValues @50 +PaAsio_ShowControlPanel @51 +PaUtil_InitializeX86PlainConverters @52 +PaAsio_GetInputChannelName @53 +PaAsio_GetOutputChannelName @54 +PaUtil_SetLogPrintFunction @55 +@endcode + +@section comp_win4 Building without ASIO support + +To build PortAudio without ASIO support you need to: + +1) Make sure your project doesn't try to build any ASIO SDK files. If you're using one of the shipped projects, remove the ASIO related files from the project. + +2) Make sure your project doesn't try to build the PortAudio ASIO implementation files: + +src\\hostapi\\pa_asio.cpp src\\hostapi\\iasiothiscallresolver.cpp + +If you're using one of the shipped projects, remove them from the project. + +3) Define the preprocessor symbols in the project properties as described in step 9 above. In VS2005 this can be accomplished by selecting +Project Properties -> Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions. Omitting PA_USE_ASIO or setting it to 0 stops src\\os\\win\\pa_win_hostapis.c from trying to initialize the PortAudio ASIO implementation. + +4) Remove PaAsio_* entry points from portaudio.def + + +----- +David Viens, davidv@plogue.com + +Updated by Chris on 5/26/2011 + +Improvements by John Clements on 12/15/2011 + +Back to the Tutorial: \ref tutorial_start + +*/ \ No newline at end of file diff --git a/3rdparty/portaudio/doc/src/tutorial/compile_windows_asio_msvc.dox b/3rdparty/portaudio/doc/src/tutorial/compile_windows_asio_msvc.dox new file mode 100644 index 000000000..8a8e10724 --- /dev/null +++ b/3rdparty/portaudio/doc/src/tutorial/compile_windows_asio_msvc.dox @@ -0,0 +1,95 @@ +/** @page compile_windows_asio_msvc Building Portaudio for Windows with ASIO support using MSVC +@ingroup tutorial + +@section comp_win_asiomsvc1 Portaudio Windows ASIO with MSVC + +This tutorial describes how to build PortAudio with ASIO support using MSVC *from scratch*, without an existing Visual Studio project. For instructions for building PortAudio (including ASIO support) using the bundled Visual Studio project file see the compiling instructions for \ref compile_windows. + +ASIO is a low latency audio API from Steinberg. To compile an ASIO +application, you must first download the ASIO SDK from Steinberg. You also +need to obtain ASIO drivers for your audio device. Download the ASIO SDK from Steinberg at http://www.steinberg.net/en/company/developer.html. The SDK is free but you will need to set up a developer account with Steinberg. + +This tutorial assumes that you have 3 directories set up at the same level (side by side), one containing PortAudio, one containing the ASIO SDK and one containing your Visual Studio project: + +@code +/ASIOSDK2 +/portaudio +/DirContainingYourVisualStudioProject +@endcode + +First, make sure that the Steinberg SDK and the portaudio files are "side by side" in the same directory. + +Open Microsoft Visual C++ and create a new blank Console exe Project/Workspace in that same directory. + +For example, the paths for all three groups might read like this: + +@code +C:\Program Files\Microsoft Visual Studio\VC98\My Projects\ASIOSDK2 +C:\Program Files\Microsoft Visual Studio\VC98\My Projects\portaudio +C:\Program Files\Microsoft Visual Studio\VC98\My Projects\Sawtooth +@endcode + + +Next, add the following Steinberg ASIO SDK files to the project Source Files: + +@code +asio.cpp (ASIOSDK2\common) +asiodrivers.cpp (ASIOSDK2\host) +asiolist.cpp (ASIOSDK2\host\pc) +@endcode + + +Then, add the following PortAudio files to the project Source Files: + +@code +pa_asio.cpp (portaudio\src\hostapi\asio) +pa_allocation.c (portaudio\src\common) +pa_converters.c (portaudio\src\common) +pa_cpuload.c (portaudio\src\common) +pa_dither.c (portaudio\src\common) +pa_front.c (portaudio\src\common) +pa_process.c (portaudio\src\common) +pa_ringbuffer.c (portaudio\src\common) +pa_stream.c (portaudio\src\common) +pa_trace.c (portaudio\src\common) +pa_win_hostapis.c (portaudio\src\os\win) +pa_win_util.c (portaudio\src\os\win) +pa_win_waveformat.c (portaudio\src\os\win) +pa_x86_plain_converters.c (portaudio\src\os\win) +patest_saw.c (portaudio\test) (Or another file containing main() + for the console exe to be built.) +@endcode + + +Although not strictly necessary, you may also want to add the following files to the project Header Files: + +@code +portaudio.h (portaudio\include) +pa_asio.h (portaudio\include) +@endcode + +These header files define the interfaces to the PortAudio API. + + +Next, go to Project Settings > All Configurations > C/C++ > Preprocessor > Preprocessor definitions and add +PA_USE_ASIO=1 to any entries that might be there. + +eg: WIN32;_CONSOLE;_MBCS changes to WIN32;_CONSOLE,_MBCS;PA_USE_ASIO=1 + +Then, on the same Project Settings tab, go down to Additional include directories: and enter the following relative include paths. + +@code +..\portaudio\include,..\portaudio\src\common,..\asiosdk2\common,..\asiosdk2\host,..\asiosdk2\host\pc +@endcode + +You'll need to make sure the relative paths are correct for the particular directory layout you're using. The above should work fine if you use the side-by-side layout we recommended earlier. + +You should now be able to build any of the test executables in the portaudio\test directory. +We suggest that you start with patest_saw.c because it's one of the simplest test files. + +--- Chris Share, Tom McCandless, Ross Bencina + +[wiki:UsingThePortAudioSvnRepository SVN instructions] +Back to the Tutorial: \ref tutorial_start + +*/ \ No newline at end of file diff --git a/3rdparty/portaudio/doc/src/tutorial/compile_windows_mingw.dox b/3rdparty/portaudio/doc/src/tutorial/compile_windows_mingw.dox new file mode 100644 index 000000000..47bba386a --- /dev/null +++ b/3rdparty/portaudio/doc/src/tutorial/compile_windows_mingw.dox @@ -0,0 +1,53 @@ +/** @page compile_windows_mingw Building Portaudio for Windows with MinGW +@ingroup tutorial + +@section comp_mingw1 Portaudio for Windows With MinGW + +The following document is still being reviewed + += MinGW/MSYS = + +From the [http://www.mingw.org MinGW projectpage]: + +MinGW: A collection of freely available and freely distributable +Windows specific header files and import libraries, augmenting +the GNU Compiler Collection, (GCC), and its associated +tools, (GNU binutils). MinGW provides a complete Open Source +programming tool set which is suitable for the development of +native Windows programs that do not depend on any 3rd-party C +runtime DLLs. + +MSYS: A Minimal SYStem providing a POSIX compatible Bourne shell +environment, with a small collection of UNIX command line +tools. Primarily developed as a means to execute the configure +scripts and Makefiles used to build Open Source software, but +also useful as a general purpose command line interface to +replace Windows cmd.exe. + +MinGW provides a compiler/linker toolchain while MSYS is required +to actually run the PortAudio configure script. + +Once MinGW and MSYS are installed (see the [http://www.mingw.org/MinGWiki MinGW-Wiki]) open an MSYS shell and run the famous: + +@code +./configure +make +make install +@endcode + +The above should create a working version though you might want to +provide '--prefix=' to configure. + +'./configure --help' gives details as to what can be tinkered with. + +--- Mikael Magnusson + +To update your copy or check out a fresh copy of the source + +[wiki:UsingThePortAudioSvnRepository SVN instructions] + +--- Bob !McGwier + +Back to the Tutorial: \ref tutorial_start + +*/ \ No newline at end of file diff --git a/3rdparty/portaudio/doc/src/tutorial/exploring.dox b/3rdparty/portaudio/doc/src/tutorial/exploring.dox new file mode 100644 index 000000000..9dd087348 --- /dev/null +++ b/3rdparty/portaudio/doc/src/tutorial/exploring.dox @@ -0,0 +1,15 @@ +/** @page exploring Exploring PortAudio +@ingroup tutorial + +Now that you have a good idea of how PortAudio works, you can try out the example programs. You'll find them in the examples/ directory in the PortAudio distribution. + +For an example of playing a sine wave, see examples/paex_sine.c. + +For an example of recording and playing back a sound, see examples/paex_record.c. + +I also encourage you to examine the source for the PortAudio libraries. If you have suggestions on ways to improve them, please let us know. If you want to implement PortAudio on a new platform, please let us know as well so we can coordinate people's efforts. + + +Previous: \ref blocking_read_write | Next: This is the end of the tutorial. + +*/ \ No newline at end of file diff --git a/3rdparty/portaudio/doc/src/tutorial/initializing_portaudio.dox b/3rdparty/portaudio/doc/src/tutorial/initializing_portaudio.dox new file mode 100644 index 000000000..9439c350d --- /dev/null +++ b/3rdparty/portaudio/doc/src/tutorial/initializing_portaudio.dox @@ -0,0 +1,29 @@ +/** @page initializing_portaudio Initializing PortAudio +@ingroup tutorial + +@section tut_init1 Initializing PortAudio + +Before making any other calls to PortAudio, you 'must' call Pa_Initialize(). This will trigger a scan of available devices which can be queried later. Like most PA functions, it will return a result of type paError. If the result is not paNoError, then an error has occurred. +@code +err = Pa_Initialize(); +if( err != paNoError ) goto error; +@endcode + +You can get a text message that explains the error message by passing it to Pa_GetErrorText( err ). For Example: + +@code +printf( "PortAudio error: %s\n", Pa_GetErrorText( err ) ); +@endcode + +It is also important, when you are done with PortAudio, to Terminate it: + +@code +err = Pa_Terminate(); +if( err != paNoError ) + printf( "PortAudio error: %s\n", Pa_GetErrorText( err ) ); +@endcode + + +Previous: \ref writing_a_callback | Next: \ref open_default_stream + +*/ \ No newline at end of file diff --git a/3rdparty/portaudio/doc/src/tutorial/open_default_stream.dox b/3rdparty/portaudio/doc/src/tutorial/open_default_stream.dox new file mode 100644 index 000000000..7512d1e7e --- /dev/null +++ b/3rdparty/portaudio/doc/src/tutorial/open_default_stream.dox @@ -0,0 +1,48 @@ +/** @page open_default_stream Opening a Stream Using Defaults +@ingroup tutorial + +The next step is to open a stream, which is similar to opening a file. You can specify whether you want audio input and/or output, how many channels, the data format, sample rate, etc. Opening a ''default'' stream means opening the default input and output devices, which saves you the trouble of getting a list of devices and choosing one from the list. (We'll see how to do that later.) +@code +#define SAMPLE_RATE (44100) +static paTestData data; + +..... + + PaStream *stream; + PaError err; + + /* Open an audio I/O stream. */ + err = Pa_OpenDefaultStream( &stream, + 0, /* no input channels */ + 2, /* stereo output */ + paFloat32, /* 32 bit floating point output */ + SAMPLE_RATE, + 256, /* frames per buffer, i.e. the number + of sample frames that PortAudio will + request from the callback. Many apps + may want to use + paFramesPerBufferUnspecified, which + tells PortAudio to pick the best, + possibly changing, buffer size.*/ + patestCallback, /* this is your callback function */ + &data ); /*This is a pointer that will be passed to + your callback*/ + if( err != paNoError ) goto error; +@endcode + +The data structure and callback are described in \ref writing_a_callback. + +The above example opens the stream for writing, which is sufficient for playback. It is also possible to open a stream for reading, to do recording, or both reading and writing, for simultaneous recording and playback or even real-time audio processing. If you plan to do playback and recording at the same time, open only one stream with valid input and output parameters. + +There are some caveats to note about simultaneous read/write: + + - Some platforms can only open a read/write stream using the same device. + - Although multiple streams can be opened, it is difficult to synchronize them. + - Some platforms don't support opening multiple streams on the same device. + - Using multiple streams may not be as well tested as other features. + - The PortAudio library calls must be made from the same thread or synchronized by the user. + + +Previous: \ref initializing_portaudio | Next: \ref start_stop_abort + +*/ \ No newline at end of file diff --git a/3rdparty/portaudio/doc/src/tutorial/querying_devices.dox b/3rdparty/portaudio/doc/src/tutorial/querying_devices.dox new file mode 100644 index 000000000..0c2327495 --- /dev/null +++ b/3rdparty/portaudio/doc/src/tutorial/querying_devices.dox @@ -0,0 +1,111 @@ +/** @page querying_devices Enumerating and Querying PortAudio Devices +@ingroup tutorial + +@section tut_query1 Querying Devices + +It is often fine to use the default device as we did previously in this tutorial, but there are times when you'll want to explicitly choose the device from a list of available devices on the system. To see a working example of this, check out pa_devs.c in the tests/ directory of the PortAudio source code. To do so, you'll need to first initialize PortAudio and Query for the number of Devices: + +@code + int numDevices; + + numDevices = Pa_GetDeviceCount(); + if( numDevices < 0 ) + { + printf( "ERROR: Pa_CountDevices returned 0x%x\n", numDevices ); + err = numDevices; + goto error; + } +@endcode + + +If you want to get information about each device, simply loop through as follows: + +@code + const PaDeviceInfo *deviceInfo; + + for( i=0; idefaultLowInputLatency ; + inputParameters.hostApiSpecificStreamInfo = NULL; //See you specific host's API docs for info on using this field + + + bzero( &outputParameters, sizeof( outputParameters ) ); //not necessary if you are filling in all the fields + outputParameters.channelCount = outChan; + outputParameters.device = outDevNum; + outputParameters.hostApiSpecificStreamInfo = NULL; + outputParameters.sampleFormat = paFloat32; + outputParameters.suggestedLatency = Pa_GetDeviceInfo(outDevNum)->defaultLowOutputLatency ; + outputParameters.hostApiSpecificStreamInfo = NULL; //See you specific host's API docs for info on using this field + + err = Pa_OpenStream( + &stream, + &inputParameters, + &outputParameters, + srate, + framesPerBuffer, + paNoFlag, //flags that can be used to define dither, clip settings and more + portAudioCallback, //your callback function + (void *)this ); //data to be passed to callback. In C++, it is frequently (void *)this + //don't forget to check errors! +@endcode + + +Previous: \ref utility_functions | Next: \ref blocking_read_write + +*/ \ No newline at end of file diff --git a/3rdparty/portaudio/doc/src/tutorial/start_stop_abort.dox b/3rdparty/portaudio/doc/src/tutorial/start_stop_abort.dox new file mode 100644 index 000000000..6d4f77752 --- /dev/null +++ b/3rdparty/portaudio/doc/src/tutorial/start_stop_abort.dox @@ -0,0 +1,35 @@ +/** @page start_stop_abort Starting, Stopping and Aborting a Stream +@ingroup tutorial + +@section tut_startstop1 Starting, Stopping and Aborting a Stream + +PortAudio will not start playing back audio until you start the stream. After calling Pa_StartStream(), PortAudio will start calling your callback function to perform the audio processing. + +@code + err = Pa_StartStream( stream ); + if( err != paNoError ) goto error; +@endcode + +You can communicate with your callback routine through the data structure you passed in on the open call, or through global variables, or using other interprocess communication techniques, but please be aware that your callback function may be called at interrupt time when your foreground process is least expecting it. So avoid sharing complex data structures that are easily corrupted like double linked lists, and avoid using locks such as mutexs as this may cause your callback function to block and therefore drop audio. Such techniques may even cause deadlock on some platforms. + +PortAudio will continue to call your callback and process audio until you stop the stream. This can be done in one of several ways, but, before we do so, we'll want to see that some of our audio gets processed by sleeping for a few seconds. This is easy to do with Pa_Sleep(), which is used by many of the examples in the patests/ directory for exactly this purpose. Note that, for a variety of reasons, you can not rely on this function for accurate scheduling, so your stream may not run for exactly the same amount of time as you expect, but it's good enough for our example. + +@code + /* Sleep for several seconds. */ + Pa_Sleep(NUM_SECONDS*1000); +@endcode + +Now we need to stop playback. There are several ways to do this, the simplest of which is to call Pa_StopStream(): + +@code + err = Pa_StopStream( stream ); + if( err != paNoError ) goto error; +@endcode + +Pa_StopStream() is designed to make sure that the buffers you've processed in your callback are all played, which may cause some delay. Alternatively, you could call Pa_AbortStream(). On some platforms, aborting the stream is much faster and may cause some data processed by your callback not to be played. + +Another way to stop the stream is to return either paComplete, or paAbort from your callback. paComplete ensures that the last buffer is played whereas paAbort stops the stream as soon as possible. If you stop the stream using this technique, you will need to call Pa_StopStream() before starting the stream again. + +Previous: \ref open_default_stream | Next: \ref terminating_portaudio + +*/ \ No newline at end of file diff --git a/3rdparty/portaudio/doc/src/tutorial/terminating_portaudio.dox b/3rdparty/portaudio/doc/src/tutorial/terminating_portaudio.dox new file mode 100644 index 000000000..67f74f6bc --- /dev/null +++ b/3rdparty/portaudio/doc/src/tutorial/terminating_portaudio.dox @@ -0,0 +1,20 @@ +/** @page terminating_portaudio Closing a Stream and Terminating PortAudio +@ingroup tutorial + +When you are done with a stream, you should close it to free up resources: + +@code + err = Pa_CloseStream( stream ); + if( err != paNoError ) goto error; +@endcode + +We've already mentioned this in \ref initializing_portaudio, but in case you forgot, be sure to terminate PortAudio when you are done: + +@code + err = Pa_Terminate( ); + if( err != paNoError ) goto error; +@endcode + +Previous: \ref start_stop_abort | Next: \ref utility_functions + +*/ \ No newline at end of file diff --git a/3rdparty/portaudio/doc/src/tutorial/tutorial_start.dox b/3rdparty/portaudio/doc/src/tutorial/tutorial_start.dox new file mode 100644 index 000000000..b80bc236e --- /dev/null +++ b/3rdparty/portaudio/doc/src/tutorial/tutorial_start.dox @@ -0,0 +1,56 @@ +/** @page tutorial_start PortAudio Tutorials +@ingroup tutorial + +These tutorials takes you through a hands-on example of using PortAudio to make sound. If you'd prefer to start with a top-down overview of the PortAudio API, check out the @ref api_overview. + +@section tut_start1 Downloading + +First thing you need to do is download the PortAudio source code either as a tarball from the website, or from the Subversion Repository. + +@section tut_start2 Compiling + +Once you've downloaded PortAudio you'll need to compile it, which of course, depends on your environment: + + - Windows + - \ref compile_windows + - \ref compile_windows_mingw + - \ref compile_windows_asio_msvc + - \ref compile_cmake + - Mac OS X + - \ref compile_mac_coreaudio + - POSIX + - \ref compile_linux + +Many platforms with GCC/make can use the simple ./configure && make combination and simply use the resulting libraries in their code. + +@section tut_start3 Programming with PortAudio + +Below are the steps to writing a PortAudio application: + + - Write a callback function that will be called by PortAudio when audio processing is needed. + - Initialize the PA library and open a stream for audio I/O. + - Start the stream. Your callback function will be now be called repeatedly by PA in the background. + - In your callback you can read audio data from the inputBuffer and/or write data to the outputBuffer. + - Stop the stream by returning 1 from your callback, or by calling a stop function. + - Close the stream and terminate the library. + +In addition to this "Callback" architecture, V19 also supports a "Blocking I/O" model which uses read and write calls which may be more familiar to non-audio programmers. Note that at this time, not all APIs support this functionality. + +In this tutorial, we'll show how to use the callback architecture to play a sawtooth wave. Much of the tutorial is taken from the file paex_saw.c, which is part of the PortAudio distribution. When you're done with this tutorial, you'll be armed with the basic knowledge you need to write an audio program. If you need more sample code, look in the "examples" and "test" directory of the PortAudio distribution. Another great source of info is the portaudio.h Doxygen page, which documents the entire V19 API. Also see the page for tips on programming PortAudio on the PortAudio wiki. + +If you are upgrading from V18, you may want to look at the Proposed Enhancements to PortAudio, which describes the differences between V18 and V19. + +- \ref writing_a_callback +- \ref initializing_portaudio +- \ref open_default_stream +- \ref start_stop_abort +- \ref terminating_portaudio +- \ref utility_functions +- \ref querying_devices +- \ref blocking_read_write + +Once you have a basic understanding of how to use PortAudio, you might be interested in \ref exploring. + +Next: \ref writing_a_callback + +*/ \ No newline at end of file diff --git a/3rdparty/portaudio/doc/src/tutorial/utility_functions.dox b/3rdparty/portaudio/doc/src/tutorial/utility_functions.dox new file mode 100644 index 000000000..c06bf3bca --- /dev/null +++ b/3rdparty/portaudio/doc/src/tutorial/utility_functions.dox @@ -0,0 +1,69 @@ +/** @page utility_functions Utility Functions +@ingroup tutorial + +In addition to the functions described elsewhere in this tutorial, PortAudio provides a number of Utility functions that are useful in a variety of circumstances. +You'll want to read the portaudio.h reference, which documents the entire V19 API for details, but we'll try to cover the basics here. + +@section tut_util2 Version Information + +PortAudio offers two functions to determine the PortAudio Version. This is most useful when you are using PortAudio as a dynamic library, but it may also be useful at other times. + +@code +int Pa_GetVersion (void) +const char * Pa_GetVersionText (void) +@endcode + +@section tut_util3 Error Text + +PortAudio allows you to get error text from an error number. + +@code +const char * Pa_GetErrorText (PaError errorCode) +@endcode + +@section tut_util4 Stream State + +PortAudio Streams exist in 3 states: Active, Stopped, and Callback Stopped. If a stream is in callback stopped state, you'll need to stop it before you can start it again. If you need to query the state of a PortAudio stream, there are two functions for doing so: + +@code +PaError Pa_IsStreamStopped (PaStream *stream) +PaError Pa_IsStreamActive (PaStream *stream) +@endcode + +@section tut_util5 Stream Info + +If you need to retrieve info about a given stream, such as latency, and sample rate info, there's a function for that too: + +@code +const PaStreamInfo * Pa_GetStreamInfo (PaStream *stream) +@endcode + +@section tut_util6 Stream Time + +If you need to synchronise other activities such as display updates or MIDI output with the PortAudio callback you need to know the current time according to the same timebase used by the stream callback timestamps. + +@code +PaTime Pa_GetStreamTime (PaStream *stream) +@endcode + +@section tut_util6CPU Usage + +To determine how much CPU is being used by the callback, use these: + +@code +double Pa_GetStreamCpuLoad (PaStream *stream) +@endcode + +@section tut_util7 Other utilities + +These functions allow you to determine the size of a sample from its format and sleep for a given amount of time. The sleep function should not be used for precise timing or synchronization because it makes few guarantees about the exact length of time it waits. It is most useful for testing. + +@code +PaError Pa_GetSampleSize (PaSampleFormat format) +void Pa_Sleep (long msec) +@endcode + + +Previous: \ref terminating_portaudio | Next: \ref querying_devices + +*/ \ No newline at end of file diff --git a/3rdparty/portaudio/doc/src/tutorial/writing_a_callback.dox b/3rdparty/portaudio/doc/src/tutorial/writing_a_callback.dox new file mode 100644 index 000000000..f0a43ccd0 --- /dev/null +++ b/3rdparty/portaudio/doc/src/tutorial/writing_a_callback.dox @@ -0,0 +1,66 @@ +/** @page writing_a_callback Writing a Callback Function +@ingroup tutorial + +To write a program using PortAudio, you must include the "portaudio.h" include file. You may wish to read "portaudio.h" because it contains a complete description of the PortAudio functions and constants. Alternatively, you could browse the [http://www.portaudio.com/docs/v19-doxydocs/portaudio_8h.html "portaudio.h" Doxygen page] +@code +#include "portaudio.h" +@endcode +The next task is to write your own "callback" function. The "callback" is a function that is called by the PortAudio engine whenever it has captured audio data, or when it needs more audio data for output. + +Before we begin, it's important to realize that the callback is a delicate place. This is because some systems perform the callback in a special thread, or interrupt handler, and it is rarely treated the same as the rest of your code. In addition, if you want your audio to reach the speakers on time, you'll need to make sure whatever code you run in the callback runs quickly. What is safe or not safe will vary from platform to platform, but as a rule of thumb, don't do anything like allocating or freeing memory, reading or writing files, printf(), or anything else that might take an unbounded amount of time or rely on the OS or require a context switch. Ed: is this still true?: Also do not call any PortAudio functions in the callback except for Pa_StreamTime() and Pa_GetCPULoad(). + +Your callback function must return an int and accept the exact parameters specified in this typedef: + +@code +typedef int PaStreamCallback( const void *input, + void *output, + unsigned long frameCount, + const PaStreamCallbackTimeInfo* timeInfo, + PaStreamCallbackFlags statusFlags, + void *userData ) ; +@endcode +Here is an example callback function from the test file "patests/patest_saw.c". It calculates a simple left and right sawtooth signal and writes it to the output buffer. Notice that in this example, the signals are of float data type. The signals must be between -1.0 and +1.0. You can also use 16 bit integers or other formats which are specified during setup, but floats are easiest to work with. You can pass a pointer to your data structure through PortAudio which will appear as userData. + +@code +typedef struct +{ + float left_phase; + float right_phase; +} +paTestData; + +/* This routine will be called by the PortAudio engine when audio is needed. +** It may called at interrupt level on some machines so don't do anything +** that could mess up the system like calling malloc() or free(). +*/ +static int patestCallback( const void *inputBuffer, void *outputBuffer, + unsigned long framesPerBuffer, + const PaStreamCallbackTimeInfo* timeInfo, + PaStreamCallbackFlags statusFlags, + void *userData ) +{ + /* Cast data passed through stream to our structure. */ + paTestData *data = (paTestData*)userData; + float *out = (float*)outputBuffer; + unsigned int i; + (void) inputBuffer; /* Prevent unused variable warning. */ + + for( i=0; ileft_phase; /* left */ + *out++ = data->right_phase; /* right */ + /* Generate simple sawtooth phaser that ranges between -1.0 and 1.0. */ + data->left_phase += 0.01f; + /* When signal reaches top, drop back down. */ + if( data->left_phase >= 1.0f ) data->left_phase -= 2.0f; + /* higher pitch so we can distinguish left and right. */ + data->right_phase += 0.03f; + if( data->right_phase >= 1.0f ) data->right_phase -= 2.0f; + } + return 0; +} +@endcode + +Previous: \ref tutorial_start | Next: \ref initializing_portaudio + +*/ \ No newline at end of file diff --git a/3rdparty/portaudio/include/pa_mac_core.h b/3rdparty/portaudio/include/pa_mac_core.h index f7a90f08f..1d615feed 100644 --- a/3rdparty/portaudio/include/pa_mac_core.h +++ b/3rdparty/portaudio/include/pa_mac_core.h @@ -124,6 +124,19 @@ AudioDeviceID PaMacCore_GetStreamOutputDevice( PaStream* s ); */ const char *PaMacCore_GetChannelName( int device, int channelIndex, bool input ); + +/** Retrieve the range of legal native buffer sizes for the specificed device, in sample frames. + + @param device The global index of the PortAudio device about which the query is being made. + @param minBufferSizeFrames A pointer to the location which will receive the minimum buffer size value. + @param maxBufferSizeFrames A pointer to the location which will receive the maximum buffer size value. + + @see kAudioDevicePropertyBufferFrameSizeRange in the CoreAudio SDK. + */ +PaError PaMacCore_GetBufferSizeRange( PaDeviceIndex device, + long *minBufferSizeFrames, long *maxBufferSizeFrames ); + + /** * Flags */ diff --git a/3rdparty/portaudio/include/pa_win_wdmks.h b/3rdparty/portaudio/include/pa_win_wdmks.h new file mode 100644 index 000000000..9fe9284bd --- /dev/null +++ b/3rdparty/portaudio/include/pa_win_wdmks.h @@ -0,0 +1,106 @@ +#ifndef PA_WIN_WDMKS_H +#define PA_WIN_WDMKS_H +/* + * $Id: pa_win_wdmks.h 1812 2012-02-14 09:32:57Z robiwan $ + * PortAudio Portable Real-Time Audio Library + * WDM/KS specific extensions + * + * Copyright (c) 1999-2007 Ross Bencina and Phil Burk + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * The text above constitutes the entire PortAudio license; however, + * the PortAudio community also makes the following non-binding requests: + * + * Any person wishing to distribute modifications to the Software is + * requested to send the modifications to the original developer so that + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the + * license above. + */ + +/** @file + @ingroup public_header + @brief WDM Kernel Streaming-specific PortAudio API extension header file. +*/ + + +#include "portaudio.h" + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + typedef struct PaWinWDMKSInfo{ + unsigned long size; /**< sizeof(PaWinWDMKSInfo) */ + PaHostApiTypeId hostApiType; /**< paWDMKS */ + unsigned long version; /**< 1 */ + + /* The number of packets to use for WaveCyclic devices, range is [2, 8]. Set to zero for default value of 2. */ + unsigned noOfPackets; + } PaWinWDMKSInfo; + + typedef enum PaWDMKSType + { + Type_kNotUsed, + Type_kWaveCyclic, + Type_kWaveRT, + Type_kCnt, + } PaWDMKSType; + + typedef enum PaWDMKSSubType + { + SubType_kUnknown, + SubType_kNotification, + SubType_kPolled, + SubType_kCnt, + } PaWDMKSSubType; + + typedef struct PaWinWDMKSDeviceInfo { + wchar_t filterPath[MAX_PATH]; /**< KS filter path in Unicode! */ + wchar_t topologyPath[MAX_PATH]; /**< Topology filter path in Unicode! */ + PaWDMKSType streamingType; + GUID deviceProductGuid; /**< The product GUID of the device (if supported) */ + } PaWinWDMKSDeviceInfo; + + typedef struct PaWDMKSDirectionSpecificStreamInfo + { + PaDeviceIndex device; + unsigned channels; /**< No of channels the device is opened with */ + unsigned framesPerHostBuffer; /**< No of frames of the device buffer */ + int endpointPinId; /**< Endpoint pin ID (on topology filter if topologyName is not empty) */ + int muxNodeId; /**< Only valid for input */ + PaWDMKSSubType streamingSubType; /**< Not known until device is opened for streaming */ + } PaWDMKSDirectionSpecificStreamInfo; + + typedef struct PaWDMKSSpecificStreamInfo { + PaWDMKSDirectionSpecificStreamInfo input; + PaWDMKSDirectionSpecificStreamInfo output; + } PaWDMKSSpecificStreamInfo; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* PA_WIN_DS_H */ diff --git a/3rdparty/portaudio/src/SConscript b/3rdparty/portaudio/src/SConscript index 5cc915216..84ab1338b 100644 --- a/3rdparty/portaudio/src/SConscript +++ b/3rdparty/portaudio/src/SConscript @@ -1,220 +1,220 @@ -import os.path, copy, sys - -def checkSymbol(conf, header, library=None, symbol=None, autoAdd=True, critical=False, pkgName=None): - """ Check for symbol in library, optionally look only for header. - @param conf: Configure instance. - @param header: The header file where the symbol is declared. - @param library: The library in which the symbol exists, if None it is taken to be the standard C library. - @param symbol: The symbol to look for, if None only the header will be looked up. - @param autoAdd: Automatically link with this library if check is positive. - @param critical: Raise on error? - @param pkgName: Optional name of pkg-config entry for library, to determine build parameters. - @return: True/False - """ - origEnv = conf.env.Copy() # Copy unmodified environment so we can restore it upon error - env = conf.env - if library is None: - library = "c" # Standard library - autoAdd = False - - if pkgName is not None: - origLibs = copy.copy(env.get("LIBS", None)) - - try: env.ParseConfig("pkg-config --silence-errors %s --cflags --libs" % pkgName) - except: pass - else: - # I see no other way of checking that the parsing succeeded, if it did add no more linking parameters - if env.get("LIBS", None) != origLibs: - autoAdd = False - - try: - if not conf.CheckCHeader(header, include_quotes="<>"): - raise ConfigurationError("missing header %s" % header) - if symbol is not None and not conf.CheckLib(library, symbol, language="C", autoadd=autoAdd): - raise ConfigurationError("missing symbol %s in library %s" % (symbol, library)) - except ConfigurationError: - conf.env = origEnv - if not critical: - return False - raise - - return True - -import SCons.Errors - -# Import common variables - -# Could use '#' to refer to top-level SConstruct directory, but looks like env.SConsignFile doesn't interpret this at least :( -sconsDir = os.path.abspath(os.path.join("build", "scons")) - -try: - Import("Platform", "Posix", "ConfigurationError", "ApiVer") -except SCons.Errors.UserError: - # The common objects must be exported first - SConscript(os.path.join(sconsDir, "SConscript_common")) - Import("Platform", "Posix", "ConfigurationError", "ApiVer") - -Import("env") - -# This will be manipulated -env = env.Copy() - -# We operate with a set of needed libraries and optional libraries, the latter stemming from host API implementations. -# For libraries of both types we record a set of values that is used to look for the library in question, during -# configuration. If the corresponding library for a host API implementation isn't found, the implementation is left out. -neededLibs = [] -optionalImpls = {} -if Platform in Posix: - env.Append(CPPPATH=os.path.join("os", "unix")) - neededLibs += [("pthread", "pthread.h", "pthread_create"), ("m", "math.h", "sin")] - if env["useALSA"]: - optionalImpls["ALSA"] = ("asound", "alsa/asoundlib.h", "snd_pcm_open") - if env["useJACK"]: - optionalImpls["JACK"] = ("jack", "jack/jack.h", "jack_client_new") - if env["useOSS"]: - # TODO: It looks like the prefix for soundcard.h depends on the platform - optionalImpls["OSS"] = ("oss", "sys/soundcard.h", None) - if Platform == 'netbsd': - optionalImpls["OSS"] = ("ossaudio", "sys/soundcard.h", "_oss_ioctl") - if env["useASIHPI"]: - optionalImpls["ASIHPI"] = ("hpi", "asihpi/hpi.h", "HPI_SubSysCreate") - if env["useCOREAUDIO"]: - optionalImpls["COREAUDIO"] = ("CoreAudio", "CoreAudio/CoreAudio.h", None) -else: - raise ConfigurationError("unknown platform %s" % Platform) - -if Platform == "darwin": - env.Append(LINKFLAGS="-framework CoreFoundation -framework CoreServices -framework CoreAudio -framework AudioToolBox -framework AudioUnit") -elif Platform == "cygwin": - env.Append(LIBS=["winmm"]) -elif Platform == "irix": - neededLibs += [("audio", "dmedia/audio.h", "alOpenPort"), ("dmedia", "dmedia/dmedia.h", "dmGetUST")] - env.Append(CPPDEFINES=["PA_USE_SGI"]) - -def CheckCTypeSize(context, tp): - """ Check size of C type. - @param context: A configuration context. - @param tp: The type to check. - @return: Size of type, in bytes. - """ - context.Message("Checking the size of C type %s..." % tp) - ret = context.TryRun(""" -#include - -int main() { - printf("%%d", sizeof(%s)); - return 0; -} -""" % tp, ".c") - if not ret[0]: - context.Result(" Couldn't obtain size of type %s!" % tp) - return None - - assert ret[1] - sz = int(ret[1]) - context.Result("%d" % sz) - return sz - -""" -if sys.byteorder == "little": - env.Append(CPPDEFINES=["PA_LITTLE_ENDIAN"]) -elif sys.byteorder == "big": - env.Append(CPPDEFINES=["PA_BIG_ENDIAN"]) -else: - raise ConfigurationError("unknown byte order: %s" % sys.byteorder) -""" -if env["enableDebugOutput"]: - env.Append(CPPDEFINES=["PA_ENABLE_DEBUG_OUTPUT"]) - -# Start configuration - -# Use an absolute path for conf_dir, otherwise it gets created both relative to current directory and build directory -conf = env.Configure(log_file=os.path.join(sconsDir, "sconf.log"), custom_tests={"CheckCTypeSize": CheckCTypeSize}, - conf_dir=os.path.join(sconsDir, ".sconf_temp")) -conf.env.Append(CPPDEFINES=["SIZEOF_SHORT=%d" % conf.CheckCTypeSize("short")]) -conf.env.Append(CPPDEFINES=["SIZEOF_INT=%d" % conf.CheckCTypeSize("int")]) -conf.env.Append(CPPDEFINES=["SIZEOF_LONG=%d" % conf.CheckCTypeSize("long")]) -if checkSymbol(conf, "time.h", "rt", "clock_gettime"): - conf.env.Append(CPPDEFINES=["HAVE_CLOCK_GETTIME"]) -if checkSymbol(conf, "time.h", symbol="nanosleep"): - conf.env.Append(CPPDEFINES=["HAVE_NANOSLEEP"]) -if conf.CheckCHeader("sys/soundcard.h"): - conf.env.Append(CPPDEFINES=["HAVE_SYS_SOUNDCARD_H"]) -if conf.CheckCHeader("linux/soundcard.h"): - conf.env.Append(CPPDEFINES=["HAVE_LINUX_SOUNDCARD_H"]) -if conf.CheckCHeader("machine/soundcard.h"): - conf.env.Append(CPPDEFINES=["HAVE_MACHINE_SOUNDCARD_H"]) - -# Look for needed libraries and link with them -for lib, hdr, sym in neededLibs: - checkSymbol(conf, hdr, lib, sym, critical=True) -# Look for host API libraries, if a library isn't found disable corresponding host API implementation. -for name, val in optionalImpls.items(): - lib, hdr, sym = val - if checkSymbol(conf, hdr, lib, sym, critical=False, pkgName=name.lower()): - conf.env.Append(CPPDEFINES=["PA_USE_%s=1" % name.upper()]) - else: - del optionalImpls[name] - -# Configuration finished -env = conf.Finish() - -# PA infrastructure -CommonSources = [os.path.join("common", f) for f in "pa_allocation.c pa_converters.c pa_cpuload.c pa_dither.c pa_front.c \ - pa_process.c pa_stream.c pa_trace.c pa_debugprint.c pa_ringbuffer.c".split()] -CommonSources.append(os.path.join("hostapi", "skeleton", "pa_hostapi_skeleton.c")) - -# Host APIs implementations -ImplSources = [] -if Platform in Posix: - ImplSources += [os.path.join("os", "unix", f) for f in "pa_unix_hostapis.c pa_unix_util.c".split()] - -if "ALSA" in optionalImpls: - ImplSources.append(os.path.join("hostapi", "alsa", "pa_linux_alsa.c")) -if "JACK" in optionalImpls: - ImplSources.append(os.path.join("hostapi", "jack", "pa_jack.c")) -if "OSS" in optionalImpls: - ImplSources.append(os.path.join("hostapi", "oss", "pa_unix_oss.c")) -if "ASIHPI" in optionalImpls: - ImplSources.append(os.path.join("hostapi", "asihpi", "pa_linux_asihpi.c")) -if "COREAUDIO" in optionalImpls: - ImplSources.append([os.path.join("hostapi", "coreaudio", f) for f in """ - pa_mac_core.c pa_mac_core_blocking.c pa_mac_core_utilities.c - """.split()]) - - -sources = CommonSources + ImplSources - -sharedLibEnv = env.Copy() -if Platform in Posix: - # Add soname to library, this is so a reference is made to the versioned library in programs linking against libportaudio.so - if Platform != 'darwin': - sharedLibEnv.AppendUnique(SHLINKFLAGS="-Wl,-soname=libportaudio.so.%d" % int(ApiVer.split(".")[0])) -sharedLib = sharedLibEnv.SharedLibrary(target="portaudio", source=sources) - -staticLib = env.StaticLibrary(target="portaudio", source=sources) - -if Platform in Posix: - prefix = env["prefix"] - includeDir = os.path.join(prefix, "include") - libDir = os.path.join(prefix, "lib") - -testNames = ["patest_sine", "paqa_devs", "paqa_errs", "patest1", "patest_buffer", "patest_callbackstop", "patest_clip", \ - "patest_dither", "patest_hang", "patest_in_overflow", "patest_latency", "patest_leftright", "patest_longsine", \ - "patest_many", "patest_maxsines", "patest_multi_sine", "patest_out_underflow", "patest_pink", "patest_prime", \ - "patest_read_record", "patest_record", "patest_ringmix", "patest_saw", "patest_sine8", "patest_sine", \ - "patest_sine_time", "patest_start_stop", "patest_stop", "patest_sync", "patest_toomanysines", \ - "patest_underflow", "patest_wire", "patest_write_sine", "pa_devs", "pa_fuzz", "pa_minlat", \ - "patest_sine_channelmaps",] - -# The test directory ("bin") should be in the top-level PA directory -tests = [env.Program(target=os.path.join("#", "bin", name), source=[os.path.join("#", "test", name + ".c"), - staticLib]) for name in testNames] - -# Detect host APIs -hostApis = [] -for cppdef in env["CPPDEFINES"]: - if cppdef.startswith("PA_USE_"): - hostApis.append(cppdef[7:-2]) - -Return("sources", "sharedLib", "staticLib", "tests", "env", "hostApis") +import os.path, copy, sys + +def checkSymbol(conf, header, library=None, symbol=None, autoAdd=True, critical=False, pkgName=None): + """ Check for symbol in library, optionally look only for header. + @param conf: Configure instance. + @param header: The header file where the symbol is declared. + @param library: The library in which the symbol exists, if None it is taken to be the standard C library. + @param symbol: The symbol to look for, if None only the header will be looked up. + @param autoAdd: Automatically link with this library if check is positive. + @param critical: Raise on error? + @param pkgName: Optional name of pkg-config entry for library, to determine build parameters. + @return: True/False + """ + origEnv = conf.env.Copy() # Copy unmodified environment so we can restore it upon error + env = conf.env + if library is None: + library = "c" # Standard library + autoAdd = False + + if pkgName is not None: + origLibs = copy.copy(env.get("LIBS", None)) + + try: env.ParseConfig("pkg-config --silence-errors %s --cflags --libs" % pkgName) + except: pass + else: + # I see no other way of checking that the parsing succeeded, if it did add no more linking parameters + if env.get("LIBS", None) != origLibs: + autoAdd = False + + try: + if not conf.CheckCHeader(header, include_quotes="<>"): + raise ConfigurationError("missing header %s" % header) + if symbol is not None and not conf.CheckLib(library, symbol, language="C", autoadd=autoAdd): + raise ConfigurationError("missing symbol %s in library %s" % (symbol, library)) + except ConfigurationError: + conf.env = origEnv + if not critical: + return False + raise + + return True + +import SCons.Errors + +# Import common variables + +# Could use '#' to refer to top-level SConstruct directory, but looks like env.SConsignFile doesn't interpret this at least :( +sconsDir = os.path.abspath(os.path.join("build", "scons")) + +try: + Import("Platform", "Posix", "ConfigurationError", "ApiVer") +except SCons.Errors.UserError: + # The common objects must be exported first + SConscript(os.path.join(sconsDir, "SConscript_common")) + Import("Platform", "Posix", "ConfigurationError", "ApiVer") + +Import("env") + +# This will be manipulated +env = env.Copy() + +# We operate with a set of needed libraries and optional libraries, the latter stemming from host API implementations. +# For libraries of both types we record a set of values that is used to look for the library in question, during +# configuration. If the corresponding library for a host API implementation isn't found, the implementation is left out. +neededLibs = [] +optionalImpls = {} +if Platform in Posix: + env.Append(CPPPATH=os.path.join("os", "unix")) + neededLibs += [("pthread", "pthread.h", "pthread_create"), ("m", "math.h", "sin")] + if env["useALSA"]: + optionalImpls["ALSA"] = ("asound", "alsa/asoundlib.h", "snd_pcm_open") + if env["useJACK"]: + optionalImpls["JACK"] = ("jack", "jack/jack.h", "jack_client_new") + if env["useOSS"]: + # TODO: It looks like the prefix for soundcard.h depends on the platform + optionalImpls["OSS"] = ("oss", "sys/soundcard.h", None) + if Platform == 'netbsd': + optionalImpls["OSS"] = ("ossaudio", "sys/soundcard.h", "_oss_ioctl") + if env["useASIHPI"]: + optionalImpls["ASIHPI"] = ("hpi", "asihpi/hpi.h", "HPI_SubSysCreate") + if env["useCOREAUDIO"]: + optionalImpls["COREAUDIO"] = ("CoreAudio", "CoreAudio/CoreAudio.h", None) +else: + raise ConfigurationError("unknown platform %s" % Platform) + +if Platform == "darwin": + env.Append(LINKFLAGS="-framework CoreFoundation -framework CoreServices -framework CoreAudio -framework AudioToolBox -framework AudioUnit") +elif Platform == "cygwin": + env.Append(LIBS=["winmm"]) +elif Platform == "irix": + neededLibs += [("audio", "dmedia/audio.h", "alOpenPort"), ("dmedia", "dmedia/dmedia.h", "dmGetUST")] + env.Append(CPPDEFINES=["PA_USE_SGI"]) + +def CheckCTypeSize(context, tp): + """ Check size of C type. + @param context: A configuration context. + @param tp: The type to check. + @return: Size of type, in bytes. + """ + context.Message("Checking the size of C type %s..." % tp) + ret = context.TryRun(""" +#include + +int main() { + printf("%%d", sizeof(%s)); + return 0; +} +""" % tp, ".c") + if not ret[0]: + context.Result(" Couldn't obtain size of type %s!" % tp) + return None + + assert ret[1] + sz = int(ret[1]) + context.Result("%d" % sz) + return sz + +""" +if sys.byteorder == "little": + env.Append(CPPDEFINES=["PA_LITTLE_ENDIAN"]) +elif sys.byteorder == "big": + env.Append(CPPDEFINES=["PA_BIG_ENDIAN"]) +else: + raise ConfigurationError("unknown byte order: %s" % sys.byteorder) +""" +if env["enableDebugOutput"]: + env.Append(CPPDEFINES=["PA_ENABLE_DEBUG_OUTPUT"]) + +# Start configuration + +# Use an absolute path for conf_dir, otherwise it gets created both relative to current directory and build directory +conf = env.Configure(log_file=os.path.join(sconsDir, "sconf.log"), custom_tests={"CheckCTypeSize": CheckCTypeSize}, + conf_dir=os.path.join(sconsDir, ".sconf_temp")) +conf.env.Append(CPPDEFINES=["SIZEOF_SHORT=%d" % conf.CheckCTypeSize("short")]) +conf.env.Append(CPPDEFINES=["SIZEOF_INT=%d" % conf.CheckCTypeSize("int")]) +conf.env.Append(CPPDEFINES=["SIZEOF_LONG=%d" % conf.CheckCTypeSize("long")]) +if checkSymbol(conf, "time.h", "rt", "clock_gettime"): + conf.env.Append(CPPDEFINES=["HAVE_CLOCK_GETTIME"]) +if checkSymbol(conf, "time.h", symbol="nanosleep"): + conf.env.Append(CPPDEFINES=["HAVE_NANOSLEEP"]) +if conf.CheckCHeader("sys/soundcard.h"): + conf.env.Append(CPPDEFINES=["HAVE_SYS_SOUNDCARD_H"]) +if conf.CheckCHeader("linux/soundcard.h"): + conf.env.Append(CPPDEFINES=["HAVE_LINUX_SOUNDCARD_H"]) +if conf.CheckCHeader("machine/soundcard.h"): + conf.env.Append(CPPDEFINES=["HAVE_MACHINE_SOUNDCARD_H"]) + +# Look for needed libraries and link with them +for lib, hdr, sym in neededLibs: + checkSymbol(conf, hdr, lib, sym, critical=True) +# Look for host API libraries, if a library isn't found disable corresponding host API implementation. +for name, val in optionalImpls.items(): + lib, hdr, sym = val + if checkSymbol(conf, hdr, lib, sym, critical=False, pkgName=name.lower()): + conf.env.Append(CPPDEFINES=["PA_USE_%s=1" % name.upper()]) + else: + del optionalImpls[name] + +# Configuration finished +env = conf.Finish() + +# PA infrastructure +CommonSources = [os.path.join("common", f) for f in "pa_allocation.c pa_converters.c pa_cpuload.c pa_dither.c pa_front.c \ + pa_process.c pa_stream.c pa_trace.c pa_debugprint.c pa_ringbuffer.c".split()] +CommonSources.append(os.path.join("hostapi", "skeleton", "pa_hostapi_skeleton.c")) + +# Host APIs implementations +ImplSources = [] +if Platform in Posix: + ImplSources += [os.path.join("os", "unix", f) for f in "pa_unix_hostapis.c pa_unix_util.c".split()] + +if "ALSA" in optionalImpls: + ImplSources.append(os.path.join("hostapi", "alsa", "pa_linux_alsa.c")) +if "JACK" in optionalImpls: + ImplSources.append(os.path.join("hostapi", "jack", "pa_jack.c")) +if "OSS" in optionalImpls: + ImplSources.append(os.path.join("hostapi", "oss", "pa_unix_oss.c")) +if "ASIHPI" in optionalImpls: + ImplSources.append(os.path.join("hostapi", "asihpi", "pa_linux_asihpi.c")) +if "COREAUDIO" in optionalImpls: + ImplSources.append([os.path.join("hostapi", "coreaudio", f) for f in """ + pa_mac_core.c pa_mac_core_blocking.c pa_mac_core_utilities.c + """.split()]) + + +sources = CommonSources + ImplSources + +sharedLibEnv = env.Copy() +if Platform in Posix: + # Add soname to library, this is so a reference is made to the versioned library in programs linking against libportaudio.so + if Platform != 'darwin': + sharedLibEnv.AppendUnique(SHLINKFLAGS="-Wl,-soname=libportaudio.so.%d" % int(ApiVer.split(".")[0])) +sharedLib = sharedLibEnv.SharedLibrary(target="portaudio", source=sources) + +staticLib = env.StaticLibrary(target="portaudio", source=sources) + +if Platform in Posix: + prefix = env["prefix"] + includeDir = os.path.join(prefix, "include") + libDir = os.path.join(prefix, "lib") + +testNames = ["patest_sine", "paqa_devs", "paqa_errs", "patest1", "patest_buffer", "patest_callbackstop", "patest_clip", \ + "patest_dither", "patest_hang", "patest_in_overflow", "patest_latency", "patest_leftright", "patest_longsine", \ + "patest_many", "patest_maxsines", "patest_multi_sine", "patest_out_underflow", "patest_pink", "patest_prime", \ + "patest_read_record", "patest_record", "patest_ringmix", "patest_saw", "patest_sine8", "patest_sine", \ + "patest_sine_time", "patest_start_stop", "patest_stop", "patest_sync", "patest_toomanysines", \ + "patest_underflow", "patest_wire", "patest_write_sine", "pa_devs", "pa_fuzz", "pa_minlat", \ + "patest_sine_channelmaps",] + +# The test directory ("bin") should be in the top-level PA directory +tests = [env.Program(target=os.path.join("#", "bin", name), source=[os.path.join("#", "test", name + ".c"), + staticLib]) for name in testNames] + +# Detect host APIs +hostApis = [] +for cppdef in env["CPPDEFINES"]: + if cppdef.startswith("PA_USE_"): + hostApis.append(cppdef[7:-2]) + +Return("sources", "sharedLib", "staticLib", "tests", "env", "hostApis") diff --git a/3rdparty/portaudio/src/common/pa_trace.c b/3rdparty/portaudio/src/common/pa_trace.c index 24305003f..bf1ad443e 100644 --- a/3rdparty/portaudio/src/common/pa_trace.c +++ b/3rdparty/portaudio/src/common/pa_trace.c @@ -1,5 +1,5 @@ /* - * $Id: pa_trace.c 1339 2008-02-15 07:50:33Z rossb $ + * $Id: pa_trace.c 1812 2012-02-14 09:32:57Z robiwan $ * Portable Audio I/O Library Trace Facility * Store trace information in real-time for later printing. * @@ -46,12 +46,16 @@ #include #include +#include #include +#include #include "pa_trace.h" +#include "pa_util.h" +#include "pa_debugprint.h" #if PA_TRACE_REALTIME_EVENTS -static char *traceTextArray[PA_MAX_TRACE_RECORDS]; +static char const *traceTextArray[PA_MAX_TRACE_RECORDS]; static int traceIntArray[PA_MAX_TRACE_RECORDS]; static int traceIndex = 0; static int traceBlock = 0; @@ -94,4 +98,133 @@ void PaUtil_AddTraceMessage( const char *msg, int data ) } } +/************************************************************************/ +/* High performance log alternative */ +/************************************************************************/ + +typedef unsigned long long PaUint64; + +typedef struct __PaHighPerformanceLog +{ + unsigned magik; + int writePtr; + int readPtr; + int size; + double refTime; + char* data; +} PaHighPerformanceLog; + +static const unsigned kMagik = 0xcafebabe; + +#define USEC_PER_SEC (1000000ULL) + +int PaUtil_InitializeHighSpeedLog( LogHandle* phLog, unsigned maxSizeInBytes ) +{ + PaHighPerformanceLog* pLog = (PaHighPerformanceLog*)PaUtil_AllocateMemory(sizeof(PaHighPerformanceLog)); + if (pLog == 0) + { + return paInsufficientMemory; + } + assert(phLog != 0); + *phLog = pLog; + + pLog->data = (char*)PaUtil_AllocateMemory(maxSizeInBytes); + if (pLog->data == 0) + { + PaUtil_FreeMemory(pLog); + return paInsufficientMemory; + } + pLog->magik = kMagik; + pLog->size = maxSizeInBytes; + pLog->refTime = PaUtil_GetTime(); + return paNoError; +} + +void PaUtil_ResetHighSpeedLogTimeRef( LogHandle hLog ) +{ + PaHighPerformanceLog* pLog = (PaHighPerformanceLog*)hLog; + assert(pLog->magik == kMagik); + pLog->refTime = PaUtil_GetTime(); +} + +typedef struct __PaLogEntryHeader +{ + int size; + double timeStamp; +} PaLogEntryHeader; + +#ifdef __APPLE__ +#define _vsnprintf vsnprintf +#define min(a,b) ((a)<(b)?(a):(b)) +#endif + + +int PaUtil_AddHighSpeedLogMessage( LogHandle hLog, const char* fmt, ... ) +{ + va_list l; + int n = 0; + PaHighPerformanceLog* pLog = (PaHighPerformanceLog*)hLog; + if (pLog != 0) + { + PaLogEntryHeader* pHeader; + char* p; + int maxN; + assert(pLog->magik == kMagik); + pHeader = (PaLogEntryHeader*)( pLog->data + pLog->writePtr ); + p = (char*)( pHeader + 1 ); + maxN = pLog->size - pLog->writePtr - 2 * sizeof(PaLogEntryHeader); + + pHeader->timeStamp = PaUtil_GetTime() - pLog->refTime; + if (maxN > 0) + { + if (maxN > 32) + { + va_start(l, fmt); + n = _vsnprintf(p, min(1024, maxN), fmt, l); + va_end(l); + } + else { + n = sprintf(p, "End of log..."); + } + n = ((n + sizeof(unsigned)) & ~(sizeof(unsigned)-1)) + sizeof(PaLogEntryHeader); + pHeader->size = n; +#if 0 + PaUtil_DebugPrint("%05u.%03u: %s\n", pHeader->timeStamp/1000, pHeader->timeStamp%1000, p); +#endif + pLog->writePtr += n; + } + } + return n; +} + +void PaUtil_DumpHighSpeedLog( LogHandle hLog, const char* fileName ) +{ + FILE* f = (fileName != NULL) ? fopen(fileName, "w") : stdout; + unsigned localWritePtr; + PaHighPerformanceLog* pLog = (PaHighPerformanceLog*)hLog; + assert(pLog->magik == kMagik); + localWritePtr = pLog->writePtr; + while (pLog->readPtr != localWritePtr) + { + const PaLogEntryHeader* pHeader = (const PaLogEntryHeader*)( pLog->data + pLog->readPtr ); + const char* p = (const char*)( pHeader + 1 ); + const PaUint64 ts = (const PaUint64)( pHeader->timeStamp * USEC_PER_SEC ); + assert(pHeader->size < (1024+sizeof(unsigned)+sizeof(PaLogEntryHeader))); + fprintf(f, "%05u.%03u: %s\n", (unsigned)(ts/1000), (unsigned)(ts%1000), p); + pLog->readPtr += pHeader->size; + } + if (f != stdout) + { + fclose(f); + } +} + +void PaUtil_DiscardHighSpeedLog( LogHandle hLog ) +{ + PaHighPerformanceLog* pLog = (PaHighPerformanceLog*)hLog; + assert(pLog->magik == kMagik); + PaUtil_FreeMemory(pLog->data); + PaUtil_FreeMemory(pLog); +} + #endif /* TRACE_REALTIME_EVENTS */ diff --git a/3rdparty/portaudio/src/common/pa_trace.h b/3rdparty/portaudio/src/common/pa_trace.h index b11509e0e..612dbf327 100644 --- a/3rdparty/portaudio/src/common/pa_trace.h +++ b/3rdparty/portaudio/src/common/pa_trace.h @@ -1,7 +1,7 @@ #ifndef PA_TRACE_H #define PA_TRACE_H /* - * $Id: pa_trace.h 1339 2008-02-15 07:50:33Z rossb $ + * $Id: pa_trace.h 1812 2012-02-14 09:32:57Z robiwan $ * Portable Audio I/O Library Trace Facility * Store trace information in real-time for later printing. * @@ -84,13 +84,29 @@ extern "C" void PaUtil_ResetTraceMessages(); void PaUtil_AddTraceMessage( const char *msg, int data ); void PaUtil_DumpTraceMessages(); - + +/* Alternative interface */ + +typedef void* LogHandle; + +int PaUtil_InitializeHighSpeedLog(LogHandle* phLog, unsigned maxSizeInBytes); +void PaUtil_ResetHighSpeedLogTimeRef(LogHandle hLog); +int PaUtil_AddHighSpeedLogMessage(LogHandle hLog, const char* fmt, ...); +void PaUtil_DumpHighSpeedLog(LogHandle hLog, const char* fileName); +void PaUtil_DiscardHighSpeedLog(LogHandle hLog); + #else #define PaUtil_ResetTraceMessages() /* noop */ #define PaUtil_AddTraceMessage(msg,data) /* noop */ #define PaUtil_DumpTraceMessages() /* noop */ +#define PaUtil_InitializeHighSpeedLog(phLog, maxSizeInBytes) (0) +#define PaUtil_ResetHighSpeedLogTimeRef(hLog) +#define PaUtil_AddHighSpeedLogMessage(...) (0) +#define PaUtil_DumpHighSpeedLog(hLog, fileName) +#define PaUtil_DiscardHighSpeedLog(hLog) + #endif diff --git a/3rdparty/portaudio/src/hostapi/alsa/pa_linux_alsa.c b/3rdparty/portaudio/src/hostapi/alsa/pa_linux_alsa.c index 4dda3bb62..796b612f2 100644 --- a/3rdparty/portaudio/src/hostapi/alsa/pa_linux_alsa.c +++ b/3rdparty/portaudio/src/hostapi/alsa/pa_linux_alsa.c @@ -1,5 +1,5 @@ /* - * $Id: pa_linux_alsa.c 1798 2011-12-08 19:43:29Z alan_horstmann $ + * $Id: pa_linux_alsa.c 1822 2012-03-28 16:14:49Z dmitrykos $ * PortAudio Portable Real-Time Audio Library * Latest Version at: http://www.portaudio.com * ALSA implementation by Joshua Haberman and Arve Knudsen @@ -7,6 +7,7 @@ * Copyright (c) 2002 Joshua Haberman * Copyright (c) 2005-2009 Arve Knudsen * Copyright (c) 2008 Kevin Kofler + * Copyright (c) 2011 Dmitry Kostjuchenko * * Based on the Open Source API proposed by Ross Bencina * Copyright (c) 1999-2002 Ross Bencina, Phil Burk @@ -79,10 +80,20 @@ #include "pa_linux_alsa.h" +/* Add missing define (for compatibility with older ALSA versions). */ #ifndef SND_PCM_TSTAMP_ENABLE -#define SND_PCM_TSTAMP_ENABLE SND_PCM_TSTAMP_MMAP + #define SND_PCM_TSTAMP_ENABLE SND_PCM_TSTAMP_MMAP #endif +/* Combine version elements into a single (unsigned) integer */ +#define ALSA_VERSION_INT(major, minor, subminor) ((major << 16) | (minor << 8) | subminor) + +/* Specifies that hardware audio sample needs byte-swapping into platfom native value representation. */ +#define paSwapEndian ((PaSampleFormat) 0x40000000) /**< @see PaSampleFormat */ + +/* Remove paSwapEndian and paNonInterleaved flags to get pure format value. */ +#define PA_ALSA_TO_FORMAT(X) ((X) & ~(paSwapEndian|paNonInterleaved)) + /* Defines Alsa function types and pointers to these functions. */ #define _PA_DEFINE_FUNC(x) typedef typeof(x) x##_ft; static x##_ft *alsa_##x = 0 @@ -186,6 +197,9 @@ _PA_DEFINE_FUNC(snd_pcm_info_set_subdevice); _PA_DEFINE_FUNC(snd_pcm_info_set_stream); _PA_DEFINE_FUNC(snd_pcm_info_get_name); _PA_DEFINE_FUNC(snd_pcm_info_get_card); +_PA_DEFINE_FUNC(snd_pcm_info_get_subdevices_count); +_PA_DEFINE_FUNC(snd_pcm_info_get_subdevice_name); +_PA_DEFINE_FUNC(snd_pcm_info_get_subdevices_avail); #define alsa_snd_pcm_info_alloca(ptr) __alsa_snd_alloca(ptr, snd_pcm_info) _PA_DEFINE_FUNC(snd_ctl_pcm_next_device); @@ -219,6 +233,7 @@ _PA_DEFINE_FUNC(snd_pcm_status_get_delay); #define alsa_snd_pcm_status_alloca(ptr) __alsa_snd_alloca(ptr, snd_pcm_status) _PA_DEFINE_FUNC(snd_card_next); +_PA_DEFINE_FUNC(snd_asoundlib_version); _PA_DEFINE_FUNC(snd_strerror); _PA_DEFINE_FUNC(snd_output_stdio_attach); @@ -244,96 +259,96 @@ static void *g_AlsaLib = NULL; int _PA_LOCAL_IMPL(snd_pcm_hw_params_set_rate_near) (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir) { - int ret; + int ret; - if ((ret = alsa_snd_pcm_hw_params_set_rate(pcm, params, (*val), (*dir))) < 0) - return ret; + if ((ret = alsa_snd_pcm_hw_params_set_rate(pcm, params, (*val), (*dir))) < 0) + return ret; - return 0; + return 0; } int _PA_LOCAL_IMPL(snd_pcm_hw_params_set_buffer_size_near) (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val) { - int ret; + int ret; - if ((ret = alsa_snd_pcm_hw_params_set_buffer_size(pcm, params, (*val))) < 0) - return ret; + if ((ret = alsa_snd_pcm_hw_params_set_buffer_size(pcm, params, (*val))) < 0) + return ret; - return 0; + return 0; } int _PA_LOCAL_IMPL(snd_pcm_hw_params_set_period_size_near) (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val, int *dir) { - int ret; + int ret; - if ((ret = alsa_snd_pcm_hw_params_set_period_size(pcm, params, (*val), (*dir))) < 0) - return ret; + if ((ret = alsa_snd_pcm_hw_params_set_period_size(pcm, params, (*val), (*dir))) < 0) + return ret; - return 0; + return 0; } int _PA_LOCAL_IMPL(snd_pcm_hw_params_get_channels_min) (const snd_pcm_hw_params_t *params, unsigned int *val) { - (*val) = 1; - return 0; + (*val) = 1; + return 0; } int _PA_LOCAL_IMPL(snd_pcm_hw_params_get_channels_max) (const snd_pcm_hw_params_t *params, unsigned int *val) { - (*val) = 2; - return 0; + (*val) = 2; + return 0; } int _PA_LOCAL_IMPL(snd_pcm_hw_params_get_periods_min) (const snd_pcm_hw_params_t *params, unsigned int *val, int *dir) { - (*val) = 2; - return 0; + (*val) = 2; + return 0; } int _PA_LOCAL_IMPL(snd_pcm_hw_params_get_periods_max) (const snd_pcm_hw_params_t *params, unsigned int *val, int *dir) { - (*val) = 8; - return 0; + (*val) = 8; + return 0; } int _PA_LOCAL_IMPL(snd_pcm_hw_params_get_period_size_min) (const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *frames, int *dir) { - (*frames) = 64; - return 0; + (*frames) = 64; + return 0; } int _PA_LOCAL_IMPL(snd_pcm_hw_params_get_period_size_max) (const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *frames, int *dir) { - (*frames) = 512; - return 0; + (*frames) = 512; + return 0; } int _PA_LOCAL_IMPL(snd_pcm_hw_params_get_buffer_size_max) (const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val) { - int ret; - int dir = 0; - snd_pcm_uframes_t pmax = 0; - unsigned int pcnt = 0; + int ret; + int dir = 0; + snd_pcm_uframes_t pmax = 0; + unsigned int pcnt = 0; - if ((ret = _PA_LOCAL_IMPL(snd_pcm_hw_params_get_period_size_max)(params, &pmax, &dir)) < 0) - return ret; - if ((ret = _PA_LOCAL_IMPL(snd_pcm_hw_params_get_periods_max)(params, &pcnt, &dir)) < 0) - return ret; + if ((ret = _PA_LOCAL_IMPL(snd_pcm_hw_params_get_period_size_max)(params, &pmax, &dir)) < 0) + return ret; + if ((ret = _PA_LOCAL_IMPL(snd_pcm_hw_params_get_periods_max)(params, &pcnt, &dir)) < 0) + return ret; - (*val) = pmax * pcnt; - return 0; + (*val) = pmax * pcnt; + return 0; } int _PA_LOCAL_IMPL(snd_pcm_hw_params_get_rate_min) (const snd_pcm_hw_params_t *params, unsigned int *val, int *dir) { - (*val) = 44100; - return 0; + (*val) = 44100; + return 0; } int _PA_LOCAL_IMPL(snd_pcm_hw_params_get_rate_max) (const snd_pcm_hw_params_t *params, unsigned int *val, int *dir) { - (*val) = 44100; - return 0; + (*val) = 44100; + return 0; } #endif // PA_ALSA_DYNAMIC @@ -345,22 +360,22 @@ static int PaAlsa_LoadLibrary() { #ifdef PA_ALSA_DYNAMIC - PA_DEBUG(( "%s: loading ALSA library file - %s\n", __FUNCTION__, g_AlsaLibName )); + PA_DEBUG(( "%s: loading ALSA library file - %s\n", __FUNCTION__, g_AlsaLibName )); - dlerror(); + dlerror(); g_AlsaLib = dlopen(g_AlsaLibName, (RTLD_NOW|RTLD_GLOBAL)); if (g_AlsaLib == NULL) { - PA_DEBUG(( "%s: failed dlopen() ALSA library file - %s, error: %s\n", __FUNCTION__, g_AlsaLibName, dlerror() )); - return 0; + PA_DEBUG(( "%s: failed dlopen() ALSA library file - %s, error: %s\n", __FUNCTION__, g_AlsaLibName, dlerror() )); + return 0; } PA_DEBUG(( "%s: loading ALSA API\n", __FUNCTION__ )); #define _PA_LOAD_FUNC(x) do { \ - alsa_##x = dlsym(g_AlsaLib, #x); \ - if (alsa_##x == NULL) { \ - PA_DEBUG(( "%s: symbol [%s] not found in - %s, error: %s\n", __FUNCTION__, #x, g_AlsaLibName, dlerror() )); }\ + alsa_##x = dlsym(g_AlsaLib, #x); \ + if (alsa_##x == NULL) { \ + PA_DEBUG(( "%s: symbol [%s] not found in - %s, error: %s\n", __FUNCTION__, #x, g_AlsaLibName, dlerror() )); }\ } while(0) #else @@ -464,6 +479,9 @@ _PA_LOAD_FUNC(snd_pcm_info_set_subdevice); _PA_LOAD_FUNC(snd_pcm_info_set_stream); _PA_LOAD_FUNC(snd_pcm_info_get_name); _PA_LOAD_FUNC(snd_pcm_info_get_card); +_PA_LOAD_FUNC(snd_pcm_info_get_subdevices_count); +_PA_LOAD_FUNC(snd_pcm_info_get_subdevice_name); +_PA_LOAD_FUNC(snd_pcm_info_get_subdevices_avail); _PA_LOAD_FUNC(snd_ctl_pcm_next_device); _PA_LOAD_FUNC(snd_ctl_pcm_info); @@ -494,34 +512,35 @@ _PA_LOAD_FUNC(snd_pcm_status_get_trigger_tstamp); _PA_LOAD_FUNC(snd_pcm_status_get_delay); _PA_LOAD_FUNC(snd_card_next); +_PA_LOAD_FUNC(snd_asoundlib_version); _PA_LOAD_FUNC(snd_strerror); _PA_LOAD_FUNC(snd_output_stdio_attach); #undef _PA_LOAD_FUNC #ifdef PA_ALSA_DYNAMIC - PA_DEBUG(( "%s: loaded ALSA API - ok\n", __FUNCTION__ )); + PA_DEBUG(( "%s: loaded ALSA API - ok\n", __FUNCTION__ )); #define _PA_VALIDATE_LOAD_REPLACEMENT(x)\ - do {\ - if (alsa_##x == NULL)\ - {\ - alsa_##x = &_PA_LOCAL_IMPL(x);\ - PA_DEBUG(( "%s: replacing [%s] with local implementation\n", __FUNCTION__, #x ));\ - }\ - } while (0) + do {\ + if (alsa_##x == NULL)\ + {\ + alsa_##x = &_PA_LOCAL_IMPL(x);\ + PA_DEBUG(( "%s: replacing [%s] with local implementation\n", __FUNCTION__, #x ));\ + }\ + } while (0) - _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_set_rate_near); - _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_set_buffer_size_near); - _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_set_period_size_near); - _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_channels_min); - _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_channels_max); - _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_periods_min); - _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_periods_max); - _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_period_size_min); - _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_period_size_max); - _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_buffer_size_max); - _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_rate_min); - _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_rate_max); + _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_set_rate_near); + _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_set_buffer_size_near); + _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_set_period_size_near); + _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_channels_min); + _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_channels_max); + _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_periods_min); + _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_periods_max); + _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_period_size_min); + _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_period_size_max); + _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_buffer_size_max); + _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_rate_min); + _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_rate_max); #undef _PA_LOCAL_IMPL #undef _PA_VALIDATE_LOAD_REPLACEMENT @@ -545,14 +564,14 @@ static void PaAlsa_CloseLibrary() { #ifdef PA_ALSA_DYNAMIC dlclose(g_AlsaLib); - g_AlsaLib = NULL; + g_AlsaLib = NULL; #endif } /* Check return value of ALSA function, and map it to PaError */ #define ENSURE_(expr, code) \ do { \ - int __pa_unsure_error_id;\ + int __pa_unsure_error_id;\ if( UNLIKELY( (__pa_unsure_error_id = (expr)) < 0 ) ) \ { \ /* PaUtil_SetLastHostErrorInfo should only be used in the main thread */ \ @@ -570,10 +589,10 @@ static void PaAlsa_CloseLibrary() #define ASSERT_CALL_(expr, success) \ do {\ - int __pa_assert_error_id;\ - __pa_assert_error_id = (expr);\ - assert( success == __pa_assert_error_id );\ - } while (0) + int __pa_assert_error_id;\ + __pa_assert_error_id = (expr);\ + assert( success == __pa_assert_error_id );\ + } while (0) static int numPeriods_ = 4; static int busyRetries_ = 100; @@ -600,6 +619,8 @@ typedef struct void *nonMmapBuffer; unsigned int nonMmapBufferSize; PaDeviceIndex device; /* Keep the device index */ + int deviceIsPlug; /* Distinguish plug types from direct 'hw:' devices */ + int useReventFix; /* Alsa older than 1.0.16, plug devices need a fix */ snd_pcm_t *pcm; snd_pcm_uframes_t bufferSize; @@ -659,6 +680,7 @@ typedef struct PaAlsaHostApiRepresentation PaUtilAllocationGroup *allocations; PaHostApiIndex hostApiIndex; + PaUint32 alsaLibVersion; /* Retrieved from the library at run-time */ } PaAlsaHostApiRepresentation; @@ -699,6 +721,7 @@ static double GetStreamCpuLoad( PaStream* stream ); static PaError BuildDeviceList( PaAlsaHostApiRepresentation *hostApi ); static int SetApproximateSampleRate( snd_pcm_t *pcm, snd_pcm_hw_params_t *hwParams, double sampleRate ); static int GetExactSampleRate( snd_pcm_hw_params_t *hwParams, double *sampleRate ); +static PaUint32 PaAlsaVersionNum(void); /* Callback prototypes */ static void *CallbackThreadFunc( void *userData ); @@ -715,6 +738,9 @@ static const PaAlsaDeviceInfo *GetDeviceInfo( const PaUtilHostApiRepresentation return (const PaAlsaDeviceInfo *)hostApi->deviceInfos[device]; } +static void CheckAndReplaceConverterForSwapEndian(PaAlsaStream *stream, PaSampleFormat hostInputSampleFormat, + PaSampleFormat hostOutputSampleFormat); + /** Uncommented because AlsaErrorHandler is unused for anything good yet. If AlsaErrorHandler is to be used, do not forget to register this callback in PaAlsa_Initialize, and unregister in Terminate. */ @@ -735,6 +761,7 @@ PaError PaAlsa_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex sizeof(PaAlsaHostApiRepresentation) ), paInsufficientMemory ); PA_UNLESS( alsaHostApi->allocations = PaUtil_CreateAllocationGroup(), paInsufficientMemory ); alsaHostApi->hostApiIndex = hostApiIndex; + alsaHostApi->alsaLibVersion = PaAlsaVersionNum(); *hostApi = (PaUtilHostApiRepresentation*)alsaHostApi; (*hostApi)->info.structVersion = 1; @@ -944,6 +971,24 @@ static void InitializeDeviceInfo( PaDeviceInfo *deviceInfo ) deviceInfo->defaultSampleRate = -1.; } + +/* Retrieve the version of the runtime Alsa-lib, as a single number equivalent to + * SND_LIB_VERSION. Only a version string is available ("a.b.c") so this has to be converted. + * Assume 'a' and 'b' are single digits only. + */ +static PaUint32 PaAlsaVersionNum(void) +{ + char* verStr; + PaUint32 verNum; + + verStr = (char*) alsa_snd_asoundlib_version(); + verNum = ALSA_VERSION_INT( atoi(verStr), atoi(verStr + 2), atoi(verStr + 4) ); + PA_DEBUG(( "ALSA version (build): " SND_LIB_VERSION_STR "\nALSA version (runtime): %s\n", verStr )); + + return verNum; +} + + /* Helper struct */ typedef struct { @@ -982,11 +1027,11 @@ HwDevInfo predefinedNames[] = { { "AndroidPlayback_ExtraDockSpeaker_normal", NULL, 0, 1, 0 }, { "AndroidPlayback_TvOut_normal", NULL, 0, 1, 0 }, - { "AndroidRecord_Microphone", NULL, 0, 0, 1 }, + { "AndroidRecord_Microphone", NULL, 0, 0, 1 }, { "AndroidRecord_Earpiece_normal", NULL, 0, 0, 1 }, - { "AndroidRecord_Speaker_normal", NULL, 0, 0, 1 }, + { "AndroidRecord_Speaker_normal", NULL, 0, 0, 1 }, { "AndroidRecord_Headset_normal", NULL, 0, 0, 1 }, - { "AndroidRecord_Bluetooth_normal", NULL, 0, 0, 1 }, + { "AndroidRecord_Bluetooth_normal", NULL, 0, 0, 1 }, { "AndroidRecord_Speaker_Headset_normal", NULL, 0, 0, 1 }, { NULL, NULL, 0, 1, 0 } @@ -1061,8 +1106,7 @@ static int OpenPcm( snd_pcm_t **pcmp, const char *name, snd_pcm_stream_t stream, ret = alsa_snd_pcm_open( pcmp, name, stream, mode ); if( -EBUSY != ret ) { - PA_DEBUG(( "%s: Successfully opened initially busy device after %d tries\n", - __FUNCTION__, tries )); + PA_DEBUG(( "%s: Successfully opened initially busy device after %d tries\n", __FUNCTION__, tries )); } } if( -EBUSY == ret ) @@ -1071,8 +1115,8 @@ static int OpenPcm( snd_pcm_t **pcmp, const char *name, snd_pcm_stream_t stream, } else { - if (ret < 0) - PA_DEBUG(( "%s: Opened device '%s' ptr[%p] - result: [%d:%s]\n", __FUNCTION__, name, *pcmp, ret, alsa_snd_strerror(ret) )); + if (ret < 0) + PA_DEBUG(( "%s: Opened device '%s' ptr[%p] - result: [%d:%s]\n", __FUNCTION__, name, *pcmp, ret, alsa_snd_strerror(ret) )); } return ret; @@ -1086,7 +1130,7 @@ static PaError FillInDevInfo( PaAlsaHostApiRepresentation *alsaApi, HwDevInfo* d snd_pcm_t *pcm = NULL; PaUtilHostApiRepresentation *baseApi = &alsaApi->baseHostApiRep; - PA_DEBUG(( "%s: filling device info for: %s\n", __FUNCTION__, deviceName->name )); + PA_DEBUG(( "%s: Filling device info for: %s\n", __FUNCTION__, deviceName->name )); /* Zero fields */ InitializeDeviceInfo( baseDeviceInfo ); @@ -1096,8 +1140,7 @@ static PaError FillInDevInfo( PaAlsaHostApiRepresentation *alsaApi, HwDevInfo* d /* Query capture */ if( deviceName->hasCapture && - OpenPcm( &pcm, deviceName->alsaName, SND_PCM_STREAM_CAPTURE, blocking, 0 ) - >= 0 ) + OpenPcm( &pcm, deviceName->alsaName, SND_PCM_STREAM_CAPTURE, blocking, 0 ) >= 0 ) { if( GropeDevice( pcm, deviceName->isPlug, StreamDirection_In, blocking, devInfo ) != paNoError ) { @@ -1109,8 +1152,7 @@ static PaError FillInDevInfo( PaAlsaHostApiRepresentation *alsaApi, HwDevInfo* d /* Query playback */ if( deviceName->hasPlayback && - OpenPcm( &pcm, deviceName->alsaName, SND_PCM_STREAM_PLAYBACK, blocking, 0 ) - >= 0 ) + OpenPcm( &pcm, deviceName->alsaName, SND_PCM_STREAM_PLAYBACK, blocking, 0 ) >= 0 ) { if( GropeDevice( pcm, deviceName->isPlug, StreamDirection_Out, blocking, devInfo ) != paNoError ) { @@ -1121,10 +1163,10 @@ static PaError FillInDevInfo( PaAlsaHostApiRepresentation *alsaApi, HwDevInfo* d } baseDeviceInfo->structVersion = 2; - baseDeviceInfo->hostApi = alsaApi->hostApiIndex; - baseDeviceInfo->name = deviceName->name; - devInfo->alsaName = deviceName->alsaName; - devInfo->isPlug = deviceName->isPlug; + baseDeviceInfo->hostApi = alsaApi->hostApiIndex; + baseDeviceInfo->name = deviceName->name; + devInfo->alsaName = deviceName->alsaName; + devInfo->isPlug = deviceName->isPlug; /* A: Storing pointer to PaAlsaDeviceInfo object as pointer to PaDeviceInfo object. * Should now be safe to add device info, unless the device supports neither capture nor playback @@ -1132,14 +1174,14 @@ static PaError FillInDevInfo( PaAlsaHostApiRepresentation *alsaApi, HwDevInfo* d if( baseDeviceInfo->maxInputChannels > 0 || baseDeviceInfo->maxOutputChannels > 0 ) { /* Make device default if there isn't already one or it is the ALSA "default" device */ - if( (baseApi->info.defaultInputDevice == paNoDevice || !strcmp(deviceName->alsaName, - "default" )) && baseDeviceInfo->maxInputChannels > 0 ) + if( (baseApi->info.defaultInputDevice == paNoDevice || + !strcmp(deviceName->alsaName, "default" )) && baseDeviceInfo->maxInputChannels > 0 ) { baseApi->info.defaultInputDevice = *devIdx; PA_DEBUG(("Default input device: %s\n", deviceName->name)); } - if( (baseApi->info.defaultOutputDevice == paNoDevice || !strcmp(deviceName->alsaName, - "default" )) && baseDeviceInfo->maxOutputChannels > 0 ) + if( (baseApi->info.defaultOutputDevice == paNoDevice || + !strcmp(deviceName->alsaName, "default" )) && baseDeviceInfo->maxOutputChannels > 0 ) { baseApi->info.defaultOutputDevice = *devIdx; PA_DEBUG(("Default output device: %s\n", deviceName->name)); @@ -1150,7 +1192,7 @@ static PaError FillInDevInfo( PaAlsaHostApiRepresentation *alsaApi, HwDevInfo* d } else { - PA_DEBUG(( "%s: skipped device: %s, all channels - 0\n", __FUNCTION__, deviceName->name )); + PA_DEBUG(( "%s: Skipped device: %s, all channels == 0\n", __FUNCTION__, deviceName->name )); } end: @@ -1171,7 +1213,6 @@ static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi ) snd_pcm_info_t *pcmInfo; int res; int blocking = SND_PCM_NONBLOCK; - char alsaCardName[50]; #ifdef PA_ENABLE_DEBUG_OUTPUT PaTime startTime = PaUtil_GetTime(); #endif @@ -1196,87 +1237,130 @@ static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi ) alsa_snd_pcm_info_alloca( &pcmInfo ); while( alsa_snd_card_next( &cardIdx ) == 0 && cardIdx >= 0 ) { + char alsaCardNameId[64] = { 0 }; char *cardName; int devIdx = -1; snd_ctl_t *ctl; - char buf[50]; - snprintf( alsaCardName, sizeof (alsaCardName), "hw:%d", cardIdx ); + /* Make card name */ + snprintf( alsaCardNameId, sizeof (alsaCardNameId)-1, "hw:%d", cardIdx ); - /* Acquire name of card */ - if( alsa_snd_ctl_open( &ctl, alsaCardName, 0 ) < 0 ) + /* Try opening card */ + if( alsa_snd_ctl_open( &ctl, alsaCardNameId, 0 ) < 0 ) { /* Unable to open card :( */ - PA_DEBUG(( "%s: Unable to open device %s\n", __FUNCTION__, alsaCardName )); + PA_DEBUG(( "%s: Unable to open device %s\n", __FUNCTION__, alsaCardNameId )); continue; } alsa_snd_ctl_card_info( ctl, cardInfo ); PA_ENSURE( PaAlsa_StrDup( alsaApi, &cardName, alsa_snd_ctl_card_info_get_name( cardInfo )) ); + PA_DEBUG(( "%s: Open card: id[%s] name[%s]\n", __FUNCTION__, alsaCardNameId, cardName )); + + /* Iterate devices */ while( alsa_snd_ctl_pcm_next_device( ctl, &devIdx ) == 0 && devIdx >= 0 ) { char *alsaDeviceName, *deviceName; size_t len; int hasPlayback = 0, hasCapture = 0; - snprintf( buf, sizeof (buf), "hw:%d,%d", cardIdx, devIdx ); + int subDevIdx, subDevCount = 1; - /* Obtain info about this particular device */ + PA_DEBUG(( "%s: - idx = %d:\n", __FUNCTION__, devIdx )); + + /* Make this device current */ alsa_snd_pcm_info_set_device( pcmInfo, devIdx ); - alsa_snd_pcm_info_set_subdevice( pcmInfo, 0 ); - alsa_snd_pcm_info_set_stream( pcmInfo, SND_PCM_STREAM_CAPTURE ); - if( alsa_snd_ctl_pcm_info( ctl, pcmInfo ) >= 0 ) + + /* Iterate sub-devices */ + for( subDevIdx = 0; subDevIdx < subDevCount; ++subDevIdx ) { - hasCapture = 1; + char buf[64] = { 0 }; + + /* Make this sub-device current */ + alsa_snd_pcm_info_set_subdevice( pcmInfo, subDevIdx ); + + /* Test for Capture capability */ + alsa_snd_pcm_info_set_stream( pcmInfo, SND_PCM_STREAM_CAPTURE ); + if( alsa_snd_ctl_pcm_info( ctl, pcmInfo ) >= 0 ) + { + hasCapture = 1; + } + + /* Test for Playback capability */ + alsa_snd_pcm_info_set_stream( pcmInfo, SND_PCM_STREAM_PLAYBACK ); + if( alsa_snd_ctl_pcm_info( ctl, pcmInfo ) >= 0 ) + { + hasPlayback = 1; + } + + /* If neither supported, such device is stub or failed */ + if( !hasPlayback && !hasCapture ) + { + continue; + } + + /* Get sub-device count */ + if( subDevIdx == 0 ) + { + subDevCount = alsa_snd_pcm_info_get_subdevices_count( pcmInfo ); + PA_DEBUG(( "%s: sub-devices: %d/%d\n", __FUNCTION__, alsa_snd_pcm_info_get_subdevices_avail( pcmInfo ), subDevCount)); + } + + PA_DEBUG(( "%s: - sub: %d\n", __FUNCTION__, subDevIdx )); + if( hasCapture ) PA_DEBUG(( "%s: - cap: CAPTURE\n", __FUNCTION__ )); + if( hasPlayback ) PA_DEBUG(( "%s: - cap: PLAYBACK\n", __FUNCTION__ )); + + /* Make name Id */ + snprintf( buf, sizeof(buf)-1, ( subDevCount > 1 ? "hw:%d,%d,%d" : "hw:%d,%d" ), cardIdx, devIdx, subDevIdx ); + + /* Make name */ + if( subDevCount <= 1 ) + { + const char *snd_deviceName = alsa_snd_pcm_info_get_name( pcmInfo ); + + len = snprintf( NULL, 0, "%s: %s (%s)", cardName, snd_deviceName, buf ) + 1; + PA_UNLESS( deviceName = (char *)PaUtil_GroupAllocateMemory( alsaApi->allocations, len ), paInsufficientMemory ); + snprintf( deviceName, len, "%s: %s (%s)", cardName, snd_deviceName, buf ); + } + else + { + const char *snd_deviceName = alsa_snd_pcm_info_get_name( pcmInfo ); + const char *snd_subDeviceName = alsa_snd_pcm_info_get_subdevice_name( pcmInfo ); + + len = snprintf( NULL, 0, "%s: %s (%s) {%s}", cardName, snd_deviceName, buf, snd_subDeviceName ) + 1; + PA_UNLESS( deviceName = (char *)PaUtil_GroupAllocateMemory( alsaApi->allocations, len ), paInsufficientMemory ); + snprintf( deviceName, len, "%s: %s (%s) {%s}", cardName, snd_deviceName, buf, snd_subDeviceName ); + } + + ++numDeviceNames; + if( !hwDevInfos || numDeviceNames > maxDeviceNames ) + { + maxDeviceNames *= 2; + PA_UNLESS( hwDevInfos = (HwDevInfo *) realloc( hwDevInfos, maxDeviceNames * sizeof (HwDevInfo) ), paInsufficientMemory ); + } + + PA_ENSURE( PaAlsa_StrDup( alsaApi, &alsaDeviceName, buf ) ); + + hwDevInfos[ numDeviceNames - 1 ].alsaName = alsaDeviceName; + hwDevInfos[ numDeviceNames - 1 ].name = deviceName; + hwDevInfos[ numDeviceNames - 1 ].isPlug = 0; + hwDevInfos[ numDeviceNames - 1 ].hasPlayback = hasPlayback; + hwDevInfos[ numDeviceNames - 1 ].hasCapture = hasCapture; + + PA_DEBUG(( "%s: Registered device: id[%s] name[%s]\n", __FUNCTION__, alsaDeviceName, deviceName )); } - - alsa_snd_pcm_info_set_stream( pcmInfo, SND_PCM_STREAM_PLAYBACK ); - if( alsa_snd_ctl_pcm_info( ctl, pcmInfo ) >= 0 ) - { - hasPlayback = 1; - } - - if( !hasPlayback && !hasCapture ) - { - /* Error */ - continue; - } - - /* The length of the string written by snprintf plus terminating 0 */ - len = snprintf( NULL, 0, "%s: %s (%s)", cardName, alsa_snd_pcm_info_get_name( pcmInfo ), buf ) + 1; - PA_UNLESS( deviceName = (char *)PaUtil_GroupAllocateMemory( alsaApi->allocations, len ), - paInsufficientMemory ); - snprintf( deviceName, len, "%s: %s (%s)", cardName, - alsa_snd_pcm_info_get_name( pcmInfo ), buf ); - - ++numDeviceNames; - if( !hwDevInfos || numDeviceNames > maxDeviceNames ) - { - maxDeviceNames *= 2; - PA_UNLESS( hwDevInfos = (HwDevInfo *) realloc( hwDevInfos, maxDeviceNames * sizeof (HwDevInfo) ), - paInsufficientMemory ); - } - - PA_ENSURE( PaAlsa_StrDup( alsaApi, &alsaDeviceName, buf ) ); - - hwDevInfos[ numDeviceNames - 1 ].alsaName = alsaDeviceName; - hwDevInfos[ numDeviceNames - 1 ].name = deviceName; - hwDevInfos[ numDeviceNames - 1 ].isPlug = 0; - hwDevInfos[ numDeviceNames - 1 ].hasPlayback = hasPlayback; - hwDevInfos[ numDeviceNames - 1 ].hasCapture = hasCapture; } alsa_snd_ctl_close( ctl ); } /* Iterate over plugin devices */ - if( NULL == (*alsa_snd_config) ) { /* alsa_snd_config_update is called implicitly by some functions, if this hasn't happened snd_config will be NULL (bleh) */ ENSURE_( alsa_snd_config_update(), paUnanticipatedHostError ); PA_DEBUG(( "Updating snd_config\n" )); } - assert( *alsa_snd_config ); + assert( *alsa_snd_config ); if( (res = alsa_snd_config_search( *alsa_snd_config, "pcm", &topNode )) >= 0 ) { snd_config_iterator_t i, next; @@ -1309,36 +1393,34 @@ static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi ) } PA_DEBUG(( "%s: Found plugin [%s] of type [%s]\n", __FUNCTION__, idStr, tpStr )); - PA_UNLESS( alsaDeviceName = (char*)PaUtil_GroupAllocateMemory( alsaApi->allocations, - strlen(idStr) + 6 ), paInsufficientMemory ); + PA_UNLESS( alsaDeviceName = (char*)PaUtil_GroupAllocateMemory( alsaApi->allocations, strlen(idStr) + 6 ), paInsufficientMemory ); strcpy( alsaDeviceName, idStr ); - PA_UNLESS( deviceName = (char*)PaUtil_GroupAllocateMemory( alsaApi->allocations, - strlen(idStr) + 1 ), paInsufficientMemory ); + + PA_UNLESS( deviceName = (char*)PaUtil_GroupAllocateMemory( alsaApi->allocations, strlen(idStr) + 1 ), paInsufficientMemory ); strcpy( deviceName, idStr ); ++numDeviceNames; if( !hwDevInfos || numDeviceNames > maxDeviceNames ) { maxDeviceNames *= 2; - PA_UNLESS( hwDevInfos = (HwDevInfo *) realloc( hwDevInfos, maxDeviceNames * sizeof (HwDevInfo) ), - paInsufficientMemory ); + PA_UNLESS( hwDevInfos = (HwDevInfo *) realloc( hwDevInfos, maxDeviceNames * sizeof (HwDevInfo) ), paInsufficientMemory ); } predefined = FindDeviceName( alsaDeviceName ); hwDevInfos[numDeviceNames - 1].alsaName = alsaDeviceName; - hwDevInfos[numDeviceNames - 1].name = deviceName; - hwDevInfos[numDeviceNames - 1].isPlug = 1; + hwDevInfos[numDeviceNames - 1].name = deviceName; + hwDevInfos[numDeviceNames - 1].isPlug = 1; if( predefined ) { hwDevInfos[numDeviceNames - 1].hasPlayback = predefined->hasPlayback; - hwDevInfos[numDeviceNames - 1].hasCapture = predefined->hasCapture; + hwDevInfos[numDeviceNames - 1].hasCapture = predefined->hasCapture; } else { hwDevInfos[numDeviceNames - 1].hasPlayback = 1; - hwDevInfos[numDeviceNames - 1].hasCapture = 1; + hwDevInfos[numDeviceNames - 1].hasCapture = 1; } } } @@ -1346,12 +1428,10 @@ static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi ) PA_DEBUG(( "%s: Iterating over ALSA plugins failed: %s\n", __FUNCTION__, alsa_snd_strerror( res ) )); /* allocate deviceInfo memory based on the number of devices */ - PA_UNLESS( baseApi->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory( - alsaApi->allocations, sizeof(PaDeviceInfo*) * (numDeviceNames) ), paInsufficientMemory ); + PA_UNLESS( baseApi->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory( alsaApi->allocations, sizeof(PaDeviceInfo*) * (numDeviceNames) ), paInsufficientMemory ); /* allocate all device info structs in a contiguous block */ - PA_UNLESS( deviceInfoArray = (PaAlsaDeviceInfo*)PaUtil_GroupAllocateMemory( - alsaApi->allocations, sizeof(PaAlsaDeviceInfo) * numDeviceNames ), paInsufficientMemory ); + PA_UNLESS( deviceInfoArray = (PaAlsaDeviceInfo*)PaUtil_GroupAllocateMemory( alsaApi->allocations, sizeof(PaAlsaDeviceInfo) * numDeviceNames ), paInsufficientMemory ); /* Loop over list of cards, filling in info. If a device is deemed unavailable (can't get name), * it's ignored. @@ -1361,7 +1441,7 @@ static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi ) * (dmix) is closed. The 'default' plugin may also point to the dmix plugin, so the same goes * for this. */ - PA_DEBUG(( "%s: filling device info for %d devices\n", __FUNCTION__, numDeviceNames )); + PA_DEBUG(( "%s: Filling device info for %d devices\n", __FUNCTION__, numDeviceNames )); for( i = 0, devIdx = 0; i < numDeviceNames; ++i ) { PaAlsaDeviceInfo* devInfo = &deviceInfoArray[i]; @@ -1384,8 +1464,7 @@ static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi ) continue; } - PA_ENSURE( FillInDevInfo( alsaApi, hwInfo, blocking, devInfo, - &devIdx ) ); + PA_ENSURE( FillInDevInfo( alsaApi, hwInfo, blocking, devInfo, &devIdx ) ); } free( hwDevInfos ); @@ -1449,32 +1528,58 @@ static PaSampleFormat GetAvailableFormats( snd_pcm_t *pcm ) alsa_snd_pcm_hw_params_any( pcm, hwParams ); - if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_FLOAT ) >= 0) + if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_FLOAT ) >= 0 ) available |= paFloat32; - if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S32 ) >= 0) + if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S32 ) >= 0 ) available |= paInt32; -#ifdef PA_LITTLE_ENDIAN - if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24_3LE ) >= 0) + if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24_3LE ) >= 0 ) available |= paInt24; -#elif defined PA_BIG_ENDIAN - if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24_3BE ) >= 0) + else + if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24_3BE ) >= 0 ) available |= paInt24; -#endif - if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S16 ) >= 0) + if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S16 ) >= 0 ) available |= paInt16; - if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_U8 ) >= 0) + if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_U8 ) >= 0 ) available |= paUInt8; - if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S8 ) >= 0) + if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S8 ) >= 0 ) available |= paInt8; return available; } +/* Check if format is available in native endianness, if not apply paSwapEndian flag for futher + processing by Alsa swapping converters. +*/ +static void CheckAndApplyEndianSwapToFormat( PaSampleFormat *format, snd_pcm_t *pcm ) +{ + snd_pcm_hw_params_t *hwParams; + alsa_snd_pcm_hw_params_alloca( &hwParams ); + + alsa_snd_pcm_hw_params_any( pcm, hwParams ); + + if( *format & paInt24 ) + { +#ifdef PA_LITTLE_ENDIAN + if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24_3LE ) < 0 ) + { + if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24_3BE ) >= 0 ) + *format |= paSwapEndian; + } +#elif defined PA_BIG_ENDIAN + if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24_3BE ) < 0 ) + { + if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24_3LE ) >= 0 ) + *format |= paSwapEndian; + } +#endif + } +} + /* Output to console all formats supported by device */ static void LogAllAvailableFormats( snd_pcm_t *pcm ) { @@ -1484,7 +1589,7 @@ static void LogAllAvailableFormats( snd_pcm_t *pcm ) alsa_snd_pcm_hw_params_any( pcm, hwParams ); - PA_DEBUG(( " --- Supported Formats ---\n" )); + PA_DEBUG(( " --- Supported Formats ---\n" )); if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S8 ) >= 0) PA_DEBUG(( "SND_PCM_FORMAT_S8\n" )); @@ -1599,7 +1704,7 @@ static void LogAllAvailableFormats( snd_pcm_t *pcm ) static snd_pcm_format_t Pa2AlsaFormat( PaSampleFormat paFormat ) { - switch( paFormat ) + switch( PA_ALSA_TO_FORMAT(paFormat) ) { case paFloat32: return SND_PCM_FORMAT_FLOAT; @@ -1609,11 +1714,10 @@ static snd_pcm_format_t Pa2AlsaFormat( PaSampleFormat paFormat ) case paInt24: #ifdef PA_LITTLE_ENDIAN - return SND_PCM_FORMAT_S24_3LE; + return ( paFormat & paSwapEndian ? SND_PCM_FORMAT_S24_3BE : SND_PCM_FORMAT_S24_3LE ); #elif defined PA_BIG_ENDIAN - return SND_PCM_FORMAT_S24_3BE; + return ( paFormat & paSwapEndian ? SND_PCM_FORMAT_S24_3LE : SND_PCM_FORMAT_S24_3BE ); #endif - case paInt32: return SND_PCM_FORMAT_S32; @@ -1716,7 +1820,10 @@ static PaError TestParameters( const PaUtilHostApiRepresentation *hostApi, const /* See if we can find a best possible match */ availableFormats = GetAvailableFormats( pcm ); - PA_ENSURE( hostFormat = PaUtil_SelectClosestAvailableFormat( availableFormats, parameters->sampleFormat ) ); + PA_ENSURE( hostFormat = PaUtil_SelectClosestAvailableFormat( PA_ALSA_TO_FORMAT(availableFormats), parameters->sampleFormat ) ); + + /* Append endiannes conversion flag */ + CheckAndApplyEndianSwapToFormat( &hostFormat, pcm ); /* Some specific hardware (reported: Audio8 DJ) can fail with assertion during this step. */ ENSURE_( alsa_snd_pcm_hw_params_set_format( pcm, hwParams, Pa2AlsaFormat( hostFormat ) ), paUnanticipatedHostError ); @@ -1801,9 +1908,11 @@ error: return result; } + static PaError PaAlsaStreamComponent_Initialize( PaAlsaStreamComponent *self, PaAlsaHostApiRepresentation *alsaApi, const PaStreamParameters *params, StreamDirection streamDir, int callbackMode ) { + PaSampleFormat availableFormats; PaError result = paNoError; PaSampleFormat userSampleFormat = params->sampleFormat, hostSampleFormat = paNoError; assert( params->channelCount > 0 ); @@ -1816,19 +1925,30 @@ static PaError PaAlsaStreamComponent_Initialize( PaAlsaStreamComponent *self, Pa const PaAlsaDeviceInfo *devInfo = GetDeviceInfo( &alsaApi->baseHostApiRep, params->device ); self->numHostChannels = PA_MAX( params->channelCount, StreamDirection_In == streamDir ? devInfo->minInputChannels : devInfo->minOutputChannels ); + self->deviceIsPlug = devInfo->isPlug; } else { /* We're blissfully unaware of the minimum channelCount */ self->numHostChannels = params->channelCount; + /* Check if device name does not start with hw: to determine if it is a 'plug' device */ + if( strncmp( "hw:", ((PaAlsaStreamInfo *)params->hostApiSpecificStreamInfo)->deviceString, 3 ) != 0 ) + self->deviceIsPlug = 1; /* An Alsa plug device, not a direct hw device */ } + if( self->deviceIsPlug && alsaApi->alsaLibVersion < ALSA_VERSION_INT( 1, 0, 16 ) ) + self->useReventFix = 1; /* Prior to Alsa1.0.16, plug devices may stutter without this fix */ self->device = params->device; PA_ENSURE( AlsaOpen( &alsaApi->baseHostApiRep, params, streamDir, &self->pcm ) ); self->nfds = alsa_snd_pcm_poll_descriptors_count( self->pcm ); - PA_ENSURE( hostSampleFormat = PaUtil_SelectClosestAvailableFormat( GetAvailableFormats( self->pcm ), userSampleFormat ) ); + /* Get host sample format */ + availableFormats = GetAvailableFormats( self->pcm ); + PA_ENSURE( hostSampleFormat = PaUtil_SelectClosestAvailableFormat( PA_ALSA_TO_FORMAT(availableFormats), userSampleFormat ) ); + + /* Append endiannes conversion flag */ + CheckAndApplyEndianSwapToFormat( &hostSampleFormat, self->pcm ); self->hostSampleFormat = hostSampleFormat; self->nativeFormat = Pa2AlsaFormat( hostSampleFormat ); @@ -1850,7 +1970,7 @@ error: /* Log all available formats. */ if ( hostSampleFormat == paSampleFormatNotSupported ) - { + { LogAllAvailableFormats( self->pcm ); PA_DEBUG(( "%s: Please provide the log output to PortAudio developers, your hardware does not have any sample format implemented yet.\n", __FUNCTION__ )); } @@ -2014,12 +2134,12 @@ static PaError PaAlsaStreamComponent_FinishConfigure( PaAlsaStreamComponent *sel } if (alsa_snd_pcm_hw_params_get_buffer_size != NULL) { - ENSURE_( alsa_snd_pcm_hw_params_get_buffer_size( hwParams, &self->bufferSize ), paUnanticipatedHostError ); - } - else - { - self->bufferSize = bufSz; - } + ENSURE_( alsa_snd_pcm_hw_params_get_buffer_size( hwParams, &self->bufferSize ), paUnanticipatedHostError ); + } + else + { + self->bufferSize = bufSz; + } /* Latency in seconds */ *latency = self->bufferSize / sampleRate; @@ -2145,7 +2265,7 @@ static int CalculatePollTimeout( const PaAlsaStream *stream, unsigned long frame */ static unsigned long PaAlsa_AlignBackward(unsigned long v, unsigned long align) { - return ((v - (align ? v % align : 0))); + return ((v - (align ? v % align : 0))); } /** Align value in forward direction. @@ -2155,8 +2275,8 @@ static unsigned long PaAlsa_AlignBackward(unsigned long v, unsigned long align) */ static unsigned long PaAlsa_AlignForward(unsigned long v, unsigned long align) { - unsigned long remainder = (align ? (v % align) : 0); - return (remainder != 0 ? v + (align - remainder) : v); + unsigned long remainder = (align ? (v % align) : 0); + return (remainder != 0 ? v + (align - remainder) : v); } /** Get size of host buffer maintained from the number of user frames, sample rate and suggested latency. Minimum double buffering @@ -2168,8 +2288,8 @@ static unsigned long PaAlsa_AlignForward(unsigned long v, unsigned long align) */ static unsigned long PaAlsa_GetFramesPerHostBuffer(unsigned long userFramesPerBuffer, PaTime suggestedLatency, double sampleRate) { - unsigned long frames = userFramesPerBuffer + PA_MAX( userFramesPerBuffer, (unsigned long)(suggestedLatency * sampleRate) ); - return frames; + unsigned long frames = userFramesPerBuffer + PA_MAX( userFramesPerBuffer, (unsigned long)(suggestedLatency * sampleRate) ); + return frames; } /** Determine size per host buffer. @@ -2239,7 +2359,7 @@ static PaError PaAlsaStreamComponent_DetermineFramesPerBuffer( PaAlsaStreamCompo #endif - { + { unsigned numPeriods = numPeriods_, maxPeriods = 0, minPeriods = numPeriods_; /* It may be that the device only supports 2 periods for instance */ @@ -2356,7 +2476,7 @@ static PaError PaAlsaStreamComponent_DetermineFramesPerBuffer( PaAlsaStreamCompo framesPerHostBuffer = 2048; #endif PA_DEBUG(( "%s: suggested host buffer period = %lu \n", __FUNCTION__, framesPerHostBuffer )); - } + } { /* Get min/max period sizes and adjust our chosen */ @@ -2377,10 +2497,10 @@ static PaError PaAlsaStreamComponent_DetermineFramesPerBuffer( PaAlsaStreamCompo framesPerHostBuffer = ((minmax_diff == 2) ? max - 1 : max); } - PA_DEBUG(( "%s: device period minimum = %lu\n", __FUNCTION__, min )); - PA_DEBUG(( "%s: device period maximum = %lu\n", __FUNCTION__, max )); - PA_DEBUG(( "%s: host buffer period = %lu\n", __FUNCTION__, framesPerHostBuffer )); - PA_DEBUG(( "%s: host buffer period latency = %f\n", __FUNCTION__, (double)(framesPerHostBuffer / sampleRate) )); + PA_DEBUG(( "%s: device period minimum = %lu\n", __FUNCTION__, min )); + PA_DEBUG(( "%s: device period maximum = %lu\n", __FUNCTION__, max )); + PA_DEBUG(( "%s: host buffer period = %lu\n", __FUNCTION__, framesPerHostBuffer )); + PA_DEBUG(( "%s: host buffer period latency = %f\n", __FUNCTION__, (double)(framesPerHostBuffer / sampleRate) )); /* Try setting period size */ dir = 0; @@ -2764,11 +2884,16 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, hostOutputSampleFormat = stream->playback.hostSampleFormat | (!stream->playback.hostInterleaved ? paNonInterleaved : 0); PA_ENSURE( PaUtil_InitializeBufferProcessor( &stream->bufferProcessor, - numInputChannels, inputSampleFormat, hostInputSampleFormat, - numOutputChannels, outputSampleFormat, hostOutputSampleFormat, + numInputChannels, inputSampleFormat, (hostInputSampleFormat & ~paSwapEndian), + numOutputChannels, outputSampleFormat, (hostOutputSampleFormat & ~paSwapEndian), sampleRate, streamFlags, framesPerBuffer, stream->maxFramesPerHostBuffer, hostBufferSizeMode, callback, userData ) ); + /* Some drivers may work only in Big-Endian format (like Audio4DJ), check it and replace + original converter with our specific with swapping capability. + */ + CheckAndReplaceConverterForSwapEndian(stream, hostInputSampleFormat, hostOutputSampleFormat); + /* Ok, buffer processor is initialized, now we can deduce it's latency */ if( numInputChannels > 0 ) stream->streamRepresentation.streamInfo.inputLatency = inputLatency + (PaTime)( @@ -3607,6 +3732,16 @@ static PaError PaAlsaStreamComponent_EndPolling( PaAlsaStreamComponent* self, st *shouldPoll = 0; } + else /* (A zero revent occurred) */ + /* Work around an issue with Alsa older than 1.0.16 using some plugins (eg default with plug + dmix) where + * POLLIN or POLLOUT are zeroed by Alsa-lib if _mmap_avail() is a few frames short of avail_min at period + * boundary, possibly due to erratic dma interrupts at period boundary? Treat as a valid event. + */ + if( self->useReventFix ) + { + self->ready = 1; + *shouldPoll = 0; + } error: return result; @@ -3769,8 +3904,8 @@ static PaError PaAlsaStream_WaitForFrames( PaAlsaStream *self, unsigned long *fr /* not else ! */ if (timeouts >= 2048) /* audio device not working, shall return error to notify waiters */ { - *framesAvail = 0; /* no frames available for processing */ - xrun = 1; /* try recovering device */ + *framesAvail = 0; /* no frames available for processing */ + xrun = 1; /* try recovering device */ PA_DEBUG(( "%s: poll timed out\n", __FUNCTION__, timeouts )); goto end;/*PA_ENSURE( paTimedOut );*/ @@ -4148,7 +4283,7 @@ static void *CallbackThreadFunc( void *userData ) int xrun = 0; #ifdef PTHREAD_CANCELED - pthread_testcancel(); + pthread_testcancel(); #endif /* @concern StreamStop if the main thread has requested a stop and the stream has not been effectively @@ -4550,3 +4685,648 @@ PaError PaAlsa_SetRetriesBusy( int retries ) busyRetries_ = retries; return paNoError; } + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ +/* CONVERTERS (Swapping SRC/DST) */ +/* -------------------------------------------------------------------------- */ + +#define PA_CLIP_( val, min, max )\ + { val = ((val) < (min)) ? (min) : (((val) > (max)) ? (max) : (val)); } + +static const double const_1_div_2147483648_ = 1.0 / 2147483648.0; /* 32 bit multiplier */ + +/* -------------------------------------------------------------------------- */ + +static void Copy_24_To_24_Swap( + void *destinationBuffer, signed int destinationStride, + void *sourceBuffer, signed int sourceStride, + unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator ) +{ + unsigned char *src = (unsigned char*)sourceBuffer; + unsigned char *dest = (unsigned char*)destinationBuffer; + + (void) ditherGenerator; /* unused parameter */ + + while( count-- ) + { + dest[2] = src[0]; + dest[1] = src[1]; + dest[0] = src[2]; + + src += sourceStride * 3; + dest += destinationStride * 3; + } +} + +/* -------------------------------------------------------------------------- */ + +static void UInt8_To_Int24_Swap( + void *destinationBuffer, signed int destinationStride, + void *sourceBuffer, signed int sourceStride, + unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator ) +{ + unsigned char *src = (unsigned char*)sourceBuffer; + unsigned char *dest = (unsigned char*)destinationBuffer; + (void) ditherGenerator; /* unused parameters */ + + while( count-- ) + { + +#if defined(PA_LITTLE_ENDIAN) + dest[2] = 0; + dest[1] = 0; + dest[0] = (unsigned char)(*src - 128); +#elif defined(PA_BIG_ENDIAN) + dest[2] = (unsigned char)(*src - 128); + dest[1] = 0; + dest[0] = 0; +#endif + + src += sourceStride; + dest += destinationStride * 3; + } +} + +/* -------------------------------------------------------------------------- */ + +static void Int8_To_Int24_Swap( + void *destinationBuffer, signed int destinationStride, + void *sourceBuffer, signed int sourceStride, + unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator ) +{ + signed char *src = (signed char*)sourceBuffer; + unsigned char *dest = (unsigned char*)destinationBuffer; + (void)ditherGenerator; /* unused parameter */ + + while( count-- ) + { + +#if defined(PA_LITTLE_ENDIAN) + dest[2] = 0; + dest[1] = 0; + dest[0] = (*src); +#elif defined(PA_BIG_ENDIAN) + dest[2] = (*src); + dest[1] = 0; + dest[0] = 0; +#endif + + src += sourceStride; + dest += destinationStride * 3; + } +} + +/* -------------------------------------------------------------------------- */ + +static void Int16_To_Int24_Swap( + void *destinationBuffer, signed int destinationStride, + void *sourceBuffer, signed int sourceStride, + unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator ) +{ + PaInt16 *src = (PaInt16*) sourceBuffer; + unsigned char *dest = (unsigned char*)destinationBuffer; + PaInt16 temp; + + (void) ditherGenerator; /* unused parameter */ + + while( count-- ) + { + temp = *src; + +#if defined(PA_LITTLE_ENDIAN) + dest[2] = 0; + dest[1] = (unsigned char)(temp); + dest[0] = (unsigned char)(temp >> 8); +#elif defined(PA_BIG_ENDIAN) + dest[2] = (unsigned char)(temp >> 8); + dest[1] = (unsigned char)(temp); + dest[0] = 0; +#endif + + src += sourceStride; + dest += destinationStride * 3; + } +} + +/* -------------------------------------------------------------------------- */ + +static void Int32_To_Int24_Swap( + void *destinationBuffer, signed int destinationStride, + void *sourceBuffer, signed int sourceStride, + unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator ) +{ + PaInt32 *src = (PaInt32*)sourceBuffer; + unsigned char *dest = (unsigned char*)destinationBuffer; + (void) ditherGenerator; /* unused parameter */ + + while( count-- ) + { + /* REVIEW */ +#if defined(PA_LITTLE_ENDIAN) + dest[2] = (unsigned char)(*src >> 8); + dest[1] = (unsigned char)(*src >> 16); + dest[0] = (unsigned char)(*src >> 24); +#elif defined(PA_BIG_ENDIAN) + dest[2] = (unsigned char)(*src >> 24); + dest[1] = (unsigned char)(*src >> 16); + dest[0] = (unsigned char)(*src >> 8); +#endif + src += sourceStride; + dest += destinationStride * 3; + } +} + +/* -------------------------------------------------------------------------- */ + +static void Float32_To_Int24_Swap( + void *destinationBuffer, signed int destinationStride, + void *sourceBuffer, signed int sourceStride, + unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator ) +{ + float *src = (float*)sourceBuffer; + unsigned char *dest = (unsigned char*)destinationBuffer; + PaInt32 temp; + + (void) ditherGenerator; /* unused parameter */ + + while( count-- ) + { + /* convert to 32 bit and drop the low 8 bits */ + double scaled = (double)(*src) * 2147483647.0; + temp = (PaInt32) scaled; + +#if defined(PA_LITTLE_ENDIAN) + dest[2] = (unsigned char)(temp >> 8); + dest[1] = (unsigned char)(temp >> 16); + dest[0] = (unsigned char)(temp >> 24); +#elif defined(PA_BIG_ENDIAN) + dest[2] = (unsigned char)(temp >> 24); + dest[1] = (unsigned char)(temp >> 16); + dest[0] = (unsigned char)(temp >> 8); +#endif + + src += sourceStride; + dest += destinationStride * 3; + } +} + +/* -------------------------------------------------------------------------- */ + +static void Float32_To_Int24_Dither_Swap( + void *destinationBuffer, signed int destinationStride, + void *sourceBuffer, signed int sourceStride, + unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator ) +{ + float *src = (float*)sourceBuffer; + unsigned char *dest = (unsigned char*)destinationBuffer; + PaInt32 temp; + + while( count-- ) + { + /* convert to 32 bit and drop the low 8 bits */ + + double dither = PaUtil_GenerateFloatTriangularDither( ditherGenerator ); + /* use smaller scaler to prevent overflow when we add the dither */ + double dithered = ((double)*src * (2147483646.0)) + dither; + + temp = (PaInt32) dithered; + +#if defined(PA_LITTLE_ENDIAN) + dest[2] = (unsigned char)(temp >> 8); + dest[1] = (unsigned char)(temp >> 16); + dest[0] = (unsigned char)(temp >> 24); +#elif defined(PA_BIG_ENDIAN) + dest[2] = (unsigned char)(temp >> 24); + dest[1] = (unsigned char)(temp >> 16); + dest[0] = (unsigned char)(temp >> 8); +#endif + + src += sourceStride; + dest += destinationStride * 3; + } +} + +/* -------------------------------------------------------------------------- */ + +static void Float32_To_Int24_Clip_Swap( + void *destinationBuffer, signed int destinationStride, + void *sourceBuffer, signed int sourceStride, + unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator ) +{ + float *src = (float*)sourceBuffer; + unsigned char *dest = (unsigned char*)destinationBuffer; + PaInt32 temp; + + (void) ditherGenerator; /* unused parameter */ + + while( count-- ) + { + /* convert to 32 bit and drop the low 8 bits */ + double scaled = *src * 0x7FFFFFFF; + PA_CLIP_( scaled, -2147483648., 2147483647. ); + temp = (PaInt32) scaled; + +#if defined(PA_LITTLE_ENDIAN) + dest[2] = (unsigned char)(temp >> 8); + dest[1] = (unsigned char)(temp >> 16); + dest[0] = (unsigned char)(temp >> 24); +#elif defined(PA_BIG_ENDIAN) + dest[2] = (unsigned char)(temp >> 24); + dest[1] = (unsigned char)(temp >> 16); + dest[0] = (unsigned char)(temp >> 8); +#endif + + src += sourceStride; + dest += destinationStride * 3; + } +} + +/* -------------------------------------------------------------------------- */ + +static void Float32_To_Int24_DitherClip_Swap( + void *destinationBuffer, signed int destinationStride, + void *sourceBuffer, signed int sourceStride, + unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator ) +{ + float *src = (float*)sourceBuffer; + unsigned char *dest = (unsigned char*)destinationBuffer; + PaInt32 temp; + + while( count-- ) + { + /* convert to 32 bit and drop the low 8 bits */ + + double dither = PaUtil_GenerateFloatTriangularDither( ditherGenerator ); + /* use smaller scaler to prevent overflow when we add the dither */ + double dithered = ((double)*src * (2147483646.0)) + dither; + PA_CLIP_( dithered, -2147483648., 2147483647. ); + + temp = (PaInt32) dithered; + +#if defined(PA_LITTLE_ENDIAN) + dest[2] = (unsigned char)(temp >> 8); + dest[1] = (unsigned char)(temp >> 16); + dest[0] = (unsigned char)(temp >> 24); +#elif defined(PA_BIG_ENDIAN) + dest[2] = (unsigned char)(temp >> 24); + dest[1] = (unsigned char)(temp >> 16); + dest[0] = (unsigned char)(temp >> 8); +#endif + + src += sourceStride; + dest += destinationStride * 3; + } +} + +/* -------------------------------------------------------------------------- */ + +static void Int24_To_Float32_Swap( + void *destinationBuffer, signed int destinationStride, + void *sourceBuffer, signed int sourceStride, + unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator ) +{ + unsigned char *src = (unsigned char*)sourceBuffer; + float *dest = (float*)destinationBuffer; + PaInt32 temp; + + (void) ditherGenerator; /* unused parameter */ + + while( count-- ) + { + +#if defined(PA_LITTLE_ENDIAN) + temp = (((PaInt32)src[2]) << 8); + temp = temp | (((PaInt32)src[1]) << 16); + temp = temp | (((PaInt32)src[0]) << 24); +#elif defined(PA_BIG_ENDIAN) + temp = (((PaInt32)src[2]) << 24); + temp = temp | (((PaInt32)src[1]) << 16); + temp = temp | (((PaInt32)src[0]) << 8); +#endif + + *dest = (float) ((double)temp * const_1_div_2147483648_); + + src += sourceStride * 3; + dest += destinationStride; + } +} + +/* -------------------------------------------------------------------------- */ + +static void Int24_To_Int32_Swap( + void *destinationBuffer, signed int destinationStride, + void *sourceBuffer, signed int sourceStride, + unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator ) +{ + unsigned char *src = (unsigned char*)sourceBuffer; + PaInt32 *dest = (PaInt32*) destinationBuffer; + PaInt32 temp; + + (void) ditherGenerator; /* unused parameter */ + + while( count-- ) + { + +#if defined(PA_LITTLE_ENDIAN) + temp = (((PaInt32)src[2]) << 8); + temp = temp | (((PaInt32)src[1]) << 16); + temp = temp | (((PaInt32)src[0]) << 24); +#elif defined(PA_BIG_ENDIAN) + temp = (((PaInt32)src[2]) << 24); + temp = temp | (((PaInt32)src[1]) << 16); + temp = temp | (((PaInt32)src[0]) << 8); +#endif + + *dest = temp; + + src += sourceStride * 3; + dest += destinationStride; + } +} + +/* -------------------------------------------------------------------------- */ + +static void Int24_To_Int16_Swap( + void *destinationBuffer, signed int destinationStride, + void *sourceBuffer, signed int sourceStride, + unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator ) +{ + unsigned char *src = (unsigned char*)sourceBuffer; + PaInt16 *dest = (PaInt16*)destinationBuffer; + + PaInt16 temp; + + (void) ditherGenerator; /* unused parameter */ + + while( count-- ) + { + +#if defined(PA_LITTLE_ENDIAN) + /* src[2] is discarded */ + temp = (((PaInt16)src[1])); + temp = temp | (PaInt16)(((PaInt16)src[0]) << 8); +#elif defined(PA_BIG_ENDIAN) + /* src[0] is discarded */ + temp = (PaInt16)(((PaInt16)src[2]) << 8); + temp = temp | (((PaInt16)src[1])); +#endif + + *dest = temp; + + src += sourceStride * 3; + dest += destinationStride; + } +} + +/* -------------------------------------------------------------------------- */ + +static void Int24_To_Int16_Dither_Swap( + void *destinationBuffer, signed int destinationStride, + void *sourceBuffer, signed int sourceStride, + unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator ) +{ + unsigned char *src = (unsigned char*)sourceBuffer; + PaInt16 *dest = (PaInt16*)destinationBuffer; + + PaInt32 temp, dither; + + while( count-- ) + { + +#if defined(PA_LITTLE_ENDIAN) + temp = (((PaInt32)src[2]) << 8); + temp = temp | (((PaInt32)src[1]) << 16); + temp = temp | (((PaInt32)src[0]) << 24); +#elif defined(PA_BIG_ENDIAN) + temp = (((PaInt32)src[2]) << 24); + temp = temp | (((PaInt32)src[1]) << 16); + temp = temp | (((PaInt32)src[0]) << 8); +#endif + + /* REVIEW */ + dither = PaUtil_Generate16BitTriangularDither( ditherGenerator ); + *dest = (PaInt16) (((temp >> 1) + dither) >> 15); + + src += sourceStride * 3; + dest += destinationStride; + } +} + +/* -------------------------------------------------------------------------- */ + +static void Int24_To_Int8_Swap( + void *destinationBuffer, signed int destinationStride, + void *sourceBuffer, signed int sourceStride, + unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator ) +{ + unsigned char *src = (unsigned char*)sourceBuffer; + signed char *dest = (signed char*)destinationBuffer; + + (void) ditherGenerator; /* unused parameter */ + + while( count-- ) + { + +#if defined(PA_LITTLE_ENDIAN) + /* src[0] is discarded */ + /* src[1] is discarded */ + *dest = src[0]; +#elif defined(PA_BIG_ENDIAN) + /* src[2] is discarded */ + /* src[1] is discarded */ + *dest = src[2]; +#endif + + src += sourceStride * 3; + dest += destinationStride; + } +} + +/* -------------------------------------------------------------------------- */ + +static void Int24_To_Int8_Dither_Swap( + void *destinationBuffer, signed int destinationStride, + void *sourceBuffer, signed int sourceStride, + unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator ) +{ + unsigned char *src = (unsigned char*)sourceBuffer; + signed char *dest = (signed char*)destinationBuffer; + + PaInt32 temp, dither; + + while( count-- ) + { + +#if defined(PA_LITTLE_ENDIAN) + temp = (((PaInt32)src[2]) << 8); + temp = temp | (((PaInt32)src[1]) << 16); + temp = temp | (((PaInt32)src[0]) << 24); +#elif defined(PA_BIG_ENDIAN) + temp = (((PaInt32)src[2]) << 24); + temp = temp | (((PaInt32)src[1]) << 16); + temp = temp | (((PaInt32)src[0]) << 8); +#endif + + /* REVIEW */ + dither = PaUtil_Generate16BitTriangularDither( ditherGenerator ); + *dest = (signed char) (((temp >> 1) + dither) >> 23); + + src += sourceStride * 3; + dest += destinationStride; + } +} + +/* -------------------------------------------------------------------------- */ + +static void Int24_To_UInt8_Swap( + void *destinationBuffer, signed int destinationStride, + void *sourceBuffer, signed int sourceStride, + unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator ) +{ + unsigned char *src = (unsigned char*)sourceBuffer; + unsigned char *dest = (unsigned char*)destinationBuffer; + + (void) ditherGenerator; /* unused parameter */ + + while( count-- ) + { + +#if defined(PA_LITTLE_ENDIAN) + /* src[0] is discarded */ + /* src[1] is discarded */ + *dest = (unsigned char)(src[0] + 128); +#elif defined(PA_BIG_ENDIAN) + *dest = (unsigned char)(src[2] + 128); + /* src[1] is discarded */ + /* src[2] is discarded */ +#endif + + src += sourceStride * 3; + dest += destinationStride; + } +} + +/* -------------------------------------------------------------------------- */ + +static void X_To_X_Stub( + void *destinationBuffer, signed int destinationStride, + void *sourceBuffer, signed int sourceStride, + unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator ) +{ + (void) destinationBuffer; /* unused parameters */ + (void) destinationStride; /* unused parameters */ + (void) sourceBuffer; /* unused parameters */ + (void) sourceStride; /* unused parameters */ + (void) count; /* unused parameters */ + (void) ditherGenerator; /* unused parameters */ + /* IMPLEMENT ME */ + + assert(0 && "input/output format needs additional swapping converter"); +} + +/* -------------------------------------------------------------------------- */ + +static PaUtilConverterTable paAlsaSwapConverters = { + X_To_X_Stub, /* PaUtilConverter *Float32_To_Int32; */ + X_To_X_Stub, /* PaUtilConverter *Float32_To_Int32_Dither; */ + X_To_X_Stub, /* PaUtilConverter *Float32_To_Int32_Clip; */ + X_To_X_Stub, /* PaUtilConverter *Float32_To_Int32_DitherClip; */ + + Float32_To_Int24_Swap, /* PaUtilConverter *Float32_To_Int24; */ + Float32_To_Int24_Dither_Swap, /* PaUtilConverter *Float32_To_Int24_Dither; */ + Float32_To_Int24_Clip_Swap, /* PaUtilConverter *Float32_To_Int24_Clip; */ + Float32_To_Int24_DitherClip_Swap, /* PaUtilConverter *Float32_To_Int24_DitherClip; */ + + X_To_X_Stub, /* PaUtilConverter *Float32_To_Int16; */ + X_To_X_Stub, /* PaUtilConverter *Float32_To_Int16_Dither; */ + X_To_X_Stub, /* PaUtilConverter *Float32_To_Int16_Clip; */ + X_To_X_Stub, /* PaUtilConverter *Float32_To_Int16_DitherClip; */ + + X_To_X_Stub, /* PaUtilConverter *Float32_To_Int8; */ + X_To_X_Stub, /* PaUtilConverter *Float32_To_Int8_Dither; */ + X_To_X_Stub, /* PaUtilConverter *Float32_To_Int8_Clip; */ + X_To_X_Stub, /* PaUtilConverter *Float32_To_Int8_DitherClip; */ + + X_To_X_Stub, /* PaUtilConverter *Float32_To_UInt8; */ + X_To_X_Stub, /* PaUtilConverter *Float32_To_UInt8_Dither; */ + X_To_X_Stub, /* PaUtilConverter *Float32_To_UInt8_Clip; */ + X_To_X_Stub, /* PaUtilConverter *Float32_To_UInt8_DitherClip; */ + + X_To_X_Stub, /* PaUtilConverter *Int32_To_Float32; */ + Int32_To_Int24_Swap, /* PaUtilConverter *Int32_To_Int24; */ + X_To_X_Stub,/*TO-DO*//* PaUtilConverter *Int32_To_Int24_Dither; */ + X_To_X_Stub, /* PaUtilConverter *Int32_To_Int16; */ + X_To_X_Stub, /* PaUtilConverter *Int32_To_Int16_Dither; */ + X_To_X_Stub, /* PaUtilConverter *Int32_To_Int8; */ + X_To_X_Stub, /* PaUtilConverter *Int32_To_Int8_Dither; */ + X_To_X_Stub, /* PaUtilConverter *Int32_To_UInt8; */ + X_To_X_Stub, /* PaUtilConverter *Int32_To_UInt8_Dither; */ + + Int24_To_Float32_Swap, /* PaUtilConverter *Int24_To_Float32; */ + Int24_To_Int32_Swap, /* PaUtilConverter *Int24_To_Int32; */ + Int24_To_Int16_Swap, /* PaUtilConverter *Int24_To_Int16; */ + Int24_To_Int16_Dither_Swap, /* PaUtilConverter *Int24_To_Int16_Dither; */ + Int24_To_Int8_Swap, /* PaUtilConverter *Int24_To_Int8; */ + Int24_To_Int8_Dither_Swap, /* PaUtilConverter *Int24_To_Int8_Dither; */ + Int24_To_UInt8_Swap, /* PaUtilConverter *Int24_To_UInt8; */ + X_To_X_Stub, /* PaUtilConverter *Int24_To_UInt8_Dither; */ + + X_To_X_Stub, /* PaUtilConverter *Int16_To_Float32; */ + X_To_X_Stub, /* PaUtilConverter *Int16_To_Int32; */ + Int16_To_Int24_Swap, /* PaUtilConverter *Int16_To_Int24; */ + X_To_X_Stub, /* PaUtilConverter *Int16_To_Int8; */ + X_To_X_Stub, /* PaUtilConverter *Int16_To_Int8_Dither; */ + X_To_X_Stub, /* PaUtilConverter *Int16_To_UInt8; */ + X_To_X_Stub, /* PaUtilConverter *Int16_To_UInt8_Dither; */ + + X_To_X_Stub, /* PaUtilConverter *Int8_To_Float32; */ + X_To_X_Stub, /* PaUtilConverter *Int8_To_Int32; */ + Int8_To_Int24_Swap, /* PaUtilConverter *Int8_To_Int24 */ + X_To_X_Stub, /* PaUtilConverter *Int8_To_Int16; */ + X_To_X_Stub, /* PaUtilConverter *Int8_To_UInt8; */ + + X_To_X_Stub, /* PaUtilConverter *UInt8_To_Float32; */ + X_To_X_Stub, /* PaUtilConverter *UInt8_To_Int32; */ + UInt8_To_Int24_Swap, /* PaUtilConverter *UInt8_To_Int24; */ + X_To_X_Stub, /* PaUtilConverter *UInt8_To_Int16; */ + X_To_X_Stub, /* PaUtilConverter *UInt8_To_Int8; */ + + X_To_X_Stub, /* PaUtilConverter *Copy_8_To_8; */ + X_To_X_Stub, /* PaUtilConverter *Copy_16_To_16; */ + Copy_24_To_24_Swap, /* PaUtilConverter *Copy_24_To_24; */ + X_To_X_Stub /* PaUtilConverter *Copy_32_To_32; */ +}; +void CheckAndReplaceConverterForSwapEndian(PaAlsaStream *stream, PaSampleFormat hostInputSampleFormat, + PaSampleFormat hostOutputSampleFormat) +{ + PaUtilConverter **cv_org = (PaUtilConverter **)&paConverters, + **cv_swp = (PaUtilConverter **)&paAlsaSwapConverters; + + int i, i_max = sizeof(PaUtilConverterTable)/sizeof(PaUtilConverter *); + + if (hostInputSampleFormat & paSwapEndian) + { + for (i = 0; i < i_max; ++i) + { + if (cv_org[i] == stream->bufferProcessor.inputConverter) + { + stream->bufferProcessor.inputConverter = cv_swp[i]; + break; + } + } + } + + if (hostOutputSampleFormat & paSwapEndian) + { + for (i = 0; i < i_max; ++i) + { + if (cv_org[i] == stream->bufferProcessor.outputConverter) + { + stream->bufferProcessor.outputConverter = cv_swp[i]; + break; + } + } + } +} diff --git a/3rdparty/portaudio/src/hostapi/asio/pa_asio.cpp b/3rdparty/portaudio/src/hostapi/asio/pa_asio.cpp index 28eee9dbb..3ecc2170a 100644 --- a/3rdparty/portaudio/src/hostapi/asio/pa_asio.cpp +++ b/3rdparty/portaudio/src/hostapi/asio/pa_asio.cpp @@ -1,5 +1,5 @@ /* - * $Id: pa_asio.cpp 1778 2011-11-10 13:59:53Z rossb $ + * $Id: pa_asio.cpp 1825 2012-04-02 07:58:04Z rbencina $ * Portable Audio I/O Library for ASIO Drivers * * Author: Stephane Letz @@ -1031,8 +1031,6 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex PaAsioHostApiRepresentation *asioHostApi; PaAsioDeviceInfo *deviceInfoArray; char **names; - PaAsioDriverInfo paAsioDriverInfo; - asioHostApi = (PaAsioHostApiRepresentation*)PaUtil_AllocateMemory( sizeof(PaAsioHostApiRepresentation) ); if( !asioHostApi ) { @@ -1040,6 +1038,8 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex goto error; } + memset( asioHostApi, 0, sizeof(PaAsioHostApiRepresentation) ); /* ensure all fields are zeroed. especially asioHostApi->allocations */ + /* We initialize COM ourselves here and uninitialize it in Terminate(). This should be the only COM initialization needed in this module. @@ -1142,6 +1142,13 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex for( i=0; i < driverCount; ++i ) { + /* Due to the headless design of the ASIO API, drivers are free to write over data given to them (like M-Audio + drivers f.i.). This is an attempt to overcome that. */ + union _tag_local { + PaAsioDriverInfo info; + char _padding[4096]; + } paAsioDriver; + PA_DEBUG(("ASIO names[%d]:%s\n",i,names[i])); @@ -1176,7 +1183,7 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex /* Attempt to load the asio driver... */ - if( LoadAsioDriver( asioHostApi, names[i], &paAsioDriverInfo, asioHostApi->systemSpecific ) == paNoError ) + if( LoadAsioDriver( asioHostApi, names[i], &paAsioDriver.info, asioHostApi->systemSpecific ) == paNoError ) { PaAsioDeviceInfo *asioDeviceInfo = &deviceInfoArray[ (*hostApi)->info.deviceCount ]; PaDeviceInfo *deviceInfo = &asioDeviceInfo->commonDeviceInfo; @@ -1186,15 +1193,15 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex deviceInfo->name = names[i]; PA_DEBUG(("PaAsio_Initialize: drv:%d name = %s\n", i,deviceInfo->name)); - PA_DEBUG(("PaAsio_Initialize: drv:%d inputChannels = %d\n", i, paAsioDriverInfo.inputChannelCount)); - PA_DEBUG(("PaAsio_Initialize: drv:%d outputChannels = %d\n", i, paAsioDriverInfo.outputChannelCount)); - PA_DEBUG(("PaAsio_Initialize: drv:%d bufferMinSize = %d\n", i, paAsioDriverInfo.bufferMinSize)); - PA_DEBUG(("PaAsio_Initialize: drv:%d bufferMaxSize = %d\n", i, paAsioDriverInfo.bufferMaxSize)); - PA_DEBUG(("PaAsio_Initialize: drv:%d bufferPreferredSize = %d\n", i, paAsioDriverInfo.bufferPreferredSize)); - PA_DEBUG(("PaAsio_Initialize: drv:%d bufferGranularity = %d\n", i, paAsioDriverInfo.bufferGranularity)); + PA_DEBUG(("PaAsio_Initialize: drv:%d inputChannels = %d\n", i, paAsioDriver.info.inputChannelCount)); + PA_DEBUG(("PaAsio_Initialize: drv:%d outputChannels = %d\n", i, paAsioDriver.info.outputChannelCount)); + PA_DEBUG(("PaAsio_Initialize: drv:%d bufferMinSize = %d\n", i, paAsioDriver.info.bufferMinSize)); + PA_DEBUG(("PaAsio_Initialize: drv:%d bufferMaxSize = %d\n", i, paAsioDriver.info.bufferMaxSize)); + PA_DEBUG(("PaAsio_Initialize: drv:%d bufferPreferredSize = %d\n", i, paAsioDriver.info.bufferPreferredSize)); + PA_DEBUG(("PaAsio_Initialize: drv:%d bufferGranularity = %d\n", i, paAsioDriver.info.bufferGranularity)); - deviceInfo->maxInputChannels = paAsioDriverInfo.inputChannelCount; - deviceInfo->maxOutputChannels = paAsioDriverInfo.outputChannelCount; + deviceInfo->maxInputChannels = paAsioDriver.info.inputChannelCount; + deviceInfo->maxOutputChannels = paAsioDriver.info.outputChannelCount; deviceInfo->defaultSampleRate = 0.; bool foundDefaultSampleRate = false; @@ -1222,13 +1229,13 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex */ double defaultLowLatency = - paAsioDriverInfo.bufferPreferredSize / deviceInfo->defaultSampleRate; + paAsioDriver.info.bufferPreferredSize / deviceInfo->defaultSampleRate; deviceInfo->defaultLowInputLatency = defaultLowLatency; deviceInfo->defaultLowOutputLatency = defaultLowLatency; double defaultHighLatency = - paAsioDriverInfo.bufferMaxSize / deviceInfo->defaultSampleRate; + paAsioDriver.info.bufferMaxSize / deviceInfo->defaultSampleRate; if( defaultHighLatency < defaultLowLatency ) defaultHighLatency = defaultLowLatency; /* just in case the driver returns something strange */ @@ -1249,10 +1256,10 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex PA_DEBUG(("PaAsio_Initialize: drv:%d defaultHighInputLatency = %f\n", i, deviceInfo->defaultHighInputLatency)); PA_DEBUG(("PaAsio_Initialize: drv:%d defaultHighOutputLatency = %f\n", i, deviceInfo->defaultHighOutputLatency)); - asioDeviceInfo->minBufferSize = paAsioDriverInfo.bufferMinSize; - asioDeviceInfo->maxBufferSize = paAsioDriverInfo.bufferMaxSize; - asioDeviceInfo->preferredBufferSize = paAsioDriverInfo.bufferPreferredSize; - asioDeviceInfo->bufferGranularity = paAsioDriverInfo.bufferGranularity; + asioDeviceInfo->minBufferSize = paAsioDriver.info.bufferMinSize; + asioDeviceInfo->maxBufferSize = paAsioDriver.info.bufferMaxSize; + asioDeviceInfo->preferredBufferSize = paAsioDriver.info.bufferPreferredSize; + asioDeviceInfo->bufferGranularity = paAsioDriver.info.bufferGranularity; asioDeviceInfo->asioChannelInfos = (ASIOChannelInfo*)PaUtil_GroupAllocateMemory( @@ -3046,7 +3053,7 @@ previousIndex = index; paTimeInfo.outputBufferDacTime = paTimeInfo.currentTime + theAsioStream->streamRepresentation.streamInfo.outputLatency; */ -/* Disabled! Stopping and re-starting the stream causes an input overflow / output undeflow. S.Fischer */ +/* Disabled! Stopping and re-starting the stream causes an input overflow / output underflow. S.Fischer */ #if 0 // detect underflows by checking inter-callback time > 2 buffer period static double previousTime = -1; @@ -3498,6 +3505,7 @@ static PaError IsStreamActive( PaStream *s ) static PaTime GetStreamTime( PaStream *s ) { (void) s; /* unused parameter */ + return (double)timeGetTime() * .001; } diff --git a/3rdparty/portaudio/src/hostapi/coreaudio/pa_mac_core.c b/3rdparty/portaudio/src/hostapi/coreaudio/pa_mac_core.c index 55ce9f0c0..339e2afa3 100644 --- a/3rdparty/portaudio/src/hostapi/coreaudio/pa_mac_core.c +++ b/3rdparty/portaudio/src/hostapi/coreaudio/pa_mac_core.c @@ -204,8 +204,40 @@ const char *PaMacCore_GetChannelName( int device, int channelIndex, bool input ) return channelName; } + +PaError PaMacCore_GetBufferSizeRange( PaDeviceIndex device, + long *minBufferSizeFrames, long *maxBufferSizeFrames ) +{ + PaError result; + PaUtilHostApiRepresentation *hostApi; + + result = PaUtil_GetHostApiRepresentation( &hostApi, paCoreAudio ); + + if( result == paNoError ) + { + PaDeviceIndex hostApiDeviceIndex; + result = PaUtil_DeviceIndexToHostApiDeviceIndex( &hostApiDeviceIndex, device, hostApi ); + if( result == paNoError ) + { + PaMacAUHAL *macCoreHostApi = (PaMacAUHAL*)hostApi; + AudioDeviceID macCoreDeviceId = macCoreHostApi->devIds[hostApiDeviceIndex]; + AudioValueRange audioRange; + UInt32 propSize = sizeof( audioRange ); + + // return the size range for the output scope unless we only have inputs + Boolean isInput = 0; + if( macCoreHostApi->inheritedHostApiRep.deviceInfos[hostApiDeviceIndex]->maxOutputChannels == 0 ) + isInput = 1; + + result = WARNING(AudioDeviceGetProperty( macCoreDeviceId, 0, isInput, kAudioDevicePropertyBufferFrameSizeRange, &propSize, &audioRange ) ); - + *minBufferSizeFrames = audioRange.mMinimum; + *maxBufferSizeFrames = audioRange.mMaximum; + } + } + + return result; +} AudioDeviceID PaMacCore_GetStreamInputDevice( PaStream* s ) @@ -1596,12 +1628,19 @@ static UInt32 CalculateOptimalBufferSize( PaMacAUHAL *auhalHostApi, resultBufferSizeFrames = MAX( resultBufferSizeFrames, (UInt32) variableLatencyFrames ); } + // can't have zero frames. code to round up to next user buffer requires non-zero + resultBufferSizeFrames = MAX( resultBufferSizeFrames, 1 ); + if( requestedFramesPerBuffer != paFramesPerBufferUnspecified ) { // make host buffer the next highest integer multiple of user frames per buffer UInt32 n = (resultBufferSizeFrames + requestedFramesPerBuffer - 1) / requestedFramesPerBuffer; resultBufferSizeFrames = n * requestedFramesPerBuffer; + + // FIXME: really we should be searching for a multiple of requestedFramesPerBuffer + // that is >= suggested latency and also fits within device buffer min/max + }else{ VDBUG( ("Block Size unspecified. Based on Latency, the user wants a Block Size near: %ld.\n", resultBufferSizeFrames ) ); diff --git a/3rdparty/portaudio/src/hostapi/dsound/pa_win_ds.c b/3rdparty/portaudio/src/hostapi/dsound/pa_win_ds.c index 11dd701cf..24c322bbe 100644 --- a/3rdparty/portaudio/src/hostapi/dsound/pa_win_ds.c +++ b/3rdparty/portaudio/src/hostapi/dsound/pa_win_ds.c @@ -1,5 +1,5 @@ /* - * $Id: pa_win_ds.c 1794 2011-11-24 18:11:33Z rossb $ + * $Id: pa_win_ds.c 1824 2012-04-02 07:45:18Z rbencina $ * Portable Audio I/O Library DirectSound implementation * * Authors: Phil Burk, Robert Marsanyi & Ross Bencina @@ -480,7 +480,7 @@ static PaError ExpandDSDeviceNameAndGUIDVector( DSDeviceNameAndGUIDVector *guidV else { newItems[i].lpGUID = &newItems[i].guid; - memcpy( &newItems[i].guid, guidVector->items[i].lpGUID, sizeof(GUID) );; + memcpy( &newItems[i].guid, guidVector->items[i].lpGUID, sizeof(GUID) ); } newItems[i].pnpInterface = guidVector->items[i].pnpInterface; } @@ -1167,6 +1167,8 @@ PaError PaWinDs_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInde goto error; } + memset( winDsHostApi, 0, sizeof(PaWinDsHostApiRepresentation) ); /* ensure all fields are zeroed. especially winDsHostApi->allocations */ + result = PaWinUtil_CoInitialize( paDirectSound, &winDsHostApi->comInitializationResult ); if( result != paNoError ) { @@ -1306,7 +1308,7 @@ error: TerminateDSDeviceNameAndGUIDVector( &deviceNamesAndGUIDs.inputNamesAndGUIDs ); TerminateDSDeviceNameAndGUIDVector( &deviceNamesAndGUIDs.outputNamesAndGUIDs ); - Terminate( winDsHostApi ); + Terminate( (struct PaUtilHostApiRepresentation *)winDsHostApi ); return result; } @@ -1703,9 +1705,9 @@ static void CalculateBufferSettings( unsigned long *hostBufferSizeFrames, unsigned long suggestedOutputLatencyFrames, double sampleRate, unsigned long userFramesPerBuffer ) { - unsigned long minimumPollingPeriodFrames = sampleRate * PA_DS_MINIMUM_POLLING_PERIOD_SECONDS; - unsigned long maximumPollingPeriodFrames = sampleRate * PA_DS_MAXIMUM_POLLING_PERIOD_SECONDS; - unsigned long pollingJitterFrames = sampleRate * PA_DS_POLLING_JITTER_SECONDS; + unsigned long minimumPollingPeriodFrames = (unsigned long)(sampleRate * PA_DS_MINIMUM_POLLING_PERIOD_SECONDS); + unsigned long maximumPollingPeriodFrames = (unsigned long)(sampleRate * PA_DS_MAXIMUM_POLLING_PERIOD_SECONDS); + unsigned long pollingJitterFrames = (unsigned long)(sampleRate * PA_DS_POLLING_JITTER_SECONDS); if( userFramesPerBuffer == paFramesPerBufferUnspecified ) { @@ -1771,9 +1773,9 @@ static void CalculatePollingPeriodFrames( unsigned long hostBufferSizeFrames, unsigned long *pollingPeriodFrames, double sampleRate, unsigned long userFramesPerBuffer ) { - unsigned long minimumPollingPeriodFrames = sampleRate * PA_DS_MINIMUM_POLLING_PERIOD_SECONDS; - unsigned long maximumPollingPeriodFrames = sampleRate * PA_DS_MAXIMUM_POLLING_PERIOD_SECONDS; - unsigned long pollingJitterFrames = sampleRate * PA_DS_POLLING_JITTER_SECONDS; + unsigned long minimumPollingPeriodFrames = (unsigned long)(sampleRate * PA_DS_MINIMUM_POLLING_PERIOD_SECONDS); + unsigned long maximumPollingPeriodFrames = (unsigned long)(sampleRate * PA_DS_MAXIMUM_POLLING_PERIOD_SECONDS); + unsigned long pollingJitterFrames = (unsigned long)(sampleRate * PA_DS_POLLING_JITTER_SECONDS); *pollingPeriodFrames = max( max(1, userFramesPerBuffer / 4), hostBufferSizeFrames / 16 ); @@ -2471,6 +2473,8 @@ static int TimeSlice( PaWinDsStream *stream ) framesToXfer = numOutFramesReady = bytesEmpty / stream->outputFrameSizeBytes; /* Check for underflow */ + /* FIXME QueryOutputSpace should not adjust underflow count as a side effect. + A query function should be a const operator on the stream and return a flag on underflow. */ if( stream->outputUnderflowCount != previousUnderflowCount ) stream->callbackFlags |= paOutputUnderflow; @@ -2536,7 +2540,7 @@ static int TimeSlice( PaWinDsStream *stream ) { /* We don't currently add outputLatency here because it appears to produce worse - results than non adding it. Need to do more testing to verify this. + results than not adding it. Need to do more testing to verify this. */ /* timeInfo.outputBufferDacTime = timeInfo.currentTime + outputLatency; */ timeInfo.outputBufferDacTime = timeInfo.currentTime; @@ -2729,7 +2733,7 @@ PA_THREAD_FUNC ProcessingThreadProc( void *pArg ) LARGE_INTEGER dueTime; int timerPeriodMs; - timerPeriodMs = stream->pollingPeriodSeconds * MSECS_PER_SECOND; + timerPeriodMs = (int)(stream->pollingPeriodSeconds * MSECS_PER_SECOND); if( timerPeriodMs < 1 ) timerPeriodMs = 1; @@ -2953,7 +2957,7 @@ static PaError StartStream( PaStream *s ) if( stream->streamRepresentation.streamCallback ) { TIMECAPS timecaps; - int timerPeriodMs = stream->pollingPeriodSeconds * MSECS_PER_SECOND; + int timerPeriodMs = (int)(stream->pollingPeriodSeconds * MSECS_PER_SECOND); if( timerPeriodMs < 1 ) timerPeriodMs = 1; @@ -2967,7 +2971,7 @@ static PaError StartStream( PaStream *s ) if( timeGetDevCaps( &timecaps, sizeof(TIMECAPS) == MMSYSERR_NOERROR && timecaps.wPeriodMin > 0 ) ) { /* aim for resolution 4 times higher than polling rate */ - stream->systemTimerResolutionPeriodMs = (stream->pollingPeriodSeconds * MSECS_PER_SECOND) / 4; + stream->systemTimerResolutionPeriodMs = (UINT)((stream->pollingPeriodSeconds * MSECS_PER_SECOND) * .25); if( stream->systemTimerResolutionPeriodMs < timecaps.wPeriodMin ) stream->systemTimerResolutionPeriodMs = timecaps.wPeriodMin; if( stream->systemTimerResolutionPeriodMs > timecaps.wPeriodMax ) diff --git a/3rdparty/portaudio/src/hostapi/wasapi/pa_win_wasapi.c b/3rdparty/portaudio/src/hostapi/wasapi/pa_win_wasapi.c index 0172e4714..3cb5ecc73 100644 --- a/3rdparty/portaudio/src/hostapi/wasapi/pa_win_wasapi.c +++ b/3rdparty/portaudio/src/hostapi/wasapi/pa_win_wasapi.c @@ -1065,6 +1065,8 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd result = paInsufficientMemory; goto error; } + + memset( paWasapi, 0, sizeof(PaWasapiHostApiRepresentation) ); /* ensure all fields are zeroed. especially paWasapi->allocations */ result = PaWinUtil_CoInitialize( paWASAPI, &paWasapi->comInitializationResult ); if( result != paNoError ) @@ -1248,7 +1250,7 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd goto error; } if (value.pwszVal) - wcstombs(deviceName, value.pwszVal, MAX_STR_LEN-1); + WideCharToMultiByte(CP_UTF8, 0, value.pwszVal, (int)wcslen(value.pwszVal), deviceName, MAX_STR_LEN-1, 0, 0); else _snprintf(deviceName, MAX_STR_LEN-1, "baddev%d", i); deviceInfo->name = deviceName; @@ -2211,11 +2213,15 @@ static HRESULT CreateAudioClient(PaWasapiStream *pStream, PaWasapiSubStream *pSu if (framesPerLatency == 0) framesPerLatency = MakeFramesFromHns(pInfo->DefaultDevicePeriod, pSub->wavex.Format.nSamplesPerSec); - //! Exclusive Input stream renders data in 6 packets, we must set then the size of - //! single packet, total buffer size, e.g. required latency will be PacketSize * 6 + // Exclusive Input stream renders data in 6 packets, we must set then the size of + // single packet, total buffer size, e.g. required latency will be PacketSize * 6 if (!output && (pSub->shareMode == AUDCLNT_SHAREMODE_EXCLUSIVE)) { - framesPerLatency /= WASAPI_PACKETS_PER_INPUT_BUFFER; + // Do it only for Polling mode + if ((pSub->streamFlags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) == 0) + { + framesPerLatency /= WASAPI_PACKETS_PER_INPUT_BUFFER; + } } // Calculate aligned period @@ -3460,7 +3466,7 @@ static PaError ReadStream( PaStream* s, void *_buffer, unsigned long frames ) // Limit desired to amount of requested frames desired = available; - if (desired > frames) + if ((UINT32)desired > frames) desired = frames; // Get pointers to read regions @@ -4795,13 +4801,15 @@ PA_THREAD_FUNC ProcThreadPoll(void *param) // output if (stream->bufferMode == paUtilFixedHostBufferSize) { - if (frames >= stream->out.framesPerBuffer) + while (frames >= stream->out.framesPerBuffer) { if ((hr = ProcessOutputBuffer(stream, processor, stream->out.framesPerBuffer)) != S_OK) { LogHostError(hr); goto thread_error; } + + frames -= stream->out.framesPerBuffer; } } else diff --git a/3rdparty/portaudio/src/hostapi/wdmks/pa_win_wdmks.c b/3rdparty/portaudio/src/hostapi/wdmks/pa_win_wdmks.c index 869cc4dac..4ab761a94 100644 --- a/3rdparty/portaudio/src/hostapi/wdmks/pa_win_wdmks.c +++ b/3rdparty/portaudio/src/hostapi/wdmks/pa_win_wdmks.c @@ -1,66 +1,70 @@ /* - * $Id: pa_win_wdmks.c 1606 2011-02-17 15:56:04Z rob_bielik $ - * PortAudio Windows WDM-KS interface - * - * Author: Andrew Baldwin - * Based on the Open Source API proposed by Ross Bencina - * Copyright (c) 1999-2004 Andrew Baldwin, Ross Bencina, Phil Burk - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ +* $Id: pa_win_wdmks.c 1820 2012-02-25 07:43:10Z robiwan $ +* PortAudio Windows WDM-KS interface +* +* Author: Andrew Baldwin, Robert Bielik (WaveRT) +* Based on the Open Source API proposed by Ross Bencina +* Copyright (c) 1999-2004 Andrew Baldwin, Ross Bencina, Phil Burk +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files +* (the "Software"), to deal in the Software without restriction, +* including without limitation the rights to use, copy, modify, merge, +* publish, distribute, sublicense, and/or sell copies of the Software, +* and to permit persons to whom the Software is furnished to do so, +* subject to the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ /* - * The text above constitutes the entire PortAudio license; however, - * the PortAudio community also makes the following non-binding requests: - * - * Any person wishing to distribute modifications to the Software is - * requested to send the modifications to the original developer so that - * they can be incorporated into the canonical version. It is also - * requested that these non-binding requests be included along with the - * license above. - */ +* The text above constitutes the entire PortAudio license; however, +* the PortAudio community also makes the following non-binding requests: +* +* Any person wishing to distribute modifications to the Software is +* requested to send the modifications to the original developer so that +* they can be incorporated into the canonical version. It is also +* requested that these non-binding requests be included along with the +* license above. +*/ /** @file - @ingroup hostapi_src - @brief Portaudio WDM-KS host API. +@ingroup hostapi_src +@brief Portaudio WDM-KS host API. - @note This is the implementation of the Portaudio host API using the - Windows WDM/Kernel Streaming API in order to enable very low latency - playback and recording on all modern Windows platforms (e.g. 2K, XP) - Note: This API accesses the device drivers below the usual KMIXER - component which is normally used to enable multi-client mixing and - format conversion. That means that it will lock out all other users - of a device for the duration of active stream using those devices +@note This is the implementation of the Portaudio host API using the +Windows WDM/Kernel Streaming API in order to enable very low latency +playback and recording on all modern Windows platforms (e.g. 2K, XP, Vista, Win7) +Note: This API accesses the device drivers below the usual KMIXER +component which is normally used to enable multi-client mixing and +format conversion. That means that it will lock out all other users +of a device for the duration of active stream using those devices */ #include +#if (defined(_WIN32) && (defined(_MSC_VER) && (_MSC_VER >= 1200))) /* MSC version 6 and above */ +#pragma comment( lib, "setupapi.lib" ) +#endif + /* Debugging/tracing support */ #define PA_LOGE_ #define PA_LOGL_ #ifdef __GNUC__ - #include - #define _WIN32_WINNT 0x0501 - #define WINVER 0x0501 +#include +#define _WIN32_WINNT 0x0501 +#define WINVER 0x0501 #endif #include /* strlen() */ @@ -74,70 +78,95 @@ #include "pa_process.h" #include "portaudio.h" #include "pa_debugprint.h" +#include "pa_memorybarrier.h" +#include "pa_ringbuffer.h" +#include "pa_trace.h" +#include "pa_win_waveformat.h" + +#include "pa_win_wdmks.h" #include #include #include +#include + +#ifdef _MSC_VER +#define snprintf _snprintf +#define vsnprintf _vsnprintf +#endif + +/* The PA_HP_TRACE macro is used in RT parts, so it can be switched off without affecting +the rest of the debug tracing */ +#if 1 +#define PA_HP_TRACE(x) PaUtil_AddHighSpeedLogMessage x ; +#else +#define PA_HP_TRACE(x) +#endif + +/* A define that selects whether the resulting pin names are chosen from pin category +instead of the available pin names, who sometimes can be quite cheesy, like "Volume control". +Default is to use the pin category. +*/ +#ifndef PA_WDMKS_USE_CATEGORY_FOR_PIN_NAMES +#define PA_WDMKS_USE_CATEGORY_FOR_PIN_NAMES 1 +#endif + #ifdef __GNUC__ - #undef PA_LOGE_ - #define PA_LOGE_ PA_DEBUG(("%s {\n",__FUNCTION__)) - #undef PA_LOGL_ - #define PA_LOGL_ PA_DEBUG(("} %s\n",__FUNCTION__)) - /* These defines are set in order to allow the WIndows DirectX - * headers to compile with a GCC compiler such as MinGW - * NOTE: The headers may generate a few warning in GCC, but - * they should compile */ - #define _INC_MMSYSTEM - #define _INC_MMREG - #define _NTRTL_ /* Turn off default definition of DEFINE_GUIDEX */ - #define DEFINE_GUID_THUNK(name,guid) DEFINE_GUID(name,guid) - #define DEFINE_GUIDEX(n) DEFINE_GUID_THUNK( n, STATIC_##n ) - #if !defined( DEFINE_WAVEFORMATEX_GUID ) - #define DEFINE_WAVEFORMATEX_GUID(x) (USHORT)(x), 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 - #endif - #define WAVE_FORMAT_ADPCM 0x0002 - #define WAVE_FORMAT_IEEE_FLOAT 0x0003 - #define WAVE_FORMAT_ALAW 0x0006 - #define WAVE_FORMAT_MULAW 0x0007 - #define WAVE_FORMAT_MPEG 0x0050 - #define WAVE_FORMAT_DRM 0x0009 - #define DYNAMIC_GUID_THUNK(l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} - #define DYNAMIC_GUID(data) DYNAMIC_GUID_THUNK(data) +#undef PA_LOGE_ +#define PA_LOGE_ PA_DEBUG(("%s {\n",__FUNCTION__)) +#undef PA_LOGL_ +#define PA_LOGL_ PA_DEBUG(("} %s\n",__FUNCTION__)) +/* These defines are set in order to allow the WIndows DirectX +* headers to compile with a GCC compiler such as MinGW +* NOTE: The headers may generate a few warning in GCC, but +* they should compile */ +#define _INC_MMSYSTEM +#define _INC_MMREG +#define _NTRTL_ /* Turn off default definition of DEFINE_GUIDEX */ +#define DEFINE_GUID_THUNK(name,guid) DEFINE_GUID(name,guid) +#define DEFINE_GUIDEX(n) DEFINE_GUID_THUNK( n, STATIC_##n ) +#if !defined( DEFINE_WAVEFORMATEX_GUID ) +#define DEFINE_WAVEFORMATEX_GUID(x) (USHORT)(x), 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 +#endif +#define WAVE_FORMAT_ADPCM 0x0002 +#define WAVE_FORMAT_IEEE_FLOAT 0x0003 +#define WAVE_FORMAT_ALAW 0x0006 +#define WAVE_FORMAT_MULAW 0x0007 +#define WAVE_FORMAT_MPEG 0x0050 +#define WAVE_FORMAT_DRM 0x0009 +#define DYNAMIC_GUID_THUNK(l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} +#define DYNAMIC_GUID(data) DYNAMIC_GUID_THUNK(data) #endif -#if (defined(WIN32) && (defined(_MSC_VER) && (_MSC_VER >= 1200))) /* MSC version 6 and above */ -#pragma comment( lib, "setupapi.lib" ) -#endif - -/* use CreateThread for CYGWIN, _beginthreadex for all others */ -#ifndef __CYGWIN__ -#define CREATE_THREAD (HANDLE)_beginthreadex( 0, 0, ProcessingThreadProc, stream, 0, &stream->processingThreadId ) +/* use CreateThread for CYGWIN/Windows Mobile, _beginthreadex for all others */ +#if !defined(__CYGWIN__) && !defined(_WIN32_WCE) +#define CREATE_THREAD_FUNCTION (HANDLE)_beginthreadex +#define PA_THREAD_FUNC static unsigned WINAPI #else -#define CREATE_THREAD CreateThread( 0, 0, ProcessingThreadProc, stream, 0, &stream->processingThreadId ) -#endif - -/* use ExitThread for CYGWIN, _endthreadex for all others */ -#ifndef __CYGWIN__ -#define EXIT_THREAD _endthreadex(0) -#else -#define EXIT_THREAD ExitThread(0) +#define CREATE_THREAD_FUNCTION CreateThread +#define PA_THREAD_FUNC static DWORD WINAPI #endif #ifdef _MSC_VER - //#define NOMMIDS - #define DYNAMIC_GUID(data) {data} - //#define _NTRTL_ /* Turn off default definition of DEFINE_GUIDEX */ - //#undef DEFINE_GUID - //#define DEFINE_GUID(n,data) EXTERN_C const GUID n = {data} - //#define DEFINE_GUID_THUNK(n,data) DEFINE_GUID(n,data) - //#define DEFINE_GUIDEX(n) DEFINE_GUID_THUNK(n, STATIC_##n) +#define NOMMIDS +#define DYNAMIC_GUID(data) {data} +#define _NTRTL_ /* Turn off default definition of DEFINE_GUIDEX */ +#undef DEFINE_GUID +#define DEFINE_GUID(n,data) EXTERN_C const GUID n = {data} +#define DEFINE_GUID_THUNK(n,data) DEFINE_GUID(n,data) +#define DEFINE_GUIDEX(n) DEFINE_GUID_THUNK(n, STATIC_##n) #endif +#include #include #include + +/* Note that Windows SDK V6.0A or later is needed for WaveRT specific structs to be present in + ksmedia.h. Also make sure that the SDK include path is before other include paths (that may contain + an "old" ksmedia.h), so the proper ksmedia.h is used */ #include -#include + #include #include @@ -146,17 +175,77 @@ typedef KSDDKAPI DWORD WINAPI KSCREATEPIN(HANDLE, PKSPIN_CONNECT, ACCESS_MASK, P extern HMODULE DllKsUser; extern KSCREATEPIN* FunctionKsCreatePin; +/* These definitions allows the use of AVRT.DLL on Vista and later OSs */ +extern HMODULE DllAvRt; +typedef HANDLE WINAPI AVSETMMTHREADCHARACTERISTICS(LPCSTR, LPDWORD TaskIndex); +typedef BOOL WINAPI AVREVERTMMTHREADCHARACTERISTICS(HANDLE); +typedef enum _PA_AVRT_PRIORITY +{ + PA_AVRT_PRIORITY_LOW = -1, + PA_AVRT_PRIORITY_NORMAL, + PA_AVRT_PRIORITY_HIGH, + PA_AVRT_PRIORITY_CRITICAL +} PA_AVRT_PRIORITY, *PPA_AVRT_PRIORITY; +typedef BOOL WINAPI AVSETMMTHREADPRIORITY(HANDLE, PA_AVRT_PRIORITY); +extern AVSETMMTHREADCHARACTERISTICS* FunctionAvSetMmThreadCharacteristics; +extern AVREVERTMMTHREADCHARACTERISTICS* FunctionAvRevertMmThreadCharacteristics; +extern AVSETMMTHREADPRIORITY* FunctionAvSetMmThreadPriority; + +/* An unspecified channel count (-1) is not treated correctly, so we replace it with +* an arbitrarily large number */ +#define MAXIMUM_NUMBER_OF_CHANNELS 256 + /* Forward definition to break circular type reference between pin and filter */ struct __PaWinWdmFilter; typedef struct __PaWinWdmFilter PaWinWdmFilter; +struct __PaWinWdmPin; +typedef struct __PaWinWdmPin PaWinWdmPin; + +struct __PaWinWdmStream; +typedef struct __PaWinWdmStream PaWinWdmStream; + +/* Function prototype for getting audio position */ +typedef PaError (*FunctionGetPinAudioPosition)(PaWinWdmPin*, unsigned long*); + +/* Function prototype for memory barrier */ +typedef void (*FunctionMemoryBarrier)(void); + +struct __PaProcessThreadInfo; +typedef struct __PaProcessThreadInfo PaProcessThreadInfo; + +typedef PaError (*FunctionPinHandler)(PaProcessThreadInfo* pInfo, unsigned eventIndex); + +typedef enum __PaStreamStartEnum +{ + StreamStart_kOk, + StreamStart_kFailed, + StreamStart_kCnt +} PaStreamStartEnum; + +/* Multiplexed input structure. +* Very often several physical inputs are multiplexed through a MUX node (represented in the topology filter) */ +typedef struct __PaWinWdmMuxedInput +{ + wchar_t friendlyName[MAX_PATH]; + ULONG muxPinId; + ULONG muxNodeId; + ULONG endpointPinId; +} PaWinWdmMuxedInput; + /* The Pin structure - * A pin is an input or output node, e.g. for audio flow */ -typedef struct __PaWinWdmPin +* A pin is an input or output node, e.g. for audio flow */ +struct __PaWinWdmPin { HANDLE handle; + PaWinWdmMuxedInput** inputs; + unsigned inputCount; + wchar_t friendlyName[MAX_PATH]; + PaWinWdmFilter* parentFilter; + PaWDMKSSubType pinKsSubType; unsigned long pinId; + unsigned long endpointPinId; /* For output pins */ KSPIN_CONNECT* pinConnect; unsigned long pinConnectSize; KSDATAFORMAT_WAVEFORMATEX* ksDataFormatWfx; @@ -168,26 +257,46 @@ typedef struct __PaWinWdmPin unsigned long frameSize; int maxChannels; unsigned long formats; - int bestSampleRate; -} -PaWinWdmPin; + int defaultSampleRate; + ULONG *positionRegister; /* WaveRT */ + ULONG hwLatency; /* WaveRT */ + FunctionMemoryBarrier fnMemBarrier; /* WaveRT */ + FunctionGetPinAudioPosition fnAudioPosition; /* WaveRT */ + FunctionPinHandler fnEventHandler; + FunctionPinHandler fnSubmitHandler; +}; /* The Filter structure - * A filter has a number of pins and a "friendly name" */ +* A filter has a number of pins and a "friendly name" */ struct __PaWinWdmFilter { HANDLE handle; + PaWinWDMKSDeviceInfo devInfo; /* This will hold information that is exposed in PaDeviceInfo */ + + DWORD deviceNode; int pinCount; PaWinWdmPin** pins; - TCHAR filterName[MAX_PATH]; - TCHAR friendlyName[MAX_PATH]; - int maxInputChannels; - int maxOutputChannels; - unsigned long formats; + PaWinWdmFilter* topologyFilter; + wchar_t friendlyName[MAX_PATH]; + int validPinCount; int usageCount; - int bestSampleRate; + KSMULTIPLE_ITEM* connections; + KSMULTIPLE_ITEM* nodes; + int filterRefCount; }; + +typedef struct __PaWinWdmDeviceInfo +{ + PaDeviceInfo inheritedDeviceInfo; + char compositeName[MAX_PATH]; /* Composite name consists of pin name + device name in utf8 */ + PaWinWdmFilter* filter; + unsigned long pin; + int muxPosition; /* Used only for input devices */ + int endpointPinId; +} +PaWinWdmDeviceInfo; + /* PaWinWdmHostApiRepresentation - host api datastructure specific to this implementation */ typedef struct __PaWinWdmHostApiRepresentation { @@ -196,63 +305,114 @@ typedef struct __PaWinWdmHostApiRepresentation PaUtilStreamInterface blockingStreamInterface; PaUtilAllocationGroup* allocations; - PaWinWdmFilter** filters; - int filterCount; + int deviceCount; } PaWinWdmHostApiRepresentation; -typedef struct __PaWinWdmDeviceInfo -{ - PaDeviceInfo inheritedDeviceInfo; - PaWinWdmFilter* filter; -} -PaWinWdmDeviceInfo; - typedef struct __DATAPACKET { KSSTREAM_HEADER Header; OVERLAPPED Signal; } DATAPACKET; +typedef struct __PaIOPacket +{ + DATAPACKET* packet; + unsigned startByte; + unsigned lengthBytes; +} PaIOPacket; + +typedef struct __PaWinWdmIOInfo +{ + PaWinWdmPin* pPin; + char* hostBuffer; + unsigned hostBufferSize; + unsigned framesPerBuffer; + unsigned bytesPerFrame; + unsigned bytesPerSample; + unsigned noOfPackets; /* Only used in WaveCyclic */ + HANDLE *events; /* noOfPackets handles (WaveCyclic) 1 (WaveRT) */ + DATAPACKET *packets; /* noOfPackets packets (WaveCyclic) 2 (WaveRT) */ + /* WaveRT polled mode */ + unsigned lastPosition; + unsigned pollCntr; +} PaWinWdmIOInfo; + /* PaWinWdmStream - a stream data structure specifically for this implementation */ -typedef struct __PaWinWdmStream +struct __PaWinWdmStream { PaUtilStreamRepresentation streamRepresentation; + PaWDMKSSpecificStreamInfo hostApiStreamInfo; /* This holds info that is exposed through PaStreamInfo */ PaUtilCpuLoadMeasurer cpuLoadMeasurer; PaUtilBufferProcessor bufferProcessor; - PaWinWdmPin* recordingPin; - PaWinWdmPin* playbackPin; - char* hostBuffer; - unsigned long framesPerHostIBuffer; - unsigned long framesPerHostOBuffer; - int bytesPerInputFrame; - int bytesPerOutputFrame; +#if PA_TRACE_REALTIME_EVENTS + LogHandle hLog; +#endif + + PaUtilAllocationGroup* allocGroup; + PaWinWdmIOInfo capture; + PaWinWdmIOInfo render; int streamStarted; int streamActive; int streamStop; int streamAbort; int oldProcessPriority; HANDLE streamThread; - HANDLE events[5]; /* 2 play + 2 record packets + abort events */ - DATAPACKET packets[4]; /* 2 play + 2 record */ + HANDLE eventAbort; + HANDLE eventStreamStart[StreamStart_kCnt]; /* 0 = OK, 1 = Failed */ + PaError threadResult; PaStreamFlags streamFlags; + + /* Capture ring buffer */ + PaUtilRingBuffer ringBuffer; + char* ringBufferData; + /* These values handle the case where the user wants to use fewer - * channels than the device has */ + * channels than the device has */ int userInputChannels; int deviceInputChannels; int userOutputChannels; int deviceOutputChannels; - int inputSampleSize; - int outputSampleSize; -} -PaWinWdmStream; +}; -#include +/* Gather all processing variables in a struct */ +struct __PaProcessThreadInfo +{ + PaWinWdmStream *stream; + PaStreamCallbackTimeInfo ti; + PaStreamCallbackFlags underover; + int cbResult; + volatile int pending; + volatile int priming; + volatile int pinsStarted; + unsigned long timeout; + unsigned captureHead; + unsigned captureTail; + unsigned renderHead; + unsigned renderTail; + PaIOPacket capturePackets[4]; + PaIOPacket renderPackets[4]; +}; + +/* Used for transferring device infos during scanning / rescanning */ +typedef struct __PaWinWDMScanDeviceInfosResults +{ + PaDeviceInfo **deviceInfos; + PaDeviceIndex defaultInputDevice; + PaDeviceIndex defaultOutputDevice; +} PaWinWDMScanDeviceInfosResults; + +static const unsigned cPacketsArrayMask = 3; HMODULE DllKsUser = NULL; KSCREATEPIN* FunctionKsCreatePin = NULL; +HMODULE DllAvRt = NULL; +AVSETMMTHREADCHARACTERISTICS* FunctionAvSetMmThreadCharacteristics = NULL; +AVREVERTMMTHREADCHARACTERISTICS* FunctionAvRevertMmThreadCharacteristics = NULL; +AVSETMMTHREADPRIORITY* FunctionAvSetMmThreadPriority = NULL; + /* prototypes for functions declared in this file */ #ifdef __cplusplus @@ -260,7 +420,7 @@ extern "C" { #endif /* __cplusplus */ -PaError PaWinWdm_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index ); + PaError PaWinWdm_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index ); #ifdef __cplusplus } @@ -268,37 +428,48 @@ PaError PaWinWdm_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd /* Low level I/O functions */ static PaError WdmSyncIoctl(HANDLE handle, - unsigned long ioctlNumber, - void* inBuffer, - unsigned long inBufferCount, - void* outBuffer, - unsigned long outBufferCount, - unsigned long* bytesReturned); + unsigned long ioctlNumber, + void* inBuffer, + unsigned long inBufferCount, + void* outBuffer, + unsigned long outBufferCount, + unsigned long* bytesReturned); static PaError WdmGetPropertySimple(HANDLE handle, - const GUID* const guidPropertySet, - unsigned long property, - void* value, - unsigned long valueCount, - void* instance, - unsigned long instanceCount); + const GUID* const guidPropertySet, + unsigned long property, + void* value, + unsigned long valueCount, + void* instance, + unsigned long instanceCount); static PaError WdmSetPropertySimple(HANDLE handle, - const GUID* const guidPropertySet, - unsigned long property, - void* value, - unsigned long valueCount, - void* instance, - unsigned long instanceCount); + const GUID* const guidPropertySet, + unsigned long property, + void* value, + unsigned long valueCount, + void* instance, + unsigned long instanceCount); + static PaError WdmGetPinPropertySimple(HANDLE handle, - unsigned long pinId, - const GUID* const guidPropertySet, - unsigned long property, - void* value, - unsigned long valueCount); + unsigned long pinId, + const GUID* const guidPropertySet, + unsigned long property, + void* value, + unsigned long valueCount, + unsigned long* byteCount); static PaError WdmGetPinPropertyMulti(HANDLE handle, - unsigned long pinId, - const GUID* const guidPropertySet, - unsigned long property, - KSMULTIPLE_ITEM** ksMultipleItem); + unsigned long pinId, + const GUID* const guidPropertySet, + unsigned long property, + KSMULTIPLE_ITEM** ksMultipleItem); +static PaError WdmGetPropertyMulti(HANDLE handle, + const GUID* const guidPropertySet, + unsigned long property, + KSMULTIPLE_ITEM** ksMultipleItem); + +static PaError WdmSetMuxNodeProperty(HANDLE handle, + ULONG nodeId, + ULONG pinId); + /** Pin management functions */ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, PaError* error); @@ -309,49 +480,47 @@ static PaError PinInstantiate(PaWinWdmPin* pin); static PaError PinSetState(PaWinWdmPin* pin, KSSTATE state); static PaError PinSetFormat(PaWinWdmPin* pin, const WAVEFORMATEX* format); static PaError PinIsFormatSupported(PaWinWdmPin* pin, const WAVEFORMATEX* format); +/* WaveRT support */ +static PaError PinQueryNotificationSupport(PaWinWdmPin* pPin, BOOL* pbResult); +static PaError PinGetBuffer(PaWinWdmPin* pPin, void** pBuffer, DWORD* pRequestedBufSize, BOOL* pbCallMemBarrier); +static PaError PinRegisterPositionRegister(PaWinWdmPin* pPin); +static PaError PinRegisterNotificationHandle(PaWinWdmPin* pPin, HANDLE handle); +static PaError PinUnregisterNotificationHandle(PaWinWdmPin* pPin, HANDLE handle); +static PaError PinGetHwLatency(PaWinWdmPin* pPin, ULONG* pFifoSize, ULONG* pChipsetDelay, ULONG* pCodecDelay); +static PaError PinGetAudioPositionDirect(PaWinWdmPin* pPin, ULONG* pPosition); +static PaError PinGetAudioPositionViaIOCTL(PaWinWdmPin* pPin, ULONG* pPosition); /* Filter management functions */ -static PaWinWdmFilter* FilterNew( - TCHAR* filterName, - TCHAR* friendlyName, - PaError* error); +static PaWinWdmFilter* FilterNew(PaWDMKSType type, DWORD devNode, const wchar_t* filterName, const wchar_t* friendlyName, PaError* error); +static PaError FilterInitializePins(PaWinWdmFilter* filter); static void FilterFree(PaWinWdmFilter* filter); -static PaWinWdmPin* FilterCreateRenderPin( - PaWinWdmFilter* filter, - const WAVEFORMATEX* wfex, - PaError* error); -static PaWinWdmPin* FilterFindViableRenderPin( - PaWinWdmFilter* filter, - const WAVEFORMATEX* wfex, - PaError* error); -static PaError FilterCanCreateRenderPin( - PaWinWdmFilter* filter, - const WAVEFORMATEX* wfex); -static PaWinWdmPin* FilterCreateCapturePin( - PaWinWdmFilter* filter, - const WAVEFORMATEX* wfex, - PaError* error); -static PaWinWdmPin* FilterFindViableCapturePin( - PaWinWdmFilter* filter, - const WAVEFORMATEX* wfex, - PaError* error); -static PaError FilterCanCreateCapturePin( - PaWinWdmFilter* filter, - const WAVEFORMATEX* pwfx); -static PaError FilterUse( - PaWinWdmFilter* filter); -static void FilterRelease( - PaWinWdmFilter* filter); +static void FilterAddRef(PaWinWdmFilter* filter); +static PaWinWdmPin* FilterCreatePin( + PaWinWdmFilter* filter, + int pinId, + const WAVEFORMATEX* wfex, + PaError* error); +static PaError FilterUse(PaWinWdmFilter* filter); +static void FilterRelease(PaWinWdmFilter* filter); + +/* Hot plug functions */ +static BOOL IsDeviceTheSame(const PaWinWdmDeviceInfo* pDev1, + const PaWinWdmDeviceInfo* pDev2); /* Interface functions */ static void Terminate( struct PaUtilHostApiRepresentation *hostApi ); static PaError IsFormatSupported( - struct PaUtilHostApiRepresentation *hostApi, +struct PaUtilHostApiRepresentation *hostApi, const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters, double sampleRate ); + +static PaError ScanDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex index, void **newDeviceInfos, int *newDeviceCount ); +static PaError CommitDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex index, void *deviceInfos, int deviceCount ); +static PaError DisposeDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, void *deviceInfos, int deviceCount ); + static PaError OpenStream( - struct PaUtilHostApiRepresentation *hostApi, +struct PaUtilHostApiRepresentation *hostApi, PaStream** s, const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters, @@ -369,27 +538,108 @@ static PaError IsStreamActive( PaStream *stream ); static PaTime GetStreamTime( PaStream *stream ); static double GetStreamCpuLoad( PaStream* stream ); static PaError ReadStream( - PaStream* stream, - void *buffer, - unsigned long frames ); + PaStream* stream, + void *buffer, + unsigned long frames ); static PaError WriteStream( - PaStream* stream, - const void *buffer, - unsigned long frames ); + PaStream* stream, + const void *buffer, + unsigned long frames ); static signed long GetStreamReadAvailable( PaStream* stream ); static signed long GetStreamWriteAvailable( PaStream* stream ); /* Utility functions */ static unsigned long GetWfexSize(const WAVEFORMATEX* wfex); -static PaError BuildFilterList(PaWinWdmHostApiRepresentation* wdmHostApi); +static PaWinWdmFilter** BuildFilterList(int* filterCount, int* noOfPaDevices, PaError* result); static BOOL PinWrite(HANDLE h, DATAPACKET* p); static BOOL PinRead(HANDLE h, DATAPACKET* p); static void DuplicateFirstChannelInt16(void* buffer, int channels, int samples); static void DuplicateFirstChannelInt24(void* buffer, int channels, int samples); -static DWORD WINAPI ProcessingThread(LPVOID pParam); +PA_THREAD_FUNC ProcessingThread(void*); + +/* Pin handler functions */ +static PaError PaPinCaptureEventHandler_WaveCyclic(PaProcessThreadInfo* pInfo, unsigned eventIndex); +static PaError PaPinCaptureSubmitHandler_WaveCyclic(PaProcessThreadInfo* pInfo, unsigned eventIndex); + +static PaError PaPinRenderEventHandler_WaveCyclic(PaProcessThreadInfo* pInfo, unsigned eventIndex); +static PaError PaPinRenderSubmitHandler_WaveCyclic(PaProcessThreadInfo* pInfo, unsigned eventIndex); + +static PaError PaPinCaptureEventHandler_WaveRTEvent(PaProcessThreadInfo* pInfo, unsigned eventIndex); +static PaError PaPinCaptureEventHandler_WaveRTPolled(PaProcessThreadInfo* pInfo, unsigned eventIndex); +static PaError PaPinCaptureSubmitHandler_WaveRTEvent(PaProcessThreadInfo* pInfo, unsigned eventIndex); +static PaError PaPinCaptureSubmitHandler_WaveRTPolled(PaProcessThreadInfo* pInfo, unsigned eventIndex); + +static PaError PaPinRenderEventHandler_WaveRTEvent(PaProcessThreadInfo* pInfo, unsigned eventIndex); +static PaError PaPinRenderEventHandler_WaveRTPolled(PaProcessThreadInfo* pInfo, unsigned eventIndex); +static PaError PaPinRenderSubmitHandler_WaveRTEvent(PaProcessThreadInfo* pInfo, unsigned eventIndex); +static PaError PaPinRenderSubmitHandler_WaveRTPolled(PaProcessThreadInfo* pInfo, unsigned eventIndex); /* Function bodies */ +#if defined(_DEBUG) && defined(PA_ENABLE_DEBUG_OUTPUT) +#define PA_WDMKS_SET_TREF +static PaTime tRef = 0; + +static void PaWinWdmDebugPrintf(const char* fmt, ...) +{ + va_list list; + char buffer[1024]; + PaTime t = PaUtil_GetTime() - tRef; + va_start(list, fmt); + _vsnprintf(buffer, 1023, fmt, list); + va_end(list); + PaUtil_DebugPrint("%6.3lf: %s", t, buffer); +} + +#ifdef PA_DEBUG +#undef PA_DEBUG +#define PA_DEBUG(x) PaWinWdmDebugPrintf x ; +#endif +#endif + +static BOOL IsDeviceTheSame(const PaWinWdmDeviceInfo* pDev1, + const PaWinWdmDeviceInfo* pDev2) +{ + if (pDev1 == NULL || pDev2 == NULL) + return FALSE; + + if (pDev1 == pDev2) + return TRUE; + + if (strcmp(pDev1->compositeName, pDev2->compositeName) == 0) + return TRUE; + + return FALSE; +} + +static BOOL IsEarlierThanVista() +{ + OSVERSIONINFO osvi; + osvi.dwOSVersionInfoSize = sizeof(osvi); + if (GetVersionEx(&osvi) && osvi.dwMajorVersion<6) + { + return TRUE; + } + return FALSE; +} + + + +static void MemoryBarrierDummy(void) +{ + /* Do nothing */ +} + +static void MemoryBarrierRead(void) +{ + PaUtil_ReadMemoryBarrier(); +} + +static void MemoryBarrierWrite(void) +{ + PaUtil_WriteMemoryBarrier(); +} + static unsigned long GetWfexSize(const WAVEFORMATEX* wfex) { if( wfex->wFormatTag == WAVE_FORMAT_PCM ) @@ -402,90 +652,67 @@ static unsigned long GetWfexSize(const WAVEFORMATEX* wfex) } } +static void PaWinWDM_SetLastErrorInfo(long errCode, const char* fmt, ...) +{ + va_list list; + char buffer[1024]; + va_start(list, fmt); + _vsnprintf(buffer, 1023, fmt, list); + va_end(list); + PaUtil_SetLastHostErrorInfo(paWDMKS, errCode, buffer); +} + /* Low level pin/filter access functions */ static PaError WdmSyncIoctl( - HANDLE handle, - unsigned long ioctlNumber, - void* inBuffer, - unsigned long inBufferCount, - void* outBuffer, - unsigned long outBufferCount, - unsigned long* bytesReturned) + HANDLE handle, + unsigned long ioctlNumber, + void* inBuffer, + unsigned long inBufferCount, + void* outBuffer, + unsigned long outBufferCount, + unsigned long* bytesReturned) { PaError result = paNoError; - OVERLAPPED overlapped; - int boolResult; - unsigned long dummyBytesReturned; - unsigned long error; + unsigned long dummyBytesReturned = 0; + BOOL bRes; if( !bytesReturned ) { - /* User a dummy as the caller hasn't supplied one */ + /* Use a dummy as the caller hasn't supplied one */ bytesReturned = &dummyBytesReturned; } - FillMemory((void *)&overlapped,sizeof(overlapped),0); - overlapped.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL); - if( !overlapped.hEvent ) + bRes = DeviceIoControl(handle, ioctlNumber, inBuffer, inBufferCount, outBuffer, outBufferCount, bytesReturned, NULL); + if (!bRes) { - result = paInsufficientMemory; - goto error; - } - overlapped.hEvent = (HANDLE)((DWORD_PTR)overlapped.hEvent | 0x1); - - boolResult = DeviceIoControl(handle, ioctlNumber, inBuffer, inBufferCount, - outBuffer, outBufferCount, bytesReturned, &overlapped); - if( !boolResult ) - { - error = GetLastError(); - if( error == ERROR_IO_PENDING ) - { - error = WaitForSingleObject(overlapped.hEvent,INFINITE); - if( error != WAIT_OBJECT_0 ) - { - result = paUnanticipatedHostError; - goto error; - } - } - else if((( error == ERROR_INSUFFICIENT_BUFFER ) || - ( error == ERROR_MORE_DATA )) && - ( ioctlNumber == IOCTL_KS_PROPERTY ) && - ( outBufferCount == 0 )) - { - boolResult = TRUE; - } - else + unsigned long error = GetLastError(); + if ( !(((error == ERROR_INSUFFICIENT_BUFFER ) || ( error == ERROR_MORE_DATA )) && + ( ioctlNumber == IOCTL_KS_PROPERTY ) && + ( outBufferCount == 0 ) ) ) { + PaWinWDM_SetLastErrorInfo(result, "WdmSyncIoctl: DeviceIoControl GLE = 0x%08X", error); result = paUnanticipatedHostError; } } - if( !boolResult ) - *bytesReturned = 0; - -error: - if( overlapped.hEvent ) - { - CloseHandle( overlapped.hEvent ); - } return result; } static PaError WdmGetPropertySimple(HANDLE handle, - const GUID* const guidPropertySet, - unsigned long property, - void* value, - unsigned long valueCount, - void* instance, - unsigned long instanceCount) + const GUID* const guidPropertySet, + unsigned long property, + void* value, + unsigned long valueCount, + void* instance, + unsigned long instanceCount) { PaError result; KSPROPERTY* ksProperty; unsigned long propertyCount; propertyCount = sizeof(KSPROPERTY) + instanceCount; - ksProperty = (KSPROPERTY*)PaUtil_AllocateMemory( propertyCount ); + ksProperty = (KSPROPERTY*)_alloca( propertyCount ); if( !ksProperty ) { return paInsufficientMemory; @@ -502,33 +729,32 @@ static PaError WdmGetPropertySimple(HANDLE handle, } result = WdmSyncIoctl( - handle, - IOCTL_KS_PROPERTY, - ksProperty, - propertyCount, - value, - valueCount, - NULL); + handle, + IOCTL_KS_PROPERTY, + ksProperty, + propertyCount, + value, + valueCount, + NULL); - PaUtil_FreeMemory( ksProperty ); return result; } static PaError WdmSetPropertySimple( - HANDLE handle, - const GUID* const guidPropertySet, - unsigned long property, - void* value, - unsigned long valueCount, - void* instance, - unsigned long instanceCount) + HANDLE handle, + const GUID* const guidPropertySet, + unsigned long property, + void* value, + unsigned long valueCount, + void* instance, + unsigned long instanceCount) { PaError result; KSPROPERTY* ksProperty; unsigned long propertyCount = 0; propertyCount = sizeof(KSPROPERTY) + instanceCount; - ksProperty = (KSPROPERTY*)PaUtil_AllocateMemory( propertyCount ); + ksProperty = (KSPROPERTY*)_alloca( propertyCount ); if( !ksProperty ) { return paInsufficientMemory; @@ -544,25 +770,25 @@ static PaError WdmSetPropertySimple( } result = WdmSyncIoctl( - handle, - IOCTL_KS_PROPERTY, - ksProperty, - propertyCount, - value, - valueCount, - NULL); + handle, + IOCTL_KS_PROPERTY, + ksProperty, + propertyCount, + value, + valueCount, + NULL); - PaUtil_FreeMemory( ksProperty ); return result; } static PaError WdmGetPinPropertySimple( - HANDLE handle, - unsigned long pinId, - const GUID* const guidPropertySet, - unsigned long property, - void* value, - unsigned long valueCount) + HANDLE handle, + unsigned long pinId, + const GUID* const guidPropertySet, + unsigned long property, + void* value, + unsigned long valueCount, + unsigned long *byteCount) { PaError result; @@ -574,23 +800,23 @@ static PaError WdmGetPinPropertySimple( ksPProp.Reserved = 0; result = WdmSyncIoctl( - handle, - IOCTL_KS_PROPERTY, - &ksPProp, - sizeof(KSP_PIN), - value, - valueCount, - NULL); + handle, + IOCTL_KS_PROPERTY, + &ksPProp, + sizeof(KSP_PIN), + value, + valueCount, + byteCount); return result; } static PaError WdmGetPinPropertyMulti( - HANDLE handle, - unsigned long pinId, - const GUID* const guidPropertySet, - unsigned long property, - KSMULTIPLE_ITEM** ksMultipleItem) + HANDLE handle, + unsigned long pinId, + const GUID* const guidPropertySet, + unsigned long property, + KSMULTIPLE_ITEM** ksMultipleItem) { PaError result; unsigned long multipleItemSize = 0; @@ -603,13 +829,13 @@ static PaError WdmGetPinPropertyMulti( ksPProp.Reserved = 0; result = WdmSyncIoctl( - handle, - IOCTL_KS_PROPERTY, - &ksPProp.Property, - sizeof(KSP_PIN), - NULL, - 0, - &multipleItemSize); + handle, + IOCTL_KS_PROPERTY, + &ksPProp.Property, + sizeof(KSP_PIN), + NULL, + 0, + &multipleItemSize); if( result != paNoError ) { return result; @@ -622,13 +848,13 @@ static PaError WdmGetPinPropertyMulti( } result = WdmSyncIoctl( - handle, - IOCTL_KS_PROPERTY, - &ksPProp, - sizeof(KSP_PIN), - (void*)*ksMultipleItem, - multipleItemSize, - NULL); + handle, + IOCTL_KS_PROPERTY, + &ksPProp, + sizeof(KSP_PIN), + (void*)*ksMultipleItem, + multipleItemSize, + NULL); if( result != paNoError ) { @@ -638,6 +864,398 @@ static PaError WdmGetPinPropertyMulti( return result; } +static PaError WdmGetPropertyMulti(HANDLE handle, + const GUID* const guidPropertySet, + unsigned long property, + KSMULTIPLE_ITEM** ksMultipleItem) +{ + PaError result; + unsigned long multipleItemSize = 0; + KSPROPERTY ksProp; + + ksProp.Set = *guidPropertySet; + ksProp.Id = property; + ksProp.Flags = KSPROPERTY_TYPE_GET; + + result = WdmSyncIoctl( + handle, + IOCTL_KS_PROPERTY, + &ksProp, + sizeof(KSPROPERTY), + NULL, + 0, + &multipleItemSize); + if( result != paNoError ) + { + return result; + } + + *ksMultipleItem = (KSMULTIPLE_ITEM*)PaUtil_AllocateMemory( multipleItemSize ); + if( !*ksMultipleItem ) + { + return paInsufficientMemory; + } + + result = WdmSyncIoctl( + handle, + IOCTL_KS_PROPERTY, + &ksProp, + sizeof(KSPROPERTY), + (void*)*ksMultipleItem, + multipleItemSize, + NULL); + + if( result != paNoError ) + { + PaUtil_FreeMemory( ksMultipleItem ); + } + + return result; +} + +static PaError WdmSetMuxNodeProperty(HANDLE handle, + ULONG nodeId, + ULONG pinId) +{ + PaError result = paNoError; + KSNODEPROPERTY prop; + prop.Property.Set = KSPROPSETID_Audio; + prop.Property.Id = KSPROPERTY_AUDIO_MUX_SOURCE; + prop.Property.Flags = KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_TOPOLOGY; + prop.NodeId = nodeId; + prop.Reserved = 0; + + result = WdmSyncIoctl(handle, IOCTL_KS_PROPERTY, &prop, sizeof(KSNODEPROPERTY), &pinId, sizeof(ULONG), NULL); + + return result; +} + +/* Used when traversing topology for outputs */ +static const KSTOPOLOGY_CONNECTION* GetConnectionTo(const KSTOPOLOGY_CONNECTION* pFrom, PaWinWdmFilter* filter, int muxIdx) +{ + unsigned i; + const KSTOPOLOGY_CONNECTION* retval = NULL; + const KSTOPOLOGY_CONNECTION* connections = (const KSTOPOLOGY_CONNECTION*)(filter->connections + 1); + (void)muxIdx; + PA_DEBUG(("GetConnectionTo: Checking %u connections... (pFrom = %p)", filter->connections->Count, pFrom)); + for (i = 0; i < filter->connections->Count; ++i) + { + const KSTOPOLOGY_CONNECTION* pConn = connections + i; + if (pConn == pFrom) + continue; + + if (pConn->FromNode == pFrom->ToNode) + { + retval = pConn; + break; + } + } + PA_DEBUG(("GetConnectionTo: Returning %p\n", retval)); + return retval; +} + +/* Used when traversing topology for inputs */ +static const KSTOPOLOGY_CONNECTION* GetConnectionFrom(const KSTOPOLOGY_CONNECTION* pTo, PaWinWdmFilter* filter, int muxIdx) +{ + unsigned i; + const KSTOPOLOGY_CONNECTION* retval = NULL; + const KSTOPOLOGY_CONNECTION* connections = (const KSTOPOLOGY_CONNECTION*)(filter->connections + 1); + int muxCntr = 0; + PA_DEBUG(("GetConnectionFrom: Checking %u connections... (pTo = %p)\n", filter->connections->Count, pTo)); + for (i = 0; i < filter->connections->Count; ++i) + { + const KSTOPOLOGY_CONNECTION* pConn = connections + i; + if (pConn == pTo) + continue; + + if (pConn->ToNode == pTo->FromNode) + { + if (muxIdx >= 0) + { + if (muxCntr < muxIdx) + { + ++muxCntr; + continue; + } + } + retval = pConn; + break; + } + } + PA_DEBUG(("GetConnectionFrom: Returning %p\n", retval)); + return retval; +} + +static ULONG GetNumberOfConnectionsTo(const KSTOPOLOGY_CONNECTION* pTo, PaWinWdmFilter* filter) +{ + ULONG retval = 0; + unsigned i; + const KSTOPOLOGY_CONNECTION* connections = (const KSTOPOLOGY_CONNECTION*)(filter->connections + 1); + PA_DEBUG(("GetNumberOfConnectionsTo: Checking %u connections...", filter->connections->Count)); + for (i = 0; i < filter->connections->Count; ++i) + { + const KSTOPOLOGY_CONNECTION* pConn = connections + i; + if (pConn->ToNode == pTo->FromNode && + (pTo->FromNode != KSFILTER_NODE || pConn->ToNodePin == pTo->FromNodePin)) + { + ++retval; + } + } + return retval; +} + +typedef const KSTOPOLOGY_CONNECTION *(*TFnGetConnection)(const KSTOPOLOGY_CONNECTION*, PaWinWdmFilter*, int); + +static const KSTOPOLOGY_CONNECTION* FindStartConnectionFrom(ULONG startPin, PaWinWdmFilter* filter) +{ + unsigned i; + const KSTOPOLOGY_CONNECTION* connections = (const KSTOPOLOGY_CONNECTION*)(filter->connections + 1); + PA_DEBUG(("FindStartConnectionFrom: Checking %u connections...", filter->connections->Count)); + for (i = 0; i < filter->connections->Count; ++i) + { + const KSTOPOLOGY_CONNECTION* pConn = connections + i; + if (pConn->ToNode == KSFILTER_NODE && pConn->ToNodePin == startPin) + { + return pConn; + } + } + + assert(FALSE); + return 0; +} + +static const KSTOPOLOGY_CONNECTION* FindStartConnectionTo(ULONG startPin, PaWinWdmFilter* filter) +{ + unsigned i; + const KSTOPOLOGY_CONNECTION* connections = (const KSTOPOLOGY_CONNECTION*)(filter->connections + 1); + PA_DEBUG(("FindStartConnectionTo: Checking %u connections...", filter->connections->Count)); + for (i = 0; i < filter->connections->Count; ++i) + { + const KSTOPOLOGY_CONNECTION* pConn = connections + i; + if (pConn->FromNode == KSFILTER_NODE && pConn->FromNodePin == startPin) + { + return pConn; + } + } + + assert(FALSE); + return 0; +} + +static ULONG GetConnectedPin(ULONG startPin, BOOL forward, PaWinWdmFilter* filter, int muxPosition, ULONG *muxInputPinId, ULONG *muxNodeId) +{ + const KSTOPOLOGY_CONNECTION *conn = NULL; + TFnGetConnection fnGetConnection = forward ? GetConnectionTo : GetConnectionFrom ; + while (1) + { + if (conn == NULL) + { + conn = forward ? FindStartConnectionTo(startPin, filter) : FindStartConnectionFrom(startPin, filter); + } + else + { + conn = fnGetConnection(conn, filter, -1); + } + + /* Handling case of erroneous connection list */ + if (conn == NULL) + { + break; + } + + if (forward ? conn->ToNode == KSFILTER_NODE : conn->FromNode == KSFILTER_NODE) + { + return forward ? conn->ToNodePin : conn->FromNodePin; + } + else + { + PA_DEBUG(("GetConnectedPin: count=%d, forward=%d, muxPosition=%d\n", filter->nodes->Count, forward, muxPosition)); + if (filter->nodes->Count > 0 && !forward && muxPosition >= 0) + { + const GUID* nodes = (const GUID*)(filter->nodes + 1); + if (IsEqualGUID(&nodes[conn->FromNode], &KSNODETYPE_MUX)) + { + ULONG nConn = GetNumberOfConnectionsTo(conn, filter); + conn = fnGetConnection(conn, filter, muxPosition); + if (conn == NULL) + { + break; + } + if (muxInputPinId != 0) + { + *muxInputPinId = conn->ToNodePin; + } + if (muxNodeId != 0) + { + *muxNodeId = conn->ToNode; + } + } + } + } + } + return KSFILTER_NODE; +} + +static void DumpConnectionsAndNodes(PaWinWdmFilter* filter) +{ + unsigned i; + const KSTOPOLOGY_CONNECTION* connections = (const KSTOPOLOGY_CONNECTION*)(filter->connections + 1); + const GUID* nodes = (const GUID*)(filter->nodes + 1); + + PA_DEBUG(("DumpConnectionsAndNodes: connections=%d, nodes=%d\n", filter->connections->Count, filter->nodes->Count)); + + for (i=0; i < filter->connections->Count; ++i) + { + const KSTOPOLOGY_CONNECTION* pConn = connections + i; + PA_DEBUG((" Connection: %u - FromNode=%u,FromPin=%u -> ToNode=%u,ToPin=%u\n", + i, + pConn->FromNode, pConn->FromNodePin, + pConn->ToNode, pConn->ToNodePin + )); + } + + for (i=0; i < filter->nodes->Count; ++i) + { + const GUID* pConn = nodes + i; + PA_DEBUG((" Node: %d - {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n", + i, + pConn->Data1, pConn->Data2, pConn->Data3, + pConn->Data4[0], pConn->Data4[1], + pConn->Data4[2], pConn->Data4[3], + pConn->Data4[4], pConn->Data4[5], + pConn->Data4[6], pConn->Data4[7] + )); + } + +} + +typedef struct __PaUsbTerminalGUIDToName +{ + USHORT usbGUID; + wchar_t name[64]; +} PaUsbTerminalGUIDToName; + +static const PaUsbTerminalGUIDToName kNames[] = +{ + /* Types copied from: http://msdn.microsoft.com/en-us/library/ff537742(v=vs.85).aspx */ + /* Input terminal types */ + { 0x0201, L"Microphone" }, + { 0x0202, L"Desktop Microphone" }, + { 0x0203, L"Personal Microphone" }, + { 0x0204, L"Omni Directional Microphone" }, + { 0x0205, L"Microphone Array" }, + { 0x0206, L"Processing Microphone Array" }, + /* Output terminal types */ + { 0x0301, L"Speakers" }, + { 0x0302, L"Headphones" }, + { 0x0303, L"Head Mounted Display Audio" }, + { 0x0304, L"Desktop Speaker" }, + { 0x0305, L"Room Speaker" }, + { 0x0306, L"Communication Speaker" }, + { 0x0307, L"LFE Speakers" }, + /* External terminal types */ + { 0x0601, L"Analog" }, + { 0x0602, L"Digital" }, + { 0x0603, L"Line" }, + { 0x0604, L"Audio" }, + { 0x0605, L"SPDIF" }, +}; + +static const unsigned kNamesCnt = sizeof(kNames)/sizeof(PaUsbTerminalGUIDToName); + +static int PaUsbTerminalGUIDToNameCmp(const void* lhs, const void* rhs) +{ + const PaUsbTerminalGUIDToName* pL = (const PaUsbTerminalGUIDToName*)lhs; + const PaUsbTerminalGUIDToName* pR = (const PaUsbTerminalGUIDToName*)rhs; + return ((int)(pL->usbGUID) - (int)(pR->usbGUID)); +} + +static PaError GetNameFromCategory(const GUID* pGUID, BOOL input, wchar_t* name, unsigned length) +{ + PaError result = paUnanticipatedHostError; + USHORT usbTerminalGUID = (USHORT)(pGUID->Data1 - 0xDFF219E0); + + if (input && usbTerminalGUID >= 0x301 && usbTerminalGUID < 0x400) + { + /* Output terminal name for an input !? Set it to Line! */ + usbTerminalGUID = 0x603; + } + if (!input && usbTerminalGUID >= 0x201 && usbTerminalGUID < 0x300) + { + /* Input terminal name for an output !? Set it to Line! */ + usbTerminalGUID = 0x603; + } + if (usbTerminalGUID >= 0x201 && usbTerminalGUID < 0x713) + { + PaUsbTerminalGUIDToName s = { usbTerminalGUID }; + const PaUsbTerminalGUIDToName* ptr = bsearch( + &s, + kNames, + kNamesCnt, + sizeof(PaUsbTerminalGUIDToName), + PaUsbTerminalGUIDToNameCmp + ); + if (ptr != 0) + { + PA_DEBUG(("GetNameFromCategory: USB GUID %04X -> '%S'\n", usbTerminalGUID, ptr->name)); + + if (name != NULL && length > 0) + { + int n = _snwprintf(name, length, L"%s", ptr->name); + if (usbTerminalGUID >= 0x601 && usbTerminalGUID < 0x700) + { + _snwprintf(name + n, length - n, L" %s", (input ? L"In":L"Out")); + } + } + result = paNoError; + } + } + else + { + PaWinWDM_SetLastErrorInfo(result, "GetNameFromCategory: usbTerminalGUID = %04X ", usbTerminalGUID); + } + return result; +} + +static BOOL IsFrequencyWithinRange(const KSDATARANGE_AUDIO* range, int frequency) +{ + if (frequency < (int)range->MinimumSampleFrequency) + return FALSE; + if (frequency > (int)range->MaximumSampleFrequency) + return FALSE; + return TRUE; +} + +static BOOL IsBitsWithinRange(const KSDATARANGE_AUDIO* range, int noOfBits) +{ + if (noOfBits < (int)range->MinimumBitsPerSample) + return FALSE; + if (noOfBits > (int)range->MaximumBitsPerSample) + return FALSE; + return TRUE; +} + +/* Note: Somewhat different order compared to WMME implementation, as we want to focus on fidelity first */ +static const int defaultSampleRateSearchOrder[] = +{ 44100, 48000, 88200, 96000, 192000, 32000, 24000, 22050, 16000, 12000, 11025, 9600, 8000 }; +static const int defaultSampleRateSearchOrderCount = sizeof(defaultSampleRateSearchOrder)/sizeof(defaultSampleRateSearchOrder[0]); + +static int DefaultSampleFrequencyIndex(const KSDATARANGE_AUDIO* range) +{ + int i; + + for(i=0; i < defaultSampleRateSearchOrderCount; ++i) + { + int currentFrequency = defaultSampleRateSearchOrder[i]; + + if (IsFrequencyWithinRange(range, currentFrequency)) + { + return i; + } + } + + return -1; +} /* Create a new pin object belonging to a filter @@ -652,9 +1270,11 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa KSMULTIPLE_ITEM* item = NULL; KSIDENTIFIER* identifier; KSDATARANGE* dataRange; + const ULONG streamingId = (parentFilter->devInfo.streamingType == Type_kWaveRT) ? KSINTERFACE_STANDARD_LOOPED_STREAMING : KSINTERFACE_STANDARD_STREAMING; + int defaultSampleRateIndex = defaultSampleRateSearchOrderCount; PA_LOGE_; - PA_DEBUG(("Creating pin %d:\n",pinId)); + PA_DEBUG(("PinNew: Creating pin %d:\n",pinId)); /* Allocate the new PIN object */ pin = (PaWinWdmPin*)PaUtil_AllocateMemory( sizeof(PaWinWdmPin) ); @@ -681,7 +1301,7 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa /* Configure the connect structure with default values */ pin->pinConnect->Interface.Set = KSINTERFACESETID_Standard; - pin->pinConnect->Interface.Id = KSINTERFACE_STANDARD_STREAMING; + pin->pinConnect->Interface.Id = streamingId; pin->pinConnect->Interface.Flags = 0; pin->pinConnect->Medium.Set = KSMEDIUMSETID_Standard; pin->pinConnect->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE; @@ -707,15 +1327,16 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa &KSPROPSETID_Pin, KSPROPERTY_PIN_COMMUNICATION, &pin->communication, - sizeof(KSPIN_COMMUNICATION)); + sizeof(KSPIN_COMMUNICATION), + NULL); if( result != paNoError ) goto error; if( /*(pin->communication != KSPIN_COMMUNICATION_SOURCE) &&*/ - (pin->communication != KSPIN_COMMUNICATION_SINK) && - (pin->communication != KSPIN_COMMUNICATION_BOTH) ) + (pin->communication != KSPIN_COMMUNICATION_SINK) && + (pin->communication != KSPIN_COMMUNICATION_BOTH) ) { - PA_DEBUG(("Not source/sink\n")); + PA_DEBUG(("PinNew: Not source/sink\n")); result = paInvalidDevice; goto error; } @@ -727,7 +1348,8 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa &KSPROPSETID_Pin, KSPROPERTY_PIN_DATAFLOW, &pin->dataFlow, - sizeof(KSPIN_DATAFLOW)); + sizeof(KSPIN_DATAFLOW), + NULL); if( result != paNoError ) goto error; @@ -749,8 +1371,7 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa result = paUnanticipatedHostError; for( i = 0; i < item->Count; i++ ) { - if( !memcmp( (void*)&identifier[i].Set, (void*)&KSINTERFACESETID_Standard, sizeof( GUID ) ) && - ( identifier[i].Id == KSINTERFACE_STANDARD_STREAMING ) ) + if( IsEqualGUID(&identifier[i].Set, &KSINTERFACESETID_Standard) && ( identifier[i].Id == streamingId ) ) { result = paNoError; break; @@ -759,7 +1380,7 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa if( result != paNoError ) { - PA_DEBUG(("No standard streaming\n")); + PA_DEBUG(("PinNew: No %s streaming\n", streamingId==KSINTERFACE_STANDARD_LOOPED_STREAMING?"looped":"standard")); goto error; } @@ -784,8 +1405,7 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa result = paUnanticipatedHostError; for( i = 0; i < item->Count; i++ ) { - if( !memcmp( (void*)&identifier[i].Set, (void*)&KSMEDIUMSETID_Standard, sizeof( GUID ) ) && - ( identifier[i].Id == KSMEDIUM_STANDARD_DEVIO ) ) + if( IsEqualGUID(&identifier[i].Set, &KSMEDIUMSETID_Standard) && ( identifier[i].Id == KSMEDIUM_STANDARD_DEVIO ) ) { result = paNoError; break; @@ -818,53 +1438,66 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa result = paUnanticipatedHostError; dataRange = pin->dataRanges; pin->maxChannels = 0; - pin->bestSampleRate = 0; + pin->defaultSampleRate = 0; pin->formats = 0; - for( i = 0; i dataRangesItem->Count; i++) + PA_DEBUG(("PinNew: Checking %u no of dataranges...\n", pin->dataRangesItem->Count)); + for( i = 0; i < pin->dataRangesItem->Count; i++) { - PA_DEBUG(("DR major format %x\n",*(unsigned long*)(&(dataRange->MajorFormat)))); + PA_DEBUG(("PinNew: DR major format %x\n",*(unsigned long*)(&(dataRange->MajorFormat)))); /* Check that subformat is WAVEFORMATEX, PCM or WILDCARD */ if( IS_VALID_WAVEFORMATEX_GUID(&dataRange->SubFormat) || - !memcmp((void*)&dataRange->SubFormat, (void*)&KSDATAFORMAT_SUBTYPE_PCM, sizeof ( GUID ) ) || - ( !memcmp((void*)&dataRange->SubFormat, (void*)&KSDATAFORMAT_SUBTYPE_WILDCARD, sizeof ( GUID ) ) && - ( !memcmp((void*)&dataRange->MajorFormat, (void*)&KSDATAFORMAT_TYPE_AUDIO, sizeof ( GUID ) ) ) ) ) + IsEqualGUID(&dataRange->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM) || + IsEqualGUID(&dataRange->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) || + IsEqualGUID(&dataRange->SubFormat, &KSDATAFORMAT_SUBTYPE_WILDCARD) || + IsEqualGUID(&dataRange->MajorFormat, &KSDATAFORMAT_TYPE_AUDIO) ) { + int defaultIndex; result = paNoError; /* Record the maximum possible channels with this pin */ - PA_DEBUG(("MaxChannel: %d\n",pin->maxChannels)); - if( (int)((KSDATARANGE_AUDIO*)dataRange)->MaximumChannels > pin->maxChannels ) + if( ((KSDATARANGE_AUDIO*)dataRange)->MaximumChannels == (ULONG) -1 ) { - pin->maxChannels = ((KSDATARANGE_AUDIO*)dataRange)->MaximumChannels; - /*PA_DEBUG(("MaxChannel: %d\n",pin->maxChannels));*/ + pin->maxChannels = MAXIMUM_NUMBER_OF_CHANNELS; } + else if( (int) ((KSDATARANGE_AUDIO*)dataRange)->MaximumChannels > pin->maxChannels ) + { + pin->maxChannels = (int) ((KSDATARANGE_AUDIO*)dataRange)->MaximumChannels; + } + PA_DEBUG(("PinNew: MaxChannel: %d\n",pin->maxChannels)); + /* Record the formats (bit depths) that are supported */ - if( ((KSDATARANGE_AUDIO*)dataRange)->MinimumBitsPerSample <= 16 ) + if( IsBitsWithinRange((KSDATARANGE_AUDIO*)dataRange, 8) ) + { + pin->formats |= paInt8; + PA_DEBUG(("PinNew: Format PCM 8 bit supported\n")); + } + if( IsBitsWithinRange((KSDATARANGE_AUDIO*)dataRange, 16) ) { pin->formats |= paInt16; - PA_DEBUG(("Format 16 bit supported\n")); + PA_DEBUG(("PinNew: Format PCM 16 bit supported\n")); } - if( ((KSDATARANGE_AUDIO*)dataRange)->MaximumBitsPerSample >= 24 ) + if( IsBitsWithinRange((KSDATARANGE_AUDIO*)dataRange, 24) ) { pin->formats |= paInt24; - PA_DEBUG(("Format 24 bit supported\n")); + PA_DEBUG(("PinNew: Format PCM 24 bit supported\n")); } - if( ( pin->bestSampleRate != 48000) && - (((KSDATARANGE_AUDIO*)dataRange)->MaximumSampleFrequency >= 48000) && - (((KSDATARANGE_AUDIO*)dataRange)->MinimumSampleFrequency <= 48000) ) + if( IsBitsWithinRange((KSDATARANGE_AUDIO*)dataRange, 32) ) { - pin->bestSampleRate = 48000; - PA_DEBUG(("48kHz supported\n")); + if (IsEqualGUID(&dataRange->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) + { + pin->formats |= paFloat32; + PA_DEBUG(("PinNew: Format IEEE float 32 bit supported\n")); + } + else + { + pin->formats |= paInt32; + PA_DEBUG(("PinNew: Format PCM 32 bit supported\n")); + } } - else if(( pin->bestSampleRate != 48000) && ( pin->bestSampleRate != 44100 ) && - (((KSDATARANGE_AUDIO*)dataRange)->MaximumSampleFrequency >= 44100) && - (((KSDATARANGE_AUDIO*)dataRange)->MinimumSampleFrequency <= 44100) ) + + defaultIndex = DefaultSampleFrequencyIndex((KSDATARANGE_AUDIO*)dataRange); + if (defaultIndex >= 0 && defaultIndex < defaultSampleRateIndex) { - pin->bestSampleRate = 44100; - PA_DEBUG(("44.1kHz supported\n")); - } - else - { - pin->bestSampleRate = ((KSDATARANGE_AUDIO*)dataRange)->MaximumSampleFrequency; + defaultSampleRateIndex = defaultIndex; } } dataRange = (KSDATARANGE*)( ((char*)dataRange) + dataRange->FormatSize); @@ -873,6 +1506,19 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa if( result != paNoError ) goto error; + /* If none of the frequencies searched for are present, there's something seriously wrong */ + if (defaultSampleRateIndex == defaultSampleRateSearchOrderCount) + { + PA_DEBUG(("PinNew: No default sample rate found, skipping pin!\n")); + PaWinWDM_SetLastErrorInfo(paUnanticipatedHostError, "PinNew: No default sample rate found"); + result = paUnanticipatedHostError; + goto error; + } + + /* Set the default sample rate */ + pin->defaultSampleRate = defaultSampleRateSearchOrder[defaultSampleRateIndex]; + PA_DEBUG(("PinNew: Default sample rate = %d Hz\n", pin->defaultSampleRate)); + /* Get instance information */ result = WdmGetPinPropertySimple( parentFilter->handle, @@ -880,11 +1526,413 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa &KSPROPSETID_Pin, KSPROPERTY_PIN_CINSTANCES, &pin->instances, - sizeof(KSPIN_CINSTANCES)); + sizeof(KSPIN_CINSTANCES), + NULL); if( result != paNoError ) goto error; + /* If WaveRT, check if pin supports notification mode */ + if (parentFilter->devInfo.streamingType == Type_kWaveRT) + { + BOOL bSupportsNotification = FALSE; + if (PinQueryNotificationSupport(pin, &bSupportsNotification) == paNoError) + { + pin->pinKsSubType = bSupportsNotification ? SubType_kNotification : SubType_kPolled; + } + } + + /* Query pin name (which means we need to traverse to non IRP pin, via physical connection to topology filter pin, through + its nodes to the endpoint pin, and get that ones name... phew...) */ + PA_DEBUG(("PinNew: Finding topology pin...\n")); + + { + ULONG topoPinId = GetConnectedPin(pinId, (pin->dataFlow == KSPIN_DATAFLOW_IN), parentFilter, -1, NULL, NULL); + const wchar_t kInputName[] = L"Input"; + const wchar_t kOutputName[] = L"Output"; + + if (topoPinId != KSFILTER_NODE) + { + /* Get physical connection for topo pin */ + unsigned long cbBytes = 0; + PA_DEBUG(("PinNew: Getting physical connection...\n")); + result = WdmGetPinPropertySimple(parentFilter->handle, + topoPinId, + &KSPROPSETID_Pin, + KSPROPERTY_PIN_PHYSICALCONNECTION, + 0, + 0, + &cbBytes + ); + + if (result != paNoError) + { + /* No physical connection -> there is no topology filter! So we get the name of the pin! */ + PA_DEBUG(("PinNew: No physical connection! Getting the pin name\n")); + result = WdmGetPinPropertySimple(parentFilter->handle, + topoPinId, + &KSPROPSETID_Pin, + KSPROPERTY_PIN_NAME, + pin->friendlyName, + MAX_PATH, + NULL); + if (result != paNoError) + { + GUID category = {0}; + + /* Get pin category information */ + result = WdmGetPinPropertySimple(parentFilter->handle, + topoPinId, + &KSPROPSETID_Pin, + KSPROPERTY_PIN_CATEGORY, + &category, + sizeof(GUID), + NULL); + + if (result == paNoError) + { + result = GetNameFromCategory(&category, (pin->dataFlow == KSPIN_DATAFLOW_OUT), pin->friendlyName, MAX_PATH); + } + } + + /* Make sure pin gets a name here... */ + if (wcslen(pin->friendlyName) == 0) + { + wcscpy(pin->friendlyName, (pin->dataFlow == KSPIN_DATAFLOW_IN) ? kOutputName : kInputName); +#ifdef UNICODE + PA_DEBUG(("PinNew: Setting pin friendly name to '%s'\n", pin->friendlyName)); +#else + PA_DEBUG(("PinNew: Setting pin friendly name to '%S'\n", pin->friendlyName)); +#endif + } + + /* This is then == the endpoint pin */ + pin->endpointPinId = (pin->dataFlow == KSPIN_DATAFLOW_IN) ? pinId : topoPinId; + } + else + { + KSPIN_PHYSICALCONNECTION* pc = (KSPIN_PHYSICALCONNECTION*)PaUtil_AllocateMemory(cbBytes + 2); + PA_DEBUG(("PinNew: Physical connection found!\n")); + if (pc == NULL) + { + result = paInsufficientMemory; + goto error; + } + result = WdmGetPinPropertySimple(parentFilter->handle, + topoPinId, + &KSPROPSETID_Pin, + KSPROPERTY_PIN_PHYSICALCONNECTION, + pc, + cbBytes, + NULL + ); + if (result == paNoError) + { + wchar_t symbLinkName[MAX_PATH]; + wcsncpy(symbLinkName, pc->SymbolicLinkName, MAX_PATH); + if (symbLinkName[1] == TEXT('?')) + { + symbLinkName[1] = TEXT('\\'); + } + + if (pin->parentFilter->topologyFilter == NULL) + { + PA_DEBUG(("PinNew: Creating topology filter '%S'\n", symbLinkName)); + + pin->parentFilter->topologyFilter = FilterNew(Type_kNotUsed, 0, symbLinkName, L"", &result); + if (pin->parentFilter->topologyFilter == NULL) + { + PA_DEBUG(("PinNew: Failed creating topology filter\n")); + result = paUnanticipatedHostError; + PaWinWDM_SetLastErrorInfo(result, "Failed to create topology filter '%S'", symbLinkName); + goto error; + } + + /* Copy info so we have it in device info */ + wcsncpy(pin->parentFilter->devInfo.topologyPath, symbLinkName, MAX_PATH); + } + else + { + /* Must be the same */ + assert(wcscmp(symbLinkName, pin->parentFilter->topologyFilter->devInfo.filterPath) == 0); + } + + PA_DEBUG(("PinNew: Opening topology filter...")); + + result = FilterUse(pin->parentFilter->topologyFilter); + if (result == paNoError) + { + unsigned long endpointPinId; + + if (pin->dataFlow == KSPIN_DATAFLOW_IN) + { + /* The "endpointPinId" is what WASAPI looks at for pin names */ + GUID category = {0}; + + PA_DEBUG(("PinNew: Checking for output endpoint pin id...\n")); + + endpointPinId = GetConnectedPin(pc->Pin, TRUE, pin->parentFilter->topologyFilter, -1, NULL, NULL); + + if (endpointPinId == KSFILTER_NODE) + { + result = paUnanticipatedHostError; + PaWinWDM_SetLastErrorInfo(result, "Failed to get endpoint pin ID on topology filter!"); + goto error; + } + + PA_DEBUG(("PinNew: Found endpoint pin id %u\n", endpointPinId)); + + /* Get pin category information */ + result = WdmGetPinPropertySimple(pin->parentFilter->topologyFilter->handle, + endpointPinId, + &KSPROPSETID_Pin, + KSPROPERTY_PIN_CATEGORY, + &category, + sizeof(GUID), + NULL); + + if (result == paNoError) + { +#if !PA_WDMKS_USE_CATEGORY_FOR_PIN_NAMES + wchar_t pinName[MAX_PATH]; + + PA_DEBUG(("PinNew: Getting pin name property...")); + + /* Ok, try pin name also, and favor that if available */ + result = WdmGetPinPropertySimple(pin->parentFilter->topologyFilter->handle, + endpointPinId, + &KSPROPSETID_Pin, + KSPROPERTY_PIN_NAME, + pinName, + MAX_PATH, + NULL); + + if (result == paNoError && wcslen(pinName)>0) + { + wcsncpy(pin->friendlyName, pinName, MAX_PATH); + } + else +#endif + { + result = GetNameFromCategory(&category, (pin->dataFlow == KSPIN_DATAFLOW_OUT), pin->friendlyName, MAX_PATH); + } + + if (wcslen(pin->friendlyName) == 0) + { + wcscpy(pin->friendlyName, L"Output"); + } +#ifdef UNICODE + PA_DEBUG(("PinNew: Pin name '%s'\n", pin->friendlyName)); +#else + PA_DEBUG(("PinNew: Pin name '%S'\n", pin->friendlyName)); +#endif + } + + /* Set endpoint pin ID (this is the topology INPUT pin, since portmixer will always traverse the + filter in audio streaming direction, see http://msdn.microsoft.com/en-us/library/windows/hardware/ff536331(v=vs.85).aspx + for more information) + */ + pin->endpointPinId = pc->Pin; + } + else + { + unsigned muxCount = 0; + int muxPos = 0; + /* Max 64 multiplexer inputs... sanity check :) */ + for (i = 0; i < 64; ++i) + { + ULONG muxNodeIdTest = (unsigned)-1; + PA_DEBUG(("PinNew: Checking for input endpoint pin id (%d)...\n", i)); + + endpointPinId = GetConnectedPin(pc->Pin, + FALSE, + pin->parentFilter->topologyFilter, + (int)i, + NULL, + &muxNodeIdTest); + + + if (endpointPinId == KSFILTER_NODE) + { + /* We're done */ + PA_DEBUG(("PinNew: Done with inputs.\n", endpointPinId)); + break; + } + else + { + /* The "endpointPinId" is what WASAPI looks at for pin names */ + GUID category = {0}; + + PA_DEBUG(("PinNew: Found endpoint pin id %u\n", endpointPinId)); + + /* Get pin category information */ + result = WdmGetPinPropertySimple(pin->parentFilter->topologyFilter->handle, + endpointPinId, + &KSPROPSETID_Pin, + KSPROPERTY_PIN_CATEGORY, + &category, + sizeof(GUID), + NULL); + + if (result == paNoError) + { + if (muxNodeIdTest == (unsigned)-1) + { + /* Ok, try pin name, and favor that if available */ + result = WdmGetPinPropertySimple(pin->parentFilter->topologyFilter->handle, + endpointPinId, + &KSPROPSETID_Pin, + KSPROPERTY_PIN_NAME, + pin->friendlyName, + MAX_PATH, + NULL); + + if (result != paNoError) + { + result = GetNameFromCategory(&category, TRUE, pin->friendlyName, MAX_PATH); + } + break; + } + else + { + result = GetNameFromCategory(&category, TRUE, NULL, 0); + + if (result == paNoError) + { + ++muxCount; + } + } + } + else + { + PA_DEBUG(("PinNew: Failed to get pin category")); + } + } + } + + if (muxCount == 0) + { + pin->endpointPinId = endpointPinId; + /* Make sure we get a name for the pin */ + if (wcslen(pin->friendlyName) == 0) + { + wcscpy(pin->friendlyName, kInputName); + } +#ifdef UNICODE + PA_DEBUG(("PinNew: Input friendly name '%s'\n", pin->friendlyName)); +#else + PA_DEBUG(("PinNew: Input friendly name '%S'\n", pin->friendlyName)); +#endif + } + else // muxCount > 0 + { + PA_DEBUG(("PinNew: Setting up %u inputs\n", muxCount)); + + /* Now we redo the operation once known how many multiplexer positions there are */ + pin->inputs = (PaWinWdmMuxedInput**)PaUtil_AllocateMemory(muxCount * sizeof(PaWinWdmMuxedInput*)); + if (pin->inputs == NULL) + { + FilterRelease(pin->parentFilter->topologyFilter); + result = paInsufficientMemory; + goto error; + } + pin->inputCount = muxCount; + + for (i = 0; i < muxCount; ++muxPos) + { + PA_DEBUG(("PinNew: Setting up input %u...\n", i)); + + if (pin->inputs[i] == NULL) + { + pin->inputs[i] = (PaWinWdmMuxedInput*)PaUtil_AllocateMemory(sizeof(PaWinWdmMuxedInput)); + if (pin->inputs[i] == NULL) + { + FilterRelease(pin->parentFilter->topologyFilter); + result = paInsufficientMemory; + goto error; + } + } + + endpointPinId = GetConnectedPin(pc->Pin, + FALSE, + pin->parentFilter->topologyFilter, + muxPos, + &pin->inputs[i]->muxPinId, + &pin->inputs[i]->muxNodeId); + + if (endpointPinId != KSFILTER_NODE) + { + /* The "endpointPinId" is what WASAPI looks at for pin names */ + GUID category = {0}; + + /* Set input endpoint ID */ + pin->inputs[i]->endpointPinId = endpointPinId; + + /* Get pin category information */ + result = WdmGetPinPropertySimple(pin->parentFilter->topologyFilter->handle, + endpointPinId, + &KSPROPSETID_Pin, + KSPROPERTY_PIN_CATEGORY, + &category, + sizeof(GUID), + NULL); + + if (result == paNoError) + { + /* Try pin name first, and if that is not defined, use category instead */ + result = WdmGetPinPropertySimple(pin->parentFilter->topologyFilter->handle, + endpointPinId, + &KSPROPSETID_Pin, + KSPROPERTY_PIN_NAME, + pin->inputs[i]->friendlyName, + MAX_PATH, + NULL); + + if (result != paNoError) + { + result = GetNameFromCategory(&category, TRUE, pin->inputs[i]->friendlyName, MAX_PATH); + if (result != paNoError) + { + /* Only specify name, let name hash in ScanDeviceInfos fix postfix enumerators */ + wcscpy(pin->inputs[i]->friendlyName, kInputName); + } + } +#ifdef UNICODE + PA_DEBUG(("PinNew: Input (%u) friendly name '%s'\n", i, pin->inputs[i]->friendlyName)); +#else + PA_DEBUG(("PinNew: Input (%u) friendly name '%S'\n", i, pin->inputs[i]->friendlyName)); +#endif + ++i; + } + } + else + { + /* Should never come here! */ + assert(FALSE); + } + } + } + } + } + } + PaUtil_FreeMemory(pc); + } + } + else + { + PA_DEBUG(("PinNew: No topology pin id found. Bad...\n")); + /* No TOPO pin id ??? This is bad. Ok, so we just say it is an input or output... */ + wcscpy(pin->friendlyName, (pin->dataFlow == KSPIN_DATAFLOW_IN) ? kOutputName : kInputName); + } + } + + /* Release topology filter if it has been used */ + if (pin->parentFilter->topologyFilter && pin->parentFilter->topologyFilter->handle != NULL) + { + PA_DEBUG(("PinNew: Releasing topology filter...\n")); + FilterRelease(pin->parentFilter->topologyFilter); + } + /* Success */ *error = paNoError; PA_DEBUG(("Pin created successfully\n")); @@ -892,12 +1940,19 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa return pin; error: + PA_DEBUG(("PinNew: Error %d\n", result)); /* Error cleanup */ + PaUtil_FreeMemory( item ); if( pin ) { + if (pin->parentFilter->topologyFilter && pin->parentFilter->topologyFilter->handle != NULL) + { + FilterRelease(pin->parentFilter->topologyFilter); + } + PaUtil_FreeMemory( pin->pinConnect ); PaUtil_FreeMemory( pin->dataRangesItem ); PaUtil_FreeMemory( pin ); @@ -912,6 +1967,7 @@ Safely free all resources associated with the pin */ static void PinFree(PaWinWdmPin* pin) { + unsigned i; PA_LOGE_; if( pin ) { @@ -924,6 +1980,14 @@ static void PinFree(PaWinWdmPin* pin) { PaUtil_FreeMemory( pin->dataRangesItem ); } + if( pin->inputs ) + { + for (i = 0; i < pin->inputCount; ++i) + { + PaUtil_FreeMemory( pin->inputs[i] ); + } + PaUtil_FreeMemory( pin->inputs ); + } PaUtil_FreeMemory( pin ); } PA_LOGL_; @@ -957,22 +2021,21 @@ Set the state of this (instantiated) pin */ static PaError PinSetState(PaWinWdmPin* pin, KSSTATE state) { - PaError result; + PaError result = paNoError; + KSPROPERTY prop; PA_LOGE_; + prop.Set = KSPROPSETID_Connection; + prop.Id = KSPROPERTY_CONNECTION_STATE; + prop.Flags = KSPROPERTY_TYPE_SET; + if( pin == NULL ) return paInternalError; if( pin->handle == NULL ) return paInternalError; - result = WdmSetPropertySimple( - pin->handle, - &KSPROPSETID_Connection, - KSPROPERTY_CONNECTION_STATE, - &state, - sizeof(state), - NULL, - 0); + result = WdmSyncIoctl(pin->handle, IOCTL_KS_PROPERTY, &prop, sizeof(KSPROPERTY), &state, sizeof(KSSTATE), NULL); + PA_LOGL_; return result; } @@ -1000,41 +2063,56 @@ static PaError PinInstantiate(PaWinWdmPin* pin) &pin->handle ); - PA_DEBUG(("Pin create result = %x\n",createResult)); + PA_DEBUG(("Pin create result = 0x%08x\n",createResult)); if( createResult != ERROR_SUCCESS ) { FilterRelease(pin->parentFilter); pin->handle = NULL; - return paInvalidDevice; + switch (createResult) + { + case ERROR_INVALID_PARAMETER: + /* First case when pin actually don't support the format */ + return paSampleFormatNotSupported; + case ERROR_BAD_COMMAND: + /* Case when pin is occupied (by another application) */ + return paDeviceUnavailable; + default: + /* All other cases */ + return paInvalidDevice; + } } - result = WdmGetPropertySimple( - pin->handle, - &KSPROPSETID_Connection, - KSPROPERTY_CONNECTION_ALLOCATORFRAMING, - &ksaf, - sizeof(ksaf), - NULL, - 0); - - if( result != paNoError ) + if (pin->parentFilter->devInfo.streamingType == Type_kWaveCyclic) { + /* Framing size query only valid for WaveCyclic devices */ result = WdmGetPropertySimple( pin->handle, &KSPROPSETID_Connection, - KSPROPERTY_CONNECTION_ALLOCATORFRAMING_EX, - &ksafex, - sizeof(ksafex), + KSPROPERTY_CONNECTION_ALLOCATORFRAMING, + &ksaf, + sizeof(ksaf), NULL, 0); - if( result == paNoError ) + + if( result != paNoError ) { - pin->frameSize = ksafex.FramingItem[0].FramingRange.Range.MinFrameSize; + result = WdmGetPropertySimple( + pin->handle, + &KSPROPSETID_Connection, + KSPROPERTY_CONNECTION_ALLOCATORFRAMING_EX, + &ksafex, + sizeof(ksafex), + NULL, + 0); + if( result == paNoError ) + { + pin->frameSize = ksafex.FramingItem[0].FramingRange.Range.MinFrameSize; + } + } + else + { + pin->frameSize = ksaf.FrameSize; } - } - else - { - pin->frameSize = ksaf.FrameSize; } PA_LOGL_; @@ -1042,30 +2120,6 @@ static PaError PinInstantiate(PaWinWdmPin* pin) return paNoError; } -/* NOT USED -static PaError PinGetState(PaWinWdmPin* pin, KSSTATE* state) -{ - PaError result; - - if( state == NULL ) - return paInternalError; - if( pin == NULL ) - return paInternalError; - if( pin->handle == NULL ) - return paInternalError; - - result = WdmGetPropertySimple( - pin->handle, - KSPROPSETID_Connection, - KSPROPERTY_CONNECTION_STATE, - state, - sizeof(KSSTATE), - NULL, - 0); - - return result; -} -*/ static PaError PinSetFormat(PaWinWdmPin* pin, const WAVEFORMATEX* format) { unsigned long size; @@ -1107,65 +2161,285 @@ static PaError PinIsFormatSupported(PaWinWdmPin* pin, const WAVEFORMATEX* format unsigned long count; GUID guid = DYNAMIC_GUID( DEFINE_WAVEFORMATEX_GUID(format->wFormatTag) ); PaError result = paInvalidDevice; + const WAVEFORMATEXTENSIBLE* pFormatExt = (format->wFormatTag == WAVE_FORMAT_EXTENSIBLE) ? (const WAVEFORMATEXTENSIBLE*)format : 0; PA_LOGE_; - if( format->wFormatTag == WAVE_FORMAT_EXTENSIBLE ) + if( pFormatExt != 0 ) { - guid = ((WAVEFORMATEXTENSIBLE*)format)->SubFormat; + guid = pFormatExt->SubFormat; } dataRange = (KSDATARANGE_AUDIO*)pin->dataRanges; - for(count = 0; countdataRangesItem->Count; count++) + for(count = 0; + countdataRangesItem->Count; + count++, + dataRange = (KSDATARANGE_AUDIO*)( ((char*)dataRange) + dataRange->DataRange.FormatSize)) /* Need to update dataRange here, due to 'continue' !! */ { - if(( !memcmp(&(dataRange->DataRange.MajorFormat),&KSDATAFORMAT_TYPE_AUDIO,sizeof(GUID)) ) || - ( !memcmp(&(dataRange->DataRange.MajorFormat),&KSDATAFORMAT_TYPE_WILDCARD,sizeof(GUID)) )) + /* Check major format*/ + if (!(IsEqualGUID(&(dataRange->DataRange.MajorFormat), &KSDATAFORMAT_TYPE_AUDIO) || + IsEqualGUID(&(dataRange->DataRange.MajorFormat), &KSDATAFORMAT_TYPE_WILDCARD))) { - /* This is an audio or wildcard datarange... */ - if(( !memcmp(&(dataRange->DataRange.SubFormat),&KSDATAFORMAT_SUBTYPE_WILDCARD,sizeof(GUID)) ) || - ( !memcmp(&(dataRange->DataRange.SubFormat),&guid,sizeof(GUID)) )) + continue; + } + + /* This is an audio or wildcard datarange... */ + if (! (IsEqualGUID(&(dataRange->DataRange.SubFormat), &KSDATAFORMAT_SUBTYPE_WILDCARD) || + IsEqualGUID(&(dataRange->DataRange.SubFormat), &KSDATAFORMAT_SUBTYPE_PCM) || + IsEqualGUID(&(dataRange->DataRange.SubFormat), &guid) )) + { + continue; + } + + /* Check specifier... */ + if (! (IsEqualGUID(&(dataRange->DataRange.Specifier), &KSDATAFORMAT_SPECIFIER_WILDCARD) || + IsEqualGUID(&(dataRange->DataRange.Specifier), &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)) ) + { + continue; + } + + PA_DEBUG(("Pin:%x, DataRange:%d\n",(void*)pin,count)); + PA_DEBUG(("\tFormatSize:%d, SampleSize:%d\n",dataRange->DataRange.FormatSize,dataRange->DataRange.SampleSize)); + PA_DEBUG(("\tMaxChannels:%d\n",dataRange->MaximumChannels)); + PA_DEBUG(("\tBits:%d-%d\n",dataRange->MinimumBitsPerSample,dataRange->MaximumBitsPerSample)); + PA_DEBUG(("\tSampleRate:%d-%d\n",dataRange->MinimumSampleFrequency,dataRange->MaximumSampleFrequency)); + + if( dataRange->MaximumChannels != (ULONG)-1 && + dataRange->MaximumChannels < format->nChannels ) + { + result = paInvalidChannelCount; + continue; + } + + if (pFormatExt != 0) + { + if ( dataRange->MinimumBitsPerSample > pFormatExt->Samples.wValidBitsPerSample ) { - if(( !memcmp(&(dataRange->DataRange.Specifier),&KSDATAFORMAT_SPECIFIER_WILDCARD,sizeof(GUID)) ) || - ( !memcmp(&(dataRange->DataRange.Specifier),&KSDATAFORMAT_SPECIFIER_WAVEFORMATEX,sizeof(GUID) ))) - { - - PA_DEBUG(("Pin:%x, DataRange:%d\n",(void*)pin,count)); - PA_DEBUG(("\tFormatSize:%d, SampleSize:%d\n",dataRange->DataRange.FormatSize,dataRange->DataRange.SampleSize)); - PA_DEBUG(("\tMaxChannels:%d\n",dataRange->MaximumChannels)); - PA_DEBUG(("\tBits:%d-%d\n",dataRange->MinimumBitsPerSample,dataRange->MaximumBitsPerSample)); - PA_DEBUG(("\tSampleRate:%d-%d\n",dataRange->MinimumSampleFrequency,dataRange->MaximumSampleFrequency)); - - if( dataRange->MaximumChannels < format->nChannels ) - { - result = paInvalidChannelCount; - continue; - } - if( dataRange->MinimumBitsPerSample > format->wBitsPerSample ) - { - result = paSampleFormatNotSupported; - continue; - } - if( dataRange->MaximumBitsPerSample < format->wBitsPerSample ) - { - result = paSampleFormatNotSupported; - continue; - } - if( dataRange->MinimumSampleFrequency > format->nSamplesPerSec ) - { - result = paInvalidSampleRate; - continue; - } - if( dataRange->MaximumSampleFrequency < format->nSamplesPerSec ) - { - result = paInvalidSampleRate; - continue; - } - /* Success! */ - PA_LOGL_; - return paNoError; - } + result = paSampleFormatNotSupported; + continue; + } + if ( dataRange->MaximumBitsPerSample < pFormatExt->Samples.wValidBitsPerSample ) + { + result = paSampleFormatNotSupported; + continue; } } - dataRange = (KSDATARANGE_AUDIO*)( ((char*)dataRange) + dataRange->DataRange.FormatSize); + else + { + if( dataRange->MinimumBitsPerSample > format->wBitsPerSample ) + { + result = paSampleFormatNotSupported; + continue; + } + + if( dataRange->MaximumBitsPerSample < format->wBitsPerSample ) + { + result = paSampleFormatNotSupported; + continue; + } + } + + if( dataRange->MinimumSampleFrequency > format->nSamplesPerSec ) + { + result = paInvalidSampleRate; + continue; + } + + if( dataRange->MaximumSampleFrequency < format->nSamplesPerSec ) + { + result = paInvalidSampleRate; + continue; + } + + /* Success! */ + result = paNoError; + break; + } + + PA_LOGL_; + return result; +} + +static PaError PinQueryNotificationSupport(PaWinWdmPin* pPin, BOOL* pbResult) +{ + PaError result = paNoError; + KSPROPERTY propIn; + + propIn.Set = KSPROPSETID_RtAudio; + propIn.Id = 8; /* = KSPROPERTY_RTAUDIO_QUERY_NOTIFICATION_SUPPORT */ + propIn.Flags = KSPROPERTY_TYPE_GET; + + result = WdmSyncIoctl(pPin->handle, IOCTL_KS_PROPERTY, + &propIn, + sizeof(KSPROPERTY), + pbResult, + sizeof(BOOL), + NULL); + + if (result != paNoError) + { + PA_DEBUG(("Failed PinQueryNotificationSupport\n")); + } + + return result; + +} + +static PaError PinGetBufferWithNotification(PaWinWdmPin* pPin, void** pBuffer, DWORD* pRequestedBufSize, BOOL* pbCallMemBarrier) +{ + PaError result = paNoError; + KSRTAUDIO_BUFFER_PROPERTY_WITH_NOTIFICATION propIn; + KSRTAUDIO_BUFFER propOut; + + propIn.BaseAddress = 0; + propIn.NotificationCount = 2; + propIn.RequestedBufferSize = *pRequestedBufSize; + propIn.Property.Set = KSPROPSETID_RtAudio; + propIn.Property.Id = KSPROPERTY_RTAUDIO_BUFFER_WITH_NOTIFICATION; + propIn.Property.Flags = KSPROPERTY_TYPE_GET; + + result = WdmSyncIoctl(pPin->handle, IOCTL_KS_PROPERTY, + &propIn, + sizeof(KSRTAUDIO_BUFFER_PROPERTY_WITH_NOTIFICATION), + &propOut, + sizeof(KSRTAUDIO_BUFFER), + NULL); + + if (result == paNoError) + { + *pBuffer = propOut.BufferAddress; + *pRequestedBufSize = propOut.ActualBufferSize; + *pbCallMemBarrier = propOut.CallMemoryBarrier; + } + else + { + PA_DEBUG(("Failed to get buffer with notification\n")); + } + + return result; +} + +static PaError PinGetBufferWithoutNotification(PaWinWdmPin* pPin, void** pBuffer, DWORD* pRequestedBufSize, BOOL* pbCallMemBarrier) +{ + PaError result = paNoError; + KSRTAUDIO_BUFFER_PROPERTY propIn; + KSRTAUDIO_BUFFER propOut; + + propIn.BaseAddress = NULL; + propIn.RequestedBufferSize = *pRequestedBufSize; + propIn.Property.Set = KSPROPSETID_RtAudio; + propIn.Property.Id = KSPROPERTY_RTAUDIO_BUFFER; + propIn.Property.Flags = KSPROPERTY_TYPE_GET; + + result = WdmSyncIoctl(pPin->handle, IOCTL_KS_PROPERTY, + &propIn, + sizeof(KSRTAUDIO_BUFFER_PROPERTY), + &propOut, + sizeof(KSRTAUDIO_BUFFER), + NULL); + + if (result == paNoError) + { + *pBuffer = propOut.BufferAddress; + *pRequestedBufSize = propOut.ActualBufferSize; + *pbCallMemBarrier = propOut.CallMemoryBarrier; + } + else + { + PA_DEBUG(("Failed to get buffer without notification\n")); + } + + return result; +} + +/* greatest common divisor - PGCD in French */ +static unsigned long PaWinWDMGCD( unsigned long a, unsigned long b ) +{ + return (b==0) ? a : PaWinWDMGCD( b, a%b); +} + + +/* This function will handle getting the cyclic buffer from a WaveRT driver. Certain WaveRT drivers needs to have +requested buffer size on multiples of 128 bytes: + +*/ +static PaError PinGetBuffer(PaWinWdmPin* pPin, void** pBuffer, DWORD* pRequestedBufSize, BOOL* pbCallMemBarrier) +{ + PaError result = paNoError; + + while (1) + { + if (pPin->pinKsSubType != SubType_kPolled) + { + /* In case of unknown (or notification), we try both modes */ + result = PinGetBufferWithNotification(pPin, pBuffer, pRequestedBufSize, pbCallMemBarrier); + if (result == paNoError) + { + PA_DEBUG(("PinGetBuffer: SubType_kNotification\n")); + pPin->pinKsSubType = SubType_kNotification; + break; + } + } + + result = PinGetBufferWithoutNotification(pPin, pBuffer, pRequestedBufSize, pbCallMemBarrier); + if (result == paNoError) + { + PA_DEBUG(("PinGetBuffer: SubType_kPolled\n")); + pPin->pinKsSubType = SubType_kPolled; + break; + } + + /* Check if requested size is on a 128 byte boundary */ + if (((*pRequestedBufSize) % 128UL) == 0) + { + PA_DEBUG(("Buffer size on 128 byte boundary, still fails :(\n")); + /* Ok, can't do much more */ + break; + } + else + { + /* Compute LCM so we know which sizes are on a 128 byte boundary */ + const unsigned gcd = PaWinWDMGCD(128UL, pPin->ksDataFormatWfx->WaveFormatEx.nBlockAlign); + const unsigned lcm = (128UL * pPin->ksDataFormatWfx->WaveFormatEx.nBlockAlign) / gcd; + DWORD dwOldSize = *pRequestedBufSize; + + /* Align size to (next larger) LCM byte boundary, and then we try again. Note that LCM is not necessarily a + power of 2. */ + *pRequestedBufSize = ((*pRequestedBufSize + lcm - 1) / lcm) * lcm; + + PA_DEBUG(("Adjusting buffer size from %u to %u bytes (128 byte boundary, LCM=%u)\n", dwOldSize, *pRequestedBufSize, lcm)); + } + } + + return result; +} + +static PaError PinRegisterPositionRegister(PaWinWdmPin* pPin) +{ + PaError result = paNoError; + KSRTAUDIO_HWREGISTER_PROPERTY propIn; + KSRTAUDIO_HWREGISTER propOut; + + PA_LOGE_; + + propIn.BaseAddress = NULL; + propIn.Property.Set = KSPROPSETID_RtAudio; + propIn.Property.Id = KSPROPERTY_RTAUDIO_POSITIONREGISTER; + propIn.Property.Flags = KSPROPERTY_TYPE_GET; + + result = WdmSyncIoctl(pPin->handle, IOCTL_KS_PROPERTY, + &propIn, + sizeof(KSRTAUDIO_HWREGISTER_PROPERTY), + &propOut, + sizeof(KSRTAUDIO_HWREGISTER), + NULL); + + if (result == paNoError) + { + pPin->positionRegister = (ULONG*)propOut.Register; + } + else + { + PA_DEBUG(("Failed to register position register\n")); } PA_LOGL_; @@ -1173,16 +2447,151 @@ static PaError PinIsFormatSupported(PaWinWdmPin* pin, const WAVEFORMATEX* format return result; } -/** - * Create a new filter object - */ -static PaWinWdmFilter* FilterNew(TCHAR* filterName, TCHAR* friendlyName, PaError* error) +static PaError PinRegisterNotificationHandle(PaWinWdmPin* pPin, HANDLE handle) { - PaWinWdmFilter* filter; - PaError result; - int pinId; - int valid; + PaError result = paNoError; + KSRTAUDIO_NOTIFICATION_EVENT_PROPERTY prop; + PA_LOGE_; + + prop.NotificationEvent = handle; + prop.Property.Set = KSPROPSETID_RtAudio; + prop.Property.Id = KSPROPERTY_RTAUDIO_REGISTER_NOTIFICATION_EVENT; + prop.Property.Flags = KSPROPERTY_TYPE_GET; + + result = WdmSyncIoctl(pPin->handle, + IOCTL_KS_PROPERTY, + &prop, + sizeof(KSRTAUDIO_NOTIFICATION_EVENT_PROPERTY), + &prop, + sizeof(KSRTAUDIO_NOTIFICATION_EVENT_PROPERTY), + NULL); + + if (result != paNoError) { + PA_DEBUG(("Failed to register notification handle 0x%08X\n", handle)); + } + + PA_LOGL_; + + return result; +} + +static PaError PinUnregisterNotificationHandle(PaWinWdmPin* pPin, HANDLE handle) +{ + PaError result = paNoError; + KSRTAUDIO_NOTIFICATION_EVENT_PROPERTY prop; + + PA_LOGE_; + + if (handle != NULL) + { + prop.NotificationEvent = handle; + prop.Property.Set = KSPROPSETID_RtAudio; + prop.Property.Id = KSPROPERTY_RTAUDIO_UNREGISTER_NOTIFICATION_EVENT; + prop.Property.Flags = KSPROPERTY_TYPE_GET; + + result = WdmSyncIoctl(pPin->handle, + IOCTL_KS_PROPERTY, + &prop, + sizeof(KSRTAUDIO_NOTIFICATION_EVENT_PROPERTY), + &prop, + sizeof(KSRTAUDIO_NOTIFICATION_EVENT_PROPERTY), + NULL); + + if (result != paNoError) { + PA_DEBUG(("Failed to unregister notification handle 0x%08X\n", handle)); + } + } + PA_LOGL_; + + return result; +} + +static PaError PinGetHwLatency(PaWinWdmPin* pPin, ULONG* pFifoSize, ULONG* pChipsetDelay, ULONG* pCodecDelay) +{ + PaError result = paNoError; + KSPROPERTY propIn; + KSRTAUDIO_HWLATENCY propOut; + + PA_LOGE_; + + propIn.Set = KSPROPSETID_RtAudio; + propIn.Id = KSPROPERTY_RTAUDIO_HWLATENCY; + propIn.Flags = KSPROPERTY_TYPE_GET; + + result = WdmSyncIoctl(pPin->handle, IOCTL_KS_PROPERTY, + &propIn, + sizeof(KSPROPERTY), + &propOut, + sizeof(KSRTAUDIO_HWLATENCY), + NULL); + + if (result == paNoError) + { + *pFifoSize = propOut.FifoSize; + *pChipsetDelay = propOut.ChipsetDelay; + *pCodecDelay = propOut.CodecDelay; + } + else + { + PA_DEBUG(("Failed to retrieve hardware FIFO size!\n")); + } + + PA_LOGL_; + + return result; +} + +/* This one is used for WaveRT */ +static PaError PinGetAudioPositionDirect(PaWinWdmPin* pPin, ULONG* pPosition) +{ + *pPosition = (*pPin->positionRegister); + return paNoError; +} + +/* This one also, but in case the driver hasn't implemented memory mapped access to the position register */ +static PaError PinGetAudioPositionViaIOCTL(PaWinWdmPin* pPin, ULONG* pPosition) +{ + PaError result = paNoError; + KSPROPERTY propIn; + KSAUDIO_POSITION propOut; + + PA_LOGE_; + + propIn.Set = KSPROPSETID_Audio; + propIn.Id = KSPROPERTY_AUDIO_POSITION; + propIn.Flags = KSPROPERTY_TYPE_GET; + + result = WdmSyncIoctl(pPin->handle, + IOCTL_KS_PROPERTY, + &propIn, sizeof(KSPROPERTY), + &propOut, sizeof(KSAUDIO_POSITION), + NULL); + + if (result == paNoError) + { + *pPosition = (ULONG)(propOut.PlayOffset); + } + else + { + PA_DEBUG(("Failed to get audio position!\n")); + } + + PA_LOGL_; + + return result; + +} + +/***********************************************************************************************/ + +/** +* Create a new filter object. +*/ +static PaWinWdmFilter* FilterNew( PaWDMKSType type, DWORD devNode, const wchar_t* filterName, const wchar_t* friendlyName, PaError* error ) +{ + PaWinWdmFilter* filter = 0; + PaError result; /* Allocate the new filter object */ filter = (PaWinWdmFilter*)PaUtil_AllocateMemory( sizeof(PaWinWdmFilter) ); @@ -1192,14 +2601,24 @@ static PaWinWdmFilter* FilterNew(TCHAR* filterName, TCHAR* friendlyName, PaError goto error; } + PA_DEBUG(("FilterNew: Creating filter '%S'\n", friendlyName)); + + /* Set type flag */ + filter->devInfo.streamingType = type; + + /* Store device node */ + filter->deviceNode = devNode; + /* Zero the filter object - done by AllocateMemory */ /* memset( (void*)filter, 0, sizeof(PaWinWdmFilter) ); */ /* Copy the filter name */ - _tcsncpy(filter->filterName, filterName, MAX_PATH); + wcsncpy(filter->devInfo.filterPath, filterName, MAX_PATH); /* Copy the friendly name */ - _tcsncpy(filter->friendlyName, friendlyName, MAX_PATH); + wcsncpy(filter->friendlyName, friendlyName, MAX_PATH); + + PA_DEBUG(("FilterNew: Opening filter...\n", friendlyName)); /* Open the filter handle */ result = FilterUse(filter); @@ -1216,14 +2635,106 @@ static PaWinWdmFilter* FilterNew(TCHAR* filterName, TCHAR* friendlyName, PaError &KSPROPSETID_Pin, KSPROPERTY_PIN_CTYPES, &filter->pinCount, - sizeof(filter->pinCount) - ); + sizeof(filter->pinCount), + NULL); if( result != paNoError) { goto error; } + /* Get connections & nodes for filter */ + result = WdmGetPropertyMulti( + filter->handle, + &KSPROPSETID_Topology, + KSPROPERTY_TOPOLOGY_CONNECTIONS, + &filter->connections); + + if( result != paNoError) + { + goto error; + } + + result = WdmGetPropertyMulti( + filter->handle, + &KSPROPSETID_Topology, + KSPROPERTY_TOPOLOGY_NODES, + &filter->nodes); + + if( result != paNoError) + { + goto error; + } + + /* For debugging purposes */ + DumpConnectionsAndNodes(filter); + + /* Get product GUID (it might not be supported) */ + { + KSCOMPONENTID compId; + if (WdmGetPropertySimple(filter->handle, &KSPROPSETID_General, KSPROPERTY_GENERAL_COMPONENTID, &compId, sizeof(KSCOMPONENTID), NULL, 0) == paNoError) + { + filter->devInfo.deviceProductGuid = compId.Product; + } + } + + /* This section is not executed for topology filters */ + if (type != Type_kNotUsed) + { + /* Initialize the pins */ + result = FilterInitializePins(filter); + + if( result != paNoError) + { + goto error; + } + } + + /* Close the filter handle for now + * It will be opened later when needed */ + FilterRelease(filter); + + *error = paNoError; + return filter; + +error: + PA_DEBUG(("FilterNew: Error %d\n", result)); + /* + Error cleanup + */ + FilterFree(filter); + + *error = result; + return NULL; +} + +/** +* Add reference to filter +*/ +static void FilterAddRef( PaWinWdmFilter* filter ) +{ + if (filter != 0) + { + filter->filterRefCount++; + } +} + + +/** +* Initialize the pins of the filter. This is separated from FilterNew because this might fail if there is another +* process using the pin(s). +*/ +PaError FilterInitializePins( PaWinWdmFilter* filter ) +{ + PaError result = paNoError; + int pinId; + + if (filter->devInfo.streamingType == Type_kNotUsed) + return paNoError; + + if (filter->pins != NULL) + return paNoError; + /* Allocate pointer array to hold the pins */ filter->pins = (PaWinWdmPin**)PaUtil_AllocateMemory( sizeof(PaWinWdmPin*) * filter->pinCount ); if( !filter->pins ) @@ -1233,11 +2744,6 @@ static PaWinWdmFilter* FilterNew(TCHAR* filterName, TCHAR* friendlyName, PaError } /* Create all the pins we can */ - filter->maxInputChannels = 0; - filter->maxOutputChannels = 0; - filter->bestSampleRate = 0; - - valid = 0; for(pinId = 0; pinId < filter->pinCount; pinId++) { /* Create the pin with this Id */ @@ -1248,83 +2754,75 @@ static PaWinWdmFilter* FilterNew(TCHAR* filterName, TCHAR* friendlyName, PaError if( newPin != NULL ) { filter->pins[pinId] = newPin; - valid = 1; - - /* Get the max output channel count */ - if(( newPin->dataFlow == KSPIN_DATAFLOW_IN ) && - (( newPin->communication == KSPIN_COMMUNICATION_SINK) || - ( newPin->communication == KSPIN_COMMUNICATION_BOTH))) - { - if(newPin->maxChannels > filter->maxOutputChannels) - filter->maxOutputChannels = newPin->maxChannels; - filter->formats |= newPin->formats; - } - /* Get the max input channel count */ - if(( newPin->dataFlow == KSPIN_DATAFLOW_OUT ) && - (( newPin->communication == KSPIN_COMMUNICATION_SINK) || - ( newPin->communication == KSPIN_COMMUNICATION_BOTH))) - { - if(newPin->maxChannels > filter->maxInputChannels) - filter->maxInputChannels = newPin->maxChannels; - filter->formats |= newPin->formats; - } - - if(newPin->bestSampleRate > filter->bestSampleRate) - { - filter->bestSampleRate = newPin->bestSampleRate; - } + ++filter->validPinCount; } } - if(( filter->maxInputChannels == 0) && ( filter->maxOutputChannels == 0)) + if (filter->validPinCount == 0) { - /* No input or output... not valid */ - valid = 0; - } - - if( !valid ) - { - /* No valid pin was found on this filter so we destroy it */ result = paDeviceUnavailable; goto error; } - /* Close the filter handle for now - * It will be opened later when needed */ - FilterRelease(filter); - - *error = paNoError; - return filter; + return paNoError; error: - /* - Error cleanup - */ - if( filter ) + + if (filter->pins) { - for( pinId = 0; pinId < filter->pinCount; pinId++ ) - PinFree(filter->pins[pinId]); + for (pinId = 0; pinId < filter->pinCount; ++pinId) + { + if (filter->pins[pinId]) + { + PaUtil_FreeMemory(filter->pins[pinId]); + filter->pins[pinId] = 0; + } + } PaUtil_FreeMemory( filter->pins ); - if( filter->handle ) - CloseHandle( filter->handle ); - PaUtil_FreeMemory( filter ); + filter->pins = 0; } - *error = result; - return NULL; + + return result; } + /** - * Free a previously created filter - */ +* Free a previously created filter +*/ static void FilterFree(PaWinWdmFilter* filter) { int pinId; PA_LOGL_; if( filter ) { - for( pinId = 0; pinId < filter->pinCount; pinId++ ) - PinFree(filter->pins[pinId]); - PaUtil_FreeMemory( filter->pins ); + if (--filter->filterRefCount > 0) + { + /* Ok, a stream has a ref count to this filter */ + return; + } + + if (filter->topologyFilter) + { + FilterFree(filter->topologyFilter); + filter->topologyFilter = 0; + } + if ( filter->pins ) + { + for( pinId = 0; pinId < filter->pinCount; pinId++ ) + PinFree(filter->pins[pinId]); + PaUtil_FreeMemory( filter->pins ); + filter->pins = 0; + } + if( filter->connections ) + { + PaUtil_FreeMemory(filter->connections); + filter->connections = 0; + } + if( filter->nodes ) + { + PaUtil_FreeMemory(filter->nodes); + filter->nodes = 0; + } if( filter->handle ) CloseHandle( filter->handle ); PaUtil_FreeMemory( filter ); @@ -1333,8 +2831,8 @@ static void FilterFree(PaWinWdmFilter* filter) } /** - * Reopen the filter handle if necessary so it can be used - **/ +* Reopen the filter handle if necessary so it can be used +**/ static PaError FilterUse(PaWinWdmFilter* filter) { assert( filter ); @@ -1343,8 +2841,8 @@ static PaError FilterUse(PaWinWdmFilter* filter) if( filter->handle == NULL ) { /* Open the filter */ - filter->handle = CreateFile( - filter->filterName, + filter->handle = CreateFileW( + filter->devInfo.filterPath, GENERIC_READ | GENERIC_WRITE, 0, NULL, @@ -1363,14 +2861,20 @@ static PaError FilterUse(PaWinWdmFilter* filter) } /** - * Release the filter handle if nobody is using it - **/ +* Release the filter handle if nobody is using it +**/ static void FilterRelease(PaWinWdmFilter* filter) { assert( filter ); assert( filter->usageCount > 0 ); PA_LOGE_; + /* Check first topology filter, if used */ + if (filter->topologyFilter != NULL && filter->topologyFilter->handle != NULL) + { + FilterRelease(filter->topologyFilter); + } + filter->usageCount--; if( filter->usageCount == 0 ) { @@ -1384,200 +2888,85 @@ static void FilterRelease(PaWinWdmFilter* filter) } /** - * Create a render (playback) Pin using the supplied format - **/ -static PaWinWdmPin* FilterCreateRenderPin(PaWinWdmFilter* filter, - const WAVEFORMATEX* wfex, - PaError* error) -{ - PaError result; - PaWinWdmPin* pin; - - assert( filter ); - - pin = FilterFindViableRenderPin(filter,wfex,&result); - if(!pin) - { - goto error; - } - result = PinSetFormat(pin,wfex); - if( result != paNoError ) - { - goto error; - } - result = PinInstantiate(pin); - if( result != paNoError ) - { - goto error; - } - - *error = paNoError; - return pin; - -error: - *error = result; - return NULL; -} - -/** - * Find a pin that supports the given format - **/ -static PaWinWdmPin* FilterFindViableRenderPin(PaWinWdmFilter* filter, - const WAVEFORMATEX* wfex, - PaError* error) -{ - int pinId; - PaWinWdmPin* pin; - PaError result = paDeviceUnavailable; - *error = paNoError; - - assert( filter ); - - for( pinId = 0; pinIdpinCount; pinId++ ) - { - pin = filter->pins[pinId]; - if( pin != NULL ) - { - if(( pin->dataFlow == KSPIN_DATAFLOW_IN ) && - (( pin->communication == KSPIN_COMMUNICATION_SINK) || - ( pin->communication == KSPIN_COMMUNICATION_BOTH))) - { - result = PinIsFormatSupported( pin, wfex ); - if( result == paNoError ) - { - return pin; - } - } - } - } - - *error = result; - return NULL; -} - -/** - * Check if there is a pin that should playback - * with the supplied format - **/ -static PaError FilterCanCreateRenderPin(PaWinWdmFilter* filter, - const WAVEFORMATEX* wfex) -{ - PaWinWdmPin* pin; - PaError result; - - assert ( filter ); - - pin = FilterFindViableRenderPin(filter,wfex,&result); - /* result will be paNoError if pin found - * or else an error code indicating what is wrong with the format - **/ - return result; -} - -/** - * Create a capture (record) Pin using the supplied format - **/ -static PaWinWdmPin* FilterCreateCapturePin(PaWinWdmFilter* filter, - const WAVEFORMATEX* wfex, - PaError* error) -{ - PaError result; - PaWinWdmPin* pin; - - assert( filter ); - - pin = FilterFindViableCapturePin(filter,wfex,&result); - if(!pin) - { - goto error; - } - - result = PinSetFormat(pin,wfex); - if( result != paNoError ) - { - goto error; - } - - result = PinInstantiate(pin); - if( result != paNoError ) - { - goto error; - } - - *error = paNoError; - return pin; - -error: - *error = result; - return NULL; -} - -/** - * Find a capture pin that supports the given format - **/ -static PaWinWdmPin* FilterFindViableCapturePin(PaWinWdmFilter* filter, - const WAVEFORMATEX* wfex, - PaError* error) -{ - int pinId; - PaWinWdmPin* pin; - PaError result = paDeviceUnavailable; - *error = paNoError; - - assert( filter ); - - for( pinId = 0; pinIdpinCount; pinId++ ) - { - pin = filter->pins[pinId]; - if( pin != NULL ) - { - if(( pin->dataFlow == KSPIN_DATAFLOW_OUT ) && - (( pin->communication == KSPIN_COMMUNICATION_SINK) || - ( pin->communication == KSPIN_COMMUNICATION_BOTH))) - { - result = PinIsFormatSupported( pin, wfex ); - if( result == paNoError ) - { - return pin; - } - } - } - } - - *error = result; - return NULL; -} - -/** - * Check if there is a pin that should playback - * with the supplied format - **/ -static PaError FilterCanCreateCapturePin(PaWinWdmFilter* filter, - const WAVEFORMATEX* wfex) -{ - PaWinWdmPin* pin; - PaError result; - - assert ( filter ); - - pin = FilterFindViableCapturePin(filter,wfex,&result); - /* result will be paNoError if pin found - * or else an error code indicating what is wrong with the format - **/ - return result; -} - -/** - * Build the list of available filters - * Use the SetupDi API to enumerate all devices in the KSCATEGORY_AUDIO which - * have a KSCATEGORY_RENDER or KSCATEGORY_CAPTURE alias. For each of these - * devices initialise a PaWinWdmFilter structure by calling our NewFilter() - * function. We enumerate devices twice, once to count how many there are, - * and once to initialize the PaWinWdmFilter structures. - */ -static PaError BuildFilterList(PaWinWdmHostApiRepresentation* wdmHostApi) +* Create a render or playback pin using the supplied format +**/ +static PaWinWdmPin* FilterCreatePin(PaWinWdmFilter* filter, + int pinId, + const WAVEFORMATEX* wfex, + PaError* error) { PaError result = paNoError; + PaWinWdmPin* pin = NULL; + assert( filter ); + assert( pinId < filter->pinCount ); + pin = filter->pins[pinId]; + assert( pin ); + result = PinSetFormat(pin,wfex); + if( result == paNoError ) + { + result = PinInstantiate(pin); + } + *error = result; + return result == paNoError ? pin : 0; +} + +static const wchar_t kUsbPrefix[] = L"\\\\?\\USB"; + +static BOOL IsUSBDevice(const wchar_t* devicePath) +{ + /* Alex Lessard pointed out that different devices might present the device path with + lower case letters. */ + return (_wcsnicmp(devicePath, kUsbPrefix, sizeof(kUsbPrefix)/sizeof(kUsbPrefix[0]) ) == 0); +} + +/* This should make it more language tolerant, I hope... */ +static const wchar_t kUsbNamePrefix[] = L"USB Audio"; + +static BOOL IsNameUSBAudioDevice(const wchar_t* friendlyName) +{ + return (_wcsnicmp(friendlyName, kUsbNamePrefix, sizeof(kUsbNamePrefix)/sizeof(kUsbNamePrefix[0])) == 0); +} + +typedef enum _tag_EAlias +{ + Alias_kRender = (1<<0), + Alias_kCapture = (1<<1), + Alias_kRealtime = (1<<2), +} EAlias; + +/* Trim whitespace from string */ +static void TrimString(wchar_t* str, size_t length) +{ + wchar_t* s = str; + wchar_t* e = 0; + + /* Find start of string */ + while (iswspace(*s)) ++s; + e=s+min(length,wcslen(s))-1; + + /* Find end of string */ + while(e>s && iswspace(*e)) --e; + ++e; + + length = e - s; + memmove(str, s, length * sizeof(wchar_t)); + str[length] = 0; +} + +/** +* Build the list of available filters +* Use the SetupDi API to enumerate all devices in the KSCATEGORY_AUDIO which +* have a KSCATEGORY_RENDER or KSCATEGORY_CAPTURE alias. For each of these +* devices initialise a PaWinWdmFilter structure by calling our NewFilter() +* function. We enumerate devices twice, once to count how many there are, +* and once to initialize the PaWinWdmFilter structures. +* +* Vista and later: Also check KSCATEGORY_REALTIME for WaveRT devices. +*/ +//PaError BuildFilterList( PaWinWdmHostApiRepresentation* wdmHostApi, int* noOfPaDevices ) +PaWinWdmFilter** BuildFilterList( int* pFilterCount, int* pNoOfPaDevices, PaError* pResult ) +{ + PaWinWdmFilter** ppFilters = NULL; HDEVINFO handle = NULL; int device; int invalidDevices; @@ -1588,26 +2977,32 @@ static PaError BuildFilterList(PaWinWdmHostApiRepresentation* wdmHostApi) int noError; const int sizeInterface = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + (MAX_PATH * sizeof(WCHAR)); unsigned char interfaceDetailsArray[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + (MAX_PATH * sizeof(WCHAR))]; - SP_DEVICE_INTERFACE_DETAIL_DATA* devInterfaceDetails = (SP_DEVICE_INTERFACE_DETAIL_DATA*)interfaceDetailsArray; - TCHAR friendlyName[MAX_PATH]; - HKEY hkey; - DWORD sizeFriendlyName; - DWORD type; - PaWinWdmFilter* newFilter; - GUID* category = (GUID*)&KSCATEGORY_AUDIO; - GUID* alias_render = (GUID*)&KSCATEGORY_RENDER; - GUID* alias_capture = (GUID*)&KSCATEGORY_CAPTURE; - DWORD hasAlias; + SP_DEVICE_INTERFACE_DETAIL_DATA_W* devInterfaceDetails = (SP_DEVICE_INTERFACE_DETAIL_DATA_W*)interfaceDetailsArray; + const GUID* category = (const GUID*)&KSCATEGORY_AUDIO; + const GUID* alias_render = (const GUID*)&KSCATEGORY_RENDER; + const GUID* alias_capture = (const GUID*)&KSCATEGORY_CAPTURE; + const GUID* category_realtime = (const GUID*)&KSCATEGORY_REALTIME; + DWORD aliasFlags; + PaWDMKSType streamingType; + int filterCount = 0; + int noOfPaDevices = 0; PA_LOGE_; - devInterfaceDetails->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); + assert(pFilterCount != NULL); + assert(pNoOfPaDevices != NULL); + assert(pResult != NULL); + + devInterfaceDetails->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W); + *pFilterCount = 0; + *pNoOfPaDevices = 0; /* Open a handle to search for devices (filters) */ handle = SetupDiGetClassDevs(category,NULL,NULL,DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - if( handle == NULL ) + if( handle == INVALID_HANDLE_VALUE ) { - return paUnanticipatedHostError; + *pResult = paUnanticipatedHostError; + return NULL; } PA_DEBUG(("Setup called\n")); @@ -1625,7 +3020,7 @@ static PaError BuildFilterList(PaWinWdmHostApiRepresentation* wdmHostApi) break; /* No more devices */ /* Check this one has the render or capture alias */ - hasAlias = 0; + aliasFlags = 0; noError = SetupDiGetDeviceInterfaceAlias(handle,&interfaceData,alias_render,&aliasData); PA_DEBUG(("noError = %d\n",noError)); if(noError) @@ -1633,7 +3028,7 @@ static PaError BuildFilterList(PaWinWdmHostApiRepresentation* wdmHostApi) if(aliasData.Flags && (!(aliasData.Flags & SPINT_REMOVED))) { PA_DEBUG(("Device %d has render alias\n",device)); - hasAlias |= 1; /* Has render alias */ + aliasFlags |= Alias_kRender; /* Has render alias */ } else { @@ -1646,29 +3041,29 @@ static PaError BuildFilterList(PaWinWdmHostApiRepresentation* wdmHostApi) if(aliasData.Flags && (!(aliasData.Flags & SPINT_REMOVED))) { PA_DEBUG(("Device %d has capture alias\n",device)); - hasAlias |= 2; /* Has capture alias */ + aliasFlags |= Alias_kCapture; /* Has capture alias */ } else { PA_DEBUG(("Device %d has no capture alias\n",device)); } } - if(!hasAlias) + if(!aliasFlags) invalidDevices++; /* This was not a valid capture or render audio device */ - } /* Remember how many there are */ - wdmHostApi->filterCount = device-invalidDevices; + filterCount = device-invalidDevices; PA_DEBUG(("Interfaces found: %d\n",device-invalidDevices)); /* Now allocate the list of pointers to devices */ - wdmHostApi->filters = (PaWinWdmFilter**)PaUtil_AllocateMemory( sizeof(PaWinWdmFilter*) * device ); - if( !wdmHostApi->filters ) + ppFilters = (PaWinWdmFilter**)PaUtil_AllocateMemory( sizeof(PaWinWdmFilter*) * filterCount); + if( ppFilters == 0 ) { if(handle != NULL) SetupDiDestroyDeviceInfoList(handle); - return paInsufficientMemory; + *pResult = paInsufficientMemory; + return NULL; } /* Now create filter objects for each interface found */ @@ -1681,20 +3076,21 @@ static PaError BuildFilterList(PaWinWdmHostApiRepresentation* wdmHostApi) aliasData.Reserved = 0; devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); devInfoData.Reserved = 0; + streamingType = Type_kWaveCyclic; noError = SetupDiEnumDeviceInterfaces(handle,NULL,category,device,&interfaceData); if( !noError ) break; /* No more devices */ /* Check this one has the render or capture alias */ - hasAlias = 0; + aliasFlags = 0; noError = SetupDiGetDeviceInterfaceAlias(handle,&interfaceData,alias_render,&aliasData); if(noError) { if(aliasData.Flags && (!(aliasData.Flags & SPINT_REMOVED))) { PA_DEBUG(("Device %d has render alias\n",device)); - hasAlias |= 1; /* Has render alias */ + aliasFlags |= Alias_kRender; /* Has render alias */ } } noError = SetupDiGetDeviceInterfaceAlias(handle,&interfaceData,alias_capture,&aliasData); @@ -1703,48 +3099,114 @@ static PaError BuildFilterList(PaWinWdmHostApiRepresentation* wdmHostApi) if(aliasData.Flags && (!(aliasData.Flags & SPINT_REMOVED))) { PA_DEBUG(("Device %d has capture alias\n",device)); - hasAlias |= 2; /* Has capture alias */ + aliasFlags |= Alias_kCapture; /* Has capture alias */ } } - if(!hasAlias) + if(!aliasFlags) + { continue; /* This was not a valid capture or render audio device */ + } + else + { + /* Check if filter is WaveRT, if not it is a WaveCyclic */ + noError = SetupDiGetDeviceInterfaceAlias(handle,&interfaceData,category_realtime,&aliasData); + if (noError) + { + PA_DEBUG(("Device %d has realtime alias\n",device)); + aliasFlags |= Alias_kRealtime; + streamingType = Type_kWaveRT; + } + } - noError = SetupDiGetDeviceInterfaceDetail(handle,&interfaceData,devInterfaceDetails,sizeInterface,NULL,&devInfoData); + noError = SetupDiGetDeviceInterfaceDetailW(handle,&interfaceData,devInterfaceDetails,sizeInterface,NULL,&devInfoData); if( noError ) { + DWORD type; + WCHAR friendlyName[MAX_PATH] = {0}; + DWORD sizeFriendlyName; + PaWinWdmFilter* newFilter = 0; + + PaError result = paNoError; /* Try to get the "friendly name" for this interface */ sizeFriendlyName = sizeof(friendlyName); - /* Fix contributed by Ben Allison - * Removed KEY_SET_VALUE from flags on following call - * as its causes failure when running without admin rights - * and it was not required */ - hkey=SetupDiOpenDeviceInterfaceRegKey(handle,&interfaceData,0,KEY_QUERY_VALUE); - if(hkey!=INVALID_HANDLE_VALUE) + + if (IsEarlierThanVista() && IsUSBDevice(devInterfaceDetails->DevicePath)) { - noError = RegQueryValueEx(hkey,TEXT("FriendlyName"),0,&type,(BYTE*)friendlyName,&sizeFriendlyName); - if( noError == ERROR_SUCCESS ) - { - PA_DEBUG(("Interface %d, Name: %s\n",device,friendlyName)); - RegCloseKey(hkey); - } - else + /* XP and USB audio device needs to look elsewhere, otherwise it'll only be a "USB Audio Device". Not + very literate. */ + if (!SetupDiGetDeviceRegistryPropertyW(handle, + &devInfoData, + SPDRP_LOCATION_INFORMATION, + &type, + (BYTE*)friendlyName, + sizeof(friendlyName), + NULL)) { friendlyName[0] = 0; } } - newFilter = FilterNew(devInterfaceDetails->DevicePath,friendlyName,&result); + + if (friendlyName[0] == 0 || IsNameUSBAudioDevice(friendlyName)) + { + /* Fix contributed by Ben Allison + * Removed KEY_SET_VALUE from flags on following call + * as its causes failure when running without admin rights + * and it was not required */ + HKEY hkey=SetupDiOpenDeviceInterfaceRegKey(handle,&interfaceData,0,KEY_QUERY_VALUE); + if(hkey!=INVALID_HANDLE_VALUE) + { + noError = RegQueryValueExW(hkey,L"FriendlyName",0,&type,(BYTE*)friendlyName,&sizeFriendlyName); + if( noError == ERROR_SUCCESS ) + { + PA_DEBUG(("Interface %d, Name: %s\n",device,friendlyName)); + RegCloseKey(hkey); + } + else + { + friendlyName[0] = 0; + } + } + } + + TrimString(friendlyName, sizeFriendlyName); + + newFilter = FilterNew(streamingType, + devInfoData.DevInst, + devInterfaceDetails->DevicePath, + friendlyName, + &result); + if( result == paNoError ) { - PA_DEBUG(("Filter created\n")); - wdmHostApi->filters[slot] = newFilter; + int pin; + unsigned filterIOs = 0; + + /* Increment number of "devices" */ + for (pin = 0; pin < newFilter->pinCount; ++pin) + { + PaWinWdmPin* pPin = newFilter->pins[pin]; + if (pPin == NULL) + continue; + + filterIOs += max(1, pPin->inputCount); + } + + noOfPaDevices += filterIOs; + + PA_DEBUG(("Filter (%s) created with %d valid pins (total I/Os: %u)\n", ((newFilter->devInfo.streamingType==Type_kWaveRT)?"WaveRT":"WaveCyclic"), newFilter->validPinCount, filterIOs)); + + assert(slot < filterCount); + + ppFilters[slot] = newFilter; + slot++; } else { PA_DEBUG(("Filter NOT created\n")); /* As there are now less filters than we initially thought - * we must reduce the count by one */ - wdmHostApi->filterCount--; + * we must reduce the count by one */ + filterCount--; } } } @@ -1753,21 +3215,467 @@ static PaError BuildFilterList(PaWinWdmHostApiRepresentation* wdmHostApi) if(handle != NULL) SetupDiDestroyDeviceInfoList(handle); + *pFilterCount = filterCount; + *pNoOfPaDevices = noOfPaDevices; + + return ppFilters; +} + +typedef struct PaNameHashIndex +{ + unsigned index; + unsigned count; + ULONG hash; + struct PaNameHashIndex *next; +} PaNameHashIndex; + +typedef struct PaNameHashObject +{ + PaNameHashIndex* list; + PaUtilAllocationGroup* allocGroup; +} PaNameHashObject; + +static ULONG GetNameHash(const wchar_t* str, const BOOL input) +{ + /* This is to make sure that a name that exists as both input & output won't get the same hash value */ + const ULONG fnv_prime = (input ? 0x811C9DD7 : 0x811FEB0B); + ULONG hash = 0; + for(; *str != 0; str++) + { + hash *= fnv_prime; + hash ^= (*str); + } + assert(hash != 0); + return hash; +} + +static PaError CreateHashEntry(PaNameHashObject* obj, const wchar_t* name, const BOOL input) +{ + ULONG hash = GetNameHash(name, input); + PaNameHashIndex * pLast = NULL; + PaNameHashIndex * p = obj->list; + while (p != 0) + { + if (p->hash == hash) + { + break; + } + pLast = p; + p = p->next; + } + if (p == NULL) + { + p = (PaNameHashIndex*)PaUtil_GroupAllocateMemory(obj->allocGroup, sizeof(PaNameHashIndex)); + if (p == NULL) + { + return paInsufficientMemory; + } + p->hash = hash; + p->count = 1; + if (pLast != 0) + { + assert(pLast->next == 0); + pLast->next = p; + } + if (obj->list == 0) + { + obj->list = p; + } + } + else + { + ++p->count; + } return paNoError; } +static PaError InitNameHashObject(PaNameHashObject* obj, PaWinWdmFilter* pFilter) +{ + int i; + + obj->allocGroup = PaUtil_CreateAllocationGroup(); + if (obj->allocGroup == NULL) + { + return paInsufficientMemory; + } + + for (i = 0; i < pFilter->pinCount; ++i) + { + unsigned m; + PaWinWdmPin* pin = pFilter->pins[i]; + + if (pin == NULL) + continue; + + for (m = 0; m < max(1, pin->inputCount); ++m) + { + const BOOL isInput = (pin->dataFlow == KSPIN_DATAFLOW_OUT); + const wchar_t* name = (pin->inputs == NULL) ? pin->friendlyName : pin->inputs[m]->friendlyName; + + PaError result = CreateHashEntry(obj, name, isInput); + + if (result != paNoError) + { + return result; + } + } + } + return paNoError; +} + +static void DeinitNameHashObject(PaNameHashObject* obj) +{ + assert(obj != 0); + PaUtil_FreeAllAllocations(obj->allocGroup); + PaUtil_DestroyAllocationGroup(obj->allocGroup); + memset(obj, 0, sizeof(PaNameHashObject)); +} + +static unsigned GetNameIndex(PaNameHashObject* obj, const wchar_t* name, const BOOL input) +{ + ULONG hash = GetNameHash(name, input); + PaNameHashIndex* p = obj->list; + while (p != NULL) + { + if (p->hash == hash) + { + if (p->count > 1) + { + return (++p->index); + } + else + { + return 0; + } + } + + p = p->next; + } + // Should never get here!! + assert(FALSE); + return 0; +} + +static PaError ScanDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex hostApiIndex, void **scanResults, int *newDeviceCount ) +{ + PaWinWdmHostApiRepresentation *wdmHostApi = (PaWinWdmHostApiRepresentation*)hostApi; + PaError result = paNoError; + PaWinWdmFilter** ppFilters = 0; + PaWinWDMScanDeviceInfosResults *outArgument = 0; + int filterCount = 0; + int totalDeviceCount = 0; + int idxDevice = 0; + + ppFilters = BuildFilterList( &filterCount, &totalDeviceCount, &result ); + if( result != paNoError ) + { + goto error; + } + + if( totalDeviceCount > 0 ) + { + PaWinWdmDeviceInfo *deviceInfoArray = 0; + int idxFilter; + int i; + + /* Allocate the out param for all the info we need */ + outArgument = (PaWinWDMScanDeviceInfosResults *) PaUtil_GroupAllocateMemory( + wdmHostApi->allocations, sizeof(PaWinWDMScanDeviceInfosResults) ); + if( !outArgument ) + { + result = paInsufficientMemory; + goto error; + } + + outArgument->defaultInputDevice = paNoDevice; + outArgument->defaultOutputDevice = paNoDevice; + + outArgument->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory( + wdmHostApi->allocations, sizeof(PaDeviceInfo*) * totalDeviceCount ); + if( !outArgument->deviceInfos ) + { + result = paInsufficientMemory; + goto error; + } + + /* allocate all device info structs in a contiguous block */ + deviceInfoArray = (PaWinWdmDeviceInfo*)PaUtil_GroupAllocateMemory( + wdmHostApi->allocations, sizeof(PaWinWdmDeviceInfo) * totalDeviceCount ); + if( !deviceInfoArray ) + { + result = paInsufficientMemory; + goto error; + } + + /* Make sure all items in array */ + for( i = 0 ; i < totalDeviceCount; ++i ) + { + PaDeviceInfo *deviceInfo = &deviceInfoArray[i].inheritedDeviceInfo; + deviceInfo->structVersion = 2; + deviceInfo->hostApi = hostApiIndex; + deviceInfo->name = 0; + outArgument->deviceInfos[ i ] = deviceInfo; + } + + idxDevice = 0; + for (idxFilter = 0; idxFilter < filterCount; ++idxFilter) + { + PaNameHashObject nameHash = {0}; + PaWinWdmFilter* pFilter = ppFilters[idxFilter]; + if( pFilter == NULL ) + continue; + + if (InitNameHashObject(&nameHash, pFilter) != paNoError) + { + DeinitNameHashObject(&nameHash); + continue; + } + + for (i = 0; i < pFilter->pinCount; ++i) + { + unsigned m; + ULONG nameIndex = 0; + ULONG nameIndexHash = 0; + PaWinWdmPin* pin = pFilter->pins[i]; + + if (pin == NULL) + continue; + + for (m = 0; m < max(1, pin->inputCount); ++m) + { + PaWinWdmDeviceInfo *wdmDeviceInfo = (PaWinWdmDeviceInfo *)outArgument->deviceInfos[idxDevice]; + PaDeviceInfo *deviceInfo = &wdmDeviceInfo->inheritedDeviceInfo; + wchar_t localCompositeName[MAX_PATH]; + unsigned nameIndex = 0; + const BOOL isInput = (pin->dataFlow == KSPIN_DATAFLOW_OUT); + + wdmDeviceInfo->filter = pFilter; + + deviceInfo->structVersion = 2; + deviceInfo->hostApi = hostApiIndex; + deviceInfo->name = wdmDeviceInfo->compositeName; + /* deviceInfo->hostApiSpecificDeviceInfo = &pFilter->devInfo; */ + + wdmDeviceInfo->pin = pin->pinId; + + /* Get the name of the "device" */ + if (pin->inputs == NULL) + { + wcsncpy(localCompositeName, pin->friendlyName, MAX_PATH); + wdmDeviceInfo->muxPosition = -1; + wdmDeviceInfo->endpointPinId = pin->endpointPinId; + } + else + { + PaWinWdmMuxedInput* input = pin->inputs[m]; + wcsncpy(localCompositeName, input->friendlyName, MAX_PATH); + wdmDeviceInfo->muxPosition = (int)m; + wdmDeviceInfo->endpointPinId = input->endpointPinId; + } + + { + /* Get base length */ + size_t n = wcslen(localCompositeName); + + /* Check if there are more entries with same name (which might very well be the case), if there + are, the name will be postfixed with an index. */ + nameIndex = GetNameIndex(&nameHash, localCompositeName, isInput); + if (nameIndex > 0) + { + /* This name has multiple instances, so we post fix with a number */ + n += _snwprintf(localCompositeName + n, MAX_PATH - n, L" %u", nameIndex); + } + /* Postfix with filter name */ + _snwprintf(localCompositeName + n, MAX_PATH - n, L" (%s)", pFilter->friendlyName); + } + + /* Convert wide char string to utf-8 */ + WideCharToMultiByte(CP_UTF8, 0, localCompositeName, -1, wdmDeviceInfo->compositeName, MAX_PATH, NULL, NULL); + + /* NB! WDM/KS has no concept of a full-duplex device, each pin is either an input or and output */ + if (isInput) + { + /* INPUT ! */ + deviceInfo->maxInputChannels = pin->maxChannels; + deviceInfo->maxOutputChannels = 0; + + if (outArgument->defaultInputDevice == paNoDevice) + { + outArgument->defaultInputDevice = idxDevice; + } + } + else + { + /* OUTPUT ! */ + deviceInfo->maxInputChannels = 0; + deviceInfo->maxOutputChannels = pin->maxChannels; + + if (outArgument->defaultOutputDevice == paNoDevice) + { + outArgument->defaultOutputDevice = idxDevice; + } + } + + /* These low values are not very useful because + * a) The lowest latency we end up with can depend on many factors such + * as the device buffer sizes/granularities, sample rate, channels and format + * b) We cannot know the device buffer sizes until we try to open/use it at + * a particular setting + * So: we give 512x48000Hz frames as the default low input latency + **/ + switch (pFilter->devInfo.streamingType) + { + case Type_kWaveCyclic: + if (IsEarlierThanVista()) + { + /* XP doesn't tolerate low latency, unless the Process Priority Class is set to REALTIME_PRIORITY_CLASS + through SetPriorityClass, then 10 ms is quite feasible. However, one should then bear in mind that ALL of + the process is running in REALTIME_PRIORITY_CLASS, which might not be appropriate for an application with + a GUI . In this case it is advisable to separate the audio engine in another process and use IPC to communicate + with it. */ + deviceInfo->defaultLowInputLatency = 0.02; + deviceInfo->defaultLowOutputLatency = 0.02; + } + else + { + /* This is a conservative estimate. Most WaveCyclic drivers will limit the available latency, but f.i. my Edirol + PCR-A30 can reach 3 ms latency easily... */ + deviceInfo->defaultLowInputLatency = 0.01; + deviceInfo->defaultLowOutputLatency = 0.01; + } + deviceInfo->defaultHighInputLatency = (4096.0/48000.0); + deviceInfo->defaultHighOutputLatency = (4096.0/48000.0); + deviceInfo->defaultSampleRate = (double)(pin->defaultSampleRate); + break; + case Type_kWaveRT: + /* This is also a conservative estimate, based on WaveRT polled mode. In polled mode, the latency will be dictated + by the buffer size given by the driver. */ + deviceInfo->defaultLowInputLatency = 0.01; + deviceInfo->defaultLowOutputLatency = 0.01; + deviceInfo->defaultHighInputLatency = 0.04; + deviceInfo->defaultHighOutputLatency = 0.04; + deviceInfo->defaultSampleRate = (double)(pin->defaultSampleRate); + break; + default: + assert(0); + break; + } + + /* Add reference to filter */ + FilterAddRef(wdmDeviceInfo->filter); + + assert(idxDevice < totalDeviceCount); + ++idxDevice; + } + } + + /* If no one has add ref'd the filter, drop it */ + if (pFilter->filterRefCount == 0) + { + FilterFree(pFilter); + } + + /* Deinitialize name hash object */ + DeinitNameHashObject(&nameHash); + } + } + + *scanResults = outArgument; + *newDeviceCount = idxDevice; + return result; + +error: + result = DisposeDeviceInfos(hostApi, outArgument, totalDeviceCount); + + return result; +} + +static PaError CommitDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex index, void *scanResults, int deviceCount ) +{ + PaWinWdmHostApiRepresentation *wdmHostApi = (PaWinWdmHostApiRepresentation*)hostApi; + + hostApi->info.deviceCount = 0; + hostApi->info.defaultInputDevice = paNoDevice; + hostApi->info.defaultOutputDevice = paNoDevice; + + /* Free any old memory which might be in the device info */ + if( hostApi->deviceInfos ) + { + PaWinWDMScanDeviceInfosResults* localScanResults = (PaWinWDMScanDeviceInfosResults*)PaUtil_GroupAllocateMemory( + wdmHostApi->allocations, sizeof(PaWinWDMScanDeviceInfosResults)); + localScanResults->deviceInfos = hostApi->deviceInfos; + + DisposeDeviceInfos(hostApi, &localScanResults, hostApi->info.deviceCount); + + hostApi->deviceInfos = NULL; + } + + if( scanResults != NULL ) + { + PaWinWDMScanDeviceInfosResults *scanDeviceInfosResults = ( PaWinWDMScanDeviceInfosResults * ) scanResults; + + if( deviceCount > 0 ) + { + /* use the array allocated in ScanDeviceInfos() as our deviceInfos */ + hostApi->deviceInfos = scanDeviceInfosResults->deviceInfos; + + hostApi->info.defaultInputDevice = scanDeviceInfosResults->defaultInputDevice; + hostApi->info.defaultOutputDevice = scanDeviceInfosResults->defaultOutputDevice; + + hostApi->info.deviceCount = deviceCount; + } + + PaUtil_GroupFreeMemory( wdmHostApi->allocations, scanDeviceInfosResults ); + } + + return paNoError; + +} + +static PaError DisposeDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, void *scanResults, int deviceCount ) +{ + PaWinWdmHostApiRepresentation *winDsHostApi = (PaWinWdmHostApiRepresentation*)hostApi; + + if( scanResults != NULL ) + { + PaWinWDMScanDeviceInfosResults *scanDeviceInfosResults = ( PaWinWDMScanDeviceInfosResults * ) scanResults; + + if( scanDeviceInfosResults->deviceInfos ) + { + int i; + for (i = 0; i < deviceCount; ++i) + { + PaWinWdmDeviceInfo* pDevice = (PaWinWdmDeviceInfo*)scanDeviceInfosResults->deviceInfos[i]; + if (pDevice->filter != 0) + { + FilterFree(pDevice->filter); + } + } + + PaUtil_GroupFreeMemory( winDsHostApi->allocations, scanDeviceInfosResults->deviceInfos[0] ); /* all device info structs are allocated in a block so we can destroy them here */ + PaUtil_GroupFreeMemory( winDsHostApi->allocations, scanDeviceInfosResults->deviceInfos ); + } + + PaUtil_GroupFreeMemory( winDsHostApi->allocations, scanDeviceInfosResults ); + } + + return paNoError; + +} + PaError PaWinWdm_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex ) { PaError result = paNoError; - int i, deviceCount; + int deviceCount = 0; + void *scanResults = 0; PaWinWdmHostApiRepresentation *wdmHostApi; - PaWinWdmDeviceInfo *deviceInfoArray; - PaWinWdmFilter* pFilter; - PaWinWdmDeviceInfo *wdmDeviceInfo; - PaDeviceInfo *deviceInfo; PA_LOGE_; +#ifdef PA_WDMKS_SET_TREF + tRef = PaUtil_GetTime(); +#endif + /* Attempt to load the KSUSER.DLL without which we cannot create pins We will unload this on termination @@ -1779,6 +3687,18 @@ PaError PaWinWdm_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd goto error; } + /* Attempt to load AVRT.DLL, if we can't, then we'll just use time critical prio instead... */ + if(DllAvRt == NULL) + { + DllAvRt = LoadLibrary(TEXT("avrt.dll")); + if (DllAvRt != NULL) + { + FunctionAvSetMmThreadCharacteristics = (AVSETMMTHREADCHARACTERISTICS*)GetProcAddress(DllAvRt,"AvSetMmThreadCharacteristicsA"); + FunctionAvRevertMmThreadCharacteristics = (AVREVERTMMTHREADCHARACTERISTICS*)GetProcAddress(DllAvRt, "AvRevertMmThreadCharacteristics"); + FunctionAvSetMmThreadPriority = (AVSETMMTHREADPRIORITY*)GetProcAddress(DllAvRt, "AvSetMmThreadPriority"); + } + } + FunctionKsCreatePin = (KSCREATEPIN*)GetProcAddress(DllKsUser, "KsCreatePin"); if(FunctionKsCreatePin == NULL) goto error; @@ -1797,129 +3717,50 @@ PaError PaWinWdm_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd goto error; } - result = BuildFilterList( wdmHostApi ); - if( result != paNoError ) - { - goto error; - } - deviceCount = wdmHostApi->filterCount; - *hostApi = &wdmHostApi->inheritedHostApiRep; (*hostApi)->info.structVersion = 1; (*hostApi)->info.type = paWDMKS; (*hostApi)->info.name = "Windows WDM-KS"; + + /* these are all updated by CommitDeviceInfos() */ + (*hostApi)->info.deviceCount = 0; (*hostApi)->info.defaultInputDevice = paNoDevice; (*hostApi)->info.defaultOutputDevice = paNoDevice; + (*hostApi)->deviceInfos = 0; - if( deviceCount > 0 ) + result = ScanDeviceInfos(&wdmHostApi->inheritedHostApiRep, hostApiIndex, &scanResults, &deviceCount); + if (result != paNoError) { - (*hostApi)->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory( - wdmHostApi->allocations, sizeof(PaWinWdmDeviceInfo*) * deviceCount ); - if( !(*hostApi)->deviceInfos ) - { - result = paInsufficientMemory; - goto error; - } - - /* allocate all device info structs in a contiguous block */ - deviceInfoArray = (PaWinWdmDeviceInfo*)PaUtil_GroupAllocateMemory( - wdmHostApi->allocations, sizeof(PaWinWdmDeviceInfo) * deviceCount ); - if( !deviceInfoArray ) - { - result = paInsufficientMemory; - goto error; - } - - for( i=0; i < deviceCount; ++i ) - { - wdmDeviceInfo = &deviceInfoArray[i]; - deviceInfo = &wdmDeviceInfo->inheritedDeviceInfo; - pFilter = wdmHostApi->filters[i]; - if( pFilter == NULL ) - continue; - wdmDeviceInfo->filter = pFilter; - deviceInfo->structVersion = 2; - deviceInfo->hostApi = hostApiIndex; - deviceInfo->name = (char*)pFilter->friendlyName; - PA_DEBUG(("Device found name: %s\n",(char*)pFilter->friendlyName)); - deviceInfo->maxInputChannels = pFilter->maxInputChannels; - if(deviceInfo->maxInputChannels > 0) - { - /* Set the default input device to the first device we find with - * more than zero input channels - **/ - if((*hostApi)->info.defaultInputDevice == paNoDevice) - { - (*hostApi)->info.defaultInputDevice = i; - } - } - - deviceInfo->maxOutputChannels = pFilter->maxOutputChannels; - if(deviceInfo->maxOutputChannels > 0) - { - /* Set the default output device to the first device we find with - * more than zero output channels - **/ - if((*hostApi)->info.defaultOutputDevice == paNoDevice) - { - (*hostApi)->info.defaultOutputDevice = i; - } - } - - /* These low values are not very useful because - * a) The lowest latency we end up with can depend on many factors such - * as the device buffer sizes/granularities, sample rate, channels and format - * b) We cannot know the device buffer sizes until we try to open/use it at - * a particular setting - * So: we give 512x48000Hz frames as the default low input latency - **/ - deviceInfo->defaultLowInputLatency = (512.0/48000.0); - deviceInfo->defaultLowOutputLatency = (512.0/48000.0); - deviceInfo->defaultHighInputLatency = (4096.0/48000.0); - deviceInfo->defaultHighOutputLatency = (4096.0/48000.0); - deviceInfo->defaultSampleRate = (double)(pFilter->bestSampleRate); - - (*hostApi)->deviceInfos[i] = deviceInfo; - } + goto error; } - (*hostApi)->info.deviceCount = deviceCount; + CommitDeviceInfos(&wdmHostApi->inheritedHostApiRep, hostApiIndex, scanResults, deviceCount); (*hostApi)->Terminate = Terminate; (*hostApi)->OpenStream = OpenStream; (*hostApi)->IsFormatSupported = IsFormatSupported; - + /* In preparation for hotplug + (*hostApi)->ScanDeviceInfos = ScanDeviceInfos; + (*hostApi)->CommitDeviceInfos = CommitDeviceInfos; + (*hostApi)->DisposeDeviceInfos = DisposeDeviceInfos; + */ PaUtil_InitializeStreamInterface( &wdmHostApi->callbackStreamInterface, CloseStream, StartStream, - StopStream, AbortStream, IsStreamStopped, IsStreamActive, - GetStreamTime, GetStreamCpuLoad, - PaUtil_DummyRead, PaUtil_DummyWrite, - PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable ); + StopStream, AbortStream, IsStreamStopped, IsStreamActive, + GetStreamTime, GetStreamCpuLoad, + PaUtil_DummyRead, PaUtil_DummyWrite, + PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable ); PaUtil_InitializeStreamInterface( &wdmHostApi->blockingStreamInterface, CloseStream, StartStream, - StopStream, AbortStream, IsStreamStopped, IsStreamActive, - GetStreamTime, PaUtil_DummyGetCpuLoad, - ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable ); + StopStream, AbortStream, IsStreamStopped, IsStreamActive, + GetStreamTime, PaUtil_DummyGetCpuLoad, + ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable ); PA_LOGL_; return result; error: - if( DllKsUser != NULL ) - { - FreeLibrary( DllKsUser ); - DllKsUser = NULL; - } + Terminate( (PaUtilHostApiRepresentation*)wdmHostApi ); - if( wdmHostApi ) - { - PaUtil_FreeMemory( wdmHostApi->filters ); - if( wdmHostApi->allocations ) - { - PaUtil_FreeAllAllocations( wdmHostApi->allocations ); - PaUtil_DestroyAllocationGroup( wdmHostApi->allocations ); - } - PaUtil_FreeMemory( wdmHostApi ); - } PA_LOGL_; return result; } @@ -1928,85 +3769,42 @@ error: static void Terminate( struct PaUtilHostApiRepresentation *hostApi ) { PaWinWdmHostApiRepresentation *wdmHostApi = (PaWinWdmHostApiRepresentation*)hostApi; - int i; PA_LOGE_; - if( wdmHostApi->filters ) + /* Do not unload the libraries */ + if( DllKsUser != NULL ) { - for( i=0; ifilterCount; i++) + FreeLibrary( DllKsUser ); + DllKsUser = NULL; + } + + if( DllAvRt != NULL ) + { + FreeLibrary( DllAvRt ); + DllAvRt = NULL; + } + + if( wdmHostApi) + { + PaWinWDMScanDeviceInfosResults* localScanResults = (PaWinWDMScanDeviceInfosResults*)PaUtil_GroupAllocateMemory( + wdmHostApi->allocations, sizeof(PaWinWDMScanDeviceInfosResults)); + localScanResults->deviceInfos = hostApi->deviceInfos; + DisposeDeviceInfos(hostApi, localScanResults, hostApi->info.deviceCount); + + if( wdmHostApi->allocations ) { - if( wdmHostApi->filters[i] != NULL ) - { - FilterFree( wdmHostApi->filters[i] ); - wdmHostApi->filters[i] = NULL; - } + PaUtil_FreeAllAllocations( wdmHostApi->allocations ); + PaUtil_DestroyAllocationGroup( wdmHostApi->allocations ); } + PaUtil_FreeMemory( wdmHostApi ); } - PaUtil_FreeMemory( wdmHostApi->filters ); - if( wdmHostApi->allocations ) - { - PaUtil_FreeAllAllocations( wdmHostApi->allocations ); - PaUtil_DestroyAllocationGroup( wdmHostApi->allocations ); - } - PaUtil_FreeMemory( wdmHostApi ); - PA_LOGL_; -} - -static void FillWFEXT( WAVEFORMATEXTENSIBLE* pwfext, PaSampleFormat sampleFormat, double sampleRate, int channelCount) -{ - PA_LOGE_; - PA_DEBUG(( "sampleFormat = %lx\n" , sampleFormat )); - PA_DEBUG(( "sampleRate = %f\n" , sampleRate )); - PA_DEBUG(( "chanelCount = %d\n", channelCount )); - - pwfext->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; - pwfext->Format.nChannels = channelCount; - pwfext->Format.nSamplesPerSec = (int)sampleRate; - if(channelCount == 1) - pwfext->dwChannelMask = KSAUDIO_SPEAKER_DIRECTOUT; - else - pwfext->dwChannelMask = KSAUDIO_SPEAKER_STEREO; - if(sampleFormat == paFloat32) - { - pwfext->Format.nBlockAlign = channelCount * 4; - pwfext->Format.wBitsPerSample = 32; - pwfext->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX); - pwfext->Samples.wValidBitsPerSample = 32; - pwfext->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; - } - else if(sampleFormat == paInt32) - { - pwfext->Format.nBlockAlign = channelCount * 4; - pwfext->Format.wBitsPerSample = 32; - pwfext->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX); - pwfext->Samples.wValidBitsPerSample = 32; - pwfext->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - } - else if(sampleFormat == paInt24) - { - pwfext->Format.nBlockAlign = channelCount * 3; - pwfext->Format.wBitsPerSample = 24; - pwfext->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX); - pwfext->Samples.wValidBitsPerSample = 24; - pwfext->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - } - else if(sampleFormat == paInt16) - { - pwfext->Format.nBlockAlign = channelCount * 2; - pwfext->Format.wBitsPerSample = 16; - pwfext->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX); - pwfext->Samples.wValidBitsPerSample = 16; - pwfext->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - } - pwfext->Format.nAvgBytesPerSec = pwfext->Format.nSamplesPerSec * pwfext->Format.nBlockAlign; - PA_LOGL_; } static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi, - const PaStreamParameters *inputParameters, - const PaStreamParameters *outputParameters, - double sampleRate ) + const PaStreamParameters *inputParameters, + const PaStreamParameters *outputParameters, + double sampleRate ) { int inputChannelCount, outputChannelCount; PaSampleFormat inputSampleFormat, outputSampleFormat; @@ -2014,49 +3812,114 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi, PaWinWdmFilter* pFilter; int result = paFormatIsSupported; WAVEFORMATEXTENSIBLE wfx; + PaWinWaveFormatChannelMask channelMask; PA_LOGE_; if( inputParameters ) { + PaWinWdmDeviceInfo* pDeviceInfo = (PaWinWdmDeviceInfo*)wdmHostApi->inheritedHostApiRep.deviceInfos[inputParameters->device]; + PaWinWdmPin* pin; + unsigned fmt; + unsigned long testFormat = 0; + unsigned validBits = 0; + inputChannelCount = inputParameters->channelCount; inputSampleFormat = inputParameters->sampleFormat; /* all standard sample formats are supported by the buffer adapter, - this implementation doesn't support any custom sample formats */ + this implementation doesn't support any custom sample formats */ if( inputSampleFormat & paCustomFormat ) + { + PaWinWDM_SetLastErrorInfo(paSampleFormatNotSupported, "IsFormatSupported: Custom input format not supported"); return paSampleFormatNotSupported; + } /* unless alternate device specification is supported, reject the use of - paUseHostApiSpecificDeviceSpecification */ + paUseHostApiSpecificDeviceSpecification */ if( inputParameters->device == paUseHostApiSpecificDeviceSpecification ) + { + PaWinWDM_SetLastErrorInfo(paInvalidDevice, "IsFormatSupported: paUseHostApiSpecificDeviceSpecification not supported"); return paInvalidDevice; + } /* check that input device can support inputChannelCount */ if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels ) + { + PaWinWDM_SetLastErrorInfo(paInvalidChannelCount, "IsFormatSupported: Invalid input channel count"); return paInvalidChannelCount; + } /* validate inputStreamInfo */ if( inputParameters->hostApiSpecificStreamInfo ) + { + PaWinWDM_SetLastErrorInfo(paIncompatibleHostApiSpecificStreamInfo, "Host API stream info not supported"); return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */ + } + + pFilter = pDeviceInfo->filter; + pin = pFilter->pins[pDeviceInfo->pin]; + + /* Find out the testing format */ + for (fmt = paFloat32; fmt <= paUInt8; fmt <<= 1) + { + if ((fmt & pin->formats) != 0) + { + /* Found a matching format! */ + testFormat = fmt; + break; + } + } + if (testFormat == 0) + { + PaWinWDM_SetLastErrorInfo(result, "IsFormatSupported(capture) failed: no testformat found!"); + return paUnanticipatedHostError; + } + + /* Due to special considerations, WaveRT devices with paInt24 should be tested with paInt32 and + valid bits = 24 (instead of 24 bit samples) */ + if (pFilter->devInfo.streamingType == Type_kWaveRT && testFormat == paInt24) + { + PA_DEBUG(("IsFormatSupported (capture): WaveRT overriding testFormat paInt24 with paInt32 (24 valid bits)")); + testFormat = paInt32; + validBits = 24; + } /* Check that the input format is supported */ - FillWFEXT(&wfx,paInt16,sampleRate,inputChannelCount); + channelMask = PaWin_DefaultChannelMask(inputChannelCount); + PaWin_InitializeWaveFormatExtensible((PaWinWaveFormat*)&wfx, + inputChannelCount, + testFormat, + PaWin_SampleFormatToLinearWaveFormatTag(testFormat), + sampleRate, + channelMask ); + if (validBits != 0) + { + wfx.Samples.wValidBitsPerSample = validBits; + } - pFilter = wdmHostApi->filters[inputParameters->device]; - result = FilterCanCreateCapturePin(pFilter,(const WAVEFORMATEX*)&wfx); + result = PinIsFormatSupported(pin, (const WAVEFORMATEX*)&wfx); if( result != paNoError ) { /* Try a WAVE_FORMAT_PCM instead */ - wfx.Format.wFormatTag = WAVE_FORMAT_PCM; - wfx.Format.cbSize = 0; - wfx.Samples.wValidBitsPerSample = 0; - wfx.dwChannelMask = 0; - wfx.SubFormat = GUID_NULL; - result = FilterCanCreateCapturePin(pFilter,(const WAVEFORMATEX*)&wfx); + PaWin_InitializeWaveFormatEx((PaWinWaveFormat*)&wfx, + inputChannelCount, + testFormat, + PaWin_SampleFormatToLinearWaveFormatTag(testFormat), + sampleRate); + + if (validBits != 0) + { + wfx.Samples.wValidBitsPerSample = validBits; + } + + result = PinIsFormatSupported(pin, (const WAVEFORMATEX*)&wfx); if( result != paNoError ) - return result; + { + PaWinWDM_SetLastErrorInfo(result, "IsFormatSupported(capture) failed: sr=%u,ch=%u,bits=%u", wfx.Format.nSamplesPerSec, wfx.Format.nChannels, wfx.Format.wBitsPerSample); + return result; + } } } else @@ -2066,44 +3929,109 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi, if( outputParameters ) { + PaWinWdmDeviceInfo* pDeviceInfo = (PaWinWdmDeviceInfo*)wdmHostApi->inheritedHostApiRep.deviceInfos[outputParameters->device]; + PaWinWdmPin* pin; + unsigned fmt; + unsigned long testFormat = 0; + unsigned validBits = 0; + outputChannelCount = outputParameters->channelCount; outputSampleFormat = outputParameters->sampleFormat; /* all standard sample formats are supported by the buffer adapter, - this implementation doesn't support any custom sample formats */ + this implementation doesn't support any custom sample formats */ if( outputSampleFormat & paCustomFormat ) + { + PaWinWDM_SetLastErrorInfo(paSampleFormatNotSupported, "IsFormatSupported: Custom output format not supported"); return paSampleFormatNotSupported; + } /* unless alternate device specification is supported, reject the use of - paUseHostApiSpecificDeviceSpecification */ + paUseHostApiSpecificDeviceSpecification */ if( outputParameters->device == paUseHostApiSpecificDeviceSpecification ) + { + PaWinWDM_SetLastErrorInfo(paInvalidDevice, "IsFormatSupported: paUseHostApiSpecificDeviceSpecification not supported"); return paInvalidDevice; + } /* check that output device can support outputChannelCount */ if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels ) + { + PaWinWDM_SetLastErrorInfo(paInvalidChannelCount, "Invalid output channel count"); return paInvalidChannelCount; + } /* validate outputStreamInfo */ if( outputParameters->hostApiSpecificStreamInfo ) + { + PaWinWDM_SetLastErrorInfo(paIncompatibleHostApiSpecificStreamInfo, "Host API stream info not supported"); return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */ + } + + pFilter = pDeviceInfo->filter; + pin = pFilter->pins[pDeviceInfo->pin]; + + /* Find out the testing format */ + for (fmt = paFloat32; fmt <= paUInt8; fmt <<= 1) + { + if ((fmt & pin->formats) != 0) + { + /* Found a matching format! */ + testFormat = fmt; + break; + } + } + if (testFormat == 0) + { + PaWinWDM_SetLastErrorInfo(result, "IsFormatSupported(render) failed: no testformat found!"); + return paUnanticipatedHostError; + } + + /* Due to special considerations, WaveRT devices with paInt24 should be tested with paInt32 and + valid bits = 24 (instead of 24 bit samples) */ + if (pFilter->devInfo.streamingType == Type_kWaveRT && testFormat == paInt24) + { + PA_DEBUG(("IsFormatSupported (render): WaveRT overriding testFormat paInt24 with paInt32 (24 valid bits)")); + testFormat = paInt32; + validBits = 24; + } /* Check that the output format is supported */ - FillWFEXT(&wfx,paInt16,sampleRate,outputChannelCount); + channelMask = PaWin_DefaultChannelMask(outputChannelCount); + PaWin_InitializeWaveFormatExtensible((PaWinWaveFormat*)&wfx, + outputChannelCount, + testFormat, + PaWin_SampleFormatToLinearWaveFormatTag(testFormat), + sampleRate, + channelMask ); - pFilter = wdmHostApi->filters[outputParameters->device]; - result = FilterCanCreateRenderPin(pFilter,(const WAVEFORMATEX*)&wfx); + if (validBits != 0) + { + wfx.Samples.wValidBitsPerSample = validBits; + } + + result = PinIsFormatSupported(pin, (const WAVEFORMATEX*)&wfx); if( result != paNoError ) { /* Try a WAVE_FORMAT_PCM instead */ - wfx.Format.wFormatTag = WAVE_FORMAT_PCM; - wfx.Format.cbSize = 0; - wfx.Samples.wValidBitsPerSample = 0; - wfx.dwChannelMask = 0; - wfx.SubFormat = GUID_NULL; - result = FilterCanCreateRenderPin(pFilter,(const WAVEFORMATEX*)&wfx); + PaWin_InitializeWaveFormatEx((PaWinWaveFormat*)&wfx, + outputChannelCount, + testFormat, + PaWin_SampleFormatToLinearWaveFormatTag(testFormat), + sampleRate); + + if (validBits != 0) + { + wfx.Samples.wValidBitsPerSample = validBits; + } + + result = PinIsFormatSupported(pin, (const WAVEFORMATEX*)&wfx); if( result != paNoError ) - return result; + { + PaWinWDM_SetLastErrorInfo(result, "IsFormatSupported(render) failed: %u,%u,%u", wfx.Format.nSamplesPerSec, wfx.Format.nChannels, wfx.Format.wBitsPerSample); + return result; + } } } @@ -2113,43 +4041,149 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi, } /* - IMPLEMENT ME: + IMPLEMENT ME: - - if a full duplex stream is requested, check that the combination - of input and output parameters is supported if necessary + - if a full duplex stream is requested, check that the combination + of input and output parameters is supported if necessary - - check that the device supports sampleRate + - check that the device supports sampleRate - Because the buffer adapter handles conversion between all standard - sample formats, the following checks are only required if paCustomFormat - is implemented, or under some other unusual conditions. + Because the buffer adapter handles conversion between all standard + sample formats, the following checks are only required if paCustomFormat + is implemented, or under some other unusual conditions. - - check that input device can support inputSampleFormat, or that - we have the capability to convert from inputSampleFormat to - a native format + - check that input device can support inputSampleFormat, or that + we have the capability to convert from inputSampleFormat to + a native format - - check that output device can support outputSampleFormat, or that - we have the capability to convert from outputSampleFormat to - a native format + - check that output device can support outputSampleFormat, or that + we have the capability to convert from outputSampleFormat to + a native format */ if((inputChannelCount == 0)&&(outputChannelCount == 0)) - result = paSampleFormatNotSupported; /* Not right error */ + { + PaWinWDM_SetLastErrorInfo(paSampleFormatNotSupported, "No input or output channels defined"); + result = paSampleFormatNotSupported; /* Not right error */ + } PA_LOGL_; return result; } +static void ResetStreamEvents(PaWinWdmStream* stream) +{ + unsigned i; + ResetEvent(stream->eventAbort); + ResetEvent(stream->eventStreamStart[StreamStart_kOk]); + ResetEvent(stream->eventStreamStart[StreamStart_kFailed]); + + for (i=0; icapture.noOfPackets; ++i) + { + if (stream->capture.events && stream->capture.events[i]) + { + ResetEvent(stream->capture.events[i]); + } + } + + for (i=0; irender.noOfPackets; ++i) + { + if (stream->render.events && stream->render.events[i]) + { + ResetEvent(stream->render.events[i]); + } + } +} + +static void CloseStreamEvents(PaWinWdmStream* stream) +{ + unsigned i; + PaWinWdmIOInfo* ios[2] = { &stream->capture, &stream->render }; + + if (stream->eventAbort) + { + CloseHandle(stream->eventAbort); + stream->eventAbort = 0; + } + if (stream->eventStreamStart[StreamStart_kOk]) + { + CloseHandle(stream->eventStreamStart[StreamStart_kOk]); + } + if (stream->eventStreamStart[StreamStart_kFailed]) + { + CloseHandle(stream->eventStreamStart[StreamStart_kFailed]); + } + + for (i = 0; i < 2; ++i) + { + unsigned j; + /* Unregister notification handles for WaveRT */ + if (ios[i]->pPin && ios[i]->pPin->parentFilter->devInfo.streamingType == Type_kWaveRT && + ios[i]->pPin->pinKsSubType == SubType_kNotification && + ios[i]->events != 0) + { + PinUnregisterNotificationHandle(ios[i]->pPin, ios[i]->events[0]); + } + + for (j=0; j < ios[i]->noOfPackets; ++j) + { + if (ios[i]->events && ios[i]->events[j]) + { + CloseHandle(ios[i]->events[j]); + ios[i]->events[j] = 0; + } + } + } +} + +static unsigned NextPowerOf2(unsigned val) +{ + val--; + val = (val >> 1) | val; + val = (val >> 2) | val; + val = (val >> 4) | val; + val = (val >> 8) | val; + val = (val >> 16) | val; + return ++val; +} + +static PaError ValidateSpecificStreamParameters( + const PaStreamParameters *streamParameters, + const PaWinWDMKSInfo *streamInfo) +{ + if( streamInfo ) + { + if( streamInfo->size != sizeof( PaWinWDMKSInfo ) + || streamInfo->version != 1 ) + { + PA_DEBUG(("Stream parameters: size or version not correct")); + return paIncompatibleHostApiSpecificStreamInfo; + } + + if (streamInfo->noOfPackets != 0 && + (streamInfo->noOfPackets < 2 || streamInfo->noOfPackets > 8)) + { + PA_DEBUG(("Stream parameters: noOfPackets %u out of range [2,8]", streamInfo->noOfPackets)); + return paIncompatibleHostApiSpecificStreamInfo; + } + + } + + return paNoError; +} + + + /* see pa_hostapi.h for a list of validity guarantees made about OpenStream parameters */ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, - PaStream** s, - const PaStreamParameters *inputParameters, - const PaStreamParameters *outputParameters, - double sampleRate, - unsigned long framesPerBuffer, - PaStreamFlags streamFlags, - PaStreamCallback *streamCallback, - void *userData ) + PaStream** s, + const PaStreamParameters *inputParameters, + const PaStreamParameters *outputParameters, + double sampleRate, + unsigned long framesPerUserBuffer, + PaStreamFlags streamFlags, + PaStreamCallback *streamCallback, + void *userData ) { PaError result = paNoError; PaWinWdmHostApiRepresentation *wdmHostApi = (PaWinWdmHostApiRepresentation*)hostApi; @@ -2158,13 +4192,11 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, PaSampleFormat inputSampleFormat, outputSampleFormat; PaSampleFormat hostInputSampleFormat, hostOutputSampleFormat; int userInputChannels,userOutputChannels; - int size; - PaWinWdmFilter* pFilter; WAVEFORMATEXTENSIBLE wfx; PA_LOGE_; PA_DEBUG(("OpenStream:sampleRate = %f\n",sampleRate)); - PA_DEBUG(("OpenStream:framesPerBuffer = %lu\n",framesPerBuffer)); + PA_DEBUG(("OpenStream:framesPerBuffer = %lu\n",framesPerUserBuffer)); if( inputParameters ) { @@ -2172,24 +4204,33 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, inputSampleFormat = inputParameters->sampleFormat; /* unless alternate device specification is supported, reject the use of - paUseHostApiSpecificDeviceSpecification */ + paUseHostApiSpecificDeviceSpecification */ if( inputParameters->device == paUseHostApiSpecificDeviceSpecification ) + { + PaWinWDM_SetLastErrorInfo(paInvalidDevice, "paUseHostApiSpecificDeviceSpecification(in) not supported"); return paInvalidDevice; + } /* check that input device can support stream->userInputChannels */ if( userInputChannels > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels ) + { + PaWinWDM_SetLastErrorInfo(paInvalidChannelCount, "Invalid input channel count"); return paInvalidChannelCount; + } /* validate inputStreamInfo */ - if( inputParameters->hostApiSpecificStreamInfo ) - return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */ - + result = ValidateSpecificStreamParameters(inputParameters, inputParameters->hostApiSpecificStreamInfo); + if(result != paNoError) + { + PaWinWDM_SetLastErrorInfo(result, "Host API stream info not supported (in)"); + return result; /* this implementation doesn't use custom stream info */ + } } else { userInputChannels = 0; - inputSampleFormat = hostInputSampleFormat = paInt16; /* Surpress 'uninitialised var' warnings. */ + inputSampleFormat = hostInputSampleFormat = paInt16; /* Supress 'uninitialised var' warnings. */ } if( outputParameters ) @@ -2198,29 +4239,41 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, outputSampleFormat = outputParameters->sampleFormat; /* unless alternate device specification is supported, reject the use of - paUseHostApiSpecificDeviceSpecification */ + paUseHostApiSpecificDeviceSpecification */ if( outputParameters->device == paUseHostApiSpecificDeviceSpecification ) + { + PaWinWDM_SetLastErrorInfo(paInvalidDevice, "paUseHostApiSpecificDeviceSpecification(out) not supported"); return paInvalidDevice; + } /* check that output device can support stream->userInputChannels */ if( userOutputChannels > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels ) + { + PaWinWDM_SetLastErrorInfo(paInvalidChannelCount, "Invalid output channel count"); return paInvalidChannelCount; + } /* validate outputStreamInfo */ - if( outputParameters->hostApiSpecificStreamInfo ) - return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */ - + result = ValidateSpecificStreamParameters( outputParameters, outputParameters->hostApiSpecificStreamInfo ); + if (result != paNoError) + { + PaWinWDM_SetLastErrorInfo(result, "Host API stream info not supported (out)"); + return result; /* this implementation doesn't use custom stream info */ + } } else { userOutputChannels = 0; - outputSampleFormat = hostOutputSampleFormat = paInt16; /* Surpress 'uninitialized var' warnings. */ + outputSampleFormat = hostOutputSampleFormat = paInt16; /* Supress 'uninitialized var' warnings. */ } /* validate platform specific flags */ if( (streamFlags & paPlatformSpecificFlags) != 0 ) + { + PaWinWDM_SetLastErrorInfo(paInvalidFlag, "Invalid flag supplied"); return paInvalidFlag; /* unexpected platform specific flag */ + } stream = (PaWinWdmStream*)PaUtil_AllocateMemory( sizeof(PaWinWdmStream) ); if( !stream ) @@ -2228,18 +4281,33 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, result = paInsufficientMemory; goto error; } + + /* Create allocation group */ + stream->allocGroup = PaUtil_CreateAllocationGroup(); + if( !stream->allocGroup ) + { + result = paInsufficientMemory; + goto error; + } + /* Zero the stream object */ /* memset((void*)stream,0,sizeof(PaWinWdmStream)); */ if( streamCallback ) { PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation, - &wdmHostApi->callbackStreamInterface, streamCallback, userData ); + &wdmHostApi->callbackStreamInterface, streamCallback, userData ); } else { - PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation, - &wdmHostApi->blockingStreamInterface, streamCallback, userData ); + /* PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation, + &wdmHostApi->blockingStreamInterface, streamCallback, userData ); */ + + /* We don't support the blocking API yet */ + PA_DEBUG(("Blocking API not supported yet!\n")); + PaWinWDM_SetLastErrorInfo(paUnanticipatedHostError, "Blocking API not supported yet"); + result = paUnanticipatedHostError; + goto error; } PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate ); @@ -2247,315 +4315,767 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, /* Instantiate the input pin if necessary */ if(userInputChannels > 0) { + PaWinWdmFilter* pFilter; + PaWinWdmDeviceInfo* pDeviceInfo; + PaWinWdmPin* pPin; + unsigned validBitsPerSample = 0; + PaWinWaveFormatChannelMask channelMask = PaWin_DefaultChannelMask( userInputChannels ); + result = paSampleFormatNotSupported; - pFilter = wdmHostApi->filters[inputParameters->device]; + pDeviceInfo = (PaWinWdmDeviceInfo*)wdmHostApi->inheritedHostApiRep.deviceInfos[inputParameters->device]; + pFilter = pDeviceInfo->filter; + pPin = pFilter->pins[pDeviceInfo->pin]; + stream->userInputChannels = userInputChannels; - if(((inputSampleFormat & ~paNonInterleaved) & pFilter->formats) != 0) - { /* inputSampleFormat is supported, so try to use it */ - hostInputSampleFormat = inputSampleFormat; - FillWFEXT(&wfx, hostInputSampleFormat, sampleRate, stream->userInputChannels); - stream->bytesPerInputFrame = wfx.Format.nBlockAlign; - stream->recordingPin = FilterCreateCapturePin(pFilter, (const WAVEFORMATEX*)&wfx, &result); - stream->deviceInputChannels = stream->userInputChannels; - } - - if(result != paNoError) - { /* Search through all PaSampleFormats to find one that works */ - hostInputSampleFormat = paFloat32; - - do { - FillWFEXT(&wfx, hostInputSampleFormat, sampleRate, stream->userInputChannels); - stream->bytesPerInputFrame = wfx.Format.nBlockAlign; - stream->recordingPin = FilterCreateCapturePin(pFilter, (const WAVEFORMATEX*)&wfx, &result); - stream->deviceInputChannels = stream->userInputChannels; - - if(stream->recordingPin == NULL) result = paSampleFormatNotSupported; - if(result != paNoError) hostInputSampleFormat <<= 1; - } - while(result != paNoError && hostInputSampleFormat <= paUInt8); - } - - if(result != paNoError) - { /* None of the PaSampleFormats worked. Set the hostInputSampleFormat to the best fit - * and try a PCM format. - **/ - hostInputSampleFormat = - PaUtil_SelectClosestAvailableFormat( pFilter->formats, inputSampleFormat ); - - /* Try a WAVE_FORMAT_PCM instead */ - wfx.Format.wFormatTag = WAVE_FORMAT_PCM; - wfx.Format.cbSize = 0; - wfx.Samples.wValidBitsPerSample = 0; - wfx.dwChannelMask = 0; - wfx.SubFormat = GUID_NULL; - stream->recordingPin = FilterCreateCapturePin(pFilter,(const WAVEFORMATEX*)&wfx,&result); - if(stream->recordingPin == NULL) result = paSampleFormatNotSupported; - } - - if( result != paNoError ) + hostInputSampleFormat = PaUtil_SelectClosestAvailableFormat( pPin->formats, inputSampleFormat ); + if (hostInputSampleFormat == paSampleFormatNotSupported) { - /* Some or all KS devices can only handle the exact number of channels - * they specify. But PortAudio clients expect to be able to - * at least specify mono I/O on a multi-channel device - * If this is the case, then we will do the channel mapping internally - **/ - if( stream->userInputChannels < pFilter->maxInputChannels ) - { - FillWFEXT(&wfx,hostInputSampleFormat,sampleRate,pFilter->maxInputChannels); - stream->bytesPerInputFrame = wfx.Format.nBlockAlign; - stream->recordingPin = FilterCreateCapturePin(pFilter,(const WAVEFORMATEX*)&wfx,&result); - stream->deviceInputChannels = pFilter->maxInputChannels; + result = paUnanticipatedHostError; + PaWinWDM_SetLastErrorInfo(result, "PU_SCAF(%X,%X) failed (input)", pPin->formats, inputSampleFormat); + goto error; + } + else if (pFilter->devInfo.streamingType == Type_kWaveRT && hostInputSampleFormat == paInt24) + { + /* For WaveRT, we choose 32 bit format instead of paInt24, since we MIGHT need to align buffer on a + 128 byte boundary (see PinGetBuffer) */ + hostInputSampleFormat = paInt32; + /* But we'll tell the driver that it's 24 bit in 32 bit container */ + validBitsPerSample = 24; + } - if( result != paNoError ) + while (hostInputSampleFormat <= paUInt8) + { + unsigned channelsToProbe = stream->userInputChannels; + /* Some or all KS devices can only handle the exact number of channels + * they specify. But PortAudio clients expect to be able to + * at least specify mono I/O on a multi-channel device + * If this is the case, then we will do the channel mapping internally + * The following loop tests this case + **/ + while (1) + { + PaWin_InitializeWaveFormatExtensible((PaWinWaveFormat*)&wfx, + channelsToProbe, + hostInputSampleFormat, + PaWin_SampleFormatToLinearWaveFormatTag(hostInputSampleFormat), + sampleRate, + channelMask ); + stream->capture.bytesPerFrame = wfx.Format.nBlockAlign; + if (validBitsPerSample != 0) + { + wfx.Samples.wValidBitsPerSample = validBitsPerSample; + } + stream->capture.pPin = FilterCreatePin(pFilter, pPin->pinId, (WAVEFORMATEX*)&wfx, &result); + stream->deviceInputChannels = channelsToProbe; + + if( result != paNoError && result != paDeviceUnavailable ) { /* Try a WAVE_FORMAT_PCM instead */ - wfx.Format.wFormatTag = WAVE_FORMAT_PCM; - wfx.Format.cbSize = 0; - wfx.Samples.wValidBitsPerSample = 0; - wfx.dwChannelMask = 0; - wfx.SubFormat = GUID_NULL; - stream->recordingPin = FilterCreateCapturePin(pFilter,(const WAVEFORMATEX*)&wfx,&result); + PaWin_InitializeWaveFormatEx((PaWinWaveFormat*)&wfx, + channelsToProbe, + hostInputSampleFormat, + PaWin_SampleFormatToLinearWaveFormatTag(hostInputSampleFormat), + sampleRate); + if (validBitsPerSample != 0) + { + wfx.Samples.wValidBitsPerSample = validBitsPerSample; + } + stream->capture.pPin = FilterCreatePin(pFilter, pPin->pinId, (const WAVEFORMATEX*)&wfx, &result); } + + if (result == paDeviceUnavailable) goto occupied; + + if (result == paNoError) + { + /* We're done */ + break; + } + + if (channelsToProbe < (unsigned)pPin->maxChannels) + { + /* Go to next multiple of 2 */ + channelsToProbe = min((((channelsToProbe>>1)+1)<<1), (unsigned)pPin->maxChannels); + continue; + } + + break; } + + if (result == paNoError) + { + /* We're done */ + break; + } + + /* Go to next format in line with lower resolution */ + hostInputSampleFormat <<= 1; } - if(stream->recordingPin == NULL) + if(stream->capture.pPin == NULL) { + PaWinWDM_SetLastErrorInfo(result, "Failed to create capture pin: sr=%u,ch=%u,bits=%u,align=%u", + wfx.Format.nSamplesPerSec, wfx.Format.nChannels, wfx.Format.wBitsPerSample, wfx.Format.nBlockAlign); goto error; } - switch(hostInputSampleFormat) + /* Select correct mux input on MUX node of topology filter */ + if (pDeviceInfo->muxPosition >= 0) { - case paInt16: stream->inputSampleSize = 2; break; - case paInt24: stream->inputSampleSize = 3; break; - case paInt32: - case paFloat32: stream->inputSampleSize = 4; break; + assert(pPin->parentFilter->topologyFilter != NULL); + + result = FilterUse(pPin->parentFilter->topologyFilter); + if (result != paNoError) + { + PaWinWDM_SetLastErrorInfo(result, "Failed to open topology filter"); + goto error; + } + + result = WdmSetMuxNodeProperty(pPin->parentFilter->topologyFilter->handle, + pPin->inputs[pDeviceInfo->muxPosition]->muxNodeId, + pPin->inputs[pDeviceInfo->muxPosition]->muxPinId); + + FilterRelease(pPin->parentFilter->topologyFilter); + + if(result != paNoError) + { + PaWinWDM_SetLastErrorInfo(result, "Failed to set topology mux node"); + goto error; + } } - stream->recordingPin->frameSize /= stream->bytesPerInputFrame; - PA_DEBUG(("Pin output frames: %d\n",stream->recordingPin->frameSize)); + stream->capture.bytesPerSample = stream->capture.bytesPerFrame / stream->deviceInputChannels; + stream->capture.pPin->frameSize /= stream->capture.bytesPerFrame; + PA_DEBUG(("Capture pin frames: %d\n",stream->capture.pPin->frameSize)); } else { - stream->recordingPin = NULL; - stream->bytesPerInputFrame = 0; + stream->capture.pPin = NULL; + stream->capture.bytesPerFrame = 0; } /* Instantiate the output pin if necessary */ if(userOutputChannels > 0) { + PaWinWdmFilter* pFilter; + PaWinWdmDeviceInfo* pDeviceInfo; + PaWinWdmPin* pPin; + unsigned validBitsPerSample = 0; + PaWinWaveFormatChannelMask channelMask = PaWin_DefaultChannelMask( userOutputChannels ); + result = paSampleFormatNotSupported; - pFilter = wdmHostApi->filters[outputParameters->device]; + pDeviceInfo = (PaWinWdmDeviceInfo*)wdmHostApi->inheritedHostApiRep.deviceInfos[outputParameters->device]; + pFilter = pDeviceInfo->filter; + pPin = pFilter->pins[pDeviceInfo->pin]; + stream->userOutputChannels = userOutputChannels; - if(((outputSampleFormat & ~paNonInterleaved) & pFilter->formats) != 0) + hostOutputSampleFormat = PaUtil_SelectClosestAvailableFormat( pPin->formats, outputSampleFormat ); + if (hostOutputSampleFormat == paSampleFormatNotSupported) { - hostOutputSampleFormat = outputSampleFormat; - FillWFEXT(&wfx,hostOutputSampleFormat,sampleRate,stream->userOutputChannels); - stream->bytesPerOutputFrame = wfx.Format.nBlockAlign; - stream->playbackPin = FilterCreateRenderPin(pFilter,(WAVEFORMATEX*)&wfx,&result); - stream->deviceOutputChannels = stream->userOutputChannels; + result = paUnanticipatedHostError; + PaWinWDM_SetLastErrorInfo(result, "PU_SCAF(%X,%X) failed (output)", pPin->formats, hostOutputSampleFormat); + goto error; + } + else if (pFilter->devInfo.streamingType == Type_kWaveRT && hostOutputSampleFormat == paInt24) + { + /* For WaveRT, we choose 32 bit format instead of paInt24, since we MIGHT need to align buffer on a + 128 byte boundary (see PinGetBuffer) */ + hostOutputSampleFormat = paInt32; + /* But we'll tell the driver that it's 24 bit in 32 bit container */ + validBitsPerSample = 24; } - if(result != paNoError) - { - hostOutputSampleFormat = paFloat32; - - do { - FillWFEXT(&wfx,hostOutputSampleFormat,sampleRate,stream->userOutputChannels); - stream->bytesPerOutputFrame = wfx.Format.nBlockAlign; - stream->playbackPin = FilterCreateRenderPin(pFilter,(WAVEFORMATEX*)&wfx,&result); - stream->deviceOutputChannels = stream->userOutputChannels; - - if(stream->playbackPin == NULL) result = paSampleFormatNotSupported; - if(result != paNoError) hostOutputSampleFormat <<= 1; - } - while(result != paNoError && hostOutputSampleFormat <= paUInt8); - } - - if(result != paNoError) - { - hostOutputSampleFormat = - PaUtil_SelectClosestAvailableFormat( pFilter->formats, outputSampleFormat ); - - /* Try a WAVE_FORMAT_PCM instead */ - wfx.Format.wFormatTag = WAVE_FORMAT_PCM; - wfx.Format.cbSize = 0; - wfx.Samples.wValidBitsPerSample = 0; - wfx.dwChannelMask = 0; - wfx.SubFormat = GUID_NULL; - stream->playbackPin = FilterCreateRenderPin(pFilter,(WAVEFORMATEX*)&wfx,&result); - if(stream->playbackPin == NULL) result = paSampleFormatNotSupported; - } - - if( result != paNoError ) + while (hostOutputSampleFormat <= paUInt8) { + unsigned channelsToProbe = stream->userOutputChannels; /* Some or all KS devices can only handle the exact number of channels - * they specify. But PortAudio clients expect to be able to - * at least specify mono I/O on a multi-channel device - * If this is the case, then we will do the channel mapping internally - **/ - if( stream->userOutputChannels < pFilter->maxOutputChannels ) + * they specify. But PortAudio clients expect to be able to + * at least specify mono I/O on a multi-channel device + * If this is the case, then we will do the channel mapping internally + * The following loop tests this case + **/ + while (1) { - FillWFEXT(&wfx,hostOutputSampleFormat,sampleRate,pFilter->maxOutputChannels); - stream->bytesPerOutputFrame = wfx.Format.nBlockAlign; - stream->playbackPin = FilterCreateRenderPin(pFilter,(const WAVEFORMATEX*)&wfx,&result); - stream->deviceOutputChannels = pFilter->maxOutputChannels; - if( result != paNoError ) + PaWin_InitializeWaveFormatExtensible((PaWinWaveFormat*)&wfx, + channelsToProbe, + hostOutputSampleFormat, + PaWin_SampleFormatToLinearWaveFormatTag(hostOutputSampleFormat), + sampleRate, + channelMask ); + stream->render.bytesPerFrame = wfx.Format.nBlockAlign; + if (validBitsPerSample != 0) { - /* Try a WAVE_FORMAT_PCM instead */ - wfx.Format.wFormatTag = WAVE_FORMAT_PCM; - wfx.Format.cbSize = 0; - wfx.Samples.wValidBitsPerSample = 0; - wfx.dwChannelMask = 0; - wfx.SubFormat = GUID_NULL; - stream->playbackPin = FilterCreateRenderPin(pFilter,(const WAVEFORMATEX*)&wfx,&result); + wfx.Samples.wValidBitsPerSample = validBitsPerSample; } + stream->render.pPin = FilterCreatePin(pFilter, pPin->pinId, (WAVEFORMATEX*)&wfx, &result); + stream->deviceOutputChannels = channelsToProbe; + + if( result != paNoError && result != paDeviceUnavailable ) + { + PaWin_InitializeWaveFormatEx((PaWinWaveFormat*)&wfx, + channelsToProbe, + hostOutputSampleFormat, + PaWin_SampleFormatToLinearWaveFormatTag(hostOutputSampleFormat), + sampleRate); + if (validBitsPerSample != 0) + { + wfx.Samples.wValidBitsPerSample = validBitsPerSample; + } + stream->render.pPin = FilterCreatePin(pFilter, pPin->pinId, (const WAVEFORMATEX*)&wfx, &result); + } + + if (result == paDeviceUnavailable) goto occupied; + + if (result == paNoError) + { + /* We're done */ + break; + } + + if (channelsToProbe < (unsigned)pPin->maxChannels) + { + /* Go to next multiple of 2 */ + channelsToProbe = min((((channelsToProbe>>1)+1)<<1), (unsigned)pPin->maxChannels); + continue; + } + + break; + }; + + if (result == paNoError) + { + /* We're done */ + break; } + + /* Go to next format in line with lower resolution */ + hostOutputSampleFormat <<= 1; } - if(stream->playbackPin == NULL) + if(stream->render.pPin == NULL) { + PaWinWDM_SetLastErrorInfo(result, "Failed to create render pin: sr=%u,ch=%u,bits=%u,align=%u", + wfx.Format.nSamplesPerSec, wfx.Format.nChannels, wfx.Format.wBitsPerSample, wfx.Format.nBlockAlign); goto error; } - switch(hostOutputSampleFormat) - { - case paInt16: stream->outputSampleSize = 2; break; - case paInt24: stream->outputSampleSize = 3; break; - case paInt32: - case paFloat32: stream->outputSampleSize = 4; break; - } - - stream->playbackPin->frameSize /= stream->bytesPerOutputFrame; - PA_DEBUG(("Pin output frames: %d\n",stream->playbackPin->frameSize)); + stream->render.bytesPerSample = stream->render.bytesPerFrame / stream->deviceOutputChannels; + stream->render.pPin->frameSize /= stream->render.bytesPerFrame; + PA_DEBUG(("Render pin frames: %d\n",stream->render.pPin->frameSize)); } else { - stream->playbackPin = NULL; - stream->bytesPerOutputFrame = 0; + stream->render.pPin = NULL; + stream->render.bytesPerFrame = 0; } /* Calculate the framesPerHostXxxxBuffer size based upon the suggested latency values */ - /* Record the buffer length */ if(inputParameters) { /* Calculate the frames from the user's value - add a bit to round up */ - stream->framesPerHostIBuffer = (unsigned long)((inputParameters->suggestedLatency*sampleRate)+0.0001); - if(stream->framesPerHostIBuffer > (unsigned long)sampleRate) + stream->capture.framesPerBuffer = (unsigned long)((inputParameters->suggestedLatency*sampleRate)+0.0001); + if(stream->capture.framesPerBuffer > (unsigned long)sampleRate) { /* Upper limit is 1 second */ - stream->framesPerHostIBuffer = (unsigned long)sampleRate; + stream->capture.framesPerBuffer = (unsigned long)sampleRate; } - else if(stream->framesPerHostIBuffer < stream->recordingPin->frameSize) + else if(stream->capture.framesPerBuffer < stream->capture.pPin->frameSize) { - stream->framesPerHostIBuffer = stream->recordingPin->frameSize; + stream->capture.framesPerBuffer = stream->capture.pPin->frameSize; + } + PA_DEBUG(("Input frames chosen:%ld\n",stream->capture.framesPerBuffer)); + + /* Setup number of packets to use */ + stream->capture.noOfPackets = 2; + + if (inputParameters->hostApiSpecificStreamInfo) + { + PaWinWDMKSInfo* pInfo = (PaWinWDMKSInfo*)inputParameters->hostApiSpecificStreamInfo; + + if (stream->capture.pPin->parentFilter->devInfo.streamingType == Type_kWaveCyclic && + pInfo->noOfPackets != 0) + { + stream->capture.noOfPackets = pInfo->noOfPackets; + } } - PA_DEBUG(("Input frames chosen:%ld\n",stream->framesPerHostIBuffer)); } if(outputParameters) { /* Calculate the frames from the user's value - add a bit to round up */ - stream->framesPerHostOBuffer = (unsigned long)((outputParameters->suggestedLatency*sampleRate)+0.0001); - if(stream->framesPerHostOBuffer > (unsigned long)sampleRate) + stream->render.framesPerBuffer = (unsigned long)((outputParameters->suggestedLatency*sampleRate)+0.0001); + if(stream->render.framesPerBuffer > (unsigned long)sampleRate) { /* Upper limit is 1 second */ - stream->framesPerHostOBuffer = (unsigned long)sampleRate; + stream->render.framesPerBuffer = (unsigned long)sampleRate; } - else if(stream->framesPerHostOBuffer < stream->playbackPin->frameSize) + else if(stream->render.framesPerBuffer < stream->render.pPin->frameSize) { - stream->framesPerHostOBuffer = stream->playbackPin->frameSize; + stream->render.framesPerBuffer = stream->render.pPin->frameSize; + } + PA_DEBUG(("Output frames chosen:%ld\n",stream->render.framesPerBuffer)); + + /* Setup number of packets to use */ + stream->render.noOfPackets = 2; + + if (outputParameters->hostApiSpecificStreamInfo) + { + PaWinWDMKSInfo* pInfo = (PaWinWDMKSInfo*)outputParameters->hostApiSpecificStreamInfo; + + if (stream->render.pPin->parentFilter->devInfo.streamingType == Type_kWaveCyclic && + pInfo->noOfPackets != 0) + { + stream->render.noOfPackets = pInfo->noOfPackets; + } } - PA_DEBUG(("Output frames chosen:%ld\n",stream->framesPerHostOBuffer)); } - /* Host buffer size is bounded to the largest of the input and output - frame sizes */ - + /* Host buffer size is bound to the largest of the input and output frame sizes */ result = PaUtil_InitializeBufferProcessor( &stream->bufferProcessor, - stream->userInputChannels, inputSampleFormat, hostInputSampleFormat, - stream->userOutputChannels, outputSampleFormat, hostOutputSampleFormat, - sampleRate, streamFlags, framesPerBuffer, - max(stream->framesPerHostOBuffer,stream->framesPerHostIBuffer), - paUtilBoundedHostBufferSize, - streamCallback, userData ); + stream->userInputChannels, inputSampleFormat, hostInputSampleFormat, + stream->userOutputChannels, outputSampleFormat, hostOutputSampleFormat, + sampleRate, streamFlags, framesPerUserBuffer, + max(stream->capture.framesPerBuffer, stream->render.framesPerBuffer), + paUtilBoundedHostBufferSize, + streamCallback, userData ); if( result != paNoError ) + { + PaWinWDM_SetLastErrorInfo(result, "PaUtil_InitializeBufferProcessor failed: ich=%u, isf=%u, hisf=%u, och=%u, osf=%u, hosf=%u, sr=%lf, flags=0x%X, fpub=%u, fphb=%u", + stream->userInputChannels, inputSampleFormat, hostInputSampleFormat, + stream->userOutputChannels, outputSampleFormat, hostOutputSampleFormat, + sampleRate, streamFlags, framesPerUserBuffer, + max(stream->capture.framesPerBuffer, stream->render.framesPerBuffer)); goto error; + } + + /* Allocate/get all the buffers for host I/O */ + if (stream->userInputChannels > 0) + { + stream->streamRepresentation.streamInfo.inputLatency = stream->capture.framesPerBuffer / sampleRate; + + switch (stream->capture.pPin->parentFilter->devInfo.streamingType) + { + case Type_kWaveCyclic: + { + unsigned size = stream->capture.noOfPackets * stream->capture.framesPerBuffer * stream->capture.bytesPerFrame; + /* Allocate input host buffer */ + stream->capture.hostBuffer = (char*)PaUtil_GroupAllocateMemory(stream->allocGroup, size); + PA_DEBUG(("Input buffer allocated (size = %u)\n", size)); + if( !stream->capture.hostBuffer ) + { + PA_DEBUG(("Cannot allocate host input buffer!\n")); + PaWinWDM_SetLastErrorInfo(paInsufficientMemory, "Failed to allocate input buffer"); + result = paInsufficientMemory; + goto error; + } + stream->capture.hostBufferSize = size; + PA_DEBUG(("Input buffer start = %p (size=%u)\n",stream->capture.hostBuffer, stream->capture.hostBufferSize)); + stream->capture.pPin->fnEventHandler = PaPinCaptureEventHandler_WaveCyclic; + stream->capture.pPin->fnSubmitHandler = PaPinCaptureSubmitHandler_WaveCyclic; + } + break; + case Type_kWaveRT: + { + const DWORD dwTotalSize = 2 * stream->capture.framesPerBuffer * stream->capture.bytesPerFrame; + DWORD dwRequestedSize = dwTotalSize; + BOOL bCallMemoryBarrier = FALSE; + ULONG hwFifoLatency = 0; + ULONG dummy; + result = PinGetBuffer(stream->capture.pPin, (void**)&stream->capture.hostBuffer, &dwRequestedSize, &bCallMemoryBarrier); + if (!result) + { + PA_DEBUG(("Input buffer start = %p, size = %u\n", stream->capture.hostBuffer, dwRequestedSize)); + if (dwRequestedSize != dwTotalSize) + { + PA_DEBUG(("Buffer length changed by driver from %u to %u !\n", dwTotalSize, dwRequestedSize)); + /* Recalculate to what the driver has given us */ + stream->capture.framesPerBuffer = dwRequestedSize / (2 * stream->capture.bytesPerFrame); + } + stream->capture.hostBufferSize = dwRequestedSize; + + if (stream->capture.pPin->pinKsSubType == SubType_kPolled) + { + stream->capture.pPin->fnEventHandler = PaPinCaptureEventHandler_WaveRTPolled; + stream->capture.pPin->fnSubmitHandler = PaPinCaptureSubmitHandler_WaveRTPolled; + } + else + { + stream->capture.pPin->fnEventHandler = PaPinCaptureEventHandler_WaveRTEvent; + stream->capture.pPin->fnSubmitHandler = PaPinCaptureSubmitHandler_WaveRTEvent; + } + + stream->capture.pPin->fnMemBarrier = bCallMemoryBarrier ? MemoryBarrierRead : MemoryBarrierDummy; + } + else + { + PA_DEBUG(("Failed to get input buffer (WaveRT)\n")); + PaWinWDM_SetLastErrorInfo(paUnanticipatedHostError, "Failed to get input buffer (WaveRT)"); + result = paUnanticipatedHostError; + goto error; + } + + /* Get latency */ + result = PinGetHwLatency(stream->capture.pPin, &hwFifoLatency, &dummy, &dummy); + if (result == paNoError) + { + stream->capture.pPin->hwLatency = hwFifoLatency; + + /* Add HW latency into total input latency */ + stream->streamRepresentation.streamInfo.inputLatency += ((hwFifoLatency / stream->capture.bytesPerFrame) / sampleRate); + } + else + { + PA_DEBUG(("Failed to get size of FIFO hardware buffer (is set to zero)\n")); + stream->capture.pPin->hwLatency = 0; + } + } + break; + default: + /* Undefined wave type!! */ + assert(0); + result = paInternalError; + PaWinWDM_SetLastErrorInfo(result, "Wave type %u ??", stream->capture.pPin->parentFilter->devInfo.streamingType); + goto error; + } + } + else + { + stream->capture.hostBuffer = 0; + } + + if (stream->userOutputChannels > 0) + { + stream->streamRepresentation.streamInfo.outputLatency = stream->render.framesPerBuffer / sampleRate; + + switch (stream->render.pPin->parentFilter->devInfo.streamingType) + { + case Type_kWaveCyclic: + { + unsigned size = stream->render.noOfPackets * stream->render.framesPerBuffer * stream->render.bytesPerFrame; + /* Allocate output device buffer */ + stream->render.hostBuffer = (char*)PaUtil_GroupAllocateMemory(stream->allocGroup, size); + PA_DEBUG(("Output buffer allocated (size = %u)\n", size)); + if( !stream->render.hostBuffer ) + { + PA_DEBUG(("Cannot allocate host output buffer!\n")); + PaWinWDM_SetLastErrorInfo(paInsufficientMemory, "Failed to allocate output buffer"); + result = paInsufficientMemory; + goto error; + } + stream->render.hostBufferSize = size; + PA_DEBUG(("Output buffer start = %p (size=%u)\n",stream->render.hostBuffer, stream->render.hostBufferSize)); + + stream->render.pPin->fnEventHandler = PaPinRenderEventHandler_WaveCyclic; + stream->render.pPin->fnSubmitHandler = PaPinRenderSubmitHandler_WaveCyclic; + } + break; + case Type_kWaveRT: + { + const DWORD dwTotalSize = 2 * stream->render.framesPerBuffer * stream->render.bytesPerFrame; + DWORD dwRequestedSize = dwTotalSize; + BOOL bCallMemoryBarrier = FALSE; + ULONG hwFifoLatency = 0; + ULONG dummy; + result = PinGetBuffer(stream->render.pPin, (void**)&stream->render.hostBuffer, &dwRequestedSize, &bCallMemoryBarrier); + if (!result) + { + PA_DEBUG(("Output buffer start = %p, size = %u, membarrier = %u\n", stream->render.hostBuffer, dwRequestedSize, bCallMemoryBarrier)); + if (dwRequestedSize != dwTotalSize) + { + PA_DEBUG(("Buffer length changed by driver from %u to %u !\n", dwTotalSize, dwRequestedSize)); + /* Recalculate to what the driver has given us */ + stream->render.framesPerBuffer = dwRequestedSize / (2 * stream->render.bytesPerFrame); + } + stream->render.hostBufferSize = dwRequestedSize; + + if (stream->render.pPin->pinKsSubType == SubType_kPolled) + { + stream->render.pPin->fnEventHandler = PaPinRenderEventHandler_WaveRTPolled; + stream->render.pPin->fnSubmitHandler = PaPinRenderSubmitHandler_WaveRTPolled; + } + else + { + stream->render.pPin->fnEventHandler = PaPinRenderEventHandler_WaveRTEvent; + stream->render.pPin->fnSubmitHandler = PaPinRenderSubmitHandler_WaveRTEvent; + } + + stream->render.pPin->fnMemBarrier = bCallMemoryBarrier ? MemoryBarrierWrite : MemoryBarrierDummy; + } + else + { + PA_DEBUG(("Failed to get output buffer (with notification)\n")); + PaWinWDM_SetLastErrorInfo(paUnanticipatedHostError, "Failed to get output buffer (with notification)"); + result = paUnanticipatedHostError; + goto error; + } + + /* Get latency */ + result = PinGetHwLatency(stream->render.pPin, &hwFifoLatency, &dummy, &dummy); + if (result == paNoError) + { + stream->render.pPin->hwLatency = hwFifoLatency; + + /* Add HW latency into total output latency */ + stream->streamRepresentation.streamInfo.outputLatency += ((hwFifoLatency / stream->render.bytesPerFrame) / sampleRate); + } + else + { + PA_DEBUG(("Failed to get size of FIFO hardware buffer (is set to zero)\n")); + stream->render.pPin->hwLatency = 0; + } + } + break; + default: + /* Undefined wave type!! */ + assert(0); + result = paInternalError; + PaWinWDM_SetLastErrorInfo(result, "Wave type %u ??", stream->capture.pPin->parentFilter->devInfo.streamingType); + goto error; + } + } + else + { + stream->render.hostBuffer = 0; + } - stream->streamRepresentation.streamInfo.inputLatency = - ((double)stream->framesPerHostIBuffer) / sampleRate; - stream->streamRepresentation.streamInfo.outputLatency = - ((double)stream->framesPerHostOBuffer) / sampleRate; stream->streamRepresentation.streamInfo.sampleRate = sampleRate; - PA_DEBUG(("BytesPerInputFrame = %d\n",stream->bytesPerInputFrame)); - PA_DEBUG(("BytesPerOutputFrame = %d\n",stream->bytesPerOutputFrame)); + PA_DEBUG(("BytesPerInputFrame = %d\n",stream->capture.bytesPerFrame)); + PA_DEBUG(("BytesPerOutputFrame = %d\n",stream->render.bytesPerFrame)); - /* Allocate all the buffers for host I/O */ - size = 2 * (stream->framesPerHostIBuffer*stream->bytesPerInputFrame + stream->framesPerHostOBuffer*stream->bytesPerOutputFrame); - PA_DEBUG(("Buffer size = %d\n",size)); - stream->hostBuffer = (char*)PaUtil_AllocateMemory(size); - PA_DEBUG(("Buffer allocated\n")); - if( !stream->hostBuffer ) + /* memset(stream->hostBuffer,0,size); */ + + /* Abort */ + stream->eventAbort = CreateEvent(NULL, TRUE, FALSE, NULL); + if (stream->eventAbort == 0) + { + result = paInsufficientMemory; + goto error; + } + stream->eventStreamStart[0] = CreateEvent(NULL, TRUE, FALSE, NULL); + if (stream->eventStreamStart[0] == 0) + { + result = paInsufficientMemory; + goto error; + } + stream->eventStreamStart[1] = CreateEvent(NULL, TRUE, FALSE, NULL); + if (stream->eventStreamStart[1] == 0) { - PA_DEBUG(("Cannot allocate host buffer!\n")); result = paInsufficientMemory; goto error; } - PA_DEBUG(("Buffer start = %p\n",stream->hostBuffer)); - /* memset(stream->hostBuffer,0,size); */ - /* Set up the packets */ - stream->events[0] = CreateEvent(NULL, FALSE, FALSE, NULL); - ResetEvent(stream->events[0]); /* Record buffer 1 */ - stream->events[1] = CreateEvent(NULL, FALSE, FALSE, NULL); - ResetEvent(stream->events[1]); /* Record buffer 2 */ - stream->events[2] = CreateEvent(NULL, FALSE, FALSE, NULL); - ResetEvent(stream->events[2]); /* Play buffer 1 */ - stream->events[3] = CreateEvent(NULL, FALSE, FALSE, NULL); - ResetEvent(stream->events[3]); /* Play buffer 2 */ - stream->events[4] = CreateEvent(NULL, FALSE, FALSE, NULL); - ResetEvent(stream->events[4]); /* Abort event */ if(stream->userInputChannels > 0) { - DATAPACKET *p = &(stream->packets[0]); - p->Signal.hEvent = stream->events[0]; - p->Header.Data = stream->hostBuffer; - p->Header.FrameExtent = stream->framesPerHostIBuffer*stream->bytesPerInputFrame; - p->Header.DataUsed = 0; - p->Header.Size = sizeof(p->Header); - p->Header.PresentationTime.Numerator = 1; - p->Header.PresentationTime.Denominator = 1; + const unsigned bufferSizeInBytes = stream->capture.framesPerBuffer * stream->capture.bytesPerFrame; + const unsigned ringBufferFrameSize = NextPowerOf2( 1024 + 2 * max(stream->capture.framesPerBuffer, stream->render.framesPerBuffer) ); - p = &(stream->packets[1]); - p->Signal.hEvent = stream->events[1]; - p->Header.Data = stream->hostBuffer + stream->framesPerHostIBuffer*stream->bytesPerInputFrame; - p->Header.FrameExtent = stream->framesPerHostIBuffer*stream->bytesPerInputFrame; - p->Header.DataUsed = 0; - p->Header.Size = sizeof(p->Header); - p->Header.PresentationTime.Numerator = 1; - p->Header.PresentationTime.Denominator = 1; + stream->capture.events = (HANDLE*)PaUtil_GroupAllocateMemory(stream->allocGroup, stream->capture.noOfPackets * sizeof(HANDLE)); + if (stream->capture.events == NULL) + { + result = paInsufficientMemory; + goto error; + } + + stream->capture.packets = (DATAPACKET*)PaUtil_GroupAllocateMemory(stream->allocGroup, stream->capture.noOfPackets * sizeof(DATAPACKET)); + if (stream->capture.packets == NULL) + { + result = paInsufficientMemory; + goto error; + } + + switch(stream->capture.pPin->parentFilter->devInfo.streamingType) + { + case Type_kWaveCyclic: + { + /* WaveCyclic case */ + unsigned i; + for (i = 0; i < stream->capture.noOfPackets; ++i) + { + /* Set up the packets */ + DATAPACKET *p = stream->capture.packets + i; + + /* Record event */ + stream->capture.events[i] = CreateEvent(NULL, TRUE, FALSE, NULL); + + p->Signal.hEvent = stream->capture.events[i]; + p->Header.Data = stream->capture.hostBuffer + (i*bufferSizeInBytes); + p->Header.FrameExtent = bufferSizeInBytes; + p->Header.DataUsed = 0; + p->Header.Size = sizeof(p->Header); + p->Header.PresentationTime.Numerator = 1; + p->Header.PresentationTime.Denominator = 1; + } + } + break; + case Type_kWaveRT: + { + /* Set up the "packets" */ + DATAPACKET *p = stream->capture.packets + 0; + + /* Record event: WaveRT has a single event for 2 notification per buffer */ + stream->capture.events[0] = CreateEvent(NULL, FALSE, FALSE, NULL); + + p->Header.Data = stream->capture.hostBuffer; + p->Header.FrameExtent = bufferSizeInBytes; + p->Header.DataUsed = 0; + p->Header.Size = sizeof(p->Header); + p->Header.PresentationTime.Numerator = 1; + p->Header.PresentationTime.Denominator = 1; + + ++p; + p->Header.Data = stream->capture.hostBuffer + bufferSizeInBytes; + p->Header.FrameExtent = bufferSizeInBytes; + p->Header.DataUsed = 0; + p->Header.Size = sizeof(p->Header); + p->Header.PresentationTime.Numerator = 1; + p->Header.PresentationTime.Denominator = 1; + + if (stream->capture.pPin->pinKsSubType == SubType_kNotification) + { + result = PinRegisterNotificationHandle(stream->capture.pPin, stream->capture.events[0]); + + if (result != paNoError) + { + PA_DEBUG(("Failed to register capture notification handle\n")); + PaWinWDM_SetLastErrorInfo(paUnanticipatedHostError, "Failed to register capture notification handle"); + result = paUnanticipatedHostError; + goto error; + } + } + + result = PinRegisterPositionRegister(stream->capture.pPin); + + if (result != paNoError) + { + PA_DEBUG(("Failed to register capture position register, using PinGetAudioPositionViaIOCTL\n")); + stream->capture.pPin->fnAudioPosition = PinGetAudioPositionViaIOCTL; + } + else + { + stream->capture.pPin->fnAudioPosition = PinGetAudioPositionDirect; + } + } + break; + default: + /* Undefined wave type!! */ + assert(0); + result = paInternalError; + PaWinWDM_SetLastErrorInfo(result, "Wave type %u ??", stream->capture.pPin->parentFilter->devInfo.streamingType); + goto error; + } + + /* Setup the input ring buffer here */ + stream->ringBufferData = (char*)PaUtil_GroupAllocateMemory(stream->allocGroup, ringBufferFrameSize * stream->capture.bytesPerFrame); + if (stream->ringBufferData == NULL) + { + result = paInsufficientMemory; + goto error; + } + PaUtil_InitializeRingBuffer(&stream->ringBuffer, stream->capture.bytesPerFrame, ringBufferFrameSize, stream->ringBufferData); } if(stream->userOutputChannels > 0) { - DATAPACKET *p = &(stream->packets[2]); - p->Signal.hEvent = stream->events[2]; - p->Header.Data = stream->hostBuffer + 2*stream->framesPerHostIBuffer*stream->bytesPerInputFrame; - p->Header.FrameExtent = stream->framesPerHostOBuffer*stream->bytesPerOutputFrame; - p->Header.DataUsed = stream->framesPerHostOBuffer*stream->bytesPerOutputFrame; - p->Header.Size = sizeof(p->Header); - p->Header.PresentationTime.Numerator = 1; - p->Header.PresentationTime.Denominator = 1; - - p = &(stream->packets[3]); - p->Signal.hEvent = stream->events[3]; - p->Header.Data = stream->hostBuffer + 2*stream->framesPerHostIBuffer*stream->bytesPerInputFrame + stream->framesPerHostOBuffer*stream->bytesPerOutputFrame; - p->Header.FrameExtent = stream->framesPerHostOBuffer*stream->bytesPerOutputFrame; - p->Header.DataUsed = stream->framesPerHostOBuffer*stream->bytesPerOutputFrame; - p->Header.Size = sizeof(p->Header); - p->Header.PresentationTime.Numerator = 1; - p->Header.PresentationTime.Denominator = 1; + const unsigned bufferSizeInBytes = stream->render.framesPerBuffer * stream->render.bytesPerFrame; + + stream->render.events = (HANDLE*)PaUtil_GroupAllocateMemory(stream->allocGroup, stream->render.noOfPackets * sizeof(HANDLE)); + if (stream->render.events == NULL) + { + result = paInsufficientMemory; + goto error; + } + + stream->render.packets = (DATAPACKET*)PaUtil_GroupAllocateMemory(stream->allocGroup, stream->render.noOfPackets * sizeof(DATAPACKET)); + if (stream->render.packets == NULL) + { + result = paInsufficientMemory; + goto error; + } + + switch(stream->render.pPin->parentFilter->devInfo.streamingType) + { + case Type_kWaveCyclic: + { + /* WaveCyclic case */ + unsigned i; + for (i = 0; i < stream->render.noOfPackets; ++i) + { + /* Set up the packets */ + DATAPACKET *p = stream->render.packets + i; + + /* Playback event */ + stream->render.events[i] = CreateEvent(NULL, TRUE, FALSE, NULL); + + /* In this case, we just use the packets as ptr to the device buffer */ + p->Signal.hEvent = stream->render.events[i]; + p->Header.Data = stream->render.hostBuffer + (i*bufferSizeInBytes); + p->Header.FrameExtent = bufferSizeInBytes; + p->Header.DataUsed = bufferSizeInBytes; + p->Header.Size = sizeof(p->Header); + p->Header.PresentationTime.Numerator = 1; + p->Header.PresentationTime.Denominator = 1; + } + } + break; + case Type_kWaveRT: + { + /* WaveRT case */ + + /* Set up the "packets" */ + DATAPACKET *p = stream->render.packets; + + /* The only playback event */ + stream->render.events[0] = CreateEvent(NULL, FALSE, FALSE, NULL); + + /* In this case, we just use the packets as ptr to the device buffer */ + p->Header.Data = stream->render.hostBuffer; + p->Header.FrameExtent = stream->render.framesPerBuffer*stream->render.bytesPerFrame; + p->Header.DataUsed = stream->render.framesPerBuffer*stream->render.bytesPerFrame; + p->Header.Size = sizeof(p->Header); + p->Header.PresentationTime.Numerator = 1; + p->Header.PresentationTime.Denominator = 1; + + ++p; + p->Header.Data = stream->render.hostBuffer + stream->render.framesPerBuffer*stream->render.bytesPerFrame; + p->Header.FrameExtent = stream->render.framesPerBuffer*stream->render.bytesPerFrame; + p->Header.DataUsed = stream->render.framesPerBuffer*stream->render.bytesPerFrame; + p->Header.Size = sizeof(p->Header); + p->Header.PresentationTime.Numerator = 1; + p->Header.PresentationTime.Denominator = 1; + + if (stream->render.pPin->pinKsSubType == SubType_kNotification) + { + result = PinRegisterNotificationHandle(stream->render.pPin, stream->render.events[0]); + + if (result != paNoError) + { + PA_DEBUG(("Failed to register rendering notification handle\n")); + PaWinWDM_SetLastErrorInfo(paUnanticipatedHostError, "Failed to register rendering notification handle"); + result = paUnanticipatedHostError; + goto error; + } + } + + result = PinRegisterPositionRegister(stream->render.pPin); + + if (result != paNoError) + { + PA_DEBUG(("Failed to register rendering position register, using PinGetAudioPositionViaIOCTL\n")); + stream->render.pPin->fnAudioPosition = PinGetAudioPositionViaIOCTL; + } + else + { + stream->render.pPin->fnAudioPosition = PinGetAudioPositionDirect; + } + } + break; + default: + /* Undefined wave type!! */ + assert(0); + result = paInternalError; + PaWinWDM_SetLastErrorInfo(result, "Wave type %u ??", stream->capture.pPin->parentFilter->devInfo.streamingType); + goto error; + } } stream->streamStarted = 0; @@ -2565,45 +5085,93 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, stream->streamFlags = streamFlags; stream->oldProcessPriority = REALTIME_PRIORITY_CLASS; + /* Increase ref count on filters in use, so that a CommitDeviceInfos won't delete them */ + if (stream->capture.pPin != 0) + { + FilterAddRef(stream->capture.pPin->parentFilter); + } + if (stream->render.pPin != 0) + { + FilterAddRef(stream->render.pPin->parentFilter); + } + + /* Ok, now update our host API specific stream info */ + if (stream->userInputChannels) + { + PaWinWdmDeviceInfo *pDeviceInfo = (PaWinWdmDeviceInfo*)wdmHostApi->inheritedHostApiRep.deviceInfos[inputParameters->device]; + + stream->hostApiStreamInfo.input.device = Pa_HostApiDeviceIndexToDeviceIndex(Pa_HostApiTypeIdToHostApiIndex(paWDMKS), inputParameters->device); + stream->hostApiStreamInfo.input.channels = stream->deviceInputChannels; + stream->hostApiStreamInfo.input.muxNodeId = -1; + if (stream->capture.pPin->inputs) + { + stream->hostApiStreamInfo.input.muxNodeId = stream->capture.pPin->inputs[pDeviceInfo->muxPosition]->muxNodeId; + } + stream->hostApiStreamInfo.input.endpointPinId = pDeviceInfo->endpointPinId; + stream->hostApiStreamInfo.input.framesPerHostBuffer = stream->capture.framesPerBuffer; + stream->hostApiStreamInfo.input.streamingSubType = stream->capture.pPin->pinKsSubType; + } + else + { + stream->hostApiStreamInfo.input.device = paNoDevice; + } + if (stream->userOutputChannels) + { + stream->hostApiStreamInfo.output.device = Pa_HostApiDeviceIndexToDeviceIndex(Pa_HostApiTypeIdToHostApiIndex(paWDMKS), outputParameters->device); + stream->hostApiStreamInfo.output.channels = stream->deviceOutputChannels; + stream->hostApiStreamInfo.output.framesPerHostBuffer = stream->render.framesPerBuffer; + stream->hostApiStreamInfo.output.endpointPinId = stream->render.pPin->endpointPinId; + stream->hostApiStreamInfo.output.streamingSubType = stream->render.pPin->pinKsSubType; + } + else + { + stream->hostApiStreamInfo.output.device = paNoDevice; + } + /*stream->streamRepresentation.streamInfo.hostApiTypeId = paWDMKS; + stream->streamRepresentation.streamInfo.hostApiSpecificStreamInfo = &stream->hostApiStreamInfo;*/ + stream->streamRepresentation.streamInfo.structVersion = 2; + *s = (PaStream*)stream; PA_LOGL_; return result; +occupied: + /* Ok, someone else is hogging the pin, bail out */ + assert (result == paDeviceUnavailable); + PaWinWDM_SetLastErrorInfo(result, "Device is occupied"); + error: - size = 5; - while(size--) + PaUtil_TerminateBufferProcessor( &stream->bufferProcessor ); + + CloseStreamEvents(stream); + + if (stream->allocGroup) { - if(stream->events[size] != NULL) - { - CloseHandle(stream->events[size]); - stream->events[size] = NULL; - } + PaUtil_FreeAllAllocations(stream->allocGroup); + PaUtil_DestroyAllocationGroup(stream->allocGroup); + stream->allocGroup = 0; } - if(stream->hostBuffer) - PaUtil_FreeMemory( stream->hostBuffer ); - if(stream->playbackPin) - PinClose(stream->playbackPin); - if(stream->recordingPin) - PinClose(stream->recordingPin); + if(stream->render.pPin) + PinClose(stream->render.pPin); + if(stream->capture.pPin) + PinClose(stream->capture.pPin); - if( stream ) - PaUtil_FreeMemory( stream ); + PaUtil_FreeMemory( stream ); PA_LOGL_; return result; } /* - When CloseStream() is called, the multi-api layer ensures that - the stream has already been stopped or aborted. +When CloseStream() is called, the multi-api layer ensures that +the stream has already been stopped or aborted. */ static PaError CloseStream( PaStream* s ) { PaError result = paNoError; PaWinWdmStream *stream = (PaWinWdmStream*)s; - int size; PA_LOGE_; @@ -2612,22 +5180,33 @@ static PaError CloseStream( PaStream* s ) PaUtil_TerminateBufferProcessor( &stream->bufferProcessor ); PaUtil_TerminateStreamRepresentation( &stream->streamRepresentation ); - size = 5; - while(size--) - { - if(stream->events[size] != NULL) - { - CloseHandle(stream->events[size]); - stream->events[size] = NULL; - } - } - if(stream->hostBuffer) - PaUtil_FreeMemory( stream->hostBuffer ); - if(stream->playbackPin) - PinClose(stream->playbackPin); - if(stream->recordingPin) - PinClose(stream->recordingPin); + CloseStreamEvents(stream); + + if (stream->allocGroup) + { + PaUtil_FreeAllAllocations(stream->allocGroup); + PaUtil_DestroyAllocationGroup(stream->allocGroup); + stream->allocGroup = 0; + } + + if(stream->render.pPin) + { + PinClose(stream->render.pPin); + } + if(stream->capture.pPin) + { + PinClose(stream->capture.pPin); + } + + if (stream->render.pPin) + { + FilterFree(stream->render.pPin->parentFilter); + } + if (stream->capture.pPin) + { + FilterFree(stream->capture.pPin->parentFilter); + } PaUtil_FreeMemory( stream ); @@ -2638,25 +5217,57 @@ static PaError CloseStream( PaStream* s ) /* Write the supplied packet to the pin Asynchronous -Should return false on success +Should return paNoError on success */ -static BOOL PinWrite(HANDLE h, DATAPACKET* p) +static PaError PinWrite(HANDLE h, DATAPACKET* p) { + PaError result = paNoError; unsigned long cbReturned = 0; - return DeviceIoControl(h,IOCTL_KS_WRITE_STREAM,NULL,0, - &p->Header,p->Header.Size,&cbReturned,&p->Signal); + BOOL fRes = DeviceIoControl(h, + IOCTL_KS_WRITE_STREAM, + NULL, + 0, + &p->Header, + p->Header.Size, + &cbReturned, + &p->Signal); + if (!fRes) + { + unsigned long error = GetLastError(); + if (error != ERROR_IO_PENDING) + { + result = paInternalError; + } + } + return result; } /* Read to the supplied packet from the pin Asynchronous -Should return false on success +Should return paNoError on success */ -static BOOL PinRead(HANDLE h, DATAPACKET* p) +static PaError PinRead(HANDLE h, DATAPACKET* p) { + PaError result = paNoError; unsigned long cbReturned = 0; - return DeviceIoControl(h,IOCTL_KS_READ_STREAM,NULL,0, - &p->Header,p->Header.Size,&cbReturned,&p->Signal); + BOOL fRes = DeviceIoControl(h, + IOCTL_KS_READ_STREAM, + NULL, + 0, + &p->Header, + p->Header.Size, + &cbReturned, + &p->Signal); + if (!fRes) + { + unsigned long error = GetLastError(); + if (error != ERROR_IO_PENDING) + { + result = paInternalError; + } + } + return result; } /* @@ -2722,365 +5333,763 @@ static void DuplicateFirstChannelInt32(void* buffer, int channels, int samples) } } -static DWORD WINAPI ProcessingThread(LPVOID pParam) +/* +Increase the priority of the calling thread to RT +*/ +static HANDLE BumpThreadPriority() +{ + HANDLE hThread = GetCurrentThread(); + DWORD dwTask = 0; + HANDLE hAVRT = NULL; + + /* If we have access to AVRT.DLL (Vista and later), use it */ + if (FunctionAvSetMmThreadCharacteristics != NULL) + { + hAVRT = FunctionAvSetMmThreadCharacteristics("Pro Audio", &dwTask); + if (hAVRT != NULL && hAVRT != INVALID_HANDLE_VALUE) + { + BOOL bret = FunctionAvSetMmThreadPriority(hAVRT, PA_AVRT_PRIORITY_CRITICAL); + if (!bret) + { + PA_DEBUG(("Set mm thread prio to critical failed!\n")); + } + else + { + return hAVRT; + } + } + else + { + PA_DEBUG(("Set mm thread characteristic to 'Pro Audio' failed, reverting to SetThreadPriority\n")); + } + } + + /* For XP and earlier, or if AvSetMmThreadCharacteristics fails (MMCSS disabled ?) */ + if (timeBeginPeriod(1) != TIMERR_NOERROR) { + PA_DEBUG(("timeBeginPeriod(1) failed!\n")); + } + + if (!SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL)) { + PA_DEBUG(("SetThreadPriority failed!\n")); + } + + return hAVRT; +} + +/* +Decrease the priority of the calling thread to normal +*/ +static void DropThreadPriority(HANDLE hAVRT) +{ + HANDLE hThread = GetCurrentThread(); + + if (hAVRT != NULL) + { + FunctionAvSetMmThreadPriority(hAVRT, PA_AVRT_PRIORITY_NORMAL); + FunctionAvRevertMmThreadCharacteristics(hAVRT); + return; + } + + SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL); + timeEndPeriod(1); +} + +static PaError PreparePinForStart(PaWinWdmPin* pin) { - PaWinWdmStream *stream = (PaWinWdmStream*)pParam; - PaStreamCallbackTimeInfo ti; - int cbResult = paContinue; - int inbuf = 0; - int outbuf = 0; - int pending = 0; PaError result; - unsigned long wait; - unsigned long eventSignaled; - int fillPlaybuf = 0; - int emptyRecordbuf = 0; - int framesProcessed; - unsigned long timeout; - int i; - int doChannelCopy; - int priming = 0; - PaStreamCallbackFlags underover = 0; + result = PinSetState(pin, KSSTATE_ACQUIRE); + if (result != paNoError) + { + goto error; + } + result = PinSetState(pin, KSSTATE_PAUSE); + if (result != paNoError) + { + goto error; + } + return result; + +error: + PinSetState(pin, KSSTATE_STOP); + return result; +} + +static PaError PreparePinsForStart(PaProcessThreadInfo* pInfo) +{ + PaError result = paNoError; + /* Submit buffers */ + if (pInfo->stream->capture.pPin) + { + if ((result = PreparePinForStart(pInfo->stream->capture.pPin)) != paNoError) + { + goto error; + } + + if (pInfo->stream->capture.pPin->parentFilter->devInfo.streamingType == Type_kWaveCyclic) + { + unsigned i; + for(i=0; i < pInfo->stream->capture.noOfPackets; ++i) + { + if ((result = PinRead(pInfo->stream->capture.pPin->handle, pInfo->stream->capture.packets + i)) != paNoError) + { + goto error; + } + ++pInfo->pending; + } + } + else + { + pInfo->pending = 2; + } + } + + if(pInfo->stream->render.pPin) + { + if ((result = PreparePinForStart(pInfo->stream->render.pPin)) != paNoError) + { + goto error; + } + + pInfo->priming += pInfo->stream->render.noOfPackets; + ++pInfo->pending; + SetEvent(pInfo->stream->render.events[0]); + if (pInfo->stream->render.pPin->parentFilter->devInfo.streamingType == Type_kWaveCyclic) + { + unsigned i; + for(i=1; i < pInfo->stream->render.noOfPackets; ++i) + { + SetEvent(pInfo->stream->render.events[i]); + ++pInfo->pending; + } + } + } + +error: + PA_DEBUG(("PreparePinsForStart = %d\n", result)); + return result; +} + +static PaError StartPin(PaWinWdmPin* pin) +{ + return PinSetState(pin, KSSTATE_RUN); +} + +static PaError StartPins(PaProcessThreadInfo* pInfo) +{ + PaError result = paNoError; + /* Start the pins as synced as possible */ + if (pInfo->stream->capture.pPin) + { + result = StartPin(pInfo->stream->capture.pPin); + } + if(pInfo->stream->render.pPin) + { + result = StartPin(pInfo->stream->render.pPin); + } + PA_DEBUG(("StartPins = %d\n", result)); + return result; +} + + +static PaError StopPin(PaWinWdmPin* pin) +{ + PinSetState(pin, KSSTATE_PAUSE); + PinSetState(pin, KSSTATE_STOP); + return paNoError; +} + + +static PaError StopPins(PaProcessThreadInfo* pInfo) +{ + PaError result = paNoError; + if(pInfo->stream->render.pPin) + { + StopPin(pInfo->stream->render.pPin); + } + if(pInfo->stream->capture.pPin) + { + StopPin(pInfo->stream->capture.pPin); + } + return result; +} + +typedef void (*TSetInputFrameCount)(PaUtilBufferProcessor*, unsigned long); +typedef void (*TSetInputChannel)(PaUtilBufferProcessor*, unsigned int, void *, unsigned int); +static const TSetInputFrameCount fnSetInputFrameCount[2] = { PaUtil_SetInputFrameCount, PaUtil_Set2ndInputFrameCount }; +static const TSetInputChannel fnSetInputChannel[2] = { PaUtil_SetInputChannel, PaUtil_Set2ndInputChannel }; + +static PaError PaDoProcessing(PaProcessThreadInfo* pInfo) +{ + PaError result = paNoError; + int i, framesProcessed = 0, doChannelCopy = 0; + ring_buffer_size_t inputFramesAvailable = PaUtil_GetRingBufferReadAvailable(&pInfo->stream->ringBuffer); + + /* Do necessary buffer processing (which will invoke user callback if necessary) */ + if (pInfo->cbResult == paContinue && + (pInfo->renderHead != pInfo->renderTail || inputFramesAvailable)) + { + unsigned processFullDuplex = pInfo->stream->capture.pPin && pInfo->stream->render.pPin && (!pInfo->priming); + + PA_HP_TRACE((pInfo->stream->hLog, "DoProcessing: InputFrames=%u", inputFramesAvailable)); + + PaUtil_BeginCpuLoadMeasurement( &pInfo->stream->cpuLoadMeasurer ); + + pInfo->ti.currentTime = PaUtil_GetTime(); + + PaUtil_BeginBufferProcessing(&pInfo->stream->bufferProcessor, &pInfo->ti, pInfo->underover); + pInfo->underover = 0; /* Reset the (under|over)flow status */ + + if (pInfo->renderTail != pInfo->renderHead) + { + DATAPACKET* packet = pInfo->renderPackets[pInfo->renderTail & cPacketsArrayMask].packet; + + assert(packet != 0); + assert(packet->Header.Data != 0); + + PaUtil_SetOutputFrameCount(&pInfo->stream->bufferProcessor, pInfo->stream->render.framesPerBuffer); + + for(i=0;istream->userOutputChannels;i++) + { + /* Only write the user output channels. Leave the rest blank */ + PaUtil_SetOutputChannel(&pInfo->stream->bufferProcessor, + i, + ((unsigned char*)(packet->Header.Data))+(i*pInfo->stream->render.bytesPerSample), + pInfo->stream->deviceOutputChannels); + } + + /* We will do a copy to the other channels after the data has been written */ + doChannelCopy = ( pInfo->stream->userOutputChannels == 1 ); + } + + if (inputFramesAvailable && (!pInfo->stream->userOutputChannels || inputFramesAvailable >= (int)pInfo->stream->render.framesPerBuffer)) + { + unsigned wrapCntr = 0; + char* data[2] = {0}; + ring_buffer_size_t size[2] = {0}; + + /* If full-duplex, we just extract output buffer number of frames */ + if (pInfo->stream->userOutputChannels) + { + inputFramesAvailable = min(inputFramesAvailable, (int)pInfo->stream->render.framesPerBuffer); + } + + inputFramesAvailable = PaUtil_GetRingBufferReadRegions(&pInfo->stream->ringBuffer, + inputFramesAvailable, + &data[0], + &size[0], + &data[1], + &size[1]); + + for (wrapCntr = 0; wrapCntr < 2; ++wrapCntr) + { + if (size[wrapCntr] == 0) + break; + + fnSetInputFrameCount[wrapCntr](&pInfo->stream->bufferProcessor, size[wrapCntr]); + for(i=0;istream->userInputChannels;i++) + { + /* Only read as many channels as the user wants */ + fnSetInputChannel[wrapCntr](&pInfo->stream->bufferProcessor, + i, + ((unsigned char*)(data[wrapCntr]))+(i*pInfo->stream->capture.bytesPerSample), + pInfo->stream->deviceInputChannels); + } + } + } + else + { + /* We haven't consumed anything from the ring buffer... */ + inputFramesAvailable = 0; + /* If we have full-duplex, this is at startup, so mark no-input! */ + if (pInfo->stream->userOutputChannels>0 && pInfo->stream->userInputChannels>0) + { + PA_HP_TRACE((pInfo->stream->hLog, "Input startup, marking no input.")); + PaUtil_SetNoInput(&pInfo->stream->bufferProcessor); + } + } + + if (processFullDuplex) /* full duplex */ + { + /* Only call the EndBufferProcessing function when the total input frames == total output frames */ + const unsigned long totalInputFrameCount = pInfo->stream->bufferProcessor.hostInputFrameCount[0] + pInfo->stream->bufferProcessor.hostInputFrameCount[1]; + const unsigned long totalOutputFrameCount = pInfo->stream->bufferProcessor.hostOutputFrameCount[0] + pInfo->stream->bufferProcessor.hostOutputFrameCount[1]; + + if(totalInputFrameCount == totalOutputFrameCount && totalOutputFrameCount != 0) + { + framesProcessed = PaUtil_EndBufferProcessing(&pInfo->stream->bufferProcessor, &pInfo->cbResult); + } + else + { + framesProcessed = 0; + } + } + else + { + framesProcessed = PaUtil_EndBufferProcessing(&pInfo->stream->bufferProcessor, &pInfo->cbResult); + } + + PA_HP_TRACE((pInfo->stream->hLog, "Frames processed: %u %s", framesProcessed, (pInfo->priming ? "(priming)":""))); + + if( doChannelCopy ) + { + DATAPACKET* packet = pInfo->renderPackets[pInfo->renderTail & cPacketsArrayMask].packet; + /* Copy the first output channel to the other channels */ + switch (pInfo->stream->render.bytesPerSample) + { + case 2: + DuplicateFirstChannelInt16(packet->Header.Data, pInfo->stream->deviceOutputChannels, pInfo->stream->render.framesPerBuffer); + break; + case 3: + DuplicateFirstChannelInt24(packet->Header.Data, pInfo->stream->deviceOutputChannels, pInfo->stream->render.framesPerBuffer); + break; + case 4: + DuplicateFirstChannelInt32(packet->Header.Data, pInfo->stream->deviceOutputChannels, pInfo->stream->render.framesPerBuffer); + break; + default: + assert(0); /* Unsupported format! */ + break; + } + } + PaUtil_EndCpuLoadMeasurement( &pInfo->stream->cpuLoadMeasurer, framesProcessed ); + + if (inputFramesAvailable) + { + PaUtil_AdvanceRingBufferReadIndex(&pInfo->stream->ringBuffer, inputFramesAvailable); + } + + if (pInfo->renderTail != pInfo->renderHead) + { + if (!pInfo->stream->streamStop) + { + result = pInfo->stream->render.pPin->fnSubmitHandler(pInfo, pInfo->renderTail); + if (result != paNoError) + { + PA_HP_TRACE((pInfo->stream->hLog, "Capture submit handler failed with result %d", result)); + return result; + } + } + pInfo->renderTail++; + if (!pInfo->pinsStarted && pInfo->priming == 0) + { + /* We start the pins here to allow "prime time" */ + if ((result = StartPins(pInfo)) == paNoError) + { + PA_HP_TRACE((pInfo->stream->hLog, "Starting pins!")); + pInfo->pinsStarted = 1; + } + } + } + } + + return result; +} + +static VOID CALLBACK TimerAPCWaveRTPolledMode( + LPVOID lpArgToCompletionRoutine, + DWORD dwTimerLowValue, + DWORD dwTimerHighValue) +{ + HANDLE* pHandles = (HANDLE*)lpArgToCompletionRoutine; + if (pHandles[0]) SetEvent(pHandles[0]); + if (pHandles[1]) SetEvent(pHandles[1]); +} + +static DWORD GetCurrentTimeInMillisecs() +{ + return timeGetTime(); +} + +PA_THREAD_FUNC ProcessingThread(void* pParam) +{ + PaError result = paNoError; + HANDLE hAVRT = NULL; + HANDLE hTimer = NULL; + HANDLE *handleArray = NULL; + HANDLE timerEventHandles[2] = {0}; + unsigned noOfHandles = 0; + unsigned captureEvents = 0; + unsigned renderEvents = 0; + unsigned timerPeriod = 0; + DWORD timeStamp[2] = {0}; + + PaProcessThreadInfo info; + memset(&info, 0, sizeof(PaProcessThreadInfo)); + info.stream = (PaWinWdmStream*)pParam; + + info.stream->threadResult = paNoError; PA_LOGE_; - ti.inputBufferAdcTime = 0.0; - ti.currentTime = 0.0; - ti.outputBufferDacTime = 0.0; + info.ti.inputBufferAdcTime = 0.0; + info.ti.currentTime = 0.0; + info.ti.outputBufferDacTime = 0.0; - /* Get double buffering going */ + PA_DEBUG(("In buffer len: %.3f ms\n",(2000*info.stream->capture.framesPerBuffer) / info.stream->streamRepresentation.streamInfo.sampleRate)); + PA_DEBUG(("Out buffer len: %.3f ms\n",(2000*info.stream->render.framesPerBuffer) / info.stream->streamRepresentation.streamInfo.sampleRate)); + info.timeout = (DWORD)max( + (2000*info.stream->render.framesPerBuffer/info.stream->streamRepresentation.streamInfo.sampleRate + 0.5), + (2000*info.stream->capture.framesPerBuffer/info.stream->streamRepresentation.streamInfo.sampleRate + 0.5)); + info.timeout = max(info.timeout*8, 100); + timerPeriod = info.timeout; + PA_DEBUG(("Timeout = %ld ms\n",info.timeout)); - /* Submit buffers */ - if(stream->playbackPin) + /* Allocate handle array */ + handleArray = (HANDLE*)PaUtil_AllocateMemory((info.stream->capture.noOfPackets + info.stream->render.noOfPackets + 1) * sizeof(HANDLE)); + + /* Setup handle array for WFMO */ + if (info.stream->capture.pPin != 0) { - result = PinSetState(stream->playbackPin, KSSTATE_RUN); - - PA_DEBUG(("play state run = %d;",(int)result)); - SetEvent(stream->events[outbuf+2]); - outbuf = (outbuf+1)&1; - SetEvent(stream->events[outbuf+2]); - outbuf = (outbuf+1)&1; - pending += 2; - priming += 4; - } - if(stream->recordingPin) - { - result = PinSetState(stream->recordingPin, KSSTATE_RUN); - - PA_DEBUG(("recording state run = %d;",(int)result)); - PinRead(stream->recordingPin->handle,&stream->packets[inbuf]); - inbuf = (inbuf+1)&1; /* Increment and wrap */ - PinRead(stream->recordingPin->handle,&stream->packets[inbuf]); - inbuf = (inbuf+1)&1; /* Increment and wrap */ - /* FIXME - do error checking */ - pending += 2; - } - PA_DEBUG(("Out buffer len:%f\n",(2000*stream->framesPerHostOBuffer) / stream->streamRepresentation.streamInfo.sampleRate)); - PA_DEBUG(("In buffer len:%f\n",(2000*stream->framesPerHostIBuffer) / stream->streamRepresentation.streamInfo.sampleRate)); - timeout = max( - ((2000*(DWORD)stream->framesPerHostOBuffer) / (DWORD)stream->streamRepresentation.streamInfo.sampleRate), - ((2000*(DWORD)stream->framesPerHostIBuffer) / (DWORD)stream->streamRepresentation.streamInfo.sampleRate)); - timeout = max(timeout,1); - PA_DEBUG(("Timeout = %ld\n",timeout)); - - while(!stream->streamAbort) - { - fillPlaybuf = 0; - emptyRecordbuf = 0; - - /* Wait for next input or output buffer to be finished with*/ - assert(pending>0); - - if(stream->streamStop) + handleArray[noOfHandles++] = info.stream->capture.events[0]; + if (info.stream->capture.pPin->parentFilter->devInfo.streamingType == Type_kWaveCyclic) { - PA_DEBUG(("ss1:pending=%d ",pending)); + unsigned i; + for(i=1; i < info.stream->capture.noOfPackets; ++i) + { + handleArray[noOfHandles++] = info.stream->capture.events[i]; + } } - wait = WaitForMultipleObjects(5, stream->events, FALSE, 0); - if( wait == WAIT_TIMEOUT ) + captureEvents = noOfHandles; + renderEvents = noOfHandles; + } + + if (info.stream->render.pPin != 0) + { + handleArray[noOfHandles++] = info.stream->render.events[0]; + if (info.stream->render.pPin->parentFilter->devInfo.streamingType == Type_kWaveCyclic) { - /* No (under|over)flow has ocurred */ - wait = WaitForMultipleObjects(5, stream->events, FALSE, timeout); - eventSignaled = wait - WAIT_OBJECT_0; + unsigned i; + for(i=1; i < info.stream->render.noOfPackets; ++i) + { + handleArray[noOfHandles++] = info.stream->render.events[i]; + } + } + renderEvents = noOfHandles; + } + handleArray[noOfHandles++] = info.stream->eventAbort; + assert(noOfHandles <= (info.stream->capture.noOfPackets + info.stream->render.noOfPackets + 1)); + + /* Prepare render and capture pins */ + if ((result = PreparePinsForStart(&info)) != paNoError) + { + PA_DEBUG(("Failed to prepare device(s)!\n")); + goto error; + } + + /* Init high speed logger */ + if (PaUtil_InitializeHighSpeedLog(&info.stream->hLog, 1000000) != paNoError) + { + PA_DEBUG(("Failed to init high speed logger!\n")); + goto error; + } + + /* Heighten priority here */ + hAVRT = BumpThreadPriority(); + + /* If input only, we start the pins immediately */ + if (info.stream->render.pPin == 0) + { + if ((result = StartPins(&info)) != paNoError) + { + PA_DEBUG(("Failed to start device(s)!\n")); + goto error; + } + info.pinsStarted = 1; + } + + /* Handle WaveRT polled mode */ + { + const unsigned fs = (unsigned)info.stream->streamRepresentation.streamInfo.sampleRate; + if (info.stream->capture.pPin != 0 && info.stream->capture.pPin->pinKsSubType == SubType_kPolled) + { + timerEventHandles[0] = info.stream->capture.events[0]; + timerPeriod = min(timerPeriod, (1000*info.stream->capture.framesPerBuffer)/fs); + } + + if (info.stream->render.pPin != 0 && info.stream->render.pPin->pinKsSubType == SubType_kPolled) + { + timerEventHandles[1] = info.stream->render.events[0]; + timerPeriod = min(timerPeriod, (1000*info.stream->render.framesPerBuffer)/fs); + } + + if (timerEventHandles[0] || timerEventHandles[1]) + { + LARGE_INTEGER dueTime = {0}; + + timerPeriod=max(timerPeriod/5,1); + PA_DEBUG(("Timer event handles=0x%04X,0x%04X period=%u ms", timerEventHandles[0], timerEventHandles[1], timerPeriod)); + hTimer = CreateWaitableTimer(0, FALSE, NULL); + if (hTimer == NULL) + { + result = paUnanticipatedHostError; + goto error; + } + /* invoke first timeout immediately */ + if (!SetWaitableTimer(hTimer, &dueTime, timerPeriod, TimerAPCWaveRTPolledMode, timerEventHandles, FALSE)) + { + result = paUnanticipatedHostError; + goto error; + } + PA_DEBUG(("Waitable timer started, period = %u ms\n", timerPeriod)); + } + } + + /* Mark stream as active */ + info.stream->streamActive = 1; + info.stream->threadResult = paNoError; + + /* Up and running... */ + SetEvent(info.stream->eventStreamStart[StreamStart_kOk]); + + /* Take timestamp here */ + timeStamp[0] = timeStamp[1] = GetCurrentTimeInMillisecs(); + + while(!info.stream->streamAbort) + { + unsigned doProcessing = 1; + unsigned wait = WaitForMultipleObjects(noOfHandles, handleArray, FALSE, 0); + unsigned eventSignalled = wait - WAIT_OBJECT_0; + DWORD dwCurrentTime = 0; + + if (wait == WAIT_FAILED) + { + PA_DEBUG(("Wait failed = %ld! \n",wait)); + break; + } + if (wait == WAIT_TIMEOUT) + { + wait = WaitForMultipleObjectsEx(noOfHandles, handleArray, FALSE, 50, TRUE); + eventSignalled = wait - WAIT_OBJECT_0; } else { - eventSignaled = wait - WAIT_OBJECT_0; - if( eventSignaled < 2 ) + if (eventSignalled < captureEvents) { - underover |= paInputOverflow; - PA_DEBUG(("Input overflow\n")); + if (PaUtil_GetRingBufferWriteAvailable(&info.stream->ringBuffer) == 0) + { + PA_HP_TRACE((info.stream->hLog, "!!!!! Input overflow !!!!!")); + info.underover |= paInputOverflow; + } } - else if(( eventSignaled < 4 )&&(!priming)) + else if (eventSignalled < renderEvents) { - underover |= paOutputUnderflow; - PA_DEBUG(("Output underflow\n")); + if (!info.priming && info.renderHead - info.renderTail > 1) + { + PA_HP_TRACE((info.stream->hLog, "!!!!! Output underflow !!!!!")); + info.underover |= paOutputUnderflow; + } } } - if(stream->streamStop) + /* Get event time */ + dwCurrentTime = GetCurrentTimeInMillisecs(); + + /* Since we can mix capture/render devices between WaveCyclic, WaveRT polled and WaveRT notification (3x3 combinations), + we can't rely on the timeout of WFMO to check for device timeouts, we need to keep tally. */ + if (info.stream->capture.pPin && (dwCurrentTime - timeStamp[0]) >= info.timeout) { - PA_DEBUG(("ss2:wait=%ld",wait)); - } - if(wait == WAIT_FAILED) - { - PA_DEBUG(("Wait fail = %ld! ",wait)); + PA_DEBUG(("Timeout for capture device (%u ms)!", info.timeout, (dwCurrentTime - timeStamp[0]))); + result = paTimedOut; break; } - if(wait == WAIT_TIMEOUT) + if (info.stream->render.pPin && (dwCurrentTime - timeStamp[1]) >= info.timeout) { + PA_DEBUG(("Timeout for render device (%u ms)!", info.timeout, (dwCurrentTime - timeStamp[1]))); + result = paTimedOut; + break; + } + + if (wait == WAIT_IO_COMPLETION) + { + /* Waitable timer has fired! */ + PA_HP_TRACE((info.stream->hLog, "WAIT_IO_COMPLETION")); continue; } - if(eventSignaled < 2) - { /* Recording input buffer has been filled */ - if(stream->playbackPin) - { - /* First check if also the next playback buffer has been signaled */ - wait = WaitForSingleObject(stream->events[outbuf+2],0); - if(wait == WAIT_OBJECT_0) - { - /* Yes, so do both buffers at same time */ - fillPlaybuf = 1; - pending--; - /* Was this an underflow situation? */ - if( underover ) - underover |= paOutputUnderflow; /* Yes! */ - } - } - emptyRecordbuf = 1; - pending--; - } - else if(eventSignaled < 4) - { /* Playback output buffer has been emptied */ - if(stream->recordingPin) - { - /* First check if also the next recording buffer has been signaled */ - wait = WaitForSingleObject(stream->events[inbuf],0); - if(wait == WAIT_OBJECT_0) - { /* Yes, so do both buffers at same time */ - emptyRecordbuf = 1; - pending--; - /* Was this an overflow situation? */ - if( underover ) - underover |= paInputOverflow; /* Yes! */ - } - } - fillPlaybuf = 1; - pending--; + if (wait == WAIT_TIMEOUT) + { + continue; } else { - /* Abort event! */ - assert(stream->streamAbort); /* Should have been set */ - PA_DEBUG(("ABORTING ")); - break; - } - ResetEvent(stream->events[eventSignaled]); - - if(stream->streamStop) - { - PA_DEBUG(("Stream stop! pending=%d",pending)); - cbResult = paComplete; /* Stop, but play remaining buffers */ - } - - /* Do necessary buffer processing (which will invoke user callback if necessary */ - doChannelCopy = 0; - if(cbResult==paContinue) - { - PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer ); - if((stream->bufferProcessor.hostInputFrameCount[0] + stream->bufferProcessor.hostInputFrameCount[1]) == - (stream->bufferProcessor.hostOutputFrameCount[0] + stream->bufferProcessor.hostOutputFrameCount[1]) ) - PaUtil_BeginBufferProcessing(&stream->bufferProcessor,&ti,underover); - underover = 0; /* Reset the (under|over)flow status */ - if(fillPlaybuf) + if (eventSignalled < captureEvents) { - PaUtil_SetOutputFrameCount(&stream->bufferProcessor,0); - if( stream->userOutputChannels == 1 ) + if (info.stream->capture.pPin->fnEventHandler(&info, eventSignalled) == paNoError) { - /* Write the single user channel to the first interleaved block */ - PaUtil_SetOutputChannel(&stream->bufferProcessor,0,stream->packets[outbuf+2].Header.Data,stream->deviceOutputChannels); - /* We will do a copy to the other channels after the data has been written */ - doChannelCopy = 1; - } - else - { - for(i=0;iuserOutputChannels;i++) + timeStamp[0] = dwCurrentTime; + + /* Since we use the ring buffer, we can submit the buffers directly */ + if (!info.stream->streamStop) { - /* Only write the user output channels. Leave the rest blank */ - PaUtil_SetOutputChannel(&stream->bufferProcessor,i,((unsigned char*)(stream->packets[outbuf+2].Header.Data))+(i*stream->outputSampleSize),stream->deviceOutputChannels); + result = info.stream->capture.pPin->fnSubmitHandler(&info, info.captureTail); + if (result != paNoError) + { + PA_HP_TRACE((info.stream->hLog, "Capture submit handler failed with result %d", result)); + break; + } + } + ++info.captureTail; + /* If full-duplex, let _only_ render event trigger processing. We still need the stream stop + handling working, so let that be processed anyways... */ + if (info.stream->userOutputChannels > 0) + { + doProcessing = 0; } } } - if(emptyRecordbuf) + else if (eventSignalled < renderEvents) { - PaUtil_SetInputFrameCount(&stream->bufferProcessor,stream->packets[inbuf].Header.DataUsed/stream->bytesPerInputFrame); - for(i=0;iuserInputChannels;i++) - { - /* Only read as many channels as the user wants */ - PaUtil_SetInputChannel(&stream->bufferProcessor,i,((unsigned char*)(stream->packets[inbuf].Header.Data))+(i*stream->inputSampleSize),stream->deviceInputChannels); - } + timeStamp[1] = dwCurrentTime; + eventSignalled -= captureEvents; + info.stream->render.pPin->fnEventHandler(&info, eventSignalled); } - - if (stream->recordingPin && stream->playbackPin) /* full duplex */ + else { - /* Only call the EndBufferProcessing function when the total input frames == total output frames */ + assert(info.stream->streamAbort); + PA_HP_TRACE((info.stream->hLog, "Stream abort!")); + continue; + } + } - if((stream->bufferProcessor.hostInputFrameCount[0] + stream->bufferProcessor.hostInputFrameCount[1]) == - (stream->bufferProcessor.hostOutputFrameCount[0] + stream->bufferProcessor.hostOutputFrameCount[1]) ) - { - framesProcessed = PaUtil_EndBufferProcessing(&stream->bufferProcessor,&cbResult); - } - else - { - framesProcessed = 0; - } - } - else + /* Handle processing */ + if (doProcessing) + { + result = PaDoProcessing(&info); + if (result != paNoError) { - framesProcessed = PaUtil_EndBufferProcessing(&stream->bufferProcessor,&cbResult); + PA_HP_TRACE((info.stream->hLog, "PaDoProcessing failed!")); + break; } + } - if( doChannelCopy ) - { - /* Copy the first output channel to the other channels */ - switch(stream->outputSampleSize) - { - case 2: - DuplicateFirstChannelInt16(stream->packets[outbuf+2].Header.Data,stream->deviceOutputChannels,stream->framesPerHostOBuffer); - break; - case 3: - DuplicateFirstChannelInt24(stream->packets[outbuf+2].Header.Data,stream->deviceOutputChannels,stream->framesPerHostOBuffer); - break; - case 4: - DuplicateFirstChannelInt32(stream->packets[outbuf+2].Header.Data,stream->deviceOutputChannels,stream->framesPerHostOBuffer); - break; - default: - assert(0); /* Unsupported format! */ - break; - } - } - PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, framesProcessed ); - } - else + if(info.stream->streamStop && info.cbResult != paComplete) { - fillPlaybuf = 0; - emptyRecordbuf = 0; + PA_HP_TRACE((info.stream->hLog, "Stream stop! pending=%d",info.pending)); + info.cbResult = paComplete; /* Stop, but play remaining buffers */ } - - /* - if(cbResult != paContinue) + + if(info.pending<=0) { - PA_DEBUG(("cbResult=%d, pending=%d:",cbResult,pending)); - } - */ - /* Submit buffers */ - if((fillPlaybuf)&&(cbResult!=paAbort)) - { - if(!PinWrite(stream->playbackPin->handle,&stream->packets[outbuf+2])) - outbuf = (outbuf+1)&1; /* Increment and wrap */ - pending++; - if( priming ) - priming--; /* Have to prime twice */ - } - if((emptyRecordbuf)&&(cbResult==paContinue)) - { - stream->packets[inbuf].Header.DataUsed = 0; /* Reset for reuse */ - PinRead(stream->recordingPin->handle,&stream->packets[inbuf]); - inbuf = (inbuf+1)&1; /* Increment and wrap */ - pending++; - } - if(pending==0) - { - PA_DEBUG(("pending==0 finished...;")); + PA_HP_TRACE((info.stream->hLog, "pending==0 finished...")); break; } - if((!stream->playbackPin)&&(cbResult!=paContinue)) + if((!info.stream->render.pPin)&&(info.cbResult!=paContinue)) { - PA_DEBUG(("record only cbResult=%d...;",cbResult)); + PA_HP_TRACE((info.stream->hLog, "record only cbResult=%d...",info.cbResult)); break; } } - PA_DEBUG(("Finished thread")); + PA_DEBUG(("Finished processing loop\n")); - /* Finished, either normally or aborted */ - if(stream->playbackPin) + info.stream->threadResult = result; + goto bailout; + +error: + PA_DEBUG(("Error starting processing thread\n")); + /* Set the "error" event together with result */ + info.stream->threadResult = result; + SetEvent(info.stream->eventStreamStart[StreamStart_kFailed]); + +bailout: + if (hTimer) { - result = PinSetState(stream->playbackPin, KSSTATE_PAUSE); - result = PinSetState(stream->playbackPin, KSSTATE_STOP); - } - if(stream->recordingPin) - { - result = PinSetState(stream->recordingPin, KSSTATE_PAUSE); - result = PinSetState(stream->recordingPin, KSSTATE_STOP); + PA_DEBUG(("Waitable timer stopped\n", timerPeriod)); + CancelWaitableTimer(hTimer); + CloseHandle(hTimer); + hTimer = 0; } - stream->streamActive = 0; - - if((!stream->streamStop)&&(!stream->streamAbort)) + if (info.pinsStarted) { - /* Invoke the user stream finished callback */ - /* Only do it from here if not being stopped/aborted by user */ - if( stream->streamRepresentation.streamFinishedCallback != 0 ) - stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData ); + StopPins(&info); } - stream->streamStop = 0; - stream->streamAbort = 0; - /* Reset process priority if necessary */ - if(stream->oldProcessPriority != REALTIME_PRIORITY_CLASS) + /* Lower prio here */ + DropThreadPriority(hAVRT); + + if (handleArray != NULL) { - SetPriorityClass(GetCurrentProcess(),stream->oldProcessPriority); - stream->oldProcessPriority = REALTIME_PRIORITY_CLASS; + PaUtil_FreeMemory(handleArray); } +#if PA_TRACE_REALTIME_EVENTS + if (info.stream->hLog) + { + PA_DEBUG(("Dumping highspeed trace...\n")); + PaUtil_DumpHighSpeedLog(info.stream->hLog, "hp_trace.log"); + PaUtil_DiscardHighSpeedLog(info.stream->hLog); + info.stream->hLog = 0; + } +#endif + info.stream->streamActive = 0; + + if((!info.stream->streamStop)&&(!info.stream->streamAbort)) + { + /* Invoke the user stream finished callback */ + /* Only do it from here if not being stopped/aborted by user */ + if( info.stream->streamRepresentation.streamFinishedCallback != 0 ) + info.stream->streamRepresentation.streamFinishedCallback( info.stream->streamRepresentation.userData ); + } + info.stream->streamStop = 0; + info.stream->streamAbort = 0; + PA_LOGL_; - EXIT_THREAD; return 0; } + static PaError StartStream( PaStream *s ) { PaError result = paNoError; PaWinWdmStream *stream = (PaWinWdmStream*)s; DWORD dwID; - BOOL ret; - int size; PA_LOGE_; stream->streamStop = 0; stream->streamAbort = 0; - size = 5; - while(size--) - { - if(stream->events[size] != NULL) - { - ResetEvent(stream->events[size]); - } - } + + ResetStreamEvents(stream); PaUtil_ResetBufferProcessor( &stream->bufferProcessor ); stream->oldProcessPriority = GetPriorityClass(GetCurrentProcess()); /* Uncomment the following line to enable dynamic boosting of the process - * priority to real time for best low latency support - * Disabled by default because RT processes can easily block the OS */ + * priority to real time for best low latency support + * Disabled by default because RT processes can easily block the OS */ /*ret = SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS); - PA_DEBUG(("Class ret = %d;",ret));*/ + PA_DEBUG(("Class ret = %d;",ret));*/ - stream->streamStarted = 1; - stream->streamThread = (HANDLE)_beginthreadex(NULL, 0, ProcessingThread, stream, 0, &dwID); + stream->streamThread = CREATE_THREAD_FUNCTION (NULL, 0, ProcessingThread, stream, CREATE_SUSPENDED, &dwID); if(stream->streamThread == NULL) { - stream->streamStarted = 0; result = paInsufficientMemory; goto end; } - ret = SetThreadPriority(stream->streamThread,THREAD_PRIORITY_TIME_CRITICAL); - PA_DEBUG(("Priority ret = %d;",ret)); - /* Make the stream active */ - stream->streamActive = 1; + ResumeThread(stream->streamThread); + + switch (WaitForMultipleObjects(2, stream->eventStreamStart, FALSE, 5000)) + { + case WAIT_OBJECT_0 + StreamStart_kOk: + PA_DEBUG(("Processing thread started!\n")); + result = paNoError; + /* streamActive is set in processing thread */ + stream->streamStarted = 1; + break; + case WAIT_OBJECT_0 + StreamStart_kFailed: + PA_DEBUG(("Processing thread start failed! (result=%d)\n", stream->threadResult)); + result = stream->threadResult; + /* Wait for the stream to really exit */ + WaitForSingleObject(stream->streamThread, 200); + CloseHandle(stream->streamThread); + stream->streamThread = 0; + break; + case WAIT_TIMEOUT: + default: + result = paTimedOut; + PaWinWDM_SetLastErrorInfo(result, "Failed to start processing thread (timeout)!"); + break; + } end: PA_LOGL_; @@ -3098,29 +6107,39 @@ static PaError StopStream( PaStream *s ) if(stream->streamActive) { + DWORD dwExitCode; doCb = 1; stream->streamStop = 1; - while(stream->streamActive) + if (GetExitCodeThread(stream->streamThread, &dwExitCode) && dwExitCode == STILL_ACTIVE) { - PA_DEBUG(("W.")); - Sleep(10); /* Let thread sleep for 10 msec */ + if (WaitForSingleObject(stream->streamThread, INFINITE) != WAIT_OBJECT_0) + { + PA_DEBUG(("StopStream: stream thread terminated\n")); + TerminateThread(stream->streamThread, -1); + result = paTimedOut; + } + } + else + { + PA_DEBUG(("StopStream: GECT says not active, but streamActive is not false ??")); + result = paUnanticipatedHostError; + PaWinWDM_SetLastErrorInfo(result, "StopStream: GECT says not active, but streamActive = %d", stream->streamActive); + } + } + else + { + if (stream->threadResult != paNoError) + { + PA_DEBUG(("StopStream: Stream not active (%d)\n", stream->threadResult)); + result = stream->threadResult; + stream->threadResult = paNoError; } } - PA_DEBUG(("Terminating thread")); - if(stream->streamStarted && stream->streamThread) - { - TerminateThread(stream->streamThread,0); - stream->streamThread = NULL; - } - + CloseHandle(stream->streamThread); + stream->streamThread = 0; stream->streamStarted = 0; - - if(stream->oldProcessPriority != REALTIME_PRIORITY_CLASS) - { - SetPriorityClass(GetCurrentProcess(),stream->oldProcessPriority); - stream->oldProcessPriority = REALTIME_PRIORITY_CLASS; - } + stream->streamActive = 0; if(doCb) { @@ -3128,7 +6147,7 @@ static PaError StopStream( PaStream *s ) /* This means it should be safe for the called function */ /* to invoke e.g. StartStream */ if( stream->streamRepresentation.streamFinishedCallback != 0 ) - stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData ); + stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData ); } PA_LOGL_; @@ -3147,27 +6166,20 @@ static PaError AbortStream( PaStream *s ) { doCb = 1; stream->streamAbort = 1; - SetEvent(stream->events[4]); /* Signal immediately */ - while(stream->streamActive) + SetEvent(stream->eventAbort); /* Signal immediately */ + if (WaitForSingleObject(stream->streamThread, 10000) != WAIT_OBJECT_0) { - Sleep(10); + TerminateThread(stream->streamThread, -1); + result = paTimedOut; + + PA_DEBUG(("AbortStream: stream thread terminated\n")); } + assert(!stream->streamActive); } - - if(stream->streamStarted && stream->streamThread) - { - TerminateThread(stream->streamThread,0); - stream->streamThread = NULL; - } - + CloseHandle(stream->streamThread); + stream->streamThread = NULL; stream->streamStarted = 0; - if(stream->oldProcessPriority != REALTIME_PRIORITY_CLASS) - { - SetPriorityClass(GetCurrentProcess(),stream->oldProcessPriority); - stream->oldProcessPriority = REALTIME_PRIORITY_CLASS; - } - if(doCb) { /* Do user callback now after all state has been reset */ @@ -3236,13 +6248,32 @@ static double GetStreamCpuLoad( PaStream* s ) /* - As separate stream interfaces are used for blocking and callback - streams, the following functions can be guaranteed to only be called - for blocking streams. +As separate stream interfaces are used for blocking and callback +streams, the following functions can be guaranteed to only be called +for blocking streams. */ static PaError ReadStream( PaStream* s, - void *buffer, + void *buffer, + unsigned long frames ) +{ + PaWinWdmStream *stream = (PaWinWdmStream*)s; + + PA_LOGE_; + + /* suppress unused variable warnings */ + (void) buffer; + (void) frames; + (void) stream; + + /* IMPLEMENT ME, see portaudio.h for required behavior*/ + PA_LOGL_; + return paInternalError; +} + + +static PaError WriteStream( PaStream* s, + const void *buffer, unsigned long frames ) { PaWinWdmStream *stream = (PaWinWdmStream*)s; @@ -3256,26 +6287,7 @@ static PaError ReadStream( PaStream* s, /* IMPLEMENT ME, see portaudio.h for required behavior*/ PA_LOGL_; - return paNoError; -} - - -static PaError WriteStream( PaStream* s, - const void *buffer, - unsigned long frames ) -{ - PaWinWdmStream *stream = (PaWinWdmStream*)s; - - PA_LOGE_; - - /* suppress unused variable warnings */ - (void) buffer; - (void) frames; - (void) stream; - - /* IMPLEMENT ME, see portaudio.h for required behavior*/ - PA_LOGL_; - return paNoError; + return paInternalError; } @@ -3305,4 +6317,296 @@ static signed long GetStreamWriteAvailable( PaStream* s ) /* IMPLEMENT ME, see portaudio.h for required behavior*/ PA_LOGL_; return 0; -} \ No newline at end of file +} + +/***************************************************************************************/ +/* Event and submit handlers for WaveCyclic */ +/***************************************************************************************/ + +static PaError PaPinCaptureEventHandler_WaveCyclic(PaProcessThreadInfo* pInfo, unsigned eventIndex) +{ + ring_buffer_size_t frameCount; + DATAPACKET* packet = pInfo->stream->capture.packets + eventIndex; + + assert( eventIndex < pInfo->stream->capture.noOfPackets ); + + if (packet->Header.DataUsed == 0) + { + PA_HP_TRACE((pInfo->stream->hLog, ">>> Capture bogus event: idx=%u (DataUsed=%u)", eventIndex, packet->Header.DataUsed)); + + /* Bogus event, reset! This is to handle the behavior of this USB mic: http://shop.xtz.se/measurement-system/microphone-to-dirac-live-room-correction-suite + on startup of streaming, where it erroneously sets the event without the corresponding buffer being filled (DataUsed == 0) */ + ResetEvent(packet->Signal.hEvent); + return -1; + } + + pInfo->capturePackets[pInfo->captureHead & cPacketsArrayMask].packet = packet; + + frameCount = PaUtil_WriteRingBuffer(&pInfo->stream->ringBuffer, packet->Header.Data, pInfo->stream->capture.framesPerBuffer); + + PA_HP_TRACE((pInfo->stream->hLog, ">>> Capture event: idx=%u (frames=%u)", eventIndex, frameCount)); + ++pInfo->captureHead; + --pInfo->pending; + return paNoError; +} + +static PaError PaPinCaptureSubmitHandler_WaveCyclic(PaProcessThreadInfo* pInfo, unsigned eventIndex) +{ + PaError result = paNoError; + DATAPACKET* packet = pInfo->capturePackets[pInfo->captureTail & cPacketsArrayMask].packet; + pInfo->capturePackets[pInfo->captureTail & cPacketsArrayMask].packet = 0; + assert(packet != 0); + PA_HP_TRACE((pInfo->stream->hLog, "Capture submit: %u", eventIndex)); + packet->Header.DataUsed = 0; /* Reset for reuse */ + ResetEvent(packet->Signal.hEvent); + result = PinRead(pInfo->stream->capture.pPin->handle, packet); + ++pInfo->pending; + return result; +} + +static PaError PaPinRenderEventHandler_WaveCyclic(PaProcessThreadInfo* pInfo, unsigned eventIndex) +{ + assert( eventIndex < pInfo->stream->render.noOfPackets ); + + pInfo->renderPackets[pInfo->renderHead & cPacketsArrayMask].packet = pInfo->stream->render.packets + eventIndex; + PA_HP_TRACE((pInfo->stream->hLog, "<<< Render event : idx=%u head=%u", eventIndex, pInfo->renderHead)); + ++pInfo->renderHead; + --pInfo->pending; + return paNoError; +} + +static PaError PaPinRenderSubmitHandler_WaveCyclic(PaProcessThreadInfo* pInfo, unsigned eventIndex) +{ + PaError result = paNoError; + DATAPACKET* packet = pInfo->renderPackets[pInfo->renderTail & cPacketsArrayMask].packet; + pInfo->renderPackets[pInfo->renderTail & cPacketsArrayMask].packet = 0; + assert(packet != 0); + + PA_HP_TRACE((pInfo->stream->hLog, "Render submit : %u idx=%u", pInfo->renderTail, (unsigned)(packet - pInfo->stream->render.packets))); + ResetEvent(packet->Signal.hEvent); + result = PinWrite(pInfo->stream->render.pPin->handle, packet); + /* Reset event, just in case we have an analogous situation to capture (see PaPinCaptureSubmitHandler_WaveCyclic) */ + ++pInfo->pending; + if (pInfo->priming) + { + --pInfo->priming; + } + return result; +} + +/***************************************************************************************/ +/* Event and submit handlers for WaveRT */ +/***************************************************************************************/ + +static PaError PaPinCaptureEventHandler_WaveRTEvent(PaProcessThreadInfo* pInfo, unsigned eventIndex) +{ + unsigned long pos; + unsigned realInBuf; + unsigned frameCount; + PaWinWdmIOInfo* pCapture = &pInfo->stream->capture; + const unsigned halfInputBuffer = pCapture->hostBufferSize >> 1; + PaWinWdmPin* pin = pCapture->pPin; + DATAPACKET* packet = 0; + + /* Get hold of current ADC position */ + pin->fnAudioPosition(pin, &pos); + /* Wrap it (robi: why not use hw latency compensation here ?? because pos then gets _way_ off from + where it should be, i.e. at beginning or half buffer position. Why? No idea.) */ + + pos %= pCapture->hostBufferSize; + /* Then realInBuf will point to "other" half of double buffer */ + realInBuf = pos < halfInputBuffer ? 1U : 0U; + + packet = pInfo->stream->capture.packets + realInBuf; + + /* Call barrier (or dummy) */ + pin->fnMemBarrier(); + + /* Put it in queue */ + frameCount = PaUtil_WriteRingBuffer(&pInfo->stream->ringBuffer, packet->Header.Data, pCapture->framesPerBuffer); + + pInfo->capturePackets[pInfo->captureHead & cPacketsArrayMask].packet = packet; + + PA_HP_TRACE((pInfo->stream->hLog, "Capture event (WaveRT): idx=%u head=%u (pos = %4.1lf%%, frames=%u)", realInBuf, pInfo->captureHead, (pos * 100.0 / pCapture->hostBufferSize), frameCount)); + + ++pInfo->captureHead; + --pInfo->pending; + + return paNoError; +} + +static PaError PaPinCaptureEventHandler_WaveRTPolled(PaProcessThreadInfo* pInfo, unsigned eventIndex) +{ + unsigned long pos; + unsigned bytesToRead; + PaWinWdmIOInfo* pCapture = &pInfo->stream->capture; + const unsigned halfInputBuffer = pCapture->hostBufferSize>>1; + PaWinWdmPin* pin = pInfo->stream->capture.pPin; + + /* Get hold of current ADC position */ + pin->fnAudioPosition(pin, &pos); + /* Wrap it (robi: why not use hw latency compensation here ?? because pos then gets _way_ off from + where it should be, i.e. at beginning or half buffer position. Why? No idea.) */ + /* Compensate for HW FIFO to get to last read buffer position */ + pos += pin->hwLatency; + pos %= pCapture->hostBufferSize; + /* Need to align position on frame boundary */ + pos &= ~(pCapture->bytesPerFrame - 1); + + /* Call barrier (or dummy) */ + pin->fnMemBarrier(); + + /* Put it in "queue" */ + bytesToRead = (pCapture->hostBufferSize + pos - pCapture->lastPosition) % pCapture->hostBufferSize; + if (bytesToRead > 0) + { + unsigned frameCount = PaUtil_WriteRingBuffer(&pInfo->stream->ringBuffer, + pCapture->hostBuffer + pCapture->lastPosition, + bytesToRead / pCapture->bytesPerFrame); + + pCapture->lastPosition = (pCapture->lastPosition + frameCount * pCapture->bytesPerFrame) % pCapture->hostBufferSize; + + PA_HP_TRACE((pInfo->stream->hLog, "Capture event (WaveRTPolled): pos = %4.1lf%%, framesRead=%u", (pos * 100.0 / pCapture->hostBufferSize), frameCount)); + ++pInfo->captureHead; + --pInfo->pending; + } + return paNoError; +} + +static PaError PaPinCaptureSubmitHandler_WaveRTEvent(PaProcessThreadInfo* pInfo, unsigned eventIndex) +{ + pInfo->capturePackets[pInfo->captureTail & cPacketsArrayMask].packet = 0; + ++pInfo->pending; + return paNoError; +} + +static PaError PaPinCaptureSubmitHandler_WaveRTPolled(PaProcessThreadInfo* pInfo, unsigned eventIndex) +{ + pInfo->capturePackets[pInfo->captureTail & cPacketsArrayMask].packet = 0; + ++pInfo->pending; + return paNoError; +} + +static PaError PaPinRenderEventHandler_WaveRTEvent(PaProcessThreadInfo* pInfo, unsigned eventIndex) +{ + unsigned long pos; + unsigned realOutBuf; + PaWinWdmIOInfo* pRender = &pInfo->stream->render; + const unsigned halfOutputBuffer = pRender->hostBufferSize >> 1; + PaWinWdmPin* pin = pInfo->stream->render.pPin; + PaIOPacket* ioPacket = &pInfo->renderPackets[pInfo->renderHead & cPacketsArrayMask]; + + /* Get hold of current DAC position */ + pin->fnAudioPosition(pin, &pos); + /* Compensate for HW FIFO to get to last read buffer position */ + pos += pin->hwLatency; + /* Wrap it */ + pos %= pRender->hostBufferSize; + /* And align it, not sure its really needed though */ + pos &= ~(pRender->bytesPerFrame - 1); + /* Then realOutBuf will point to "other" half of double buffer */ + realOutBuf = pos < halfOutputBuffer ? 1U : 0U; + + if (pInfo->priming) + { + realOutBuf = pInfo->renderHead & 0x1; + } + ioPacket->packet = pInfo->stream->render.packets + realOutBuf; + ioPacket->startByte = realOutBuf * halfOutputBuffer; + ioPacket->lengthBytes = halfOutputBuffer; + + PA_HP_TRACE((pInfo->stream->hLog, "Render event (WaveRT) : idx=%u head=%u (pos = %4.1lf%%)", realOutBuf, pInfo->renderHead, (pos * 100.0 / pRender->hostBufferSize) )); + + ++pInfo->renderHead; + --pInfo->pending; + return paNoError; +} + +static PaError PaPinRenderEventHandler_WaveRTPolled(PaProcessThreadInfo* pInfo, unsigned eventIndex) +{ + unsigned long pos; + unsigned realOutBuf; + unsigned bytesToWrite; + + PaWinWdmIOInfo* pRender = &pInfo->stream->render; + const unsigned halfOutputBuffer = pRender->hostBufferSize >> 1; + PaWinWdmPin* pin = pInfo->stream->render.pPin; + PaIOPacket* ioPacket = &pInfo->renderPackets[pInfo->renderHead & cPacketsArrayMask]; + + /* Get hold of current DAC position */ + pin->fnAudioPosition(pin, &pos); + /* Compensate for HW FIFO to get to last read buffer position */ + pos += pin->hwLatency; + /* Wrap it */ + pos %= pRender->hostBufferSize; + /* And align it, not sure its really needed though */ + pos &= ~(pRender->bytesPerFrame - 1); + + if (pInfo->priming) + { + realOutBuf = pInfo->renderHead & 0x1; + ioPacket->packet = pInfo->stream->render.packets + realOutBuf; + ioPacket->startByte = realOutBuf * halfOutputBuffer; + ioPacket->lengthBytes = halfOutputBuffer; + ++pInfo->renderHead; + --pInfo->pending; + } + else + { + bytesToWrite = (pRender->hostBufferSize + pos - pRender->lastPosition) % pRender->hostBufferSize; + ++pRender->pollCntr; + if (bytesToWrite >= halfOutputBuffer) + { + realOutBuf = (pos < halfOutputBuffer) ? 1U : 0U; + ioPacket->packet = pInfo->stream->render.packets + realOutBuf; + pRender->lastPosition = realOutBuf ? 0U : halfOutputBuffer; + ioPacket->startByte = realOutBuf * halfOutputBuffer; + ioPacket->lengthBytes = halfOutputBuffer; + ++pInfo->renderHead; + --pInfo->pending; + PA_HP_TRACE((pInfo->stream->hLog, "Render event (WaveRTPolled) : idx=%u head=%u (pos = %4.1lf%%, cnt=%u)", realOutBuf, pInfo->renderHead, (pos * 100.0 / pRender->hostBufferSize), pRender->pollCntr)); + pRender->pollCntr = 0; + } + } + return paNoError; +} + +static PaError PaPinRenderSubmitHandler_WaveRTEvent(PaProcessThreadInfo* pInfo, unsigned eventIndex) +{ + PaWinWdmPin* pin = pInfo->stream->render.pPin; + pInfo->renderPackets[pInfo->renderTail & cPacketsArrayMask].packet = 0; + /* Call barrier (if needed) */ + pin->fnMemBarrier(); + PA_HP_TRACE((pInfo->stream->hLog, "Render submit (WaveRT) : submit=%u", pInfo->renderTail)); + ++pInfo->pending; + if (pInfo->priming) + { + --pInfo->priming; + if (pInfo->priming) + { + PA_HP_TRACE((pInfo->stream->hLog, "Setting WaveRT event for priming (2)")); + SetEvent(pInfo->stream->render.events[0]); + } + } + return paNoError; +} + +static PaError PaPinRenderSubmitHandler_WaveRTPolled(PaProcessThreadInfo* pInfo, unsigned eventIndex) +{ + PaWinWdmPin* pin = pInfo->stream->render.pPin; + pInfo->renderPackets[pInfo->renderTail & cPacketsArrayMask].packet = 0; + /* Call barrier (if needed) */ + pin->fnMemBarrier(); + PA_HP_TRACE((pInfo->stream->hLog, "Render submit (WaveRTPolled) : submit=%u", pInfo->renderTail)); + ++pInfo->pending; + if (pInfo->priming) + { + --pInfo->priming; + if (pInfo->priming) + { + PA_HP_TRACE((pInfo->stream->hLog, "Setting WaveRT event for priming (2)")); + SetEvent(pInfo->stream->render.events[0]); + } + } + return paNoError; +} diff --git a/3rdparty/portaudio/src/hostapi/wdmks/readme.txt b/3rdparty/portaudio/src/hostapi/wdmks/readme.txt index 2a366f237..b3faf3385 100644 --- a/3rdparty/portaudio/src/hostapi/wdmks/readme.txt +++ b/3rdparty/portaudio/src/hostapi/wdmks/readme.txt @@ -3,12 +3,15 @@ Notes about WDM-KS host API Status history -------------- +16th January 2011: +Added support for WaveRT device API (Vista and later) for even lesser +latency support. + 10th November 2005: Made following changes: * OpenStream: Try all PaSampleFormats internally if the the chosen format is not supported natively. This fixed several problems - with soundcards that soundcards that did not take kindly to - using 24-bit 3-byte formats. + with soundcards that did not take kindly to using 24-bit 3-byte formats. * OpenStream: Make the minimum framesPerHostIBuffer (and framesPerHostOBuffer) the default frameSize for the playback/recording pin. * ProcessingThread: Added a switch to only call PaUtil_EndBufferProcessing @@ -71,7 +74,7 @@ In PortAudio terms, this means having a stream Open on a WDMKS device. Usage ----- To add the WDMKS backend to your program which is already using -PortAudio, you must undefine PA_NO_WDMKS from your build file, +PortAudio, you must define PA_USE_WDMKS=1 in your build file, and include the pa_win_wdmks\pa_win_wdmks.c into your build. The file should compile in both C and C++. You will need a DirectX SDK installed on your system for the @@ -79,4 +82,4 @@ ks.h and ksmedia.h header files. You will need to link to the system "setupapi" library. Note that if you use MinGW, you will get more warnings from the DX header files when using GCC(C), and still a few warnings -with G++(CPP). \ No newline at end of file +with G++(CPP). From 72d47d547ef42c4e832af13f4a74b25b0d696a81 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Thu, 12 Apr 2012 06:30:35 +0000 Subject: [PATCH 59/83] copyright: * update missing copyright on + plugins/GSdx/config.h + pcsx2/MTVU.h + plugins/zzogl-pg/opengl/ZZHacks.h + plugins/spu2-x/src/DplIIdecoder.cpp * put a copyright for trivial script file + pcsx2/gui/Resources/rebuild.sh + tools/bin2app.sh + plugins/zzogl-pg/opengl/shaders.sh * remove autotool from zzogl * apply the patch for issue 1257. Thanks very much Micove for the hard work. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5154 96395faa-99c1-11dd-bbfe-3dabce05a288 --- cmake/SelectPcsx2Plugins.cmake | 2 +- linux_various/detect_missing_file_in_cmake.sh | 14 + pcsx2/MTVU.h | 16 +- pcsx2/ZipTools/thread_gzip.cpp | 2 +- pcsx2/ZipTools/thread_lzma.cpp | 2 +- pcsx2/gui/Panels/ThemeSelectorPanel.cpp | 2 +- pcsx2/gui/Resources/rebuild.sh | 14 + pcsx2/gui/SysState.cpp | 2 +- plugins/GSdx/config.h | 21 ++ plugins/spu2-x/src/DecodeDPLII.cpp | 2 +- plugins/spu2-x/src/DplIIdecoder.cpp | 20 ++ plugins/spu2-x/src/Linux/ConfigSoundTouch.cpp | 2 +- plugins/zzogl-pg/build.sh | 32 -- plugins/zzogl-pg/opengl/Linux/Makefile.am | 4 - plugins/zzogl-pg/opengl/Makefile.am | 42 --- plugins/zzogl-pg/opengl/ZZHacks.h | 19 ++ plugins/zzogl-pg/opengl/common.h | 10 +- plugins/zzogl-pg/opengl/configure.ac | 123 ------- plugins/zzogl-pg/opengl/depcomp | 1 - plugins/zzogl-pg/opengl/install-sh | 323 ------------------ plugins/zzogl-pg/opengl/linux_replay.cpp | 2 +- plugins/zzogl-pg/opengl/missing | 1 - plugins/zzogl-pg/opengl/shaders.sh | 15 + tools/bin2app.sh | 14 + 24 files changed, 145 insertions(+), 540 deletions(-) delete mode 100644 plugins/zzogl-pg/build.sh delete mode 100644 plugins/zzogl-pg/opengl/Linux/Makefile.am delete mode 100644 plugins/zzogl-pg/opengl/Makefile.am delete mode 100644 plugins/zzogl-pg/opengl/configure.ac delete mode 120000 plugins/zzogl-pg/opengl/depcomp delete mode 100644 plugins/zzogl-pg/opengl/install-sh delete mode 120000 plugins/zzogl-pg/opengl/missing diff --git a/cmake/SelectPcsx2Plugins.cmake b/cmake/SelectPcsx2Plugins.cmake index 060bf0681..88bb76597 100644 --- a/cmake/SelectPcsx2Plugins.cmake +++ b/cmake/SelectPcsx2Plugins.cmake @@ -222,7 +222,7 @@ endif(ALSA_FOUND AND PORTAUDIO_FOUND AND SOUNDTOUCH_FOUND AND common_libs) #--------------------------------------- if(SOUNDTOUCH_FOUND AND ALSA_FOUND) set(zerospu2 TRUE) - # Comment the next line, if you want to compile spu2x + # Comment the next line, if you want to compile zerospu2 set(zerospu2 FALSE) message(STATUS "Don't build zerospu2. It is super-seeded by spu2x") else(SOUNDTOUCH_FOUND AND ALSA_FOUND) diff --git a/linux_various/detect_missing_file_in_cmake.sh b/linux_various/detect_missing_file_in_cmake.sh index c4807b386..a46141b24 100755 --- a/linux_various/detect_missing_file_in_cmake.sh +++ b/linux_various/detect_missing_file_in_cmake.sh @@ -1,5 +1,19 @@ #!/bin/sh +# PCSX2 - PS2 Emulator for PCs +# Copyright (C) 2002-2011 PCSX2 Dev Team +# +# PCSX2 is free software: you can redistribute it and/or modify it under the terms +# of the GNU Lesser General Public License as published by the Free Software Found- +# ation, either version 3 of the License, or (at your option) any later version. +# +# PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with PCSX2. +# If not, see . + # Script default parameter MAX_DEPTH=1 DIR=$PWD diff --git a/pcsx2/MTVU.h b/pcsx2/MTVU.h index 052bfdac5..d6eec9104 100644 --- a/pcsx2/MTVU.h +++ b/pcsx2/MTVU.h @@ -1,3 +1,17 @@ +/* PCSX2 - PS2 Emulator for PCs + * Copyright (C) 2002-2010 PCSX2 Dev Team + * + * PCSX2 is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with PCSX2. + * If not, see . + */ #pragma once #include "System/SysThreads.h" @@ -87,4 +101,4 @@ private: u32 Get_vuCycles(); }; -extern __aligned16 VU_Thread vu1Thread; \ No newline at end of file +extern __aligned16 VU_Thread vu1Thread; diff --git a/pcsx2/ZipTools/thread_gzip.cpp b/pcsx2/ZipTools/thread_gzip.cpp index ca437fda8..41d09eecd 100644 --- a/pcsx2/ZipTools/thread_gzip.cpp +++ b/pcsx2/ZipTools/thread_gzip.cpp @@ -3,7 +3,7 @@ * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of te License, or (at your option) any later version. + * ation, either version 3 of the License, or (at your option) any later version. * * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR diff --git a/pcsx2/ZipTools/thread_lzma.cpp b/pcsx2/ZipTools/thread_lzma.cpp index fd06a199f..48c9329f2 100644 --- a/pcsx2/ZipTools/thread_lzma.cpp +++ b/pcsx2/ZipTools/thread_lzma.cpp @@ -3,7 +3,7 @@ * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of te License, or (at your option) any later version. + * ation, either version 3 of the License, or (at your option) any later version. * * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR diff --git a/pcsx2/gui/Panels/ThemeSelectorPanel.cpp b/pcsx2/gui/Panels/ThemeSelectorPanel.cpp index 6c9719b45..e9044824f 100644 --- a/pcsx2/gui/Panels/ThemeSelectorPanel.cpp +++ b/pcsx2/gui/Panels/ThemeSelectorPanel.cpp @@ -3,7 +3,7 @@ * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of te License, or (at your option) any later version. + * ation, either version 3 of the License, or (at your option) any later version. * * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR diff --git a/pcsx2/gui/Resources/rebuild.sh b/pcsx2/gui/Resources/rebuild.sh index 51cb30614..6a4b060dd 100755 --- a/pcsx2/gui/Resources/rebuild.sh +++ b/pcsx2/gui/Resources/rebuild.sh @@ -1,5 +1,19 @@ #!/bin/sh +# PCSX2 - PS2 Emulator for PCs +# Copyright (C) 2002-2011 PCSX2 Dev Team +# +# PCSX2 is free software: you can redistribute it and/or modify it under the terms +# of the GNU Lesser General Public License as published by the Free Software Found- +# ation, either version 3 of the License, or (at your option) any later version. +# +# PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with PCSX2. +# If not, see . + ../../../tools/bin/bin2cpp BackgroundLogo.png ../../../tools/bin/bin2cpp AppIcon16.png ../../../tools/bin/bin2cpp AppIcon32.png diff --git a/pcsx2/gui/SysState.cpp b/pcsx2/gui/SysState.cpp index c976dd058..dafa635e7 100644 --- a/pcsx2/gui/SysState.cpp +++ b/pcsx2/gui/SysState.cpp @@ -3,7 +3,7 @@ * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of te License, or (at your option) any later version. + * ation, either version 3 of the License, or (at your option) any later version. * * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR diff --git a/plugins/GSdx/config.h b/plugins/GSdx/config.h index 1f63b0142..745bc3582 100644 --- a/plugins/GSdx/config.h +++ b/plugins/GSdx/config.h @@ -1,3 +1,24 @@ +/* + * Copyright (C) 2007-2009 Gabest + * http://www.gabest.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + #pragma once //#define ENABLE_VTUNE diff --git a/plugins/spu2-x/src/DecodeDPLII.cpp b/plugins/spu2-x/src/DecodeDPLII.cpp index bd219ca8d..57e89ba3b 100644 --- a/plugins/spu2-x/src/DecodeDPLII.cpp +++ b/plugins/spu2-x/src/DecodeDPLII.cpp @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free - * Software Foundation; either version 2.1 of the the License, or (at your + * Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT diff --git a/plugins/spu2-x/src/DplIIdecoder.cpp b/plugins/spu2-x/src/DplIIdecoder.cpp index afe054679..4fad8137a 100644 --- a/plugins/spu2-x/src/DplIIdecoder.cpp +++ b/plugins/spu2-x/src/DplIIdecoder.cpp @@ -1,3 +1,23 @@ +/* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2 + * Developed and maintained by the Pcsx2 Development Team. + * + * Original portions from SPU2ghz are (c) 2008 by David Quintana [gigaherz] + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + #include "Global.h" static const u8 sLogTable[256] = { diff --git a/plugins/spu2-x/src/Linux/ConfigSoundTouch.cpp b/plugins/spu2-x/src/Linux/ConfigSoundTouch.cpp index ccc23215b..d1535fffc 100644 --- a/plugins/spu2-x/src/Linux/ConfigSoundTouch.cpp +++ b/plugins/spu2-x/src/Linux/ConfigSoundTouch.cpp @@ -5,7 +5,7 @@ * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free - * Software Foundation; either version 2.1 of the the License, or (at your + * Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT diff --git a/plugins/zzogl-pg/build.sh b/plugins/zzogl-pg/build.sh deleted file mode 100644 index 4271e3b1c..000000000 --- a/plugins/zzogl-pg/build.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh - -curdir=`pwd` - -echo ---------------------- -echo Building ZZOpenGL -echo ---------------------- - -cd ${curdir}/opengl - -if [ $# -gt 0 ] && [ $1 = "all" ] -then - -aclocal -automake -autoconf -chmod +x configure -./configure --enable-sse2 --prefix=${PCSX2PLUGINS} -make clean -make install - -else -make $@ -fi - -if [ $? -ne 0 ] -then -exit 1 -fi - -#cp libZeroGSogl*.so* ${PCSX2PLUGINS}/ -cp Win32/ps2hw.dat ${PCSX2PLUGINS}/ diff --git a/plugins/zzogl-pg/opengl/Linux/Makefile.am b/plugins/zzogl-pg/opengl/Linux/Makefile.am deleted file mode 100644 index 49198459e..000000000 --- a/plugins/zzogl-pg/opengl/Linux/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -noinst_LIBRARIES = libZeroGSLinux.a - -INCLUDES = $(shell pkg-config --cflags gtk+-2.0) -I@srcdir@/../ -I@srcdir@/../../../../common/include -libZeroGSLinux_a_SOURCES = Conf.cpp Linux.cpp diff --git a/plugins/zzogl-pg/opengl/Makefile.am b/plugins/zzogl-pg/opengl/Makefile.am deleted file mode 100644 index faf2a7fc3..000000000 --- a/plugins/zzogl-pg/opengl/Makefile.am +++ /dev/null @@ -1,42 +0,0 @@ -# Create a shared library libzzoglpg -AUTOMAKE_OPTIONS = foreign -noinst_LIBRARIES = libzzoglpg.a -INCLUDES = -I@srcdir@/../../../common/include -I@srcdir@/common -I@srcdir@/../../../3rdparty/ - -libzzoglpg_a_CPPFLAGS = $(shell pkg-config --cflags gtk+-2.0) -libzzoglpg_a_CXXFLAGS = $(shell pkg-config --cflags gtk+-2.0) - -# Create a shared object by faking an exe (thanks to ODE makefiles) -traplibdir=$(prefix) - - -if RELEASE_TO_PUBLIC -preext=r -endif - -EXEEXT=$(preext)@so_ext@ - -traplib_PROGRAMS=libzzoglpg -libzzoglpg_SOURCES= -libzzoglpg_DEPENDENCIES = libzzoglpg.a ../../../deps/release/libUtilities.a -libzzoglpg_LDFLAGS= @SHARED_LDFLAGS@ -libzzoglpg_LDFLAGS+=-Wl,-soname,@ZEROGS_SONAME@ -libzzoglpg_LDADD=$(libzzoglpg_a_OBJECTS) - -libzzoglpg_a_SOURCES = \ -GSmain.cpp GLWinX11.cpp GifTransfer.cpp memcpy_amd.cpp Regs.cpp x86.cpp zpipe.cpp Mem.cpp Profile.cpp Profile.h \ -rasterfont.cpp targets.cpp zerogs.cpp ZZoglVB.cpp ZZoglShoots.cpp ZZoglCreate.cpp \ -ZZoglShaders.cpp ZZoglCRTC.cpp ZZoglSave.cpp ZZoglFlush.cpp \ -Mem_Swizzle.h Mem_Tables.cpp Mem_Transmit.h Mem_Swizzle.cpp - - -libzzoglpg_a_SOURCES += x86-32.S - -if SSE2 -CCASFLAGS+= -DZEROGS_SSE2 -endif - -libzzoglpg_a_DEPENDENCIES = Linux/libZeroGSLinux.a ../../../deps/release/libUtilities.a -libzzoglpg_LDADD += Linux/libZeroGSLinux.a ../../../deps/release/libUtilities.a - -SUBDIRS = Linux ZeroGSShaders . diff --git a/plugins/zzogl-pg/opengl/ZZHacks.h b/plugins/zzogl-pg/opengl/ZZHacks.h index 2df9fd098..b4bf03b28 100644 --- a/plugins/zzogl-pg/opengl/ZZHacks.h +++ b/plugins/zzogl-pg/opengl/ZZHacks.h @@ -1,3 +1,22 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + #ifndef ZZHACKS_H_INCLUDED #define ZZHACKS_H_INCLUDED diff --git a/plugins/zzogl-pg/opengl/common.h b/plugins/zzogl-pg/opengl/common.h index 3c87f46b6..5202a6350 100644 --- a/plugins/zzogl-pg/opengl/common.h +++ b/plugins/zzogl-pg/opengl/common.h @@ -1,19 +1,19 @@ /* ZZ Open GL graphics plugin - * Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * Copyright (c)2005-2008 Zerofrog's ZeroGS KOSMOS * - * Based on ffmepeg program, (c)2006 Michael Niedermayer + * Based on the ffmpeg program, (c)2006 Michael Niedermayer * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ diff --git a/plugins/zzogl-pg/opengl/configure.ac b/plugins/zzogl-pg/opengl/configure.ac deleted file mode 100644 index 8d77c714f..000000000 --- a/plugins/zzogl-pg/opengl/configure.ac +++ /dev/null @@ -1,123 +0,0 @@ -AC_INIT(ZZOgl-pg,0.1.0,arcum42@gmail.com) - -AM_INIT_AUTOMAKE(ZZOgl-pg,0.1.0) - -AC_PROG_CC([gcc g++ cl KCC CC cxx cc++ xlC aCC c++]) -AC_PROG_CXX([gcc g++ cl KCC CC cxx cc++ xlC aCC c++]) -AC_PROG_CPP([gcc g++ cl KCC CC cxx cc++ xlC aCC c++]) -AM_PROG_CC_C_O - -AC_PROG_INSTALL -AC_PROG_RANLIB - -dnl necessary for compiling assembly -AM_PROG_AS - -ZEROGS_CURRENT=0 -ZEROGS_REVISION=1 -ZEROGS_AGE=0 -ZEROGS_SONAME=libzzoglpg.so.[$ZEROGS_CURRENT].[$ZEROGS_REVISION].[$ZEROGS_AGE] -ZEROGS_RELEASE=[$ZEROGS_CURRENT].[$ZEROGS_REVISION].[$ZEROGS_AGE] - -AC_SUBST(ZEROGS_CURRENT) -AC_SUBST(ZEROGS_REVISION) -AC_SUBST(ZEROGS_AGE) -AC_SUBST(ZEROGS_RELEASE) -AC_SUBST(ZEROGS_SONAME) - -CFLAGS=" -I/opt/cg/include -L/opt/cg/lib -Wall -Wno-format -Wno-unused " -CPPFLAGS=" -I/opt/cg/include -L/opt/cg/lib -Wall -Wno-format -Wno-unused " -CXXFLAGS=" -I/opt/cg/include -L/opt/cg/lib -Wall -Wno-format -Wno-unused " - -dnl Check for debug build -AC_MSG_CHECKING(debug build) -AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], [debug build]), - debug=$enableval,debug=no) -if test "x$debug" == xyes -then - AC_DEFINE(_DEBUG,1,[_DEBUG]) - CFLAGS+="-g " - CPPFLAGS+="-g " - CXXFLAGS+="-g -fpermissive " -else - AC_DEFINE(NDEBUG,1,[NDEBUG]) - CFLAGS+="-O2 -msse2 " - CPPFLAGS+="-O2 -msse2 " - CXXFLAGS+="-O2 -msse2 -fno-regmove " -fi -AC_MSG_RESULT($debug) - -AC_CHECK_FUNCS([ _aligned_malloc _aligned_free ], AC_DEFINE(HAVE_ALIGNED_MALLOC)) - -dnl Check for dev build -AC_MSG_CHECKING(for development build...) -AC_ARG_ENABLE(devbuild, AC_HELP_STRING([--enable-devbuild], [Special Build for developers that simplifies testing and adds extra checks]), - devbuild=$enableval,devbuild=no) -if test "x$devbuild" == xno -then - AC_DEFINE(RELEASE_TO_PUBLIC,1,[RELEASE_TO_PUBLIC]) -fi -AC_MSG_RESULT($devbuild) -AM_CONDITIONAL(RELEASE_TO_PUBLIC, test x$devbuild = xno) - -dnl Check for recompilation -AC_MSG_CHECKING(check for sse2...) -AC_ARG_ENABLE(sse2, AC_HELP_STRING([--enable-sse2], [Enable sse2 instructions]), - sse2=$enableval,sse2=no) -if test "x$sse2" == xyes -then - AC_DEFINE(ZEROGS_SSE2,1,[ZEROGS_SSE2]) -fi -AC_MSG_RESULT($sse2) -AM_CONDITIONAL(SSE2, test x$sse2 = xyes) - -dnl gtk -AC_MSG_CHECKING(gtk2+) -AC_CHECK_PROG(GTK_CONFIG, pkg-config, pkg-config) -LIBS+=$(pkg-config --libs gtk+-2.0) - -dnl bindir = pcsx2exe - -dnl assuming linux environment -so_ext=".so.$ZEROGS_RELEASE" -SHARED_LDFLAGS="-shared" -AC_SUBST(so_ext) -AC_SUBST(SHARED_LDFLAGS) - -AC_MSG_CHECKING(OpenGL) -AC_CHECK_HEADERS([GL/gl.h GL/glu.h GL/glext.h],,, - [[#if HAVE_GL_GL_H - #include - #endif - #if HAVE_GL_GLU_H - #include - #endif - ]]) -AC_CHECK_LIB(GL,main,[LIBS="$LIBS -lGL"]) -AC_CHECK_LIB(GLU,main,[LIBS="$LIBS -lGLU"]) -AC_CHECK_LIB(GLEW,main,[LIBS="$LIBS -lGLEW"]) -AC_MSG_CHECKING(Cg) -AC_CHECK_HEADERS([Cg/cg.h Cg/cgGL.h]) -AC_CHECK_LIB(jpeg,main,[LIBS="$LIBS -ljpeg"]) -AC_CHECK_HEADERS([jpeglib.h],,[AC_MSG_ERROR(Install libjpeg-dev)]) -AC_CHECK_LIB(pthread,main,[LIBS="$LIBS -lpthread"]) -AC_CHECK_LIB(stdc++,main,[LIBS="$LIBS -lstdc++"]) -AC_CHECK_LIB(z,main,[LIBS="$LIBS -lz"]) -AC_CHECK_LIB(dl,main,[LIBS="$LIBS -ldl"]) -AC_CHECK_LIB(Xxf86vm,main,[LIBS="$LIBS -lXxf86vm"],[echo "Error! You need to have libXxf86vm-dev." ; exit -1]) - -dnl AC_CHECK_LIB(Cg,cgCreateContext,[LIBS="$LIBS -lCg"]) -dnl AC_CHECK_LIB(CgGL,cgGLEnableProfile,[LIBS="$LIBS -lCgGL"]) -LIBS+=" -lCg -lCgGL" - -AC_OUTPUT([ - Makefile - Linux/Makefile - ZeroGSShaders/Makefile - ]) - -echo "Configuration:" -echo " Target system type: $target" -echo " Debug build? $debug" -echo " Dev build? $devbuild" -echo " SSE2 enabled? $sse2" diff --git a/plugins/zzogl-pg/opengl/depcomp b/plugins/zzogl-pg/opengl/depcomp deleted file mode 120000 index b0ad20c05..000000000 --- a/plugins/zzogl-pg/opengl/depcomp +++ /dev/null @@ -1 +0,0 @@ -/usr/share/automake-1.11/depcomp \ No newline at end of file diff --git a/plugins/zzogl-pg/opengl/install-sh b/plugins/zzogl-pg/opengl/install-sh deleted file mode 100644 index 4d4a9519e..000000000 --- a/plugins/zzogl-pg/opengl/install-sh +++ /dev/null @@ -1,323 +0,0 @@ -#!/bin/sh -# install - install a program, script, or datafile - -scriptversion=2005-05-14.22 - -# This originates from X11R5 (mit/util/scripts/install.sh), which was -# later released in X11R6 (xc/config/util/install.sh) with the -# following copyright and license. -# -# Copyright (C) 1994 X Consortium -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- -# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -# Except as contained in this notice, the name of the X Consortium shall not -# be used in advertising or otherwise to promote the sale, use or other deal- -# ings in this Software without prior written authorization from the X Consor- -# tium. -# -# -# FSF changes to this file are in the public domain. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# `make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. It can only install one file at a time, a restriction -# shared with many OS's install programs. - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit="${DOITPROG-}" - -# put in absolute paths if you don't have them in your path; or use env. vars. - -mvprog="${MVPROG-mv}" -cpprog="${CPPROG-cp}" -chmodprog="${CHMODPROG-chmod}" -chownprog="${CHOWNPROG-chown}" -chgrpprog="${CHGRPPROG-chgrp}" -stripprog="${STRIPPROG-strip}" -rmprog="${RMPROG-rm}" -mkdirprog="${MKDIRPROG-mkdir}" - -chmodcmd="$chmodprog 0755" -chowncmd= -chgrpcmd= -stripcmd= -rmcmd="$rmprog -f" -mvcmd="$mvprog" -src= -dst= -dir_arg= -dstarg= -no_target_directory= - -usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE - or: $0 [OPTION]... SRCFILES... DIRECTORY - or: $0 [OPTION]... -t DIRECTORY SRCFILES... - or: $0 [OPTION]... -d DIRECTORIES... - -In the 1st form, copy SRCFILE to DSTFILE. -In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. -In the 4th, create DIRECTORIES. - -Options: --c (ignored) --d create directories instead of installing files. --g GROUP $chgrpprog installed files to GROUP. --m MODE $chmodprog installed files to MODE. --o USER $chownprog installed files to USER. --s $stripprog installed files. --t DIRECTORY install into DIRECTORY. --T report an error if DSTFILE is a directory. ---help display this help and exit. ---version display version info and exit. - -Environment variables override the default commands: - CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG -" - -while test -n "$1"; do - case $1 in - -c) shift - continue;; - - -d) dir_arg=true - shift - continue;; - - -g) chgrpcmd="$chgrpprog $2" - shift - shift - continue;; - - --help) echo "$usage"; exit $?;; - - -m) chmodcmd="$chmodprog $2" - shift - shift - continue;; - - -o) chowncmd="$chownprog $2" - shift - shift - continue;; - - -s) stripcmd=$stripprog - shift - continue;; - - -t) dstarg=$2 - shift - shift - continue;; - - -T) no_target_directory=true - shift - continue;; - - --version) echo "$0 $scriptversion"; exit $?;; - - *) # When -d is used, all remaining arguments are directories to create. - # When -t is used, the destination is already specified. - test -n "$dir_arg$dstarg" && break - # Otherwise, the last argument is the destination. Remove it from $@. - for arg - do - if test -n "$dstarg"; then - # $@ is not empty: it contains at least $arg. - set fnord "$@" "$dstarg" - shift # fnord - fi - shift # arg - dstarg=$arg - done - break;; - esac -done - -if test -z "$1"; then - if test -z "$dir_arg"; then - echo "$0: no input file specified." >&2 - exit 1 - fi - # It's OK to call `install-sh -d' without argument. - # This can happen when creating conditional directories. - exit 0 -fi - -for src -do - # Protect names starting with `-'. - case $src in - -*) src=./$src ;; - esac - - if test -n "$dir_arg"; then - dst=$src - src= - - if test -d "$dst"; then - mkdircmd=: - chmodcmd= - else - mkdircmd=$mkdirprog - fi - else - # Waiting for this to be detected by the "$cpprog $src $dsttmp" command - # might cause directories to be created, which would be especially bad - # if $src (and thus $dsttmp) contains '*'. - if test ! -f "$src" && test ! -d "$src"; then - echo "$0: $src does not exist." >&2 - exit 1 - fi - - if test -z "$dstarg"; then - echo "$0: no destination specified." >&2 - exit 1 - fi - - dst=$dstarg - # Protect names starting with `-'. - case $dst in - -*) dst=./$dst ;; - esac - - # If destination is a directory, append the input filename; won't work - # if double slashes aren't ignored. - if test -d "$dst"; then - if test -n "$no_target_directory"; then - echo "$0: $dstarg: Is a directory" >&2 - exit 1 - fi - dst=$dst/`basename "$src"` - fi - fi - - # This sed command emulates the dirname command. - dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` - - # Make sure that the destination directory exists. - - # Skip lots of stat calls in the usual case. - if test ! -d "$dstdir"; then - defaultIFS=' - ' - IFS="${IFS-$defaultIFS}" - - oIFS=$IFS - # Some sh's can't handle IFS=/ for some reason. - IFS='%' - set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` - shift - IFS=$oIFS - - pathcomp= - - while test $# -ne 0 ; do - pathcomp=$pathcomp$1 - shift - if test ! -d "$pathcomp"; then - $mkdirprog "$pathcomp" - # mkdir can fail with a `File exist' error in case several - # install-sh are creating the directory concurrently. This - # is OK. - test -d "$pathcomp" || exit - fi - pathcomp=$pathcomp/ - done - fi - - if test -n "$dir_arg"; then - $doit $mkdircmd "$dst" \ - && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ - && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ - && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ - && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } - - else - dstfile=`basename "$dst"` - - # Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/_inst.$$_ - rmtmp=$dstdir/_rm.$$_ - - # Trap to clean up those temp files at exit. - trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 - trap '(exit $?); exit' 1 2 13 15 - - # Copy the file name to the temp name. - $doit $cpprog "$src" "$dsttmp" && - - # and set any options; do chmod last to preserve setuid bits. - # - # If any of these fail, we abort the whole thing. If we want to - # ignore errors from any of these, just make sure not to ignore - # errors from the above "$doit $cpprog $src $dsttmp" command. - # - { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ - && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ - && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ - && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && - - # Now rename the file to the real destination. - { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ - || { - # The rename failed, perhaps because mv can't rename something else - # to itself, or perhaps because mv is so ancient that it does not - # support -f. - - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - if test -f "$dstdir/$dstfile"; then - $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ - || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ - || { - echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 - (exit 1); exit 1 - } - else - : - fi - } && - - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" - } - } - fi || { (exit 1); exit 1; } -done - -# The final little trick to "correctly" pass the exit status to the exit trap. -{ - (exit 0); exit 0 -} - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" -# End: diff --git a/plugins/zzogl-pg/opengl/linux_replay.cpp b/plugins/zzogl-pg/opengl/linux_replay.cpp index f95b19b0a..28ca68808 100644 --- a/plugins/zzogl-pg/opengl/linux_replay.cpp +++ b/plugins/zzogl-pg/opengl/linux_replay.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 20011-2012 Hainaut gregory + * Copyright (C) 2011-2012 Hainaut gregory * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/plugins/zzogl-pg/opengl/missing b/plugins/zzogl-pg/opengl/missing deleted file mode 120000 index 20bc5b0ed..000000000 --- a/plugins/zzogl-pg/opengl/missing +++ /dev/null @@ -1 +0,0 @@ -/usr/share/automake-1.11/missing \ No newline at end of file diff --git a/plugins/zzogl-pg/opengl/shaders.sh b/plugins/zzogl-pg/opengl/shaders.sh index 7b6a8d179..7c5e57b04 100755 --- a/plugins/zzogl-pg/opengl/shaders.sh +++ b/plugins/zzogl-pg/opengl/shaders.sh @@ -1,3 +1,18 @@ #!/bin/sh + +# PCSX2 - PS2 Emulator for PCs +# Copyright (C) 2002-2011 PCSX2 Dev Team +# +# PCSX2 is free software: you can redistribute it and/or modify it under the terms +# of the GNU Lesser General Public License as published by the Free Software Found- +# ation, either version 3 of the License, or (at your option) any later version. +# +# PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with PCSX2. +# If not, see . + ./zgsbuild ps2hw.fx cp ps2hw.dat ../../../bin/plugins/ diff --git a/tools/bin2app.sh b/tools/bin2app.sh index 6c1c0a20c..64461ad9a 100755 --- a/tools/bin2app.sh +++ b/tools/bin2app.sh @@ -1,5 +1,19 @@ #!/bin/sh +# PCSX2 - PS2 Emulator for PCs +# Copyright (C) 2002-2011 PCSX2 Dev Team +# +# PCSX2 is free software: you can redistribute it and/or modify it under the terms +# of the GNU Lesser General Public License as published by the Free Software Found- +# ation, either version 3 of the License, or (at your option) any later version. +# +# PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with PCSX2. +# If not, see . + # Probably self-explanatory: This batch file compiles a single souce image into a # CPP header file for use by pcsx2. # From 5627b4dfaf84e422645378dc51cb875398e892a1 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Thu, 12 Apr 2012 17:52:43 +0000 Subject: [PATCH 60/83] copyright: * change the man page to gpl3 * add missing copyrigh for zerogsshader * re write bin2cpp tool (in perl) to avoid any copyright issue => hex2h.pl git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5155 96395faa-99c1-11dd-bbfe-3dabce05a288 --- CMakeLists.txt | 3 - bin/docs/pcsx2.man | 19 +++- linux_various/hex2h.pl | 97 +++++++++++++++++++ pcsx2/CMakeLists.txt | 4 +- .../zzogl-pg/opengl/ZeroGSShaders/Makefile.am | 3 - .../opengl/ZeroGSShaders/zerogsshaders.cpp | 24 +++-- .../opengl/ZeroGSShaders/zerogsshaders.h | 24 +++-- plugins/zzogl-pg/opengl/compile | 1 - plugins/zzogl-pg/opengl/ps2hw.fx | 18 ++++ 9 files changed, 169 insertions(+), 24 deletions(-) create mode 100644 linux_various/hex2h.pl delete mode 100644 plugins/zzogl-pg/opengl/ZeroGSShaders/Makefile.am delete mode 120000 plugins/zzogl-pg/opengl/compile diff --git a/CMakeLists.txt b/CMakeLists.txt index ae57e9c94..8b2a3ecd2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,9 +79,6 @@ if(common_libs) add_subdirectory(common/src/x86emitter) endif(common_libs) -# make tools -add_subdirectory(tools) - # make pcsx2 if(EXISTS "${PROJECT_SOURCE_DIR}/pcsx2" AND pcsx2_core) add_subdirectory(pcsx2) diff --git a/bin/docs/pcsx2.man b/bin/docs/pcsx2.man index 3e4c2bf3a..6cdc1102d 100644 --- a/bin/docs/pcsx2.man +++ b/bin/docs/pcsx2.man @@ -125,4 +125,21 @@ http://forums.pcsx2.net .SH "COPYRIGHT NOTICE" Copyright \(co 2002-2010 PCSX2 Dev Team -Permission is granted to copy and distribute this manual under the terms of the GNU Free Documentation License. +This is free documentation; you can redistribute it and/or +modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 3 of +the License, or (at your option) any later version. + +The GNU General Public License's references to "object code" +and "executables" are to be interpreted as the output of any +document formatting or typesetting system, including +intermediate and printed output. + +This manual is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public +License along with this manual; if not, see +. diff --git a/linux_various/hex2h.pl b/linux_various/hex2h.pl new file mode 100644 index 000000000..1370d4524 --- /dev/null +++ b/linux_various/hex2h.pl @@ -0,0 +1,97 @@ +#!/usr/bin/perl + +# PCSX2 - PS2 Emulator for PCs +# Copyright (C) 2002-2011 PCSX2 Dev Team +# +# PCSX2 is free software: you can redistribute it and/or modify it under the terms +# of the GNU Lesser General Public License as published by the Free Software Found- +# ation, either version 3 of the License, or (at your option) any later version. +# +# PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with PCSX2. +# If not, see . + +# This basic script convert an jpeg/png image to a .h include file +# compatible with PCSX2 gui + +use File::Basename; +use strict; +use warnings; + +sub ascii_to_hex ($) +{ + (my $str = shift) =~ s/(.|\n)/sprintf("%02lx", ord $1)/eg; + return $str; +} + +sub get_wx_ext ($) +{ + my $ext = shift; + + my $result = "BAD_FORMAT"; + if ($ext =~ /png/i) { + $result = "wxBITMAP_TYPE_PNG"; + } elsif ($ext =~ /jpe?g/i) { + $result = "wxBITMAP_TYPE_JPEG"; + } else { + print "ERROR: bad format $ext\n"; + } + + return $result; +} + +my $input=$ARGV[0]; +my $output=$ARGV[1] . ".h" ; + +my($filename, $directories, $suffix) = fileparse($input); +my ($name, $ext) = split(/\./,$filename); + +my $wx_img_class = "res_$name"; +my $wx_img_extension = get_wx_ext($ext); +my $filesize = -s $input; + +### Collect binary data +my $lenght = 1; +my $binary = "\t\t"; +my $data; +my $byte; + +open(IN,"$input"); +binmode IN; +while (($byte = read IN, $data, 1) != 0) { + my $hex = ascii_to_hex($data); + $binary .= "0x$hex"; + if ($lenght % 17 == 0 && $lenght > 1) { + # End of line + $binary .= ",\n\t\t"; + } elsif ($filesize == $lenght) { + # End of file + $binary .= "\n"; + } else { + $binary .= ","; + } + $lenght++; +} +close(IN); + +open(OUT,">$output"); +### Print the header +print OUT "#pragma once\n\n"; +print OUT "#include \"Pcsx2Types.h\"\n"; +print OUT "#include \n\n"; +print OUT "class $wx_img_class\n{\n"; +print OUT "public:\n"; +print OUT "\tstatic const uint Length = $filesize;\n"; +print OUT "\tstatic const u8 Data[Length];\n"; +print OUT "\tstatic wxBitmapType GetFormat() { return $wx_img_extension; }\n};\n\n"; +print OUT "const u8 ${wx_img_class}::Data[Length] =\n{\n"; + +### Print the array +print OUT $binary; +print OUT "};\n"; + +close(OUT); + diff --git a/pcsx2/CMakeLists.txt b/pcsx2/CMakeLists.txt index 9bef3c82d..3a76434bc 100644 --- a/pcsx2/CMakeLists.txt +++ b/pcsx2/CMakeLists.txt @@ -654,13 +654,13 @@ add_executable(${Output} ### Generate the resources files file(MAKE_DIRECTORY ${res_bin}) -add_custom_command(OUTPUT "${res_bin}/Dualshock.h" COMMAND bin2cpp "${res_src}/Dualshock.jpg" "${res_bin}/Dualshock" ) +add_custom_command(OUTPUT "${res_bin}/Dualshock.h" COMMAND "${PROJECT_SOURCE_DIR}/linux_various/hex2h.pl" "${res_src}/Dualshock.jpg" "${res_bin}/Dualshock" ) foreach(res_file IN ITEMS AppIcon16 AppIcon32 AppIcon64 BackgroundLogo ButtonIcon_Camera ConfigIcon_Appearance ConfigIcon_Cpu ConfigIcon_Gamefixes ConfigIcon_MemoryCard ConfigIcon_Paths ConfigIcon_Plugins ConfigIcon_Speedhacks ConfigIcon_Video) - add_custom_command(OUTPUT "${res_bin}/${res_file}.h" COMMAND bin2cpp "${res_src}/${res_file}.png" "${res_bin}/${res_file}" ) + add_custom_command(OUTPUT "${res_bin}/${res_file}.h" COMMAND "${PROJECT_SOURCE_DIR}/linux_various/hex2h.pl" "${res_src}/${res_file}.png" "${res_bin}/${res_file}" ) endforeach(res_file IN ITEMS AppIcon16 AppIcon32 AppIcon64 BackgroundLogo ButtonIcon_Camera ConfigIcon_Appearance ConfigIcon_Cpu ConfigIcon_Gamefixes ConfigIcon_MemoryCard diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/Makefile.am b/plugins/zzogl-pg/opengl/ZeroGSShaders/Makefile.am deleted file mode 100644 index a4025f5ea..000000000 --- a/plugins/zzogl-pg/opengl/ZeroGSShaders/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -INCLUDES = -I@srcdir@/../../../../common/include -I@srcdir@/../common -I@srcdir@/../../../../3rdparty/ -noinst_PROGRAMS = zgsbuild -zgsbuild_SOURCES = zpipe.cpp zerogsshaders.cpp diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/zerogsshaders.cpp b/plugins/zzogl-pg/opengl/ZeroGSShaders/zerogsshaders.cpp index d15ae8570..e9de68639 100644 --- a/plugins/zzogl-pg/opengl/ZeroGSShaders/zerogsshaders.cpp +++ b/plugins/zzogl-pg/opengl/ZeroGSShaders/zerogsshaders.cpp @@ -1,10 +1,20 @@ - /* ZeroGS KOSMOS - * - * Zerofrog's ZeroGS KOSMOS (c)2005-2008 - * - * Zerofrog forgot to write any copyright notice after release the plugin into GPLv2 - * If someone can contact him successfully to clarify this matter that would be great. - */ +/* ZZ Open GL graphics plugin + * Copyright on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ #define _CRT_SECURE_NO_DEPRECATE diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/zerogsshaders.h b/plugins/zzogl-pg/opengl/ZeroGSShaders/zerogsshaders.h index 37784436b..aa9819baf 100644 --- a/plugins/zzogl-pg/opengl/ZeroGSShaders/zerogsshaders.h +++ b/plugins/zzogl-pg/opengl/ZeroGSShaders/zerogsshaders.h @@ -1,10 +1,20 @@ - /* ZeroGS KOSMOS - * - * Zerofrog's ZeroGS KOSMOS (c)2005-2008 - * - * Zerofrog forgot to write any copyright notice after release the plugin into GPLv2 - * If someone can contact him successfully to clarify this matter that would be great. - */ +/* ZZ Open GL graphics plugin + * Copyright on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ #ifndef __ZEROGS_SHADERS_H__ #define __ZEROGS_SHADERS_H__ diff --git a/plugins/zzogl-pg/opengl/compile b/plugins/zzogl-pg/opengl/compile deleted file mode 120000 index cf0edba28..000000000 --- a/plugins/zzogl-pg/opengl/compile +++ /dev/null @@ -1 +0,0 @@ -/usr/share/automake-1.11/compile \ No newline at end of file diff --git a/plugins/zzogl-pg/opengl/ps2hw.fx b/plugins/zzogl-pg/opengl/ps2hw.fx index 43c14ca02..0965c3adc 100644 --- a/plugins/zzogl-pg/opengl/ps2hw.fx +++ b/plugins/zzogl-pg/opengl/ps2hw.fx @@ -1,3 +1,21 @@ +// ZZ Open GL graphics plugin +// Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com +// Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + // Cg Shaders for PS2 GS emulation // divides by z for every pixel, instead of in vertex shader From 0f60fc2ffc2bd85424e6fc8d550f81bf359e3097 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Thu, 12 Apr 2012 19:09:25 +0000 Subject: [PATCH 61/83] cmake: svn remove my executable permission so directly call perl interpreter git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5156 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pcsx2/CMakeLists.txt b/pcsx2/CMakeLists.txt index 3a76434bc..98f3ef4e2 100644 --- a/pcsx2/CMakeLists.txt +++ b/pcsx2/CMakeLists.txt @@ -654,13 +654,13 @@ add_executable(${Output} ### Generate the resources files file(MAKE_DIRECTORY ${res_bin}) -add_custom_command(OUTPUT "${res_bin}/Dualshock.h" COMMAND "${PROJECT_SOURCE_DIR}/linux_various/hex2h.pl" "${res_src}/Dualshock.jpg" "${res_bin}/Dualshock" ) +add_custom_command(OUTPUT "${res_bin}/Dualshock.h" COMMAND perl ${PROJECT_SOURCE_DIR}/linux_various/hex2h.pl "${res_src}/Dualshock.jpg" "${res_bin}/Dualshock" ) foreach(res_file IN ITEMS AppIcon16 AppIcon32 AppIcon64 BackgroundLogo ButtonIcon_Camera ConfigIcon_Appearance ConfigIcon_Cpu ConfigIcon_Gamefixes ConfigIcon_MemoryCard ConfigIcon_Paths ConfigIcon_Plugins ConfigIcon_Speedhacks ConfigIcon_Video) - add_custom_command(OUTPUT "${res_bin}/${res_file}.h" COMMAND "${PROJECT_SOURCE_DIR}/linux_various/hex2h.pl" "${res_src}/${res_file}.png" "${res_bin}/${res_file}" ) + add_custom_command(OUTPUT "${res_bin}/${res_file}.h" COMMAND perl ${PROJECT_SOURCE_DIR}/linux_various/hex2h.pl "${res_src}/${res_file}.png" "${res_bin}/${res_file}" ) endforeach(res_file IN ITEMS AppIcon16 AppIcon32 AppIcon64 BackgroundLogo ButtonIcon_Camera ConfigIcon_Appearance ConfigIcon_Cpu ConfigIcon_Gamefixes ConfigIcon_MemoryCard From d75da041f63bab8fb5604319fc5504cb0f8c2c02 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Mon, 16 Apr 2012 15:36:16 +0000 Subject: [PATCH 62/83] copyright: soundtouch was LGPL2.1 not LGPL2.1+, add an header to launch_pcsx2_linux.sh cmake: keep all library for the linking of plugins hex2h.pl: add svn:executable git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5157 96395faa-99c1-11dd-bbfe-3dabce05a288 --- bin/launch_pcsx2_linux.sh | 14 ++++++++++++++ linux_various/hex2h.pl | 0 plugins/CDVDnull/CMakeLists.txt | 5 +++++ plugins/FWnull/CMakeLists.txt | 5 +++++ plugins/GSdx/CMakeLists.txt | 5 +++++ plugins/GSnull/CMakeLists.txt | 8 ++++++++ plugins/PadNull/CMakeLists.txt | 8 ++++++++ plugins/SPU2null/CMakeLists.txt | 5 +++++ plugins/USBnull/CMakeLists.txt | 5 +++++ plugins/dev9null/CMakeLists.txt | 5 +++++ plugins/onepad/CMakeLists.txt | 8 ++++++++ plugins/spu2-x/src/CMakeLists.txt | 5 +++++ plugins/spu2-x/src/WavFile.cpp | 13 +++++++------ plugins/spu2-x/src/WavFile.h | 13 +++++++------ plugins/zzogl-pg/opengl/CMakeLists.txt | 8 ++++++++ 15 files changed, 95 insertions(+), 12 deletions(-) mode change 100644 => 100755 linux_various/hex2h.pl diff --git a/bin/launch_pcsx2_linux.sh b/bin/launch_pcsx2_linux.sh index f46f3cc1b..afdd7a516 100755 --- a/bin/launch_pcsx2_linux.sh +++ b/bin/launch_pcsx2_linux.sh @@ -1,5 +1,19 @@ #!/bin/sh -e +# PCSX2 - PS2 Emulator for PCs +# Copyright (C) 2002-2011 PCSX2 Dev Team +# +# PCSX2 is free software: you can redistribute it and/or modify it under the terms +# of the GNU Lesser General Public License as published by the Free Software Found- +# ation, either version 3 of the License, or (at your option) any later version. +# +# PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with PCSX2. +# If not, see . + # This script is a small wrapper to the PCSX2 exectuable. The purpose is to # launch PCSX2 from the same repository every times. # Rationale: There is no guarantee on the directory when PCSX2 is launched from a shortcut. diff --git a/linux_various/hex2h.pl b/linux_various/hex2h.pl old mode 100644 new mode 100755 diff --git a/plugins/CDVDnull/CMakeLists.txt b/plugins/CDVDnull/CMakeLists.txt index 10d245b5a..27a72d14f 100644 --- a/plugins/CDVDnull/CMakeLists.txt +++ b/plugins/CDVDnull/CMakeLists.txt @@ -63,6 +63,11 @@ add_library(${Output} SHARED ${CDVDnullHeaders} ) +if(Linux) + # link target with gtk2 + target_link_libraries(${Output} ${GTK2_LIBRARIES}) +endif(Linux) + # User flags options if(NOT USER_CMAKE_LD_FLAGS STREQUAL "") target_link_libraries(${Output} "${USER_CMAKE_LD_FLAGS}") diff --git a/plugins/FWnull/CMakeLists.txt b/plugins/FWnull/CMakeLists.txt index 4e3c93d11..0d8a7ba36 100644 --- a/plugins/FWnull/CMakeLists.txt +++ b/plugins/FWnull/CMakeLists.txt @@ -75,6 +75,11 @@ add_library(${Output} SHARED ${FWnullLinuxSources} ${FWnullLinuxHeaders}) +if(Linux) + # link target with gtk2 + target_link_libraries(${Output} ${GTK2_LIBRARIES}) +endif(Linux) + # User flags options if(NOT USER_CMAKE_LD_FLAGS STREQUAL "") target_link_libraries(${Output} "${USER_CMAKE_LD_FLAGS}") diff --git a/plugins/GSdx/CMakeLists.txt b/plugins/GSdx/CMakeLists.txt index 91dfee01e..6071e3056 100644 --- a/plugins/GSdx/CMakeLists.txt +++ b/plugins/GSdx/CMakeLists.txt @@ -176,6 +176,11 @@ target_link_libraries(${Output} ${X11_LIBRARIES}) # link target with SDL target_link_libraries(${Output} ${SDL_LIBRARY}) +if(Linux) + # link target with gtk2 + target_link_libraries(${Output} ${GTK2_LIBRARIES}) +endif(Linux) + # User flags options if(NOT USER_CMAKE_LD_FLAGS STREQUAL "") target_link_libraries(${Output} "${USER_CMAKE_LD_FLAGS}") diff --git a/plugins/GSnull/CMakeLists.txt b/plugins/GSnull/CMakeLists.txt index 3ca4b35ff..15bfa9a87 100644 --- a/plugins/GSnull/CMakeLists.txt +++ b/plugins/GSnull/CMakeLists.txt @@ -94,6 +94,14 @@ add_library(${Output} SHARED ${GSnullLinuxSources} ${GSnullLinuxHeaders}) +if(Linux) + # link target with gtk2 + target_link_libraries(${Output} ${GTK2_LIBRARIES}) +endif(Linux) + +# link target with X11 +target_link_libraries(${Output} ${X11_LIBRARIES}) + # User flags options if(NOT USER_CMAKE_LD_FLAGS STREQUAL "") target_link_libraries(${Output} "${USER_CMAKE_LD_FLAGS}") diff --git a/plugins/PadNull/CMakeLists.txt b/plugins/PadNull/CMakeLists.txt index 6c454922a..2cba99fd5 100644 --- a/plugins/PadNull/CMakeLists.txt +++ b/plugins/PadNull/CMakeLists.txt @@ -77,6 +77,14 @@ add_library(${Output} SHARED ${PadNullLinuxSources} ${PadNullLinuxHeaders}) +if(Linux) + # link target with gtk2 + target_link_libraries(${Output} ${GTK2_LIBRARIES}) +endif(Linux) + +# link target with X11 +target_link_libraries(${Output} ${X11_LIBRARIES}) + # User flags options if(NOT USER_CMAKE_LD_FLAGS STREQUAL "") target_link_libraries(${Output} "${USER_CMAKE_LD_FLAGS}") diff --git a/plugins/SPU2null/CMakeLists.txt b/plugins/SPU2null/CMakeLists.txt index 8c1c1eb6e..08271ef5f 100644 --- a/plugins/SPU2null/CMakeLists.txt +++ b/plugins/SPU2null/CMakeLists.txt @@ -74,6 +74,11 @@ add_library(${Output} SHARED ${SPU2nullLinuxSources} ${SPU2nullLinuxHeaders}) +if(Linux) + # link target with gtk2 + target_link_libraries(${Output} ${GTK2_LIBRARIES}) +endif(Linux) + # User flags options if(NOT USER_CMAKE_LD_FLAGS STREQUAL "") target_link_libraries(${Output} "${USER_CMAKE_LD_FLAGS}") diff --git a/plugins/USBnull/CMakeLists.txt b/plugins/USBnull/CMakeLists.txt index cec09e425..55cfa8aef 100644 --- a/plugins/USBnull/CMakeLists.txt +++ b/plugins/USBnull/CMakeLists.txt @@ -76,6 +76,11 @@ add_library(${Output} SHARED ${USBnullLinuxSources} ${USBnullLinuxHeaders}) +if(Linux) + # link target with gtk2 + target_link_libraries(${Output} ${GTK2_LIBRARIES}) +endif(Linux) + # User flags options if(NOT USER_CMAKE_LD_FLAGS STREQUAL "") target_link_libraries(${Output} "${USER_CMAKE_LD_FLAGS}") diff --git a/plugins/dev9null/CMakeLists.txt b/plugins/dev9null/CMakeLists.txt index e21929d0f..3d53e8121 100644 --- a/plugins/dev9null/CMakeLists.txt +++ b/plugins/dev9null/CMakeLists.txt @@ -73,6 +73,11 @@ add_library(${Output} SHARED ${dev9nullLinuxSources} ${dev9nullLinuxHeaders}) +if(Linux) + # link target with gtk2 + target_link_libraries(${Output} ${GTK2_LIBRARIES}) +endif(Linux) + # User flags options if(NOT USER_CMAKE_LD_FLAGS STREQUAL "") target_link_libraries(${Output} "${USER_CMAKE_LD_FLAGS}") diff --git a/plugins/onepad/CMakeLists.txt b/plugins/onepad/CMakeLists.txt index 12247e384..4f24cb52c 100644 --- a/plugins/onepad/CMakeLists.txt +++ b/plugins/onepad/CMakeLists.txt @@ -85,6 +85,14 @@ add_library(${Output} SHARED # link target with SDL target_link_libraries(${Output} ${SDL_LIBRARY}) +if(Linux) + # link target with gtk2 + target_link_libraries(${Output} ${GTK2_LIBRARIES}) +endif(Linux) + +# link target with X11 +target_link_libraries(${Output} ${X11_LIBRARIES}) + # User flags options if(NOT USER_CMAKE_LD_FLAGS STREQUAL "") target_link_libraries(${Output} "${USER_CMAKE_LD_FLAGS}") diff --git a/plugins/spu2-x/src/CMakeLists.txt b/plugins/spu2-x/src/CMakeLists.txt index 8395a9a88..9d523e6b6 100644 --- a/plugins/spu2-x/src/CMakeLists.txt +++ b/plugins/spu2-x/src/CMakeLists.txt @@ -121,6 +121,11 @@ target_link_libraries(${Output} ${PORTAUDIO_LIBRARIES}) # link target with SoundTouch target_link_libraries(${Output} ${SOUNDTOUCH_LIBRARIES}) +if(Linux) + # link target with gtk2 + target_link_libraries(${Output} ${GTK2_LIBRARIES}) +endif(Linux) + # User flags options if(NOT USER_CMAKE_LD_FLAGS STREQUAL "") target_link_libraries(${Output} "${USER_CMAKE_LD_FLAGS}") diff --git a/plugins/spu2-x/src/WavFile.cpp b/plugins/spu2-x/src/WavFile.cpp index dc0953ace..f25abccc1 100644 --- a/plugins/spu2-x/src/WavFile.cpp +++ b/plugins/spu2-x/src/WavFile.cpp @@ -4,13 +4,14 @@ * The file is based on WavFile.h from SoundTouch library. * Original portions are (c) 2009 by Olli Parviainen (oparviai 'at' iki.fi) * - * SPU2-X is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License, version 2.1 + * as published by the Free Software Foundation. * - * SPU2-X is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU Lesser General Public License for more details. + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with SPU2-X. If not, see . diff --git a/plugins/spu2-x/src/WavFile.h b/plugins/spu2-x/src/WavFile.h index 2e07f97ed..d65ddb604 100644 --- a/plugins/spu2-x/src/WavFile.h +++ b/plugins/spu2-x/src/WavFile.h @@ -4,13 +4,14 @@ * The file is based on WavFile.h from SoundTouch library. * Original portions are (c) 2009 by Olli Parviainen (oparviai 'at' iki.fi) * - * SPU2-X is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License, version 2.1 + * as published by the Free Software Foundation. * - * SPU2-X is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU Lesser General Public License for more details. + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with SPU2-X. If not, see . diff --git a/plugins/zzogl-pg/opengl/CMakeLists.txt b/plugins/zzogl-pg/opengl/CMakeLists.txt index ed70bb269..8f19622ef 100644 --- a/plugins/zzogl-pg/opengl/CMakeLists.txt +++ b/plugins/zzogl-pg/opengl/CMakeLists.txt @@ -164,6 +164,14 @@ target_link_libraries(${Output} ${X11_LIBRARIES}) # link target with jpeg target_link_libraries(${Output} ${JPEG_LIBRARIES}) +if(Linux) + # link target with gtk2 + target_link_libraries(${Output} ${GTK2_LIBRARIES}) +endif(Linux) + +# link target with zlib +target_link_libraries(${Output} ${ZLIB_LIBRARIES}) + # User flags options if(NOT USER_CMAKE_LD_FLAGS STREQUAL "") target_link_libraries(${Output} "${USER_CMAKE_LD_FLAGS}") From 05fd151a9e70a2df5d5f4768fb80ad434c798c62 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Tue, 17 Apr 2012 16:09:42 +0000 Subject: [PATCH 63/83] Small fix to mVU. Doesn't seem to help any game though. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5158 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/x86/microVU_Lower.inl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pcsx2/x86/microVU_Lower.inl b/pcsx2/x86/microVU_Lower.inl index 6f337914a..d816b11fa 100644 --- a/pcsx2/x86/microVU_Lower.inl +++ b/pcsx2/x86/microVU_Lower.inl @@ -949,13 +949,14 @@ mVUop(mVU_LQD) { pass1 { mVUanalyzeLQ(mVU, _Ft_, _Is_, 1); } pass2 { xAddressVoid ptr(mVU.regs().Mem); - if (_Is_) { + if (_Is_ || isVU0) { // Access VU1 regs mem-map in !_Is_ case mVUallocVIa(mVU, gprT2, _Is_); xSUB(gprT2b, 1); - mVUallocVIb(mVU, gprT2, _Is_); + if (_Is_) mVUallocVIb(mVU, gprT2, _Is_); mVUaddrFix (mVU, gprT2); ptr += gprT2; } + else ptr += (0xffff & (mVU.microMemSize-8)); if (!mVUlow.noWriteVF) { const xmm& Ft = mVU.regAlloc->allocReg(-1, _Ft_, _X_Y_Z_W); mVUloadReg(Ft, ptr, _X_Y_Z_W); @@ -1016,13 +1017,14 @@ mVUop(mVU_SQD) { pass1 { mVUanalyzeSQ(mVU, _Fs_, _It_, 1); } pass2 { xAddressVoid ptr(mVU.regs().Mem); - if (_It_) { + if (_It_ || isVU0) {// Access VU1 regs mem-map in !_It_ case mVUallocVIa(mVU, gprT2, _It_); xSUB(gprT2b, 1); - mVUallocVIb(mVU, gprT2, _It_); + if (_It_) mVUallocVIb(mVU, gprT2, _It_); mVUaddrFix (mVU, gprT2); ptr += gprT2; } + else ptr += (0xffff & (mVU.microMemSize-8)); const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W); mVUsaveReg(Fs, ptr, _X_Y_Z_W, 1); mVU.regAlloc->clearNeeded(Fs); From 5936caa2fead5383594be3d33741339d453670e7 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Tue, 17 Apr 2012 17:06:58 +0000 Subject: [PATCH 64/83] cmake: * build the utility to prebuilt cg shader (zzogl-shader) * build the shader (ps2hw_cmake.dat) that would avoid copyright issue for debian/ubuntu git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5159 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/zzogl-pg/opengl/CMakeLists.txt | 4 + .../opengl/ZeroGSShaders/CMakeLists.txt | 75 +++++++++++++++++++ .../opengl/ZeroGSShaders/zerogsshaders.h | 3 + 3 files changed, 82 insertions(+) create mode 100644 plugins/zzogl-pg/opengl/ZeroGSShaders/CMakeLists.txt diff --git a/plugins/zzogl-pg/opengl/CMakeLists.txt b/plugins/zzogl-pg/opengl/CMakeLists.txt index 8f19622ef..c8bed7a17 100644 --- a/plugins/zzogl-pg/opengl/CMakeLists.txt +++ b/plugins/zzogl-pg/opengl/CMakeLists.txt @@ -5,6 +5,10 @@ if(NOT TOP_CMAKE_WAS_SOURCED) It is advice to delete all wrongly generated cmake stuff => CMakeFiles & CMakeCache.txt") endif(NOT TOP_CMAKE_WAS_SOURCED) +# Allow to build the shader files +if(EXISTS "${PROJECT_SOURCE_DIR}/plugins/zzogl-pg/opengl/ZeroGSShaders") + add_subdirectory(ZeroGSShaders) +endif(EXISTS "${PROJECT_SOURCE_DIR}/plugins/zzogl-pg/opengl/ZeroGSShaders") # plugin name set(Output zzogl-0.3.0) diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/CMakeLists.txt b/plugins/zzogl-pg/opengl/ZeroGSShaders/CMakeLists.txt new file mode 100644 index 000000000..9aa62a3bc --- /dev/null +++ b/plugins/zzogl-pg/opengl/ZeroGSShaders/CMakeLists.txt @@ -0,0 +1,75 @@ +# Check that people use the good file +if(NOT TOP_CMAKE_WAS_SOURCED) + message(FATAL_ERROR " + You did not 'cmake' the good CMakeLists.txt file. Use the one in the top dir. + It is advice to delete all wrongly generated cmake stuff => CMakeFiles & CMakeCache.txt") +endif(NOT TOP_CMAKE_WAS_SOURCED) + + +# plugin name +set(Output zzogl-shader) + +set(CommonFlags + -pthread + -DZEROGS_SSE2 + -fno-strict-aliasing + -Wstrict-aliasing # Allow to track strict aliasing issue. + -Wunused-variable + -DNVIDIA_CG_API + ) + +set(OptimizationFlags + -O2 + -DNDEBUG + ) + +# Debug - Build +if(CMAKE_BUILD_TYPE STREQUAL Debug) + # add defines + add_definitions(${CommonFlags} -g -Wall -D_DEBUG) +endif(CMAKE_BUILD_TYPE STREQUAL Debug) + +# Devel - Build +if(CMAKE_BUILD_TYPE STREQUAL Devel) + # add defines + add_definitions(${CommonFlags} ${OptimizationFlags} -g -W -DZEROGS_DEVBUILD) +endif(CMAKE_BUILD_TYPE STREQUAL Devel) + +# Release - Build +if(CMAKE_BUILD_TYPE STREQUAL Release) + # add defines + add_definitions(${CommonFlags} ${OptimizationFlags} -W) +endif(CMAKE_BUILD_TYPE STREQUAL Release) + +include_directories(.) + +# add library +add_executable(${Output} zerogsshaders.cpp zpipe.cpp) + +# link target with zlib +target_link_libraries(${Output} ${ZLIB_LIBRARIES}) + +# link target with Cg +target_link_libraries(${Output} ${CG_LIBRARIES}) + +# link target with opengl +target_link_libraries(${Output} ${OPENGL_LIBRARIES}) + +# User flags options +if(NOT USER_CMAKE_LD_FLAGS STREQUAL "") + target_link_libraries(${Output} "${USER_CMAKE_LD_FLAGS}") +endif(NOT USER_CMAKE_LD_FLAGS STREQUAL "") + +# Now build the shader +add_custom_command(TARGET ${Output} POST_BUILD + COMMAND ${Output} ps2hw.fx ${CMAKE_CURRENT_BINARY_DIR}/ps2hw_cmake.dat + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/plugins/zzogl-pg/opengl + ) + +if(PACKAGE_MODE) + install(TARGETS ${Output} DESTINATION bin) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ps2hw_cmake.dat DESTINATION ${PLUGIN_DIR}) +else(PACKAGE_MODE) + install(TARGETS ${Output} DESTINATION ${CMAKE_SOURCE_DIR}/bin) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ps2hw_cmake.dat DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins) +endif(PACKAGE_MODE) diff --git a/plugins/zzogl-pg/opengl/ZeroGSShaders/zerogsshaders.h b/plugins/zzogl-pg/opengl/ZeroGSShaders/zerogsshaders.h index aa9819baf..388bd1c7a 100644 --- a/plugins/zzogl-pg/opengl/ZeroGSShaders/zerogsshaders.h +++ b/plugins/zzogl-pg/opengl/ZeroGSShaders/zerogsshaders.h @@ -26,6 +26,9 @@ #include #include +#define ZZshProgram CGprogram +#define ZZshContext CGcontext + using namespace std; #define NUM_FILTERS 2 // texture filtering From 26392e7f3e2110294b179137e0c1d83be1de9a09 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Tue, 17 Apr 2012 17:55:51 +0000 Subject: [PATCH 65/83] Change various logs to sound "nicer". git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5160 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/CDVD/CDVD.cpp | 2 +- pcsx2/Gif_Unit.h | 2 +- pcsx2/PluginManager.cpp | 2 +- pcsx2/gui/Panels/MemoryCardListPanel.cpp | 8 ++++---- pcsx2/gui/SysState.cpp | 6 +++--- pcsx2/x86/microVU_Analyze.inl | 12 ++++++------ plugins/GSdx/GSCrc.cpp | 3 ++- plugins/GSdx/GSState.cpp | 2 +- 8 files changed, 19 insertions(+), 18 deletions(-) diff --git a/pcsx2/CDVD/CDVD.cpp b/pcsx2/CDVD/CDVD.cpp index 3a8ab4892..be4bf99b9 100644 --- a/pcsx2/CDVD/CDVD.cpp +++ b/pcsx2/CDVD/CDVD.cpp @@ -765,7 +765,7 @@ __fi void cdvdActionInterrupt() case cdvdAction_Break: // Make sure the cdvd action state is pretty well cleared: - DevCon.Warning("CDVD Break Call"); + DevCon.WriteLn("CDVD Break Call"); cdvd.Reading = 0; cdvd.Readed = 0; cdvd.Ready = CDVD_READY2; // should be CDVD_READY1 or something else? diff --git a/pcsx2/Gif_Unit.h b/pcsx2/Gif_Unit.h index b86772013..4e4dc1047 100644 --- a/pcsx2/Gif_Unit.h +++ b/pcsx2/Gif_Unit.h @@ -429,7 +429,7 @@ struct Gif_Unit { Gif_Tag gifTag(&pMem[offset & memMask]); incTag(offset, curSize, 16 + gifTag.len); // Tag + Data length if (pathIdx == GIF_PATH_1 && curSize >= 0x4000) { - Console.Warning("Gif Unit - GS packet size exceeded VU memory size!"); + DevCon.Warning("Gif Unit - GS packet size exceeded VU memory size!"); return 0; // Bios does this... (Fixed if you delay vu1's xgkick by 103 vu cycles) } if (curSize >= size) return size; diff --git a/pcsx2/PluginManager.cpp b/pcsx2/PluginManager.cpp index 0fc2cba71..1166fca2c 100644 --- a/pcsx2/PluginManager.cpp +++ b/pcsx2/PluginManager.cpp @@ -967,7 +967,7 @@ void SysCorePlugins::Load( PluginsEnum_t pid, const wxString& srcfile ) { ScopedLock lock( m_mtx_PluginStatus ); pxAssert( (uint)pid < PluginId_Count ); - Console.Indent().WriteLn( L"Binding %s\t: %s ", tbl_PluginInfo[pid].GetShortname().c_str(), srcfile.c_str() ); + Console.Indent().WriteLn( L"Binding %4s: %s ", tbl_PluginInfo[pid].GetShortname().c_str(), srcfile.c_str() ); m_info[pid] = new PluginStatus_t( pid, srcfile ); } diff --git a/pcsx2/gui/Panels/MemoryCardListPanel.cpp b/pcsx2/gui/Panels/MemoryCardListPanel.cpp index 918bedde5..b365fcd8b 100644 --- a/pcsx2/gui/Panels/MemoryCardListPanel.cpp +++ b/pcsx2/gui/Panels/MemoryCardListPanel.cpp @@ -53,7 +53,7 @@ bool EnumerateMemoryCard( McdSlotItem& dest, const wxFileName& filename, const w const wxString fullpath( filename.GetFullPath() ); if( !filename.FileExists() ) return false; - DevCon.WriteLn( fullpath ); + //DevCon.WriteLn( fullpath ); wxFFile mcdFile( fullpath ); if( !mcdFile.IsOpened() ) return false; // wx should log the error for us. if( mcdFile.Length() < (1024*528) ) @@ -1095,10 +1095,10 @@ void Panels::MemoryCardListPanel_Simple::ReadFilesAtMcdFolder(){ currentCardFile.Slot = -1; currentCardFile.IsEnabled = false; m_allFilesystemCards.push_back(currentCardFile); - DevCon.WriteLn(L"Enumerated file: '%s'", currentCardFile.Filename.GetFullName().c_str() ); + //DevCon.WriteLn(L"Enumerated file: '%s'", currentCardFile.Filename.GetFullName().c_str() ); } - else - DevCon.WriteLn(L"MCD folder card file skipped: '%s'", memcardList[i].c_str() ); + /*else + DevCon.WriteLn(L"MCD folder card file skipped: '%s'", memcardList[i].c_str() );*/ } } diff --git a/pcsx2/gui/SysState.cpp b/pcsx2/gui/SysState.cpp index dafa635e7..4e6f137aa 100644 --- a/pcsx2/gui/SysState.cpp +++ b/pcsx2/gui/SysState.cpp @@ -280,14 +280,14 @@ static void CheckVersion( pxInputStream& thr ) if( savever > g_SaveVersion ) throw Exception::SaveStateLoadError( thr.GetStreamName() ) .SetDiagMsg(pxsFmt( L"Savestate uses an unsupported or unknown savestate version.\n(PCSX2 ver=%x, state ver=%x)", g_SaveVersion, savever )) - .SetUserMsg(_("Cannot load this savestate. The state is from an incompatible edition of PCSX2 that is either newer than this version, or is no longer supported.")); + .SetUserMsg(_("Cannot load this savestate. The state is an unsupported version.")); // check for a "minor" version incompatibility; which happens if the savestate being loaded is a newer version // than the emulator recognizes. 99% chance that trying to load it will just corrupt emulation or crash. if( (savever >> 16) != (g_SaveVersion >> 16) ) throw Exception::SaveStateLoadError( thr.GetStreamName() ) - .SetDiagMsg(pxsFmt( L"Savestate uses an unknown (future?!) savestate version.\n(PCSX2 ver=%x, state ver=%x)", g_SaveVersion, savever )) - .SetUserMsg(_("Cannot load this savestate. The state is an unsupported version, likely created by a newer edition of PCSX2.")); + .SetDiagMsg(pxsFmt( L"Savestate uses an unknown savestate version.\n(PCSX2 ver=%x, state ver=%x)", g_SaveVersion, savever )) + .SetUserMsg(_("Cannot load this savestate. The state is an unsupported version.")); }; // -------------------------------------------------------------------------------------- diff --git a/pcsx2/x86/microVU_Analyze.inl b/pcsx2/x86/microVU_Analyze.inl index 51f1e1798..7fd22f544 100644 --- a/pcsx2/x86/microVU_Analyze.inl +++ b/pcsx2/x86/microVU_Analyze.inl @@ -364,7 +364,7 @@ __fi void mVUanalyzeXGkick(mV, int Fs, int xCycles) { static void analyzeBranchVI(mV, int xReg, bool& infoVar) { if (!xReg) return; if (mVUstall) { // I assume a stall on branch means the vi reg is not modified directly b4 the branch... - DevCon.Warning("microVU%d: Warning %d cycle stall on branch instruction [%04x]", getIndex, mVUstall, xPC); + DevCon.Warning("microVU%d: %d cycle stall on branch instruction [%04x]", getIndex, mVUstall, xPC); return; } int i, j = 0; @@ -374,7 +374,7 @@ static void analyzeBranchVI(mV, int xReg, bool& infoVar) { incPC2(-2); for (i = 0; i < iEnd && cyc < iEnd; i++) { if (i && mVUstall) { - DevCon.Warning("microVU%d: Warning Branch VI-Delay with %d cycle stall (%d) [%04x]", getIndex, mVUstall, i, xPC); + DevCon.Warning("microVU%d: Branch VI-Delay with %d cycle stall (%d) [%04x]", getIndex, mVUstall, i, xPC); } if (i == mVUcount) { bool warn = 0; @@ -385,12 +385,12 @@ static void analyzeBranchVI(mV, int xReg, bool& infoVar) { infoVar = 1; j = i; i++; } - if (warn) DevCon.Warning("microVU%d: Warning Branch VI-Delay with small block (%d) [%04x]", getIndex, i, xPC); + if (warn) DevCon.Warning("microVU%d: Branch VI-Delay with small block (%d) [%04x]", getIndex, i, xPC); break; // if (warn), we don't have enough information to always guarantee the correct result. } if ((mVUlow.VI_write.reg == xReg) && mVUlow.VI_write.used) { if (mVUlow.readFlags) { - if (i) DevCon.Warning("microVU%d: Warning Branch VI-Delay with Read Flags Set (%d) [%04x]", getIndex, i, xPC); + if (i) DevCon.Warning("microVU%d: Branch VI-Delay with Read Flags Set (%d) [%04x]", getIndex, i, xPC); break; // Not sure if on the above "if (i)" case, if we need to "continue" or if we should "break" } j = i; @@ -465,14 +465,14 @@ __ri int mVUbranchCheck(mV) { mVUregs.flagInfo = 0; mVUregs.fullFlags0 = 0; mVUregs.fullFlags1 = 0; - DevCon.Warning("microVU%d Warning: %s in %s delay slot! [%04x]", mVU.index, + DevCon.Warning("microVU%d: %s in %s delay slot! [%04x]", mVU.index, branchSTR[mVUlow.branch&0xf], branchSTR[branchType&0xf], xPC); return 1; } else { incPC(2); mVUlow.isNOP = 1; - DevCon.Warning("microVU%d Warning: %s in %s delay slot! [%04x]", mVU.index, + DevCon.Warning("microVU%d: %s in %s delay slot! [%04x]", mVU.index, branchSTR[mVUlow.branch&0xf], branchSTR[branchType&0xf], xPC); return 0; } diff --git a/plugins/GSdx/GSCrc.cpp b/plugins/GSdx/GSCrc.cpp index 002f8be42..5bffeb484 100644 --- a/plugins/GSdx/GSCrc.cpp +++ b/plugins/GSdx/GSCrc.cpp @@ -389,7 +389,8 @@ CRC::Game CRC::Lookup(uint32 crc) if(m_map.empty()) { string exclusions = theApp.GetConfig( "CrcHacksExclusions", "" ); - printf( "GSdx: CrcHacksExclusions: %s\n", exclusions.c_str() ); + if (exclusions.length() != 0) + printf( "GSdx: CrcHacksExclusions: %s\n", exclusions.c_str() ); for(int i = 0; i < countof(m_games); i++) { diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index 9d6490c6b..77c64f49a 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -183,7 +183,7 @@ void GSState::SetFrameSkip(int skip) void GSState::Reset() { - printf("GSdx info: GS reset\n"); + //printf("GSdx info: GS reset\n"); // FIXME: memset(m_mem.m_vm8, 0, m_mem.m_vmsize); // bios logo not shown cut in half after reset, missing graphics in GoW after first FMV memset(&m_path[0], 0, sizeof(m_path[0]) * countof(m_path)); From ea98450eb0ed4c1e7eda76582ffbedefa8ae76af Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Wed, 18 Apr 2012 14:09:18 +0000 Subject: [PATCH 66/83] copyright again: * add some missing copyright header * (l)GPLv* requires to have a full copy of the license. We already have them in various sub-directory but files in source root are easier to find git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5161 96395faa-99c1-11dd-bbfe-3dabce05a288 --- COPYING.GPLv2 | 339 ++++++++++++++++++++++++ COPYING.GPLv3 | 674 +++++++++++++++++++++++++++++++++++++++++++++++ COPYING.LGPLv2.1 | 502 +++++++++++++++++++++++++++++++++++ COPYING.LGPLv3 | 165 ++++++++++++ build.sh | 16 +- rebuild.sh | 16 +- 6 files changed, 1710 insertions(+), 2 deletions(-) create mode 100644 COPYING.GPLv2 create mode 100644 COPYING.GPLv3 create mode 100644 COPYING.LGPLv2.1 create mode 100644 COPYING.LGPLv3 diff --git a/COPYING.GPLv2 b/COPYING.GPLv2 new file mode 100644 index 000000000..d159169d1 --- /dev/null +++ b/COPYING.GPLv2 @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/COPYING.GPLv3 b/COPYING.GPLv3 new file mode 100644 index 000000000..94a9ed024 --- /dev/null +++ b/COPYING.GPLv3 @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/COPYING.LGPLv2.1 b/COPYING.LGPLv2.1 new file mode 100644 index 000000000..4362b4915 --- /dev/null +++ b/COPYING.LGPLv2.1 @@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/COPYING.LGPLv3 b/COPYING.LGPLv3 new file mode 100644 index 000000000..65c5ca88a --- /dev/null +++ b/COPYING.LGPLv3 @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/build.sh b/build.sh index 4d2ab59ad..c6425f099 100755 --- a/build.sh +++ b/build.sh @@ -1,5 +1,19 @@ #!/bin/sh +# PCSX2 - PS2 Emulator for PCs +# Copyright (C) 2002-2011 PCSX2 Dev Team +# +# PCSX2 is free software: you can redistribute it and/or modify it under the terms +# of the GNU Lesser General Public License as published by the Free Software Found- +# ation, either version 3 of the License, or (at your option) any later version. +# +# PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with PCSX2. +# If not, see . + flags="" args="$@" clean_build=false @@ -42,4 +56,4 @@ fi make 2>&1 | tee -a ../install_log.txt make install 2>&1 | tee -a ../install_log.txt -cd .. \ No newline at end of file +cd .. diff --git a/rebuild.sh b/rebuild.sh index d40689e5b..789762615 100755 --- a/rebuild.sh +++ b/rebuild.sh @@ -1,8 +1,22 @@ #!/bin/sh +# PCSX2 - PS2 Emulator for PCs +# Copyright (C) 2002-2011 PCSX2 Dev Team +# +# PCSX2 is free software: you can redistribute it and/or modify it under the terms +# of the GNU Lesser General Public License as published by the Free Software Found- +# ation, either version 3 of the License, or (at your option) any later version. +# +# PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with PCSX2. +# If not, see . + # Run before compiling. Compile by loading up pcsx2/Linux/pcsx2.workspace # with Code::Blocks. cd pcsx2/gui/Resources ./rebuild.sh -cd ../../.. \ No newline at end of file +cd ../../.. From fc5dd5a180c67e0f7e7755085ff722bf080663ee Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Wed, 18 Apr 2012 17:01:24 +0000 Subject: [PATCH 67/83] zzogl: fix Visual studio build. thank Miseru for the patch git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5163 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/zzogl-pg/opengl/Win32/zerogsogl.vcxproj | 4 +++- .../zzogl-pg/opengl/Win32/zerogsogl.vcxproj.filters | 8 +++++++- plugins/zzogl-pg/opengl/Win32/zerogsogl_2008.vcproj | 10 +++++++++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/plugins/zzogl-pg/opengl/Win32/zerogsogl.vcxproj b/plugins/zzogl-pg/opengl/Win32/zerogsogl.vcxproj index 6bc071797..125e31cfe 100644 --- a/plugins/zzogl-pg/opengl/Win32/zerogsogl.vcxproj +++ b/plugins/zzogl-pg/opengl/Win32/zerogsogl.vcxproj @@ -134,6 +134,7 @@ + @@ -187,6 +188,7 @@ + @@ -275,4 +277,4 @@ - \ No newline at end of file + diff --git a/plugins/zzogl-pg/opengl/Win32/zerogsogl.vcxproj.filters b/plugins/zzogl-pg/opengl/Win32/zerogsogl.vcxproj.filters index eff33c914..0a0899e27 100644 --- a/plugins/zzogl-pg/opengl/Win32/zerogsogl.vcxproj.filters +++ b/plugins/zzogl-pg/opengl/Win32/zerogsogl.vcxproj.filters @@ -111,6 +111,9 @@ Source Files + + Source Files + @@ -197,6 +200,9 @@ Header Files + + Header Files + @@ -208,4 +214,4 @@ Source Files - \ No newline at end of file + diff --git a/plugins/zzogl-pg/opengl/Win32/zerogsogl_2008.vcproj b/plugins/zzogl-pg/opengl/Win32/zerogsogl_2008.vcproj index f90d71f5d..4266a05ab 100644 --- a/plugins/zzogl-pg/opengl/Win32/zerogsogl_2008.vcproj +++ b/plugins/zzogl-pg/opengl/Win32/zerogsogl_2008.vcproj @@ -1,7 +1,7 @@ + + @@ -429,6 +433,10 @@ RelativePath="..\GS.h" > + + From 4ef1ee37544539d4f849f86c85a4ed0e3a1cebcc Mon Sep 17 00:00:00 2001 From: avihal Date: Thu, 19 Apr 2012 19:10:24 +0000 Subject: [PATCH 68/83] GSdx: F9 is now switching better between HW and SW renderer. Previously: GSdx was switching between the configured renderer and the best SW renderer (best = DX11 if supported). Now: If using DX: Switch SW/HW renderer and use the same DX version. If using SDL: same as before. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5164 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GS.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/plugins/GSdx/GS.cpp b/plugins/GSdx/GS.cpp index 2eab01093..5c8a60507 100644 --- a/plugins/GSdx/GS.cpp +++ b/plugins/GSdx/GS.cpp @@ -334,8 +334,17 @@ EXPORT_C_(int) GSopen2(void** dsp, uint32 flags) { #ifdef _WINDOWS D3D_FEATURE_LEVEL level; + int best_sw_renderer = GSUtil::CheckDirect3D11Level(level) && level >= D3D_FEATURE_LEVEL_10_0 ? 4 : 1; // dx11 / dx9 sw + + switch(renderer){ + // Use alternative renderer (SW if currently using HW renderer, and vice versa, keeping the same DX level) + case 1: renderer = 0; break; // DX9: SW to HW + case 0: renderer = 1; break; // DX9: HW to SW + case 4: renderer = 3; break; // DX11: SW to HW + case 3: renderer = 4; break; // DX11: HW to SW + default: renderer = best_sw_renderer; // If wasn't using DX (e.g. SDL), use best SW renderer. + } - renderer = GSUtil::CheckDirect3D11Level(level) && level >= D3D_FEATURE_LEVEL_10_0 ? 4 : 1; // dx11 / dx9 sw #endif } From 8fcadb3616d8e2977363d9865e8db2e247bafd56 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Thu, 19 Apr 2012 19:38:29 +0000 Subject: [PATCH 69/83] zzogl: duplicate zzogl. The idea is to merge the dev branch to allow building/testing the 2 in concurency Then it would be easier to separate CG/GLSL for copyright issue. CG is not compatible with the GPL... Old version will be zzogl-pg-cg Future version will be zzogl-pg git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5165 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/CMakeLists.txt | 5 + plugins/zzogl-pg-cg/opengl/CMakeLists.txt | 232 + plugins/zzogl-pg-cg/opengl/CRC.h | 408 + plugins/zzogl-pg-cg/opengl/GLWin.h | 89 + plugins/zzogl-pg-cg/opengl/GLWin32.cpp | 400 + plugins/zzogl-pg-cg/opengl/GLWinX11.cpp | 478 + plugins/zzogl-pg-cg/opengl/GS.h | 987 + plugins/zzogl-pg-cg/opengl/GSDump.cpp | 96 + plugins/zzogl-pg-cg/opengl/GSDump.h | 65 + plugins/zzogl-pg-cg/opengl/GSmain.cpp | 801 + plugins/zzogl-pg-cg/opengl/GifTransfer.cpp | 284 + plugins/zzogl-pg-cg/opengl/GifTransfer.h | 134 + plugins/zzogl-pg-cg/opengl/HostMemory.cpp | 578 + plugins/zzogl-pg-cg/opengl/HostMemory.h | 114 + plugins/zzogl-pg-cg/opengl/Linux/Conf.cpp | 121 + plugins/zzogl-pg-cg/opengl/Linux/Linux.cpp | 519 + plugins/zzogl-pg-cg/opengl/Linux/Linux.h | 31 + .../opengl/Linux/zzogl-pg/zzogl-pg.cbp | 194 + plugins/zzogl-pg-cg/opengl/Mem.cpp | 384 + plugins/zzogl-pg-cg/opengl/Mem.h | 531 + plugins/zzogl-pg-cg/opengl/Mem_Swizzle.cpp | 756 + plugins/zzogl-pg-cg/opengl/Mem_Swizzle.h | 63 + plugins/zzogl-pg-cg/opengl/Mem_Tables.cpp | 420 + plugins/zzogl-pg-cg/opengl/Mem_Transmit.h | 319 + plugins/zzogl-pg-cg/opengl/NewRegs.cpp | 1144 + plugins/zzogl-pg-cg/opengl/NewRegs.h | 973 + plugins/zzogl-pg-cg/opengl/Profile.cpp | 266 + plugins/zzogl-pg-cg/opengl/Profile.h | 172 + plugins/zzogl-pg-cg/opengl/README.txt | 13 + plugins/zzogl-pg-cg/opengl/Regs.cpp | 1080 + plugins/zzogl-pg-cg/opengl/Regs.h | 964 + plugins/zzogl-pg-cg/opengl/Util.h | 279 + plugins/zzogl-pg-cg/opengl/Win32/Conf.cpp | 115 + plugins/zzogl-pg-cg/opengl/Win32/Win32.cpp | 325 + plugins/zzogl-pg-cg/opengl/Win32/Win32.h | 9 + plugins/zzogl-pg-cg/opengl/Win32/aviUtil.h | 488 + plugins/zzogl-pg-cg/opengl/Win32/ps2hw.dat | Bin 0 -> 108445 bytes plugins/zzogl-pg-cg/opengl/Win32/resource.h | 45 + plugins/zzogl-pg-cg/opengl/Win32/resrc1.h | 88 + .../opengl/Win32/tsvnrev/svnrev_template.h | 18 + .../opengl/Win32/tsvnrev/svnrev_unknown.h | 23 + .../opengl/Win32/tsvnrev/updateRevision.cmd | 8 + plugins/zzogl-pg-cg/opengl/Win32/wglext.h | 813 + plugins/zzogl-pg-cg/opengl/Win32/zerogs.bmp | Bin 0 -> 921654 bytes plugins/zzogl-pg-cg/opengl/Win32/zerogs.def | 38 + plugins/zzogl-pg-cg/opengl/Win32/zerogs.rc | 324 + .../opengl/Win32/zerogsogl.vcxproj | 280 + .../opengl/Win32/zerogsogl.vcxproj.filters | 217 + .../opengl/Win32/zerogsogl_2008.sln | 42 + .../opengl/Win32/zerogsogl_2008.vcproj | 597 + plugins/zzogl-pg-cg/opengl/ZZClut.cpp | 1083 + plugins/zzogl-pg-cg/opengl/ZZClut.h | 30 + plugins/zzogl-pg-cg/opengl/ZZGl.h | 134 + plugins/zzogl-pg-cg/opengl/ZZHacks.cpp | 186 + plugins/zzogl-pg-cg/opengl/ZZHacks.h | 118 + plugins/zzogl-pg-cg/opengl/ZZKeyboard.cpp | 247 + plugins/zzogl-pg-cg/opengl/ZZLog.cpp | 354 + plugins/zzogl-pg-cg/opengl/ZZLog.h | 201 + plugins/zzogl-pg-cg/opengl/ZZoglCRTC.cpp | 895 + plugins/zzogl-pg-cg/opengl/ZZoglCRTC.h | 97 + plugins/zzogl-pg-cg/opengl/ZZoglCreate.cpp | 877 + plugins/zzogl-pg-cg/opengl/ZZoglDrawing.cpp | 255 + plugins/zzogl-pg-cg/opengl/ZZoglDrawing.h | 67 + plugins/zzogl-pg-cg/opengl/ZZoglFlush.cpp | 2874 +++ plugins/zzogl-pg-cg/opengl/ZZoglFlushHack.cpp | 531 + plugins/zzogl-pg-cg/opengl/ZZoglFlushHack.h | 84 + plugins/zzogl-pg-cg/opengl/ZZoglMath.h | 511 + plugins/zzogl-pg-cg/opengl/ZZoglSave.cpp | 175 + plugins/zzogl-pg-cg/opengl/ZZoglShaders.cpp | 889 + plugins/zzogl-pg-cg/opengl/ZZoglShaders.h | 231 + plugins/zzogl-pg-cg/opengl/ZZoglShoots.cpp | 655 + plugins/zzogl-pg-cg/opengl/ZZoglShoots.h | 35 + plugins/zzogl-pg-cg/opengl/ZZoglVB.cpp | 506 + plugins/zzogl-pg-cg/opengl/ZZoglVB.h | 158 + .../opengl/ZeroGSShaders/CMakeLists.txt | 75 + .../opengl/ZeroGSShaders/ZeroGSShaders.vcproj | 191 + .../ZeroGSShaders/ZeroGSShaders_2005.sln | 23 + .../ZeroGSShaders/ZeroGSShaders_2005.vcproj | 335 + .../opengl/ZeroGSShaders/copytozerogs.bat | 1 + .../opengl/ZeroGSShaders/zerogsshaders.cpp | 362 + .../opengl/ZeroGSShaders/zerogsshaders.h | 120 + .../opengl/ZeroGSShaders/zlib/crc32.h | 441 + .../opengl/ZeroGSShaders/zlib/deflate.h | 331 + .../opengl/ZeroGSShaders/zlib/inffast.h | 11 + .../opengl/ZeroGSShaders/zlib/inffixed.h | 94 + .../opengl/ZeroGSShaders/zlib/inflate.h | 115 + .../opengl/ZeroGSShaders/zlib/inftrees.h | 55 + .../opengl/ZeroGSShaders/zlib/trees.h | 128 + .../opengl/ZeroGSShaders/zlib/zconf.h | 332 + .../opengl/ZeroGSShaders/zlib/zconf.in.h | 332 + .../opengl/ZeroGSShaders/zlib/zlib.h | 1357 ++ .../opengl/ZeroGSShaders/zlib/zutil.h | 269 + .../opengl/ZeroGSShaders/zpipe.cpp | 122 + .../zzogl-pg-cg/opengl/ZeroGSShaders/zpipe.h | 26 + plugins/zzogl-pg-cg/opengl/buildshaders.bat | 3 + plugins/zzogl-pg-cg/opengl/common.h | 1164 + plugins/zzogl-pg-cg/opengl/ctx0/ps2hw_ctx.fx | 24 + plugins/zzogl-pg-cg/opengl/ctx1/ps2hw_ctx.fx | 23 + plugins/zzogl-pg-cg/opengl/glprocs.c | 17868 ++++++++++++++++ plugins/zzogl-pg-cg/opengl/glprocs.h | 2217 ++ plugins/zzogl-pg-cg/opengl/linux_replay.cpp | 44 + plugins/zzogl-pg-cg/opengl/ps2hw.dat | Bin 0 -> 113923 bytes plugins/zzogl-pg-cg/opengl/ps2hw.fx | 867 + plugins/zzogl-pg-cg/opengl/rasterfont.cpp | 168 + plugins/zzogl-pg-cg/opengl/rasterfont.h | 43 + plugins/zzogl-pg-cg/opengl/shaders.sh | 18 + plugins/zzogl-pg-cg/opengl/targets.cpp | 3521 +++ plugins/zzogl-pg-cg/opengl/targets.h | 607 + plugins/zzogl-pg-cg/opengl/x86-32.S | 716 + plugins/zzogl-pg-cg/opengl/x86-32.asm | 652 + plugins/zzogl-pg-cg/opengl/x86.cpp | 1366 ++ plugins/zzogl-pg-cg/opengl/x86.h | 174 + plugins/zzogl-pg-cg/opengl/zerogs.cpp | 442 + plugins/zzogl-pg-cg/opengl/zerogs.h | 86 + plugins/zzogl-pg-cg/opengl/zpipe.cpp | 131 + plugins/zzogl-pg-cg/opengl/zpipe.h | 26 + 116 files changed, 62403 insertions(+) create mode 100644 plugins/zzogl-pg-cg/opengl/CMakeLists.txt create mode 100644 plugins/zzogl-pg-cg/opengl/CRC.h create mode 100644 plugins/zzogl-pg-cg/opengl/GLWin.h create mode 100644 plugins/zzogl-pg-cg/opengl/GLWin32.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/GLWinX11.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/GS.h create mode 100644 plugins/zzogl-pg-cg/opengl/GSDump.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/GSDump.h create mode 100644 plugins/zzogl-pg-cg/opengl/GSmain.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/GifTransfer.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/GifTransfer.h create mode 100644 plugins/zzogl-pg-cg/opengl/HostMemory.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/HostMemory.h create mode 100644 plugins/zzogl-pg-cg/opengl/Linux/Conf.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/Linux/Linux.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/Linux/Linux.h create mode 100644 plugins/zzogl-pg-cg/opengl/Linux/zzogl-pg/zzogl-pg.cbp create mode 100644 plugins/zzogl-pg-cg/opengl/Mem.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/Mem.h create mode 100644 plugins/zzogl-pg-cg/opengl/Mem_Swizzle.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/Mem_Swizzle.h create mode 100644 plugins/zzogl-pg-cg/opengl/Mem_Tables.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/Mem_Transmit.h create mode 100644 plugins/zzogl-pg-cg/opengl/NewRegs.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/NewRegs.h create mode 100644 plugins/zzogl-pg-cg/opengl/Profile.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/Profile.h create mode 100644 plugins/zzogl-pg-cg/opengl/README.txt create mode 100644 plugins/zzogl-pg-cg/opengl/Regs.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/Regs.h create mode 100644 plugins/zzogl-pg-cg/opengl/Util.h create mode 100644 plugins/zzogl-pg-cg/opengl/Win32/Conf.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/Win32/Win32.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/Win32/Win32.h create mode 100644 plugins/zzogl-pg-cg/opengl/Win32/aviUtil.h create mode 100644 plugins/zzogl-pg-cg/opengl/Win32/ps2hw.dat create mode 100644 plugins/zzogl-pg-cg/opengl/Win32/resource.h create mode 100644 plugins/zzogl-pg-cg/opengl/Win32/resrc1.h create mode 100644 plugins/zzogl-pg-cg/opengl/Win32/tsvnrev/svnrev_template.h create mode 100644 plugins/zzogl-pg-cg/opengl/Win32/tsvnrev/svnrev_unknown.h create mode 100644 plugins/zzogl-pg-cg/opengl/Win32/tsvnrev/updateRevision.cmd create mode 100644 plugins/zzogl-pg-cg/opengl/Win32/wglext.h create mode 100644 plugins/zzogl-pg-cg/opengl/Win32/zerogs.bmp create mode 100644 plugins/zzogl-pg-cg/opengl/Win32/zerogs.def create mode 100644 plugins/zzogl-pg-cg/opengl/Win32/zerogs.rc create mode 100644 plugins/zzogl-pg-cg/opengl/Win32/zerogsogl.vcxproj create mode 100644 plugins/zzogl-pg-cg/opengl/Win32/zerogsogl.vcxproj.filters create mode 100644 plugins/zzogl-pg-cg/opengl/Win32/zerogsogl_2008.sln create mode 100644 plugins/zzogl-pg-cg/opengl/Win32/zerogsogl_2008.vcproj create mode 100644 plugins/zzogl-pg-cg/opengl/ZZClut.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/ZZClut.h create mode 100644 plugins/zzogl-pg-cg/opengl/ZZGl.h create mode 100644 plugins/zzogl-pg-cg/opengl/ZZHacks.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/ZZHacks.h create mode 100644 plugins/zzogl-pg-cg/opengl/ZZKeyboard.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/ZZLog.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/ZZLog.h create mode 100644 plugins/zzogl-pg-cg/opengl/ZZoglCRTC.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/ZZoglCRTC.h create mode 100644 plugins/zzogl-pg-cg/opengl/ZZoglCreate.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/ZZoglDrawing.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/ZZoglDrawing.h create mode 100644 plugins/zzogl-pg-cg/opengl/ZZoglFlush.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/ZZoglFlushHack.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/ZZoglFlushHack.h create mode 100644 plugins/zzogl-pg-cg/opengl/ZZoglMath.h create mode 100644 plugins/zzogl-pg-cg/opengl/ZZoglSave.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/ZZoglShaders.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/ZZoglShaders.h create mode 100644 plugins/zzogl-pg-cg/opengl/ZZoglShoots.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/ZZoglShoots.h create mode 100644 plugins/zzogl-pg-cg/opengl/ZZoglVB.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/ZZoglVB.h create mode 100644 plugins/zzogl-pg-cg/opengl/ZeroGSShaders/CMakeLists.txt create mode 100644 plugins/zzogl-pg-cg/opengl/ZeroGSShaders/ZeroGSShaders.vcproj create mode 100644 plugins/zzogl-pg-cg/opengl/ZeroGSShaders/ZeroGSShaders_2005.sln create mode 100644 plugins/zzogl-pg-cg/opengl/ZeroGSShaders/ZeroGSShaders_2005.vcproj create mode 100644 plugins/zzogl-pg-cg/opengl/ZeroGSShaders/copytozerogs.bat create mode 100644 plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zerogsshaders.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zerogsshaders.h create mode 100644 plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/crc32.h create mode 100644 plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/deflate.h create mode 100644 plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/inffast.h create mode 100644 plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/inffixed.h create mode 100644 plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/inflate.h create mode 100644 plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/inftrees.h create mode 100644 plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/trees.h create mode 100644 plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/zconf.h create mode 100644 plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/zconf.in.h create mode 100644 plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/zlib.h create mode 100644 plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/zutil.h create mode 100644 plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zpipe.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zpipe.h create mode 100644 plugins/zzogl-pg-cg/opengl/buildshaders.bat create mode 100644 plugins/zzogl-pg-cg/opengl/common.h create mode 100644 plugins/zzogl-pg-cg/opengl/ctx0/ps2hw_ctx.fx create mode 100644 plugins/zzogl-pg-cg/opengl/ctx1/ps2hw_ctx.fx create mode 100644 plugins/zzogl-pg-cg/opengl/glprocs.c create mode 100644 plugins/zzogl-pg-cg/opengl/glprocs.h create mode 100644 plugins/zzogl-pg-cg/opengl/linux_replay.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/ps2hw.dat create mode 100644 plugins/zzogl-pg-cg/opengl/ps2hw.fx create mode 100644 plugins/zzogl-pg-cg/opengl/rasterfont.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/rasterfont.h create mode 100755 plugins/zzogl-pg-cg/opengl/shaders.sh create mode 100644 plugins/zzogl-pg-cg/opengl/targets.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/targets.h create mode 100644 plugins/zzogl-pg-cg/opengl/x86-32.S create mode 100644 plugins/zzogl-pg-cg/opengl/x86-32.asm create mode 100644 plugins/zzogl-pg-cg/opengl/x86.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/x86.h create mode 100644 plugins/zzogl-pg-cg/opengl/zerogs.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/zerogs.h create mode 100644 plugins/zzogl-pg-cg/opengl/zpipe.cpp create mode 100644 plugins/zzogl-pg-cg/opengl/zpipe.h diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index e9b14baf9..ce5a5fd74 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -116,6 +116,11 @@ if(EXISTS "${PROJECT_SOURCE_DIR}/plugins/zzogl-pg" AND zzogl) add_subdirectory(zzogl-pg/opengl) endif(EXISTS "${PROJECT_SOURCE_DIR}/plugins/zzogl-pg" AND zzogl) +# make zzogl-pg +if(EXISTS "${PROJECT_SOURCE_DIR}/plugins/zzogl-pg-cg" AND zzogl) + add_subdirectory(zzogl-pg-cg/opengl) +endif(EXISTS "${PROJECT_SOURCE_DIR}/plugins/zzogl-pg-cg" AND zzogl) + # make zeropad if(EXISTS "${PROJECT_SOURCE_DIR}/plugins/zeropad" AND zeropad) add_subdirectory(zeropad) diff --git a/plugins/zzogl-pg-cg/opengl/CMakeLists.txt b/plugins/zzogl-pg-cg/opengl/CMakeLists.txt new file mode 100644 index 000000000..4b8848766 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/CMakeLists.txt @@ -0,0 +1,232 @@ +# Check that people use the good file +if(NOT TOP_CMAKE_WAS_SOURCED) + message(FATAL_ERROR " + You did not 'cmake' the good CMakeLists.txt file. Use the one in the top dir. + It is advice to delete all wrongly generated cmake stuff => CMakeFiles & CMakeCache.txt") +endif(NOT TOP_CMAKE_WAS_SOURCED) + +# Allow to build the shader files +if(EXISTS "${PROJECT_SOURCE_DIR}/plugins/zzogl-pg/opengl/ZeroGSShaders") + add_subdirectory(ZeroGSShaders) +endif(EXISTS "${PROJECT_SOURCE_DIR}/plugins/zzogl-pg/opengl/ZeroGSShaders") + +# plugin name +set(Output zzogl-cg-0.3.0) + +set(CommonFlags + -pthread + -DZEROGS_SSE2 + -fno-regmove + -fno-strict-aliasing + -Wstrict-aliasing # Allow to track strict aliasing issue. + -Wunused-variable + ) + +set(OptimizationFlags + -O2 + -DNDEBUG + ) + +# Debug - Build +if(CMAKE_BUILD_TYPE STREQUAL Debug) + # add defines + add_definitions(${CommonFlags} -g -Wall -D_DEBUG) +endif(CMAKE_BUILD_TYPE STREQUAL Debug) + +# Devel - Build +if(CMAKE_BUILD_TYPE STREQUAL Devel) + # add defines + add_definitions(${CommonFlags} ${OptimizationFlags} -g -W -DZEROGS_DEVBUILD) +endif(CMAKE_BUILD_TYPE STREQUAL Devel) + +# Release - Build +if(CMAKE_BUILD_TYPE STREQUAL Release) + # add defines + add_definitions(${CommonFlags} ${OptimizationFlags} -W) +endif(CMAKE_BUILD_TYPE STREQUAL Release) + +# zzogl sources +set(zzoglSources + GifTransfer.cpp + GLWin32.cpp + GLWinX11.cpp + GSDump.cpp + GSmain.cpp + HostMemory.cpp + Mem.cpp + # memcpy_amd.cpp + Mem_Swizzle.cpp + Mem_Tables.cpp + Profile.cpp + rasterfont.cpp + NewRegs.cpp + Regs.cpp + targets.cpp + x86.cpp + zerogs.cpp + zpipe.cpp + ZZClut.cpp + ZZHacks.cpp + ZZKeyboard.cpp + ZZoglDrawing.cpp + ZZLog.cpp + ZZoglCreate.cpp + ZZoglCRTC.cpp + ZZoglFlush.cpp + ZZoglFlushHack.cpp + ZZoglSave.cpp + ZZoglShaders.cpp + ZZoglShoots.cpp + ZZoglVB.cpp + ) + +# zzogl headers +set(zzoglHeaders + common.h + CRC.h + GifTransfer.h + # glprocs.h + GS.h + GSDump.h + HostMemory.h + Mem.h + Mem_Swizzle.h + Mem_Transmit.h + Profile.h + rasterfont.h + NewRegs.h + Regs.h + targets.h + Util.h + x86.h + zerogs.h + zpipe.h + ZZClut.h + ZZGl.h + ZZHacks.h + ZZoglDrawing.h + ZZLog.h + ZZoglCRTC.h + ZZoglMath.h + ZZoglShaders.h + ZZoglShoots.h + ZZoglVB.h + ) + +# zzogl S sources +set(zzoglSSources + x86-32.S) + +# zzogl shader sources +set(zzoglShaderSources + ctx0/ps2hw_ctx.fx + ctx1/ps2hw_ctx.fx) + +# zzogl Linux sources +set(zzoglLinuxSources + Linux/Conf.cpp + Linux/Linux.cpp) + +# zzogl Linux headers +set(zzoglLinuxHeaders + Linux/Linux.h) + +# change language of .S-files to c++ +set_source_files_properties(${zzoglSSources} PROPERTIES LANGUAGE CXX) + +# add additional include directories +include_directories(. + Linux) + +# add library +add_library(${Output} SHARED + ${zzoglSources} + ${zzoglHeaders} + ${zzoglSSources} + ${zzoglShaderSources} + ${zzoglLinuxSources} + ${zzoglLinuxHeaders}) + +# Trick that allow to compile zzogl with GSOPEN2 and the replayer with GSOPEN +set_target_properties(${Output} PROPERTIES COMPILE_DEFINITIONS USE_GSOPEN2) + +# link target with project internal libraries +target_link_libraries(${Output} Utilities) + +# link target with Cg +target_link_libraries(${Output} ${CG_LIBRARIES}) + +# link target with glew +target_link_libraries(${Output} ${GLEW_LIBRARY}) + +# link target with opengl +target_link_libraries(${Output} ${OPENGL_LIBRARIES}) + +# link target with X11 +target_link_libraries(${Output} ${X11_LIBRARIES}) + +# link target with jpeg +target_link_libraries(${Output} ${JPEG_LIBRARIES}) + +if(Linux) + # link target with gtk2 + target_link_libraries(${Output} ${GTK2_LIBRARIES}) +endif(Linux) + +# link target with zlib +target_link_libraries(${Output} ${ZLIB_LIBRARIES}) + +# User flags options +if(NOT USER_CMAKE_LD_FLAGS STREQUAL "") + target_link_libraries(${Output} "${USER_CMAKE_LD_FLAGS}") +endif(NOT USER_CMAKE_LD_FLAGS STREQUAL "") + +if(PACKAGE_MODE) + install(TARGETS ${Output} DESTINATION ${PLUGIN_DIR}) + install(FILES ${PROJECT_SOURCE_DIR}/plugins/zzogl-pg/opengl/ps2hw.dat DESTINATION ${PLUGIN_DIR}) +else(PACKAGE_MODE) + install(TARGETS ${Output} DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins) + install(FILES ${PROJECT_SOURCE_DIR}/plugins/zzogl-pg/opengl/ps2hw.dat DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins) +endif(PACKAGE_MODE) + +################################### Replay Loader +set(Replay pcsx2_ZZCGReplayLoader) +set(Static zzogl-cg-static) + +add_library(${Static} STATIC + ${zzoglSources} + ${zzoglHeaders} + ${zzoglSSources} + ${zzoglShaderSources} + ${zzoglLinuxSources} + ${zzoglLinuxHeaders}) + +target_link_libraries(${Static} Utilities) +target_link_libraries(${Static} ${CG_LIBRARIES}) +target_link_libraries(${Static} ${GLEW_LIBRARY}) +target_link_libraries(${Static} ${OPENGL_LIBRARIES}) +target_link_libraries(${Static} ${X11_LIBRARIES}) +target_link_libraries(${Static} ${JPEG_LIBRARIES}) + +add_executable(${Replay} linux_replay.cpp) + +target_link_libraries(${Replay} ${Static}) +target_link_libraries(${Replay} Utilities) +target_link_libraries(${Replay} ${CG_LIBRARIES}) +target_link_libraries(${Replay} ${GLEW_LIBRARY}) +target_link_libraries(${Replay} ${OPENGL_LIBRARIES}) +target_link_libraries(${Replay} ${X11_LIBRARIES}) +target_link_libraries(${Replay} ${JPEG_LIBRARIES}) + +target_link_libraries(${Replay} ${GTK2_LIBRARIES}) +target_link_libraries(${Replay} ${ZLIB_LIBRARIES}) + +if(NOT USER_CMAKE_LD_FLAGS STREQUAL "") + target_link_libraries(${Replay} "${USER_CMAKE_LD_FLAGS}") +endif(NOT USER_CMAKE_LD_FLAGS STREQUAL "") + +if(PACKAGE_MODE) + install(TARGETS ${Replay} DESTINATION bin) +else(PACKAGE_MODE) + install(TARGETS ${Replay} DESTINATION ${CMAKE_SOURCE_DIR}/bin) +endif(PACKAGE_MODE) diff --git a/plugins/zzogl-pg-cg/opengl/CRC.h b/plugins/zzogl-pg-cg/opengl/CRC.h new file mode 100644 index 000000000..207e2faa3 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/CRC.h @@ -0,0 +1,408 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef CRC_H_INCLUDED +#define CRC_H_INCLUDED + +#include "ZZHacks.h" + +// CRC Information +enum Title_Info +{ + Unknown_Title, + MetalSlug6, + TomoyoAfter, + Clannad, + Lamune, + KyuuketsuKitanMoonties, + PiaCarroteYoukosoGPGakuenPrincess, + KazokuKeikakuKokoroNoKizuna, + DuelSaviorDestiny, + FFX, + FFX2, + FFXII, + ShadowHearts, + Okami, + MetalGearSolid3, + DBZBT2, + DBZBT3, + SFEX3, + Bully, + BullyCC, + SoTC, + OnePieceGrandAdventure, + OnePieceGrandBattle, + ICO, + GT4, + WildArms4, + WildArms5, + Manhunt2, + CrashBandicootWoC, + ResidentEvil4, + Spartan, + AceCombat4, + Drakengard2, + Tekken5, + IkkiTousen, + GodOfWar, + GodOfWar2, + JackieChanAdv, + HarvestMoon, + NamcoXCapcom, + GiTS, + Onimusha3, + MajokkoALaMode2, + TalesOfAbyss, + SonicUnleashed, + SimpsonsGame, + Genji, + StarOcean3, + ValkyrieProfile2, + RadiataStories, + SMTNocturne, + SMTDDS1, + SMTDDS2, + RozenMaidenGebetGarden, + Xenosaga, + Espgaluda, + OkageShadowKing, + ShadowTheHedgehog, + AtelierIris1, + AtelierIris2, + AtelierIris3, + AtelierJudie, + AtelierLilie, + AtelierViorate, + ArTonelico1, + ArTonelico2, + ManaKhemia1, + ManaKhemia2, + DarkCloud1, + DarkCloud2, + GhostInTheShell, + TitleCount, + Disgaea, + Disgaea2, + Gradius, + KingdomHearts, + KingdomHeartsFM, + KingdomHearts2, + KingdomHearts2FM, + KingdomHeartsCOM, + Tekken4, + Kaena, + Sims_The_Urbz, + MarvelxCapcom2, + NeoPets_Darkest_Faerie, + CrashnBurn, + Xenosaga2, + HauntingGround, + NightmareBeforeChristmas, + PowershotPinball, + BioHazard4, + NUMBER_OF_TITLES +}; + +enum Region_Info +{ + Unknown_Region, + US, + EU, + JP, + JPUNDUB, + RU, + FR, + DE, + IT, + ES, + ASIA, + RegionCount, +}; + +struct Game_Info +{ + u32 crc; + Title_Info title; + Region_Info region; + u32 flags; + s32 v_thresh, t_thresh; +}; + +static const Game_Info crc_game_list[] = +{ + // This section is straight from GSdx. Ones that also have ZZOgl hacks are commented out. + + {0x00000000, Unknown_Title, Unknown_Region, 0, -1, -1}, + {0x2113EA2E, MetalSlug6, Unknown_Region, 0, -1, -1}, + {0x42E05BAF, TomoyoAfter, JP, 0, -1, -1}, + {0x7800DC84, Clannad, JP, 0, -1, -1}, + {0xA6167B59, Lamune, JP, 0, -1, -1}, + {0xDDB59F46, KyuuketsuKitanMoonties, JP, 0, -1, -1}, + {0xC8EE2562, PiaCarroteYoukosoGPGakuenPrincess, JP, 0, -1, -1}, + {0x6CF94A43, KazokuKeikakuKokoroNoKizuna, JP, 0, -1, -1}, + {0xEDAF602D, DuelSaviorDestiny, JP, 0, -1, -1}, + {0xa39517ab, FFX, EU, 0, -1, -1}, + {0xa39517ae, FFX, FR, 0, -1, -1}, + {0x941bb7d9, FFX, DE, 0, -1, -1}, + {0xa39517a9, FFX, IT, 0, -1, -1}, + {0x941bb7de, FFX, ES, 0, -1, -1}, + {0xb4414ea1, FFX, RU, 0, -1, -1}, + {0xee97db5b, FFX, RU, 0, -1, -1}, + {0xaec495cc, FFX, RU, 0, -1, -1}, + {0xbb3d833a, FFX, US, 0, -1, -1}, + {0x6a4efe60, FFX, JP, 0, -1, -1}, + {0x3866ca7e, FFX, ASIA, 0, -1, -1}, // int. + {0x658597e2, FFX, JP, 0, -1, -1}, // int. + {0x9aac5309, FFX2, EU, 0, -1, -1}, + {0x9aac530c, FFX2, FR, 0, -1, -1}, + {0x9aac530a, FFX2, FR, 0, -1, -1}, // ? + {0x9aac530d, FFX2, DE, 0, -1, -1}, + {0x9aac530b, FFX2, IT, 0, -1, -1}, + {0x48fe0c71, FFX2, US, 0, -1, -1}, + {0xe1fd9a2d, FFX2, JP, 0, -1, -1}, // int. + {0x78da0252, FFXII, EU, 0, -1, -1}, + {0xc1274668, FFXII, EU, 0, -1, -1}, + {0xdc2a467e, FFXII, EU, 0, -1, -1}, + {0xca284668, FFXII, EU, 0, -1, -1}, + {0x280AD120, FFXII, JP, 0, -1, -1}, + {0x08C1ED4D, HauntingGround, Unknown_Region, 0, -1, -1}, + {0x2CD5794C, HauntingGround, EU, 0, -1, -1}, + {0x867BB945, HauntingGround, JP, 0, -1, -1}, + {0xE263BC4B, HauntingGround, JP, 0, -1, -1}, + {0x901AAC09, HauntingGround, US, 0, -1, -1}, + {0x8BE3D7B2, ShadowHearts, Unknown_Region, 0, -1, -1}, + {0xDEFA4763, ShadowHearts, US, 0, -1, -1}, + //{0x21068223, Okami, US, 0, -1, -1}, + //{0x891f223f, Okami, FR, 0, -1, -1}, + //{0xC5DEFEA0, Okami, JP, 0, -1, -1}, + {0x053D2239, MetalGearSolid3, US, 0, -1, -1}, + {0x086273D2, MetalGearSolid3, FR, 0, -1, -1}, + {0x26A6E286, MetalGearSolid3, EU, 0, -1, -1}, + {0xAA31B5BF, MetalGearSolid3, Unknown_Region, 0, -1, -1}, + {0x9F185CE1, MetalGearSolid3, Unknown_Region, 0, -1, -1}, + {0x98D4BC93, MetalGearSolid3, EU, 0, -1, -1}, + {0x86BC3040, MetalGearSolid3, US, 0, -1, -1}, //Subsistance disc 1 + {0x0481AD8A, MetalGearSolid3, JP, 0, -1, -1}, + {0x79ED26AD, MetalGearSolid3, EU, 0, -1, -1}, + {0x5E31EA42, MetalGearSolid3, EU, 0, -1, -1}, + {0xD7ED797D, MetalGearSolid3, EU, 0, -1, -1}, + {0x278722BF, DBZBT2, US, 0, -1, -1}, + {0xFE961D28, DBZBT2, US, 0, -1, -1}, + {0x0393B6BE, DBZBT2, EU, 0, -1, -1}, + {0xE2F289ED, DBZBT2, JP, 0, -1, -1}, // Sparking Neo! + {0x35AA84D1, DBZBT2, Unknown_Region, 0, -1, -1}, + {0x428113C2, DBZBT3, US, 0, -1, -1}, + {0xA422BB13, DBZBT3, EU, 0, -1, -1}, + {0x983C53D2, DBZBT3, Unknown_Region, 0, -1, -1}, + {0x983C53D3, DBZBT3, Unknown_Region, 0, -1, -1}, + {0x72B3802A, SFEX3, US, 0, -1, -1}, + {0x71521863, SFEX3, US, 0, -1, -1}, + {0x28703748, Bully, US, 0, -1, -1}, + {0xC78A495D, BullyCC, US, 0, -1, -1}, + {0xC19A374E, SoTC, US, 0, -1, -1}, + {0x7D8F539A, SoTC, EU, 0, -1, -1}, + {0x3122B508, OnePieceGrandAdventure, US, 0, -1, -1}, + {0x8DF14A24, OnePieceGrandAdventure, EU, 0, -1, -1}, + {0xB049DD5E, OnePieceGrandBattle, US, 0, -1, -1}, + {0x5D02CC5B, OnePieceGrandBattle, Unknown_Region, 0, -1, -1}, + {0x6F8545DB, ICO, US, 0, -1, -1}, + {0xB01A4C95, ICO, JP, 0, -1, -1}, + {0x5C991F4E, ICO, Unknown_Region, 0, -1, -1}, + // FIXME multiple CRC + {0x7ACF7E03, ICO, Unknown_Region, 0, -1, -1}, + {0xAEAD1CA3, GT4, JP, 0, -1, -1}, + {0x44A61C8F, GT4, Unknown_Region, 0, -1, -1}, + {0x0086E35B, GT4, Unknown_Region, 0, -1, -1}, + {0x77E61C8A, GT4, Unknown_Region, 0, -1, -1}, + {0xC164550A, WildArms5, JPUNDUB, 0, -1, -1}, + {0xC1640D2C, WildArms5, US, 0, -1, -1}, + {0x0FCF8FE4, WildArms5, EU, 0, -1, -1}, + {0x2294D322, WildArms5, JP, 0, -1, -1}, + {0x565B6170, WildArms5, JP, 0, -1, -1}, + {0xBBC3EFFA, WildArms4, US, 0, -1, -1}, + {0xBBC396EC, WildArms4, US, 0, -1, -1}, //hmm such a small diff in the CRC.. + {0x8B029334, Manhunt2, Unknown_Region, 0, -1, -1}, + {0x09F49E37, CrashBandicootWoC, Unknown_Region, 0, -1, -1}, + {0x013E349D, ResidentEvil4, US, 0, -1, -1}, + {0x6BA2F6B9, ResidentEvil4, Unknown_Region, 0, -1, -1}, + {0x60FA8C69, ResidentEvil4, JP, 0, -1, -1}, + {0x72E1E60E, Spartan, Unknown_Region, 0, -1, -1}, + {0x5ED8FB53, AceCombat4, JP, 0, -1, -1}, + {0x1B9B7563, AceCombat4, Unknown_Region, 0, -1, -1}, + {0xEC432B24, Drakengard2, Unknown_Region, 0, -1, -1}, + {0xFC46EA61, Tekken5, JP, 0, -1, -1}, + {0x1F88EE37, Tekken5, Unknown_Region, 0, -1, -1}, + {0x652050D2, Tekken5, Unknown_Region, 0, -1, -1}, + {0x9E98B8AE, IkkiTousen, JP, 0, -1, -1}, + //{0xD6385328, GodOfWar, US, 0, -1, -1}, + //{0xFB0E6D72, GodOfWar, EU, 0, -1, -1}, + //{0xEB001875, GodOfWar, EU, 0, -1, -1}, + //{0xA61A4C6D, GodOfWar, Unknown_Region, 0, -1, -1}, + //{0xE23D532B, GodOfWar, Unknown_Region, 0, -1, -1}, + //{0xDF1AF973, GodOfWar, Unknown_Region, 0, -1, -1}, + //{0xD6385328, GodOfWar, Unknown_Region, 0, -1, -1}, + {0x2F123FD8, GodOfWar2, RU, 0, -1, -1}, + {0x2F123FD8, GodOfWar2, US, 0, -1, -1}, + {0x44A8A22A, GodOfWar2, EU, 0, -1, -1}, + {0x4340C7C6, GodOfWar2, Unknown_Region, 0, -1, -1}, + {0xF8CD3DF6, GodOfWar2, Unknown_Region, 0, -1, -1}, + {0x0B82BFF7, GodOfWar2, Unknown_Region, 0, -1, -1}, + {0x5D482F18, JackieChanAdv, Unknown_Region, 0, -1, -1}, + //{0xf0a6d880, HarvestMoon, US, 0, -1, -1}, + {0x75c01a04, NamcoXCapcom, US, 0, -1, -1}, + {0xBF6F101F, GiTS, US, 0, -1, -1}, + {0xA5768F53, GiTS, JP, 0, -1, -1}, + {0x6BF11378, Onimusha3, US, 0, -1, -1}, + {0xF442260C, MajokkoALaMode2, JP, 0, -1, -1}, + {0x14FE77F7, TalesOfAbyss, US, 0, -1, -1}, + {0x045D77E9, TalesOfAbyss, JPUNDUB, 0, -1, -1}, + {0xAA5EC3A3, TalesOfAbyss, JP, 0, -1, -1}, + //{0xFB236A46, SonicUnleashed, US, 0, -1, -1}, + {0x4C7BB3C8, SimpsonsGame, Unknown_Region, 0, -1, -1}, + {0x4C94B32C, SimpsonsGame, Unknown_Region, 0, -1, -1}, + {0xD71B57F4, Genji, Unknown_Region, 0, -1, -1}, + {0x23A97857, StarOcean3, US, 0, -1, -1}, + {0xBEC32D49, StarOcean3, JP, 0, -1, -1}, + {0x8192A241, StarOcean3, JP, 0, -1, -1}, //NTSC JP special directors cut limited extra sugar on top edition (the special one :p) + {0x23A97857, StarOcean3, JPUNDUB, 0, -1, -1}, + {0xCC96CE93, ValkyrieProfile2, US, 0, -1, -1}, + {0x774DE8E2, ValkyrieProfile2, JP, 0, -1, -1}, + {0x04CCB600, ValkyrieProfile2, EU, 0, -1, -1}, + {0xB65E141B, ValkyrieProfile2, EU, 0, -1, -1}, // PAL German + {0x47B9B2FD, RadiataStories, US, 0, -1, -1}, + {0xE8FCF8EC, SMTNocturne, US, 0, -1, -1}, // GSdx saves/reloads z buffer around shadow drawing, same issue with all the SMT games following + {0xF0A31EE3, SMTNocturne, EU, 0, -1, -1}, // SMTNocturne (Lucifers Call in EU) + {0xAE0DE7B7, SMTNocturne, EU, 0, -1, -1}, // SMTNocturne (Lucifers Call in EU) + {0xD60DA6D4, SMTNocturne, JP, 0, -1, -1}, // SMTNocturne + {0x0e762e8d, SMTNocturne, JP, 0, -1, -1}, // SMTNocturne Maniacs + {0x47BA9034, SMTNocturne, JP, 0, -1, -1}, // SMTNocturne Maniacs Chronicle + {0xD7273511, SMTDDS1, US, 0, -1, -1}, // SMT Digital Devil Saga + {0x1683A6BE, SMTDDS1, EU, 0, -1, -1}, // SMT Digital Devil Saga + {0x44865CE1, SMTDDS1, JP, 0, -1, -1}, // SMT Digital Devil Saga + {0xD382C164, SMTDDS2, US, 0, -1, -1}, // SMT Digital Devil Saga 2 + {0xD568B684, SMTDDS2, EU, 0, -1, -1}, // SMT Digital Devil Saga 2 + {0xE47C1A9C, SMTDDS2, JP, 0, -1, -1}, // SMT Digital Devil Saga 2 + {0x0B8AB37B, RozenMaidenGebetGarden, JP, 0, -1, -1}, + + // And these are here for ZZogl hacks. + {0xA3D63039, Xenosaga, JP, GAME_DOPARALLELCTX, 64, 32}, + {0x0E7807B2, Xenosaga, US, GAME_DOPARALLELCTX, 64, 32}, + {0x7D2FE035, Espgaluda, JP, 0/*GAME_BIGVALIDATE*/, 24, -1}, + {0x21068223, Okami, US, GAME_XENOSPECHACK, -1, -1}, + {0x891f223f, Okami, FR, GAME_XENOSPECHACK, -1, -1}, + {0xC5DEFEA0, Okami, JP, GAME_XENOSPECHACK, -1, -1}, + {0xe0426fc6, OkageShadowKing, Unknown_Region, GAME_XENOSPECHACK, -1, -1}, + + {0xD6385328, GodOfWar, US, GAME_FULL16BITRES, -1, -1}, + {0xFB0E6D72, GodOfWar, EU, GAME_FULL16BITRES, -1, -1}, + {0xEB001875, GodOfWar, EU, GAME_FULL16BITRES, -1, -1}, + {0xA61A4C6D, GodOfWar, Unknown_Region, GAME_FULL16BITRES, -1, -1}, + {0xE23D532B, GodOfWar, Unknown_Region, GAME_FULL16BITRES, -1, -1}, + {0xDF1AF973, GodOfWar, Unknown_Region, GAME_FULL16BITRES, -1, -1}, + {0xD6385328, GodOfWar, Unknown_Region, GAME_FULL16BITRES, -1, -1}, + + //{0x2F123FD8, GodOfWar2, Unknown_Region, GAME_FULL16BITRES, -1, -1}, + //{0x44A8A22A, GodOfWar2, Unknown_Region, GAME_FULL16BITRES, -1, -1}, + //{0x4340C7C6, GodOfWar2, Unknown_Region, GAME_FULL16BITRES, -1, -1}, + //{0xF8CD3DF6, GodOfWar2, Unknown_Region, GAME_FULL16BITRES, -1, -1}, + //{0x0B82BFF7, GodOfWar2, Unknown_Region, GAME_FULL16BITRES, -1, -1}, + + {0xF0A6D880, HarvestMoon, US, GAME_NOSTENCIL, -1, -1}, + //{0x304C115C, HarvestMoon, Unknown, GAME_NOSTENCIL, -1, -1}, + {0xFB236A46, SonicUnleashed, US, GAME_FASTUPDATE | GAME_NOALPHAFAIL, -1, -1}, + {0xa5d29941, ShadowTheHedgehog, US, GAME_FASTUPDATE | GAME_NOALPHAFAIL, -1, -1}, + + {0x7acf7e03, AtelierIris1, Unknown_Region, GAME_GUSTHACK, -1, -1}, + {0xF0457CEF, AtelierIris1, Unknown_Region, GAME_GUSTHACK, -1, -1}, + {0xE3981DBB, AtelierIris1, US, GAME_GUSTHACK, -1, -1}, + {0x9AC65D6A, AtelierIris2, US, GAME_GUSTHACK, -1, -1}, + {0x4CCC9212, AtelierIris3, US, GAME_GUSTHACK, -1, -1}, + {0xCA295E61, AtelierIris3, JP, GAME_GUSTHACK, -1, -1}, + //{0x4437F4B1, ArTonelico1, US, GAME_GUSTHACK, -1, -1}, + {0xF95F37EE, ArTonelico2, US, GAME_GUSTHACK, -1, -1}, + {0xF46142D3, ArTonelico2, JPUNDUB, GAME_GUSTHACK, -1, -1}, + + // According to Zeydlitz, Mana Khemia no longer needs the Gust Hack. + //{0x77b0236f, ManaKhemia1, US, GAME_GUSTHACK, -1, -1}, + //{0x433951e7, ManaKhemia2, US, GAME_GUSTHACK, -1, -1}, + //{0xda11c6d4, AtelierJudie, JP, GAME_GUSTHACK, -1, -1}, + //{0x3e72c085, AtelierLilie, JP, GAME_GUSTHACK, -1, -1}, + //{0x6eac076b, AtelierViorate, JP, GAME_GUSTHACK, -1, -1}, + + {0xbaa8dd8, DarkCloud1, US, GAME_NOTARGETRESOLVE, -1, -1}, + {0xA5C05C78, DarkCloud1, Unknown_Region, GAME_NOTARGETRESOLVE, -1, -1}, + //{0x1DF41F33, DarkCloud2, US, 0, -1, -1}, + {0x95cc86ef, GhostInTheShell, Unknown_Region, GAME_NOALPHAFAIL, -1, -1} + +// Game settings that used to be in the Patches folder. Commented out until I decide what to do with them. +// {0x951555A0, Disgaea2, US, GAME_NODEPTHRESOLVE, -1, -1}, +// {0x4334E17D, Disgaea2, JP, GAME_NODEPTHRESOLVE, -1, -1}, +// +// {0x5EB127E7, Gradius, JP, GAME_INTERLACE2X, -1, -1}, +// {0x6ADBC24B, Gradius, EU, GAME_INTERLACE2X, -1, -1}, +// {0xF22CDDAF, Gradius, US, GAME_INTERLACE2X, -1, -1}, +// +// {0xF52FB2BE, KingdomHearts, EU, GAME_QUICKRESOLVE1, -1, -1}, +// {0xAE3EAA05, KingdomHearts, DE, GAME_QUICKRESOLVE1, -1, -1}, +// {0xF6DC728D, KingdomHearts, FR, GAME_QUICKRESOLVE1, -1, -1}, +// {0x0F6B6315, KingdomHearts, US, GAME_QUICKRESOLVE1, -1, -1}, +// {0x3E68955A, KingdomHeartsFM, JP, GAME_QUICKRESOLVE1, -1, -1}, +// +// {0xC398F477, KingdomHearts2, EU, GAME_NODEPTHRESOLVE, -1, -1}, +// {0xDA0535FD, KingdomHearts2, US, GAME_NODEPTHRESOLVE, -1, -1}, +// {0x93F8A60B, KingdomHearts2, JP, GAME_NODEPTHRESOLVE, -1, -1}, +// {0xF266B00B, KingdomHearts2FM, JP, GAME_NODEPTHRESOLVE, -1, -1}, +// +// //The patch claimed to stop characters appearing as wigs on GeForce 8x00 series cards (Disable Alpha Testing) +// {0x2251E14D, Tekken4, EU, GAME_NOALPHATEST, -1, -1}, +// +// // This one is supposed to fix a refresh bug. +// {0x51F91783, Kaena, JP, GAME_NOTARGETRESOLVE, -1, -1}, +// +// {0xDEFA4763, ShadowHearts, EU, GAME_NODEPTHRESOLVE | GAME_NOQUICKRESOLVE | GAME_NOTARGETRESOLVE | GAME_AUTORESET, -1, -1}, +// {0x8BE3D7B2, ShadowHearts, US, GAME_NODEPTHUPDATE | GAME_AUTORESET | GAME_NOQUICKRESOLVE, -1, -1}, +// +// {0x015314A2, Sims_The_Urbz, US, GAME_NOQUICKRESOLVE, -1, -1}, +// +// // "Required fixes to visuals" +// {0x086273D2, MetalGearSolid3, US, GAME_FULL16BITRES | GAME_NODEPTHRESOLVE, -1, -1}, +// +// {0x4D228733, MarvelxCapcom2, US, GAME_QUICKRESOLVE1, -1, -1}, +// {0x934F9081, NeoPets_Darkest_Faerie, US, GAME_RESOLVEPROMOTED | GAME_FULL16BITRES | GAME_NODEPTHRESOLVE, -1, -1}, +// +// {0x21068223, Okami, US, GAME_FULL16BITRES|GAME_NODEPTHRESOLVE|GAME_FASTUPDATE, -1, -1}, +// {0xC5DEFEA0, Okami, JP, GAME_FULL16BITRES|GAME_NODEPTHRESOLVE|GAME_FASTUPDATE, -1, -1}, +// +// // Speed up +// {0x6BA2F6B9, ResidentEvil4, EU, GAME_NOTARGETRESOLVE | GAME_32BITTARGS, -1, -1}, +// {0x013E349D, ResidentEvil4, US, GAME_NOTARGETCLUT, -1, -1}, +// +// {0x2088950A, Xenosaga2, JP, GAME_FULL16BITRES | GAME_NODEPTHRESOLVE, -1, -1}, +// {0x901AAC09, HauntingGround, US, GAME_FULL16BITRES | GAME_NODEPTHRESOLVE, -1, -1}, +// {0x625AF967, NightmareBeforeChristmas, JP, GAME_TEXAHACK, -1, -1}, +// +// {0x3CFE3B37, PowershotPinball, EU, GAME_AUTORESET, -1, -1}, +// {0x60FA8C69, BioHazard4, JP, GAME_NOTARGETCLUT, -1, -1} +// End of game settings from the patch folder. +}; + +#define GAME_INFO_INDEX (sizeof(crc_game_list)/sizeof(Game_Info)) + + +#endif // CRC_H_INCLUDED diff --git a/plugins/zzogl-pg-cg/opengl/GLWin.h b/plugins/zzogl-pg-cg/opengl/GLWin.h new file mode 100644 index 000000000..0a314b25c --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/GLWin.h @@ -0,0 +1,89 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef GLWIN_H_INCLUDED +#define GLWIN_H_INCLUDED + +#ifdef _WIN32 +#define GL_WIN32_WINDOW +#else +#define GL_X11_WINDOW +#endif + +#undef CreateWindow // Undo Windows.h global namespace pollution + +extern void SetDeviceSize(int nNewWidth, int nNewHeight); +extern void OnFKey(int key, int shift); + +class GLWindow +{ + private: +#ifdef GL_X11_WINDOW + Display *glDisplay; + GLXContext context; + XVisualInfo *vi; + + Window glWindow; + XSetWindowAttributes attr; + + bool CreateVisual(); + void GetGLXVersion(); + void GetWindowSize(); + void UpdateGrabKey(); + void Force43Ratio(); + void CreateContextGL(); +#endif + bool fullScreen, doubleBuffered; + u32 width, height, depth; + + public: + char title[256]; + Size backbuffer; + + void SwapGLBuffers(); + bool ReleaseContext(); + +#ifdef GL_X11_WINDOW + void ToggleFullscreen(); +#endif + + bool CreateWindow(void *pDisplay); + void CloseWindow(); + bool DisplayWindow(int _width, int _height); + void SetTitle(char *strtitle); + void ResizeCheck(); + void ProcessEvents(); + + void UpdateWindowSize(int nNewWidth, int nNewHeight) + { + FUNCLOG + backbuffer.w = std::max(nNewWidth, 16); + backbuffer.h = std::max(nNewHeight, 16); + + if (!(conf.fullscreen())) + { + conf.width = nNewWidth; + conf.height = nNewHeight; + } + } +}; + +extern GLWindow GLWin; + +#endif // GLWIN_H_INCLUDED diff --git a/plugins/zzogl-pg-cg/opengl/GLWin32.cpp b/plugins/zzogl-pg-cg/opengl/GLWin32.cpp new file mode 100644 index 000000000..d71ca84ae --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/GLWin32.cpp @@ -0,0 +1,400 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "GS.h" +#include "GLWin.h" + +#ifdef GL_WIN32_WINDOW + +HWND GShwnd = NULL; +HDC hDC = NULL; // Private GDI Device Context +HGLRC hRC = NULL; // Permanent Rendering Context + +LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static int nWindowWidth = 0, nWindowHeight = 0; + + switch (msg) + { + case WM_DESTROY: + PostQuitMessage(0); + return 0; + + case WM_KEYDOWN: +// switch(wParam) { +// case VK_ESCAPE: +// SendMessage(hWnd, WM_DESTROY, 0L, 0L); +// break; +// } + break; + + case WM_SIZE: + nWindowWidth = lParam & 0xffff; + nWindowHeight = lParam >> 16; + GLWin.UpdateWindowSize(nWindowWidth, nWindowHeight); + break; + + case WM_SIZING: + // if button is 0, then just released so can resize + if (GetSystemMetrics(SM_SWAPBUTTON) ? !GetAsyncKeyState(VK_RBUTTON) : !GetAsyncKeyState(VK_LBUTTON)) + { + SetDeviceSize(nWindowWidth, nWindowHeight); + } + break; + + case WM_SETCURSOR: + SetCursor(NULL); + break; + } + + return DefWindowProc(hWnd, msg, wParam, lParam); +} + +bool GLWindow::CreateWindow(void *pDisplay) +{ + RECT rc, rcdesktop; + rc.left = 0; + rc.top = 0; + rc.right = conf.width; + rc.bottom = conf.height; + + WNDCLASSEX wc; + HINSTANCE hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window + DWORD dwExStyle, dwStyle; + + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Move, And Own DC For Window + wc.lpfnWndProc = (WNDPROC) MsgProc; // MsgProc Handles Messages + wc.cbClsExtra = 0; // No Extra Window Data + wc.cbWndExtra = 0; // No Extra Window Data + wc.hInstance = hInstance; // Set The Instance + wc.hIcon = NULL; + wc.hIconSm = NULL; // Load The Default Icon + wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load The Arrow Pointer + wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); // No Background Required For GL + wc.lpszMenuName = NULL; // We Don't Want A Menu + wc.lpszClassName = L"PS2EMU_ZEROGS"; // Set The Class Name + + RegisterClassEx(&wc); + + if (conf.fullscreen()) + { + dwExStyle = WS_EX_APPWINDOW; + dwStyle = WS_POPUP; + } + else + { + dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; + dwStyle = WS_OVERLAPPEDWINDOW | WS_BORDER; + } + + dwStyle |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN; + AdjustWindowRectEx(&rc, dwStyle, false, dwExStyle); + + GetWindowRect(GetDesktopWindow(), &rcdesktop); + + GShwnd = CreateWindowEx( dwExStyle, // Extended Style For The Window + L"PS2EMU_ZEROGS", // Class Name + L"ZZOgl", // Window Title + dwStyle, // Selected Window Style + (rcdesktop.right - (rc.right - rc.left)) / 2, // Window Position + (rcdesktop.bottom - (rc.bottom - rc.top)) / 2, // Window Position + rc.right - rc.left, // Calculate Adjusted Window Width + rc.bottom - rc.top, // Calculate Adjusted Window Height + NULL, // No Parent Window + NULL, // No Menu + hInstance, // Instance + NULL); // Don't Pass Anything To WM_CREATE + + if (GShwnd == NULL) + { + ZZLog::Error_Log("Failed to create window. Exiting..."); + return false; + } + + if (pDisplay != NULL) *(HWND*)pDisplay = GShwnd; + + // set just in case + SetWindowLongPtr(GShwnd, GWLP_WNDPROC, (LPARAM)(WNDPROC)MsgProc); + + ShowWindow(GShwnd, SW_SHOWDEFAULT); + + UpdateWindow(GShwnd); + + SetFocus(GShwnd); + + if (pDisplay == NULL) ZZLog::Error_Log("Failed to create window. Exiting..."); + return (pDisplay != NULL); +} + +bool GLWindow::ReleaseContext() +{ + if (hRC) // Do We Have A Rendering Context? + { + if (!wglMakeCurrent(NULL, NULL)) // Are We Able To Release The DC And RC Contexts? + { + MessageBox(NULL, L"Release Of DC And RC Failed.", L"SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); + } + + if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC? + { + MessageBox(NULL, L"Release Rendering Context Failed.", L"SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); + } + + hRC = NULL; // Set RC To NULL + } + + if (hDC && !ReleaseDC(GShwnd, hDC)) // Are We Able To Release The DC + { + MessageBox(NULL, L"Release Device Context Failed.", L"SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); + hDC = NULL; // Set DC To NULL + } + + return true; +} + +void GLWindow::CloseWindow() +{ + if (GShwnd != NULL) + { + DestroyWindow(GShwnd); + GShwnd = NULL; + } +} + +bool GLWindow::DisplayWindow(int _width, int _height) +{ + GLuint PixelFormat; // Holds The Results After Searching For A Match + DWORD dwExStyle; // Window Extended Style + DWORD dwStyle; // Window Style + + RECT rcdesktop; + GetWindowRect(GetDesktopWindow(), &rcdesktop); + + if (conf.fullscreen()) + { + backbuffer.w = rcdesktop.right - rcdesktop.left; + backbuffer.h = rcdesktop.bottom - rcdesktop.top; + + dwExStyle = WS_EX_APPWINDOW; + dwStyle = WS_POPUP; + ShowCursor(false); + } + else + { + dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; + dwStyle = WS_OVERLAPPEDWINDOW; + backbuffer.w = _width; + backbuffer.h = _height; + } + dwStyle |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN; + + RECT rc; + + rc.left = 0; + rc.top = 0; + rc.right = backbuffer.w; + rc.bottom = backbuffer.h; + AdjustWindowRectEx(&rc, dwStyle, false, dwExStyle); + int X = (rcdesktop.right - rcdesktop.left) / 2 - (rc.right - rc.left) / 2; + int Y = (rcdesktop.bottom - rcdesktop.top) / 2 - (rc.bottom - rc.top) / 2; + + SetWindowLong(GShwnd, GWL_STYLE, dwStyle); + SetWindowLong(GShwnd, GWL_EXSTYLE, dwExStyle); + + SetWindowPos(GShwnd, HWND_TOP, X, Y, rc.right - rc.left, rc.bottom - rc.top, SWP_SHOWWINDOW); + + if (conf.fullscreen()) + { + DEVMODE dmScreenSettings; + memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); + dmScreenSettings.dmSize = sizeof(dmScreenSettings); + dmScreenSettings.dmPelsWidth = backbuffer.w; + dmScreenSettings.dmPelsHeight = backbuffer.h; + dmScreenSettings.dmBitsPerPel = 32; + dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; + + // Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar. + + if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) + { + if (MessageBox(NULL, + L"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?", + L"NeHe GL", + MB_YESNO | MB_ICONEXCLAMATION) == IDYES) + conf.setFullscreen(false); + else + return false; + } + } + else + { + // change to default resolution + ChangeDisplaySettings(NULL, 0); + } + + PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be + + { + sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor + 1, // Version Number + PFD_DRAW_TO_WINDOW | // Format Must Support Window + PFD_SUPPORT_OPENGL | // Format Must Support OpenGL + PFD_DOUBLEBUFFER, // Must Support Double Buffering + PFD_TYPE_RGBA, // Request An RGBA Format + 32, // Select Our Color Depth + 0, 0, 0, 0, 0, 0, // Color Bits Ignored + 0, // 8bit Alpha Buffer + 0, // Shift Bit Ignored + 0, // No Accumulation Buffer + 0, 0, 0, 0, // Accumulation Bits Ignored + 24, // 24Bit Z-Buffer (Depth Buffer) + 8, // 8bit Stencil Buffer + 0, // No Auxiliary Buffer + PFD_MAIN_PLANE, // Main Drawing Layer + 0, // Reserved + 0, 0, 0 // Layer Masks Ignored + }; + + if (!(hDC = GetDC(GShwnd))) + { + MessageBox(NULL, L"(1) Can't Create A GL Device Context.", L"ERROR", MB_OK | MB_ICONEXCLAMATION); + return false; + } + + if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) + { + MessageBox(NULL, L"(2) Can't Find A Suitable PixelFormat.", L"ERROR", MB_OK | MB_ICONEXCLAMATION); + return false; + } + + if (!SetPixelFormat(hDC, PixelFormat, &pfd)) + { + MessageBox(NULL, L"(3) Can't Set The PixelFormat.", L"ERROR", MB_OK | MB_ICONEXCLAMATION); + return false; + } + + if (!(hRC = wglCreateContext(hDC))) + { + MessageBox(NULL, L"(4) Can't Create A GL Rendering Context.", L"ERROR", MB_OK | MB_ICONEXCLAMATION); + return false; + } + + if (!wglMakeCurrent(hDC, hRC)) + { + MessageBox(NULL, L"(5) Can't Activate The GL Rendering Context.", L"ERROR", MB_OK | MB_ICONEXCLAMATION); + return false; + } + + UpdateWindow(GShwnd); + + return true; +} + +void GLWindow::SwapGLBuffers() +{ + static u32 lastswaptime = 0; + + if (glGetError() != GL_NO_ERROR) ZZLog::Debug_Log("glError before swap!"); + + SwapBuffers(hDC); + lastswaptime = timeGetTime(); +} + +void GLWindow::SetTitle(char *strtitle) +{ + if (!conf.fullscreen()) SetWindowText(GShwnd, wxString::FromUTF8(strtitle)); +} + +void GLWindow::ResizeCheck() +{ + +} + + +extern void ChangeDeviceSize(int nNewWidth, int nNewHeight); + +void GLWindow::ProcessEvents() +{ + MSG msg; + + ZeroMemory(&msg, sizeof(msg)); + + while (1) + { + if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) + { + switch (msg.message) + { + case WM_KEYDOWN : + int my_KeyEvent = msg.wParam; + bool my_bShift = !!(GetKeyState(VK_SHIFT) & 0x8000); + + switch (msg.wParam) + { + case VK_F5: + case VK_F6: + case VK_F7: + case VK_F9: + OnFKey(msg.wParam - VK_F1 + 1, my_bShift); + break; + + case VK_ESCAPE: + + if (conf.fullscreen()) + { + // destroy that msg + conf.setFullscreen(false); + ChangeDeviceSize(conf.width, conf.height); + UpdateWindow(GShwnd); + continue; // so that msg doesn't get sent + } + else + { + SendMessage(GShwnd, WM_DESTROY, 0, 0); + return; + } + + break; + } + + break; + } + + TranslateMessage(&msg); + DispatchMessage(&msg); + } + else + { + break; + } + } + + if ((GetKeyState(VK_MENU) & 0x8000) && (GetKeyState(VK_RETURN) & 0x8000)) + { + conf.zz_options.fullscreen = !conf.zz_options.fullscreen; + + SetDeviceSize( + (conf.fullscreen()) ? 1280 : conf.width, + (conf.fullscreen()) ? 960 : conf.height); + } +} + + +#endif diff --git a/plugins/zzogl-pg-cg/opengl/GLWinX11.cpp b/plugins/zzogl-pg-cg/opengl/GLWinX11.cpp new file mode 100644 index 000000000..0730acc21 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/GLWinX11.cpp @@ -0,0 +1,478 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "Util.h" +#include "GLWin.h" + +#ifdef GL_X11_WINDOW + +#include +#include + +#ifdef USE_GSOPEN2 +bool GLWindow::CreateWindow(void *pDisplay) +{ + glWindow = (Window)*((u32*)(pDisplay)+1); + // Do not take the display which come from pcsx2 neither change it. + // You need a new one to do the operation in the GS thread + glDisplay = XOpenDisplay(NULL); + + return true; +} +#else +bool GLWindow::CreateWindow(void *pDisplay) +{ + // init support of multi thread + if (!XInitThreads()) + ZZLog::Error_Log("Failed to init the xlib concurent threads"); + + glDisplay = XOpenDisplay(NULL); + + if (pDisplay == NULL) + { + ZZLog::Error_Log("Failed to create window. Exiting..."); + return false; + } + + // Allow pad to use the display + *(Display**)pDisplay = glDisplay; + // Pad can use the window to grab the input. For the moment just set to 0 to avoid + // to grab an unknow window... Anyway GSopen1 might be dropped in the future + *((u32*)(pDisplay)+1) = 0; + + return true; +} +#endif + +bool GLWindow::ReleaseContext() +{ + bool status = true; + if (!glDisplay) return status; + + // free the context + if (context) + { + if (!glXMakeCurrent(glDisplay, None, NULL)) { + ZZLog::Error_Log("Could not release drawing context."); + status = false; + } + + glXDestroyContext(glDisplay, context); + context = NULL; + } + + // free the visual + if (vi) { + XFree(vi); + vi = NULL; + } + + return status; +} + +void GLWindow::CloseWindow() +{ + SaveConfig(); + if (!glDisplay) return; + + XCloseDisplay(glDisplay); + glDisplay = NULL; +} + +bool GLWindow::CreateVisual() +{ + // attributes for a single buffered visual in RGBA format with at least + // 8 bits per color and a 24 bit depth buffer + int attrListSgl[] = {GLX_RGBA, GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_DEPTH_SIZE, 24, + None + }; + + // attributes for a double buffered visual in RGBA format with at least + // 8 bits per color and a 24 bit depth buffer + int attrListDbl[] = { GLX_RGBA, GLX_DOUBLEBUFFER, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_DEPTH_SIZE, 24, + None + }; + + /* get an appropriate visual */ + vi = glXChooseVisual(glDisplay, DefaultScreen(glDisplay), attrListDbl); + + if (vi == NULL) + { + vi = glXChooseVisual(glDisplay, DefaultScreen(glDisplay), attrListSgl); + doubleBuffered = false; + ZZLog::Error_Log("Only Singlebuffered Visual!"); + } + else + { + doubleBuffered = true; + ZZLog::Error_Log("Got Doublebuffered Visual!"); + } + + if (vi == NULL) + { + ZZLog::Error_Log("Failed to get buffered Visual!"); + return false; + } + return true; +} + +void GLWindow::GetWindowSize() +{ + if (!glDisplay or !glWindow) return; + + unsigned int borderDummy; + Window winDummy; + s32 xDummy; + s32 yDummy; + + XLockDisplay(glDisplay); + XGetGeometry(glDisplay, glWindow, &winDummy, &xDummy, &yDummy, &width, &height, &borderDummy, &depth); + XUnlockDisplay(glDisplay); + + // update the gl buffer size + UpdateWindowSize(width, height); + +#ifndef USE_GSOPEN2 + // too verbose! + ZZLog::Dev_Log("Resolution %dx%d. Depth %d bpp. Position (%d,%d)", width, height, depth, conf.x, conf.y); +#endif +} + +void GLWindow::GetGLXVersion() +{ + int glxMajorVersion, glxMinorVersion; + + glXQueryVersion(glDisplay, &glxMajorVersion, &glxMinorVersion); + + if (glXIsDirect(glDisplay, context)) + ZZLog::Error_Log("glX-Version %d.%d with Direct Rendering", glxMajorVersion, glxMinorVersion); + else + ZZLog::Error_Log("glX-Version %d.%d with Indirect Rendering !!! It will be slow", glxMajorVersion, glxMinorVersion); + +} + +void GLWindow::CreateContextGL() +{ + if (!glDisplay) return; + + // Create a 2.0 opengl context. My understanding, you need it to call the gl function to get the 3.0 context + context = glXCreateContext(glDisplay, vi, NULL, GL_TRUE); + + // FIXME + // On Geforce7, the context 3.0 creation crashes with BadAlloc (insufficient resources for operation) + // So until a better solution is found, keep the 2.0 context -- Gregory + return; + + PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddress((GLubyte *) "glXCreateContextAttribsARB"); + PFNGLXCHOOSEFBCONFIGPROC glXChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC) glXGetProcAddress((GLubyte *) "glXChooseFBConfig"); + if (!glXCreateContextAttribsARB or !glXChooseFBConfig) { + ZZLog::Error_Log("No support of OpenGL 3.0\n"); + return; + } + + // Note this part seems linux specific + int fbcount = 0; + GLXFBConfig *framebuffer_config = glXChooseFBConfig(glDisplay, DefaultScreen(glDisplay), NULL, &fbcount); + if (!framebuffer_config or !fbcount) return; + + // At least create a 3.0 context with compatibility profile + int attribs[] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 0, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, + 0 + }; + GLXContext context_temp = glXCreateContextAttribsARB(glDisplay, framebuffer_config[0], NULL, true, attribs); + if (context_temp) { + ZZLog::Error_Log("Create a 3.0 opengl context"); + glXDestroyContext(glDisplay, context); + context = context_temp; + } +} + +#ifdef USE_GSOPEN2 +bool GLWindow::DisplayWindow(int _width, int _height) +{ + GetWindowSize(); + + if (!CreateVisual()) return false; + + // connect the glx-context to the window + CreateContextGL(); + glXMakeCurrent(glDisplay, glWindow, context); + + GetGLXVersion(); + + return true; +} +#else +bool GLWindow::DisplayWindow(int _width, int _height) +{ + backbuffer.w = _width; + backbuffer.h = _height; + + if (!CreateVisual()) return false; + + /* create a color map */ + attr.colormap = XCreateColormap(glDisplay, RootWindow(glDisplay, vi->screen), + vi->visual, AllocNone); + attr.border_pixel = 0; + attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | + StructureNotifyMask | SubstructureRedirectMask | SubstructureNotifyMask | + EnterWindowMask | LeaveWindowMask | FocusChangeMask ; + + // Create a window at the last position/size + glWindow = XCreateWindow(glDisplay, RootWindow(glDisplay, vi->screen), + conf.x , conf.y , _width, _height, 0, vi->depth, InputOutput, vi->visual, + CWBorderPixel | CWColormap | CWEventMask, + &attr); + + /* Allow to kill properly the window */ + Atom wmDelete = XInternAtom(glDisplay, "WM_DELETE_WINDOW", True); + XSetWMProtocols(glDisplay, glWindow, &wmDelete, 1); + + // Set icon name + XSetIconName(glDisplay, glWindow, "ZZogl-pg"); + + // Draw the window + XMapRaised(glDisplay, glWindow); + XSync(glDisplay, false); + + // connect the glx-context to the window + CreateContextGL(); + glXMakeCurrent(glDisplay, glWindow, context); + + GetGLXVersion(); + + // Always start in window mode + fullScreen = 0; + GetWindowSize(); + + return true; +} +#endif + +void GLWindow::SwapGLBuffers() +{ + if (glGetError() != GL_NO_ERROR) ZZLog::Debug_Log("glError before swap!"); + // FIXME I think we need to flush when there is only 1 visual buffer + glXSwapBuffers(glDisplay, glWindow); + // glClear(GL_COLOR_BUFFER_BIT); +} + +u32 THR_KeyEvent = 0; // Value for key event processing between threads +bool THR_bShift = false; +bool THR_bCtrl = false; + +void GLWindow::ProcessEvents() +{ + FUNCLOG + +#ifdef USE_GSOPEN2 + GetWindowSize(); +#else + ResizeCheck(); +#endif + + if (THR_KeyEvent) // This value was passed from GSKeyEvents which could be in another thread + { + int my_KeyEvent = THR_KeyEvent; + bool my_bShift = THR_bShift; + bool my_bCtrl = THR_bCtrl; + THR_KeyEvent = 0; + + switch (my_KeyEvent) + { + case XK_F5: + case XK_F6: + case XK_F7: + case XK_F9: + // Note: to avoid some clash with PCSX2 shortcut in GSOpen2. + // GS shortcut will only be activated when ctrl is press + if (my_bCtrl) + OnFKey(my_KeyEvent - XK_F1 + 1, my_bShift); + break; + } + } +} + + +// ************************** Function that are either stub or useless in GSOPEN2 +#define _NET_WM_STATE_REMOVE 0 +#define _NET_WM_STATE_ADD 1 +#define _NET_WM_STATE_TOGGLE 2 + +void GLWindow::Force43Ratio() +{ +#ifndef USE_GSOPEN2 + // avoid black border in fullscreen + if (fullScreen && conf.isWideScreen) { + conf.width = width; + conf.height = height; + } + + if(!fullScreen && !conf.isWideScreen) { + // Compute the width based on height + s32 new_width = (4*height)/3; + // do not bother to resize for 5 pixels. Avoid a loop + // due to round value + if ( ABS(new_width - width) > 5) { + width = new_width; + conf.width = new_width; + // resize the window + XLockDisplay(glDisplay); + XResizeWindow(glDisplay, glWindow, new_width, height); + XSync(glDisplay, False); + XUnlockDisplay(glDisplay); + } + } +#endif +} + +void GLWindow::UpdateGrabKey() +{ + // Do not stole the key in debug mode. It is not breakpoint friendly... +#ifndef _DEBUG + XLockDisplay(glDisplay); + if (fullScreen) { + XGrabPointer(glDisplay, glWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, glWindow, None, CurrentTime); + XGrabKeyboard(glDisplay, glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime); + } else { + XUngrabPointer(glDisplay, CurrentTime); + XUngrabKeyboard(glDisplay, CurrentTime); + } + XUnlockDisplay(glDisplay); +#endif +} + +void GLWindow::ToggleFullscreen() +{ +#ifndef USE_GSOPEN2 + if (!glDisplay or !glWindow) return; + + Force43Ratio(); + + u32 mask = SubstructureRedirectMask | SubstructureNotifyMask; + // Setup a new event structure + XClientMessageEvent cme; + cme.type = ClientMessage; + cme.send_event = True; + cme.display = glDisplay; + cme.window = glWindow; + cme.message_type = XInternAtom(glDisplay, "_NET_WM_STATE", False); + cme.format = 32; + // Note: can not use _NET_WM_STATE_TOGGLE because the WM can change the fullscreen state + // and screw up the fullscreen variable... The test on fulscreen restore a sane configuration + cme.data.l[0] = fullScreen ? _NET_WM_STATE_REMOVE : _NET_WM_STATE_ADD; + cme.data.l[1] = (u32)XInternAtom(glDisplay, "_NET_WM_STATE_FULLSCREEN", False); + cme.data.l[2] = 0; + cme.data.l[3] = 0; + + // send the event + XLockDisplay(glDisplay); + if (!XSendEvent(glDisplay, RootWindow(glDisplay, vi->screen), False, mask, (XEvent*)(&cme))) + ZZLog::Error_Log("Failed to send event: toggle fullscreen"); + else { + fullScreen = (!fullScreen); + conf.setFullscreen(fullScreen); + } + XUnlockDisplay(glDisplay); + + // Apply the change + XSync(glDisplay, false); + + // Wait a little that the VM does his joes. Actually the best is to check some WM event + // but it not sure it will appear so a time out is necessary. + usleep(100*1000); // 100 us should be far enough for old computer and unnoticeable for users + + // update info structure + GetWindowSize(); + + UpdateGrabKey(); + + // avoid black border in widescreen fullscreen + if (fullScreen && conf.isWideScreen) { + conf.width = width; + conf.height = height; + } + + // Hide the cursor in the right bottom corner + if(fullScreen) + XWarpPointer(glDisplay, None, glWindow, 0, 0, 0, 0, 2*width, 2*height); + +#endif +} + +void GLWindow::ResizeCheck() +{ + XEvent event; + if (!glDisplay or !glWindow) return; + + XLockDisplay(glDisplay); + while (XCheckTypedWindowEvent(glDisplay, glWindow, ConfigureNotify, &event)) + { + if ((event.xconfigure.width != width) || (event.xconfigure.height != height)) + { + width = event.xconfigure.width; + height = event.xconfigure.height; + Force43Ratio(); + UpdateWindowSize(width, height); + } + + if (!fullScreen) { + if ((event.xconfigure.x != conf.x) || (event.xconfigure.y != conf.y)) + { + // Fixme; x&y occassionally gives values near the top left corner rather then the real values, + // causing the window to change positions when adjusting ZZOgl's settings. + conf.x = event.xconfigure.x; + conf.y = event.xconfigure.y; + } + } + } + XUnlockDisplay(glDisplay); +} + +void GLWindow::SetTitle(char *strtitle) +{ +#ifndef USE_GSOPEN2 + if (!glDisplay or !glWindow) return; + if (fullScreen) return; + + XTextProperty prop; + memset(&prop, 0, sizeof(prop)); + + char* ptitle = strtitle; + if (XStringListToTextProperty(&ptitle, 1, &prop)) { + XLockDisplay(glDisplay); + XSetWMName(glDisplay, glWindow, &prop); + XUnlockDisplay(glDisplay); + } + + XFree(prop.value); +#endif +} + +#endif diff --git a/plugins/zzogl-pg-cg/opengl/GS.h b/plugins/zzogl-pg-cg/opengl/GS.h new file mode 100644 index 000000000..8bded3f4c --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/GS.h @@ -0,0 +1,987 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __GS_H__ +#define __GS_H__ + + +#define USE_OLD_REGS + +#include "Util.h" +#include "GifTransfer.h" +#include "HostMemory.h" + +using namespace std; + +extern float fFPS; + +#ifdef _MSC_VER +#define EXPORT_C_(type) extern "C" type CALLBACK +#else +#define EXPORT_C_(type) extern "C" __attribute__((externally_visible,visibility("default"))) type +#endif + +extern int g_LastCRC; + +struct Vector_16F +{ + u16 x, y, z, w; +}; + +// PS2 vertex + +// Almost same as VertexGPU, controlled by prim.fst flags + +struct Vertex +{ + u16 x, y, f, resv0; // note: xy is 12d3 + u32 rgba; + u32 z; + float s, t, q; + // Texel coordinate of vertex. Used if prim.fst == 1 + // Bits 0-14 and 16-30 of UV + u16 u, v; +}; + +struct VertexGPU +{ + // gained from XYZ2, XYZ3, XYZF2, XYZF3, + // X -- bits 0-15, Y-16-31. Z - 32-63 if no F used, 32-55 otherwise, F (fog) - 56-63 + // X, Y stored in 12d3 format, + s16 x, y; + s16 f, resv0; + + // Vertex color settings. RGB -- luminance of red/green/blue, A -- alpha. 1.0 == 0x80. + // Goes grom RGBAQ register, bits 0-7, 8-15, 16-23 and 24-31 accordingly + u32 rgba; + u32 z; + // Texture coordinates. S & T going from ST register (bits 0-31, and 32-63). + // Q goes from RGBAQ register, bits 32-63 + float s, t, q; + + void move_x(Vertex v, int offset) + { + x = ((((int)v.x - offset) >> 1) & 0xffff); + } + + void move_y(Vertex v, int offset) + { + y = ((((int)v.y - offset) >> 1) & 0xffff); + } + + void move_z(Vertex v, int mask) + { + z = (mask == 0xffff) ? min((u32)0xffff, v.z) : v.z; + } + + void move_fog(Vertex v) + { + f = ((s16)(v).f << 7) | 0x7f; + } + + void set_xy(s16 x1, s16 y1) + { + x = x1; + y = y1; + } + void set_xyz(s16 x1, s16 y1, u32 z1) + { + x = x1; + y = y1; + z = z1; + } + + void set_st(float s1, float t1) + { + s = s1; + t = t1; + } + + void set_stq(float s1, float t1, float q1) + { + s = s1; + t = t1; + q = q1; + } + + void set_xyzst(s16 x1, s16 y1, u32 z1, float s1, float t1) + { + set_xyz(x1, y1, z1); + set_st(s1, t1); + } + +}; + +extern GSconf conf; + +// PSM values +// PSM types == Texture Storage Format +enum PSM_value +{ + PSMCT32 = 0, // 00 0000 + PSMCT24 = 1, // 00 0001 + PSMCT16 = 2, // 00 0010 + PSMCT16S = 10, // 00 1010 + PSMT8 = 19, // 01 0011 + PSMT4 = 20, // 01 0100 + PSMT8H = 27, // 01 1011 + PSMT4HL = 36, // 10 0100 + PSMT4HH = 44, // 10 1100 + PSMT32Z = 48, // 11 0000 + PSMT24Z = 49, // 11 0001 + PSMT16Z = 50, // 11 0010 + PSMT16SZ = 58, // 11 1010 +}; + +// Check target bit mode. PSMCT32 and 32Z return 0, 24 and 24Z - 1 +// 16, 16S, 16Z, 16SZ -- 2, PSMT8 and 8H - 3, PSMT4, 4HL, 4HH -- 4. +// This code returns the same value on Z-textures, so texel storage mode is (BITMODE and !ISZTEX). +inline int PSMT_BITMODE(int psm) {return (psm & 0x7);} + +inline int PSMT_BITS_NUM(int psm) +{ + // Treat these as 32 bit. + if ((psm == PSMT8H) || (psm == PSMT4HL) || (psm == PSMT4HH)) + { + return 4; + } + + switch (PSMT_BITMODE(psm)) + { + case 4: + return 0; + + case 3: + return 1; + + case 2: + return 2; + + default: + return 4; + } +} + +// CLUT = Color look up table. Set proper color to table according CLUT table. +// Used for PSMT8, PSMT8H, PSMT4, PSMT4HH, PSMT4HL textures +inline bool PSMT_ISCLUT(int psm) { return (PSMT_BITMODE(psm) > 2);} + +// PSMCT16, PSMCT16S, PSMT16Z, PSMT16SZ is 16-bit targets and usually there is +// two of them in each 32-bit word. +inline bool PSMT_IS16BIT(int psm) { return (PSMT_BITMODE(psm) == 2);} + +// PSMT32Z, PSMT24Z, PSMT16Z, PSMT16SZ is Z-buffer textures +inline bool PSMT_ISZTEX(int psm) {return ((psm & 0x30) == 0x30);} + +// PSMCT16, PSMCT16S, PSMT8, PSMT8H, PSMT16Z and PSMT16SZ use only half 16 bit per pixel. +inline bool PSMT_ISHALF(int psm) {return ((psm & 2) == 2);} + +// PSMT8 and PSMT8H use IDTEX8 CLUT, PSMT4H, PSMT4HL, PSMT4HH -- IDTEX4. +// Don't use it on non clut entries, please! +inline bool PSMT_IS8CLUT(int psm) {return ((psm & 3) == 3);} + +// PSM16Z and PSMT16SZ use -1 offset to z-buff. Need to check this thesis. +inline bool PSMT_IS16Z(int psm) {return ((psm & 0x32) == 0x32);} + +// Check to see if it is 32 bits. According to code comments, anyways. +// I'll have to look closer at it, because it'd seem like it'd return true for 24 bits. +// Note: the function only works for clut format. Clut PSM is 4 bits only. The possible value are PSMCT32, PSMCT16, PSMCT16S +inline bool PSMT_IS32BIT(int psm) {return !!(psm <= 1);} + +// When color format is RGB24 (PSMCT24) or RGBA16 (PSMCT16 & 16S) alpha value expanded, based on +// TEXA register and AEM status. +inline int PSMT_ALPHAEXP(int psm) {return (psm == PSMCT24 || psm == PSMCT16 || psm == PSMCT16S);} + + +// This function updates the 6th and 5th bit of psm +// 00 or 11 -> 00 ; 01 -> 10 ; 10 -> 01 +inline int Switch_Top_Bytes (int X) { + if ( ( X & 0x30 ) == 0 ) + return X; + else + return (X ^ 0x30); +} + +// How many pixel stored in 1 word. +// PSMT8 has 4 pixels per 32bit, PSMT4 has 8. All 16-bit textures are 2 pixel per bit. And all others are 1 pixel in texture. +inline int PIXELS_PER_WORD(int psm) +{ + if (psm == PSMT8) + return 4; + if (psm == PSMT4) + return 8; + if (PSMT_IS16BIT(psm)) + return 2; + return 1; +} + +// Some storage formats could share the same memory block (2 textures in 1 format). This include following combinations: +// PSMT24(24Z) with either 8H, 4HL, 4HH and PSMT4HL with PSMT4HH. +// We use slightly different versions of this function on comparison with GSDX, Storage format XOR 0x30 made Z-textures +// similar to normal ones and change higher bits on short (8 and 4 bits) textures. +inline bool PSMT_HAS_SHARED_BITS (int fpsm, int tpsm) { + int SUM = Switch_Top_Bytes(fpsm) + Switch_Top_Bytes(tpsm) ; + return (SUM == 0x15 || SUM == 0x1D || SUM == 0x2C || SUM == 0x30); +} + +// If a clut is in 32-bit color, its size is 4 bytes, and 16-bit clut has a 2 byte size. +inline int CLUT_PIXEL_SIZE(int cpsm) {return ((cpsm <= 1) ? 4 : 2); } + +//----------------------- Data from registers ----------------------- + +typedef union +{ + s64 SD; + u64 UD; + s32 SL[2]; + u32 UL[2]; + s16 SS[4]; + u16 US[4]; + s8 SC[8]; + u8 UC[8]; +} reg64; + +/* general purpose regs structs */ + +typedef struct +{ + int fbp; + int fbw; + int fbh; + int psm; + u32 fbm; +} frameInfo; + +// Create frame structure from known data +inline frameInfo CreateFrame(int fbp, int fbw, int fbh, int psm, u32 fbm) +{ + frameInfo frame; + frame.fbp = fbp; + frame.fbw = fbw; + frame.fbh = fbh; + frame.psm = psm; + frame.fbm = fbm; + return frame; +} + +typedef struct +{ + u16 prim; + + union + { + struct + { + u16 iip : 1; + u16 tme : 1; + u16 fge : 1; + u16 abe : 1; + u16 aa1 : 1; + u16 fst : 1; + u16 ctxt : 1; + u16 fix : 1; + u16 resv : 8; + }; + u16 _val; + }; +} primInfo; + +extern primInfo *prim; + +typedef union +{ + struct + { + u32 ate : 1; + u32 atst : 3; + u32 aref : 8; + u32 afail : 2; + u32 date : 1; + u32 datm : 1; + u32 zte : 1; + u32 ztst : 2; + u32 resv : 13; + }; + u32 _val; +} pixTest; + +typedef struct +{ + int bp; + int bw; + int psm; +} bufInfo; + +typedef struct +{ + int tbp0; + int tbw; + int cbp; + u16 tw, th; + u8 psm; + u8 tcc; + u8 tfx; + u8 cpsm; + u8 csm; + u8 csa; + u8 cld; +} tex0Info; + +union tex_0_info +{ + struct + { + u64 tbp0 : 14; + u64 tbw : 6; + u64 psm : 6; + u64 tw : 4; + u64 th : 4; + u64 tcc : 1; + u64 tfx : 2; + u64 cbp : 14; + u64 cpsm : 4; + u64 csm : 1; + u64 csa : 5; + u64 cld : 3; + }; + + u64 _u64; + u32 _u32[2]; + u16 _u16[4]; + u8 _u8[8]; + + tex_0_info(u64 data) { _u64 = data; } + tex_0_info(u32 data) { _u32[0] = data; _u32[1] = 0; } + tex_0_info(u32 data0, u32 data1) { _u32[0] = data0; _u32[1] = data1; } + + u32 tbw_mult() + { + if (tbw == 0) + return 64; + else + return ((u32)tbw << 6); + } + + u32 psm_fix() + { + // ZZLog::Debug_Log("psm %d\n", psm); + if (psm == 9) return 1; + + return psm; + } + + u32 tw_exp() + { + if (tw > 10) return (1 << 10); + + return (1 << tw); + } + + u32 th_exp() + { + if (th > 10) return (1 << 10); + + return (1 << th); + } + + u32 cpsm_fix() + { + return cpsm & 0xe; + } + + u32 csa_fix() + { + if (cpsm < 2) + return (csa & 0xf); + else + return (csa & 0x1f); + } +}; + +#define TEX_MODULATE 0 +#define TEX_DECAL 1 +#define TEX_HIGHLIGHT 2 +#define TEX_HIGHLIGHT2 3 + +bool SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height); +extern void SaveTex(tex0Info* ptex, int usevid); +extern char* NamedSaveTex(tex0Info* ptex, int usevid); + +typedef struct +{ + int lcm; + int mxl; + int mmag; + int mmin; + int mtba; + int l; + int k; +} tex1Info; + +typedef struct +{ + int wms; + int wmt; + int minu; + int maxu; + int minv; + int maxv; +} clampInfo; + +typedef struct +{ + int cbw; + int cou; + int cov; +} clutInfo; + +typedef struct +{ + int tbp[3]; + int tbw[3]; +} miptbpInfo; + +typedef struct +{ + u16 aem; + u8 ta[2]; + float fta[2]; +} texaInfo; + +typedef struct +{ + int sx; + int sy; + int dx; + int dy; + int diry; + int dirx; +} trxposInfo; + +typedef struct +{ + union + { + struct + { + u8 a : 2; + u8 b : 2; + u8 c : 2; + u8 d : 2; + }; + u8 abcd; + }; + + u8 fix : 8; +} alphaInfo; + +typedef struct +{ + u16 zbp; // u16 address / 64 + u8 psm; + u8 zmsk; +} zbufInfo; + +typedef struct +{ + int fba; +} fbaInfo; + +typedef struct +{ + Vertex gsvertex[4]; // circular buffer that contains the vertex + Vertex gsTriFanVertex; // Base of triangle fan primitive vertex + u32 rgba; // global color for flat shading texture + float q; + Vertex vertexregs; // accumulation buffer that collect current vertex data + + int primC; // number of verts current storing + int primIndex; // current prim index + int nTriFanVert; // remember the index of the base of triangle fan + int new_tri_fan; // 1 if we process a new triangle fan primitive. 0 otherwise + + int prac; + int dthe; + int colclamp; + int fogcol; + int smask; + int pabe; + u64 buff[2]; + int buffsize; + int cbp[2]; // internal cbp registers + + u32 CSRw; + + primInfo _prim[2]; + bufInfo srcbuf, srcbufnew; + bufInfo dstbuf, dstbufnew; + + clutInfo clut; + + texaInfo texa; + trxposInfo trxpos, trxposnew; + + int imageWtemp, imageHtemp; + + int imageTransfer; + int imageWnew, imageHnew, imageX, imageY, imageEndX, imageEndY; + + pathInfo path[4]; + GIFRegDIMX dimx; + GSMemory mem; + GSClut clut_buffer; + int primNext(int inc = 1) + { + // Note: ArraySize(gsvertex) == 2^n => modulo is replaced by an and instruction + return ((primIndex + inc) % ArraySize(gsvertex)); + } + + int primPrev(int dec = 1) + { + // Note: assert( dec <= ArraySize(gsvertex) ); + // Note: ArraySize(gsvertex) == 2^n => modulo is replaced by an and instruction + return ((primIndex + (ArraySize(gsvertex) - dec)) % ArraySize(gsvertex)); + } + + void setRGBA(u32 r, u32 g, u32 b, u32 a) + { + rgba = (r & 0xff) | + ((g & 0xff) << 8) | + ((b & 0xff) << 16) | + ((a & 0xff) << 24); + } + + inline void add_vertex(u16 x, u16 y, u32 z, u16 f) + { + vertexregs.x = x; + vertexregs.y = y; + vertexregs.z = z; + vertexregs.f = f; + if (likely(!new_tri_fan)) { + gsvertex[primIndex] = vertexregs; + } else { + gsTriFanVertex = vertexregs; + new_tri_fan = false; + } + } + + inline void add_vertex(u16 x, u16 y, u32 z) + { + vertexregs.x = x; + vertexregs.y = y; + vertexregs.z = z; + if (likely(!new_tri_fan)) { + gsvertex[primIndex] = vertexregs; + } else { + gsTriFanVertex = vertexregs; + new_tri_fan = false; + } + } +} GSinternal; + +extern GSinternal gs; + +// Note the function is used in a template parameter so it must be declared extern +// Note2: In this case extern is not compatible with __forceinline so just inline it... +extern inline u16 RGBA32to16(u32 c) +{ + return (u16)((((c) & 0x000000f8) >> 3) | + (((c) & 0x0000f800) >> 6) | + (((c) & 0x00f80000) >> 9) | + (((c) & 0x80000000) >> 16)); +} + +static __forceinline u32 RGBA16to32(u16 c) +{ + return (((c) & 0x001f) << 3) | + (((c) & 0x03e0) << 6) | + (((c) & 0x7c00) << 9) | + (((c) & 0x8000) ? 0xff000000 : 0); +} + +#if 0 +// converts float16 [0,1] to BYTE [0,255] (assumes value is in range, otherwise will take lower 8bits) +// f is a u16 +static __forceinline u16 Float16ToBYTE(u16 f) +{ + //assert( !(f & 0x8000) ); + if (f & 0x8000) return 0; + + u16 d = ((((f & 0x3ff) | 0x400) * 255) >> (10 - ((f >> 10) & 0x1f) + 15)); + + return d > 255 ? 255 : d; +} + +static __forceinline u16 Float16ToALPHA(u16 f) +{ + //assert( !(f & 0x8000) ); + if (f & 0x8000) return 0; + + // round up instead of down (crash and burn), too much and charlie breaks + u16 d = (((((f & 0x3ff) | 0x400)) * 255) >> (10 - ((f >> 10) & 0x1f) + 15)); + + d = (d) >> 1; + + return d > 255 ? 255 : d; +} + +#ifndef COLOR_ARGB +#define COLOR_ARGB(a,r,g,b) \ + ((u32)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff))) +#endif + +// assumes that positive in [1,2] (then extracts fraction by just looking at the specified bits) +#define Float16ToBYTE_2(f) ((u8)(*(u16*)&f>>2)) +#define Float16To5BIT(f) (Float16ToBYTE(f)>>3) + +#define Float16Alpha(f) (((*(u16*)&f&0x7c00)>=0x3900)?0x8000:0) // alpha is >= 1 + +// converts an array of 4 u16s to a u32 color +// f is a pointer to a u16 +#define Float16ToARGB(f) COLOR_ARGB(Float16ToALPHA(f.w), Float16ToBYTE(f.x), Float16ToBYTE(f.y), Float16ToBYTE(f.z)); + +#define Float16ToARGB16(f) (Float16Alpha(f.w)|(Float16To5BIT(f.x)<<10)|(Float16To5BIT(f.y)<<5)|Float16To5BIT(f.z)) + +// used for Z values +#define Float16ToARGB_Z(f) COLOR_ARGB((u32)Float16ToBYTE_2(f.w), Float16ToBYTE_2(f.x), Float16ToBYTE_2(f.y), Float16ToBYTE_2(f.z)) +#define Float16ToARGB16_Z(f) ((Float16ToBYTE_2(f.y)<<8)|Float16ToBYTE_2(f.z)) +#endif + + +inline float Clamp(float fx, float fmin, float fmax) +{ + if (fx < fmin) return fmin; + + return fx > fmax ? fmax : fx; +} + +// Get pixel storage format from tex0. Clutted textures store pixels in cpsm format. +inline int PIXEL_STORAGE_FORMAT(const tex0Info& tex) { + if (PSMT_ISCLUT(tex.psm)) + return tex.cpsm; + else + return tex.psm; + } + +// If pixel storage format not PSMCT24 ot PSMCT32, then it is 16-bit. +// Z-textures have 0x30 upper bits, so we eliminate them by &&(~0x30) +inline bool PSMT_ISHALF_STORAGE(const tex0Info& tex0) { return ((PIXEL_STORAGE_FORMAT(tex0) & (~0x30)) > 1); } + +//--------------------------- Inlines for bitwise ops +//--------------------------- textures +// Tex0Info (TEXD_x registers) bits, lower word +// The register is really 64-bit, but we use 2 32bit ones to represent it +// Obtain tbp0 -- Texture Buffer Base Pointer (Word Address/64) -- from data. Bits 0-13. +static __forceinline int ZZOglGet_tbp0_TexBits(u32 data) +{ + //return tex_0_info(data).tbp0; + return (data) & 0x3fff; +} + +// Obtain tbw -- Texture Buffer Width (Texels/64) -- from data, do not multiply to 64. Bits 14-19 +// ( data & 0xfc000 ) >> 14 +static __forceinline int ZZOglGet_tbw_TexBits(u32 data) +{ + //return tex_0_info(data).tbw; + return (data >> 14) & 0x3f; +} + +// Obtain tbw -- Texture Buffer Width (Texels) -- from data, do multiply to 64, never return 0. +static __forceinline int ZZOglGet_tbw_TexBitsMult(u32 data) +{ + //return text_0_info(data).tbw_mult(); + int result = ZZOglGet_tbw_TexBits(data); + + if (result == 0) + return 64; + else + return (result << 6); +} + +// Obtain psm -- Pixel Storage Format -- from data. Bits 20-25. +// (data & 0x3f00000) >> 20 +static __forceinline int ZZOglGet_psm_TexBits(u32 data) +{ + //return tex_0_info(data).psm; + return ((data >> 20) & 0x3f); +} + +// Obtain psm -- Pixel Storage Format -- from data. Bits 20-25. Fix incorrect psm == 9 +static __forceinline int ZZOglGet_psm_TexBitsFix(u32 data) +{ + //return tex_0_info(data).psm_fix(); + int result = ZZOglGet_psm_TexBits(data) ; +// ZZLog::Debug_Log("result %d", result); + + if (result == 9) result = 1; + + return result; +} + +// Obtain tw -- Texture Width (Width = 2^TW) -- from data. Bits 26-29 +// (data & 0x3c000000)>>26 +static __forceinline u16 ZZOglGet_tw_TexBits(u32 data) +{ + //return tex_0_info(data).tw; + return ((data >> 26) & 0xf); +} + +// Obtain tw -- Texture Width (Width = TW) -- from data. Width could newer be more than 1024. +static __forceinline u16 ZZOglGet_tw_TexBitsExp(u32 data) +{ + //return tex_0_info(data).tw_exp(); + u16 result = ZZOglGet_tw_TexBits(data); + + if (result > 10) result = 10; + + return (1 << result); +} + +// TH set at the border of upper and higher words. +// Obtain th -- Texture Height (Height = 2^TH) -- from data. Bits 30-31 lower, 0-1 higher +// (dataLO & 0xc0000000) >> 30 + (dataHI & 0x3) * 0x4 +static __forceinline u16 ZZOglGet_th_TexBits(u32 dataLO, u32 dataHI) +{ + //return tex_0_info(dataLO, dataHI).th; + return (((dataLO >> 30) & 0x3) | ((dataHI & 0x3) << 2)); +} + +// Obtain th --Texture Height (Height = 2^TH) -- from data. Height could newer be more than 1024. +static __forceinline u16 ZZOglGet_th_TexBitsExp(u32 dataLO, u32 dataHI) +{ + //return tex_0_info(dataLO, dataHI).th_exp(); + u16 result = ZZOglGet_th_TexBits(dataLO, dataHI); + + if (result > 10) result = 10; + + return (1 << result); +} + +// Tex0Info bits, higher word. +// Obtain tcc -- Texture Color Component 0=RGB, 1=RGBA + use Alpha from TEXA reg when not in PSM -- from data. Bit 3 +// (data & 0x4)>>2 +static __forceinline u8 ZZOglGet_tcc_TexBits(u32 data) +{ + //return tex_0_info(0, data).tcc; + return ((data >> 2) & 0x1); +} + +// Obtain tfx -- Texture Function (0=modulate, 1=decal, 2=hilight, 3=hilight2) -- from data. Bit 4-5 +// (data & 0x18)>>3 +static __forceinline u8 ZZOglGet_tfx_TexBits(u32 data) +{ + //return tex_0_info(0, data).tfx; + return ((data >> 3) & 0x3); +} + +// Obtain cbp from data -- Clut Buffer Base Pointer (Address/256) -- Bits 5-18 +// (data & 0x7ffe0)>>5 +static __forceinline int ZZOglGet_cbp_TexBits(u32 data) +{ + //return tex_0_info(0, data).cbp; + return ((data >> 5) & 0x3fff); +} + +// Obtain cpsm from data -- Clut pixel Storage Format -- Bits 19-22. 22nd is at no use. +// (data & 0x700000)>>19 +// 0000 - psmct32; 0010 - psmct16; 1010 - psmct16s. +static __forceinline u8 ZZOglGet_cpsm_TexBits(u32 data) +{ + //return (tex_0_info(0, data).cpsm & 0xe); + return ((data >> 19) & 0xe); +} + +// Obtain csm -- I don't know what is it -- from data. Bit 23 +// (data & 0x800000)>>23 +// csm is the clut storage mode. 0 for CSM1, 1 for CSM2. +static __forceinline u8 ZZOglGet_csm_TexBits(u32 data) +{ + //return tex_0_info(0, data).csm; + return ((data >> 23) & 0x1); +} + +// Obtain csa -- -- from data. Bits 24-28 +// (data & 0x1f000000)>>24 +static __forceinline u8 ZZOglGet_csa_TexBits(u32 data) +{ + //return tex_0_info(0, data).csa_fix(); + + if ((data & 0x700000) == 0) // it is cpsm < 2 check + return ((data >> 24) & 0xf); + else + return ((data >> 24) & 0x1f); +} + +// Obtain cld -- -- from data. Bits 29-31 +// (data & 0xe0000000)>>29 +static __forceinline u8 ZZOglGet_cld_TexBits(u32 data) +{ + //return tex_0_info(0, data).cld; + return ((data >> 29) & 0x7); +} + +//-------------------------- frames +// FrameInfo bits. +// Obtain fbp -- frame Buffer Base Pointer (Word Address/2048) -- from data. Bits 0-15 +inline int ZZOglGet_fbp_FrameBits(u32 data) +{ + return ((data) & 0x1ff); +} + +// So we got address / 64, henceby frame fbp and tex tbp have the same dimension -- "real address" is x64. +inline int ZZOglGet_fbp_FrameBitsMult(u32 data) +{ + return (ZZOglGet_fbp_FrameBits(data) << 5); +} + +// Obtain fbw -- width (Texels/64) -- from data. Bits 16-23 +inline int ZZOglGet_fbw_FrameBits(u32 data) +{ + return ((data >> 16) & 0x3f); +} + +inline int ZZOglGet_fbw_FrameBitsMult(u32 data) +{ + return (ZZOglGet_fbw_FrameBits(data) << 6); +} + + +// Obtain psm -- Pixel Storage Format -- from data. Bits 24-29. +// (data & 0x3f000000) >> 24 +inline int ZZOglGet_psm_FrameBits(u32 data) +{ + return ((data >> 24) & 0x3f); +} + +// Function for calculating overal height from frame data. +inline int ZZOgl_fbh_Calc(int fbp, int fbw, int psm) +{ + int fbh = (1024 * 1024 - 64 * fbp) / fbw; + fbh &= ~0x1f; + + if (PSMT_ISHALF(psm)) fbh *= 2; + if (fbh > 1024) fbh = 1024; + + //ZZLog::Debug_Log("ZZOgl_fbh_Calc: 0x%x", fbh); + return fbh; +} + +inline int ZZOgl_fbh_Calc(frameInfo frame) +{ + return ZZOgl_fbh_Calc(frame.fbp, frame.fbw, frame.psm); +} + +// Calculate fbh from data, It does not set in register +inline int ZZOglGet_fbh_FrameBitsCalc(u32 data) +{ + int fbh = 0; + int fbp = ZZOglGet_fbp_FrameBits(data); + int fbw = ZZOglGet_fbw_FrameBits(data); + int psm = ZZOglGet_psm_FrameBits(data); + + if (fbw > 0) fbh = ZZOgl_fbh_Calc(fbp, fbw, psm) ; + + return fbh ; +} + +// Obtain fbm -- frame mask -- from data. All higher word. +inline u32 ZZOglGet_fbm_FrameBits(u32 data) +{ + return (data); +} + +// Obtain fbm -- frame mask -- from data. All higher word. Fixed from psm == PCMT24 (without alpha) +inline u32 ZZOglGet_fbm_FrameBitsFix(u32 dataLO, u32 dataHI) +{ + if (PSMT_BITMODE(ZZOglGet_psm_FrameBits(dataLO)) == 1) + return (dataHI | 0xff000000); + else + return dataHI; +} + +// obtain colormask RED +inline u32 ZZOglGet_fbmRed_FrameBits(u32 data) +{ + return (data & 0xff); +} + +// obtain colormask Green +inline u32 ZZOglGet_fbmGreen_FrameBits(u32 data) +{ + return ((data >> 8) & 0xff); +} + +// obtain colormask Blue +inline u32 ZZOglGet_fbmBlue_FrameBits(u32 data) +{ + return ((data >> 16) & 0xff); +} + +// obtain colormask Alpha +inline u32 ZZOglGet_fbmAlpha_FrameBits(u32 data) +{ + return ((data >> 24) & 0xff); +} + +// obtain colormask Alpha +inline u32 ZZOglGet_fbmHighByte(u32 data) +{ + return (!!(data & 0x80000000)); +} + +//-------------------------- tex0 comparison +// Check if old and new tex0 registers have only clut difference +inline bool ZZOglAllExceptClutIsSame(const u32* oldtex, const u32* newtex) +{ + return ((oldtex[0] == newtex[0]) && ((oldtex[1] & 0x1f) == (newtex[1] & 0x1f))); +} + +// Check if the CLUT registers are same, except CLD +inline bool ZZOglClutMinusCLDunchanged(const u32* oldtex, const u32* newtex) +{ + return ((oldtex[1] & 0x1fffffe0) == (newtex[1] & 0x1fffffe0)); +} + +// Check if CLUT storage mode is not changed (CSA, CSM and CSPM) +inline bool ZZOglClutStorageUnchanged(const u32* oldtex, const u32* newtex) +{ + return ((oldtex[1] & 0x1ff10000) == (newtex[1] & 0x1ff10000)); +} + +// call to load CLUT data (depending on CLD) +void texClutWrite(int ctx); + +// Perform clutting for flushed texture. Better check if it needs a prior call. +inline void CluttingForFlushedTex(tex0Info* tex0, u32 Data, int ictx) +{ + tex0->cbp = ZZOglGet_cbp_TexBits(Data); + tex0->cpsm = ZZOglGet_cpsm_TexBits(Data); + tex0->csm = ZZOglGet_csm_TexBits(Data); + tex0->csa = ZZOglGet_csa_TexBits(Data); + tex0->cld = ZZOglGet_cld_TexBits(Data); + + texClutWrite(ictx); + }; + +// CSA and CPSM bitmask 0001 1111 0111 1000 ... +// 60 56 52 +#define CPSM_CSA_BITMASK 0x1f780000 +#define CPSM_CSA_NOTMASK 0xe0870000 + +#endif diff --git a/plugins/zzogl-pg-cg/opengl/GSDump.cpp b/plugins/zzogl-pg-cg/opengl/GSDump.cpp new file mode 100644 index 000000000..1da9a63fd --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/GSDump.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2007-2009 Gabest + * http://www.gabest.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "GSDump.h" + +GSDump::GSDump() + : m_gs(NULL) + , m_frames(0) +{ +} + +GSDump::~GSDump() +{ + Close(); +} + +void GSDump::Open(const string& fn, u32 crc, const freezeData& fd, u8* regs) +{ + if (m_gs) return; + + m_gs = fopen(fn.c_str(), "wb"); + + m_frames = 0; + + if(m_gs) + { + fwrite(&crc, 4, 1, m_gs); + fwrite(&fd.size, 4, 1, m_gs); + fwrite(fd.data, fd.size, 1, m_gs); + fwrite(regs, 0x2000, 1, m_gs); + } +} + +void GSDump::Close() +{ + if(m_gs) { + fclose(m_gs); + m_gs = NULL; + fprintf(stderr, "Closing GS dump"); + } +} + +void GSDump::Transfer(int index, const u8* mem, size_t size) +{ + if(m_gs && size > 0) + { + fputc(0, m_gs); + fputc(index, m_gs); + fwrite(&size, 4, 1, m_gs); + fwrite(mem, size, 1, m_gs); + } +} + +void GSDump::ReadFIFO(u32 size) +{ + if(m_gs && size > 0) + { + fputc(2, m_gs); + fwrite(&size, 4, 1, m_gs); + } +} + +void GSDump::VSync(int field, bool last, u8* regs) +{ + if(m_gs) + { + fputc(3, m_gs); + fwrite(regs, 0x2000, 1, m_gs); + + fputc(1, m_gs); + fputc(field, m_gs); + + if((++m_frames & 1) == 0 && last) + { + Close(); + } + } +} diff --git a/plugins/zzogl-pg-cg/opengl/GSDump.h b/plugins/zzogl-pg-cg/opengl/GSDump.h new file mode 100644 index 000000000..68c2a5c19 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/GSDump.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2007-2009 Gabest + * http://www.gabest.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#pragma once + +#include "Util.h" + +using namespace std; + +/* + +Dump file format: +- [crc/4] [state size/4] [state data/size] [PMODE/0x2000] [id/1] [data/?] .. [id/1] [data/?] + +Transfer data (id == 0) +- [0/1] [path index/1] [size/4] [data/size] + +VSync data (id == 1) +- [1/1] [field/1] + +ReadFIFO2 data (id == 2) +- [2/1] [size/?] + +Regs data (id == 3) +- [PMODE/0x2000] + +*/ + +class GSDump +{ + FILE* m_gs; + int m_frames; + +public: + GSDump(); + virtual ~GSDump(); + + void Open(const string& fn, u32 crc, const freezeData& fd, u8* regs); + void Close(); + void ReadFIFO(u32 size); + void Transfer(int index, const u8* mem, size_t size); + void VSync(int field, bool last, u8* regs); + operator bool() {return m_gs != NULL;} +}; + +extern GSDump g_dump; + diff --git a/plugins/zzogl-pg-cg/opengl/GSmain.cpp b/plugins/zzogl-pg-cg/opengl/GSmain.cpp new file mode 100644 index 000000000..af8a59173 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/GSmain.cpp @@ -0,0 +1,801 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "Util.h" +#include "GS.h" +#include "Profile.h" +#include "GLWin.h" +#include "ZZoglFlushHack.h" + + +using namespace std; + +extern void SaveSnapshot(const char* filename); + +#ifdef _MSC_VER +#pragma warning(disable:4244) +#endif + +GLWindow GLWin; +GSinternal gs; +GSconf conf; +GSDump g_dump; + +int ppf, g_GSMultiThreaded, CurrentSavestate = 0; +int g_LastCRC = 0, g_TransferredToGPU = 0, s_frameskipping = 0; +int g_SkipFlushFrame = 0; +GetSkipCount GetSkipCount_Handler = 0; + +int UPDATE_FRAMES = 16, g_nFrame = 0, g_nRealFrame = 0; +float fFPS = 0; + +void (*GSirq)(); +u8* g_pBasePS2Mem = NULL; +wxString s_strIniPath(L"inis"); // Air's new ini path (r2361) + +bool SaveStateExists = true; // We could not know save slot status before first change occured +const char* SaveStateFile = NULL; // Name of SaveFile for access check. + +extern const char* s_aa[5]; +extern const char* pbilinear[]; +// statistics +u32 g_nGenVars = 0, g_nTexVars = 0, g_nAlphaVars = 0, g_nResolve = 0; + +#define VER 3 +const unsigned char zgsversion = PS2E_GS_VERSION; +unsigned char zgsrevision = 0; // revision and build gives plugin version +unsigned char zgsbuild = VER; +unsigned char zgsminor = 0; + +#ifdef _DEBUG +char *libraryName = "ZZ Ogl PG (Debug) "; +#elif defined(ZEROGS_DEVBUILD) +char *libraryName = "ZZ Ogl PG (Dev)"; +#else +char *libraryName = "ZZ Ogl PG "; +#endif + +extern int g_nPixelShaderVer, g_nFrameRender, g_nFramesSkipped; + +extern void WriteAA(); +extern void WriteBilinear(); +extern void ZZDestroy(); +extern bool ZZCreate(int width, int height); +extern void ZZGSStateReset(); +extern int ZZSave(s8* pbydata); +extern bool ZZLoad(s8* pbydata); + +// switches the render target to the real target, flushes the current render targets and renders the real image +extern void RenderCRTC(int interlace); + +#if defined(_WIN32) && defined(_DEBUG) +HANDLE g_hCurrentThread = NULL; +#endif + +extern int VALIDATE_THRESH; +extern u32 TEXDESTROY_THRESH; + +u32 CALLBACK PS2EgetLibType() +{ + return PS2E_LT_GS; +} + +char* CALLBACK PS2EgetLibName() +{ + return libraryName; +} + +u32 CALLBACK PS2EgetLibVersion2(u32 type) +{ + return (zgsversion << 16) | (zgsrevision << 8) | zgsbuild | (zgsminor << 24); +} + +void CALLBACK GSsetBaseMem(void* pmem) +{ + g_pBasePS2Mem = (u8*)pmem; +} + +void CALLBACK GSsetSettingsDir(const char* dir) +{ + s_strIniPath = (dir == NULL) ? wxString(L"inis") : wxString(dir, wxConvFile); +} + +void CALLBACK GSsetLogDir(const char* dir) +{ + ZZLog::SetDir(dir); +} + +void CALLBACK GSsetGameCRC(int crc, int options) +{ + // build a list of function pointer for GetSkipCount (SkipDraw) + static GetSkipCount GSC_list[NUMBER_OF_TITLES]; + static bool inited = false; + + if (!inited) + { + inited = true; + + memset(GSC_list, 0, sizeof(GSC_list)); + + GSC_list[Okami] = GSC_Okami; + GSC_list[MetalGearSolid3] = GSC_MetalGearSolid3; + GSC_list[DBZBT2] = GSC_DBZBT2; + GSC_list[DBZBT3] = GSC_DBZBT3; + GSC_list[SFEX3] = GSC_SFEX3; + GSC_list[Bully] = GSC_Bully; + GSC_list[BullyCC] = GSC_BullyCC; + GSC_list[SoTC] = GSC_SoTC; + GSC_list[OnePieceGrandAdventure] = GSC_OnePieceGrandAdventure; + GSC_list[OnePieceGrandBattle] = GSC_OnePieceGrandBattle; + GSC_list[ICO] = GSC_ICO; + GSC_list[GT4] = GSC_GT4; + GSC_list[WildArms4] = GSC_WildArms4; + GSC_list[WildArms5] = GSC_WildArms5; + GSC_list[Manhunt2] = GSC_Manhunt2; + GSC_list[CrashBandicootWoC] = GSC_CrashBandicootWoC; + GSC_list[ResidentEvil4] = GSC_ResidentEvil4; + GSC_list[Spartan] = GSC_Spartan; + GSC_list[AceCombat4] = GSC_AceCombat4; + GSC_list[Drakengard2] = GSC_Drakengard2; + GSC_list[Tekken5] = GSC_Tekken5; + GSC_list[IkkiTousen] = GSC_IkkiTousen; + GSC_list[GodOfWar] = GSC_GodOfWar; + GSC_list[GodOfWar2] = GSC_GodOfWar2; + GSC_list[GiTS] = GSC_GiTS; + GSC_list[Onimusha3] = GSC_Onimusha3; + GSC_list[TalesOfAbyss] = GSC_TalesOfAbyss; + GSC_list[SonicUnleashed] = GSC_SonicUnleashed; + GSC_list[Genji] = GSC_Genji; + GSC_list[StarOcean3] = GSC_StarOcean3; + GSC_list[ValkyrieProfile2] = GSC_ValkyrieProfile2; + GSC_list[RadiataStories] = GSC_RadiataStories; + } + + // TEXDESTROY_THRESH starts out at 16. + VALIDATE_THRESH = 8; + conf.mrtdepth = (conf.settings().disable_mrt_depth != 0); + + if (!conf.mrtdepth) + ZZLog::WriteLn("Disabling MRT depth writing."); + else + ZZLog::WriteLn("Enabling MRT depth writing."); + + bool CRCValueChanged = (g_LastCRC != crc); + + g_LastCRC = crc; + + if (crc != 0) ZZLog::WriteLn("Current game CRC is %x.", crc); + + if (CRCValueChanged && (crc != 0)) + { + for (int i = 0; i < GAME_INFO_INDEX; i++) + { + if (crc_game_list[i].crc == crc) + { + ZZLog::WriteLn("Found CRC[%x] in crc game list.", crc); + + if (crc_game_list[i].v_thresh > 0) + { + VALIDATE_THRESH = crc_game_list[i].v_thresh; + ZZLog::WriteLn("Setting VALIDATE_THRESH to %d", VALIDATE_THRESH); + } + + if (crc_game_list[i].t_thresh > 0) + { + TEXDESTROY_THRESH = crc_game_list[i].t_thresh; + ZZLog::WriteLn("Setting TEXDESTROY_THRESH to %d", TEXDESTROY_THRESH); + } + + // FIXME need to check SkipDraw is positive (enabled by users) + GetSkipCount_Handler = GSC_list[crc_game_list[i].title]; + + if (!conf.disableHacks) + { + conf.def_hacks._u32 |= crc_game_list[i].flags; + ListHacks(); + } + return; + } + } + } + ListHacks(); +} + +void CALLBACK GSsetFrameSkip(int frameskip) +{ + FUNCLOG + s_frameskipping |= frameskip; + + if (frameskip && g_nFrameRender > 1) + { + SetFrameSkip(true); + } + else if (!frameskip && g_nFrameRender <= 0) + { + SetFrameSkip(false); + } +} + +void CALLBACK GSreset() +{ + FUNCLOG + + memset(&gs, 0, sizeof(gs)); + + ZZGSStateReset(); + + gs.prac = 1; + prim = &gs._prim[0]; + gs.imageTransfer = -1; + gs.q = 1; +} + +void CALLBACK GSgifSoftReset(u32 mask) +{ + FUNCLOG + + if (mask & 1) memset(&gs.path[0], 0, sizeof(gs.path[0])); + if (mask & 2) memset(&gs.path[1], 0, sizeof(gs.path[1])); + if (mask & 4) memset(&gs.path[2], 0, sizeof(gs.path[2])); + + gs.imageTransfer = -1; + gs.q = 1; +} + +s32 CALLBACK GSinit() +{ + FUNCLOG + + ZZLog::Open(); + ZZLog::WriteLn("Calling GSinit."); + + WriteTempRegs(); + GSreset(); + + ZZLog::WriteLn("GSinit finished."); + return 0; +} + +__forceinline void InitMisc() +{ + WriteBilinear(); + WriteAA(); + InitProfile(); + InitPath(); + ResetRegs(); +} + +s32 CALLBACK GSopen(void *pDsp, char *Title, int multithread) +{ + FUNCLOG + + g_GSMultiThreaded = multithread; + + ZZLog::WriteLn("Calling GSopen."); + +#if defined(_WIN32) && defined(_DEBUG) + g_hCurrentThread = GetCurrentThread(); +#endif + + LoadConfig(); + strcpy(GLWin.title, Title); + + ZZLog::GS_Log("Using %s:%d.%d.%d.", libraryName, zgsrevision, zgsbuild, zgsminor); + + ZZLog::WriteLn("Creating ZZOgl window."); + if ((!GLWin.CreateWindow(pDsp)) || (!ZZCreate(conf.width, conf.height))) return -1; + + ZZLog::WriteLn("Initialization successful."); + + InitMisc(); + ZZLog::GS_Log("GSopen finished."); + return 0; +} + +#ifdef USE_GSOPEN2 +EXPORT_C_(s32) GSopen2( void* pDsp, u32 flags ) +{ + FUNCLOG + + g_GSMultiThreaded = true; + + ZZLog::WriteLn("Calling GSopen2."); + +#if defined(_WIN32) && defined(_DEBUG) + g_hCurrentThread = GetCurrentThread(); +#endif + + LoadConfig(); + + ZZLog::GS_Log("Using %s:%d.%d.%d.", libraryName, zgsrevision, zgsbuild, zgsminor); + + ZZLog::WriteLn("Capturing ZZOgl window."); + if ((!GLWin.CreateWindow(pDsp)) || (!ZZCreate(conf.width, conf.height))) return -1; + + ZZLog::WriteLn("Initialization successful."); + + InitMisc(); + ZZLog::GS_Log("GSopen2 finished."); + return 0; + +} +#endif + +void CALLBACK GSshutdown() +{ + FUNCLOG + + ZZLog::Close(); +} +void CALLBACK GSclose() +{ + FUNCLOG + + ZZDestroy(); + GLWin.CloseWindow(); + + SaveStateFile = NULL; + SaveStateExists = true; // default value + g_LastCRC = 0; +} + +void CALLBACK GSirqCallback(void (*callback)()) +{ + FUNCLOG + + GSirq = callback; +} + +void CALLBACK GSwriteCSR(u32 write) +{ + FUNCLOG + + gs.CSRw = write; +} + +#ifdef _WIN32 +#define access _access +#endif + +void CALLBACK GSchangeSaveState(int newstate, const char* filename) +{ + FUNCLOG + + char str[255]; + sprintf(str, "save state %d", newstate); + ZZAddMessage(str); + CurrentSavestate = newstate; + + SaveStateFile = filename; + SaveStateExists = (access(SaveStateFile, 0) == 0); +} + +static bool get_snapshot_filename(char *filename, char* path, const char* extension) +{ + FUNCLOG + + FILE *bmpfile; + u32 snapshotnr = 0; + + // increment snapshot value & try to get filename + + for (;;) + { + snapshotnr++; + + sprintf(filename, "%s/snap%03ld.%s", path, snapshotnr, extension); + + bmpfile = fopen(filename, "rb"); + + if (bmpfile == NULL) break; + + fclose(bmpfile); + } + + // try opening new snapshot file + if ((bmpfile = fopen(filename, "wb")) == NULL) + { + char strdir[255]; + sprintf(strdir, "%s", path); + +#ifdef _WIN32 + CreateDirectory(wxString::FromUTF8(strdir), NULL); +#else + mkdir(path, 0777); +#endif + + if ((bmpfile = fopen(filename, "wb")) == NULL) return false; + } + + fclose(bmpfile); + + return true; +} + +void CALLBACK GSmakeSnapshot(char *path) +{ + FUNCLOG + + char filename[256]; + if (get_snapshot_filename(filename, path, (conf.zz_options.tga_snap) ? "bmp" : "jpg")) + SaveSnapshot(filename); +} + +// I'll probably move this somewhere else later, but it's got a ton of dependencies. +static __forceinline void SetGSTitle() +{ + char strtitle[256]; + +#if !defined(ZEROGS_DEVBUILD) + const char* g_pShaders[4] = { "full", "reduced", "accurate", "accurate-reduced" }; + const char* g_pInterlace[3] = { "interlace 0 |", "interlace 1 |", "" }; + const char* g_pBilinear[3] = { "", "bilinear |", "forced bilinear |" }; + + if (SaveStateFile != NULL && !SaveStateExists) + SaveStateExists = (access(SaveStateFile, 0) == 0); + else + SaveStateExists = true; + + sprintf(strtitle, "ZZ Open GL 0.%d.%d | %.1f fps | %s%s%s savestate %d%s | shaders %s | (%.1f)", zgsbuild, zgsminor, fFPS, + g_pInterlace[conf.interlace], g_pBilinear[conf.bilinear], (conf.aa ? s_aa[conf.aa] : ""), + CurrentSavestate, (SaveStateExists ? "" : "*"), + g_pShaders[g_nPixelShaderVer], (ppf&0xfffff) / (float)UPDATE_FRAMES); + +#else + sprintf(strtitle, "%d | %.1f fps (sk:%d%%) | g: %.1f, t: %.1f, a: %.1f, r: %.1f | p: %.1f | tex: %d %d (%d kbpf)", g_nFrame, fFPS, + 100*g_nFramesSkipped / g_nFrame, + g_nGenVars / (float)UPDATE_FRAMES, g_nTexVars / (float)UPDATE_FRAMES, g_nAlphaVars / (float)UPDATE_FRAMES, + g_nResolve / (float)UPDATE_FRAMES, (ppf&0xfffff) / (float)UPDATE_FRAMES, + g_MemTargs.listTargets.size(), g_MemTargs.listClearedTargets.size(), g_TransferredToGPU >> 10); + + //_snprintf(strtitle, 512, "%x %x", *(int*)(g_pbyGSMemory + 256 * 0x3e0c + 4), *(int*)(g_pbyGSMemory + 256 * 0x3e04 + 4)); +#endif + +// if( g_nFrame > 100 && fFPS > 60.0f ) { +// ZZLog::Debug_Log("Set profile."); +// g_bWriteProfile = 1; +// } + GLWin.SetTitle(strtitle); +} + +void CALLBACK GSvsync(int interlace) +{ + FUNCLOG + + //ZZLog::GS_Log("Calling GSvsync."); + + static u32 dwTime = timeGetTime(); + static int nToNextUpdate = 1; +#ifdef _DEBUG + if (conf.dump & 0x1) { + freezeData fd; + fd.size = ZZSave(NULL); + s8* payload = (s8*)malloc(fd.size); + fd.data = payload; + + ZZSave(fd.data); + + char filename[256]; + // FIXME, there is probably a better solution than /tmp ... + // A possibility will be to save the path from GSmakeSnapshot but you still need to call + // GSmakeSnapshot first. + if (get_snapshot_filename(filename, "/tmp", "gs")) + g_dump.Open(filename, g_LastCRC, fd, g_pBasePS2Mem); + conf.dump--; + } + g_dump.VSync(interlace, (conf.dump == 0), g_pBasePS2Mem); +#endif + + GL_REPORT_ERRORD(); + + g_nRealFrame++; + + // !interlace? Hmmm... Fixme. + RenderCRTC(!interlace); + + GLWin.ProcessEvents(); + + if (--nToNextUpdate <= 0) + { + u32 d = timeGetTime(); + fFPS = UPDATE_FRAMES * 1000.0f / (float)max(d - dwTime, (u32)1); + dwTime = d; + g_nFrame += UPDATE_FRAMES; +#ifndef USE_GSOPEN2 + // let PCSX2 manage the title + SetGSTitle(); +#endif + +// if( g_nFrame > 100 && fFPS > 60.0f ) { +// ZZLog::Debug_Log("Set profile."); +// g_bWriteProfile = 1; +// } + + if (fFPS < 16) + UPDATE_FRAMES = 4; + else if (fFPS < 32) + UPDATE_FRAMES = 8; + else + UPDATE_FRAMES = 16; + + nToNextUpdate = UPDATE_FRAMES; + + ppf = 0; + g_TransferredToGPU = 0; + g_nGenVars = 0; + g_nTexVars = 0; + g_nAlphaVars = 0; + g_nResolve = 0; + g_nFramesSkipped = 0; + g_SkipFlushFrame = 0; + } + +#if defined(ZEROGS_DEVBUILD) + if (g_bWriteProfile) + { + //g_bWriteProfile = 0; + DVProfWrite("prof.txt", UPDATE_FRAMES); + DVProfClear(); + } + +#endif + GL_REPORT_ERRORD(); + +} + +void CALLBACK GSreadFIFO(u64 *pMem) +{ + FUNCLOG + + //ZZLog::GS_Log("Calling GSreadFIFO."); +#ifdef _DEBUG + g_dump.ReadFIFO(1); +#endif + + TransferLocalHost((u32*)pMem, 1); +} + +void CALLBACK GSreadFIFO2(u64 *pMem, int qwc) +{ + FUNCLOG + + //ZZLog::GS_Log("Calling GSreadFIFO2."); +#ifdef _DEBUG + g_dump.ReadFIFO(qwc); +#endif + + TransferLocalHost((u32*)pMem, qwc); +} + +int CALLBACK GSsetupRecording(int start, void* pData) +{ + FUNCLOG + + if (start) + StartCapture(); + else + StopCapture(); + + return 1; +} + +s32 CALLBACK GSfreeze(int mode, freezeData *data) +{ + FUNCLOG + + switch (mode) + { + case FREEZE_LOAD: + if (!ZZLoad(data->data)) ZZLog::Error_Log("GS: Bad load format!"); + g_nRealFrame += 100; + break; + + case FREEZE_SAVE: + ZZSave(data->data); + break; + + case FREEZE_SIZE: + data->size = ZZSave(NULL); + break; + + default: + break; + } + + return 0; +} + +#ifdef __LINUX__ + +struct Packet +{ + u8 type, param; + u32 size, addr; + vector buff; +}; + +EXPORT_C_(void) GSReplay(char* lpszCmdLine) +{ + if(FILE* fp = fopen(lpszCmdLine, "rb")) + { + GSinit(); + + u8 regs[0x2000]; + GSsetBaseMem(regs); + + //s_vsync = !!theApp.GetConfig("vsync", 0); + + void* hWnd = NULL; + + //_GSopen((void**)&hWnd, "", renderer); + GSopen((void**)&hWnd, "", 0); + + u32 crc; + fread(&crc, 4, 1, fp); + GSsetGameCRC(crc, 0); + + freezeData fd; + fread(&fd.size, 4, 1, fp); + fd.data = new s8[fd.size]; + fread(fd.data, fd.size, 1, fp); + GSfreeze(FREEZE_LOAD, &fd); + delete [] fd.data; + + fread(regs, 0x2000, 1, fp); + + long start = ftell(fp); + + GSvsync(1); + + list packets; + vector buff; + int type; + + while((type = fgetc(fp)) != EOF) + { + Packet* p = new Packet(); + + p->type = (u8)type; + + switch(type) + { + case 0: + + p->param = (u8)fgetc(fp); + + fread(&p->size, 4, 1, fp); + + switch(p->param) + { + case 0: + p->buff.resize(0x4000); + p->addr = 0x4000 - p->size; + fread(&p->buff[p->addr], p->size, 1, fp); + break; + case 1: + case 2: + case 3: + p->buff.resize(p->size); + fread(&p->buff[0], p->size, 1, fp); + break; + } + + break; + + case 1: + + p->param = (u8)fgetc(fp); + + break; + + case 2: + + fread(&p->size, 4, 1, fp); + + break; + + case 3: + + p->buff.resize(0x2000); + + fread(&p->buff[0], 0x2000, 1, fp); + + break; + + default: assert(0); + } + + packets.push_back(p); + } + + sleep(1); + + //while(IsWindowVisible(hWnd)) + //FIXME map? + int finished = 2; + while(finished > 0) + { + unsigned long start = timeGetTime(); + unsigned long frame_number = 0; + for(list::iterator i = packets.begin(); i != packets.end(); i++) + { + Packet* p = *i; + + switch(p->type) + { + case 0: + + switch(p->param) + { + case 0: GSgifTransfer1(&p->buff[0], p->addr); break; + case 1: GSgifTransfer2(&p->buff[0], p->size / 16); break; + case 2: GSgifTransfer3(&p->buff[0], p->size / 16); break; + case 3: GSgifTransfer(&p->buff[0], p->size / 16); break; + } + + break; + + case 1: + + GSvsync(p->param); + frame_number++; + + break; + + case 2: + + if(buff.size() < p->size) buff.resize(p->size); + + // FIXME + // GSreadFIFO2(&buff[0], p->size / 16); + + break; + + case 3: + + memcpy(regs, &p->buff[0], 0x2000); + + break; + } + } + unsigned long end = timeGetTime(); + fprintf(stderr, "The %d frames of the scene was render on %dms\n", frame_number, end - start); + fprintf(stderr, "A means of %fms by frame\n", (float)(end - start)/(float)frame_number); + + sleep(1); + finished--; + } + + + for(list::iterator i = packets.begin(); i != packets.end(); i++) + { + delete *i; + } + + packets.clear(); + + sleep(1); + + GSclose(); + GSshutdown(); + + fclose(fp); + } +} +#endif diff --git a/plugins/zzogl-pg-cg/opengl/GifTransfer.cpp b/plugins/zzogl-pg-cg/opengl/GifTransfer.cpp new file mode 100644 index 000000000..f8be40629 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/GifTransfer.cpp @@ -0,0 +1,284 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "GS.h" +#include "Mem.h" +#include "GifTransfer.h" + +#ifdef _DEBUG +static int path1_count = 0; +#endif + +static int nPath3Hack = 0; + +void CALLBACK GSgetLastTag(u64* ptag) +{ + FUNCLOG + + *(u32*)ptag = nPath3Hack; + nPath3Hack = 0; +} + +#ifdef _WIN32 +// for debug assertion checks (thread affinity checks) +extern HANDLE g_hCurrentThread; +#endif + +__forceinline void gifTransferLog(int index, const u32 *pMem, u32 size) +{ +#ifdef DEBUG_TRANSFER + + if (conf.log) + { + static int nSaveIndex = 0; + ZZLog::Debug_Log("%d: p:%d %x", nSaveIndex++, index + 1, size); + int vals[4] = {0}; + + for (u32 i = 0; i < size; i++) + { + for (u32 j = 0; j < 4; ++j) + vals[j] ^= pMem[4*i+j]; + } + + ZZLog::Debug_Log("%x %x %x %x", vals[0], vals[1], vals[2], vals[3]); + } + +#endif +} + +extern int g_GSMultiThreaded; + +template void _GSgifTransfer(const u32 *pMem, u32 size) +{ + FUNCLOG + + pathInfo *path = &gs.path[index]; + +#ifdef _WIN32 + assert(g_hCurrentThread == GetCurrentThread()); +#endif + +#ifdef _DEBUG + gifTransferLog(index, pMem, size); + + g_dump.Transfer(index, (const u8*)pMem, size); +#endif + + while (size > 0) + { + //LOG(_T("Transfer(%08x, %d) START\n"), pMem, size); + if (path->nloop == 0) + { + path->setTag(pMem); + pMem += 4; + size--; + + // eeuser 7.2.2. GIFtag: "... when NLOOP is 0, the GIF does not output anything, and + // values other than the EOP field are disregarded." + if (path->nloop > 0) + { + gs.q = 1.0f; + + if (path->tag.PRE && (path->tag.FLG == GIF_FLG_PACKED)) + { + u32 tagprim = path->tag.PRIM; + GIFRegHandlerPRIM((u32*)&tagprim); + } + } + } + else + { + switch (path->mode) + { + case GIF_FLG_PACKED: + { + // Needs to be looked at. + + // first try a shortcut for a very common case + + if (path->adonly && size >= path->nloop) + { + size -= path->nloop; + + do + { + GIFPackedRegHandlerA_D(pMem); + + pMem += 4; //sizeof(GIFPackedReg)/4; + } + while(--path->nloop > 0); + break; + } + + do + { + u32 reg = path->GetReg(); + g_GIFPackedRegHandlers[reg](pMem); + + pMem += 4; //sizeof(GIFPackedReg)/4; + size--; + } + while (path->StepReg() && (size > 0)); + + break; + } + + case GIF_FLG_REGLIST: + { + // Needs to be looked at. + //ZZLog::GS_Log("%8.8x%8.8x %d L", ((u32*)&gs.regs)[1], *(u32*)&gs.regs, path->tag.nreg/4); + + size *= 2; + + do + { + g_GIFRegHandlers[path->GetReg()](pMem); + + pMem += 2; + size--; + } + while (path->StepReg() && (size > 0)); + + if (size & 1) pMem += 2; + size /= 2; + break; + } + + case GIF_FLG_IMAGE: // FROM_VFRAM + case GIF_FLG_IMAGE2: // Used in the DirectX version, so we'll use it here too. + { + int len = min(size, path->nloop); + //ZZLog::Error_Log("GIF_FLG_IMAGE(%d)=%d", gs.imageTransfer, len); + + switch (gs.imageTransfer) + { + case 0: + TransferHostLocal(pMem, len * 4); + break; + + case 1: + // This can't happen; downloads can not be started or performed as part of + // a GIFtag operation. They're an entirely separate process that can only be + // done through the ReverseFIFO transfer (aka ReadFIFO). --air + assert(0); + //TransferLocalHost(pMem, len); + break; + + case 2: + //TransferLocalLocal(); + break; + + case 3: + //assert(0); + break; + + default: + //assert(0); + break; + } + + pMem += len * 4; + + path->nloop -= len; + size -= len; + + break; + } + + default: // GIF_IMAGE + ZZLog::GS_Log("*** WARNING **** Unexpected GIFTag flag."); + assert(0); + path->nloop = 0; + break; + } + } + + if (index == 0) + { + if (path->tag.EOP && path->nloop == 0) + { + break; + } + } + } + + // This is the case when not all data was readed from one try: VU1 has too much data. + // So we should redo reading from the start. + if (index == 0) + { + if (size == 0 && path->nloop > 0) + { + if (g_GSMultiThreaded) + { + path->nloop = 0; + } + else + { + _GSgifTransfer<0>(pMem - 0x4000, 0x4000 / 16); + } + } + } +} + +void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr) +{ + FUNCLOG + + //ZZLog::GS_Log("GSgifTransfer1 0x%x (mode %d).", addr, path->mode); + +#ifdef _DEBUG + ZZLog::Prim_Log("count: %d\n", path1_count); + path1_count++; +#endif + + _GSgifTransfer<0>((u32*)((u8*)pMem + addr), (0x4000 - addr) / 16); +} + +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size) +{ + FUNCLOG + + //ZZLog::GS_Log("GSgifTransfer2 size = %lx (mode %d, gs.path2.tag.nloop = %d).", size, gs.path[1].mode, gs.path[1].tag.nloop); + + _GSgifTransfer<1>(const_cast(pMem), size); +} + +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size) +{ + FUNCLOG + + //ZZLog::GS_Log("GSgifTransfer3 size = %lx (mode %d, gs.path3.tag.nloop = %d).", size, gs.path[2].mode, gs.path[2].tag.nloop); + + _GSgifTransfer<2>(const_cast(pMem), size); +} + +void CALLBACK GSgifTransfer(const u32 *pMem, u32 size) +{ + FUNCLOG + + //ZZLog::GS_Log("GSgifTransfer3 size = %lx (mode %d, gs.path3.tag.nloop = %d).", size, gs.path[2].mode, gs.path[2].tag.nloop); + + _GSgifTransfer<3>(pMem, size); +} + +void InitPath() +{ + gs.path[0].mode = gs.path[1].mode = gs.path[2].mode = gs.path[3].mode = 0; +} + diff --git a/plugins/zzogl-pg-cg/opengl/GifTransfer.h b/plugins/zzogl-pg-cg/opengl/GifTransfer.h new file mode 100644 index 000000000..533733ed0 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/GifTransfer.h @@ -0,0 +1,134 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef GIFTRANSFER_H_INCLUDED +#define GIFTRANSFER_H_INCLUDED + +#include "Util.h" +#include "GS.h" +#include "Regs.h" + +enum GIF_FLG +{ + GIF_FLG_PACKED = 0, + GIF_FLG_REGLIST = 1, + GIF_FLG_IMAGE = 2, + GIF_FLG_IMAGE2 = 3 +}; + +// +// GIFTag +union GIFTag +{ + u64 ai64[2]; + u32 ai32[4]; + + struct + { + u32 NLOOP : 15; + u32 EOP : 1; + u32 _PAD1 : 16; + u32 _PAD2 : 14; + u32 PRE : 1; + u32 PRIM : 11; + u32 FLG : 2; // enum GIF_FLG + u32 NREG : 4; + u64 REGS : 64; + }; + + void set(const u32 *data) + { + for (int i = 0; i <= 3; i++) + { + ai32[i] = data[i]; + } + } + + GIFTag(u32 *data) + { + set(data); + } + + GIFTag(){ ai64[0] = 0; ai64[1] = 0; } +}; + +// EE part. Data transfer packet description + +typedef struct +{ + u32 mode; + int reg; + u64 regs; + u32 nloop; + int eop; + int nreg; + u32 adonly; + GIFTag tag; + + void setTag(const u32 *data) + { + tag.set(data); + + nloop = tag.NLOOP; + eop = tag.EOP; + mode = tag.FLG; + adonly = false; + + // Hmm.... + nreg = tag.NREG << 2; + if (nreg == 0) nreg = 64; + regs = tag.REGS; + reg = 0; + if ((nreg == 4) && (regs == GIF_REG_A_D)) adonly = true; + + // ZZLog::GS_Log("GIFtag: %8.8lx_%8.8lx_%8.8lx_%8.8lx: EOP=%d, NLOOP=%x, FLG=%x, NREG=%d, PRE=%d", + // data[3], data[2], data[1], data[0], + // path->eop, path->nloop, mode, path->nreg, tag.PRE); + } + + u32 GetReg() + { + return (regs >> reg) & 0xf; + } + + bool StepReg() + { + reg += 4; + + if (reg == nreg) + { + reg = 0; + nloop--; + + if (nloop == 0) return false; + } + + return true; + } + +} pathInfo; + +extern void _GSgifPacket(pathInfo *path, const u32 *pMem); +extern void _GSgifRegList(pathInfo *path, const u32 *pMem); +extern void _GSgifTransfer(pathInfo *path, const u32 *pMem, u32 size); + +extern GIFRegHandler g_GIFPackedRegHandlers[]; +extern GIFRegHandler g_GIFRegHandlers[]; +extern void InitPath(); +#endif // GIFTRANSFER_H_INCLUDED diff --git a/plugins/zzogl-pg-cg/opengl/HostMemory.cpp b/plugins/zzogl-pg-cg/opengl/HostMemory.cpp new file mode 100644 index 000000000..9b762e943 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/HostMemory.cpp @@ -0,0 +1,578 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "GS.h" +#include +#include + +#include +#include "Mem.h" +#include "x86.h" +#include "targets.h" +#include "ZZoglVB.h" + +// flush current vertices, call before setting new registers (the main render method) +extern void Flush(int context); + +u8* g_pbyGSMemory = NULL; // 4Mb GS system mem + +void GSMemory::init() +{ + const u32 mem_size = MEMORY_END + 0x10000; // leave some room for out of range accesses (saves on the checks) + + // clear + g_pbyGSMemory = (u8*)_aligned_malloc(mem_size, 1024); + memset(g_pbyGSMemory, 0, mem_size); +} + +void GSMemory::destroy() +{ + _aligned_free(g_pbyGSMemory); + g_pbyGSMemory = NULL; +} + +u8* GSMemory::get() +{ + return g_pbyGSMemory; +} + +u8* GSMemory::get(u32 addr) +{ + return &g_pbyGSMemory[addr*8]; +} +u8* GSMemory::get_raw(u32 addr) +{ + return &g_pbyGSMemory[addr]; +} + +u8* g_pbyGSClut = NULL; // ZZ + +void GSClut::init() +{ + g_pbyGSClut = (u8*)_aligned_malloc(256 * 8, 1024); // need 512 alignment! + memset(g_pbyGSClut, 0, 256*8); +} + +void GSClut::destroy() +{ + _aligned_free(g_pbyGSClut); + g_pbyGSClut = NULL; +} + +u8* GSClut::get() +{ + return g_pbyGSClut; +} + +u8* GSClut::get(u32 addr) +{ + return &g_pbyGSClut[addr*8]; +} +u8* GSClut::get_raw(u32 addr) +{ + return &g_pbyGSClut[addr]; +} + +extern _getPixelAddress getPixelFun[64]; + +extern CRangeManager s_RangeMngr; // manages overwritten memory +extern void ResolveInRange(int start, int end); + +static vector s_vTempBuffer, s_vTransferCache; +static int gs_imageEnd = 0; + +// From the start of monster labs. In all 3 cases, psm == 0. +// ZZogl-PG: GetRectMemAddress(0x3f4000, 0x404000, 0x0, 0x0, 0x0, 0x100, 0x40, 0x3f40, 0x100); +// ZZogl-PG: GetRectMemAddress(0x3f8000, 0x408000, 0x0, 0x0, 0x0, 0x100, 0x40, 0x3f80, 0x100); +// ZZogl-PG: GetRectMemAddress(0x3fc000, 0x40c000, 0x0, 0x0, 0x0, 0x100, 0x40, 0x3fc0, 0x100); + +void GetRectMemAddress(int& start, int& end, int psm, int x, int y, int w, int h, int bp, int bw) +{ + FUNCLOG + u32 bits = 0; + + if (m_Blocks[psm].bpp == 0) + { + ZZLog::Error_Log("ZeroGS: Bad psm 0x%x.", psm); + start = 0; + end = MEMORY_END; + return; + } + + if (PSMT_ISZTEX(psm)) + { + // Somehow, I doubt this code is right. I'll have to look into it. For the moment, I'm keeping it the + // way it was. --arcum42 + + const BLOCK& b = m_Blocks[psm]; + + bw = (bw + b.width - 1) / b.width; + start = bp * 256 + ((y / b.height) * bw + (x / b.width)) * 0x2000; + end = bp * 256 + (((y + h - 1) / b.height) * bw + (x + w + b.width - 1) / b.width) * 0x2000; + return; + } + + bits = PSMT_BITS_NUM(psm); + start = getPixelFun[psm](x, y, bp, bw); + end = getPixelFun[psm](x + w - 1, y + h - 1, bp, bw) + 1; + + if (bits > 0) + { + start *= bits; + end *= bits; + } + else + { + // This is what it used to do, which doesn't seem right. + // Keeping it for reference, in case removing it breaks anything. + + //int newx = ((x + w - 1 + 31) & ~31) - 1; + //int newy = ((y + h - 1 + 15) & ~15) - 1; + //start = getPixelAddress4(x, y, bp, bw) / 2; + //end = (getPixelAddress4(max(newx, x), max(newy, y), bp, bw) + 2) / 2; + + start /= 2; + end /= 2; + } +} + +void InitTransferHostLocal() +{ + FUNCLOG + +#if defined(_DEBUG) + // Xenosaga 1. + if (gs.trxpos.dx + gs.imageWnew > gs.dstbuf.bw) + ZZLog::Debug_Log("Transfer error, width exceeded. (0x%x > 0X%x)", gs.trxpos.dx + gs.imageWnew, gs.dstbuf.bw); +#endif + + //bool bHasFlushed = false; + + gs.imageX = gs.trxpos.dx; + gs.imageY = gs.trxpos.dy; + + gs.imageEndX = gs.imageX + gs.imageWnew; + gs.imageEndY = gs.imageY + gs.imageHnew; + + assert(gs.imageEndX < 2048 && gs.imageEndY < 2048); + + // This needs to be looked in to, since psm should *not* be 63. + // hack! viewful joe + if (gs.dstbuf.psm == 63) gs.dstbuf.psm = 0; + + int start, end; + + GetRectMemAddress(start, end, gs.dstbuf.psm, gs.trxpos.dx, gs.trxpos.dy, gs.imageWnew, gs.imageHnew, gs.dstbuf.bp, gs.dstbuf.bw); + + if (end > MEMORY_END) + { + // Monster Lab - the screwed up title screen + // Init host local out of bounds! (end == 0x404000) + // Init host local out of bounds! (end == 0x408000) + // Init host local out of bounds! (end == 0x40c000) + // MEMORY_END is 0x400000... + + ZZLog::Warn_Log("Init host local out of bounds! (end == 0x%x)", end); + //gs.imageTransfer = -1; + end = MEMORY_END; + } + + gs_imageEnd = end; + + if (vb[0].nCount > 0) Flush(0); + if (vb[1].nCount > 0) Flush(1); + + //ZZLog::Prim_Log("trans: bp:%x x:%x y:%x w:%x h:%x\n", gs.dstbuf.bp, gs.trxpos.dx, gs.trxpos.dy, gs.imageWnew, gs.imageHnew); +} + +void TransferHostLocal(const void* pbyMem, u32 nQWordSize) +{ + FUNCLOG + + int start, end; + + GetRectMemAddress(start, end, gs.dstbuf.psm, gs.imageX, gs.imageY, gs.imageWnew, gs.imageHnew, gs.dstbuf.bp, gs.dstbuf.bw); + + assert(start < gs_imageEnd); + end = gs_imageEnd; + + // sometimes games can decompress to alpha channel of render target only, in this case + // do a resolve right away. wolverine x2 + if (((gs.dstbuf.psm == PSMT8H) || (gs.dstbuf.psm == PSMT4HL) || (gs.dstbuf.psm == PSMT4HH)) && !(conf.settings().gust)) + { + list listTransmissionUpdateTargs; + s_RTs.GetTargs(start, end, listTransmissionUpdateTargs); + + for (list::iterator it = listTransmissionUpdateTargs.begin(); it != listTransmissionUpdateTargs.end(); ++it) + { + CRenderTarget* ptarg = *it; + + if ((ptarg->status & CRenderTarget::TS_Virtual)) continue; + + //ZZLog::Error_Log("Resolving to alpha channel."); + ptarg->Resolve(); + } + } + + s_RangeMngr.Insert(start, min(end, start + (int)nQWordSize*16)); + + const u8* porgend = (const u8*)pbyMem + 4 * nQWordSize; + + if (s_vTransferCache.size() > 0) + { + + int imagecache = s_vTransferCache.size(); + s_vTempBuffer.resize(imagecache + nQWordSize*4); + memcpy(&s_vTempBuffer[0], &s_vTransferCache[0], imagecache); + memcpy(&s_vTempBuffer[imagecache], pbyMem, nQWordSize*4); + + pbyMem = (const void*) & s_vTempBuffer[0]; + porgend = &s_vTempBuffer[0] + s_vTempBuffer.size(); + + int wordinc = imagecache / 4; + + if ((nQWordSize * 4 + imagecache) / 3 == ((nQWordSize + wordinc) * 4) / 3) + { + // can use the data + nQWordSize += wordinc; + } + } + + int leftover = m_Blocks[gs.dstbuf.psm].TransferHostLocal(pbyMem, nQWordSize); + + if (leftover > 0) + { + // copy the last gs.image24bitOffset to the cache + s_vTransferCache.resize(leftover); + memcpy(&s_vTransferCache[0], porgend - leftover, leftover); + } + else + { + s_vTransferCache.resize(0); + } + +#if defined(_DEBUG) + if (g_bSaveTrans) + { + tex0Info t; + t.tbp0 = gs.dstbuf.bp; + t.tw = gs.imageWnew; + t.th = gs.imageHnew; + t.tbw = gs.dstbuf.bw; + t.psm = gs.dstbuf.psm; + SaveTex(&t, 0); + } + +#endif +} + +void InitTransferLocalHost() +{ + FUNCLOG + assert(gs.trxpos.sx + gs.imageWnew <= 2048 && gs.trxpos.sy + gs.imageHnew <= 2048); + +#if defined(_DEBUG) + if (gs.trxpos.sx + gs.imageWnew > gs.srcbuf.bw) + ZZLog::Debug_Log("Transfer error, width exceeded. (0x%x > 0x%x)", gs.trxpos.sx + gs.imageWnew, gs.srcbuf.bw); +#endif + + gs.imageX = gs.trxpos.sx; + gs.imageY = gs.trxpos.sy; + + gs.imageEndX = gs.imageX + gs.imageWnew; + gs.imageEndY = gs.imageY + gs.imageHnew; + + s_vTransferCache.resize(0); + + int start, end; + + GetRectMemAddress(start, end, gs.srcbuf.psm, gs.trxpos.sx, gs.trxpos.sy, gs.imageWnew, gs.imageHnew, gs.srcbuf.bp, gs.srcbuf.bw); + + ResolveInRange(start, end); +} + +template +void TransferLocalHost(void* pbyMem, u32 nQWordSize, int& x, int& y, u8 *pstart) +{ + _readPixel_0 rp = readPixelFun_0[gs.srcbuf.psm]; + + int i = x, j = y; + T* pbuf = (T*)pbyMem; + u32 nSize = nQWordSize * 16 / sizeof(T); + + for (; i < gs.imageEndY; ++i) + { + for (; j < gs.imageEndX && nSize > 0; ++j, --nSize) + { + *pbuf++ = rp(pstart, j % 2048, i % 2048, gs.srcbuf.bw); + } + + if (j >= gs.imageEndX) + { + assert(j == gs.imageEndX); + j = gs.trxpos.sx; + } + else + { + assert(nSize == 0); + break; + } + } +} + +void TransferLocalHost_24(void* pbyMem, u32 nQWordSize, int& x, int& y, u8 *pstart) +{ + _readPixel_0 rp = readPixelFun_0[gs.srcbuf.psm]; + + int i = x, j = y; + u8* pbuf = (u8*)pbyMem; + u32 nSize = nQWordSize * 16 / 3; + + for (; i < gs.imageEndY; ++i) + { + for (; j < gs.imageEndX && nSize > 0; ++j, --nSize) + { + u32 p = rp(pstart, j % 2048, i % 2048, gs.srcbuf.bw); + pbuf[0] = (u8)p; + pbuf[1] = (u8)(p >> 8); + pbuf[2] = (u8)(p >> 16); + pbuf += 3; + } + + if (j >= gs.imageEndX) + { + assert(j == gs.imageEndX); + j = gs.trxpos.sx; + } + else + { + assert(nSize == 0); + break; + } + } +} + +// left/right, top/down +void TransferLocalHost(void* pbyMem, u32 nQWordSize) +{ + FUNCLOG + assert(gs.imageTransfer == 1); + + u8* pstart = g_pbyGSMemory + 256 * gs.srcbuf.bp; + + switch(PSMT_BITMODE(gs.srcbuf.psm)) + { + case 0: + TransferLocalHost(pbyMem, nQWordSize, gs.imageY, gs.imageX, pstart); + break; + case 1: + TransferLocalHost_24(pbyMem, nQWordSize, gs.imageY, gs.imageX, pstart); + break; + case 2: + TransferLocalHost(pbyMem, nQWordSize, gs.imageY, gs.imageX, pstart); + break; + case 3: + TransferLocalHost(pbyMem, nQWordSize, gs.imageY, gs.imageX, pstart); + break; + default: + assert(0); + break; + } + + if (gs.imageY >= gs.imageEndY) + { + ZZLog::Error_Log("gs.imageY >= gs.imageEndY!"); + assert(gs.imageY == gs.imageEndY); + gs.imageTransfer = -1; + } +} + +__forceinline void _TransferLocalLocal() +{ + //ZZLog::Error_Log("TransferLocalLocal(0x%x, 0x%x)", gs.srcbuf.psm, gs.dstbuf.psm); + _writePixel_0 wp = writePixelFun_0[gs.srcbuf.psm]; + _readPixel_0 rp = readPixelFun_0[gs.dstbuf.psm]; + u8* pSrcBuf = g_pbyGSMemory + gs.srcbuf.bp * 256; + u8* pDstBuf = g_pbyGSMemory + gs.dstbuf.bp * 256; + u32 widthlimit = 4; + u32 maxX = gs.trxpos.sx + gs.imageWnew; + u32 maxY = gs.trxpos.sy + gs.imageHnew; + + if (PSMT_BITMODE(gs.srcbuf.psm) == 0) widthlimit = 2; + if ((gs.imageWnew & widthlimit) != 0) return; + + for(u32 i = gs.trxpos.sy, i2 = gs.trxpos.dy; i < maxY; i++, i2++) + { + for(u32 j = gs.trxpos.sx, j2 = gs.trxpos.dx; j < maxX; j += widthlimit, j2 += widthlimit) + { + wp(pDstBuf, j2%2048, i2%2048, + rp(pSrcBuf, j%2048, i%2048, gs.srcbuf.bw), gs.dstbuf.bw); + + wp(pDstBuf, (j2+1)%2048, i2%2048, + rp(pSrcBuf, (j+1)%2048, i%2048, gs.srcbuf.bw), gs.dstbuf.bw); + + if (widthlimit > 2) + { + // Then widthlimit == 4. + wp(pDstBuf, (j2+2)%2048, i2%2048, + rp(pSrcBuf, (j+2)%2048, i%2048, gs.srcbuf.bw), gs.dstbuf.bw); + + wp(pDstBuf, (j2+3)%2048, i2%2048, + rp(pSrcBuf, (j+3)%2048, i%2048, gs.srcbuf.bw), gs.dstbuf.bw); + } + } + } +} + +__forceinline void _TransferLocalLocal_4() +{ + //ZZLog::Error_Log("TransferLocalLocal_4(0x%x, 0x%x)", gs.srcbuf.psm, gs.dstbuf.psm); + _getPixelAddress_0 gsp = getPixelFun_0[gs.srcbuf.psm]; + _getPixelAddress_0 gdp = getPixelFun_0[gs.dstbuf.psm]; + u8* pSrcBuf = g_pbyGSMemory + gs.srcbuf.bp * 256; + u8* pDstBuf = g_pbyGSMemory + gs.dstbuf.bp * 256; + u32 maxX = gs.trxpos.sx + gs.imageWnew; + u32 maxY = gs.trxpos.sy + gs.imageHnew; + + assert((gs.imageWnew % 8) == 0); + + for(u32 i = gs.trxpos.sy, i2 = gs.trxpos.dy; i < maxY; ++i, ++i2) + { + for(u32 j = gs.trxpos.sx, j2 = gs.trxpos.dx; j < maxX; j += 8, j2 += 8) + { + /* NOTE: the 2 conseq 4bit values are in NOT in the same byte */ + u32 read = gsp(j%2048, i%2048, gs.srcbuf.bw); + u32 write = gdp(j2%2048, i2%2048, gs.dstbuf.bw); + pDstBuf[write] = (pDstBuf[write]&0xf0)|(pSrcBuf[read]&0x0f); + + read = gsp((j+1)%2048, i%2048, gs.srcbuf.bw); + write = gdp((j2+1)%2048, i2%2048, gs.dstbuf.bw); + pDstBuf[write] = (pDstBuf[write]&0x0f)|(pSrcBuf[read]&0xf0); + + read = gsp((j+2)%2048, i%2048, gs.srcbuf.bw); + write = gdp((j2+2)%2048, i2%2048, gs.dstbuf.bw); + pDstBuf[write] = (pDstBuf[write]&0xf0)|(pSrcBuf[read]&0x0f); + + read = gsp((j+3)%2048, i%2048, gs.srcbuf.bw); + write = gdp((j2+3)%2048, i2%2048, gs.dstbuf.bw); + pDstBuf[write] = (pDstBuf[write]&0x0f)|(pSrcBuf[read]&0xf0); + + read = gsp((j+4)%2048, i%2048, gs.srcbuf.bw); + write = gdp((j2+4)%2048, i2%2048, gs.dstbuf.bw); + pDstBuf[write] = (pDstBuf[write]&0xf0)|(pSrcBuf[read]&0x0f); + + read = gsp((j+5)%2048, i%2048, gs.srcbuf.bw); + write = gdp((j2+5)%2048, i2%2048, gs.dstbuf.bw); + pDstBuf[write] = (pDstBuf[write]&0x0f)|(pSrcBuf[read]&0xf0); + + read = gsp((j+6)%2048, i%2048, gs.srcbuf.bw); + write = gdp((j2+6)%2048, i2%2048, gs.dstbuf.bw); + pDstBuf[write] = (pDstBuf[write]&0xf0)|(pSrcBuf[read]&0x0f); + + read = gsp((j+7)%2048, i%2048, gs.srcbuf.bw); + write = gdp((j2+7)%2048, i2%2048, gs.dstbuf.bw); + pDstBuf[write] = (pDstBuf[write]&0x0f)|(pSrcBuf[read]&0xf0); + } + } +} + +// dir depends on trxpos.dirx & trxpos.diry +void TransferLocalLocal() +{ + FUNCLOG + + //ZZLog::Error_Log("I'z in your code, transferring your memory..."); + assert(gs.imageTransfer == 2); + assert(gs.trxpos.sx + gs.imageWnew < 2048 && gs.trxpos.sy + gs.imageHnew < 2048); + assert(gs.trxpos.dx + gs.imageWnew < 2048 && gs.trxpos.dy + gs.imageHnew < 2048); + assert((gs.srcbuf.psm&0x7) == (gs.dstbuf.psm&0x7)); + + if (gs.trxpos.sx + gs.imageWnew > gs.srcbuf.bw) + ZZLog::Debug_Log("Transfer error, src width exceeded.(0x%x > 0x%x)", gs.trxpos.sx + gs.imageWnew, gs.srcbuf.bw); + + if (gs.trxpos.dx + gs.imageWnew > gs.dstbuf.bw) + ZZLog::Debug_Log("Transfer error, dst width exceeded.(0x%x > 0x%x)", gs.trxpos.dx + gs.imageWnew, gs.dstbuf.bw); + + int srcstart, srcend, dststart, dstend; + + GetRectMemAddress(srcstart, srcend, gs.srcbuf.psm, gs.trxpos.sx, gs.trxpos.sy, gs.imageWnew, gs.imageHnew, gs.srcbuf.bp, gs.srcbuf.bw); + GetRectMemAddress(dststart, dstend, gs.dstbuf.psm, gs.trxpos.dx, gs.trxpos.dy, gs.imageWnew, gs.imageHnew, gs.dstbuf.bp, gs.dstbuf.bw); + + // resolve the targs + ResolveInRange(srcstart, srcend); + + list listTargs; + + s_RTs.GetTargs(dststart, dstend, listTargs); + + for (list::iterator it = listTargs.begin(); it != listTargs.end(); ++it) + { + if (!((*it)->status & CRenderTarget::TS_Virtual)) + { + (*it)->Resolve(); + //(*it)->status |= CRenderTarget::TS_NeedUpdate; + } + } + + if (PSMT_BITMODE(gs.srcbuf.psm) != 4) + { + _TransferLocalLocal(); + } + else + { + _TransferLocalLocal_4(); + } + + g_MemTargs.ClearRange(dststart, dstend); + +#ifdef ZEROGS_DEVBUILD + + if (g_bSaveTrans) + { + tex0Info t; + t.tbp0 = gs.dstbuf.bp; + t.tw = gs.imageWnew; + t.th = gs.imageHnew; + t.tbw = gs.dstbuf.bw; + t.psm = gs.dstbuf.psm; + SaveTex(&t, 0); + + t.tbp0 = gs.srcbuf.bp; + t.tw = gs.imageWnew; + t.th = gs.imageHnew; + t.tbw = gs.srcbuf.bw; + t.psm = gs.srcbuf.psm; + SaveTex(&t, 0); + } + +#endif +} + +__forceinline void TerminateLocalHost() +{ + FUNCLOG + //ZZLog::Error_Log("Terminate Local Host!"); +} + +__forceinline void TerminateHostLocal() +{ + FUNCLOG + gs.imageTransfer = -1; +} + diff --git a/plugins/zzogl-pg-cg/opengl/HostMemory.h b/plugins/zzogl-pg-cg/opengl/HostMemory.h new file mode 100644 index 000000000..e9217685d --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/HostMemory.h @@ -0,0 +1,114 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef HOSTMEMORY_H_INCLUDED +#define HOSTMEMORY_H_INCLUDED + +#include "GLWin.h" + +#define MEMORY_END 0x00400000 + +extern int GPU_TEXWIDTH; + +extern u8* g_pBasePS2Mem; +extern u8* g_pbyGSMemory; + +class GSMemory +{ + public: + void init(); + void destroy(); + u8* get(); + u8* get(u32 addr); + u8* get_raw(u32 addr); +}; + +extern u8* g_pbyGSClut; // the temporary clut buffer + +class GSClut +{ + public: + void init(); + void destroy(); + u8* get(); + u8* get(u32 addr); + u8* get_raw(u32 addr); +}; + +class ZeroGSInit +{ + + public: + ZeroGSInit() + { + const u32 mem_size = MEMORY_END + 0x10000; // leave some room for out of range accesses (saves on the checks) + // clear + g_pbyGSMemory = (u8*)_aligned_malloc(mem_size, 1024); + memset(g_pbyGSMemory, 0, mem_size); + + g_pbyGSClut = (u8*)_aligned_malloc(256 * 8, 1024); // need 512 alignment! + memset(g_pbyGSClut, 0, 256*8); + memset(&GLWin, 0, sizeof(GLWin)); + } + + ~ZeroGSInit() + { + _aligned_free(g_pbyGSMemory); + g_pbyGSMemory = NULL; + + _aligned_free(g_pbyGSClut); + g_pbyGSClut = NULL; + } +}; + +// The size in bytes of x strings (of texture). +inline int MemorySize(int x) +{ + return 4 * GPU_TEXWIDTH * x; +} + +// Return the address in memory of data block for string x. +inline u8* MemoryAddress(int x) +{ + return g_pbyGSMemory + MemorySize(x); +} + +template +inline u8* _MemoryAddress(int x) +{ + return g_pbyGSMemory + mult * x; +} + +extern void GetRectMemAddress(int& start, int& end, int psm, int x, int y, int w, int h, int bp, int bw); + + +// called when trxdir is accessed. If host is involved, transfers memory to temp buffer byTransferBuf. +// Otherwise performs the transfer. TODO: Perhaps divide the transfers into chunks? +extern void InitTransferHostLocal(); +extern void TransferHostLocal(const void* pbyMem, u32 nQWordSize); + +extern void InitTransferLocalHost(); +extern void TransferLocalHost(void* pbyMem, u32 nQWordSize); + +extern void TransferLocalLocal(); + +extern void TerminateLocalHost(); +extern void TerminateHostLocal(); + +#endif // HOSTMEMORY_H_INCLUDED diff --git a/plugins/zzogl-pg-cg/opengl/Linux/Conf.cpp b/plugins/zzogl-pg-cg/opengl/Linux/Conf.cpp new file mode 100644 index 000000000..c783aa005 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/Linux/Conf.cpp @@ -0,0 +1,121 @@ +/* GSsoft + * Copyright (C) 2002-2004 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include +#include +#include "GS.h" +#include "Utilities/Path.h" + +void SaveConfig() +{ + const wxString iniFile_s(Path::Combine(s_strIniPath, L"zzogl-pg.ini")); + std::string iniFile = std::string(iniFile_s.mb_str()); + + FILE* f = fopen(iniFile.c_str(), "w"); + + if (f == NULL) + { + ZZLog::Error_Log("Failed to open '%s'", iniFile.c_str()); + return; + } + + fprintf(f, "interlace = %hhx\n", conf.interlace); + + fprintf(f, "mrtdepth = %hhx\n", conf.mrtdepth); + fprintf(f, "zzoptions = %x\n", conf.zz_options._u32); + fprintf(f, "options = %x\n", conf.hacks._u32); + fprintf(f, "bilinear = %hhx\n", conf.bilinear); + fprintf(f, "aliasing = %hhx\n", conf.aa); + fprintf(f, "width = %x\n", conf.width); + fprintf(f, "height = %x\n", conf.height); + fprintf(f, "x = %x\n", conf.x); + fprintf(f, "y = %x\n", conf.y); + fprintf(f, "log = %x\n", conf.log); + fprintf(f, "skipdraw = %x\n", conf.SkipDraw); + fprintf(f, "disablehacks = %x\n", conf.disableHacks); + fclose(f); +} + +void LoadConfig() +{ + int err = 0; + memset(&conf, 0, sizeof(conf)); + conf.interlace = 0; // on, mode 1 + conf.mrtdepth = 1; + conf.bilinear = 1; + conf.log = 1; + conf.SkipDraw = 0; + conf.width = 800; + conf.height = 600; + conf.disableHacks = 0; + + const wxString iniFile_s(Path::Combine(s_strIniPath, L"zzogl-pg.ini")); + std::string iniFile = std::string(iniFile_s.mb_str()); + + FILE* f = fopen(iniFile.c_str(), "r"); + + if (f == NULL) + { + ZZLog::Error_Log("Failed to open '%s'", iniFile.c_str()); + SaveConfig();//save and return + return; + } + + err = fscanf(f, "interlace = %hhx\n", &conf.interlace); + + err = fscanf(f, "mrtdepth = %hhx\n", &conf.mrtdepth); + err = fscanf(f, "zzoptions = %x\n", &conf.zz_options._u32); + err = fscanf(f, "options = %x\n", &conf.hacks._u32); + err = fscanf(f, "bilinear = %hhx\n", &conf.bilinear); + err = fscanf(f, "aliasing = %hhx\n", &conf.aa); + err = fscanf(f, "width = %x\n", &conf.width); + err = fscanf(f, "height = %x\n", &conf.height); + err = fscanf(f, "x = %x\n", &conf.x); + err = fscanf(f, "y = %x\n", &conf.y); + err = fscanf(f, "log = %x\n", &conf.log); + err = fscanf(f, "skipdraw = %x\n", &conf.SkipDraw); + err = fscanf(f, "disablehacks = %x\n", &conf.disableHacks); + fclose(f); + + // turn off all hacks by default + conf.setWireframe(false); + conf.setCaptureAvi(false); + conf.setLoaded(true); + + conf.isWideScreen = conf.widescreen(); + + // filter bad files + if (conf.interlace > 2) conf.interlace = 0; + if (conf.aa > 4) conf.aa = 0; + if (conf.width <= 0 || conf.height <= 0) + { + conf.width = 800; + conf.height = 600; + } + + if (conf.x < 0 || conf.y < 0) + { + conf.x = 0; + conf.y = 0; + } +} + diff --git a/plugins/zzogl-pg-cg/opengl/Linux/Linux.cpp b/plugins/zzogl-pg-cg/opengl/Linux/Linux.cpp new file mode 100644 index 000000000..3d5609f95 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/Linux/Linux.cpp @@ -0,0 +1,519 @@ +/* ZeroGS + * Copyright (C) 2002-2004 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include + +#include "GS.h" +#include "Linux.h" +#include "GLWin.h" + +#include + +extern u32 THR_KeyEvent; // value for passing out key events beetwen threads +extern bool THR_bShift; +extern bool THR_bCtrl; + +static map mapConfOpts; +static gameHacks tempHacks; + +void CALLBACK GSkeyEvent(keyEvent *ev) +{ + static bool bAlt = false; + + switch (ev->evt) + { + case KEYPRESS: + switch (ev->key) + { + case XK_F5: + case XK_F6: + case XK_F7: + case XK_F9: + THR_KeyEvent = ev->key; + break; + + case XK_Escape: + if (conf.fullscreen()) GLWin.ToggleFullscreen(); + break; + + case XK_Shift_L: + case XK_Shift_R: + THR_bShift = true; + break; + + case XK_Control_L: + case XK_Control_R: + THR_bCtrl = true; + break; + + case XK_Alt_L: + case XK_Alt_R: + bAlt = true; + break; + + case XK_Return: + if (bAlt) + GLWin.ToggleFullscreen(); + } + break; + + case KEYRELEASE: + switch (ev->key) + { + case XK_Shift_L: + case XK_Shift_R: + THR_bShift = false; + break; + + case XK_Control_L: + case XK_Control_R: + THR_bCtrl = false; + break; + + case XK_Alt_L: + case XK_Alt_R: + bAlt = false; + break; + } + } +} + +void add_map_entry(u32 option, const char *key, const char *desc) +{ + confOpts.value = option; + confOpts.desc = desc; + mapConfOpts[key] = confOpts; +} + +void CreateGameHackTable(GtkWidget *treeview, gameHacks hacks) +{ + char descbuf[255]; + bool itval; + GtkCellRenderer *treerend; + GtkListStore *treestore;//Gets typecast as GtkTreeModel as needed. + GtkTreeIter treeiter; + GtkTreeViewColumn *treecol; + + //--------- Let's build a treeview for our advanced options! --------// + treestore = gtk_list_store_new(2, G_TYPE_BOOLEAN, G_TYPE_STRING); + + //setup columns in treeview + //COLUMN 0 is the checkboxes + treecol = gtk_tree_view_column_new(); + gtk_tree_view_column_set_title(treecol, "Select"); + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), treecol); + treerend = gtk_cell_renderer_toggle_new(); + gtk_tree_view_column_pack_start(treecol, treerend, true); + gtk_tree_view_column_add_attribute(treecol, treerend, "active", 0);//link 'active' attrib to first column of model + g_object_set(treerend, "activatable", true, NULL);//set 'activatable' attrib true by default for all rows regardless of model. + g_signal_connect(treerend, "toggled", (GCallback) OnToggle_advopts, treestore);//set a global callback, we also pass a reference to our treestore. + + //COLUMN 1 is the text descriptions + treecol = gtk_tree_view_column_new(); + gtk_tree_view_column_set_title(treecol, "Description"); + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), treecol); + treerend = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(treecol, treerend, true); + gtk_tree_view_column_add_attribute(treecol, treerend, "text", 1);//link 'text' attrib to second column of model + + //setup the model with all our rows of option data + mapConfOpts.clear(); + + add_map_entry(GAME_TEXTURETARGS, "00000001", "Tex Target checking - 00000001\nLego Racers"); + add_map_entry(GAME_AUTORESET, "00000002", "Auto reset targs - 00000002\nUse when game is slow and toggling AA fixes it. Samurai Warriors. (Automatically on for Shadow Hearts)"); + add_map_entry(GAME_INTERLACE2X, "00000004", "Interlace 2X - 00000004\nFixes 2x bigger screen. Gradius 3."); + //GAME_TEXAHACK (still implemented) + add_map_entry(GAME_NOTARGETRESOLVE, "00000010", "No target resolves - 00000010\nStops all resolving of targets. Try this first for really slow games. (Automatically on for Dark Cloud 1.)"); + add_map_entry(GAME_EXACTCOLOR, "00000020", "Exact color testing - 00000020\nFixes overbright or shadow/black artifacts. Crash 'n Burn."); + //add_map_entry(GAME_NOCOLORCLAMP, "00000040", "No color clamping - 00000040\nSpeeds up games, but might be too bright or too dim."); + //GAME_FFXHACK + add_map_entry(GAME_NOALPHAFAIL, "00000100", "Alpha Fail hack - 00000100\nRemove vertical stripes or other coloring artifacts. Breaks Persona 4 and MGS3. (Automatically on for Sonic Unleashed, Shadow the Hedgehog, & Ghost in the Shell.)"); + add_map_entry(GAME_NODEPTHUPDATE, "00000200", "Disable depth updates - 00000200"); + add_map_entry(GAME_QUICKRESOLVE1, "00000400", "Resolve Hack #1 - 00000400\n Speeds some games. Kingdom Hearts."); + add_map_entry(GAME_NOQUICKRESOLVE, "00000800", "Resolve Hack #2 - 00000800\nShadow Hearts, Urbz. Destroys FFX."); + add_map_entry(GAME_NOTARGETCLUT, "00001000", "No target CLUT - 00001000\nResident Evil 4, or foggy scenes."); + add_map_entry(GAME_NOSTENCIL, "00002000", "Disable stencil buffer - 00002000\nUsually safe to do for simple scenes. Harvest Moon."); + //GAME_VSSHACKOFF (still implemented) + add_map_entry(GAME_NODEPTHRESOLVE, "00008000", "No depth resolve - 00008000\nMight give z buffer artifacts."); + add_map_entry(GAME_FULL16BITRES, "00010000", "Full 16 bit resolution - 00010000\nUse when half the screen is missing."); + add_map_entry(GAME_RESOLVEPROMOTED, "00020000", "Resolve Hack #3 - 00020000\nNeopets"); + add_map_entry(GAME_FASTUPDATE, "00040000", "Fast Update - 00040000\n Speeds some games. Needed for Sonic Unleashed. Okami."); + add_map_entry(GAME_NOALPHATEST, "00080000", "Disable alpha testing - 00080000"); + add_map_entry(GAME_DISABLEMRTDEPTH, "00100000", "Enable Multiple RTs - 00100000"); + //GAME_32BITTARGS + //GAME_PATH3HACK + //GAME_DOPARALLELCTX + add_map_entry(GAME_XENOSPECHACK, "01000000", "Specular Highlights - 01000000\nMakes graphics faster by removing highlights. (Automatically on for Xenosaga, Okami, & Okage.)"); + //add_map_entry(GAME_PARTIALPOINTERS, "02000000", "Partial targets - 02000000"); + add_map_entry(GAME_PARTIALDEPTH, "04000000", "Partial depth - 04000000"); + //GAME_REGETHACK (commented out in code) + add_map_entry(GAME_GUSTHACK, "10000000", "Gust fix - 10000000. Makes gust games cleaner and faster. (Automatically on for most Gust games)"); + add_map_entry(GAME_NOLOGZ, "20000000", "No logarithmic Z - 20000000. Could decrease number of Z-artifacts."); + add_map_entry(GAME_AUTOSKIPDRAW, "40000000", "Remove blur effect on some games\nSlow games."); + + for (map::iterator it = mapConfOpts.begin(); it != mapConfOpts.end(); ++it) + { + gtk_list_store_append(treestore, &treeiter);//new row + itval = (hacks._u32 & it->second.value) ? true : false; + + if (conf.def_hacks._u32 & it->second.value) + { + snprintf(descbuf, 254, "*%s", it->second.desc); + } + else + { + snprintf(descbuf, 254, "%s", it->second.desc); + } + + gtk_list_store_set(treestore, &treeiter, 0, itval, 1, descbuf, -1); + } + + gtk_tree_view_set_model(GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(treestore));//NB: store is cast as tree model. + + g_object_unref(treestore);//allow model to be destroyed when the tree is destroyed. + + //don't select/highlight rows + gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)), GTK_SELECTION_NONE); + //------treeview done -------// +} + +void SaveGameHackTable(GtkWidget *treeview, gameHacks& hacks) +{ + GtkTreeModel *treemodel; + GtkTreeIter treeiter; + gboolean treeoptval; + + //------- get advanced options from the treeview model -------// + treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview)); + gtk_tree_model_get_iter_first(treemodel, &treeiter); + + hacks._u32 = 0; + + for (map::iterator it = mapConfOpts.begin(); it != mapConfOpts.end(); ++it) + { + treeoptval = false; + gtk_tree_model_get(treemodel, &treeiter, 0, &treeoptval, -1); + + if (treeoptval) hacks._u32 |= it->second.value; + + gtk_tree_model_iter_next(treemodel, &treeiter); + } + + //---------- done getting advanced options ---------// +} + +void OnToggle_advopts(GtkCellRendererToggle *cell, gchar *path, gpointer user_data) +{ + GtkTreeIter treeiter; + gboolean val; + + gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(user_data), &treeiter, path); + gtk_tree_model_get(GTK_TREE_MODEL(user_data), &treeiter, 0, &val, -1); + val = !val; + gtk_list_store_set(GTK_LIST_STORE(user_data), &treeiter, 0, val, -1); +} + +void DisplayAdvancedDialog() +{ + GtkWidget *dialog; + + GtkWidget *advanced_frame, *advanced_box; + GtkWidget *advanced_scroll; + GtkWidget *tree; + + dialog = gtk_dialog_new(); + gtk_window_set_title(GTK_WINDOW(dialog), "ZZOgl PG Advanced Config"); + // A good value for the heigh will be 1000 instead of 800 but I'm afraid that some people still uses small screen... + gtk_window_set_default_size(GTK_WINDOW(dialog), 600, 800); + gtk_window_set_modal(GTK_WINDOW(dialog), true); + + advanced_box = gtk_vbox_new(false, 5); + advanced_frame = gtk_frame_new("Advanced Settings:"); + gtk_container_add(GTK_CONTAINER(advanced_frame), advanced_box); + + tree = gtk_tree_view_new(); + + CreateGameHackTable(tree, tempHacks); + + advanced_scroll = gtk_scrolled_window_new(NULL, NULL); + + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(advanced_scroll), tree); + + gtk_box_pack_start(GTK_BOX(advanced_box), advanced_scroll, true, true, 2); + + gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), advanced_frame); + + gtk_widget_show_all(dialog); + + gtk_dialog_run(GTK_DIALOG(dialog)); + SaveGameHackTable(tree, tempHacks); + gtk_widget_destroy(dialog); +} + +void DisplayDialog() +{ + int return_value; + + GtkWidget *dialog; + GtkWidget *main_frame, *main_box; + + GtkWidget *option_frame, *option_box; + GtkWidget *log_check, *dis_hacks_check; + GtkWidget *int_label, *int_box, *int_holder; + GtkWidget *bilinear_label, *bilinear_box, *bilinear_holder; + GtkWidget *aa_label, *aa_box, *aa_holder; + GtkWidget *snap_label, *snap_box, *snap_holder; + GtkWidget *fullscreen_label, *widescreen_check; + + + GtkWidget *advanced_button; + GtkWidget *separator; + GtkWidget *skipdraw_label, *skipdraw_text, *skipdraw_holder, *warning_label; + + if (!(conf.loaded())) LoadConfig(); + + /* Create the widgets */ + dialog = gtk_dialog_new_with_buttons( + "ZZOgl PG Config", + NULL, /* parent window*/ + (GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT), + GTK_STOCK_CANCEL, + GTK_RESPONSE_REJECT, + GTK_STOCK_OK, + GTK_RESPONSE_ACCEPT, + NULL); + + log_check = gtk_check_button_new_with_label("Logging"); + gtk_widget_set_tooltip_text(log_check, "Used for Debugging."); + + int_label = gtk_label_new("Interlacing:"); + int_box = gtk_combo_box_new_text(); + + gtk_combo_box_append_text(GTK_COMBO_BOX(int_box), "No Interlacing"); + gtk_combo_box_append_text(GTK_COMBO_BOX(int_box), "Interlace 0"); + gtk_combo_box_append_text(GTK_COMBO_BOX(int_box), "Interlace 1"); + gtk_combo_box_set_active(GTK_COMBO_BOX(int_box), conf.interlace); + gtk_widget_set_tooltip_text(int_box, "Toggled by pressing F5 when running."); + int_holder = gtk_hbox_new(false, 5); + gtk_box_pack_start(GTK_BOX(int_holder), int_label, false, false, 2); + gtk_box_pack_start(GTK_BOX(int_holder), int_box, false, false, 2); + + bilinear_label = gtk_label_new("Bilinear Filtering:"); + bilinear_box = gtk_combo_box_new_text(); + + gtk_combo_box_append_text(GTK_COMBO_BOX(bilinear_box), "Off"); + gtk_combo_box_append_text(GTK_COMBO_BOX(bilinear_box), "Normal"); + gtk_combo_box_append_text(GTK_COMBO_BOX(bilinear_box), "Forced"); + gtk_combo_box_set_active(GTK_COMBO_BOX(bilinear_box), conf.bilinear); + gtk_widget_set_tooltip_text(bilinear_box, "Best quality is off. Turn on for speed. Toggled by pressing Shift + F5 when running."); + bilinear_holder = gtk_hbox_new(false, 5); + gtk_box_pack_start(GTK_BOX(bilinear_holder), bilinear_label, false, false, 2); + gtk_box_pack_start(GTK_BOX(bilinear_holder), bilinear_box, false, false, 2); + + aa_label = gtk_label_new("Anti-Aliasing:"); + aa_box = gtk_combo_box_new_text(); + + gtk_combo_box_append_text(GTK_COMBO_BOX(aa_box), "1X (None)"); + gtk_combo_box_append_text(GTK_COMBO_BOX(aa_box), "2X"); + gtk_combo_box_append_text(GTK_COMBO_BOX(aa_box), "4X"); + gtk_combo_box_append_text(GTK_COMBO_BOX(aa_box), "8X"); + gtk_combo_box_append_text(GTK_COMBO_BOX(aa_box), "16X"); + gtk_combo_box_set_active(GTK_COMBO_BOX(aa_box), conf.aa); + gtk_widget_set_tooltip_text(aa_box, "Toggled by pressing F6 when running."); + aa_holder = gtk_hbox_new(false, 5); + gtk_box_pack_start(GTK_BOX(aa_holder), aa_label, false, false, 2); + gtk_box_pack_start(GTK_BOX(aa_holder), aa_box, false, false, 2); + + snap_label = gtk_label_new("Snapshot format:"); + snap_box = gtk_combo_box_new_text(); + gtk_combo_box_append_text(GTK_COMBO_BOX(snap_box), "JPEG"); + gtk_combo_box_append_text(GTK_COMBO_BOX(snap_box), "TIFF"); + gtk_combo_box_set_active(GTK_COMBO_BOX(snap_box), conf.zz_options.tga_snap); + snap_holder = gtk_hbox_new(false, 5); + gtk_box_pack_start(GTK_BOX(snap_holder), snap_label, false, false, 2); + gtk_box_pack_start(GTK_BOX(snap_holder), snap_box, false, false, 2); + + widescreen_check = gtk_check_button_new_with_label("Widescreen"); + gtk_widget_set_tooltip_text(widescreen_check, "Force a 4:3 ration when disabled"); + fullscreen_label = gtk_label_new("Press Alt-Enter for Fullscreen."); + gtk_label_set_single_line_mode(GTK_LABEL(fullscreen_label), false); + + advanced_button = gtk_button_new_with_label("Advanced..."); + + dis_hacks_check = gtk_check_button_new_with_label("Disable Automatic Hacks"); + gtk_widget_set_tooltip_text(dis_hacks_check, "Used for testing how useful hacks that are on automatically are."); + +#ifdef ZEROGS_DEVBUILD + separator = gtk_hseparator_new(); + skipdraw_label = gtk_label_new("Skipdraw:"); + skipdraw_text = gtk_entry_new(); + warning_label = gtk_label_new("Experimental!!"); + char buf[5]; + sprintf(buf, "%d", conf.SkipDraw); + gtk_entry_set_text(GTK_ENTRY(skipdraw_text), buf); + skipdraw_holder = gtk_hbox_new(false, 5); + + gtk_box_pack_start(GTK_BOX(skipdraw_holder), skipdraw_label, false, false, 2); + gtk_box_pack_start(GTK_BOX(skipdraw_holder), skipdraw_text, false, false, 2); +#endif + + main_box = gtk_hbox_new(false, 5); + main_frame = gtk_frame_new("ZZOgl PG Config"); + + gtk_container_add(GTK_CONTAINER(main_frame), main_box); + + option_box = gtk_vbox_new(false, 5); + option_frame = gtk_frame_new(""); + gtk_container_add(GTK_CONTAINER(option_frame), option_box); + gtk_frame_set_shadow_type(GTK_FRAME(option_frame), GTK_SHADOW_NONE); + + gtk_box_pack_start(GTK_BOX(option_box), log_check, false, false, 2); + gtk_box_pack_start(GTK_BOX(option_box), bilinear_holder, false, false, 2); + gtk_box_pack_start(GTK_BOX(option_box), int_holder, false, false, 2); + gtk_box_pack_start(GTK_BOX(option_box), aa_holder, false, false, 2); + gtk_box_pack_start(GTK_BOX(option_box), snap_holder, false, false, 2); + gtk_box_pack_start(GTK_BOX(option_box), widescreen_check, false, false, 2); + gtk_box_pack_start(GTK_BOX(option_box), advanced_button, false, false, 2); + gtk_box_pack_start(GTK_BOX(option_box), dis_hacks_check, false, false, 2); + +#ifdef ZEROGS_DEVBUILD + gtk_box_pack_start(GTK_BOX(option_box), separator, false, false, 2); + gtk_box_pack_start(GTK_BOX(option_box), warning_label, false, false, 2); + gtk_box_pack_start(GTK_BOX(option_box), skipdraw_holder, false, false, 2); +#endif + + gtk_box_pack_start(GTK_BOX(option_box), fullscreen_label, false, false, 2); + + gtk_box_pack_start(GTK_BOX(main_box), option_frame, false, false, 2); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(log_check), conf.log); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widescreen_check), (conf.widescreen())); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dis_hacks_check), (conf.disableHacks)); + + gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), main_frame); + g_signal_connect_swapped(GTK_OBJECT (advanced_button), "clicked", G_CALLBACK(DisplayAdvancedDialog), advanced_button); + tempHacks = conf.hacks; + gtk_widget_show_all(dialog); + + return_value = gtk_dialog_run(GTK_DIALOG(dialog)); + + if (return_value == GTK_RESPONSE_ACCEPT) + { + ZZOptions fake_options; + + if (gtk_combo_box_get_active(GTK_COMBO_BOX(int_box)) != -1) + conf.interlace = gtk_combo_box_get_active(GTK_COMBO_BOX(int_box)); + + if (gtk_combo_box_get_active(GTK_COMBO_BOX(aa_box)) != -1) + conf.aa = gtk_combo_box_get_active(GTK_COMBO_BOX(aa_box)); + + if (gtk_combo_box_get_active(GTK_COMBO_BOX(bilinear_box)) != -1) + conf.bilinear = gtk_combo_box_get_active(GTK_COMBO_BOX(bilinear_box)); + + conf.log = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(log_check)); + fake_options.widescreen = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widescreen_check)); + fake_options.tga_snap = gtk_combo_box_get_active(GTK_COMBO_BOX(snap_box)); + +#ifdef ZEROGS_DEVBUILD + conf.SkipDraw = atoi((char*)gtk_entry_get_text(GTK_ENTRY(skipdraw_text))); +#endif + + conf.zz_options = fake_options; + conf.hacks = tempHacks; + + conf.disableHacks = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dis_hacks_check)); + + GSsetGameCRC(g_LastCRC, conf.hacks._u32); + + SaveConfig(); + } + + gtk_widget_destroy(dialog); +} + +void CALLBACK GSconfigure() +{ + char strcurdir[256]; + getcwd(strcurdir, 256); + + if (!(conf.loaded())) LoadConfig(); + + DisplayDialog(); +} + +void SysMessage(const char *fmt, ...) +{ + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0; + + GtkWidget *dialog; + + dialog = gtk_message_dialog_new(NULL, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_OK, + "%s", msg); + + gtk_dialog_run(GTK_DIALOG(dialog)); + + gtk_widget_destroy(dialog); +} + +void CALLBACK GSabout() +{ + SysMessage("ZZOgl PG: by Zeydlitz (PG version worked on by arcum42, gregory, and the pcsx2 development team). Based off of ZeroGS, by zerofrog."); +} + +s32 CALLBACK GStest() +{ + return 0; +} + +void *SysLoadLibrary(char *lib) +{ + return dlopen(lib, RTLD_NOW | RTLD_GLOBAL); +} + +void *SysLoadSym(void *lib, char *sym) +{ + void *ret = dlsym(lib, sym); + + if (ret == NULL) ZZLog::Debug_Log("null: %s", sym); + + return dlsym(lib, sym); +} + +char *SysLibError() +{ + return dlerror(); +} + +void SysCloseLibrary(void *lib) +{ + dlclose(lib); +} diff --git a/plugins/zzogl-pg-cg/opengl/Linux/Linux.h b/plugins/zzogl-pg-cg/opengl/Linux/Linux.h new file mode 100644 index 000000000..fc2eb402b --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/Linux/Linux.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2002-2004 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __LINUX_H__ +#define __LINUX_H__ + +struct confOptsStruct +{ + int value; + const char *desc; +} confOpts; + + +void OnToggle_advopts(GtkCellRendererToggle *cell, gchar *path, gpointer user_data); + +#endif diff --git a/plugins/zzogl-pg-cg/opengl/Linux/zzogl-pg/zzogl-pg.cbp b/plugins/zzogl-pg-cg/opengl/Linux/zzogl-pg/zzogl-pg.cbp new file mode 100644 index 000000000..b9bf0a2d4 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/Linux/zzogl-pg/zzogl-pg.cbp @@ -0,0 +1,194 @@ + + + + + + diff --git a/plugins/zzogl-pg-cg/opengl/Mem.cpp b/plugins/zzogl-pg-cg/opengl/Mem.cpp new file mode 100644 index 000000000..2bbfd8470 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/Mem.cpp @@ -0,0 +1,384 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "GS.h" +#include "Mem.h" +#include "targets.h" +#include "x86.h" + +#include "Mem_Transmit.h" +#include "Mem_Swizzle.h" +#ifdef ZEROGS_SSE2 +#include +#endif + +BLOCK m_Blocks[0x40]; // do so blocks are indexable + +PCSX2_ALIGNED16(u32 tempblock[64]); + +// Add a bunch of local variables that used to be in the TransferHostLocal +// functions, in order to de-macro the TransmitHostLocal macros. +// May be in a class or namespace eventually. +int tempX, tempY; +int pitch, area, fracX; +int nSize; +u8* pstart; + +// ------------------------ +// | Y | +// ------------------------ +// | block | | +// | aligned area | X | +// | | | +// ------------------------ +// | Y | +// ------------------------ + +template +static __forceinline const T* AlignOnBlockBoundry(TransferData data, TransferFuncts fun, Point alignedPt, int& endY, const T* pbuf) +{ + bool bCanAlign = ((MOD_POW2(gs.trxpos.dx, data.blockwidth) == 0) && (gs.imageX == gs.trxpos.dx) && + (alignedPt.y > endY) && (alignedPt.x > gs.trxpos.dx)); + + if ((gs.imageEndX - gs.trxpos.dx) % data.widthlimit) + { + /* hack */ + int testwidth = (int)nSize - + (gs.imageEndY - gs.imageY) * (gs.imageEndX - gs.trxpos.dx) + + (gs.imageX - gs.trxpos.dx); + + if ((testwidth <= data.widthlimit) && (testwidth >= -data.widthlimit)) + { + /* don't transfer */ + /*ZZLog::Debug_Log("Bad texture %s: %d %d %d", #psm, gs.trxpos.dx, gs.imageEndX, nQWordSize);*/ + //ZZLog::Error_Log("Bad texture: testwidth = %d; data.widthlimit = %d", testwidth, data.widthlimit); + gs.imageTransfer = -1; + } + + bCanAlign = false; + } + + /* first align on block boundary */ + if (MOD_POW2(gs.imageY, data.blockheight) || !bCanAlign) + { + u32 transwidth; + + if (!bCanAlign) + endY = gs.imageEndY; /* transfer the whole image */ + else + assert(endY < gs.imageEndY); /* part of alignment condition */ + + if (((gs.imageEndX - gs.trxpos.dx) % data.widthlimit) || ((gs.imageEndX - gs.imageX) % data.widthlimit)) + { + /* transmit with a width of 1 */ + transwidth = (1 + (DSTPSM == PSMT4)); + } + else + { + transwidth = data.widthlimit; + } + + pbuf = TransmitHostLocalY(data.psm, fun.wp, transwidth, endY, pbuf); + + if (pbuf == NULL) return NULL; + + if (nSize == 0 || tempY == gs.imageEndY) return NULL; + } + + return pbuf; +} + +template +static __forceinline const T* TransferAligningToBlocks(TransferData data, TransferFuncts fun, Point alignedPt, const T* pbuf) +{ + bool bAligned; + const u32 TSize = sizeof(T); + _SwizzleBlock swizzle; + + /* can align! */ + pitch = gs.imageEndX - gs.trxpos.dx; + area = pitch * data.blockheight; + fracX = gs.imageEndX - alignedPt.x; + + /* on top of checking whether pbuf is aligned, make sure that the width is at least aligned to its limits (due to bugs in pcsx2) */ + bAligned = !((uptr)pbuf & 0xf) && (TransPitch(pitch, data.transfersize) & 0xf) == 0; + + if (bAligned || ((DSTPSM == PSMCT24) || (DSTPSM == PSMT8H) || (DSTPSM == PSMT4HH) || (DSTPSM == PSMT4HL))) + swizzle = (fun.Swizzle); + else + swizzle = (fun.Swizzle_u); + + //Transfer aligning to blocks. + for (; tempY < alignedPt.y && nSize >= area; tempY += data.blockheight, nSize -= area) + { + for (int tempj = gs.trxpos.dx; tempj < alignedPt.x; tempj += data.blockwidth, pbuf += TransPitch(data.blockwidth, data.transfersize) / TSize) + { + u8 *temp = pstart + fun.gp(tempj, tempY, gs.dstbuf.bw) * data.blockbits / 8; + swizzle(temp, (u8*)pbuf, TransPitch(pitch, data.transfersize)); + } +#ifdef ZEROGS_SSE2 + // Note: swizzle function uses some non temporal move (mm_stream) instruction. + // store fence insures that previous store are finish before execute new one. + _mm_sfence(); + +#endif + + /* transfer the rest */ + if (alignedPt.x < gs.imageEndX) + { + pbuf = TransmitHostLocalX(data.psm, fun.wp, data.widthlimit, data.blockheight, alignedPt.x, pbuf); + + if (pbuf == NULL) return NULL; + + pbuf -= TransPitch((alignedPt.x - gs.trxpos.dx), data.transfersize) / TSize; + } + else + { + pbuf += (data.blockheight - 1) * TransPitch(pitch, data.transfersize) / TSize; + } + + tempX = gs.trxpos.dx; + } + + return pbuf; +} + +static __forceinline int FinishTransfer(TransferData data, int nLeftOver) +{ + if (tempY >= gs.imageEndY) + { + assert(gs.imageTransfer == -1 || tempY == gs.imageEndY); + gs.imageTransfer = -1; + /*int start, end; + GetRectMemAddress(start, end, gs.dstbuf.psm, gs.trxpos.dx, gs.trxpos.dy, gs.imageWnew, gs.imageHnew, gs.dstbuf.bp, gs.dstbuf.bw); + g_MemTargs.ClearRange(start, end);*/ + } + else + { + /* update new params */ + gs.imageY = tempY; + gs.imageX = tempX; + } + + return (nSize * TransPitch(2, data.transfersize) + nLeftOver) / 2; +} + +template +static __forceinline int RealTransfer(u32 psm, const void* pbyMem, u32 nQWordSize) +{ + assert(gs.imageTransfer == 0); + TransferData data = tData[psm]; + TransferFuncts fun(psm); + pstart = g_pbyGSMemory + gs.dstbuf.bp * 256; + const T* pbuf = (const T*)pbyMem; + const int tp2 = TransPitch(2, data.transfersize); + int nLeftOver = (nQWordSize * 4 * 2) % tp2; + tempY = gs.imageY; + tempX = gs.imageX; + Point alignedPt; + + nSize = (nQWordSize * 4 * 2) / tp2; + nSize = min(nSize, gs.imageWnew * gs.imageHnew); + + int endY = ROUND_UPPOW2(gs.imageY, data.blockheight); + alignedPt.y = ROUND_DOWNPOW2(gs.imageEndY, data.blockheight); + alignedPt.x = ROUND_DOWNPOW2(gs.imageEndX, data.blockwidth); + + pbuf = AlignOnBlockBoundry(data, fun, alignedPt, endY, pbuf); + + if (pbuf == NULL) return FinishTransfer(data, nLeftOver); + + pbuf = TransferAligningToBlocks(data, fun, alignedPt, pbuf); + + if (pbuf == NULL) return FinishTransfer(data, nLeftOver); + + if (TransPitch(nSize, data.transfersize) / 4 > 0) + { + pbuf = TransmitHostLocalY(psm, fun.wp, data.widthlimit, gs.imageEndY, pbuf); + + if (pbuf == NULL) return FinishTransfer(data, nLeftOver); + + /* sometimes wrong sizes are sent (tekken tag) */ + assert(gs.imageTransfer == -1 || TransPitch(nSize, data.transfersize) / 4 <= 2); + } + + return FinishTransfer(data, nLeftOver); +} + +int TransferHostLocal32(const void* pbyMem, u32 nQWordSize) { return RealTransfer(PSMCT32, pbyMem, nQWordSize); } +int TransferHostLocal32Z(const void* pbyMem, u32 nQWordSize) { return RealTransfer(PSMT32Z, pbyMem, nQWordSize); } +int TransferHostLocal24(const void* pbyMem, u32 nQWordSize) { return RealTransfer(PSMCT24, pbyMem, nQWordSize); } +int TransferHostLocal24Z(const void* pbyMem, u32 nQWordSize) { return RealTransfer(PSMT24Z, pbyMem, nQWordSize); } +int TransferHostLocal16(const void* pbyMem, u32 nQWordSize) { return RealTransfer(PSMCT16, pbyMem, nQWordSize); } +int TransferHostLocal16S(const void* pbyMem, u32 nQWordSize) { return RealTransfer(PSMCT16S, pbyMem, nQWordSize); } +int TransferHostLocal16Z(const void* pbyMem, u32 nQWordSize) { return RealTransfer(PSMT16Z, pbyMem, nQWordSize); } +int TransferHostLocal16SZ(const void* pbyMem, u32 nQWordSize){ return RealTransfer(PSMT16SZ, pbyMem, nQWordSize); } +int TransferHostLocal8(const void* pbyMem, u32 nQWordSize) { return RealTransfer(PSMT8, pbyMem, nQWordSize); } +int TransferHostLocal4(const void* pbyMem, u32 nQWordSize) { return RealTransfer(PSMT4, pbyMem, nQWordSize); } +int TransferHostLocal8H(const void* pbyMem, u32 nQWordSize) { return RealTransfer(PSMT8H, pbyMem, nQWordSize); } +int TransferHostLocal4HL(const void* pbyMem, u32 nQWordSize) { return RealTransfer(PSMT4HL, pbyMem, nQWordSize); } +int TransferHostLocal4HH(const void* pbyMem, u32 nQWordSize) { return RealTransfer(PSMT4HH, pbyMem, nQWordSize); } + +void TransferLocalHost32(void* pbyMem, u32 nQWordSize) {FUNCLOG} +void TransferLocalHost24(void* pbyMem, u32 nQWordSize) {FUNCLOG} +void TransferLocalHost16(void* pbyMem, u32 nQWordSize) {FUNCLOG} +void TransferLocalHost16S(void* pbyMem, u32 nQWordSize) {FUNCLOG} +void TransferLocalHost8(void* pbyMem, u32 nQWordSize) {FUNCLOG} +void TransferLocalHost4(void* pbyMem, u32 nQWordSize) {FUNCLOG} +void TransferLocalHost8H(void* pbyMem, u32 nQWordSize) {FUNCLOG} +void TransferLocalHost4HL(void* pbyMem, u32 nQWordSize) {FUNCLOG} +void TransferLocalHost4HH(void* pbyMem, u32 nQWordSize) {FUNCLOG} +void TransferLocalHost32Z(void* pbyMem, u32 nQWordSize) {FUNCLOG} +void TransferLocalHost24Z(void* pbyMem, u32 nQWordSize) {FUNCLOG} +void TransferLocalHost16Z(void* pbyMem, u32 nQWordSize) {FUNCLOG} +void TransferLocalHost16SZ(void* pbyMem, u32 nQWordSize) {FUNCLOG} + +void fill_block(BLOCK b, vector& vBlockData, vector& vBilinearData, int floatfmt) +{ + float* psrcf = (float*)&vBlockData[0] + b.ox + b.oy * BLOCK_TEXWIDTH; + u16* psrcw = NULL; + if (!floatfmt) + psrcw = (u16*)&vBlockData[0] + b.ox + b.oy * BLOCK_TEXWIDTH; + + for(int i = 0; i < b.height; ++i) + { + u32 i_width = i*BLOCK_TEXWIDTH; + for(int j = 0; j < b.width; ++j) + { + /* fill the table */ + u32 bt = b.blockTable[(i / b.colheight)*(b.width/b.colwidth) + (j / b.colwidth)]; + u32 ct = b.columnTable[(i%b.colheight)*b.colwidth + (j%b.colwidth)]; + u32 u = bt * 64 * b.mult + ct; + b.pageTable[i * b.width + j] = u; + if (floatfmt) + psrcf[i_width + j] = (float)(u) / (float)(GPU_TEXWIDTH * b.mult); + else + psrcw[i_width + j] = u; + + } + } + + if (floatfmt) { + float4* psrcv = (float4*)&vBilinearData[0] + b.ox + b.oy * BLOCK_TEXWIDTH; + + for(int i = 0; i < b.height; ++i) + { + u32 i_width = i*BLOCK_TEXWIDTH; + u32 i_width2 = ((i+1)%b.height)*BLOCK_TEXWIDTH; + for(int j = 0; j < b.width; ++j) + { + u32 temp = ((j + 1) % b.width); + float4* pv = &psrcv[i_width + j]; + pv->x = psrcf[i_width + j]; + pv->y = psrcf[i_width + temp]; + pv->z = psrcf[i_width2 + j]; + pv->w = psrcf[i_width2 + temp]; + } + } + } +} + +void BLOCK::FillBlocks(vector& vBlockData, vector& vBilinearData, int floatfmt) +{ + FUNCLOG + if (floatfmt) { + vBlockData.resize(BLOCK_TEXWIDTH * BLOCK_TEXHEIGHT * 4); + vBilinearData.resize(BLOCK_TEXWIDTH * BLOCK_TEXHEIGHT * sizeof(float4)); + } else { + vBlockData.resize(BLOCK_TEXWIDTH * BLOCK_TEXHEIGHT * 2); + } + + BLOCK b; + + memset(m_Blocks, 0, sizeof(m_Blocks)); + + // 32 + b.SetDim(64, 32, 0, 0, 1); + b.SetTable(PSMCT32); + fill_block(b, vBlockData, vBilinearData, floatfmt); + m_Blocks[PSMCT32] = b; + m_Blocks[PSMCT32].SetFun(PSMCT32); + + // 24 (same as 32 except write/readPixel are different) + m_Blocks[PSMCT24] = b; + m_Blocks[PSMCT24].SetFun(PSMCT24); + + // 8H (same as 32 except write/readPixel are different) + m_Blocks[PSMT8H] = b; + m_Blocks[PSMT8H].SetFun(PSMT8H); + + m_Blocks[PSMT4HL] = b; + m_Blocks[PSMT4HL].SetFun(PSMT4HL); + + m_Blocks[PSMT4HH] = b; + m_Blocks[PSMT4HH].SetFun(PSMT4HH); + + // 32z + b.SetDim(64, 32, 64, 0, 1); + b.SetTable(PSMT32Z); + fill_block(b, vBlockData, vBilinearData, floatfmt); + m_Blocks[PSMT32Z] = b; + m_Blocks[PSMT32Z].SetFun(PSMT32Z); + + // 24Z (same as 32Z except write/readPixel are different) + m_Blocks[PSMT24Z] = b; + m_Blocks[PSMT24Z].SetFun(PSMT24Z); + + // 16 + b.SetDim(64, 64, 0, 32, 2); + b.SetTable(PSMCT16); + fill_block(b, vBlockData, vBilinearData, floatfmt); + m_Blocks[PSMCT16] = b; + m_Blocks[PSMCT16].SetFun(PSMCT16); + + // 16s + b.SetDim(64, 64, 64, 32, 2); + b.SetTable(PSMCT16S); + fill_block(b, vBlockData, vBilinearData, floatfmt); + m_Blocks[PSMCT16S] = b; + m_Blocks[PSMCT16S].SetFun(PSMCT16S); + + // 16z + b.SetDim(64, 64, 0, 96, 2); + b.SetTable(PSMT16Z); + fill_block(b, vBlockData, vBilinearData, floatfmt); + m_Blocks[PSMT16Z] = b; + m_Blocks[PSMT16Z].SetFun(PSMT16Z); + + // 16sz + b.SetDim(64, 64, 64, 96, 2); + b.SetTable(PSMT16SZ); + fill_block(b, vBlockData, vBilinearData, floatfmt); + m_Blocks[PSMT16SZ] = b; + m_Blocks[PSMT16SZ].SetFun(PSMT16SZ); + + // 8 + b.SetDim(128, 64, 0, 160, 4); + b.SetTable(PSMT8); + fill_block(b, vBlockData, vBilinearData, floatfmt); + m_Blocks[PSMT8] = b; + m_Blocks[PSMT8].SetFun(PSMT8); + + // 4 + b.SetDim(128, 128, 0, 224, 8); + b.SetTable(PSMT4); + fill_block(b, vBlockData, vBilinearData, floatfmt); + m_Blocks[PSMT4] = b; + m_Blocks[PSMT4].SetFun(PSMT4); +} diff --git a/plugins/zzogl-pg-cg/opengl/Mem.h b/plugins/zzogl-pg-cg/opengl/Mem.h new file mode 100644 index 000000000..f4fdb2111 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/Mem.h @@ -0,0 +1,531 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __MEM_H__ +#define __MEM_H__ + +#include +#include + +// works only when base is a power of 2 +static __forceinline int ROUND_UPPOW2(int val, int base) { return (((val) + (base - 1))&~(base - 1)); } +static __forceinline int ROUND_DOWNPOW2(int val, int base) { return ((val)&~(base - 1)); } +static __forceinline int MOD_POW2(int val, int base) { return ((val)&(base - 1)); } + +// d3d texture dims +const int BLOCK_TEXWIDTH = 128; +const int BLOCK_TEXHEIGHT = 512; + +extern PCSX2_ALIGNED16(u32 tempblock[64]); + +typedef u32(*_getPixelAddress)(int x, int y, u32 bp, u32 bw); +typedef u32(*_getPixelAddress_0)(int x, int y, u32 bw); +typedef void (*_writePixel)(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw); +typedef void (*_writePixel_0)(void* pmem, int x, int y, u32 pixel, u32 bw); +typedef u32(*_readPixel)(const void* pmem, int x, int y, u32 bp, u32 bw); +typedef u32(*_readPixel_0)(const void* pmem, int x, int y, u32 bw); +typedef int (*_TransferHostLocal)(const void* pbyMem, u32 nQWordSize); +typedef void (*_TransferLocalHost)(void* pbyMem, u32 nQWordSize); +typedef void (*_SwizzleBlock)(u8 *dst, u8 *src, int pitch); + +extern _getPixelAddress_0 getPixelFun_0[64]; +extern _writePixel_0 writePixelFun_0[64]; +extern _readPixel_0 readPixelFun_0[64]; +extern _writePixel writePixelFun[64]; +extern _readPixel readPixelFun[64]; +extern _SwizzleBlock swizzleBlockFun[64]; +extern _SwizzleBlock swizzleBlockUnFun[64]; +extern _TransferHostLocal TransferHostLocalFun[64]; +extern _TransferLocalHost TransferLocalHostFun[64]; + +// Both of the following structs should probably be local class variables or in a namespace, +// but this works for the moment. + +struct TransferData +{ + // Signed because Visual C++ is weird. + s32 widthlimit; + u32 blockbits; + u32 blockwidth; + u32 blockheight; + u32 transfersize; + u32 psm; +}; + +struct TransferFuncts +{ + _writePixel_0 wp; + _getPixelAddress_0 gp; + _SwizzleBlock Swizzle, Swizzle_u; + __forceinline TransferFuncts(_writePixel_0 writePix, _getPixelAddress_0 readPix, _SwizzleBlock s, _SwizzleBlock su) + { + wp = writePix; + gp = readPix; + Swizzle = s; + Swizzle_u = su; + } + __forceinline TransferFuncts(u32 psm) + { + wp = writePixelFun_0[psm]; + gp = getPixelFun_0[psm]; + Swizzle = swizzleBlockFun[psm]; + Swizzle_u = swizzleBlockUnFun[psm]; + } +}; + +extern TransferData tData[64]; +// rest not visible externally + +extern u32 g_blockTable32[4][8]; +extern u32 g_blockTable32Z[4][8]; +extern u32 g_blockTable16[8][4]; +extern u32 g_blockTable16S[8][4]; +extern u32 g_blockTable16Z[8][4]; +extern u32 g_blockTable16SZ[8][4]; +extern u32 g_blockTable8[4][8]; +extern u32 g_blockTable4[8][4]; + +extern u32 g_columnTable32[8][8]; +extern u32 g_columnTable16[8][16]; +extern u32 g_columnTable8[16][16]; +extern u32 g_columnTable4[16][32]; + +extern u32 g_pageTable32[32][64]; +extern u32 g_pageTable32Z[32][64]; +extern u32 g_pageTable16[64][64]; +extern u32 g_pageTable16S[64][64]; +extern u32 g_pageTable16Z[64][64]; +extern u32 g_pageTable16SZ[64][64]; +extern u32 g_pageTable8[64][128]; +extern u32 g_pageTable4[128][128]; + +struct BLOCK +{ + BLOCK() { memset(this, 0, sizeof(BLOCK)); } + + // shader constants for this block + float4 vTexBlock; + float4 vTexDims; + int width, height; // dims of one page in pixels + int ox, oy, mult; + int bpp; + int colwidth, colheight; + u32* pageTable; // offset inside each page + u32* blockTable; + u32* columnTable; + + _getPixelAddress getPixelAddress; + _getPixelAddress_0 getPixelAddress_0; + _writePixel writePixel; + _writePixel_0 writePixel_0; + _readPixel readPixel; + _readPixel_0 readPixel_0; + _TransferHostLocal TransferHostLocal; + _TransferLocalHost TransferLocalHost; + + // texture must be of dims BLOCK_TEXWIDTH and BLOCK_TEXHEIGHT + static void FillBlocks(std::vector& vBlockData, std::vector& vBilinearData, int floatfmt); + + void SetDim(u32 bw, u32 bh, u32 ox2, u32 oy2, u32 mult2) + { + ox = ox2; + oy = oy2; + mult = mult2; + vTexDims = float4(BLOCK_TEXWIDTH/(float)(bw), BLOCK_TEXHEIGHT/(float)bh, 0, 0); + vTexBlock = float4((float)bw/BLOCK_TEXWIDTH, (float)bh/BLOCK_TEXHEIGHT, ((float)ox+0.2f)/BLOCK_TEXWIDTH, ((float)oy+0.05f)/BLOCK_TEXHEIGHT); + width = bw; + height = bh; + colwidth = bh / 4; + colheight = bw / 8; + bpp = 32/mult; + } + + void SetFun(u32 psm) + { + writePixel = writePixelFun[psm]; + writePixel_0 = writePixelFun_0[psm]; + readPixel = readPixelFun[psm]; + readPixel_0 = readPixelFun_0[psm]; + TransferHostLocal = TransferHostLocalFun[psm]; + TransferLocalHost = TransferLocalHostFun[psm]; + } + + void SetTable(u32 psm) + { + switch (psm) { + case PSMCT32: + assert( sizeof(g_pageTable32) == width * height * sizeof(g_pageTable32[0][0]) ); + pageTable = &g_pageTable32[0][0]; + blockTable = &g_blockTable32[0][0]; + columnTable = &g_columnTable32[0][0]; + break; + case PSMT32Z: + assert( sizeof(g_pageTable32Z) == width * height * sizeof(g_pageTable32Z[0][0]) ); + pageTable = &g_pageTable32Z[0][0]; + blockTable = &g_blockTable32Z[0][0]; + columnTable = &g_columnTable32[0][0]; + break; + case PSMCT16: + assert( sizeof(g_pageTable16) == width * height * sizeof(g_pageTable16[0][0]) ); + pageTable = &g_pageTable16[0][0]; + blockTable = &g_blockTable16[0][0]; + columnTable = &g_columnTable16[0][0]; + break; + case PSMCT16S: + assert( sizeof(g_pageTable16S) == width * height * sizeof(g_pageTable16S[0][0]) ); + pageTable = &g_pageTable16S[0][0]; + blockTable = &g_blockTable16S[0][0]; + columnTable = &g_columnTable16[0][0]; + break; + case PSMT16Z: + assert( sizeof(g_pageTable16Z) == width * height * sizeof(g_pageTable16Z[0][0]) ); + pageTable = &g_pageTable16Z[0][0]; + blockTable = &g_blockTable16Z[0][0]; + columnTable = &g_columnTable16[0][0]; + break; + case PSMT16SZ: + assert( sizeof(g_pageTable16SZ) == width * height * sizeof(g_pageTable16SZ[0][0]) ); + pageTable = &g_pageTable16SZ[0][0]; + blockTable = &g_blockTable16SZ[0][0]; + columnTable = &g_columnTable16[0][0]; + break; + case PSMT8: + assert( sizeof(g_pageTable8) == width * height * sizeof(g_pageTable8[0][0]) ); + pageTable = &g_pageTable8[0][0]; + blockTable = &g_blockTable8[0][0]; + columnTable = &g_columnTable8[0][0]; + break; + case PSMT4: + assert( sizeof(g_pageTable4) == width * height * sizeof(g_pageTable4[0][0]) ); + pageTable = &g_pageTable4[0][0]; + blockTable = &g_blockTable4[0][0]; + columnTable = &g_columnTable4[0][0]; + break; + default: + pageTable = NULL; + blockTable = NULL; + columnTable = NULL; + break; + } + } +}; + +extern BLOCK m_Blocks[]; + +#define getPixelAddress24 getPixelAddress32 +#define getPixelAddress24_0 getPixelAddress32_0 +#define getPixelAddress8H getPixelAddress32 +#define getPixelAddress8H_0 getPixelAddress32_0 +#define getPixelAddress4HL getPixelAddress32 +#define getPixelAddress4HL_0 getPixelAddress32_0 +#define getPixelAddress4HH getPixelAddress32 +#define getPixelAddress4HH_0 getPixelAddress32_0 +#define getPixelAddress24Z getPixelAddress32Z +#define getPixelAddress24Z_0 getPixelAddress32Z_0 + +static __forceinline u32 getPixelAddress32(int x, int y, u32 bp, u32 bw) +{ + u32 basepage = ((y >> 5) * (bw >> 6)) + (x >> 6); + u32 word = bp * 64 + basepage * 2048 + g_pageTable32[y&31][x&63]; + return word; +} + +static __forceinline u32 getPixelAddress16(int x, int y, u32 bp, u32 bw) +{ + u32 basepage = ((y >> 6) * (bw >> 6)) + (x >> 6); + u32 word = bp * 128 + basepage * 4096 + g_pageTable16[y&63][x&63]; + return word; +} + +static __forceinline u32 getPixelAddress16S(int x, int y, u32 bp, u32 bw) +{ + u32 basepage = ((y >> 6) * (bw >> 6)) + (x >> 6); + u32 word = bp * 128 + basepage * 4096 + g_pageTable16S[y&63][x&63]; + return word; +} + +static __forceinline u32 getPixelAddress8(int x, int y, u32 bp, u32 bw) +{ + u32 basepage = ((y >> 6) * ((bw + 127) >> 7)) + (x >> 7); + u32 word = bp * 256 + basepage * 8192 + g_pageTable8[y&63][x&127]; + return word; +} + +static __forceinline u32 getPixelAddress4(int x, int y, u32 bp, u32 bw) +{ + u32 basepage = ((y >> 7) * ((bw + 127) >> 7)) + (x >> 7); + u32 word = bp * 512 + basepage * 16384 + g_pageTable4[y&127][x&127]; + return word; +} + +static __forceinline u32 getPixelAddress32Z(int x, int y, u32 bp, u32 bw) +{ + u32 basepage = ((y >> 5) * (bw >> 6)) + (x >> 6); + u32 word = bp * 64 + basepage * 2048 + g_pageTable32Z[y&31][x&63]; + return word; +} + +static __forceinline u32 getPixelAddress16Z(int x, int y, u32 bp, u32 bw) +{ + u32 basepage = ((y >> 6) * (bw >> 6)) + (x >> 6); + u32 word = bp * 128 + basepage * 4096 + g_pageTable16Z[y&63][x&63]; + return word; +} + +static __forceinline u32 getPixelAddress16SZ(int x, int y, u32 bp, u32 bw) +{ + u32 basepage = ((y >> 6) * (bw >> 6)) + (x >> 6); + u32 word = bp * 128 + basepage * 4096 + g_pageTable16SZ[y&63][x&63]; + return word; +} + +/////////////// + +static __forceinline void writePixel32(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) +{ + ((u32*)pmem)[getPixelAddress32(x, y, bp, bw)] = pixel; +} + +static __forceinline void writePixel24(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) +{ + u8 *buf = (u8*) & ((u32*)pmem)[getPixelAddress32(x, y, bp, bw)]; + u8 *pix = (u8*) & pixel; + buf[0] = pix[0]; + buf[1] = pix[1]; + buf[2] = pix[2]; +} + +static __forceinline void writePixel16(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) +{ + ((u16*)pmem)[getPixelAddress16(x, y, bp, bw)] = pixel; +} + +static __forceinline void writePixel16S(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) +{ + ((u16*)pmem)[getPixelAddress16S(x, y, bp, bw)] = pixel; +} + +static __forceinline void writePixel8(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) +{ + ((u8*)pmem)[getPixelAddress8(x, y, bp, bw)] = pixel; +} + +static __forceinline void writePixel8H(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) +{ + ((u8*)pmem)[4*getPixelAddress32(x, y, bp, bw)+3] = pixel; +} + +static __forceinline void writePixel4(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) +{ + u32 addr = getPixelAddress4(x, y, bp, bw); + u8 pix = ((u8*)pmem)[addr/2]; + + if (addr & 0x1)((u8*)pmem)[addr/2] = (pix & 0x0f) | (pixel << 4); + else ((u8*)pmem)[addr/2] = (pix & 0xf0) | (pixel); +} + +static __forceinline void writePixel4HL(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) +{ + u8 *p = (u8*)pmem + 4 * getPixelAddress4HL(x, y, bp, bw) + 3; + *p = (*p & 0xf0) | pixel; +} + +static __forceinline void writePixel4HH(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) +{ + u8 *p = (u8*)pmem + 4 * getPixelAddress4HH(x, y, bp, bw) + 3; + *p = (*p & 0x0f) | (pixel << 4); +} + +static __forceinline void writePixel32Z(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) +{ + ((u32*)pmem)[getPixelAddress32Z(x, y, bp, bw)] = pixel; +} + +static __forceinline void writePixel24Z(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) +{ + u8 *buf = (u8*)pmem + 4 * getPixelAddress32Z(x, y, bp, bw); + u8 *pix = (u8*) & pixel; + buf[0] = pix[0]; + buf[1] = pix[1]; + buf[2] = pix[2]; +} + +static __forceinline void writePixel16Z(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) +{ + ((u16*)pmem)[getPixelAddress16Z(x, y, bp, bw)] = pixel; +} + +static __forceinline void writePixel16SZ(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) +{ + ((u16*)pmem)[getPixelAddress16SZ(x, y, bp, bw)] = pixel; +} + +/////////////// + +static __forceinline u32 readPixel32(const void* pmem, int x, int y, u32 bp, u32 bw) +{ + return ((const u32*)pmem)[getPixelAddress32(x, y, bp, bw)]; +} + +static __forceinline u32 readPixel24(const void* pmem, int x, int y, u32 bp, u32 bw) +{ + return ((const u32*)pmem)[getPixelAddress32(x, y, bp, bw)] & 0xffffff; +} + +static __forceinline u32 readPixel16(const void* pmem, int x, int y, u32 bp, u32 bw) +{ + return ((const u16*)pmem)[getPixelAddress16(x, y, bp, bw)]; +} + +static __forceinline u32 readPixel16S(const void* pmem, int x, int y, u32 bp, u32 bw) +{ + return ((const u16*)pmem)[getPixelAddress16S(x, y, bp, bw)]; +} + +static __forceinline u32 readPixel8(const void* pmem, int x, int y, u32 bp, u32 bw) +{ + return ((const u8*)pmem)[getPixelAddress8(x, y, bp, bw)]; +} + +static __forceinline u32 readPixel8H(const void* pmem, int x, int y, u32 bp, u32 bw) +{ + return ((const u8*)pmem)[4*getPixelAddress32(x, y, bp, bw) + 3]; +} + +static __forceinline u32 readPixel4(const void* pmem, int x, int y, u32 bp, u32 bw) +{ + u32 addr = getPixelAddress4(x, y, bp, bw); + u8 pix = ((const u8*)pmem)[addr/2]; + + if (addr & 0x1) + return pix >> 4; + else + return pix & 0xf; +} + +static __forceinline u32 readPixel4HL(const void* pmem, int x, int y, u32 bp, u32 bw) +{ + const u8 *p = (const u8*)pmem + 4 * getPixelAddress4HL(x, y, bp, bw) + 3; + return *p & 0x0f; +} + +static __forceinline u32 readPixel4HH(const void* pmem, int x, int y, u32 bp, u32 bw) +{ + const u8 *p = (const u8*)pmem + 4 * getPixelAddress4HH(x, y, bp, bw) + 3; + return *p >> 4; +} + +/////////////// + +static __forceinline u32 readPixel32Z(const void* pmem, int x, int y, u32 bp, u32 bw) +{ + return ((const u32*)pmem)[getPixelAddress32Z(x, y, bp, bw)]; +} + +static __forceinline u32 readPixel24Z(const void* pmem, int x, int y, u32 bp, u32 bw) +{ + return ((const u32*)pmem)[getPixelAddress32Z(x, y, bp, bw)] & 0xffffff; +} + +static __forceinline u32 readPixel16Z(const void* pmem, int x, int y, u32 bp, u32 bw) +{ + return ((const u16*)pmem)[getPixelAddress16Z(x, y, bp, bw)]; +} + +static __forceinline u32 readPixel16SZ(const void* pmem, int x, int y, u32 bp, u32 bw) +{ + return ((const u16*)pmem)[getPixelAddress16SZ(x, y, bp, bw)]; +} + +/////////////////////////////// +// Functions that take 0 bps // +/////////////////////////////// + +static __forceinline u32 getPixelAddress32_0(int x, int y, u32 bw) { return getPixelAddress32(x, y, 0, bw); } +static __forceinline u32 getPixelAddress16_0(int x, int y, u32 bw) { return getPixelAddress16(x, y, 0, bw); } +static __forceinline u32 getPixelAddress16S_0(int x, int y, u32 bw) { return getPixelAddress16S(x, y, 0, bw); } +static __forceinline u32 getPixelAddress8_0(int x, int y, u32 bw) { return getPixelAddress8(x, y, 0, bw); } +static __forceinline u32 getPixelAddress4_0(int x, int y, u32 bw) { return getPixelAddress4(x, y, 0, bw); } +static __forceinline u32 getPixelAddress32Z_0(int x, int y, u32 bw) { return getPixelAddress32Z(x, y, 0, bw); } +static __forceinline u32 getPixelAddress16Z_0(int x, int y, u32 bw) { return getPixelAddress16Z(x, y, 0, bw); } +static __forceinline u32 getPixelAddress16SZ_0(int x, int y, u32 bw) { return getPixelAddress16SZ(x, y, 0, bw); } + +/////////////// + +static __forceinline void writePixel32_0(void* pmem, int x, int y, u32 pixel, u32 bw) { writePixel32(pmem, x, y, pixel, 0, bw); } +static __forceinline void writePixel24_0(void* pmem, int x, int y, u32 pixel, u32 bw) { writePixel24(pmem, x, y, pixel, 0, bw); } +static __forceinline void writePixel16_0(void* pmem, int x, int y, u32 pixel, u32 bw) { writePixel16(pmem, x, y, pixel, 0, bw); } +static __forceinline void writePixel16S_0(void* pmem, int x, int y, u32 pixel, u32 bw) { writePixel16S(pmem, x, y, pixel, 0, bw); } +static __forceinline void writePixel8_0(void* pmem, int x, int y, u32 pixel, u32 bw) { writePixel8(pmem, x, y, pixel, 0, bw); } +static __forceinline void writePixel8H_0(void* pmem, int x, int y, u32 pixel, u32 bw) { writePixel8H(pmem, x, y, pixel, 0, bw); } +static __forceinline void writePixel4_0(void* pmem, int x, int y, u32 pixel, u32 bw) { writePixel4(pmem, x, y, pixel, 0, bw); } +static __forceinline void writePixel4HL_0(void* pmem, int x, int y, u32 pixel, u32 bw) { writePixel4HL(pmem, x, y, pixel, 0, bw); } +static __forceinline void writePixel4HH_0(void* pmem, int x, int y, u32 pixel, u32 bw) { writePixel4HH(pmem, x, y, pixel, 0, bw); } +static __forceinline void writePixel32Z_0(void* pmem, int x, int y, u32 pixel, u32 bw) { writePixel32Z(pmem, x, y, pixel, 0, bw); } +static __forceinline void writePixel24Z_0(void* pmem, int x, int y, u32 pixel, u32 bw) { writePixel24Z(pmem, x, y, pixel, 0, bw); } +static __forceinline void writePixel16Z_0(void* pmem, int x, int y, u32 pixel, u32 bw) { writePixel16Z(pmem, x, y, pixel, 0, bw); } +static __forceinline void writePixel16SZ_0(void* pmem, int x, int y, u32 pixel, u32 bw) { writePixel16SZ(pmem, x, y, pixel, 0, bw); } + +/////////////// + +static __forceinline u32 readPixel32_0(const void* pmem, int x, int y, u32 bw) { return readPixel32(pmem, x, y, 0, bw); } +static __forceinline u32 readPixel24_0(const void* pmem, int x, int y, u32 bw) { return readPixel24(pmem, x, y, 0, bw); } +static __forceinline u32 readPixel16_0(const void* pmem, int x, int y, u32 bw) { return readPixel16(pmem, x, y, 0, bw); } +static __forceinline u32 readPixel16S_0(const void* pmem, int x, int y, u32 bw) { return readPixel16S(pmem, x, y, 0, bw); } +static __forceinline u32 readPixel8_0(const void* pmem, int x, int y, u32 bw) { return readPixel8(pmem, x, y, 0, bw); } +static __forceinline u32 readPixel8H_0(const void* pmem, int x, int y, u32 bw) { return readPixel8H(pmem, x, y, 0, bw); } +static __forceinline u32 readPixel4_0(const void* pmem, int x, int y, u32 bw) { return readPixel4(pmem, x, y, 0, bw); } +static __forceinline u32 readPixel4HL_0(const void* pmem, int x, int y, u32 bw) { return readPixel4HL(pmem, x, y, 0, bw); } +static __forceinline u32 readPixel4HH_0(const void* pmem, int x, int y, u32 bw) { return readPixel4HH(pmem, x, y, 0, bw); } +static __forceinline u32 readPixel32Z_0(const void* pmem, int x, int y, u32 bw) { return readPixel32Z(pmem, x, y, 0, bw); } +static __forceinline u32 readPixel24Z_0(const void* pmem, int x, int y, u32 bw) { return readPixel24Z(pmem, x, y, 0, bw); } +static __forceinline u32 readPixel16Z_0(const void* pmem, int x, int y, u32 bw) { return readPixel16Z(pmem, x, y, 0, bw); } +static __forceinline u32 readPixel16SZ_0(const void* pmem, int x, int y, u32 bw) { return readPixel16SZ(pmem, x, y, 0, bw); } + +/////////////// + +extern int TransferHostLocal32(const void* pbyMem, u32 nQWordSize); +extern int TransferHostLocal32Z(const void* pbyMem, u32 nQWordSize); +extern int TransferHostLocal24(const void* pbyMem, u32 nQWordSize); +extern int TransferHostLocal24Z(const void* pbyMem, u32 nQWordSize); +extern int TransferHostLocal16(const void* pbyMem, u32 nQWordSize); +extern int TransferHostLocal16S(const void* pbyMem, u32 nQWordSize); +extern int TransferHostLocal16Z(const void* pbyMem, u32 nQWordSize); +extern int TransferHostLocal16SZ(const void* pbyMem, u32 nQWordSize); +extern int TransferHostLocal8(const void* pbyMem, u32 nQWordSize); +extern int TransferHostLocal4(const void* pbyMem, u32 nQWordSize); +extern int TransferHostLocal8H(const void* pbyMem, u32 nQWordSize); +extern int TransferHostLocal4HL(const void* pbyMem, u32 nQWordSize); +extern int TransferHostLocal4HH(const void* pbyMem, u32 nQWordSize); + +extern void TransferLocalHost32(void* pbyMem, u32 nQWordSize); +extern void TransferLocalHost24(void* pbyMem, u32 nQWordSize); +extern void TransferLocalHost16(void* pbyMem, u32 nQWordSize); +extern void TransferLocalHost16S(void* pbyMem, u32 nQWordSize); +extern void TransferLocalHost8(void* pbyMem, u32 nQWordSize); +extern void TransferLocalHost4(void* pbyMem, u32 nQWordSize); +extern void TransferLocalHost8H(void* pbyMem, u32 nQWordSize); +extern void TransferLocalHost4HL(void* pbyMem, u32 nQWordSize); +extern void TransferLocalHost4HH(void* pbyMem, u32 nQWordSize); +extern void TransferLocalHost32Z(void* pbyMem, u32 nQWordSize); +extern void TransferLocalHost24Z(void* pbyMem, u32 nQWordSize); +extern void TransferLocalHost16Z(void* pbyMem, u32 nQWordSize); +extern void TransferLocalHost16SZ(void* pbyMem, u32 nQWordSize); + +#endif /* __MEM_H__ */ diff --git a/plugins/zzogl-pg-cg/opengl/Mem_Swizzle.cpp b/plugins/zzogl-pg-cg/opengl/Mem_Swizzle.cpp new file mode 100644 index 000000000..4f49dfde7 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/Mem_Swizzle.cpp @@ -0,0 +1,756 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "GS.h" +#include "Mem.h" +#include "Mem_Swizzle.h" +#ifdef ZEROGS_SSE2 +#include +#endif + +// WARNING a sfence instruction must be call after SwizzleBlock sse2 function + +// Current port of the ASM function to intrinsic +#define INTRINSIC_PORT_16 +#define INTRINSIC_PORT_8 +#define INTRINSIC_PORT_4 +#ifdef ZEROGS_SSE2 +static const __aligned16 u32 mask_24b_H[4] = {0xFF000000, 0x0000FFFF, 0xFF000000, 0x0000FFFF}; +static const __aligned16 u32 mask_24b_L[4] = {0x00FFFFFF, 0x00000000, 0x00FFFFFF, 0x00000000}; + +template +__forceinline void SwizzleBlock32_sse2_I(u8 *dst, u8 *src, int pitch) +{ + __m128i src_0; + __m128i src_1; + __m128i src_2; + __m128i src_3; + + for (int i=3 ; i >= 0 ; --i) { + // load + if (aligned) { + src_0 = _mm_load_si128((__m128i*)src); // 5 4 1 0 + src_1 = _mm_load_si128((__m128i*)(src+16)); // 13 12 9 8 + src_2 = _mm_load_si128((__m128i*)(src+pitch)); // 7 6 3 2 + src_3 = _mm_load_si128((__m128i*)(src+16+pitch)); // 15 14 11 10 + } else { + src_0 = _mm_loadu_si128((__m128i*)src); // 5 4 1 0 + src_1 = _mm_loadu_si128((__m128i*)(src+16)); // 13 12 9 8 + src_2 = _mm_loadu_si128((__m128i*)(src+pitch)); // 7 6 3 2 + src_3 = _mm_loadu_si128((__m128i*)(src+16+pitch)); // 15 14 11 10 + } + + // Reorder + __m128i dst_0 = _mm_unpacklo_epi64(src_0, src_2); // 3 2 1 0 + __m128i dst_1 = _mm_unpackhi_epi64(src_0, src_2); // 7 6 5 4 + __m128i dst_2 = _mm_unpacklo_epi64(src_1, src_3); // 11 10 9 8 + __m128i dst_3 = _mm_unpackhi_epi64(src_1, src_3); // 15 14 13 12 + + // store + _mm_stream_si128((__m128i*)dst, dst_0); + _mm_stream_si128(((__m128i*)dst)+1, dst_1); + _mm_stream_si128(((__m128i*)dst)+2, dst_2); + _mm_stream_si128(((__m128i*)dst)+3, dst_3); + + // update the pointer + dst += 64; + src += 2*pitch; + } +} + +template +__forceinline void SwizzleBlock16_sse2_I(u8 *dst, u8 *src, int pitch) +{ + __m128i src_0_L; + __m128i src_0_H; + __m128i src_2_L; + __m128i src_2_H; + + for (int i=3 ; i >= 0 ; --i) { + // load + if (aligned) { + src_0_L = _mm_load_si128((__m128i*)src); // 13L 12L 9L 8L 5L 4L 1L 0L + src_0_H = _mm_load_si128((__m128i*)(src+16)); // 13H 12H 9H 8H 5H 4H 1H 0H + src_2_L = _mm_load_si128((__m128i*)(src+pitch)); // 15L 14L 11L 10L 7L 6L 3L 2L + src_2_H = _mm_load_si128((__m128i*)(src+16+pitch)); // 15H 14H 11H 10H 7H 6H 3H 2H + } else { + src_0_L = _mm_loadu_si128((__m128i*)src); // 13L 12L 9L 8L 5L 4L 1L 0L + src_0_H = _mm_loadu_si128((__m128i*)(src+16)); // 13H 12H 9H 8H 5H 4H 1H 0H + src_2_L = _mm_loadu_si128((__m128i*)(src+pitch)); // 15L 14L 11L 10L 7L 6L 3L 2L + src_2_H = _mm_loadu_si128((__m128i*)(src+16+pitch)); // 15H 14H 11H 10H 7H 6H 3H 2H + } + + // Interleave L and H to obtains 32 bits packets + __m128i dst_0_tmp = _mm_unpacklo_epi16(src_0_L, src_0_H); // 5H 5L 4H 4L 1H 1L 0H 0L + __m128i dst_1_tmp = _mm_unpacklo_epi16(src_2_L, src_2_H); // 7H 7L 6H 6L 3H 3L 2H 2L + __m128i dst_2_tmp = _mm_unpackhi_epi16(src_0_L, src_0_H); // 13H 13L 12H 12L 9H 9L 8H 8L + __m128i dst_3_tmp = _mm_unpackhi_epi16(src_2_L, src_2_H); // 15H 15L 14H 14L 11H 11L 10H 10L + + // Reorder + __m128i dst_0 = _mm_unpacklo_epi64(dst_0_tmp, dst_1_tmp); // 3 2 1 0 + __m128i dst_1 = _mm_unpackhi_epi64(dst_0_tmp, dst_1_tmp); // 7 6 5 4 + __m128i dst_2 = _mm_unpacklo_epi64(dst_2_tmp, dst_3_tmp); // 11 10 9 8 + __m128i dst_3 = _mm_unpackhi_epi64(dst_2_tmp, dst_3_tmp); // 15 14 13 12 + + // store + _mm_stream_si128((__m128i*)dst, dst_0); + _mm_stream_si128(((__m128i*)dst)+1, dst_1); + _mm_stream_si128(((__m128i*)dst)+2, dst_2); + _mm_stream_si128(((__m128i*)dst)+3, dst_3); + + // update the pointer + dst += 64; + src += 2*pitch; + } +} + +// Template the code to improve reuse of code +template +__forceinline void SwizzleColumn8_sse2_I(u8 *dst, u8 *src, int pitch) +{ + __m128i src_0; + __m128i src_1; + __m128i src_2; + __m128i src_3; + + // load 4 line of 16*8 bits packets + if (aligned) { + src_0 = _mm_load_si128((__m128i*)src); + src_2 = _mm_load_si128((__m128i*)(src+pitch)); + src_1 = _mm_load_si128((__m128i*)(src+2*pitch)); + src_3 = _mm_load_si128((__m128i*)(src+3*pitch)); + } else { + src_0 = _mm_loadu_si128((__m128i*)src); + src_2 = _mm_loadu_si128((__m128i*)(src+pitch)); + src_1 = _mm_loadu_si128((__m128i*)(src+2*pitch)); + src_3 = _mm_loadu_si128((__m128i*)(src+3*pitch)); + } + + // shuffle 2 lines to align pixels + if (INDEX == 0 || INDEX == 2) { + src_1 = _mm_shuffle_epi32(src_1, 0xB1); // 13 12 9 8 5 4 1 0 ... (byte 3 & 1) + src_3 = _mm_shuffle_epi32(src_3, 0xB1); // 15 14 11 10 7 6 3 2 ... (byte 3 & 1) + } else if (INDEX == 1 || INDEX == 3) { + src_0 = _mm_shuffle_epi32(src_0, 0xB1); // 13 12 9 8 5 4 1 0 ... (byte 2 & 0) + src_2 = _mm_shuffle_epi32(src_2, 0xB1); // 15 14 11 10 7 6 3 2 ... (byte 2 & 0) + } else { + assert(0); + } + // src_0 = 13 12 9 8 5 4 1 0 ... (byte 2 & 0) + // src_1 = 13 12 9 8 5 4 1 0 ... (byte 3 & 1) + // src_2 = 15 14 11 10 7 6 3 2 ... (byte 2 & 0) + // src_3 = 15 14 11 10 7 6 3 2 ... (byte 3 & 1) + + // Interleave byte 1 & 0 to obtain 16 bits packets + __m128i src_0_L = _mm_unpacklo_epi8(src_0, src_1); // 13L 12L 9L 8L 5L 4L 1L 0L + __m128i src_1_L = _mm_unpacklo_epi8(src_2, src_3); // 15L 14L 11L 10L 7L 6L 3L 2L + // Interleave byte 3 & 2 to obtain 16 bits packets + __m128i src_0_H = _mm_unpackhi_epi8(src_0, src_1); // 13H 12H 9H 8H 5H 4H 1H 0H + __m128i src_1_H = _mm_unpackhi_epi8(src_2, src_3); // 15H 14H 11H 10H 7H 6H 3H 2H + + // Interleave H and L to obtain 32 bits packets + __m128i dst_0_tmp = _mm_unpacklo_epi16(src_0_L, src_0_H); // 5 4 1 0 + __m128i dst_1_tmp = _mm_unpacklo_epi16(src_1_L, src_1_H); // 7 6 3 2 + __m128i dst_2_tmp = _mm_unpackhi_epi16(src_0_L, src_0_H); // 13 12 9 8 + __m128i dst_3_tmp = _mm_unpackhi_epi16(src_1_L, src_1_H); // 15 14 11 10 + + // Reorder the 32 bits packets + __m128i dst_0 = _mm_unpacklo_epi64(dst_0_tmp, dst_1_tmp); // 3 2 1 0 + __m128i dst_1 = _mm_unpackhi_epi64(dst_0_tmp, dst_1_tmp); // 7 6 5 4 + __m128i dst_2 = _mm_unpacklo_epi64(dst_2_tmp, dst_3_tmp); // 11 10 9 8 + __m128i dst_3 = _mm_unpackhi_epi64(dst_2_tmp, dst_3_tmp); // 15 14 13 12 + + // store + _mm_stream_si128((__m128i*)dst, dst_0); + _mm_stream_si128(((__m128i*)dst)+1, dst_1); + _mm_stream_si128(((__m128i*)dst)+2, dst_2); + _mm_stream_si128(((__m128i*)dst)+3, dst_3); +} + +template +__forceinline void SwizzleBlock8_sse2_I(u8 *dst, u8 *src, int pitch) +{ + SwizzleColumn8_sse2_I(dst, src, pitch); + + dst += 64; + src += 4*pitch; + SwizzleColumn8_sse2_I(dst, src, pitch); + + dst += 64; + src += 4*pitch; + SwizzleColumn8_sse2_I(dst, src, pitch); + + dst += 64; + src += 4*pitch; + SwizzleColumn8_sse2_I(dst, src, pitch); +} + +// Template the code to improve reuse of code +template +__forceinline void SwizzleColumn4_sse2_I(u8 *dst, u8 *src, int pitch) +{ + __m128i src_0; + __m128i src_1; + __m128i src_2; + __m128i src_3; + + // Build a mask (tranform a u32 to a 4 packets u32) + const u32 mask_template = 0x0f0f0f0f; + __m128i mask = _mm_cvtsi32_si128(mask_template); + mask = _mm_shuffle_epi32(mask, 0); + + // load 4 line of 32*4 bits packets + if (aligned) { + src_0 = _mm_load_si128((__m128i*)src); + src_2 = _mm_load_si128((__m128i*)(src+pitch)); + src_1 = _mm_load_si128((__m128i*)(src+2*pitch)); + src_3 = _mm_load_si128((__m128i*)(src+3*pitch)); + } else { + src_0 = _mm_loadu_si128((__m128i*)src); + src_2 = _mm_loadu_si128((__m128i*)(src+pitch)); + src_1 = _mm_loadu_si128((__m128i*)(src+2*pitch)); + src_3 = _mm_loadu_si128((__m128i*)(src+3*pitch)); + } + + // shuffle 2 lines to align pixels + if (INDEX == 0 || INDEX == 2) { + src_1 = _mm_shufflelo_epi16(src_1, 0xB1); + src_1 = _mm_shufflehi_epi16(src_1, 0xB1); // 13 12 9 8 5 4 1 0 ... (Half-byte 7 & 5 & 3 & 1) + src_3 = _mm_shufflelo_epi16(src_3, 0xB1); + src_3 = _mm_shufflehi_epi16(src_3, 0xB1); // 15 14 11 10 7 6 3 2 ... (Half-byte 7 & 5 & 3 & 1) + } else if (INDEX == 1 || INDEX == 3) { + src_0 = _mm_shufflelo_epi16(src_0, 0xB1); + src_0 = _mm_shufflehi_epi16(src_0, 0xB1); // 13 12 9 8 5 4 1 0 ... (Half-byte 6 & 4 & 2 & 0) + src_2 = _mm_shufflelo_epi16(src_2, 0xB1); + src_2 = _mm_shufflehi_epi16(src_2, 0xB1); // 15 14 11 10 7 6 3 2 ... (Half-byte 6 & 4 & 2 & 0) + } else { + assert(0); + } + // src_0 = 13 12 9 8 5 4 1 0 ... (Half-byte 6 & 4 & 2 & 0) + // src_1 = 13 12 9 8 5 4 1 0 ... (Half-byte 7 & 5 & 3 & 1) + // src_2 = 15 14 11 10 7 6 3 2 ... (Half-byte 6 & 4 & 2 & 0) + // src_3 = 15 14 11 10 7 6 3 2 ... (Half-byte 7 & 5 & 3 & 1) + + // ** Interleave Half-byte to obtain 8 bits packets + // Shift value to ease 4 bits filter. + // Note use a packet shift to allow a 4bits shifts + __m128i src_0_shift = _mm_srli_epi64(src_0, 4); // ? 13 12 9 8 5 4 1 ... (Half-byte 6 & 4 & 2 & 0) + __m128i src_1_shift = _mm_slli_epi64(src_1, 4); // 12 9 8 5 4 1 0 ? ... (Half-byte 7 & 5 & 3 & 1) + __m128i src_2_shift = _mm_srli_epi64(src_2, 4); // ? 15 14 11 10 7 6 3 ... (Half-byte 6 & 4 & 2 & 0) + __m128i src_3_shift = _mm_slli_epi64(src_3, 4); // 14 11 10 7 6 3 2 ? ... (Half-byte 7 & 5 & 3 & 1) + + // 12 - 8 - 4 - 0 - (HB odd) || - 12 - 8 - 4 - 0 (HB even) => 12 8 4 0 (byte 3 & 2 & 1 & 0) + src_0 = _mm_or_si128(_mm_andnot_si128(mask, src_1_shift), _mm_and_si128(mask, src_0)); + // - 13 - 9 - 5 - 1 (HB even) || 13 - 9 - 5 - 1 - (HB odd) => 13 9 5 1 (byte 3 & 2 & 1 & 0) + src_1 = _mm_or_si128(_mm_and_si128(mask, src_0_shift), _mm_andnot_si128(mask, src_1)); + + // 14 - 10 - 6 - 2 - (HB odd) || - 14 - 10 - 6 - 2 (HB even) => 14 10 6 2 (byte 3 & 2 & 1 & 0) + src_2 = _mm_or_si128(_mm_andnot_si128(mask, src_3_shift), _mm_and_si128(mask, src_2)); + // - 15 - 11 - 7 - 3 (HB even) || 15 - 11 - 7 - 3 - (HB odd) => 15 11 7 3 (byte 3 & 2 & 1 & 0) + src_3 = _mm_or_si128(_mm_and_si128(mask, src_2_shift), _mm_andnot_si128(mask, src_3)); + + + // reorder the 8 bits packets + __m128i src_0_tmp = _mm_unpacklo_epi8(src_0, src_1); // 13 12 9 8 5 4 1 0 (byte 1 & 0) + __m128i src_1_tmp = _mm_unpackhi_epi8(src_0, src_1); // 13 12 9 8 5 4 1 0 (byte 3 & 2) + __m128i src_2_tmp = _mm_unpacklo_epi8(src_2, src_3); // 15 14 11 10 7 6 3 2 (byte 1 & 0) + __m128i src_3_tmp = _mm_unpackhi_epi8(src_2, src_3); // 15 14 11 10 7 6 3 2 (byte 3 & 2) + + // interleave byte to obtain 32 bits packets + __m128i src_0_L = _mm_unpacklo_epi8(src_0_tmp, src_1_tmp); // 2.13 0.13 2.12 0.12 2.9 0.9 2.8 0.8 2.5 0.5 2.4 0.4 2.1 0.1 2.0 0.0 + __m128i src_0_H = _mm_unpackhi_epi8(src_0_tmp, src_1_tmp); // 3.13 1.13 3.12 1.12 3.9 1.9 3.8 1.8 3.5 1.5 3.4 1.4 3.1 1.1 3.0 1.0 + __m128i src_1_L = _mm_unpacklo_epi8(src_2_tmp, src_3_tmp); // 2.15 0.15 2.14 0.14 2.11 0.11 2.10 0.10 2.7 0.7 2.6 0.6 2.3 0.3 2.2 0.2 + __m128i src_1_H = _mm_unpackhi_epi8(src_2_tmp, src_3_tmp); // 3.15 1.15 3.14 1.14 3.11 1.11 3.10 1.10 3.7 1.7 3.6 1.6 3.3 1.3 3.2 1.2 + + __m128i dst_0_tmp = _mm_unpacklo_epi8(src_0_L, src_0_H); // 5 4 1 0 + __m128i dst_1_tmp = _mm_unpacklo_epi8(src_1_L, src_1_H); // 7 6 3 2 + __m128i dst_2_tmp = _mm_unpackhi_epi8(src_0_L, src_0_H); // 13 12 9 8 + __m128i dst_3_tmp = _mm_unpackhi_epi8(src_1_L, src_1_H); // 15 14 11 10 + + // Reorder the 32 bits packets + __m128i dst_0 = _mm_unpacklo_epi64(dst_0_tmp, dst_1_tmp); // 3 2 1 0 + __m128i dst_1 = _mm_unpackhi_epi64(dst_0_tmp, dst_1_tmp); // 7 6 5 4 + __m128i dst_2 = _mm_unpacklo_epi64(dst_2_tmp, dst_3_tmp); // 11 10 9 8 + __m128i dst_3 = _mm_unpackhi_epi64(dst_2_tmp, dst_3_tmp); // 15 14 13 12 + + // store + _mm_stream_si128((__m128i*)dst, dst_0); + _mm_stream_si128(((__m128i*)dst)+1, dst_1); + _mm_stream_si128(((__m128i*)dst)+2, dst_2); + _mm_stream_si128(((__m128i*)dst)+3, dst_3); +} + +template +__forceinline void SwizzleBlock4_sse2_I(u8 *dst, u8 *src, int pitch) +{ + SwizzleColumn4_sse2_I(dst, src, pitch); + + dst += 64; + src += 4*pitch; + SwizzleColumn4_sse2_I(dst, src, pitch); + + dst += 64; + src += 4*pitch; + SwizzleColumn4_sse2_I(dst, src, pitch); + + dst += 64; + src += 4*pitch; + SwizzleColumn4_sse2_I(dst, src, pitch); +} + +template +__forceinline void SwizzleBlock8H_4H(u8 *dst, u8 *src, int pitch) +{ + __m128i zero_128 = _mm_setzero_si128(); + __m128i src_0; + __m128i src_1; + __m128i src_2; + __m128i src_3; + __m128i src_0_init_H; + __m128i src_0_init_L; + __m128i src_2_init_H; + __m128i src_2_init_L; + __m128i src_0_init; + __m128i src_2_init; + + __m128i upper_mask = _mm_cvtsi32_si128(0xF0F0F0F0); + // Build the write_mask (tranform a u32 to a 4 packets u32) + __m128i write_mask; + if (FOUR_BIT) { + if (UPPER) write_mask = _mm_cvtsi32_si128(0xF0000000); + else write_mask = _mm_cvtsi32_si128(0x0F000000); + } else { + write_mask = _mm_cvtsi32_si128(0xFF000000); + } + write_mask = _mm_shuffle_epi32(write_mask, 0); + + for (int i=3 ; i >= 0 ; --i) { + if (FOUR_BIT) { + src_0_init = _mm_cvtsi32_si128(*(u32*)src); + src_2_init = _mm_cvtsi32_si128(*(u32*)(src + pitch)); + } else { + src_0_init = _mm_loadl_epi64((__m128i*)src); + src_2_init = _mm_loadl_epi64((__m128i*)(src + pitch)); + } + + // Convert to 8 bits + if (FOUR_BIT) { + src_0_init_H = _mm_and_si128(upper_mask, src_0_init); + src_0_init_L = _mm_andnot_si128(upper_mask, src_0_init); + src_2_init_H = _mm_and_si128(upper_mask, src_2_init); + src_2_init_L = _mm_andnot_si128(upper_mask, src_2_init); + + if (UPPER) { + src_0_init_L = _mm_slli_epi32(src_0_init_L, 4); + src_2_init_L = _mm_slli_epi32(src_2_init_L, 4); + } else { + src_0_init_H = _mm_srli_epi32(src_0_init_H, 4); + src_2_init_H = _mm_srli_epi32(src_2_init_H, 4); + } + + // Repack the src to keep HByte order + src_0_init = _mm_unpacklo_epi8(src_0_init_L, src_0_init_H); + src_2_init = _mm_unpacklo_epi8(src_2_init_L, src_2_init_H); + } + + // transform to 16 bits (add 0 in low bits) + src_0_init = _mm_unpacklo_epi8(zero_128, src_0_init); + src_2_init = _mm_unpacklo_epi8(zero_128, src_2_init); + + // transform to 32 bits (add 0 in low bits) + src_0 = _mm_unpacklo_epi16(zero_128, src_0_init); + src_1 = _mm_unpackhi_epi16(zero_128, src_0_init); + src_2 = _mm_unpacklo_epi16(zero_128, src_2_init); + src_3 = _mm_unpackhi_epi16(zero_128, src_2_init); + + // Reorder the data (same as 32 bits format) + __m128i dst_0 = _mm_unpacklo_epi64(src_0, src_2); + __m128i dst_1 = _mm_unpackhi_epi64(src_0, src_2); + __m128i dst_2 = _mm_unpacklo_epi64(src_1, src_3); + __m128i dst_3 = _mm_unpackhi_epi64(src_1, src_3); + + // Load previous value and apply the ~write_mask + __m128i old_dst_0 = _mm_andnot_si128(write_mask, _mm_load_si128((__m128i*)dst)); + dst_0 = _mm_or_si128(dst_0, old_dst_0); + + __m128i old_dst_1 = _mm_andnot_si128(write_mask, _mm_load_si128(((__m128i*)dst)+1)); + dst_1 = _mm_or_si128(dst_1, old_dst_1); + + __m128i old_dst_2 = _mm_andnot_si128(write_mask, _mm_load_si128(((__m128i*)dst)+2)); + dst_2 = _mm_or_si128(dst_2, old_dst_2); + + __m128i old_dst_3 = _mm_andnot_si128(write_mask, _mm_load_si128(((__m128i*)dst)+3)); + dst_3 = _mm_or_si128(dst_3, old_dst_3); + + // store + _mm_stream_si128((__m128i*)dst, dst_0); + _mm_stream_si128(((__m128i*)dst)+1, dst_1); + _mm_stream_si128(((__m128i*)dst)+2, dst_2); + _mm_stream_si128(((__m128i*)dst)+3, dst_3); + + // update the pointer + dst += 64; + src += 2*pitch; + } +} + +// special swizzle macros - which I converted to functions. + +__forceinline void SwizzleBlock32(u8 *dst, u8 *src, int pitch) +{ + SwizzleBlock32_sse2_I(dst, src, pitch); +} + +__forceinline void SwizzleBlock24(u8 *dst, u8 *src, int pitch) +{ + __m128i mask_H = _mm_load_si128((__m128i*)mask_24b_H); + __m128i mask_L = _mm_load_si128((__m128i*)mask_24b_L); + // Build the write_mask (tranform a u32 to a 4 packets u32) + __m128i write_mask = _mm_cvtsi32_si128(0x00FFFFFF); + write_mask = _mm_shuffle_epi32(write_mask, 0); + + for (int i=3 ; i >= 0 ; --i) { + // Note src can be out of bound of GS memory (but there is some spare allocation + // to avoid a tricky corner case) + __m128i src_0 = _mm_loadu_si128((__m128i*)src); + __m128i src_1 = _mm_loadu_si128((__m128i*)(src+12)); + __m128i src_2 = _mm_loadu_si128((__m128i*)(src+pitch)); + __m128i src_3 = _mm_loadu_si128((__m128i*)(src+pitch+12)); + + // transform 24 bits value to 32 bits one + // 1/ Align a little the data + src_0 = _mm_slli_si128(src_0, 2); + src_0 = _mm_shufflelo_epi16(src_0, 0x39); + + src_1 = _mm_slli_si128(src_1, 2); + src_1 = _mm_shufflelo_epi16(src_1, 0x39); + + src_2 = _mm_slli_si128(src_2, 2); + src_2 = _mm_shufflelo_epi16(src_2, 0x39); + + src_3 = _mm_slli_si128(src_3, 2); + src_3 = _mm_shufflelo_epi16(src_3, 0x39); + + // 2/ Filter the 24 bits pixels & do the conversion + __m128i src_0_H = _mm_and_si128(src_0, mask_H); + __m128i src_0_L = _mm_and_si128(src_0, mask_L); + src_0_H = _mm_slli_si128(src_0_H, 1); + src_0 = _mm_or_si128(src_0_H, src_0_L); + + __m128i src_1_H = _mm_and_si128(src_1, mask_H); + __m128i src_1_L = _mm_and_si128(src_1, mask_L); + src_1_H = _mm_slli_si128(src_1_H, 1); + src_1 = _mm_or_si128(src_1_H, src_1_L); + + __m128i src_2_H = _mm_and_si128(src_2, mask_H); + __m128i src_2_L = _mm_and_si128(src_2, mask_L); + src_2_H = _mm_slli_si128(src_2_H, 1); + src_2 = _mm_or_si128(src_2_H, src_2_L); + + __m128i src_3_H = _mm_and_si128(src_3, mask_H); + __m128i src_3_L = _mm_and_si128(src_3, mask_L); + src_3_H = _mm_slli_si128(src_3_H, 1); + src_3 = _mm_or_si128(src_3_H, src_3_L); + + // Reorder the data (same as 32 bits format) + __m128i dst_0 = _mm_unpacklo_epi64(src_0, src_2); + __m128i dst_1 = _mm_unpackhi_epi64(src_0, src_2); + __m128i dst_2 = _mm_unpacklo_epi64(src_1, src_3); + __m128i dst_3 = _mm_unpackhi_epi64(src_1, src_3); + + // Load previous value and apply the ~write_mask + __m128i old_dst_0 = _mm_andnot_si128(write_mask, _mm_load_si128((__m128i*)dst)); + dst_0 = _mm_or_si128(dst_0, old_dst_0); + + __m128i old_dst_1 = _mm_andnot_si128(write_mask, _mm_load_si128(((__m128i*)dst)+1)); + dst_1 = _mm_or_si128(dst_1, old_dst_1); + + __m128i old_dst_2 = _mm_andnot_si128(write_mask, _mm_load_si128(((__m128i*)dst)+2)); + dst_2 = _mm_or_si128(dst_2, old_dst_2); + + __m128i old_dst_3 = _mm_andnot_si128(write_mask, _mm_load_si128(((__m128i*)dst)+3)); + dst_3 = _mm_or_si128(dst_3, old_dst_3); + + // store + _mm_stream_si128((__m128i*)dst, dst_0); + _mm_stream_si128(((__m128i*)dst)+1, dst_1); + _mm_stream_si128(((__m128i*)dst)+2, dst_2); + _mm_stream_si128(((__m128i*)dst)+3, dst_3); + + // update the pointer + dst += 64; + src += 2*pitch; + } +} + +__forceinline void SwizzleBlock16(u8 *dst, u8 *src, int pitch) +{ +#ifdef INTRINSIC_PORT_16 + SwizzleBlock16_sse2_I(dst, src, pitch); +#else + SwizzleBlock16_sse2(dst, src, pitch); +#endif +} + +__forceinline void SwizzleBlock8(u8 *dst, u8 *src, int pitch) +{ +#ifdef INTRINSIC_PORT_8 + SwizzleBlock8_sse2_I(dst, src, pitch); +#else + SwizzleBlock8_sse2(dst, src, pitch); +#endif +} + +__forceinline void SwizzleBlock4(u8 *dst, u8 *src, int pitch) +{ +#ifdef INTRINSIC_PORT_4 + SwizzleBlock4_sse2_I(dst, src, pitch); +#else + SwizzleBlock4_sse2(dst, src, pitch); +#endif +} + +__forceinline void SwizzleBlock32u(u8 *dst, u8 *src, int pitch) +{ + SwizzleBlock32_sse2_I(dst, src, pitch); +} + +__forceinline void SwizzleBlock16u(u8 *dst, u8 *src, int pitch) +{ +#ifdef INTRINSIC_PORT_16 + SwizzleBlock16_sse2_I(dst, src, pitch); +#else + SwizzleBlock16u_sse2(dst, src, pitch); +#endif +} + +__forceinline void SwizzleBlock8u(u8 *dst, u8 *src, int pitch) +{ +#ifdef INTRINSIC_PORT_8 + SwizzleBlock8_sse2_I(dst, src, pitch); +#else + SwizzleBlock8u_sse2(dst, src, pitch); +#endif +} + +__forceinline void SwizzleBlock4u(u8 *dst, u8 *src, int pitch) +{ +#ifdef INTRINSIC_PORT_4 + SwizzleBlock4_sse2_I(dst, src, pitch); +#else + SwizzleBlock4u_sse2(dst, src, pitch); +#endif +} + +__forceinline void SwizzleBlock8H(u8 *dst, u8 *src, int pitch) +{ + SwizzleBlock8H_4H(dst, src, pitch); +} + +__forceinline void SwizzleBlock4HH(u8 *dst, u8 *src, int pitch) +{ + SwizzleBlock8H_4H(dst, src, pitch); +} + +__forceinline void SwizzleBlock4HL(u8 *dst, u8 *src, int pitch) +{ + SwizzleBlock8H_4H(dst, src, pitch); +} + +#else + +__forceinline void SwizzleBlock32(u8 *dst, u8 *src, int pitch) +{ + SwizzleBlock32_c(dst, src, pitch); +} + +__forceinline void SwizzleBlock16(u8 *dst, u8 *src, int pitch) +{ + SwizzleBlock16_c(dst, src, pitch); +} + +__forceinline void SwizzleBlock8(u8 *dst, u8 *src, int pitch) +{ + SwizzleBlock8_c(dst, src, pitch); +} + +__forceinline void SwizzleBlock4(u8 *dst, u8 *src, int pitch) +{ + SwizzleBlock4_c(dst, src, pitch); +} + +__forceinline void SwizzleBlock32u(u8 *dst, u8 *src, int pitch) +{ + SwizzleBlock32_c(dst, src, pitch); +} + +__forceinline void SwizzleBlock16u(u8 *dst, u8 *src, int pitch) +{ + SwizzleBlock16_c(dst, src, pitch); +} + +__forceinline void SwizzleBlock8u(u8 *dst, u8 *src, int pitch) +{ + SwizzleBlock8_c(dst, src, pitch); +} + +__forceinline void SwizzleBlock4u(u8 *dst, u8 *src, int pitch) +{ + SwizzleBlock4_c(dst, src, pitch); +} + +__forceinline void __fastcall SwizzleBlock32_mask(u8* dst, u8* src, int srcpitch, u32 WriteMask) +{ + u32* d = &g_columnTable32[0][0]; + + if (WriteMask == 0xffffffff) + { + for (int j = 0; j < 8; j++, d += 8, src += srcpitch) + for (int i = 0; i < 8; i++) + ((u32*)dst)[d[i]] = ((u32*)src)[i]; + } + else + { + for (int j = 0; j < 8; j++, d += 8, src += srcpitch) + for (int i = 0; i < 8; i++) + ((u32*)dst)[d[i]] = (((u32*)dst)[d[i]] & ~WriteMask) | (((u32*)src)[i] & WriteMask); + } +} + +__forceinline void __fastcall SwizzleBlock32_c(u8* dst, u8* src, int srcpitch) +{ + SwizzleBlock32_mask(dst, src, srcpitch, 0xffffffff); +} + +__forceinline void __fastcall SwizzleBlock16_c(u8* dst, u8* src, int srcpitch) +{ + u32* d = &g_columnTable16[0][0]; + + for (int j = 0; j < 8; j++, d += 16, src += srcpitch) + for (int i = 0; i < 16; i++) + ((u16*)dst)[d[i]] = ((u16*)src)[i]; +} + +__forceinline void __fastcall SwizzleBlock8_c(u8* dst, u8* src, int srcpitch) +{ + u32* d = &g_columnTable8[0][0]; + + for (int j = 0; j < 16; j++, d += 16, src += srcpitch) + for (int i = 0; i < 16; i++) + dst[d[i]] = src[i]; +} + +__forceinline void __fastcall SwizzleBlock4_c(u8* dst, u8* src, int srcpitch) +{ + u32* d = &g_columnTable4[0][0]; + + for (int j = 0; j < 16; j++, d += 32, src += srcpitch) + { + for (int i = 0; i < 32; i++) + { + u32 addr = d[i]; + u8 c = (src[i>>1] >> ((i & 1) << 2)) & 0x0f; + u32 shift = (addr & 1) << 2; + dst[addr >> 1] = (dst[addr >> 1] & (0xf0 >> shift)) | (c << shift); + } + } +} + +__forceinline void SwizzleBlock24(u8 *dst, u8 *src, int pitch) +{ + u8* pnewsrc = src; + u32* pblock = tempblock; + + // Note src can be out of bound of GS memory (but there is some spare allocation + // to avoid a tricky corner case) + for (int by = 0; by < 8; ++by, pblock += 8, pnewsrc += pitch - 24) + { + for (int bx = 0; bx < 8; ++bx, pnewsrc += 3) + { + pblock[bx] = *(u32*)pnewsrc; + } + } + + SwizzleBlock32_mask((u8*)dst, (u8*)tempblock, 32, 0x00ffffff); +} + +__forceinline void SwizzleBlock8H(u8 *dst, u8 *src, int pitch) +{ + u8* pnewsrc = src; + u32* pblock = tempblock; + + for (int by = 0; by < 8; ++by, pblock += 8, pnewsrc += pitch) + { + u32 u = *(u32*)pnewsrc; + pblock[0] = u << 24; + pblock[1] = u << 16; + pblock[2] = u << 8; + pblock[3] = u; + u = *(u32*)(pnewsrc + 4); + pblock[4] = u << 24; + pblock[5] = u << 16; + pblock[6] = u << 8; + pblock[7] = u; + } + + SwizzleBlock32_mask((u8*)dst, (u8*)tempblock, 32, 0xff000000); +} + +__forceinline void SwizzleBlock4HH(u8 *dst, u8 *src, int pitch) +{ + u8* pnewsrc = src; + u32* pblock = tempblock; + + for (int by = 0; by < 8; ++by, pblock += 8, pnewsrc += pitch) + { + u32 u = *(u32*)pnewsrc; + pblock[0] = u << 28; + pblock[1] = u << 24; + pblock[2] = u << 20; + pblock[3] = u << 16; + pblock[4] = u << 12; + pblock[5] = u << 8; + pblock[6] = u << 4; + pblock[7] = u; + } + + SwizzleBlock32_mask((u8*)dst, (u8*)tempblock, 32, 0xf0000000); +} + +__forceinline void SwizzleBlock4HL(u8 *dst, u8 *src, int pitch) +{ + u8* pnewsrc = src; + u32* pblock = tempblock; + + for (int by = 0; by < 8; ++by, pblock += 8, pnewsrc += pitch) + { + u32 u = *(u32*)pnewsrc; + pblock[0] = u << 24; + pblock[1] = u << 20; + pblock[2] = u << 16; + pblock[3] = u << 12; + pblock[4] = u << 8; + pblock[5] = u << 4; + pblock[6] = u; + pblock[7] = u >> 4; + } + + SwizzleBlock32_mask((u8*)dst, (u8*)tempblock, 32, 0x0f000000); +} +#endif diff --git a/plugins/zzogl-pg-cg/opengl/Mem_Swizzle.h b/plugins/zzogl-pg-cg/opengl/Mem_Swizzle.h new file mode 100644 index 000000000..c353d6aca --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/Mem_Swizzle.h @@ -0,0 +1,63 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef MEM_SWIZZLE_H_INCLUDED +#define MEM_SWIZZLE_H_INCLUDED + +#include "GS.h" +#include "Mem.h" +#include "x86.h" + +extern __forceinline void SwizzleBlock32(u8 *dst, u8 *src, int pitch); +extern __forceinline void SwizzleBlock16(u8 *dst, u8 *src, int pitch); +extern __forceinline void SwizzleBlock8(u8 *dst, u8 *src, int pitch); +extern __forceinline void SwizzleBlock4(u8 *dst, u8 *src, int pitch); +extern __forceinline void SwizzleBlock32u(u8 *dst, u8 *src, int pitch); +extern __forceinline void SwizzleBlock16u(u8 *dst, u8 *src, int pitch); +extern __forceinline void SwizzleBlock8u(u8 *dst, u8 *src, int pitch); +extern __forceinline void SwizzleBlock4u(u8 *dst, u8 *src, int pitch); + +extern __forceinline void __fastcall SwizzleBlock32_c(u8* dst, u8* src, int srcpitch); +extern __forceinline void __fastcall SwizzleBlock16_c(u8* dst, u8* src, int srcpitch); +extern __forceinline void __fastcall SwizzleBlock8_c(u8* dst, u8* src, int srcpitch); +extern __forceinline void __fastcall SwizzleBlock4_c(u8* dst, u8* src, int srcpitch); + +// special swizzle macros - which I converted to functions. +extern __forceinline void SwizzleBlock24(u8 *dst, u8 *src, int pitch); +extern __forceinline void SwizzleBlock8H(u8 *dst, u8 *src, int pitch); +extern __forceinline void SwizzleBlock4HH(u8 *dst, u8 *src, int pitch); +extern __forceinline void SwizzleBlock4HL(u8 *dst, u8 *src, int pitch); +#define SwizzleBlock24u SwizzleBlock24 +#define SwizzleBlock8Hu SwizzleBlock8H +#define SwizzleBlock4HHu SwizzleBlock4HH +#define SwizzleBlock4HLu SwizzleBlock4HL + +#define SwizzleBlock16S SwizzleBlock16 +#define SwizzleBlock32Z SwizzleBlock32 +#define SwizzleBlock24Z SwizzleBlock24 +#define SwizzleBlock16Z SwizzleBlock16 +#define SwizzleBlock16SZ SwizzleBlock16 + +#define SwizzleBlock16Su SwizzleBlock16u +#define SwizzleBlock32Zu SwizzleBlock32u +#define SwizzleBlock24Zu SwizzleBlock24u +#define SwizzleBlock16Zu SwizzleBlock16u +#define SwizzleBlock16SZu SwizzleBlock16u + +#endif // MEM_SWIZZLE_H_INCLUDED diff --git a/plugins/zzogl-pg-cg/opengl/Mem_Tables.cpp b/plugins/zzogl-pg-cg/opengl/Mem_Tables.cpp new file mode 100644 index 000000000..8db1b5c67 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/Mem_Tables.cpp @@ -0,0 +1,420 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "GS.h" +#include "Mem.h" +#include "Mem_Swizzle.h" + +u32 g_blockTable32[4][8] = +{ + { 0, 1, 4, 5, 16, 17, 20, 21}, + { 2, 3, 6, 7, 18, 19, 22, 23}, + { 8, 9, 12, 13, 24, 25, 28, 29}, + { 10, 11, 14, 15, 26, 27, 30, 31} +}; + +u32 g_blockTable32Z[4][8] = +{ + { 24, 25, 28, 29, 8, 9, 12, 13}, + { 26, 27, 30, 31, 10, 11, 14, 15}, + { 16, 17, 20, 21, 0, 1, 4, 5}, + { 18, 19, 22, 23, 2, 3, 6, 7} +}; + +u32 g_blockTable16[8][4] = +{ + { 0, 2, 8, 10 }, + { 1, 3, 9, 11 }, + { 4, 6, 12, 14 }, + { 5, 7, 13, 15 }, + { 16, 18, 24, 26 }, + { 17, 19, 25, 27 }, + { 20, 22, 28, 30 }, + { 21, 23, 29, 31 } +}; + +u32 g_blockTable16S[8][4] = +{ + { 0, 2, 16, 18 }, + { 1, 3, 17, 19 }, + { 8, 10, 24, 26 }, + { 9, 11, 25, 27 }, + { 4, 6, 20, 22 }, + { 5, 7, 21, 23 }, + { 12, 14, 28, 30 }, + { 13, 15, 29, 31 } +}; + +u32 g_blockTable16Z[8][4] = +{ + { 24, 26, 16, 18 }, + { 25, 27, 17, 19 }, + { 28, 30, 20, 22 }, + { 29, 31, 21, 23 }, + { 8, 10, 0, 2 }, + { 9, 11, 1, 3 }, + { 12, 14, 4, 6 }, + { 13, 15, 5, 7 } +}; + +u32 g_blockTable16SZ[8][4] = +{ + { 24, 26, 8, 10 }, + { 25, 27, 9, 11 }, + { 16, 18, 0, 2 }, + { 17, 19, 1, 3 }, + { 28, 30, 12, 14 }, + { 29, 31, 13, 15 }, + { 20, 22, 4, 6 }, + { 21, 23, 5, 7 } +}; + +u32 g_blockTable8[4][8] = +{ + { 0, 1, 4, 5, 16, 17, 20, 21}, + { 2, 3, 6, 7, 18, 19, 22, 23}, + { 8, 9, 12, 13, 24, 25, 28, 29}, + { 10, 11, 14, 15, 26, 27, 30, 31} +}; + +u32 g_blockTable4[8][4] = +{ + { 0, 2, 8, 10 }, + { 1, 3, 9, 11 }, + { 4, 6, 12, 14 }, + { 5, 7, 13, 15 }, + { 16, 18, 24, 26 }, + { 17, 19, 25, 27 }, + { 20, 22, 28, 30 }, + { 21, 23, 29, 31 } +}; + +u32 g_columnTable32[8][8] = +{ + { 0, 1, 4, 5, 8, 9, 12, 13 }, + { 2, 3, 6, 7, 10, 11, 14, 15 }, + { 16, 17, 20, 21, 24, 25, 28, 29 }, + { 18, 19, 22, 23, 26, 27, 30, 31 }, + { 32, 33, 36, 37, 40, 41, 44, 45 }, + { 34, 35, 38, 39, 42, 43, 46, 47 }, + { 48, 49, 52, 53, 56, 57, 60, 61 }, + { 50, 51, 54, 55, 58, 59, 62, 63 }, +}; + +u32 g_columnTable16[8][16] = +{ + { 0, 2, 8, 10, 16, 18, 24, 26, + 1, 3, 9, 11, 17, 19, 25, 27 }, + { 4, 6, 12, 14, 20, 22, 28, 30, + 5, 7, 13, 15, 21, 23, 29, 31 }, + { 32, 34, 40, 42, 48, 50, 56, 58, + 33, 35, 41, 43, 49, 51, 57, 59 }, + { 36, 38, 44, 46, 52, 54, 60, 62, + 37, 39, 45, 47, 53, 55, 61, 63 }, + { 64, 66, 72, 74, 80, 82, 88, 90, + 65, 67, 73, 75, 81, 83, 89, 91 }, + { 68, 70, 76, 78, 84, 86, 92, 94, + 69, 71, 77, 79, 85, 87, 93, 95 }, + { 96, 98, 104, 106, 112, 114, 120, 122, + 97, 99, 105, 107, 113, 115, 121, 123 }, + { 100, 102, 108, 110, 116, 118, 124, 126, + 101, 103, 109, 111, 117, 119, 125, 127 }, +}; + +u32 g_columnTable8[16][16] = +{ + { 0, 4, 16, 20, 32, 36, 48, 52, // column 0 + 2, 6, 18, 22, 34, 38, 50, 54 }, + { 8, 12, 24, 28, 40, 44, 56, 60, + 10, 14, 26, 30, 42, 46, 58, 62 }, + { 33, 37, 49, 53, 1, 5, 17, 21, + 35, 39, 51, 55, 3, 7, 19, 23 }, + { 41, 45, 57, 61, 9, 13, 25, 29, + 43, 47, 59, 63, 11, 15, 27, 31 }, + { 96, 100, 112, 116, 64, 68, 80, 84, // column 1 + 98, 102, 114, 118, 66, 70, 82, 86 }, + { 104, 108, 120, 124, 72, 76, 88, 92, + 106, 110, 122, 126, 74, 78, 90, 94 }, + { 65, 69, 81, 85, 97, 101, 113, 117, + 67, 71, 83, 87, 99, 103, 115, 119 }, + { 73, 77, 89, 93, 105, 109, 121, 125, + 75, 79, 91, 95, 107, 111, 123, 127 }, + { 128, 132, 144, 148, 160, 164, 176, 180, // column 2 + 130, 134, 146, 150, 162, 166, 178, 182 }, + { 136, 140, 152, 156, 168, 172, 184, 188, + 138, 142, 154, 158, 170, 174, 186, 190 }, + { 161, 165, 177, 181, 129, 133, 145, 149, + 163, 167, 179, 183, 131, 135, 147, 151 }, + { 169, 173, 185, 189, 137, 141, 153, 157, + 171, 175, 187, 191, 139, 143, 155, 159 }, + { 224, 228, 240, 244, 192, 196, 208, 212, // column 3 + 226, 230, 242, 246, 194, 198, 210, 214 }, + { 232, 236, 248, 252, 200, 204, 216, 220, + 234, 238, 250, 254, 202, 206, 218, 222 }, + { 193, 197, 209, 213, 225, 229, 241, 245, + 195, 199, 211, 215, 227, 231, 243, 247 }, + { 201, 205, 217, 221, 233, 237, 249, 253, + 203, 207, 219, 223, 235, 239, 251, 255 }, +}; + +u32 g_columnTable4[16][32] = +{ + { 0, 8, 32, 40, 64, 72, 96, 104, // column 0 + 2, 10, 34, 42, 66, 74, 98, 106, + 4, 12, 36, 44, 68, 76, 100, 108, + 6, 14, 38, 46, 70, 78, 102, 110 }, + { 16, 24, 48, 56, 80, 88, 112, 120, + 18, 26, 50, 58, 82, 90, 114, 122, + 20, 28, 52, 60, 84, 92, 116, 124, + 22, 30, 54, 62, 86, 94, 118, 126 }, + { 65, 73, 97, 105, 1, 9, 33, 41, + 67, 75, 99, 107, 3, 11, 35, 43, + 69, 77, 101, 109, 5, 13, 37, 45, + 71, 79, 103, 111, 7, 15, 39, 47 }, + { 81, 89, 113, 121, 17, 25, 49, 57, + 83, 91, 115, 123, 19, 27, 51, 59, + 85, 93, 117, 125, 21, 29, 53, 61, + 87, 95, 119, 127, 23, 31, 55, 63 }, + { 192, 200, 224, 232, 128, 136, 160, 168, // column 1 + 194, 202, 226, 234, 130, 138, 162, 170, + 196, 204, 228, 236, 132, 140, 164, 172, + 198, 206, 230, 238, 134, 142, 166, 174 }, + { 208, 216, 240, 248, 144, 152, 176, 184, + 210, 218, 242, 250, 146, 154, 178, 186, + 212, 220, 244, 252, 148, 156, 180, 188, + 214, 222, 246, 254, 150, 158, 182, 190 }, + { 129, 137, 161, 169, 193, 201, 225, 233, + 131, 139, 163, 171, 195, 203, 227, 235, + 133, 141, 165, 173, 197, 205, 229, 237, + 135, 143, 167, 175, 199, 207, 231, 239 }, + { 145, 153, 177, 185, 209, 217, 241, 249, + 147, 155, 179, 187, 211, 219, 243, 251, + 149, 157, 181, 189, 213, 221, 245, 253, + 151, 159, 183, 191, 215, 223, 247, 255 }, + { 256, 264, 288, 296, 320, 328, 352, 360, // column 2 + 258, 266, 290, 298, 322, 330, 354, 362, + 260, 268, 292, 300, 324, 332, 356, 364, + 262, 270, 294, 302, 326, 334, 358, 366 }, + { 272, 280, 304, 312, 336, 344, 368, 376, + 274, 282, 306, 314, 338, 346, 370, 378, + 276, 284, 308, 316, 340, 348, 372, 380, + 278, 286, 310, 318, 342, 350, 374, 382 }, + { 321, 329, 353, 361, 257, 265, 289, 297, + 323, 331, 355, 363, 259, 267, 291, 299, + 325, 333, 357, 365, 261, 269, 293, 301, + 327, 335, 359, 367, 263, 271, 295, 303 }, + { 337, 345, 369, 377, 273, 281, 305, 313, + 339, 347, 371, 379, 275, 283, 307, 315, + 341, 349, 373, 381, 277, 285, 309, 317, + 343, 351, 375, 383, 279, 287, 311, 319 }, + { 448, 456, 480, 488, 384, 392, 416, 424, // column 3 + 450, 458, 482, 490, 386, 394, 418, 426, + 452, 460, 484, 492, 388, 396, 420, 428, + 454, 462, 486, 494, 390, 398, 422, 430 }, + { 464, 472, 496, 504, 400, 408, 432, 440, + 466, 474, 498, 506, 402, 410, 434, 442, + 468, 476, 500, 508, 404, 412, 436, 444, + 470, 478, 502, 510, 406, 414, 438, 446 }, + { 385, 393, 417, 425, 449, 457, 481, 489, + 387, 395, 419, 427, 451, 459, 483, 491, + 389, 397, 421, 429, 453, 461, 485, 493, + 391, 399, 423, 431, 455, 463, 487, 495 }, + { 401, 409, 433, 441, 465, 473, 497, 505, + 403, 411, 435, 443, 467, 475, 499, 507, + 405, 413, 437, 445, 469, 477, 501, 509, + 407, 415, 439, 447, 471, 479, 503, 511 }, +}; + +u32 g_pageTable32[32][64]; +u32 g_pageTable32Z[32][64]; +u32 g_pageTable16[64][64]; +u32 g_pageTable16S[64][64]; +u32 g_pageTable16Z[64][64]; +u32 g_pageTable16SZ[64][64]; +u32 g_pageTable8[64][128]; +u32 g_pageTable4[128][128]; + +/* PSM reference array +{ 32, 24, 16, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, 16S, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, 8, 4, NULL, NULL, NULL, + NULL, NULL, NULL, 8H, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, 4HL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, 4HH, NULL, NULL, NULL, + 32Z, 24Z, 16Z, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, 16SZ, NULL, NULL, NULL, NULL, NULL }; +*/ +char* psm_name[64] = +{ "PSMCT32", "PSMCT24", "PSMCT16", NULL, NULL, NULL, NULL, NULL, + NULL, NULL, "PSMCT16S", NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, "PSMT8", "PSMT4", NULL, NULL, NULL, + NULL, NULL, NULL, "PSMT8H", NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "PSMT4HL", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "PSMT4HH", NULL, NULL, NULL, + "PSMT32Z", "PSMT24Z", "PSMT16Z", NULL, NULL, NULL, NULL, NULL, + NULL, NULL, "PSMT16SZ", NULL, NULL, NULL, NULL, NULL }; + +_SwizzleBlock swizzleBlockFun[64] = +{ SwizzleBlock32, SwizzleBlock24, SwizzleBlock16, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, SwizzleBlock16S, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, SwizzleBlock8, SwizzleBlock4, NULL, NULL, NULL, + NULL, NULL, NULL, SwizzleBlock8H, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, SwizzleBlock4HL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, SwizzleBlock4HH, NULL, NULL, NULL, + SwizzleBlock32Z, SwizzleBlock24Z, SwizzleBlock16Z, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, SwizzleBlock16SZ, NULL, NULL, NULL, NULL, NULL }; + +_SwizzleBlock swizzleBlockUnFun[64] = +{ SwizzleBlock32u, SwizzleBlock24u, SwizzleBlock16u, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, SwizzleBlock16Su, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, SwizzleBlock8u, SwizzleBlock4u, NULL, NULL, NULL, + NULL, NULL, NULL, SwizzleBlock8Hu, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, SwizzleBlock4HLu, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, SwizzleBlock4HHu, NULL, NULL, NULL, + SwizzleBlock32Zu, SwizzleBlock24Zu, SwizzleBlock16Zu, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, SwizzleBlock16SZu, NULL, NULL, NULL, NULL, NULL }; + +_getPixelAddress_0 getPixelFun_0[64] = +{ + getPixelAddress32_0, getPixelAddress24_0, getPixelAddress16_0, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, getPixelAddress16S_0, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, getPixelAddress8_0, getPixelAddress4_0, NULL, NULL, NULL, + NULL, NULL, NULL, getPixelAddress8H_0, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, getPixelAddress4HL_0, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, getPixelAddress4HH_0, NULL, NULL, NULL, + getPixelAddress32Z_0, getPixelAddress24Z_0, getPixelAddress16Z_0, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, getPixelAddress16SZ_0, NULL, NULL, NULL, NULL, NULL +}; + +_writePixel_0 writePixelFun_0[64] = +{ + writePixel32_0, writePixel24_0, writePixel16_0, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, writePixel16S_0, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, writePixel8_0, writePixel4_0, NULL, NULL, NULL, + NULL, NULL, NULL, writePixel8H_0, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, writePixel4HL_0, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, writePixel4HH_0, NULL, NULL, NULL, + writePixel32Z_0, writePixel24Z_0, writePixel16Z_0, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, writePixel16SZ_0, NULL, NULL, NULL, NULL, NULL +}; + +_readPixel_0 readPixelFun_0[64] = +{ + readPixel32_0, readPixel24_0, readPixel16_0, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, readPixel16S_0, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, readPixel8_0, readPixel4_0, NULL, NULL, NULL, + NULL, NULL, NULL, readPixel8H_0, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, readPixel4HL_0, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, readPixel4HH_0, NULL, NULL, NULL, + readPixel32Z_0, readPixel24Z_0, readPixel16Z_0, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, readPixel16SZ_0, NULL, NULL, NULL, NULL, NULL +}; + +_getPixelAddress getPixelFun[64] = +{ + getPixelAddress32, getPixelAddress24, getPixelAddress16, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, getPixelAddress16S, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, getPixelAddress8, getPixelAddress4, NULL, NULL, NULL, + NULL, NULL, NULL, getPixelAddress8H, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, getPixelAddress4HL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, getPixelAddress4HH, NULL, NULL, NULL, + getPixelAddress32Z, getPixelAddress24Z, getPixelAddress16Z, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, getPixelAddress16SZ, NULL, NULL, NULL, NULL, NULL +}; + +_writePixel writePixelFun[64] = +{ + writePixel32, writePixel24, writePixel16, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, writePixel16S, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, writePixel8, writePixel4, NULL, NULL, NULL, + NULL, NULL, NULL, writePixel8H, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, writePixel4HL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, writePixel4HH, NULL, NULL, NULL, + writePixel32Z, writePixel24Z, writePixel16Z, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, writePixel16SZ, NULL, NULL, NULL, NULL, NULL +}; + +_readPixel readPixelFun[64] = +{ + readPixel32, readPixel24, readPixel16, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, readPixel16S, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, readPixel8, readPixel4, NULL, NULL, NULL, + NULL, NULL, NULL, readPixel8H, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, readPixel4HL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, readPixel4HH, NULL, NULL, NULL, + readPixel32Z, readPixel24Z, readPixel16Z, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, readPixel16SZ, NULL, NULL, NULL, NULL, NULL +}; + +_TransferHostLocal TransferHostLocalFun[64] = +{ + TransferHostLocal32, TransferHostLocal24, TransferHostLocal16, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, TransferHostLocal16S, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, TransferHostLocal8, TransferHostLocal4, NULL, NULL, NULL, + NULL, NULL, NULL, TransferHostLocal8H, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, TransferHostLocal4HL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, TransferHostLocal4HH, NULL, NULL, NULL, + TransferHostLocal32Z, TransferHostLocal24Z, TransferHostLocal16Z, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, TransferHostLocal16SZ, NULL, NULL, NULL, NULL, NULL +}; + +_TransferLocalHost TransferLocalHostFun[64] = +{ + TransferLocalHost32, TransferLocalHost24, TransferLocalHost16, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, TransferLocalHost16S, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, TransferLocalHost8, TransferLocalHost4, NULL, NULL, NULL, + NULL, NULL, NULL, TransferLocalHost8H, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, TransferLocalHost4HL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, TransferLocalHost4HH, NULL, NULL, NULL, + TransferLocalHost32Z, TransferLocalHost24Z, TransferLocalHost16Z, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, TransferLocalHost16SZ, NULL, NULL, NULL, NULL, NULL +}; + +#define TD_NULL {0,0,0,0,0,0} +TransferData tData[64] = +{ + {2,32,8,8,32,PSMCT32}, + {8,32,8,8,24,PSMCT24}, + {4,16,16,8,16,PSMCT16}, + TD_NULL, TD_NULL, TD_NULL, TD_NULL, TD_NULL, + TD_NULL, TD_NULL, + {4,16,16,8,16,PSMCT16S}, + TD_NULL, TD_NULL, TD_NULL, TD_NULL, TD_NULL, + TD_NULL, TD_NULL, TD_NULL, + {4,8,16,16,8,PSMT8}, + {8,4,32,16,4,PSMT4}, + TD_NULL, TD_NULL, TD_NULL, + TD_NULL, TD_NULL, TD_NULL, + {4,32,8,8,8,PSMT8H}, + TD_NULL, TD_NULL, TD_NULL, TD_NULL, + TD_NULL, TD_NULL, TD_NULL, TD_NULL, + {8,32,8,8,4,PSMT4HL}, + TD_NULL, TD_NULL, TD_NULL, + TD_NULL, TD_NULL, TD_NULL, TD_NULL, + {8,32,8,8,4,PSMT4HH}, + TD_NULL, TD_NULL, TD_NULL, + {2,32,8,8,32,PSMT32Z}, + {8,32,8,8,24,PSMT24Z}, + {4,16,16,8,16,PSMT16Z}, + TD_NULL, TD_NULL, TD_NULL, TD_NULL, TD_NULL, + TD_NULL, TD_NULL, + {4,16,16,8,16,PSMT16SZ}, + TD_NULL, TD_NULL, TD_NULL, TD_NULL, TD_NULL +}; + diff --git a/plugins/zzogl-pg-cg/opengl/Mem_Transmit.h b/plugins/zzogl-pg-cg/opengl/Mem_Transmit.h new file mode 100644 index 000000000..0e228360b --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/Mem_Transmit.h @@ -0,0 +1,319 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef MEM_TRANSMIT_H_INCLUDED +#define MEM_TRANSMIT_H_INCLUDED + +#include "GS.h" +#include "Mem.h" + +#define DSTPSM gs.dstbuf.psm +extern int tempX, tempY; +extern int pitch, area, fracX; +extern int nSize; +extern u8* pstart; + +extern char* psm_name[64]; + +// transfers whole rows +template +static __forceinline const T *TransmitHostLocalY_(_writePixel_0 wp, s32 widthlimit, int endY, const T *buf) +{ + assert((nSize % widthlimit) == 0 && widthlimit <= 4); + + if ((gs.imageEndX - gs.trxpos.dx) % widthlimit) + { + // ZZLog::GS_Log("Bad Transmission! %d %d, psm: %d", gs.trxpos.dx, gs.imageEndX, DSTPSM); + + for (; tempY < endY; ++tempY) + { + for (; tempX < gs.imageEndX && nSize > 0; tempX += 1, nSize -= 1, buf += 1) + { + /* write as many pixel at one time as possible */ + wp(pstart, tempX % 2048, tempY % 2048, buf[0], gs.dstbuf.bw); + } + } + } + + for (; tempY < endY; ++tempY) + { + for (; tempX < gs.imageEndX && nSize > 0; tempX += widthlimit, nSize -= widthlimit, buf += widthlimit) + { + + /* write as many pixel at one time as possible */ + if (nSize < widthlimit) return NULL; + + wp(pstart, tempX % 2048, tempY % 2048, buf[0], gs.dstbuf.bw); + + if (widthlimit > 1) + { + wp(pstart, (tempX + 1) % 2048, tempY % 2048, buf[1], gs.dstbuf.bw); + + if (widthlimit > 2) + { + wp(pstart, (tempX + 2) % 2048, tempY % 2048, buf[2], gs.dstbuf.bw); + + if (widthlimit > 3) + { + wp(pstart, (tempX + 3) % 2048, tempY % 2048, buf[3], gs.dstbuf.bw); + } + } + } + } + + if (tempX >= gs.imageEndX) + { + assert(tempX == gs.imageEndX); + tempX = gs.trxpos.dx; + } + else + { + assert(gs.imageTransfer == -1 || nSize*sizeof(T) / 4 == 0); + return NULL; + } + } + + return buf; +} + +// transfers whole rows +template +static __forceinline const T *TransmitHostLocalY_24(_writePixel_0 wp, s32 widthlimit, int endY, const T *buf) +{ + if (widthlimit != 8 || ((gs.imageEndX - gs.trxpos.dx) % widthlimit)) + { + //ZZLog::GS_Log("Bad Transmission! %d %d, psm: %d", gs.trxpos.dx, gs.imageEndX, DSTPSM); + for (; tempY < endY; ++tempY) + { + for (; tempX < gs.imageEndX && nSize > 0; tempX += 1, nSize -= 1, buf += 3) + { + wp(pstart, tempX % 2048, tempY % 2048, *(u32*)(buf), gs.dstbuf.bw); + } + + if (tempX >= gs.imageEndX) + { + assert(gs.imageTransfer == -1 || tempX == gs.imageEndX); + tempX = gs.trxpos.dx; + } + else + { + assert(gs.imageTransfer == -1 || nSize == 0); + return NULL; + } + } + } + else + { + assert(/*(nSize%widthlimit) == 0 &&*/ widthlimit == 8); + + for (; tempY < endY; ++tempY) + { + for (; tempX < gs.imageEndX && nSize > 0; tempX += widthlimit, nSize -= widthlimit, buf += 3 * widthlimit) + { + if (nSize < widthlimit) return NULL; + + /* write as many pixel at one time as possible */ + + wp(pstart, tempX % 2048, tempY % 2048, *(u32*)(buf + 0), gs.dstbuf.bw); + wp(pstart, (tempX + 1) % 2048, tempY % 2048, *(u32*)(buf + 3), gs.dstbuf.bw); + wp(pstart, (tempX + 2) % 2048, tempY % 2048, *(u32*)(buf + 6), gs.dstbuf.bw); + wp(pstart, (tempX + 3) % 2048, tempY % 2048, *(u32*)(buf + 9), gs.dstbuf.bw); + wp(pstart, (tempX + 4) % 2048, tempY % 2048, *(u32*)(buf + 12), gs.dstbuf.bw); + wp(pstart, (tempX + 5) % 2048, tempY % 2048, *(u32*)(buf + 15), gs.dstbuf.bw); + wp(pstart, (tempX + 6) % 2048, tempY % 2048, *(u32*)(buf + 18), gs.dstbuf.bw); + wp(pstart, (tempX + 7) % 2048, tempY % 2048, *(u32*)(buf + 21), gs.dstbuf.bw); + } + + if (tempX >= gs.imageEndX) + { + assert(gs.imageTransfer == -1 || tempX == gs.imageEndX); + tempX = gs.trxpos.dx; + } + else + { + if (nSize < 0) + { + /* extracted too much */ + assert((nSize % 3) == 0 && nSize > -24); + tempX += nSize / 3; + nSize = 0; + } + + assert(gs.imageTransfer == -1 || nSize == 0); + + return NULL; + } + } + } + + return buf; +} + +// meant for 4bit transfers +template +static __forceinline const T *TransmitHostLocalY_4(_writePixel_0 wp, s32 widthlimit, int endY, const T *buf) +{ + for (; tempY < endY; ++tempY) + { + for (; tempX < gs.imageEndX && nSize > 0; tempX += widthlimit, nSize -= widthlimit) + { + /* write as many pixel at one time as possible */ + wp(pstart, tempX % 2048, tempY % 2048, *buf&0x0f, gs.dstbuf.bw); + wp(pstart, (tempX + 1) % 2048, tempY % 2048, *buf >> 4, gs.dstbuf.bw); + buf++; + + if (widthlimit > 2) + { + wp(pstart, (tempX + 2) % 2048, tempY % 2048, *buf&0x0f, gs.dstbuf.bw); + wp(pstart, (tempX + 3) % 2048, tempY % 2048, *buf >> 4, gs.dstbuf.bw); + buf++; + + if (widthlimit > 4) + { + wp(pstart, (tempX + 4) % 2048, tempY % 2048, *buf&0x0f, gs.dstbuf.bw); + wp(pstart, (tempX + 5) % 2048, tempY % 2048, *buf >> 4, gs.dstbuf.bw); + buf++; + + if (widthlimit > 6) + { + wp(pstart, (tempX + 6) % 2048, tempY % 2048, *buf&0x0f, gs.dstbuf.bw); + wp(pstart, (tempX + 7) % 2048, tempY % 2048, *buf >> 4, gs.dstbuf.bw); + buf++; + } + } + } + } + + if (tempX >= gs.imageEndX) + { + tempX = gs.trxpos.dx; + } + else + { + assert(gs.imageTransfer == -1 || (nSize / 32) == 0); + return NULL; + } + } + + return buf; +} + +template +static __forceinline const T *TransmitHostLocalY(u32 psm, _writePixel_0 wp, s32 widthlimit, int endY, const T *buf) +{ + //ZZLog::WriteLn("TransmitHostLocalY: psm == %s, bimode == 0x%x", psm_name[psm], PSMT_BITMODE(psm)); + switch (PSMT_BITMODE(psm)) + { + case 1: + return TransmitHostLocalY_24(wp, widthlimit, endY, buf); + case 4: + return TransmitHostLocalY_4(wp, widthlimit, endY, buf); + default: + return TransmitHostLocalY_(wp, widthlimit, endY, buf); + } + + assert(0); + + return NULL; +} + +template +static __forceinline const T *TransmitHostLocalX_(_writePixel_0 wp, u32 widthlimit, u32 blockheight, u32 startX, const T *buf) +{ + for (u32 tempi = 0; tempi < blockheight; ++tempi) + { + for (tempX = startX; tempX < gs.imageEndX; tempX++, buf++) + { + wp(pstart, tempX % 2048, (tempY + tempi) % 2048, buf[0], gs.dstbuf.bw); + } + + buf += pitch - fracX; + } + + return buf; +} + +// transmit until endX, don't check size since it has already been prevalidated +template +static __forceinline const T *TransmitHostLocalX_24(_writePixel_0 wp, u32 widthlimit, u32 blockheight, u32 startX, const T *buf) +{ + for (u32 tempi = 0; tempi < blockheight; ++tempi) + { + for (tempX = startX; tempX < gs.imageEndX; tempX++, buf += 3) + { + wp(pstart, tempX % 2048, (tempY + tempi) % 2048, *(u32*)buf, gs.dstbuf.bw); + } + + buf += 3 * (pitch - fracX); + } + + return buf; +} + +// transmit until endX, don't check size since it has already been prevalidated +template +static __forceinline const T *TransmitHostLocalX_4(_writePixel_0 wp, u32 widthlimit, u32 blockheight, u32 startX, const T *buf) +{ + for (u32 tempi = 0; tempi < blockheight; ++tempi) + { + for (tempX = startX; tempX < gs.imageEndX; tempX += 2, buf++) + { + wp(pstart, tempX % 2048, (tempY + tempi) % 2048, buf[0]&0x0f, gs.dstbuf.bw); + wp(pstart, (tempX + 1) % 2048, (tempY + tempi) % 2048, buf[0] >> 4, gs.dstbuf.bw); + } + + buf += (pitch - fracX) / 2; + } + + return buf; +} + +template +static __forceinline const T *TransmitHostLocalX(u32 psm, _writePixel_0 wp, u32 widthlimit, u32 blockheight, u32 startX, const T *buf) +{ + //ZZLog::WriteLn("TransmitHostLocalX: psm == %s, bimode == 0x%x", psm_name[psm], PSMT_BITMODE(psm)); + switch (PSMT_BITMODE(psm)) + { + case 1: + return TransmitHostLocalX_24(wp, widthlimit, blockheight, startX, buf); + case 4: + return TransmitHostLocalX_4(wp, widthlimit, blockheight, startX, buf); + default: + return TransmitHostLocalX_(wp, widthlimit, blockheight, startX, buf); + } + + assert(0); + + return NULL; +} + +// calculate pitch in source buffer +static __forceinline u32 TransPitch(u32 pitch, u32 size) +{ + return pitch * size / 8; +} + +static __forceinline u32 TransPitch2(u32 pitch, u32 size) +{ + if (size == 4) return pitch / 2; + if (size == 24) return pitch * 3; + return pitch; +} + +#endif // MEM_TRANSMIT_H_INCLUDED diff --git a/plugins/zzogl-pg-cg/opengl/NewRegs.cpp b/plugins/zzogl-pg-cg/opengl/NewRegs.cpp new file mode 100644 index 000000000..d9ff6cd7f --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/NewRegs.cpp @@ -0,0 +1,1144 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "GS.h" +#include "Mem.h" +#include "NewRegs.h" +#include "PS2Etypes.h" + +#include "targets.h" + +#ifdef USE_OLD_REGS +#include "Regs.h" +#else +#include "ZZoglVB.h" +#include "ZZoglDrawing.h" + +#ifdef _MSC_VER +#pragma warning(disable:4244) +#endif + +GIFRegHandler g_GIFPackedRegHandlers[16]; +GIFRegHandler g_GIFRegHandlers[256]; +GIFRegHandler g_GIFTempRegHandlers[16] = {0}; + +// values for keeping track of changes +u32 s_uTex1Data[2][2] = {{0, }}; +u32 s_uClampData[2] = {0, }; + +//u32 results[65535] = {0, }; + +void __gifCall GIFPackedRegHandlerNull(const u32* data) +{ + FUNCLOG + ZZLog::Debug_Log("Unexpected packed reg handler %8.8lx_%8.8lx %x.", data[0], data[1], data[2]); +} + +// All these just call their non-packed equivalent. +void __gifCall GIFPackedRegHandlerPRIM(const u32* data) { GIFRegHandlerPRIM(data); } + +template +void __gifCall GIFPackedRegHandlerTEX0(const u32* data) +{ + GIFRegHandlerTEX0(data); +} + +template +void __gifCall GIFPackedRegHandlerCLAMP(const u32* data) +{ + GIFRegHandlerCLAMP(data); +} + +void __gifCall GIFPackedRegHandlerTEX0_1(const u32* data) { GIFRegHandlerTEX0<0>(data); } +void __gifCall GIFPackedRegHandlerTEX0_2(const u32* data) { GIFRegHandlerTEX0<1>(data); } +void __gifCall GIFPackedRegHandlerCLAMP_1(const u32* data) { GIFRegHandlerCLAMP<0>(data); } +void __gifCall GIFPackedRegHandlerCLAMP_2(const u32* data) { GIFRegHandlerCLAMP<1>(data); } +void __gifCall GIFPackedRegHandlerXYZF3(const u32* data) { GIFRegHandlerXYZF3(data); } +void __gifCall GIFPackedRegHandlerXYZ3(const u32* data) { GIFRegHandlerXYZ3(data); } + +void __gifCall GIFPackedRegHandlerRGBA(const u32* data) +{ + FUNCLOG + + GIFPackedRGBA* r = (GIFPackedRGBA*)(data); + gs.rgba = (r->R | (r->G << 8) | (r->B << 16) | (r->A << 24)); + gs.vertexregs.rgba = gs.rgba; + gs.vertexregs.q = gs.q; + + ZZLog::Greg_Log("Packed RGBA: 0x%x", gs.rgba); +} + +void __gifCall GIFPackedRegHandlerSTQ(const u32* data) +{ + FUNCLOG + GIFPackedSTQ* r = (GIFPackedSTQ*)(data); + gs.vertexregs.s = r->S; + gs.vertexregs.t = r->T; + gs.q = r->Q; + ZZLog::Greg_Log("Packed STQ: 0x%x, 0x%x, %f", r->S, r->T, r->Q); +} + +void __gifCall GIFPackedRegHandlerUV(const u32* data) +{ + FUNCLOG + GIFPackedUV* r = (GIFPackedUV*)(data); + gs.vertexregs.u = r->U; + gs.vertexregs.v = r->V; + ZZLog::Greg_Log("Packed UV: 0x%x, 0x%x", r->U, r->V); +} + +void __gifCall GIFPackedRegHandlerXYZF2(const u32* data) +{ + FUNCLOG + GIFPackedXYZF2* r = (GIFPackedXYZF2*)(data); + gs.add_vertex(r->X, r->Y,r->Z, r->F); + + // Fix Vertexes up later. + ZZKick->KickVertex(!!(r->ADC)); + ZZLog::Greg_Log("Packed XYZF2: 0x%x, 0x%x, 0x%x, %f", r->X, r->Y, r->Z, r->F); +} + +void __gifCall GIFPackedRegHandlerXYZ2(const u32* data) +{ + FUNCLOG + GIFPackedXYZ2* r = (GIFPackedXYZ2*)(data); + gs.add_vertex(r->X, r->Y,r->Z); + + // Fix Vertexes up later. + ZZKick->KickVertex(!!(r->ADC)); + ZZLog::Greg_Log("Packed XYZ2: 0x%x, 0x%x, 0x%x", r->X, r->Y, r->Z); +} + +void __gifCall GIFPackedRegHandlerFOG(const u32* data) +{ + FUNCLOG + GIFPackedFOG* r = (GIFPackedFOG*)(data); + gs.vertexregs.f = r->F; + ZZLog::Greg_Log("Packed FOG: 0x%x", r->F); +} + +void __gifCall GIFPackedRegHandlerA_D(const u32* data) +{ + FUNCLOG + GIFPackedA_D* r = (GIFPackedA_D*)(data); + + g_GIFRegHandlers[r->ADDR](data); + ZZLog::Greg_Log("Packed A_D: 0x%x", r->ADDR); +} + +void __gifCall GIFPackedRegHandlerNOP(const u32* data) +{ + FUNCLOG +} + +void __gifCall GIFRegHandlerNull(const u32* data) +{ + FUNCLOG +#ifdef _DEBUG + + if ((((uptr)&data[2])&0xffff) == 0) return; + + // 0x7f happens on a lot of games + if (data[2] != 0x7f && (data[0] || data[1])) + { + ZZLog::Debug_Log("Unexpected reg handler %x %x %x.", data[0], data[1], data[2]); + } + +#endif +} + +void __gifCall GIFRegHandlerRGBAQ(const u32* data) +{ + FUNCLOG + GIFRegRGBAQ* r = (GIFRegRGBAQ*)(data); + gs.rgba = (r->R | (r->G << 8) | (r->B << 16) | (r->A << 24)); + gs.vertexregs.rgba = gs.rgba; + gs.vertexregs.q = r->Q; + ZZLog::Greg_Log("RGBAQ: 0x%x, 0x%x, 0x%x, %f", r->R, r->G, r->B, r->A, r->Q); +} + +void __gifCall GIFRegHandlerST(const u32* data) +{ + FUNCLOG + GIFRegST* r = (GIFRegST*)(data); + gs.vertexregs.s = r->S; + gs.vertexregs.t = r->T; + ZZLog::Greg_Log("ST: 0x%x, 0x%x", r->S, r->T); +} + +void __gifCall GIFRegHandlerUV(const u32* data) +{ + // Baroque breaks if u&v are 16 bits instead of 14. + FUNCLOG + GIFRegUV* r = (GIFRegUV*)(data); + gs.vertexregs.u = r->U; + gs.vertexregs.v = r->V; + ZZLog::Greg_Log("UV: 0x%x, 0x%x", r->U, r->V); +} + +void __gifCall GIFRegHandlerXYZF2(const u32* data) +{ + FUNCLOG + GIFRegXYZF* r = (GIFRegXYZF*)(data); + gs.add_vertex(r->X, r->Y,r->Z, r->F); + + ZZKick->KickVertex(false); + ZZLog::Greg_Log("XYZF2: 0x%x, 0x%x, 0x%x, %f", r->X, r->Y, r->Z, r->F); +} + +void __gifCall GIFRegHandlerXYZ2(const u32* data) +{ + FUNCLOG + GIFRegXYZ* r = (GIFRegXYZ*)(data); + gs.add_vertex(r->X, r->Y,r->Z); + + ZZKick->KickVertex(false); + ZZLog::Greg_Log("XYZF2: 0x%x, 0x%x, 0x%x", r->X, r->Y, r->Z); +} + +template +void __gifCall GIFRegHandlerTEX0(const u32* data) +{ + // Used on Mana Khemias opening dialog. + FUNCLOG + + GIFRegTEX0* r = (GIFRegTEX0*)(data); + u32 psm = ZZOglGet_psm_TexBitsFix(data[0]); + + ZZLog::Greg_Log("TEX0_%d: 0x%x", i, data); + + // Worry about this later. + if (!NoHighlights(i)) return; + + if (m_Blocks[psm].bpp == 0) + { + // kh and others + return; + } + + // Order is important. + vb[i].uNextTex0Data[0] = r->ai32[0]; + vb[i].uNextTex0Data[1] = r->ai32[1]; + vb[i].bNeedTexCheck = 1; + + // don't update unless necessary + if (PSMT_ISCLUT(psm)) + { + if (CheckChangeInClut(data[1], psm)) + { + // loading clut, so flush whole texture + vb[i].FlushTexData(); + } + else if (r->CSA != (vb[i].uCurTex0.CSA)) + { + // check if csa is the same!! (ffx bisaid island, grass) + Flush(i); // flush any previous entries + } + } +} + +template +void __gifCall GIFRegHandlerCLAMP(const u32* data) +{ + FUNCLOG + clampInfo& clamp = vb[i].clamp; + GIFRegCLAMP* r = (GIFRegCLAMP*)(data); + + // Worry about this later. + if (!NoHighlights(i)) return; + + if ((s_uClampData[i] != data[0]) || (((clamp.minv >> 8) | (clamp.maxv << 2)) != (data[1]&0x0fff))) + { + Flush(i); + + vb[i].bTexConstsSync = false; + } + + s_uClampData[i] = data[0]; + + clamp.wms = r->WMS; + clamp.wmt = r->WMT; + clamp.minu = r->MINU; + clamp.maxu = r->MAXU; + clamp.minv = r->MINV; + clamp.maxv = r->MAXV; + ZZLog::Greg_Log("CLAMP_%d: 0x%x", i, data); +} + +void __gifCall GIFRegHandlerFOG(const u32* data) +{ + FUNCLOG + GIFRegFOG* r = (GIFRegFOG*)(data); + gs.vertexregs.f = r->F; + ZZLog::Greg_Log("FOG: 0x%x", r->F); +} + +void __gifCall GIFRegHandlerXYZF3(const u32* data) +{ + FUNCLOG + GIFRegXYZF* r = (GIFRegXYZF*)(data); + gs.add_vertex(r->X, r->Y,r->Z, r->F); + + ZZKick->KickVertex(true); + ZZLog::Greg_Log("XYZF3: 0x%x, 0x%x, 0x%x, %f", r->X, r->Y, r->Z, r->F); +} + +void __gifCall GIFRegHandlerXYZ3(const u32* data) +{ + FUNCLOG + GIFRegXYZ* r = (GIFRegXYZ*)(data); + gs.add_vertex(r->X, r->Y,r->Z); + + ZZKick->KickVertex(true); + ZZLog::Greg_Log("XYZ3: 0x%x, 0x%x, 0x%x", r->X, r->Y, r->Z); +} + +void __gifCall GIFRegHandlerNOP(const u32* data) +{ + FUNCLOG +} + +template +void __fastcall GIFRegHandlerTEX1(const u32* data) +{ + FUNCLOG + GIFRegTEX1* r = (GIFRegTEX1*)(data); + tex1Info& tex1 = vb[i].tex1; + + // Worry about this later. + if (!NoHighlights(i)) return; + + if (conf.bilinear == 1 && (tex1.mmag != r->MMAG || tex1.mmin != r->MMIN)) + { + Flush(i); + vb[i].bVarsTexSync = false; + } + + tex1.lcm = r->LCM; + + tex1.mxl = r->MXL; + tex1.mmag = r->MMAG; + tex1.mmin = r->MMIN; + tex1.mtba = r->MTBA; + tex1.l = r->L; + tex1.k = r->K; + ZZLog::Greg_Log("TEX1_%d: 0x%x", i, data); +} + +template +void __gifCall GIFRegHandlerTEX2(const u32* data) +{ + FUNCLOG + tex0Info& tex0 = vb[i].tex0; + + vb[i].FlushTexData(); + + u32 psm = ZZOglGet_psm_TexBitsFix(data[0]); + + u32* s_uTex0Data = vb[i].uCurTex0Data; + + // don't update unless necessary +// if( ZZOglGet_psm_TexBitsFix(*s_uTex0Data) == ZZOglGet_psm_TexBitsFix(data[0]) ) { // psm is the same + if (ZZOglAllExceptClutIsSame(s_uTex0Data, data)) + { + if (!PSMT_ISCLUT(psm)) return; + + // have to write the CLUT again if changed + if (ZZOglClutMinusCLDunchanged(s_uTex0Data, data)) + { + tex0.cld = ZZOglGet_cld_TexBits(data[1]); + + if (tex0.cld != 0) + { + texClutWrite(i); + // invalidate to make sure target didn't change! + vb[i].bVarsTexSync = false; + } + + return; + } + } + + Flush(i); + + vb[i].bVarsTexSync = false; + vb[i].bTexConstsSync = false; + + s_uTex0Data[0] = (s_uTex0Data[0] & ~0x03f00000) | (psm << 20); + s_uTex0Data[1] = (s_uTex0Data[1] & 0x1f) | (data[1] & ~0x1f); + + tex0.psm = ZZOglGet_psm_TexBitsFix(data[0]); + + if (PSMT_ISCLUT(tex0.psm)) CluttingForFlushedTex(&tex0, data[1], i); + ZZLog::Greg_Log("TEX2_%d: 0x%x", i, data); +} + +template +void __gifCall GIFRegHandlerXYOFFSET(const u32* data) +{ + FUNCLOG + // Affects that Mana Khemia opening dialog (when i == 0). + GIFRegXYOFFSET* r = (GIFRegXYOFFSET*)(data); + vb[i].offset.x = r->OFX; + vb[i].offset.y = r->OFY; + ZZLog::Greg_Log("XYOFFSET_%d: 0x%x, 0x%x", i, r->OFX, r->OFY); +} + +// Fill out the vertex queue(prim) and the attributes. +void __gifCall GIFRegHandlerPRIM(const u32 *data) +{ + FUNCLOG + GIFRegPRIM* r = (GIFRegPRIM*)(data); + + //if (data[0] & ~0x3ff) + //{ + //ZZLog::Warn_Log("Warning: unknown bits in prim %8.8lx_%8.8lx", data[1], data[0]); + //} + + gs.primC = 0; + prim->prim = r->PRIM; + gs._prim[0].prim = r->PRIM; + gs._prim[1].prim = r->PRIM; + gs._prim[1]._val = (data[0] >> 3) & 0xff; // Setting the next 8 flags after prim at once. + + gs.new_tri_fan = !(r->PRIM ^ PRIM_TRIANGLE_FAN); + ZZKick->DirtyValidPrevPrim(); + + Prim(); + ZZLog::Greg_Log("PRIM"); +} + +// Fill out an alternate set of attributes. +void __gifCall GIFRegHandlerPRMODE(const u32* data) +{ + FUNCLOG + //GIFRegPRMODE* r = (GIFRegPRMODE*)(data); + // Re-examine all code dealing with PRIMs in a bit. + gs._prim[0]._val = (data[0] >> 3) & 0xff; + + if (gs.prac == 0) Prim(); + ZZLog::Greg_Log("PRMODE"); +} + +// Switch between the primary set of attributes (gs._prim[1]) and the secondary (gs._prim[0]). +void __gifCall GIFRegHandlerPRMODECONT(const u32* data) +{ + FUNCLOG + // Turns all the text into colored blocks on the initial Mana Khemia dialog if not run. + GIFRegPRMODECONT* r = (GIFRegPRMODECONT*)(data); + gs.prac = r->AC; + prim = &gs._prim[gs.prac]; + + Prim(); + ZZLog::Greg_Log("PRMODECONT"); +} + +void __gifCall GIFRegHandlerTEXCLUT(const u32* data) +{ + FUNCLOG + // Affects background coloration of initial Mana Khemia dialog. + GIFRegTEXCLUT* r = (GIFRegTEXCLUT*)(data); + + vb[0].FlushTexData(); + vb[1].FlushTexData(); + + // Fixme. + gs.clut.cbw = r->CBW << 6; + gs.clut.cou = r->COU << 4; + gs.clut.cov = r->COV; + ZZLog::Greg_Log("TEXCLUT: CBW:0x%x, COU:0x%x, COV:0x%x",r->CBW, r->COU, r->COV); +} + +void __gifCall GIFRegHandlerSCANMSK(const u32* data) +{ + FUNCLOG + GIFRegSCANMSK* r = (GIFRegSCANMSK*)(data); + + if(r->MSK != gs.smask) + { + FlushBoth(); +// ResolveC(&vb[0]); +// ResolveZ(&vb[0]); + } + + gs.smask = r->MSK; + ZZLog::Greg_Log("SCANMSK: 0x%x",r->MSK); +} + +template +void __gifCall GIFRegHandlerMIPTBP1(const u32* data) +{ + FUNCLOG + GIFRegMIPTBP1* r = (GIFRegMIPTBP1*)(data); + /*if(PRIM->CTXT == i && r != miptbp0) + { + Flush(); + }*/ + + miptbpInfo& miptbp0 = vb[i].miptbp0; + miptbp0.tbp[0] = r->TBP1; + miptbp0.tbw[0] = r->TBW1; + miptbp0.tbp[1] = r->TBP2; + miptbp0.tbw[1] = r->TBW2; + miptbp0.tbp[2] = r->TBP3; + miptbp0.tbw[2] = r->TBW3; + ZZLog::Greg_Log("MIPTBP1_%d: TBP/TBW: (0x%x, 0x%x), (0x%x, 0x%x), (0x%x, 0x%x)", i, r->TBP1, r->TBW1, r->TBP2, r->TBW2, r->TBP3, r->TBW3); +} + +template +void __gifCall GIFRegHandlerMIPTBP2(const u32* data) +{ + FUNCLOG + GIFRegMIPTBP2* r = (GIFRegMIPTBP2*)(data); + // Yep. + + miptbpInfo& miptbp1 = vb[i].miptbp1; + miptbp1.tbp[0] = r->TBP4; + miptbp1.tbw[0] = r->TBW4; + miptbp1.tbp[1] = r->TBP5; + miptbp1.tbw[1] = r->TBW5; + miptbp1.tbp[2] = r->TBP6; + miptbp1.tbw[2] = r->TBW6; + ZZLog::Greg_Log("MIPTBP2_%d: TBP/TBW: (0x%x, 0x%x), (0x%x, 0x%x), (0x%x, 0x%x)", i, r->TBP4, r->TBW4, r->TBP5, r->TBW5, r->TBP6, r->TBW6); +} + +void __gifCall GIFRegHandlerTEXA(const u32* data) +{ + FUNCLOG + // Background of initial Mana Khemia dialog. + GIFRegTEXA* r = (GIFRegTEXA*)(data); + + if ((r->AEM != gs.texa.aem) || (r->TA0 != gs.texa.ta[0]) || (r->TA1 != gs.texa.ta[1])) + { + FlushBoth(); + + vb[0].bTexConstsSync = false; + vb[1].bTexConstsSync = false; + } + + gs.texa.aem = r->AEM; + gs.texa.ta[0] = r->TA0; + gs.texa.ta[1] = r->TA1; + gs.texa.fta[0] = r->TA0 / 255.0f; + gs.texa.fta[1] = r->TA1 / 255.0f; + ZZLog::Greg_Log("TEXA: AEM:0x%x, TA0:0x%x, TA1:0x%x", r->AEM, r->TA0, r->TA1); +} + +void __gifCall GIFRegHandlerFOGCOL(const u32* data) +{ + FUNCLOG + GIFRegFOGCOL* r = (GIFRegFOGCOL*)(data); + + if (gs.fogcol != r->ai32[0]) + { + FlushBoth(); + } + + SetFogColor(r); + gs.fogcol = r->ai32[0]; + ZZLog::Greg_Log("FOGCOL: 0x%x", r->ai32[0]); +} + +void __gifCall GIFRegHandlerTEXFLUSH(const u32* data) +{ + FUNCLOG + // GSdx doesn't even do anything here. + SetTexFlush(); + ZZLog::Greg_Log("TEXFLUSH"); +} + +template +void __gifCall GIFRegHandlerSCISSOR(const u32* data) +{ + FUNCLOG + GIFRegSCISSOR* r = (GIFRegSCISSOR*)(data); + Rect2& scissor = vb[i].scissor; + + Rect2 newscissor; + + // << 3? + newscissor.x0 = r->SCAX0 << 3; + newscissor.x1 = r->SCAX1 << 3; + newscissor.y0 = r->SCAY0 << 3; + newscissor.y1 = r->SCAY1 << 3; + + if (newscissor.x1 != scissor.x1 || newscissor.y1 != scissor.y1 || + newscissor.x0 != scissor.x0 || newscissor.y0 != scissor.y0) + { + Flush(i); + + // flush everything + vb[i].bNeedFrameCheck = 1; + } + + scissor = newscissor; + + //Hmm... + /* + if(PRIM->CTXT == i && r->SCISSOR != m_env.CTXT[i].SCISSOR) + { + Flush(); + } + + m_env.CTXT[i].SCISSOR = (GSVector4i)r->SCISSOR; + + m_env.CTXT[i].UpdateScissor();*/ + ZZLog::Greg_Log("SCISSOR%d", i); +} + +template +void __gifCall GIFRegHandlerALPHA(const u32* data) +{ + FUNCLOG + // Mana Khemia Opening Dialog (when i = 0). + GIFRegALPHA* r = (GIFRegALPHA*)(data); + alphaInfo newalpha; + + newalpha.a = r->A; + newalpha.b = r->B; + newalpha.c = r->C; + newalpha.d = r->D; + newalpha.fix = r->FIX; + + if (newalpha.a == 3) newalpha.a = 0; + if (newalpha.b == 3) newalpha.b = 0; + if (newalpha.c == 3) newalpha.c = 0; + if (newalpha.d == 3) newalpha.d = 0; + + if ((newalpha.abcd != vb[i].alpha.abcd) || (newalpha.fix != vb[i].alpha.fix)) + { + Flush(i); + } + + vb[i].alpha = newalpha; + ZZLog::Greg_Log("ALPHA%d: A:0x%x B:0x%x C:0x%x D:0x%x FIX:0x%x ", i, r->A, r->B, r->C, r->D, r->FIX); +} + +void __gifCall GIFRegHandlerDIMX(const u32* data) +{ + FUNCLOG + + GIFRegDIMX* r = (GIFRegDIMX*)(data); + // Not even handled? Fixme. + bool update = false; + + if (r->i64 != gs.dimx.i64) + { + FlushBoth(); + + update = true; + } + + gs.dimx.i64 = r->i64; + + if (update) + { + //gs.UpdateDIMX(); + } + ZZLog::Greg_Log("DIMX"); +} + +void __gifCall GIFRegHandlerDTHE(const u32* data) +{ + FUNCLOG + GIFRegDTHE* r = (GIFRegDTHE*)(data); + + if (r->DTHE != gs.dthe) + { + FlushBoth(); + } + + gs.dthe = r->DTHE; + ZZLog::Greg_Log("DTHE: 0x%x ", r->DTHE); +} + +void __gifCall GIFRegHandlerCOLCLAMP(const u32* data) +{ + FUNCLOG + GIFRegCOLCLAMP* r = (GIFRegCOLCLAMP*)(data); + + if (r->CLAMP != gs.colclamp) + { + FlushBoth(); + } + + gs.colclamp = r->CLAMP; + ZZLog::Greg_Log("COLCLAMP: 0x%x ", r->CLAMP); +} + +template +void __gifCall GIFRegHandlerTEST(const u32* data) +{ + FUNCLOG + pixTest* test = &vb[i].test; + GIFRegTEST* r = (GIFRegTEST*)(data); + + if (test->_val != r->ai32[0]) + { + Flush(i); + } + + test->_val = r->ai32[0]; + ZZLog::Greg_Log("TEST%d", i); +} + +void __gifCall GIFRegHandlerPABE(const u32* data) +{ + FUNCLOG + GIFRegPABE* r = (GIFRegPABE*)(data); + + if (gs.pabe != r->PABE) + { + FlushBoth(); +// SetAlphaChanged(0, GPUREG_PABE); +// SetAlphaChanged(1, GPUREG_PABE); + } + + gs.pabe = r->PABE; + ZZLog::Greg_Log("PABE: 0x%x ", r->PABE); +} + +template +void __gifCall GIFRegHandlerFBA(const u32* data) +{ + FUNCLOG + GIFRegFBA* r = (GIFRegFBA*)(data); + + if (r->FBA != vb[i].fba.fba) + { + FlushBoth(); + } + + vb[i].fba.fba = r->FBA; + ZZLog::Greg_Log("FBA%d: 0x%x ", i, r->FBA); +} + +template +void __gifCall GIFRegHandlerFRAME(const u32* data) +{ + FUNCLOG + // Affects opening dialogs, movie, and menu on Mana Khemia. + + GIFRegFRAME* r = (GIFRegFRAME*)(data); + frameInfo& gsfb = vb[i].gsfb; + + int fbw = r->FBW * 64; + int fbp = r->FBP * 32; + int fbh = 0; + + if (gs.dthe != 0) + { + // Dither here. + //ZZLog::Error_Log("frameWrite: Dither!"); + } + + if ((gsfb.fbp == fbp) && + (gsfb.fbw == fbw) && + (gsfb.psm == r->PSM) && + (gsfb.fbm == ZZOglGet_fbm_FrameBitsFix(data[0], data[1]))) + { + return; + } + + FlushBoth(); + if (r->FBW > 0) fbh = ZZOgl_fbh_Calc(r->FBP, r->FBW, r->PSM); + + gsfb.fbp = fbp; + gsfb.fbw = fbw; + gsfb.psm = r->PSM; + gsfb.fbh = fbh; + gsfb.fbm = ZZOglGet_fbm_FrameBitsFix(data[0], data[1]); + + + vb[i].bNeedFrameCheck = 1; + ZZLog::Greg_Log("FRAME_%d", i); +} + +template +void __gifCall GIFRegHandlerZBUF(const u32* data) +{ + FUNCLOG + // I'll wait a bit on this one. + GIFRegZBUF* r = (GIFRegZBUF*)(data); + ZZLog::Greg_Log("ZBUF_1"); + + zbufInfo& zbuf = vb[i].zbuf; + int psm = (0x30 | r->PSM); + int zbp = r->ZBP * 32; + + if (zbuf.zbp == zbp && + zbuf.psm == psm && + zbuf.zmsk == r->ZMSK) + { + return; + } + + // error detection + if (m_Blocks[psm].bpp == 0) return; + + FlushBoth(); + + zbuf.zbp = zbp; + zbuf.psm = psm; + zbuf.zmsk = r->ZMSK; + + vb[i].zprimmask = 0xffffffff; + + if (zbuf.psm > 0x31) vb[i].zprimmask = 0xffff; + + vb[i].bNeedZCheck = 1; +} + +void __gifCall GIFRegHandlerBITBLTBUF(const u32* data) +{ + FUNCLOG + // Required for *all* graphics. (Checked on Mana Khemia) + + GIFRegBITBLTBUF* r = (GIFRegBITBLTBUF*)(data); + // Wonder why the shift? + gs.srcbufnew.bp = r->SBP; // * 64; + gs.srcbufnew.bw = r->SBW << 6; + gs.srcbufnew.psm = r->SPSM; + gs.dstbufnew.bp = r->DBP; // * 64; + gs.dstbufnew.bw = r->DBW << 6; + gs.dstbufnew.psm = r->DPSM; + + if (gs.dstbufnew.bw == 0) gs.dstbufnew.bw = 64; + // GSdx does this: + + /*if((gs.srcbufnew.bw & 1) && (gs.srcbufnew.psm == PSM_PSMT8 || gs.srcbufnew.psm == PSM_PSMT4)) + { + gs.srcbufnew.bw &= ~1; + } + + if((gs.dstbufnew.bw & 1) && (gs.dstbufnew.psm == PSM_PSMT8 || gs.dstbufnew.psm == PSM_PSMT4)) + { + gs.dstbufnew.bw &= ~1; // namcoXcapcom: 5, 11, refered to as 4, 10 in TEX0.TBW later + }*/ + ZZLog::Greg_Log("BITBLTBUF"); +} + +void __gifCall GIFRegHandlerTRXPOS(const u32* data) +{ + // Affects Mana Khemia opening background. + FUNCLOG + GIFRegTRXPOS* r = (GIFRegTRXPOS*)(data); + + gs.trxposnew.sx = r->SSAX; + gs.trxposnew.sy = r->SSAY; + gs.trxposnew.dx = r->DSAX; + gs.trxposnew.dy = r->DSAY; + gs.trxposnew.dirx = r->DIRX; + gs.trxposnew.diry = r->DIRY; + ZZLog::Greg_Log("TRXPOS: SSA:(0x%x/0x%x) DSA:(0x%x/0x%x) DIR:(0x%x/0x%x)", r->SSAX, r->SSAY, r->DSAX, r->DSAY, r->DIRX, r->DIRY); +} + +void __gifCall GIFRegHandlerTRXREG(const u32* data) +{ + FUNCLOG + GIFRegTRXREG* r = (GIFRegTRXREG*)(data); + gs.imageWtemp = r->RRW; + gs.imageHtemp = r->RRH; + ZZLog::Greg_Log("TRXREG: RRW: 0x%x, RRH: 0x%x", r->RRW, r->RRH); +} + +void __gifCall GIFRegHandlerTRXDIR(const u32* data) +{ + FUNCLOG + GIFRegTRXDIR* r = (GIFRegTRXDIR*)(data); + // Oh dear... + + // terminate any previous transfers + + switch (gs.imageTransfer) + { + case 0: // host->loc + TerminateHostLocal(); + break; + + case 1: // loc->host + TerminateLocalHost(); + break; + } + + gs.srcbuf = gs.srcbufnew; + gs.dstbuf = gs.dstbufnew; + gs.trxpos = gs.trxposnew; + + gs.imageTransfer = r->XDIR; + gs.imageWnew = gs.imageWtemp; + gs.imageHnew = gs.imageHtemp; + + if (gs.imageWnew > 0 && gs.imageHnew > 0) + { + switch (gs.imageTransfer) + { + case 0: // host->loc + InitTransferHostLocal(); + break; + + case 1: // loc->host + InitTransferLocalHost(); + break; + + case 2: + TransferLocalLocal(); + break; + + case 3: + gs.imageTransfer = -1; + break; + + default: + assert(0); + } + } + else + { +#if defined(ZEROGS_DEVBUILD) + ZZLog::Warn_Log("Dummy transfer."); +#endif + gs.imageTransfer = -1; + } + ZZLog::Greg_Log("TRXDIR"); +} + +void __gifCall GIFRegHandlerHWREG(const u32* data) +{ + FUNCLOG + + if (gs.imageTransfer == 0) + { + TransferHostLocal(data, 2); + } + else + { +#if defined(ZEROGS_DEVBUILD) + ZZLog::Error_Log("ZeroGS: HWREG!? %8.8x_%8.8x", data[0], data[1]); + //assert(0); +#endif + } + ZZLog::Greg_Log("HWREG"); +} + +extern int g_GSMultiThreaded; + +void __gifCall GIFRegHandlerSIGNAL(const u32* data) +{ + FUNCLOG + + if (!g_GSMultiThreaded) + { + SIGLBLID->SIGID = (SIGLBLID->SIGID & ~data[1]) | (data[0] & data[1]); + + if (gs.CSRw & 0x1) + { + CSR->SIGNAL = 1; + } + + if (!IMR->SIGMSK && GSirq) GSirq(); + } +} + +void __gifCall GIFRegHandlerFINISH(const u32* data) +{ + FUNCLOG + + if (!g_GSMultiThreaded) + { + if (gs.CSRw & 0x2) CSR->FINISH = 1; + + if (!IMR->FINISHMSK && GSirq) GSirq(); + } +} + +void __gifCall GIFRegHandlerLABEL(const u32* data) +{ + FUNCLOG + + if (!g_GSMultiThreaded) + { + SIGLBLID->LBLID = (SIGLBLID->LBLID & ~data[1]) | (data[0] & data[1]); + } +} + + +void SetMultithreaded() +{ + // Some older versions of PCSX2 didn't properly set the irq callback to NULL + // in multithreaded mode (possibly because ZeroGS itself would assert in such + // cases), and didn't bind them to a dummy callback either. PCSX2 handles all + // IRQs internally when multithreaded anyway -- so let's ignore them here: + + if (g_GSMultiThreaded) + { + g_GIFRegHandlers[GIF_A_D_REG_SIGNAL] = &GIFRegHandlerNull; + g_GIFRegHandlers[GIF_A_D_REG_FINISH] = &GIFRegHandlerNull; + g_GIFRegHandlers[GIF_A_D_REG_LABEL] = &GIFRegHandlerNull; + } + else + { + g_GIFRegHandlers[GIF_A_D_REG_SIGNAL] = &GIFRegHandlerSIGNAL; + g_GIFRegHandlers[GIF_A_D_REG_FINISH] = &GIFRegHandlerFINISH; + g_GIFRegHandlers[GIF_A_D_REG_LABEL] = &GIFRegHandlerLABEL; + } +} + +void ResetRegs() +{ + for (int i = 0; i < 16; i++) + { + g_GIFPackedRegHandlers[i] = &GIFPackedRegHandlerNull; + } + + g_GIFPackedRegHandlers[GIF_REG_PRIM] = &GIFPackedRegHandlerPRIM; + g_GIFPackedRegHandlers[GIF_REG_RGBA] = &GIFPackedRegHandlerRGBA; + g_GIFPackedRegHandlers[GIF_REG_STQ] = &GIFPackedRegHandlerSTQ; + g_GIFPackedRegHandlers[GIF_REG_UV] = &GIFPackedRegHandlerUV; + g_GIFPackedRegHandlers[GIF_REG_XYZF2] = &GIFPackedRegHandlerXYZF2; + g_GIFPackedRegHandlers[GIF_REG_XYZ2] = &GIFPackedRegHandlerXYZ2; + g_GIFPackedRegHandlers[GIF_REG_TEX0_1] = &GIFPackedRegHandlerTEX0<0>; + g_GIFPackedRegHandlers[GIF_REG_TEX0_2] = &GIFPackedRegHandlerTEX0<1>; + g_GIFPackedRegHandlers[GIF_REG_CLAMP_1] = &GIFPackedRegHandlerCLAMP<0>; + g_GIFPackedRegHandlers[GIF_REG_CLAMP_2] = &GIFPackedRegHandlerCLAMP<1>; + g_GIFPackedRegHandlers[GIF_REG_FOG] = &GIFPackedRegHandlerFOG; + g_GIFPackedRegHandlers[GIF_REG_XYZF3] = &GIFPackedRegHandlerXYZF3; + g_GIFPackedRegHandlers[GIF_REG_XYZ3] = &GIFPackedRegHandlerXYZ3; + g_GIFPackedRegHandlers[GIF_REG_A_D] = &GIFPackedRegHandlerA_D; + g_GIFPackedRegHandlers[GIF_REG_NOP] = &GIFPackedRegHandlerNOP; + + for (int i = 0; i < 256; i++) + { + g_GIFRegHandlers[i] = &GIFPackedRegHandlerNull; + } + + g_GIFRegHandlers[GIF_A_D_REG_PRIM] = &GIFRegHandlerPRIM; + g_GIFRegHandlers[GIF_A_D_REG_RGBAQ] = &GIFRegHandlerRGBAQ; + g_GIFRegHandlers[GIF_A_D_REG_ST] = &GIFRegHandlerST; + g_GIFRegHandlers[GIF_A_D_REG_UV] = &GIFRegHandlerUV; + g_GIFRegHandlers[GIF_A_D_REG_XYZF2] = &GIFRegHandlerXYZF2; + g_GIFRegHandlers[GIF_A_D_REG_XYZ2] = &GIFRegHandlerXYZ2; + g_GIFRegHandlers[GIF_A_D_REG_TEX0_1] = &GIFRegHandlerTEX0<0>; + g_GIFRegHandlers[GIF_A_D_REG_TEX0_2] = &GIFRegHandlerTEX0<1>; + g_GIFRegHandlers[GIF_A_D_REG_CLAMP_1] = &GIFRegHandlerCLAMP<0>; + g_GIFRegHandlers[GIF_A_D_REG_CLAMP_2] = &GIFRegHandlerCLAMP<1>; + g_GIFRegHandlers[GIF_A_D_REG_FOG] = &GIFRegHandlerFOG; + g_GIFRegHandlers[GIF_A_D_REG_XYZF3] = &GIFRegHandlerXYZF3; + g_GIFRegHandlers[GIF_A_D_REG_XYZ3] = &GIFRegHandlerXYZ3; + g_GIFRegHandlers[GIF_A_D_REG_NOP] = &GIFRegHandlerNOP; + g_GIFRegHandlers[GIF_A_D_REG_TEX1_1] = &GIFRegHandlerTEX1<0>; + g_GIFRegHandlers[GIF_A_D_REG_TEX1_2] = &GIFRegHandlerTEX1<1>; + g_GIFRegHandlers[GIF_A_D_REG_TEX2_1] = &GIFRegHandlerTEX2<0>; + g_GIFRegHandlers[GIF_A_D_REG_TEX2_2] = &GIFRegHandlerTEX2<1>; + g_GIFRegHandlers[GIF_A_D_REG_XYOFFSET_1] = &GIFRegHandlerXYOFFSET<0>; + g_GIFRegHandlers[GIF_A_D_REG_XYOFFSET_2] = &GIFRegHandlerXYOFFSET<1>; + g_GIFRegHandlers[GIF_A_D_REG_PRMODECONT] = &GIFRegHandlerPRMODECONT; + g_GIFRegHandlers[GIF_A_D_REG_PRMODE] = &GIFRegHandlerPRMODE; + g_GIFRegHandlers[GIF_A_D_REG_TEXCLUT] = &GIFRegHandlerTEXCLUT; + g_GIFRegHandlers[GIF_A_D_REG_SCANMSK] = &GIFRegHandlerSCANMSK; + g_GIFRegHandlers[GIF_A_D_REG_MIPTBP1_1] = &GIFRegHandlerMIPTBP1<0>; + g_GIFRegHandlers[GIF_A_D_REG_MIPTBP1_2] = &GIFRegHandlerMIPTBP1<1>; + g_GIFRegHandlers[GIF_A_D_REG_MIPTBP2_1] = &GIFRegHandlerMIPTBP2<0>; + g_GIFRegHandlers[GIF_A_D_REG_MIPTBP2_2] = &GIFRegHandlerMIPTBP2<1>; + g_GIFRegHandlers[GIF_A_D_REG_TEXA] = &GIFRegHandlerTEXA; + g_GIFRegHandlers[GIF_A_D_REG_FOGCOL] = &GIFRegHandlerFOGCOL; + g_GIFRegHandlers[GIF_A_D_REG_TEXFLUSH] = &GIFRegHandlerTEXFLUSH; + g_GIFRegHandlers[GIF_A_D_REG_SCISSOR_1] = &GIFRegHandlerSCISSOR<0>; + g_GIFRegHandlers[GIF_A_D_REG_SCISSOR_2] = &GIFRegHandlerSCISSOR<1>; + g_GIFRegHandlers[GIF_A_D_REG_ALPHA_1] = &GIFRegHandlerALPHA<0>; + g_GIFRegHandlers[GIF_A_D_REG_ALPHA_2] = &GIFRegHandlerALPHA<1>; + g_GIFRegHandlers[GIF_A_D_REG_DIMX] = &GIFRegHandlerDIMX; + g_GIFRegHandlers[GIF_A_D_REG_DTHE] = &GIFRegHandlerDTHE; + g_GIFRegHandlers[GIF_A_D_REG_COLCLAMP] = &GIFRegHandlerCOLCLAMP; + g_GIFRegHandlers[GIF_A_D_REG_TEST_1] = &GIFRegHandlerTEST<0>; + g_GIFRegHandlers[GIF_A_D_REG_TEST_2] = &GIFRegHandlerTEST<1>; + g_GIFRegHandlers[GIF_A_D_REG_PABE] = &GIFRegHandlerPABE; + g_GIFRegHandlers[GIF_A_D_REG_FBA_1] = &GIFRegHandlerFBA<0>; + g_GIFRegHandlers[GIF_A_D_REG_FBA_2] = &GIFRegHandlerFBA<1>; + g_GIFRegHandlers[GIF_A_D_REG_FRAME_1] = &GIFRegHandlerFRAME<0>; + g_GIFRegHandlers[GIF_A_D_REG_FRAME_2] = &GIFRegHandlerFRAME<1>; + g_GIFRegHandlers[GIF_A_D_REG_ZBUF_1] = &GIFRegHandlerZBUF<0>; + g_GIFRegHandlers[GIF_A_D_REG_ZBUF_2] = &GIFRegHandlerZBUF<1>; + g_GIFRegHandlers[GIF_A_D_REG_BITBLTBUF] = &GIFRegHandlerBITBLTBUF; + g_GIFRegHandlers[GIF_A_D_REG_TRXPOS] = &GIFRegHandlerTRXPOS; + g_GIFRegHandlers[GIF_A_D_REG_TRXREG] = &GIFRegHandlerTRXREG; + g_GIFRegHandlers[GIF_A_D_REG_TRXDIR] = &GIFRegHandlerTRXDIR; + g_GIFRegHandlers[GIF_A_D_REG_HWREG] = &GIFRegHandlerHWREG; + SetMultithreaded(); +} + +void WriteTempRegs() +{ + memcpy(g_GIFTempRegHandlers, g_GIFPackedRegHandlers, sizeof(g_GIFTempRegHandlers)); +} + +void SetFrameSkip(bool skip) +{ + if (skip) + { + g_GIFPackedRegHandlers[GIF_REG_PRIM] = &GIFPackedRegHandlerNOP; + g_GIFPackedRegHandlers[GIF_REG_RGBA] = &GIFPackedRegHandlerNOP; + g_GIFPackedRegHandlers[GIF_REG_STQ] = &GIFPackedRegHandlerNOP; + g_GIFPackedRegHandlers[GIF_REG_UV] = &GIFPackedRegHandlerNOP; + g_GIFPackedRegHandlers[GIF_REG_XYZF2] = &GIFPackedRegHandlerNOP; + g_GIFPackedRegHandlers[GIF_REG_XYZ2] = &GIFPackedRegHandlerNOP; + g_GIFPackedRegHandlers[GIF_REG_CLAMP_1] = &GIFPackedRegHandlerNOP; + g_GIFPackedRegHandlers[GIF_REG_CLAMP_2] = &GIFPackedRegHandlerNOP; + g_GIFPackedRegHandlers[GIF_REG_FOG] = &GIFPackedRegHandlerNOP; + g_GIFPackedRegHandlers[GIF_REG_XYZF3] = &GIFPackedRegHandlerNOP; + g_GIFPackedRegHandlers[GIF_REG_XYZ3] = &GIFPackedRegHandlerNOP; + + g_GIFRegHandlers[GIF_A_D_REG_PRIM] = &GIFRegHandlerNOP; + g_GIFRegHandlers[GIF_A_D_REG_RGBAQ] = &GIFRegHandlerNOP; + g_GIFRegHandlers[GIF_A_D_REG_ST] = &GIFRegHandlerNOP; + g_GIFRegHandlers[GIF_A_D_REG_UV] = &GIFRegHandlerNOP; + g_GIFRegHandlers[GIF_A_D_REG_XYZF2] = &GIFRegHandlerNOP; + g_GIFRegHandlers[GIF_A_D_REG_XYZ2] = &GIFRegHandlerNOP; + g_GIFRegHandlers[GIF_A_D_REG_XYZF3] = &GIFRegHandlerNOP; + g_GIFRegHandlers[GIF_A_D_REG_XYZ3] = &GIFRegHandlerNOP; + g_GIFRegHandlers[GIF_A_D_REG_PRMODECONT] = &GIFRegHandlerNOP; + g_GIFRegHandlers[GIF_A_D_REG_PRMODE] = &GIFRegHandlerNOP; + } + else + { + g_GIFPackedRegHandlers[GIF_REG_PRIM] = &GIFPackedRegHandlerPRIM; + g_GIFPackedRegHandlers[GIF_REG_RGBA] = &GIFPackedRegHandlerRGBA; + g_GIFPackedRegHandlers[GIF_REG_STQ] = &GIFPackedRegHandlerSTQ; + g_GIFPackedRegHandlers[GIF_REG_UV] = &GIFPackedRegHandlerUV; + g_GIFPackedRegHandlers[GIF_REG_XYZF2] = &GIFPackedRegHandlerXYZF2; + g_GIFPackedRegHandlers[GIF_REG_XYZ2] = &GIFPackedRegHandlerXYZ2; + g_GIFPackedRegHandlers[GIF_REG_CLAMP_1] = &GIFPackedRegHandlerCLAMP<0>; + g_GIFPackedRegHandlers[GIF_REG_CLAMP_2] = &GIFPackedRegHandlerCLAMP<1>; + g_GIFPackedRegHandlers[GIF_REG_FOG] = &GIFPackedRegHandlerFOG; + g_GIFPackedRegHandlers[GIF_REG_XYZF3] = &GIFPackedRegHandlerXYZF3; + g_GIFPackedRegHandlers[GIF_REG_XYZ3] = &GIFPackedRegHandlerXYZ3; + + g_GIFRegHandlers[GIF_A_D_REG_PRIM] = &GIFRegHandlerPRIM; + g_GIFRegHandlers[GIF_A_D_REG_RGBAQ] = &GIFRegHandlerRGBAQ; + g_GIFRegHandlers[GIF_A_D_REG_ST] = &GIFRegHandlerST; + g_GIFRegHandlers[GIF_A_D_REG_UV] = &GIFRegHandlerUV; + g_GIFRegHandlers[GIF_A_D_REG_XYZF2] = &GIFRegHandlerXYZF2; + g_GIFRegHandlers[GIF_A_D_REG_XYZ2] = &GIFRegHandlerXYZ2; + g_GIFRegHandlers[GIF_A_D_REG_XYZF3] = &GIFRegHandlerXYZF3; + g_GIFRegHandlers[GIF_A_D_REG_XYZ3] = &GIFRegHandlerXYZ3; + g_GIFRegHandlers[GIF_A_D_REG_PRMODECONT] = &GIFRegHandlerPRMODECONT; + g_GIFRegHandlers[GIF_A_D_REG_PRMODE] = &GIFRegHandlerPRMODE; + } +} +#endif diff --git a/plugins/zzogl-pg-cg/opengl/NewRegs.h b/plugins/zzogl-pg-cg/opengl/NewRegs.h new file mode 100644 index 000000000..b915ef1b7 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/NewRegs.h @@ -0,0 +1,973 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef NEWREGS_H_INCLUDED +#define NEWREGS_H_INCLUDED + +#ifdef USE_OLD_REGS +#include "Regs.h" +#else + +enum GIF_REG +{ + GIF_REG_PRIM = 0x00, + GIF_REG_RGBA = 0x01, + GIF_REG_STQ = 0x02, + GIF_REG_UV = 0x03, + GIF_REG_XYZF2 = 0x04, + GIF_REG_XYZ2 = 0x05, + GIF_REG_TEX0_1 = 0x06, + GIF_REG_TEX0_2 = 0x07, + GIF_REG_CLAMP_1 = 0x08, + GIF_REG_CLAMP_2 = 0x09, + GIF_REG_FOG = 0x0a, + GIF_REG_XYZF3 = 0x0c, + GIF_REG_XYZ3 = 0x0d, + GIF_REG_A_D = 0x0e, + GIF_REG_NOP = 0x0f, +}; + +enum GIF_A_D_REG +{ + GIF_A_D_REG_PRIM = 0x00, + GIF_A_D_REG_RGBAQ = 0x01, + GIF_A_D_REG_ST = 0x02, + GIF_A_D_REG_UV = 0x03, + GIF_A_D_REG_XYZF2 = 0x04, + GIF_A_D_REG_XYZ2 = 0x05, + GIF_A_D_REG_TEX0_1 = 0x06, + GIF_A_D_REG_TEX0_2 = 0x07, + GIF_A_D_REG_CLAMP_1 = 0x08, + GIF_A_D_REG_CLAMP_2 = 0x09, + GIF_A_D_REG_FOG = 0x0a, + GIF_A_D_REG_XYZF3 = 0x0c, + GIF_A_D_REG_XYZ3 = 0x0d, + GIF_A_D_REG_NOP = 0x0f, + GIF_A_D_REG_TEX1_1 = 0x14, + GIF_A_D_REG_TEX1_2 = 0x15, + GIF_A_D_REG_TEX2_1 = 0x16, + GIF_A_D_REG_TEX2_2 = 0x17, + GIF_A_D_REG_XYOFFSET_1 = 0x18, + GIF_A_D_REG_XYOFFSET_2 = 0x19, + GIF_A_D_REG_PRMODECONT = 0x1a, + GIF_A_D_REG_PRMODE = 0x1b, + GIF_A_D_REG_TEXCLUT = 0x1c, + GIF_A_D_REG_SCANMSK = 0x22, + GIF_A_D_REG_MIPTBP1_1 = 0x34, + GIF_A_D_REG_MIPTBP1_2 = 0x35, + GIF_A_D_REG_MIPTBP2_1 = 0x36, + GIF_A_D_REG_MIPTBP2_2 = 0x37, + GIF_A_D_REG_TEXA = 0x3b, + GIF_A_D_REG_FOGCOL = 0x3d, + GIF_A_D_REG_TEXFLUSH = 0x3f, + GIF_A_D_REG_SCISSOR_1 = 0x40, + GIF_A_D_REG_SCISSOR_2 = 0x41, + GIF_A_D_REG_ALPHA_1 = 0x42, + GIF_A_D_REG_ALPHA_2 = 0x43, + GIF_A_D_REG_DIMX = 0x44, + GIF_A_D_REG_DTHE = 0x45, + GIF_A_D_REG_COLCLAMP = 0x46, + GIF_A_D_REG_TEST_1 = 0x47, + GIF_A_D_REG_TEST_2 = 0x48, + GIF_A_D_REG_PABE = 0x49, + GIF_A_D_REG_FBA_1 = 0x4a, + GIF_A_D_REG_FBA_2 = 0x4b, + GIF_A_D_REG_FRAME_1 = 0x4c, + GIF_A_D_REG_FRAME_2 = 0x4d, + GIF_A_D_REG_ZBUF_1 = 0x4e, + GIF_A_D_REG_ZBUF_2 = 0x4f, + GIF_A_D_REG_BITBLTBUF = 0x50, + GIF_A_D_REG_TRXPOS = 0x51, + GIF_A_D_REG_TRXREG = 0x52, + GIF_A_D_REG_TRXDIR = 0x53, + GIF_A_D_REG_HWREG = 0x54, + GIF_A_D_REG_SIGNAL = 0x60, + GIF_A_D_REG_FINISH = 0x61, + GIF_A_D_REG_LABEL = 0x62, +}; +// In case we want to change to/from __fastcall for GIF register handlers: +#define __gifCall __fastcall + +typedef void __gifCall FnType_GIFRegHandler(const u32* data); +typedef FnType_GIFRegHandler* GIFRegHandler; + +extern FnType_GIFRegHandler GIFPackedRegHandlerNull; +extern FnType_GIFRegHandler GIFPackedRegHandlerRGBA; +extern FnType_GIFRegHandler GIFPackedRegHandlerSTQ; +extern FnType_GIFRegHandler GIFPackedRegHandlerUV; +extern FnType_GIFRegHandler GIFPackedRegHandlerXYZF2; +extern FnType_GIFRegHandler GIFPackedRegHandlerXYZ2; +extern FnType_GIFRegHandler GIFPackedRegHandlerFOG; +extern FnType_GIFRegHandler GIFPackedRegHandlerA_D; +extern FnType_GIFRegHandler GIFPackedRegHandlerNOP; + +// These are unimplemented, and fall back on the non-packed versions. +extern FnType_GIFRegHandler GIFPackedRegHandlerPRIM; + +template +extern FnType_GIFRegHandler GIFPackedRegHandlerTEX0; + +template +extern FnType_GIFRegHandler GIFPackedRegHandlerCLAMP; + +extern FnType_GIFRegHandler GIFPackedRegHandlerXYZF3; +extern FnType_GIFRegHandler GIFPackedRegHandlerXYZ3; + +extern FnType_GIFRegHandler GIFRegHandlerNull; +extern FnType_GIFRegHandler GIFRegHandlerPRIM; +extern FnType_GIFRegHandler GIFRegHandlerRGBAQ; +extern FnType_GIFRegHandler GIFRegHandlerST; +extern FnType_GIFRegHandler GIFRegHandlerUV; +extern FnType_GIFRegHandler GIFRegHandlerXYZF2; +extern FnType_GIFRegHandler GIFRegHandlerXYZ2; + +template +extern FnType_GIFRegHandler GIFRegHandlerTEX0; + +template +extern FnType_GIFRegHandler GIFRegHandlerCLAMP; + +extern FnType_GIFRegHandler GIFRegHandlerFOG; +extern FnType_GIFRegHandler GIFRegHandlerXYZF3; +extern FnType_GIFRegHandler GIFRegHandlerXYZ3; +extern FnType_GIFRegHandler GIFRegHandlerNOP; + +template +extern FnType_GIFRegHandler GIFRegHandlerTEX1; + +template +extern FnType_GIFRegHandler GIFRegHandlerTEX2; + +template +extern FnType_GIFRegHandler GIFRegHandlerXYOFFSET; + +extern FnType_GIFRegHandler GIFRegHandlerPRMODECONT; +extern FnType_GIFRegHandler GIFRegHandlerPRMODE; +extern FnType_GIFRegHandler GIFRegHandlerTEXCLUT; +extern FnType_GIFRegHandler GIFRegHandlerSCANMSK; +template +extern FnType_GIFRegHandler GIFRegHandlerMIPTBP1; +template +extern FnType_GIFRegHandler GIFRegHandlerMIPTBP2; +extern FnType_GIFRegHandler GIFRegHandlerTEXA; +extern FnType_GIFRegHandler GIFRegHandlerFOGCOL; +extern FnType_GIFRegHandler GIFRegHandlerTEXFLUSH; + +template +extern FnType_GIFRegHandler GIFRegHandlerSCISSOR; +template +extern FnType_GIFRegHandler GIFRegHandlerALPHA; + +extern FnType_GIFRegHandler GIFRegHandlerDIMX; +extern FnType_GIFRegHandler GIFRegHandlerDTHE; +extern FnType_GIFRegHandler GIFRegHandlerCOLCLAMP; +template +extern FnType_GIFRegHandler GIFRegHandlerTEST; +extern FnType_GIFRegHandler GIFRegHandlerPABE; +template +extern FnType_GIFRegHandler GIFRegHandlerFBA; +template +extern FnType_GIFRegHandler GIFRegHandlerFRAME; +template +extern FnType_GIFRegHandler GIFRegHandlerZBUF; +extern FnType_GIFRegHandler GIFRegHandlerBITBLTBUF; +extern FnType_GIFRegHandler GIFRegHandlerTRXPOS; +extern FnType_GIFRegHandler GIFRegHandlerTRXREG; +extern FnType_GIFRegHandler GIFRegHandlerTRXDIR; +extern FnType_GIFRegHandler GIFRegHandlerHWREG; +extern FnType_GIFRegHandler GIFRegHandlerSIGNAL; +extern FnType_GIFRegHandler GIFRegHandlerFINISH; +extern FnType_GIFRegHandler GIFRegHandlerLABEL; + +// GifReg & GifPackedReg structs from GSdx, slightly modified + +enum GS_ATST +{ + ATST_NEVER = 0, + ATST_ALWAYS = 1, + ATST_LESS = 2, + ATST_LEQUAL = 3, + ATST_EQUAL = 4, + ATST_GEQUAL = 5, + ATST_GREATER = 6, + ATST_NOTEQUAL = 7, +}; + +enum GS_AFAIL +{ + AFAIL_KEEP = 0, + AFAIL_FB_ONLY = 1, + AFAIL_ZB_ONLY = 2, + AFAIL_RGB_ONLY = 3, +}; + +// GIFReg + +REG64_(GIFReg, ALPHA) + u32 A:2; + u32 B:2; + u32 C:2; + u32 D:2; + u32 _PAD1:24; + u32 FIX:8; + u32 _PAD2:24; +REG_END2 + // opaque => output will be Cs/As + __forceinline bool IsOpaque() const {return (A == B || C == 2 && FIX == 0) && D == 0 || (A == 0 && B == D && C == 2 && FIX == 0x80);} + __forceinline bool IsOpaque(int amin, int amax) const {return (A == B || amax == 0) && D == 0 || A == 0 && B == D && amin == 0x80 && amax == 0x80;} +REG_END2 + +REG64_(GIFReg, BITBLTBUF) + u32 SBP:14; + u32 _PAD1:2; + u32 SBW:6; + u32 _PAD2:2; + u32 SPSM:6; + u32 _PAD3:2; + u32 DBP:14; + u32 _PAD4:2; + u32 DBW:6; + u32 _PAD5:2; + u32 DPSM:6; + u32 _PAD6:2; +REG_END + +REG64_(GIFReg, CLAMP) +union +{ + struct + { + u32 WMS:2; + u32 WMT:2; + u32 MINU:10; + u32 MAXU:10; + u32 _PAD1:8; + u32 _PAD2:2; + u32 MAXV:10; + u32 _PAD3:20; + }; + + struct + { + u64 _PAD4:24; + u64 MINV:10; + u64 _PAD5:30; + }; +}; +REG_END + +REG64_(GIFReg, COLCLAMP) + u32 CLAMP:1; + u32 _PAD1:31; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, DIMX) + s32 DM00:3; + s32 _PAD00:1; + s32 DM01:3; + s32 _PAD01:1; + s32 DM02:3; + s32 _PAD02:1; + s32 DM03:3; + s32 _PAD03:1; + s32 DM10:3; + s32 _PAD10:1; + s32 DM11:3; + s32 _PAD11:1; + s32 DM12:3; + s32 _PAD12:1; + s32 DM13:3; + s32 _PAD13:1; + s32 DM20:3; + s32 _PAD20:1; + s32 DM21:3; + s32 _PAD21:1; + s32 DM22:3; + s32 _PAD22:1; + s32 DM23:3; + s32 _PAD23:1; + s32 DM30:3; + s32 _PAD30:1; + s32 DM31:3; + s32 _PAD31:1; + s32 DM32:3; + s32 _PAD32:1; + s32 DM33:3; + s32 _PAD33:1; +REG_END + +REG64_(GIFReg, DTHE) + u32 DTHE:1; + u32 _PAD1:31; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, FBA) + u32 FBA:1; + u32 _PAD1:31; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, FINISH) + u32 _PAD1:32; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, FOG) + u32 _PAD1:32; + u32 _PAD2:24; + u32 F:8; +REG_END + +REG64_(GIFReg, FOGCOL) + u32 FCR:8; + u32 FCG:8; + u32 FCB:8; + u32 _PAD1:8; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, FRAME) + u32 FBP:9; + u32 _PAD1:7; + u32 FBW:6; + u32 _PAD2:2; + u32 PSM:6; + u32 _PAD3:2; + u32 FBMSK:32; +REG_END2 + u32 Block() const {return FBP << 5;} +REG_END2 + +REG64_(GIFReg, HWREG) + u32 DATA_LOWER:32; + u32 DATA_UPPER:32; +REG_END + +REG64_(GIFReg, LABEL) + u32 ID:32; + u32 IDMSK:32; +REG_END + +REG64_(GIFReg, MIPTBP1) + u64 TBP1:14; + u64 TBW1:6; + u64 TBP2:14; + u64 TBW2:6; + u64 TBP3:14; + u64 TBW3:6; + u64 _PAD:4; +REG_END + +REG64_(GIFReg, MIPTBP2) + u64 TBP4:14; + u64 TBW4:6; + u64 TBP5:14; + u64 TBW5:6; + u64 TBP6:14; + u64 TBW6:6; + u64 _PAD:4; +REG_END + +REG64_(GIFReg, NOP) + u32 _PAD1:32; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, PABE) + u32 PABE:1; + u32 _PAD1:31; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, PRIM) + u32 PRIM:3; + u32 IIP:1; + u32 TME:1; + u32 FGE:1; + u32 ABE:1; + u32 AA1:1; + u32 FST:1; + u32 CTXT:1; + u32 FIX:1; + u32 _PAD1:21; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, PRMODE) + u32 _PRIM:3; + u32 IIP:1; + u32 TME:1; + u32 FGE:1; + u32 ABE:1; + u32 AA1:1; + u32 FST:1; + u32 CTXT:1; + u32 FIX:1; + u32 _PAD2:21; + u32 _PAD3:32; +REG_END + +REG64_(GIFReg, PRMODECONT) + u32 AC:1; + u32 _PAD1:31; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, RGBAQ) + u32 R:8; + u32 G:8; + u32 B:8; + u32 A:8; + float Q; +REG_END + +REG64_(GIFReg, SCANMSK) + u32 MSK:2; + u32 _PAD1:30; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, SCISSOR) + u32 SCAX0:11; + u32 _PAD1:5; + u32 SCAX1:11; + u32 _PAD2:5; + u32 SCAY0:11; + u32 _PAD3:5; + u32 SCAY1:11; + u32 _PAD4:5; +REG_END + +REG64_(GIFReg, SIGNAL) + u32 ID:32; + u32 IDMSK:32; +REG_END + +REG64_(GIFReg, ST) + float S; + float T; +REG_END + +REG64_(GIFReg, TEST) + u32 ATE:1; + u32 ATST:3; + u32 AREF:8; + u32 AFAIL:2; + u32 DATE:1; + u32 DATM:1; + u32 ZTE:1; + u32 ZTST:2; + u32 _PAD1:13; + u32 _PAD2:32; +REG_END2 + __forceinline bool DoFirstPass() {return !ATE || ATST != ATST_NEVER;} // not all pixels fail automatically + __forceinline bool DoSecondPass() {return ATE && ATST != ATST_ALWAYS && AFAIL != AFAIL_KEEP;} // pixels may fail, write fb/z + __forceinline bool NoSecondPass() {return ATE && ATST != ATST_ALWAYS && AFAIL == AFAIL_KEEP;} // pixels may fail, no output +REG_END2 + +REG64_(GIFReg, TEX0) +union +{ + struct + { + u32 TBP0:14; + u32 TBW:6; + u32 PSM:6; + u32 TW:4; + u32 _PAD1:2; + u32 _PAD2:2; + u32 TCC:1; + u32 TFX:2; + u32 CBP:14; + u32 CPSM:4; + u32 CSM:1; + u32 CSA:5; + u32 CLD:3; + }; + + struct + { + u64 _PAD3:30; + u64 TH:4; + u64 _PAD4:30; + }; +}; +REG_END2 + __forceinline bool IsRepeating() {return (u32)((u32)1 << TW) > (u32)(TBW << (u32)6);} +REG_END2 + +REG64_(GIFReg, TEX1) + u32 LCM:1; + u32 _PAD1:1; + u32 MXL:3; + u32 MMAG:1; + u32 MMIN:3; + u32 MTBA:1; + u32 _PAD2:9; + u32 L:2; + u32 _PAD3:11; + s32 K:12; // 1:7:4 + u32 _PAD4:20; +REG_END2 + bool IsMinLinear() const {return (MMIN == 1) || (MMIN & 4);} + bool IsMagLinear() const {return MMAG;} +REG_END2 + +REG64_(GIFReg, TEX2) + u32 _PAD1:20; + u32 PSM:6; + u32 _PAD2:6; + u32 _PAD3:5; + u32 CBP:14; + u32 CPSM:4; + u32 CSM:1; + u32 CSA:5; + u32 CLD:3; +REG_END + +REG64_(GIFReg, TEXA) + u32 TA0:8; + u32 _PAD1:7; + u32 AEM:1; + u32 _PAD2:16; + u32 TA1:8; + u32 _PAD3:24; +REG_END + +REG64_(GIFReg, TEXCLUT) + u32 CBW:6; + u32 COU:6; + u32 COV:10; + u32 _PAD1:10; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, TEXFLUSH) + u32 _PAD1:32; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, TRXDIR) + u32 XDIR:2; + u32 _PAD1:30; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, TRXPOS) + u32 SSAX:11; + u32 _PAD1:5; + u32 SSAY:11; + u32 _PAD2:5; + u32 DSAX:11; + u32 _PAD3:5; + u32 DSAY:11; + u32 DIRY:1; + u32 DIRX:1; + u32 _PAD4:3; +REG_END + +REG64_(GIFReg, TRXREG) + u32 RRW:12; + u32 _PAD1:20; + u32 RRH:12; + u32 _PAD2:20; +REG_END + +REG64_(GIFReg, UV) + u32 U:14; + u32 _PAD1:2; + u32 V:14; + u32 _PAD2:2; + u32 _PAD3:32; +REG_END + +REG64_(GIFReg, XYOFFSET) + u32 OFX:16; + u32 _PAD1:16; + u32 OFY:16; + u32 _PAD2:16; +REG_END + +REG64_(GIFReg, XYZ) + u32 X:16; + u32 Y:16; + u32 Z:32; +REG_END + +REG64_(GIFReg, XYZF) + u32 X:16; + u32 Y:16; + u32 Z:24; + u32 F:8; +REG_END + +REG64_(GIFReg, ZBUF) + u32 ZBP:9; + u32 _PAD1:15; + // u32 PSM:4; + // u32 _PAD2:4; + u32 PSM:6; + u32 _PAD2:2; + u32 ZMSK:1; + u32 _PAD3:31; +REG_END2 + u32 Block() const {return ZBP << 5;} +REG_END2 + +REG64_SET(GIFReg) + GIFRegALPHA ALPHA; + GIFRegBITBLTBUF BITBLTBUF; + GIFRegCLAMP CLAMP; + GIFRegCOLCLAMP COLCLAMP; + GIFRegDIMX DIMX; + GIFRegDTHE DTHE; + GIFRegFBA FBA; + GIFRegFINISH FINISH; + GIFRegFOG FOG; + GIFRegFOGCOL FOGCOL; + GIFRegFRAME FRAME; + GIFRegHWREG HWREG; + GIFRegLABEL LABEL; + GIFRegMIPTBP1 MIPTBP1; + GIFRegMIPTBP2 MIPTBP2; + GIFRegNOP NOP; + GIFRegPABE PABE; + GIFRegPRIM PRIM; + GIFRegPRMODE PRMODE; + GIFRegPRMODECONT PRMODECONT; + GIFRegRGBAQ RGBAQ; + GIFRegSCANMSK SCANMSK; + GIFRegSCISSOR SCISSOR; + GIFRegSIGNAL SIGNAL; + GIFRegST ST; + GIFRegTEST TEST; + GIFRegTEX0 TEX0; + GIFRegTEX1 TEX1; + GIFRegTEX2 TEX2; + GIFRegTEXA TEXA; + GIFRegTEXCLUT TEXCLUT; + GIFRegTEXFLUSH TEXFLUSH; + GIFRegTRXDIR TRXDIR; + GIFRegTRXPOS TRXPOS; + GIFRegTRXREG TRXREG; + GIFRegUV UV; + GIFRegXYOFFSET XYOFFSET; + GIFRegXYZ XYZ; + GIFRegXYZF XYZF; + GIFRegZBUF ZBUF; +REG_SET_END + +// GIFPacked + +REG128_(GIFPacked, PRIM) + u32 PRIM:11; + u32 _PAD1:21; + u32 _PAD2:32; + u32 _PAD3:32; + u32 _PAD4:32; +REG_END + +REG128_(GIFPacked, RGBA) + u32 R:8; + u32 _PAD1:24; + u32 G:8; + u32 _PAD2:24; + u32 B:8; + u32 _PAD3:24; + u32 A:8; + u32 _PAD4:24; +REG_END + +REG128_(GIFPacked, STQ) + float S; + float T; + float Q; + u32 _PAD1:32; +REG_END + +REG128_(GIFPacked, UV) + u32 U:14; + u32 _PAD1:18; + u32 V:14; + u32 _PAD2:18; + u32 _PAD3:32; + u32 _PAD4:32; +REG_END + +REG128_(GIFPacked, XYZF2) + u32 X:16; + u32 _PAD1:16; + u32 Y:16; + u32 _PAD2:16; + u32 _PAD3:4; + u32 Z:24; + u32 _PAD4:4; + u32 _PAD5:4; + u32 F:8; + u32 _PAD6:3; + u32 ADC:1; + u32 _PAD7:16; +REG_END + +REG128_(GIFPacked, XYZ2) + u32 X:16; + u32 _PAD1:16; + u32 Y:16; + u32 _PAD2:16; + u32 Z:32; + u32 _PAD3:15; + u32 ADC:1; + u32 _PAD4:16; +REG_END + +REG128_(GIFPacked, FOG) + u32 _PAD1:32; + u32 _PAD2:32; + u32 _PAD3:32; + u32 _PAD4:4; + u32 F:8; + u32 _PAD5:20; +REG_END + +REG128_(GIFPacked, A_D) + u64 DATA:64; + u32 ADDR:8; // enum GIF_A_D_REG + u32 _PAD1:24; + u32 _PAD2:32; +REG_END + +REG128_(GIFPacked, NOP) + u32 _PAD1:32; + u32 _PAD2:32; + u32 _PAD3:32; + u32 _PAD4:32; +REG_END + +REG128_SET(GIFPackedReg) + GIFReg r; + GIFPackedPRIM PRIM; + GIFPackedRGBA RGBA; + GIFPackedSTQ STQ; + GIFPackedUV UV; + GIFPackedXYZF2 XYZF2; + GIFPackedXYZ2 XYZ2; + GIFPackedFOG FOG; + GIFPackedA_D A_D; + GIFPackedNOP NOP; +REG_SET_END + +REG64_(GSReg, BGCOLOR) + u32 R:8; + u32 G:8; + u32 B:8; + u32 _PAD1:8; + u32 _PAD2:32; +REG_END + +REG64_(GSReg, BUSDIR) + u32 DIR:1; + u32 _PAD1:31; + u32 _PAD2:32; +REG_END + +REG64_(GSReg, CSR) + u32 SIGNAL:1; + u32 FINISH:1; + u32 HSINT:1; + u32 VSINT:1; + u32 EDWINT:1; + u32 ZERO1:1; + u32 ZERO2:1; + u32 _PAD1:1; + u32 FLUSH:1; + u32 RESET:1; + u32 _PAD2:2; + u32 NFIELD:1; + u32 FIELD:1; + u32 FIFO:2; + u32 REV:8; + u32 ID:8; + u32 _PAD3:32; +REG_END + +REG64_(GSReg, DISPFB) // (-1/2) + u32 FBP:9; + u32 FBW:6; + u32 PSM:5; + u32 _PAD:12; + u32 DBX:11; + u32 DBY:11; + u32 _PAD2:10; +REG_END + +REG64_(GSReg, DISPLAY) // (-1/2) + u32 DX:12; + u32 DY:11; + u32 MAGH:4; + u32 MAGV:2; + u32 _PAD:3; + u32 DW:12; + u32 DH:11; + u32 _PAD2:9; +REG_END + +REG64_(GSReg, EXTBUF) + u32 EXBP:14; + u32 EXBW:6; + u32 FBIN:2; + u32 WFFMD:1; + u32 EMODA:2; + u32 EMODC:2; + u32 _PAD1:5; + u32 WDX:11; + u32 WDY:11; + u32 _PAD2:10; +REG_END + +REG64_(GSReg, EXTDATA) + u32 SX:12; + u32 SY:11; + u32 SMPH:4; + u32 SMPV:2; + u32 _PAD1:3; + u32 WW:12; + u32 WH:11; + u32 _PAD2:9; +REG_END + +REG64_(GSReg, EXTWRITE) + u32 WRITE; + u32 _PAD2:32; +REG_END + +REG64_(GSReg, IMR) + u32 _PAD1:8; + u32 SIGMSK:1; + u32 FINISHMSK:1; + u32 HSMSK:1; + u32 VSMSK:1; + u32 EDWMSK:1; + u32 _PAD2:19; + u32 _PAD3:32; +REG_END + +REG64_(GSReg, PMODE) + u32 EN1:1; + u32 EN2:1; + u32 CRTMD:3; + u32 MMOD:1; + u32 AMOD:1; + u32 SLBG:1; + u32 ALP:8; + u32 _PAD:16; + u32 _PAD1:32; +REG_END + +REG64_(GSReg, SIGLBLID) + u32 SIGID:32; + u32 LBLID:32; +REG_END + +REG64_(GSReg, SMODE1) + u32 RC:3; + u32 LC:7; + u32 T1248:2; + u32 SLCK:1; + u32 CMOD:2; + u32 EX:1; + u32 PRST:1; + u32 SINT:1; + u32 XPCK:1; + u32 PCK2:2; + u32 SPML:4; + u32 GCONT:1; + u32 PHS:1; + u32 PVS:1; + u32 PEHS:1; + u32 PEVS:1; + u32 CLKSEL:2; + u32 NVCK:1; + u32 SLCK2:1; + u32 VCKSEL:2; + u32 VHP:1; + u32 _PAD1:27; +REG_END + +REG64_(GSReg, SMODE2) + u32 INT:1; + u32 FFMD:1; + u32 DPMS:2; + u32 _PAD2:28; + u32 _PAD3:32; +REG_END + +REG64_(GSReg, SIGBLID) + u32 SIGID; + u32 LBLID; +REG_END + +#define PMODE ((GSRegPMODE*)(g_pBasePS2Mem+0x0000)) +#define SMODE1 ((GSRegSMODE1*)(g_pBasePS2Mem+0x0010)) +#define SMODE2 ((GSRegSMODE2*)(g_pBasePS2Mem+0x0020)) +// SRFSH +#define SYNCH1 ((GSRegSYNCH1*)(g_pBasePS2Mem+0x0040)) +#define SYNCH2 ((GSRegSYNCH2*)(g_pBasePS2Mem+0x0050)) +#define SYNCV ((GSRegSYNCV*)(g_pBasePS2Mem+0x0060)) +#define DISPFB1 ((GSRegDISPFB*)(g_pBasePS2Mem+0x0070)) +#define DISPLAY1 ((GSRegDISPLAY*)(g_pBasePS2Mem+0x0080)) +#define DISPFB2 ((GSRegDISPFB*)(g_pBasePS2Mem+0x0090)) +#define DISPLAY2 ((GSRegDISPLAY*)(g_pBasePS2Mem+0x00a0)) +#define EXTBUF ((GSRegEXTBUF*)(g_pBasePS2Mem+0x00b0)) +#define EXTDATA ((GSRegEXTDATA*)(g_pBasePS2Mem+0x00c0)) +#define EXTWRITE ((GSRegEXTWRITE*)(g_pBasePS2Mem+0x00d0)) +#define BGCOLOR ((GSRegBGCOLOR*)(g_pBasePS2Mem+0x00e0)) +#define CSR ((GSRegCSR*)(g_pBasePS2Mem+0x1000)) +#define IMR ((GSRegIMR*)(g_pBasePS2Mem+0x1010)) +#define BUSDIR ((GSRegBUSDIR*)(g_pBasePS2Mem+0x1040)) +#define SIGLBLID ((GSRegSIGBLID*)(g_pBasePS2Mem+0x1080)) + +// +// sps2tags.h +// +#define GET_GIF_REG(tag, reg) \ + (((tag).ai32[2 + ((reg) >> 3)] >> (((reg) & 7) << 2)) & 0xf) + +#define GET_GSFPS (((SMODE1->CMOD&1) ? 50 : 60) / (SMODE2->INT ? 1 : 2)) + +extern void WriteTempRegs(); +extern void SetFrameSkip(bool skip); +extern void ResetRegs(); + +extern void SetTexFlush(); +extern void SetFogColor(u32 fog); +extern void SetFogColor(GIFRegFOGCOL* fog); +extern bool CheckChangeInClut(u32 highdword, u32 psm); // returns true if clut will change after this tex0 op + +// flush current vertices, call before setting new registers (the main render method) +void Flush(int context); +void FlushBoth(); + +// called on a primitive switch +void Prim(); + +#endif + +#endif // NEWREGS_H_INCLUDED diff --git a/plugins/zzogl-pg-cg/opengl/Profile.cpp b/plugins/zzogl-pg-cg/opengl/Profile.cpp new file mode 100644 index 000000000..9e1bd81c3 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/Profile.cpp @@ -0,0 +1,266 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + + +//////////////////// +// Small profiler // +//////////////////// +#include +#include +#include +#include "Profile.h" +#include "Util.h" + +using namespace std; + +#define GET_PROFILE_TIME() GetCPUTicks() + +#if !defined(ZEROGS_DEVBUILD) +#define g_bWriteProfile 0 +#else +bool g_bWriteProfile = 0; +#endif + +u64 luPerfFreq; + +struct DVPROFSTRUCT; + +struct DVPROFSTRUCT +{ + + struct DATA + { + DATA(u64 time, u32 user = 0) : dwTime(time), dwUserData(user) {} + + DATA() : dwTime(0), dwUserData(0) {} + + u64 dwTime; + u32 dwUserData; + }; + + ~DVPROFSTRUCT() + { + list::iterator it = listpChild.begin(); + + while (it != listpChild.end()) + { + safe_delete(*it); + ++it; + } + } + + list listTimes; // before DVProfEnd is called, contains the global time it started + // after DVProfEnd is called, contains the time it lasted + // the list contains all the tracked times + char pname[256]; + + list listpChild; // other profilers called during this profiler period +}; + +struct DVPROFTRACK +{ + u32 dwUserData; + DVPROFSTRUCT::DATA* pdwTime; + DVPROFSTRUCT* pprof; +}; + +list g_listCurTracking; // the current profiling functions, the back element is the +// one that will first get popped off the list when DVProfEnd is called +// the pointer is an element in DVPROFSTRUCT::listTimes +list g_listProfilers; // the current profilers, note that these are the parents +// any profiler started during the time of another is held in +// DVPROFSTRUCT::listpChild +list g_listAllProfilers; // ignores the hierarchy, pointer to elements in g_listProfilers + +void DVProfRegister(char* pname) +{ + if (!g_bWriteProfile) return; + + list::iterator it = g_listAllProfilers.begin(); + +// while(it != g_listAllProfilers.end() ) { +// +// if( _tcscmp(pname, (*it)->pname) == 0 ) { +// (*it)->listTimes.push_back(timeGetTime()); +// DVPROFTRACK dvtrack; +// dvtrack.pdwTime = &(*it)->listTimes.back(); +// dvtrack.pprof = *it; +// g_listCurTracking.push_back(dvtrack); +// return; +// } +// +// ++it; +// } + + // else add in a new profiler to the appropriate parent profiler + DVPROFSTRUCT* pprof = NULL; + + if (g_listCurTracking.size() > 0) + { + assert(g_listCurTracking.back().pprof != NULL); + g_listCurTracking.back().pprof->listpChild.push_back(new DVPROFSTRUCT()); + pprof = g_listCurTracking.back().pprof->listpChild.back(); + } + else + { + g_listProfilers.push_back(DVPROFSTRUCT()); + pprof = &g_listProfilers.back(); + } + + strncpy(pprof->pname, pname, 256); + + // setup the profiler for tracking + pprof->listTimes.push_back(DVPROFSTRUCT::DATA(GET_PROFILE_TIME())); + + DVPROFTRACK dvtrack; + dvtrack.pdwTime = &pprof->listTimes.back(); + dvtrack.pprof = pprof; + dvtrack.dwUserData = 0; + + g_listCurTracking.push_back(dvtrack); + + // add to all profiler list + g_listAllProfilers.push_back(pprof); +} + +void DVProfEnd(u32 dwUserData) +{ + if (!g_bWriteProfile) + return; + + B_RETURN(g_listCurTracking.size() > 0); + + DVPROFTRACK dvtrack = g_listCurTracking.back(); + + assert(dvtrack.pdwTime != NULL && dvtrack.pprof != NULL); + + dvtrack.pdwTime->dwTime = 1000000 * (GET_PROFILE_TIME() - dvtrack.pdwTime->dwTime) / luPerfFreq; + + dvtrack.pdwTime->dwUserData = dwUserData; + + g_listCurTracking.pop_back(); +} + +struct DVTIMEINFO +{ + DVTIMEINFO() : uInclusive(0), uExclusive(0) {} + + u64 uInclusive, uExclusive; +}; + +map mapAggregateTimes; + +u64 DVProfWriteStruct(FILE* f, DVPROFSTRUCT* p, int ident) +{ + fprintf(f, "%*s%s - ", ident, "", p->pname); + + list::iterator ittime = p->listTimes.begin(); + + u64 utime = 0; + + while (ittime != p->listTimes.end()) + { + utime += (u32)ittime->dwTime; + + if (ittime->dwUserData) + fprintf(f, "time: %d, user: 0x%8.8x", (u32)ittime->dwTime, ittime->dwUserData); + else + fprintf(f, "time: %d", (u32)ittime->dwTime); + + ++ittime; + } + + mapAggregateTimes[p->pname].uInclusive += utime; + + fprintf(f, "\n"); + + list::iterator itprof = p->listpChild.begin(); + + u32 uex = utime; + + while (itprof != p->listpChild.end()) + { + + uex -= (u32)DVProfWriteStruct(f, *itprof, ident + 4); + ++itprof; + } + + mapAggregateTimes[p->pname].uExclusive += uex; + + return utime; +} + +void DVProfWrite(char* pfilename, u32 frames) +{ + assert(pfilename != NULL); + FILE* f = fopen(pfilename, "wb"); + + mapAggregateTimes.clear(); + list::iterator it = g_listProfilers.begin(); + + while (it != g_listProfilers.end()) + { + DVProfWriteStruct(f, &(*it), 0); + ++it; + } + + { + map::iterator it; + fprintf(f, "\n\n-------------------------------------------------------------------\n\n"); + + u64 uTotal[2] = {0}; + double fiTotalTime[2]; + + for (it = mapAggregateTimes.begin(); it != mapAggregateTimes.end(); ++it) + { + uTotal[0] += it->second.uExclusive; + uTotal[1] += it->second.uInclusive; + } + + fprintf(f, "total times (%d): ex: %Lu ", frames, uTotal[0] / frames); + + fprintf(f, "inc: %Lu\n", uTotal[1] / frames); + + fiTotalTime[0] = 1.0 / (double)uTotal[0]; + fiTotalTime[1] = 1.0 / (double)uTotal[1]; + + // output the combined times + + for (it = mapAggregateTimes.begin(); it != mapAggregateTimes.end(); ++it) + { + fprintf(f, "%s - ex: %f inc: %f\n", it->first.c_str(), (double)it->second.uExclusive * fiTotalTime[0], + (double)it->second.uInclusive * fiTotalTime[1]); + } + } + + + fclose(f); +} + +void DVProfClear() +{ + g_listCurTracking.clear(); + g_listProfilers.clear(); + g_listAllProfilers.clear(); +} + +void InitProfile() +{ + luPerfFreq = GetCPUTicks(); +} diff --git a/plugins/zzogl-pg-cg/opengl/Profile.h b/plugins/zzogl-pg-cg/opengl/Profile.h new file mode 100644 index 000000000..b6e17b7af --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/Profile.h @@ -0,0 +1,172 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef PROFILE_H_INCLUDED +#define PROFILE_H_INCLUDED + +#include "Util.h" + +#if !defined(ZEROGS_DEVBUILD) +#define g_bWriteProfile 0 +#else +extern bool g_bWriteProfile; +#endif + +extern u64 luPerfFreq; + + +// Copied from Utilities; remove later. +#ifdef __LINUX__ + +#include +#include // ftime(), struct timeb + +inline unsigned long timeGetTime() +{ + timeb t; + ftime(&t); + + return (unsigned long)(t.time*1000 + t.millitm); +} + +inline unsigned long timeGetPreciseTime() +{ + timespec t; + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t); + + return t.tv_nsec; +} + +static __forceinline void InitCPUTicks() +{ +} + +static __forceinline u64 GetTickFrequency() +{ + return 1000000; // unix measures in microseconds +} + +static __forceinline u64 GetCPUTicks() +{ + + struct timeval t; + gettimeofday(&t, NULL); + return ((u64)t.tv_sec*GetTickFrequency()) + t.tv_usec; +} + +#else +static __aligned16 LARGE_INTEGER lfreq; + +inline unsigned long timeGetPreciseTime() +{ + // Implement later. + return 0; +} + +static __forceinline void InitCPUTicks() +{ + QueryPerformanceFrequency(&lfreq); +} + +static __forceinline u64 GetTickFrequency() +{ + return lfreq.QuadPart; +} + +static __forceinline u64 GetCPUTicks() +{ + LARGE_INTEGER count; + QueryPerformanceCounter(&count); + return count.QuadPart; +} + +#endif + +// IMPORTANT: For every Register there must be an End +void DVProfRegister(char* pname); // first checks if this profiler exists in g_listProfilers +void DVProfEnd(u32 dwUserData); +void DVProfWrite(char* pfilename, u32 frames = 0); +void DVProfClear(); // clears all the profilers + +#define DVPROFILE +#ifdef DVPROFILE + +class DVProfileFunc +{ + public: + u32 dwUserData; + DVProfileFunc(char* pname) { DVProfRegister(pname); dwUserData = 0; } + DVProfileFunc(char* pname, u32 dwUserData) : dwUserData(dwUserData) { DVProfRegister(pname); } + ~DVProfileFunc() { DVProfEnd(dwUserData); } +}; + +#else + +class DVProfileFunc +{ + + public: + u32 dwUserData; + static __forceinline DVProfileFunc(char* pname) {} + static __forceinline DVProfileFunc(char* pname, u32 dwUserData) { } + ~DVProfileFunc() {} +}; + +#endif + + +template +class CInterfacePtr +{ + + public: + inline CInterfacePtr() : ptr(NULL) {} + inline explicit CInterfacePtr(T* newptr) : ptr(newptr) { if (ptr != NULL) ptr->AddRef(); } + inline ~CInterfacePtr() { if (ptr != NULL) ptr->Release(); } + inline T* operator*() { assert(ptr != NULL); return *ptr; } + inline T* operator->() { return ptr; } + inline T* get() { return ptr; } + + inline void release() + { + if (ptr != NULL) { ptr->Release(); ptr = NULL; } + } + + inline operator T*() { return ptr; } + inline bool operator==(T* rhs) { return ptr == rhs; } + inline bool operator!=(T* rhs) { return ptr != rhs; } + + inline CInterfacePtr& operator= (T* newptr) + { + if (ptr != NULL) ptr->Release(); + + ptr = newptr; + + if (ptr != NULL) ptr->AddRef(); + + return *this; + } + + private: + T* ptr; +}; + +extern void InitProfile(); + +#endif // PROFILE_H_INCLUDED diff --git a/plugins/zzogl-pg-cg/opengl/README.txt b/plugins/zzogl-pg-cg/opengl/README.txt new file mode 100644 index 000000000..447dfdf20 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/README.txt @@ -0,0 +1,13 @@ +ZeroGS OpenGL +------------- +author: zerofrog (@gmail.com) + +ZeroGS heavily uses GPU shaders. All the shaders are written in nVidia's Cg language and can be found in ps2hw.fx. + +'Dev' versions of ZeroGS directly read ps2hw.fx +'Release' versions of ZeroGS read a precompiled version of ps2hw.fx from ps2hw.dat. In order to build ps2hw.dat, compile ZeroGSShaders and execute: + +./ZeroGSShaders ps2hw.fx ps2hw.dat + +For Windows users, once ZeroGSShaders is built, run buildshaders.bat directly. It will update all necessary resource files. +Note that ZeroGSShaders has only been tested in Windows so far, but the Windows ps2hw.dat can be used in linux builds. \ No newline at end of file diff --git a/plugins/zzogl-pg-cg/opengl/Regs.cpp b/plugins/zzogl-pg-cg/opengl/Regs.cpp new file mode 100644 index 000000000..a033e7a64 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/Regs.cpp @@ -0,0 +1,1080 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "GS.h" +#include "Mem.h" +#include "Regs.h" +#include "PS2Etypes.h" + +#include "targets.h" +#include "ZZoglVB.h" +#include "ZZoglDrawing.h" + +#ifdef USE_OLD_REGS + +#ifdef _MSC_VER +#pragma warning(disable:4244) +#endif + +GIFRegHandler g_GIFPackedRegHandlers[16]; +GIFRegHandler g_GIFRegHandlers[256]; +GIFRegHandler g_GIFTempRegHandlers[16] = {0}; + +// values for keeping track of changes +u32 s_uTex1Data[2][2] = {{0, }}; +u32 s_uClampData[2] = {0, }; + +//u32 results[65535] = {0, }; + +// Note that not all the registers are currently handled, even if they write values out. +// For reference, I'm starting a list of unhandled flags here. I'm sure I missed some, +// so feel free to add to this, or remove ones that are handled that I missed. +// Cases where these values are set would be useful, too. +// +// In GIFRegHandlerFOG, I don't see gs.vertexregs.f being used anywhere afterwards. +// GIFRegHandlerTEX1 doesn't look like anything other then mmag and mmin are handled. +// This includes: +// lcm - the lod (level of detail) calculation method. If 0, it's (log2(1/|Q|)< +void __gifCall GIFPackedRegHandlerTEX0(const u32* data) { GIFRegHandlerTEX0(data); } + +template +void __gifCall GIFPackedRegHandlerCLAMP(const u32* data) { GIFRegHandlerCLAMP(data); } + +void __gifCall GIFPackedRegHandlerXYZF3(const u32* data) { GIFRegHandlerXYZF3(data); } +void __gifCall GIFPackedRegHandlerXYZ3(const u32* data) { GIFRegHandlerXYZ3(data); } + +void __gifCall GIFPackedRegHandlerRGBA(const u32* data) +{ + FUNCLOG + GIFPackedRGBA* r = (GIFPackedRGBA*)(data); + gs.rgba = (r->R | (r->G << 8) | (r->B << 16) | (r->A << 24)); + gs.vertexregs.rgba = gs.rgba; + gs.vertexregs.q = gs.q; +} + +void __gifCall GIFPackedRegHandlerSTQ(const u32* data) +{ + FUNCLOG +// GIFPackedSTQ* r = (GIFPackedSTQ*)(data); +// gs.vertexregs.s = r->S; +// gs.vertexregs.t = r->T; +// gs.q = r->Q; + // Despite this code generating a warning, it's correct. float -> float reduction. S and Y are missed mantissas. + *(u32*)&gs.vertexregs.s = data[0] & 0xffffff00; + *(u32*)&gs.vertexregs.t = data[1] & 0xffffff00; + *(u32*)&gs.q = data[2]; +} + +void __gifCall GIFPackedRegHandlerUV(const u32* data) +{ + FUNCLOG + GIFPackedUV* r = (GIFPackedUV*)(data); + + gs.vertexregs.u = r->U; + gs.vertexregs.v = r->V; +} + +void __gifCall GIFPackedRegHandlerXYZF2(const u32* data) +{ + FUNCLOG + GIFPackedXYZF2* r = (GIFPackedXYZF2*)(data); + gs.add_vertex(r->X, r->Y,r->Z, r->F); + + ZZKick->KickVertex(!!(r->ADC)); +} + +void __gifCall GIFPackedRegHandlerXYZ2(const u32* data) +{ + FUNCLOG + GIFPackedXYZ2* r = (GIFPackedXYZ2*)(data); + gs.add_vertex(r->X, r->Y,r->Z); + + ZZKick->KickVertex(!!(r->ADC)); +} + +void __gifCall GIFPackedRegHandlerFOG(const u32* data) +{ + FUNCLOG + GIFPackedFOG* r = (GIFPackedFOG*)(data); + gs.vertexregs.f = r->F; +// gs.vertexregs.f = (data[3] & 0xff0) >> 4; + if (gs.vertexregs.f != 0) REG_LOG("GIFPackedRegHandlerFOG == %d", gs.vertexregs.f); +} + +void __gifCall GIFPackedRegHandlerA_D(const u32* data) +{ + FUNCLOG + + if ((data[2] & 0xff) < 100) + g_GIFRegHandlers[data[2] & 0xff](data); + else + GIFRegHandlerNull(data); +} + +void __gifCall GIFPackedRegHandlerNOP(const u32* data) +{ + FUNCLOG +} + +void __gifCall GIFRegHandlerNull(const u32* data) +{ + FUNCLOG +#ifdef _DEBUG + + if ((((uptr)&data[2])&0xffff) == 0) return; + + // 0x7f happens on a lot of games + if (data[2] != 0x7f && (data[0] || data[1])) + { + ZZLog::Debug_Log("Unexpected reg handler %x %x %x.", data[0], data[1], data[2]); + } + +#endif +} + +void __gifCall GIFRegHandlerPRIM(const u32 *data) +{ + FUNCLOG + + //if (data[0] & ~0x3ff) + //{ + //ZZLog::Warn_Log("Warning: unknown bits in prim %8.8lx_%8.8lx", data[1], data[0]); + //} + + + gs.primC = 0; + u16 prim_type = (data[0]) & 0x7; + prim->prim = prim_type; + gs._prim[0].prim = prim_type; + gs._prim[1].prim = prim_type; + gs._prim[1]._val = (data[0] >> 3) & 0xff; + + gs.new_tri_fan = !(prim_type ^ PRIM_TRIANGLE_FAN); + ZZKick->DirtyValidPrevPrim(); + + Prim(); +} + +void __gifCall GIFRegHandlerRGBAQ(const u32* data) +{ + FUNCLOG + gs.rgba = data[0]; + gs.vertexregs.rgba = data[0]; + *(u32*)&gs.vertexregs.q = data[1]; +} + +void __gifCall GIFRegHandlerST(const u32* data) +{ + FUNCLOG + *(u32*)&gs.vertexregs.s = data[0] & 0xffffff00; + *(u32*)&gs.vertexregs.t = data[1] & 0xffffff00; + //*(u32*)&gs.q = data[2]; +} + +void __gifCall GIFRegHandlerUV(const u32* data) +{ + // Baroque breaks if u&v are 16 bits instead of 14. + FUNCLOG +// gs.vertexregs.u = (data[0]) & 0x3fff; +// gs.vertexregs.v = (data[0] >> 16) & 0x3fff; + GIFRegUV* r = (GIFRegUV*)(data); + gs.vertexregs.u = r->U; + gs.vertexregs.v = r->V; +} + +void __gifCall GIFRegHandlerXYZF2(const u32* data) +{ + FUNCLOG + GIFRegXYZF* r = (GIFRegXYZF*)(data); + gs.add_vertex(r->X, r->Y,r->Z, r->F); + + ZZKick->KickVertex(false); +} + +void __gifCall GIFRegHandlerXYZ2(const u32* data) +{ + FUNCLOG + GIFRegXYZ* r = (GIFRegXYZ*)(data); + gs.add_vertex(r->X, r->Y,r->Z); + + ZZKick->KickVertex(false); +} + +template +void __gifCall GIFRegHandlerTEX0(const u32* data) +{ + FUNCLOG + + if (!NoHighlights(ctxt)) return; + + u32 psm = ZZOglGet_psm_TexBitsFix(data[0]); + + if (m_Blocks[psm].bpp == 0) + { + // kh and others + return; + } + + vb[ctxt].uNextTex0Data[0] = data[0]; + vb[ctxt].uNextTex0Data[1] = data[1]; + vb[ctxt].bNeedTexCheck = 1; + + // don't update unless necessary + + if (PSMT_ISCLUT(psm)) + { + if (CheckChangeInClut(data[1], psm)) + { + // loading clut, so flush whole texture + vb[ctxt].FlushTexData(); + } + + // check if csa is the same!! (ffx bisaid island, grass) + else if ((data[1] & CPSM_CSA_BITMASK) != (vb[ctxt].uCurTex0Data[1] & CPSM_CSA_BITMASK)) + { + Flush(ctxt); // flush any previous entries + } + } +} + +template +void __gifCall GIFRegHandlerCLAMP(const u32* data) +{ + FUNCLOG + + if (!NoHighlights(ctxt)) return; + + clampInfo& clamp = vb[ctxt].clamp; + GIFRegCLAMP* r = (GIFRegCLAMP*)(data); + + if ((s_uClampData[ctxt] != data[0]) || (((clamp.minv >> 8) | (clamp.maxv << 2)) != (data[1]&0x0fff))) + { + Flush(ctxt); + s_uClampData[ctxt] = data[0]; + + clamp.wms = r->WMS; + clamp.wmt = r->WMT; + clamp.minu = r->MINU; + clamp.maxu = r->MAXU; + clamp.minv = r->MINV; + clamp.maxv = r->MAXV; + + vb[ctxt].bTexConstsSync = false; + } +} + +void __gifCall GIFRegHandlerFOG(const u32* data) +{ + FUNCLOG + //gs.gsvertex[gs.primIndex].f = (data[1] >> 24); // shift to upper bits + GIFRegFOG* r = (GIFRegFOG*)(data); + gs.vertexregs.f = r->F; + if (gs.vertexregs.f != 0) REG_LOG("GIFPackedRegHandlerFOG == %d", gs.vertexregs.f); + +} + +void __gifCall GIFRegHandlerXYZF3(const u32* data) +{ + FUNCLOG + GIFRegXYZF* r = (GIFRegXYZF*)(data); + gs.add_vertex(r->X, r->Y,r->Z, r->F); + + ZZKick->KickVertex(true); +} + +void __gifCall GIFRegHandlerXYZ3(const u32* data) +{ + FUNCLOG + GIFRegXYZ* r = (GIFRegXYZ*)(data); + gs.add_vertex(r->X, r->Y,r->Z); + + ZZKick->KickVertex(true); +} + +void __gifCall GIFRegHandlerNOP(const u32* data) +{ + FUNCLOG +} + +template +void __gifCall GIFRegHandlerTEX1(const u32* data) +{ + FUNCLOG + + if (!NoHighlights(ctxt)) return; + + GIFRegTEX1* r = (GIFRegTEX1*)(data); + tex1Info& tex1 = vb[ctxt].tex1; + + if (conf.bilinear == 1 && (tex1.mmag != ((data[0] >> 5) & 0x1) || tex1.mmin != ((data[0] >> 6) & 0x7))) + { + Flush(ctxt); + vb[ctxt].bVarsTexSync = false; + } + + tex1.lcm = r->LCM; + + tex1.mxl = r->MXL; + tex1.mmag = r->MMAG; + tex1.mmin = r->MMIN; + tex1.mtba = r->MTBA; + tex1.l = r->L; + tex1.k = r->K; + +#ifdef SPAM_UNUSED_REGISTERS + REG_LOG("Lcm = %d, l = %d, k = %d", tex1.lcm, tex1.l, tex1.k); + if (tex1.mxl != 0) REG_LOG("MIPMAP level set to %d, which is unsupported."); +#endif +} + +template +void __gifCall GIFRegHandlerTEX2(const u32* data) +{ + FUNCLOG + + tex0Info& tex0 = vb[ctxt].tex0; + + vb[ctxt].FlushTexData(); + + u32 psm = ZZOglGet_psm_TexBitsFix(data[0]); + + u32* s_uTex0Data = vb[ctxt].uCurTex0Data; + + // don't update unless necessary +// if( ZZOglGet_psm_TexBitsFix(*s_uTex0Data) == ZZOglGet_psm_TexBitsFix(data[0]) ) { // psm is the same + if (ZZOglAllExceptClutIsSame(s_uTex0Data, data)) + { + if (!PSMT_ISCLUT(psm)) return; + + // have to write the CLUT again if changed + if (ZZOglClutMinusCLDunchanged(s_uTex0Data, data)) + { + tex0.cld = ZZOglGet_cld_TexBits(data[1]); + + if (tex0.cld != 0) + { + texClutWrite(ctxt); + // invalidate to make sure target didn't change! + vb[ctxt].bVarsTexSync = false; + } + + return; + } + } + + Flush(ctxt); + + vb[ctxt].bVarsTexSync = false; + vb[ctxt].bTexConstsSync = false; + + s_uTex0Data[0] = (s_uTex0Data[0] & ~0x03f00000) | (psm << 20); + s_uTex0Data[1] = (s_uTex0Data[1] & 0x1f) | (data[1] & ~0x1f); + + tex0.psm = ZZOglGet_psm_TexBitsFix(data[0]); + + if (PSMT_ISCLUT(tex0.psm)) CluttingForFlushedTex(&tex0, data[1], ctxt); +} + +template +void __gifCall GIFRegHandlerXYOFFSET(const u32* data) +{ + FUNCLOG + GIFRegXYOFFSET* r = (GIFRegXYOFFSET*)(data); + vb[ctxt].offset.x = r->OFX; + vb[ctxt].offset.y = r->OFY; + +// if( !conf.interlace ) { +// vb[1].offset.x &= ~15; +// vb[1].offset.y &= ~15; +// } +} + +void __gifCall GIFRegHandlerPRMODECONT(const u32* data) +{ + FUNCLOG + gs.prac = data[0] & 0x1; + prim = &gs._prim[gs.prac]; + + Prim(); +} + +void __gifCall GIFRegHandlerPRMODE(const u32* data) +{ + FUNCLOG + gs._prim[0]._val = (data[0] >> 3) & 0xff; + + if (gs.prac == 0) Prim(); +} + +void __gifCall GIFRegHandlerTEXCLUT(const u32* data) +{ + FUNCLOG + // Affects background coloration of initial Mana Khemia dialog. + GIFRegTEXCLUT* r = (GIFRegTEXCLUT*)(data); + + vb[0].FlushTexData(); + vb[1].FlushTexData(); + + gs.clut.cbw = r->CBW << 6; + gs.clut.cou = r->COU << 4; + gs.clut.cov = r->COV; +} + +void __gifCall GIFRegHandlerSCANMSK(const u32* data) +{ + FUNCLOG + GIFRegSCANMSK* r = (GIFRegSCANMSK*)(data); +// FlushBoth(); +// ResolveC(&vb[0]); +// ResolveZ(&vb[0]); + + gs.smask = r->MSK; + REG_LOG("Scanmsk == %d", gs.smask); +} + +template +void __gifCall GIFRegHandlerMIPTBP1(const u32* data) +{ + FUNCLOG + GIFRegMIPTBP1* r = (GIFRegMIPTBP1*)(data); + + miptbpInfo& miptbp0 = vb[ctxt].miptbp0; + miptbp0.tbp[0] = r->TBP1; + miptbp0.tbw[0] = r->TBW1; + miptbp0.tbp[1] = r->TBP2; + miptbp0.tbw[1] = r->TBW2; + miptbp0.tbp[2] = r->TBP3; + miptbp0.tbw[2] = r->TBW3; + +#ifdef SPAM_UNUSED_REGISTERS + if ((miptbp0.tbp[0] != 0) || (miptbp0.tbp[1] != 0) || (miptbp0.tbp[2] != 0)) + { + REG_LOG("MIPTBP1: 0:%d(%d) 1:%d(%d) 2:%d(%d).", \ + miptbp0.tbp[0], miptbp0.tbw[0], miptbp0.tbp[1], miptbp0.tbw[1], miptbp0.tbp[2], miptbp0.tbw[2]); + } +#endif +} + +template +void __gifCall GIFRegHandlerMIPTBP2(const u32* data) +{ + FUNCLOG + GIFRegMIPTBP2* r = (GIFRegMIPTBP2*)(data); + + miptbpInfo& miptbp1 = vb[ctxt].miptbp1; + miptbp1.tbp[0] = r->TBP4; + miptbp1.tbw[0] = r->TBW4; + miptbp1.tbp[1] = r->TBP5; + miptbp1.tbw[1] = r->TBW5; + miptbp1.tbp[2] = r->TBP6; + miptbp1.tbw[2] = r->TBW6; + +#ifdef SPAM_UNUSED_REGISTERS + if ((miptbp1.tbp[0] != 0) || (miptbp1.tbp[1] != 0) || (miptbp1.tbp[2] != 0)) + { + REG_LOG("MIPTBP2: 0:%d(%d) 1:%d(%d) 2:%d(%d).", \ + miptbp1.tbp[0], miptbp1.tbw[0], miptbp1.tbp[1], miptbp1.tbw[1], miptbp1.tbp[2], miptbp1.tbw[2]); + } +#endif +} + +void __gifCall GIFRegHandlerTEXA(const u32* data) +{ + FUNCLOG + texaInfo newinfo; + newinfo.aem = (data[0] >> 15) & 0x1; + newinfo.ta[0] = data[0] & 0xff; + newinfo.ta[1] = data[1] & 0xff; + + if (*(u32*)&newinfo != *(u32*)&gs.texa) + { + FlushBoth(); + + *(u32*)&gs.texa = *(u32*) & newinfo; + + gs.texa.fta[0] = newinfo.ta[0] / 255.0f; + gs.texa.fta[1] = newinfo.ta[1] / 255.0f; + + vb[0].bTexConstsSync = false; + vb[1].bTexConstsSync = false; + } +} + +void __gifCall GIFRegHandlerFOGCOL(const u32* data) +{ + FUNCLOG + GIFRegFOGCOL* r = (GIFRegFOGCOL*)(data); + SetFogColor(r); + gs.fogcol = r->ai32[0]; +} + +void __gifCall GIFRegHandlerTEXFLUSH(const u32* data) +{ + FUNCLOG + SetTexFlush(); +} + +template +void __gifCall GIFRegHandlerSCISSOR(const u32* data) +{ + FUNCLOG + GIFRegSCISSOR* r = (GIFRegSCISSOR*)(data); + + Rect2& scissor = vb[ctxt].scissor; + Rect2 newscissor; + + newscissor.x0 = r->SCAX0 << 3; + newscissor.x1 = r->SCAX1 << 3; + newscissor.y0 = r->SCAY0 << 3; + newscissor.y1 = r->SCAY1 << 3; + + if (newscissor.x1 != scissor.x1 || newscissor.y1 != scissor.y1 || + newscissor.x0 != scissor.x0 || newscissor.y0 != scissor.y0) + { + Flush(ctxt); + scissor = newscissor; + + // flush everything + vb[ctxt].bNeedFrameCheck = 1; + } +} + +template +void __gifCall GIFRegHandlerALPHA(const u32* data) +{ + FUNCLOG + alphaInfo newalpha; + newalpha.abcd = *(u8*)data; + newalpha.fix = *(u8*)(data + 1); + + if (*(u16*)&newalpha != *(u16*)&vb[ctxt].alpha) + { + Flush(ctxt); + + if (newalpha.a == 3) newalpha.a = 0; + if (newalpha.b == 3) newalpha.b = 0; + if (newalpha.c == 3) newalpha.c = 0; + if (newalpha.d == 3) newalpha.d = 0; + + *(u16*)&vb[ctxt].alpha = *(u16*) & newalpha; + } +} + +void __gifCall GIFRegHandlerDIMX(const u32* data) +{ + FUNCLOG + GIFRegDIMX* r = (GIFRegDIMX*)(data); + + gs.dimx.i64 = r->i64; +} + +void __gifCall GIFRegHandlerDTHE(const u32* data) +{ + FUNCLOG + GIFRegDTHE* r = (GIFRegDTHE*)(data); + + gs.dthe = r->DTHE; + if (gs.dthe != 0) REG_LOG("Dithering set. (but not implemented.)"); +} + +void __gifCall GIFRegHandlerCOLCLAMP(const u32* data) +{ + FUNCLOG + GIFRegCOLCLAMP* r = (GIFRegCOLCLAMP*)(data); + + gs.colclamp = r->CLAMP; + + if (gs.colclamp == 0) + REG_LOG("COLCLAMP == MASK"); + else + REG_LOG("COLCLAMP == CLAMP"); +} + +template +void __gifCall GIFRegHandlerTEST(const u32* data) +{ + FUNCLOG + + pixTest* test = &vb[ctxt].test; + + if ((*(u32*)test & 0x0007ffff) == (data[0] & 0x0007ffff)) return; + + Flush(ctxt); + + *(u32*)test = data[0]; + +// test.ate = (data[0] ) & 0x1; +// test.atst = (data[0] >> 1) & 0x7; +// test.aref = (data[0] >> 4) & 0xff; +// test.afail = (data[0] >> 12) & 0x3; +// test.date = (data[0] >> 14) & 0x1; +// test.datm = (data[0] >> 15) & 0x1; +// test.zte = (data[0] >> 16) & 0x1; +// test.ztst = (data[0] >> 17) & 0x3; +} + +void __gifCall GIFRegHandlerPABE(const u32* data) +{ + FUNCLOG + GIFRegPABE* r = (GIFRegPABE*)(data); + //SetAlphaChanged(0, GPUREG_PABE); + //SetAlphaChanged(1, GPUREG_PABE); + FlushBoth(); + + gs.pabe = r->PABE; +} + +template +void __gifCall GIFRegHandlerFBA(const u32* data) +{ + FUNCLOG + GIFRegFBA* r = (GIFRegFBA*)(data); + + FlushBoth(); + + vb[ctxt].fba.fba = r->FBA; +} + +template +void __gifCall GIFRegHandlerFRAME(const u32* data) +{ + FUNCLOG + + frameInfo& gsfb = vb[ctxt].gsfb; + + if ((gsfb.fbp == ZZOglGet_fbp_FrameBitsMult(data[0])) && + (gsfb.fbw == ZZOglGet_fbw_FrameBitsMult(data[0])) && + (gsfb.psm == ZZOglGet_psm_FrameBits(data[0])) && + (gsfb.fbm == ZZOglGet_fbm_FrameBits(data[0]))) + { + return; + } + + FlushBoth(); + + gsfb.fbp = ZZOglGet_fbp_FrameBitsMult(data[0]); + gsfb.fbw = ZZOglGet_fbw_FrameBitsMult(data[0]); + gsfb.psm = ZZOglGet_psm_FrameBits(data[0]); + gsfb.fbm = ZZOglGet_fbm_FrameBitsFix(data[0], data[1]); + gsfb.fbh = ZZOglGet_fbh_FrameBitsCalc(data[0]); +// gsfb.fbhCalc = gsfb.fbh; + + vb[ctxt].bNeedFrameCheck = 1; +} + +template +void __gifCall GIFRegHandlerZBUF(const u32* data) +{ + FUNCLOG + zbufInfo& zbuf = vb[ctxt].zbuf; + + int psm = (0x30 | ((data[0] >> 24) & 0xf)); + + if (zbuf.zbp == (data[0] & 0x1ff) * 32 && + zbuf.psm == psm && + zbuf.zmsk == (data[1] & 0x1)) + { + return; + } + + // error detection + if (m_Blocks[psm].bpp == 0) return; + + FlushBoth(); + + zbuf.zbp = (data[0] & 0x1ff) * 32; + zbuf.psm = 0x30 | ((data[0] >> 24) & 0xf); + zbuf.zmsk = data[1] & 0x1; + + vb[ctxt].bNeedZCheck = 1; + vb[ctxt].zprimmask = 0xffffffff; + + if (zbuf.psm > 0x31) vb[ctxt].zprimmask = 0xffff; +} + +void __gifCall GIFRegHandlerBITBLTBUF(const u32* data) +{ + FUNCLOG + GIFRegBITBLTBUF* r = (GIFRegBITBLTBUF*)(data); + + gs.srcbufnew.bp = r->SBP; + gs.srcbufnew.bw = r->SBW << 6; + gs.srcbufnew.psm = r->SPSM; + gs.dstbufnew.bp = r->DBP; + gs.dstbufnew.bw = r->DBW << 6; + gs.dstbufnew.psm = r->DPSM; + + if (gs.dstbufnew.bw == 0) gs.dstbufnew.bw = 64; +} + +void __gifCall GIFRegHandlerTRXPOS(const u32* data) +{ + FUNCLOG + GIFRegTRXPOS* r = (GIFRegTRXPOS*)(data); + + gs.trxposnew.sx = r->SSAX; + gs.trxposnew.sy = r->SSAY; + gs.trxposnew.dx = r->DSAX; + gs.trxposnew.dy = r->DSAY; + gs.trxposnew.dirx = r->DIRX; + gs.trxposnew.diry = r->DIRY; +} + +void __gifCall GIFRegHandlerTRXREG(const u32* data) +{ + FUNCLOG + GIFRegTRXREG* r = (GIFRegTRXREG*)(data); + gs.imageWtemp = r->RRW; + gs.imageHtemp = r->RRH; +} + +void __gifCall GIFRegHandlerTRXDIR(const u32* data) +{ + FUNCLOG + // terminate any previous transfers + + switch (gs.imageTransfer) + { + + case 0: // host->loc + TerminateHostLocal(); + break; + + case 1: // loc->host + TerminateLocalHost(); + break; + } + + gs.srcbuf = gs.srcbufnew; + + gs.dstbuf = gs.dstbufnew; + gs.trxpos = gs.trxposnew; + gs.imageTransfer = data[0] & 0x3; + gs.imageWnew = gs.imageWtemp; + gs.imageHnew = gs.imageHtemp; + + if (gs.imageWnew > 0 && gs.imageHnew > 0) + { + switch (gs.imageTransfer) + { + case 0: // host->loc + InitTransferHostLocal(); + break; + + case 1: // loc->host + InitTransferLocalHost(); + break; + + case 2: + TransferLocalLocal(); + break; + + case 3: + gs.imageTransfer = -1; + break; + + default: + assert(0); + } + } + else + { +#if defined(ZEROGS_DEVBUILD) + ZZLog::Warn_Log("Dummy transfer."); +#endif + gs.imageTransfer = -1; + } +} + +void __gifCall GIFRegHandlerHWREG(const u32* data) +{ + FUNCLOG + + if (gs.imageTransfer == 0) + { + TransferHostLocal(data, 2); + } + else + { +#if defined(ZEROGS_DEVBUILD) + ZZLog::Error_Log("ZeroGS: HWREG!? %8.8x_%8.8x", data[0], data[1]); + //assert(0); +#endif + } +} + +extern int g_GSMultiThreaded; + +void __gifCall GIFRegHandlerSIGNAL(const u32* data) +{ + FUNCLOG + + if (!g_GSMultiThreaded) + { + SIGLBLID->SIGID = (SIGLBLID->SIGID & ~data[1]) | (data[0] & data[1]); + +// if (gs.CSRw & 0x1) CSR->SIGNAL = 1; +// if (!IMR->SIGMSK && GSirq) +// GSirq(); + + if (gs.CSRw & 0x1) + { + CSR->SIGNAL = 1; + //gs.CSRw &= ~1; + } + + if (!IMR->SIGMSK && GSirq) GSirq(); + } +} + +void __gifCall GIFRegHandlerFINISH(const u32* data) +{ + FUNCLOG + + if (!g_GSMultiThreaded) + { + if (gs.CSRw & 0x2) CSR->FINISH = 1; + + if (!IMR->FINISHMSK && GSirq) GSirq(); + +// if( gs.CSRw & 2 ) { +// //gs.CSRw &= ~2; +// //CSR->FINISH = 0; +// +// +// } +// CSR->FINISH = 1; +// +// if( !IMR->FINISHMSK && GSirq ) +// GSirq(); + } +} + +void __gifCall GIFRegHandlerLABEL(const u32* data) +{ + FUNCLOG + + if (!g_GSMultiThreaded) + { + SIGLBLID->LBLID = (SIGLBLID->LBLID & ~data[1]) | (data[0] & data[1]); + } +} + + +void SetMultithreaded() +{ + // Some older versions of PCSX2 didn't properly set the irq callback to NULL + // in multithreaded mode (possibly because ZeroGS itself would assert in such + // cases), and didn't bind them to a dummy callback either. PCSX2 handles all + // IRQs internally when multithreaded anyway -- so let's ignore them here: + + if (g_GSMultiThreaded) + { + g_GIFRegHandlers[GIF_A_D_REG_SIGNAL] = &GIFRegHandlerNull; + g_GIFRegHandlers[GIF_A_D_REG_FINISH] = &GIFRegHandlerNull; + g_GIFRegHandlers[GIF_A_D_REG_LABEL] = &GIFRegHandlerNull; + } + else + { + g_GIFRegHandlers[GIF_A_D_REG_SIGNAL] = &GIFRegHandlerSIGNAL; + g_GIFRegHandlers[GIF_A_D_REG_FINISH] = &GIFRegHandlerFINISH; + g_GIFRegHandlers[GIF_A_D_REG_LABEL] = &GIFRegHandlerLABEL; + } +} + +void ResetRegs() +{ + for (int i = 0; i < 16; i++) + { + g_GIFPackedRegHandlers[i] = &GIFPackedRegHandlerNull; + } + + g_GIFPackedRegHandlers[GIF_REG_PRIM] = &GIFPackedRegHandlerPRIM; + g_GIFPackedRegHandlers[GIF_REG_RGBA] = &GIFPackedRegHandlerRGBA; + g_GIFPackedRegHandlers[GIF_REG_STQ] = &GIFPackedRegHandlerSTQ; + g_GIFPackedRegHandlers[GIF_REG_UV] = &GIFPackedRegHandlerUV; + g_GIFPackedRegHandlers[GIF_REG_XYZF2] = &GIFPackedRegHandlerXYZF2; + g_GIFPackedRegHandlers[GIF_REG_XYZ2] = &GIFPackedRegHandlerXYZ2; + g_GIFPackedRegHandlers[GIF_REG_TEX0_1] = &GIFPackedRegHandlerTEX0<0>; + g_GIFPackedRegHandlers[GIF_REG_TEX0_2] = &GIFPackedRegHandlerTEX0<1>; + g_GIFPackedRegHandlers[GIF_REG_CLAMP_1] = &GIFPackedRegHandlerCLAMP<0>; + g_GIFPackedRegHandlers[GIF_REG_CLAMP_2] = &GIFPackedRegHandlerCLAMP<1>; + g_GIFPackedRegHandlers[GIF_REG_FOG] = &GIFPackedRegHandlerFOG; + g_GIFPackedRegHandlers[GIF_REG_XYZF3] = &GIFPackedRegHandlerXYZF3; + g_GIFPackedRegHandlers[GIF_REG_XYZ3] = &GIFPackedRegHandlerXYZ3; + g_GIFPackedRegHandlers[GIF_REG_A_D] = &GIFPackedRegHandlerA_D; + g_GIFPackedRegHandlers[GIF_REG_NOP] = &GIFPackedRegHandlerNOP; + + for (int i = 0; i < 256; i++) + { + g_GIFRegHandlers[i] = &GIFPackedRegHandlerNull; + } + + g_GIFRegHandlers[GIF_A_D_REG_PRIM] = &GIFRegHandlerPRIM; + g_GIFRegHandlers[GIF_A_D_REG_RGBAQ] = &GIFRegHandlerRGBAQ; + g_GIFRegHandlers[GIF_A_D_REG_ST] = &GIFRegHandlerST; + g_GIFRegHandlers[GIF_A_D_REG_UV] = &GIFRegHandlerUV; + g_GIFRegHandlers[GIF_A_D_REG_XYZF2] = &GIFRegHandlerXYZF2; + g_GIFRegHandlers[GIF_A_D_REG_XYZ2] = &GIFRegHandlerXYZ2; + g_GIFRegHandlers[GIF_A_D_REG_TEX0_1] = &GIFRegHandlerTEX0<0>; + g_GIFRegHandlers[GIF_A_D_REG_TEX0_2] = &GIFRegHandlerTEX0<1>; + g_GIFRegHandlers[GIF_A_D_REG_CLAMP_1] = &GIFRegHandlerCLAMP<0>; + g_GIFRegHandlers[GIF_A_D_REG_CLAMP_2] = &GIFRegHandlerCLAMP<1>; + g_GIFRegHandlers[GIF_A_D_REG_FOG] = &GIFRegHandlerFOG; + g_GIFRegHandlers[GIF_A_D_REG_XYZF3] = &GIFRegHandlerXYZF3; + g_GIFRegHandlers[GIF_A_D_REG_XYZ3] = &GIFRegHandlerXYZ3; + g_GIFRegHandlers[GIF_A_D_REG_NOP] = &GIFRegHandlerNOP; + g_GIFRegHandlers[GIF_A_D_REG_TEX1_1] = &GIFRegHandlerTEX1<0>; + g_GIFRegHandlers[GIF_A_D_REG_TEX1_2] = &GIFRegHandlerTEX1<1>; + g_GIFRegHandlers[GIF_A_D_REG_TEX2_1] = &GIFRegHandlerTEX2<0>; + g_GIFRegHandlers[GIF_A_D_REG_TEX2_2] = &GIFRegHandlerTEX2<1>; + g_GIFRegHandlers[GIF_A_D_REG_XYOFFSET_1] = &GIFRegHandlerXYOFFSET<0>; + g_GIFRegHandlers[GIF_A_D_REG_XYOFFSET_2] = &GIFRegHandlerXYOFFSET<1>; + g_GIFRegHandlers[GIF_A_D_REG_PRMODECONT] = &GIFRegHandlerPRMODECONT; + g_GIFRegHandlers[GIF_A_D_REG_PRMODE] = &GIFRegHandlerPRMODE; + g_GIFRegHandlers[GIF_A_D_REG_TEXCLUT] = &GIFRegHandlerTEXCLUT; + g_GIFRegHandlers[GIF_A_D_REG_SCANMSK] = &GIFRegHandlerSCANMSK; + g_GIFRegHandlers[GIF_A_D_REG_MIPTBP1_1] = &GIFRegHandlerMIPTBP1<0>; + g_GIFRegHandlers[GIF_A_D_REG_MIPTBP1_2] = &GIFRegHandlerMIPTBP1<1>; + g_GIFRegHandlers[GIF_A_D_REG_MIPTBP2_1] = &GIFRegHandlerMIPTBP2<0>; + g_GIFRegHandlers[GIF_A_D_REG_MIPTBP2_2] = &GIFRegHandlerMIPTBP2<1>; + g_GIFRegHandlers[GIF_A_D_REG_TEXA] = &GIFRegHandlerTEXA; + g_GIFRegHandlers[GIF_A_D_REG_FOGCOL] = &GIFRegHandlerFOGCOL; + g_GIFRegHandlers[GIF_A_D_REG_TEXFLUSH] = &GIFRegHandlerTEXFLUSH; + g_GIFRegHandlers[GIF_A_D_REG_SCISSOR_1] = &GIFRegHandlerSCISSOR<0>; + g_GIFRegHandlers[GIF_A_D_REG_SCISSOR_2] = &GIFRegHandlerSCISSOR<1>; + g_GIFRegHandlers[GIF_A_D_REG_ALPHA_1] = &GIFRegHandlerALPHA<0>; + g_GIFRegHandlers[GIF_A_D_REG_ALPHA_2] = &GIFRegHandlerALPHA<1>; + g_GIFRegHandlers[GIF_A_D_REG_DIMX] = &GIFRegHandlerDIMX; + g_GIFRegHandlers[GIF_A_D_REG_DTHE] = &GIFRegHandlerDTHE; + g_GIFRegHandlers[GIF_A_D_REG_COLCLAMP] = &GIFRegHandlerCOLCLAMP; + g_GIFRegHandlers[GIF_A_D_REG_TEST_1] = &GIFRegHandlerTEST<0>; + g_GIFRegHandlers[GIF_A_D_REG_TEST_2] = &GIFRegHandlerTEST<1>; + g_GIFRegHandlers[GIF_A_D_REG_PABE] = &GIFRegHandlerPABE; + g_GIFRegHandlers[GIF_A_D_REG_FBA_1] = &GIFRegHandlerFBA<0>; + g_GIFRegHandlers[GIF_A_D_REG_FBA_2] = &GIFRegHandlerFBA<1>; + g_GIFRegHandlers[GIF_A_D_REG_FRAME_1] = &GIFRegHandlerFRAME<0>; + g_GIFRegHandlers[GIF_A_D_REG_FRAME_2] = &GIFRegHandlerFRAME<1>; + g_GIFRegHandlers[GIF_A_D_REG_ZBUF_1] = &GIFRegHandlerZBUF<0>; + g_GIFRegHandlers[GIF_A_D_REG_ZBUF_2] = &GIFRegHandlerZBUF<1>; + g_GIFRegHandlers[GIF_A_D_REG_BITBLTBUF] = &GIFRegHandlerBITBLTBUF; + g_GIFRegHandlers[GIF_A_D_REG_TRXPOS] = &GIFRegHandlerTRXPOS; + g_GIFRegHandlers[GIF_A_D_REG_TRXREG] = &GIFRegHandlerTRXREG; + g_GIFRegHandlers[GIF_A_D_REG_TRXDIR] = &GIFRegHandlerTRXDIR; + g_GIFRegHandlers[GIF_A_D_REG_HWREG] = &GIFRegHandlerHWREG; + SetMultithreaded(); +} + +void WriteTempRegs() +{ + memcpy(g_GIFTempRegHandlers, g_GIFPackedRegHandlers, sizeof(g_GIFTempRegHandlers)); +} + +void SetFrameSkip(bool skip) +{ + if (skip) + { + g_GIFPackedRegHandlers[GIF_REG_PRIM] = &GIFPackedRegHandlerNOP; + g_GIFPackedRegHandlers[GIF_REG_RGBA] = &GIFPackedRegHandlerNOP; + g_GIFPackedRegHandlers[GIF_REG_STQ] = &GIFPackedRegHandlerNOP; + g_GIFPackedRegHandlers[GIF_REG_UV] = &GIFPackedRegHandlerNOP; + g_GIFPackedRegHandlers[GIF_REG_XYZF2] = &GIFPackedRegHandlerNOP; + g_GIFPackedRegHandlers[GIF_REG_XYZ2] = &GIFPackedRegHandlerNOP; + g_GIFPackedRegHandlers[GIF_REG_CLAMP_1] = &GIFPackedRegHandlerNOP; + g_GIFPackedRegHandlers[GIF_REG_CLAMP_2] = &GIFPackedRegHandlerNOP; + g_GIFPackedRegHandlers[GIF_REG_FOG] = &GIFPackedRegHandlerNOP; + g_GIFPackedRegHandlers[GIF_REG_XYZF3] = &GIFPackedRegHandlerNOP; + g_GIFPackedRegHandlers[GIF_REG_XYZ3] = &GIFPackedRegHandlerNOP; + + g_GIFRegHandlers[GIF_A_D_REG_PRIM] = &GIFRegHandlerNOP; + g_GIFRegHandlers[GIF_A_D_REG_RGBAQ] = &GIFRegHandlerNOP; + g_GIFRegHandlers[GIF_A_D_REG_ST] = &GIFRegHandlerNOP; + g_GIFRegHandlers[GIF_A_D_REG_UV] = &GIFRegHandlerNOP; + g_GIFRegHandlers[GIF_A_D_REG_XYZF2] = &GIFRegHandlerNOP; + g_GIFRegHandlers[GIF_A_D_REG_XYZ2] = &GIFRegHandlerNOP; + g_GIFRegHandlers[GIF_A_D_REG_XYZF3] = &GIFRegHandlerNOP; + g_GIFRegHandlers[GIF_A_D_REG_XYZ3] = &GIFRegHandlerNOP; + g_GIFRegHandlers[GIF_A_D_REG_PRMODECONT] = &GIFRegHandlerNOP; + g_GIFRegHandlers[GIF_A_D_REG_PRMODE] = &GIFRegHandlerNOP; + } + else + { + g_GIFPackedRegHandlers[GIF_REG_PRIM] = &GIFPackedRegHandlerPRIM; + g_GIFPackedRegHandlers[GIF_REG_RGBA] = &GIFPackedRegHandlerRGBA; + g_GIFPackedRegHandlers[GIF_REG_STQ] = &GIFPackedRegHandlerSTQ; + g_GIFPackedRegHandlers[GIF_REG_UV] = &GIFPackedRegHandlerUV; + g_GIFPackedRegHandlers[GIF_REG_XYZF2] = &GIFPackedRegHandlerXYZF2; + g_GIFPackedRegHandlers[GIF_REG_XYZ2] = &GIFPackedRegHandlerXYZ2; + g_GIFPackedRegHandlers[GIF_REG_CLAMP_1] = &GIFPackedRegHandlerCLAMP<0>; + g_GIFPackedRegHandlers[GIF_REG_CLAMP_2] = &GIFPackedRegHandlerCLAMP<1>; + g_GIFPackedRegHandlers[GIF_REG_FOG] = &GIFPackedRegHandlerFOG; + g_GIFPackedRegHandlers[GIF_REG_XYZF3] = &GIFPackedRegHandlerXYZF3; + g_GIFPackedRegHandlers[GIF_REG_XYZ3] = &GIFPackedRegHandlerXYZ3; + + g_GIFRegHandlers[GIF_A_D_REG_PRIM] = &GIFRegHandlerPRIM; + g_GIFRegHandlers[GIF_A_D_REG_RGBAQ] = &GIFRegHandlerRGBAQ; + g_GIFRegHandlers[GIF_A_D_REG_ST] = &GIFRegHandlerST; + g_GIFRegHandlers[GIF_A_D_REG_UV] = &GIFRegHandlerUV; + g_GIFRegHandlers[GIF_A_D_REG_XYZF2] = &GIFRegHandlerXYZF2; + g_GIFRegHandlers[GIF_A_D_REG_XYZ2] = &GIFRegHandlerXYZ2; + g_GIFRegHandlers[GIF_A_D_REG_XYZF3] = &GIFRegHandlerXYZF3; + g_GIFRegHandlers[GIF_A_D_REG_XYZ3] = &GIFRegHandlerXYZ3; + g_GIFRegHandlers[GIF_A_D_REG_PRMODECONT] = &GIFRegHandlerPRMODECONT; + g_GIFRegHandlers[GIF_A_D_REG_PRMODE] = &GIFRegHandlerPRMODE; + } +} + +#endif diff --git a/plugins/zzogl-pg-cg/opengl/Regs.h b/plugins/zzogl-pg-cg/opengl/Regs.h new file mode 100644 index 000000000..59608d396 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/Regs.h @@ -0,0 +1,964 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __GSREGS_H__ +#define __GSREGS_H__ + + +#ifdef USE_OLD_REGS + +enum GIF_REG +{ + GIF_REG_PRIM = 0x00, + GIF_REG_RGBA = 0x01, + GIF_REG_STQ = 0x02, + GIF_REG_UV = 0x03, + GIF_REG_XYZF2 = 0x04, + GIF_REG_XYZ2 = 0x05, + GIF_REG_TEX0_1 = 0x06, + GIF_REG_TEX0_2 = 0x07, + GIF_REG_CLAMP_1 = 0x08, + GIF_REG_CLAMP_2 = 0x09, + GIF_REG_FOG = 0x0a, + GIF_REG_XYZF3 = 0x0c, + GIF_REG_XYZ3 = 0x0d, + GIF_REG_A_D = 0x0e, + GIF_REG_NOP = 0x0f, +}; + +enum GIF_A_D_REG +{ + GIF_A_D_REG_PRIM = 0x00, + GIF_A_D_REG_RGBAQ = 0x01, + GIF_A_D_REG_ST = 0x02, + GIF_A_D_REG_UV = 0x03, + GIF_A_D_REG_XYZF2 = 0x04, + GIF_A_D_REG_XYZ2 = 0x05, + GIF_A_D_REG_TEX0_1 = 0x06, + GIF_A_D_REG_TEX0_2 = 0x07, + GIF_A_D_REG_CLAMP_1 = 0x08, + GIF_A_D_REG_CLAMP_2 = 0x09, + GIF_A_D_REG_FOG = 0x0a, + GIF_A_D_REG_XYZF3 = 0x0c, + GIF_A_D_REG_XYZ3 = 0x0d, + GIF_A_D_REG_NOP = 0x0f, + GIF_A_D_REG_TEX1_1 = 0x14, + GIF_A_D_REG_TEX1_2 = 0x15, + GIF_A_D_REG_TEX2_1 = 0x16, + GIF_A_D_REG_TEX2_2 = 0x17, + GIF_A_D_REG_XYOFFSET_1 = 0x18, + GIF_A_D_REG_XYOFFSET_2 = 0x19, + GIF_A_D_REG_PRMODECONT = 0x1a, + GIF_A_D_REG_PRMODE = 0x1b, + GIF_A_D_REG_TEXCLUT = 0x1c, + GIF_A_D_REG_SCANMSK = 0x22, + GIF_A_D_REG_MIPTBP1_1 = 0x34, + GIF_A_D_REG_MIPTBP1_2 = 0x35, + GIF_A_D_REG_MIPTBP2_1 = 0x36, + GIF_A_D_REG_MIPTBP2_2 = 0x37, + GIF_A_D_REG_TEXA = 0x3b, + GIF_A_D_REG_FOGCOL = 0x3d, + GIF_A_D_REG_TEXFLUSH = 0x3f, + GIF_A_D_REG_SCISSOR_1 = 0x40, + GIF_A_D_REG_SCISSOR_2 = 0x41, + GIF_A_D_REG_ALPHA_1 = 0x42, + GIF_A_D_REG_ALPHA_2 = 0x43, + GIF_A_D_REG_DIMX = 0x44, + GIF_A_D_REG_DTHE = 0x45, + GIF_A_D_REG_COLCLAMP = 0x46, + GIF_A_D_REG_TEST_1 = 0x47, + GIF_A_D_REG_TEST_2 = 0x48, + GIF_A_D_REG_PABE = 0x49, + GIF_A_D_REG_FBA_1 = 0x4a, + GIF_A_D_REG_FBA_2 = 0x4b, + GIF_A_D_REG_FRAME_1 = 0x4c, + GIF_A_D_REG_FRAME_2 = 0x4d, + GIF_A_D_REG_ZBUF_1 = 0x4e, + GIF_A_D_REG_ZBUF_2 = 0x4f, + GIF_A_D_REG_BITBLTBUF = 0x50, + GIF_A_D_REG_TRXPOS = 0x51, + GIF_A_D_REG_TRXREG = 0x52, + GIF_A_D_REG_TRXDIR = 0x53, + GIF_A_D_REG_HWREG = 0x54, + GIF_A_D_REG_SIGNAL = 0x60, + GIF_A_D_REG_FINISH = 0x61, + GIF_A_D_REG_LABEL = 0x62, +}; + +// In case we want to change to/from __fastcall for GIF register handlers: +#define __gifCall __fastcall + +typedef void __gifCall FnType_GIFRegHandler(const u32* data); +typedef FnType_GIFRegHandler* GIFRegHandler; + +extern FnType_GIFRegHandler GIFPackedRegHandlerNull; +extern FnType_GIFRegHandler GIFPackedRegHandlerRGBA; +extern FnType_GIFRegHandler GIFPackedRegHandlerSTQ; +extern FnType_GIFRegHandler GIFPackedRegHandlerUV; +extern FnType_GIFRegHandler GIFPackedRegHandlerXYZF2; +extern FnType_GIFRegHandler GIFPackedRegHandlerXYZ2; +extern FnType_GIFRegHandler GIFPackedRegHandlerFOG; +extern FnType_GIFRegHandler GIFPackedRegHandlerA_D; +extern FnType_GIFRegHandler GIFPackedRegHandlerNOP; +extern FnType_GIFRegHandler GIFPackedRegHandlerPRIM; +extern FnType_GIFRegHandler GIFPackedRegHandlerXYZF3; +extern FnType_GIFRegHandler GIFPackedRegHandlerXYZ3; + +extern FnType_GIFRegHandler GIFRegHandlerNull; +extern FnType_GIFRegHandler GIFRegHandlerPRIM; +extern FnType_GIFRegHandler GIFRegHandlerRGBAQ; +extern FnType_GIFRegHandler GIFRegHandlerST; +extern FnType_GIFRegHandler GIFRegHandlerUV; +extern FnType_GIFRegHandler GIFRegHandlerXYZF2; +extern FnType_GIFRegHandler GIFRegHandlerXYZ2; +extern FnType_GIFRegHandler GIFRegHandlerFOG; +extern FnType_GIFRegHandler GIFRegHandlerXYZF3; +extern FnType_GIFRegHandler GIFRegHandlerXYZ3; +extern FnType_GIFRegHandler GIFRegHandlerNOP; +extern FnType_GIFRegHandler GIFRegHandlerPRMODECONT; +extern FnType_GIFRegHandler GIFRegHandlerPRMODE; +extern FnType_GIFRegHandler GIFRegHandlerTEXCLUT; +extern FnType_GIFRegHandler GIFRegHandlerSCANMSK; +extern FnType_GIFRegHandler GIFRegHandlerTEXA; +extern FnType_GIFRegHandler GIFRegHandlerFOGCOL; +extern FnType_GIFRegHandler GIFRegHandlerTEXFLUSH; +extern FnType_GIFRegHandler GIFRegHandlerDIMX; +extern FnType_GIFRegHandler GIFRegHandlerDTHE; +extern FnType_GIFRegHandler GIFRegHandlerCOLCLAMP; +extern FnType_GIFRegHandler GIFRegHandlerPABE; +extern FnType_GIFRegHandler GIFRegHandlerBITBLTBUF; +extern FnType_GIFRegHandler GIFRegHandlerTRXPOS; +extern FnType_GIFRegHandler GIFRegHandlerTRXREG; +extern FnType_GIFRegHandler GIFRegHandlerTRXDIR; +extern FnType_GIFRegHandler GIFRegHandlerHWREG; +extern FnType_GIFRegHandler GIFRegHandlerSIGNAL; +extern FnType_GIFRegHandler GIFRegHandlerFINISH; +extern FnType_GIFRegHandler GIFRegHandlerLABEL; + +template +extern FnType_GIFRegHandler GIFPackedRegHandlerTEX0; +template +extern FnType_GIFRegHandler GIFPackedRegHandlerCLAMP; +template + +extern FnType_GIFRegHandler GIFRegHandlerTEX0; +template +extern FnType_GIFRegHandler GIFRegHandlerCLAMP; +template +extern FnType_GIFRegHandler GIFRegHandlerTEX1; +template +extern FnType_GIFRegHandler GIFRegHandlerTEX2; +template +extern FnType_GIFRegHandler GIFRegHandlerXYOFFSET; +template +extern FnType_GIFRegHandler GIFRegHandlerMIPTBP1; +template +extern FnType_GIFRegHandler GIFRegHandlerMIPTBP2; +template +extern FnType_GIFRegHandler GIFRegHandlerSCISSOR; +template +extern FnType_GIFRegHandler GIFRegHandlerALPHA; +template +extern FnType_GIFRegHandler GIFRegHandlerTEST; +template +extern FnType_GIFRegHandler GIFRegHandlerFBA; +template +extern FnType_GIFRegHandler GIFRegHandlerFRAME; +template +extern FnType_GIFRegHandler GIFRegHandlerZBUF; + +// GifReg & GifPackedReg structs from GSdx, slightly modified. +enum GS_ATST +{ + ATST_NEVER = 0, + ATST_ALWAYS = 1, + ATST_LESS = 2, + ATST_LEQUAL = 3, + ATST_EQUAL = 4, + ATST_GEQUAL = 5, + ATST_GREATER = 6, + ATST_NOTEQUAL = 7, +}; + +enum GS_AFAIL +{ + AFAIL_KEEP = 0, + AFAIL_FB_ONLY = 1, + AFAIL_ZB_ONLY = 2, + AFAIL_RGB_ONLY = 3, +}; + +// GIFReg + +REG64_(GIFReg, ALPHA) + u32 A:2; + u32 B:2; + u32 C:2; + u32 D:2; + u32 _PAD1:24; + u32 FIX:8; + u32 _PAD2:24; +REG_END2 + // opaque => output will be Cs/As +// __forceinline bool IsOpaque() const {return (A == B || C == 2 && FIX == 0) && D == 0 || (A == 0 && B == D && C == 2 && FIX == 0x80);} +// __forceinline bool IsOpaque(int amin, int amax) const {return (A == B || amax == 0) && D == 0 || A == 0 && B == D && amin == 0x80 && amax == 0x80;} +REG_END2 + +REG64_(GIFReg, BITBLTBUF) + u32 SBP:14; + u32 _PAD1:2; + u32 SBW:6; + u32 _PAD2:2; + u32 SPSM:6; + u32 _PAD3:2; + u32 DBP:14; + u32 _PAD4:2; + u32 DBW:6; + u32 _PAD5:2; + u32 DPSM:6; + u32 _PAD6:2; +REG_END + +REG64_(GIFReg, CLAMP) +union +{ + struct + { + u32 WMS:2; + u32 WMT:2; + u32 MINU:10; + u32 MAXU:10; + u32 _PAD1:8; + u32 _PAD2:2; + u32 MAXV:10; + u32 _PAD3:20; + }; + + struct + { + u64 _PAD4:24; + u64 MINV:10; + u64 _PAD5:30; + }; +}; +REG_END + +REG64_(GIFReg, COLCLAMP) + u32 CLAMP:1; + u32 _PAD1:31; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, DIMX) + s32 DM00:3; + s32 _PAD00:1; + s32 DM01:3; + s32 _PAD01:1; + s32 DM02:3; + s32 _PAD02:1; + s32 DM03:3; + s32 _PAD03:1; + s32 DM10:3; + s32 _PAD10:1; + s32 DM11:3; + s32 _PAD11:1; + s32 DM12:3; + s32 _PAD12:1; + s32 DM13:3; + s32 _PAD13:1; + s32 DM20:3; + s32 _PAD20:1; + s32 DM21:3; + s32 _PAD21:1; + s32 DM22:3; + s32 _PAD22:1; + s32 DM23:3; + s32 _PAD23:1; + s32 DM30:3; + s32 _PAD30:1; + s32 DM31:3; + s32 _PAD31:1; + s32 DM32:3; + s32 _PAD32:1; + s32 DM33:3; + s32 _PAD33:1; +REG_END + +REG64_(GIFReg, DTHE) + u32 DTHE:1; + u32 _PAD1:31; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, FBA) + u32 FBA:1; + u32 _PAD1:31; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, FINISH) + u32 _PAD1:32; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, FOG) + u32 _PAD1:32; + u32 _PAD2:24; + u32 F:8; +REG_END + +REG64_(GIFReg, FOGCOL) + u32 FCR:8; + u32 FCG:8; + u32 FCB:8; + u32 _PAD1:8; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, FRAME) + u32 FBP:9; + u32 _PAD1:7; + u32 FBW:6; + u32 _PAD2:2; + u32 PSM:6; + u32 _PAD3:2; + u32 FBMSK:32; +REG_END2 + u32 Block() const {return FBP << 5;} +REG_END2 + +REG64_(GIFReg, HWREG) + u32 DATA_LOWER:32; + u32 DATA_UPPER:32; +REG_END + +REG64_(GIFReg, LABEL) + u32 ID:32; + u32 IDMSK:32; +REG_END + +REG64_(GIFReg, MIPTBP1) + u64 TBP1:14; + u64 TBW1:6; + u64 TBP2:14; + u64 TBW2:6; + u64 TBP3:14; + u64 TBW3:6; + u64 _PAD:4; +REG_END + +REG64_(GIFReg, MIPTBP2) + u64 TBP4:14; + u64 TBW4:6; + u64 TBP5:14; + u64 TBW5:6; + u64 TBP6:14; + u64 TBW6:6; + u64 _PAD:4; +REG_END + +REG64_(GIFReg, NOP) + u32 _PAD1:32; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, PABE) + u32 PABE:1; + u32 _PAD1:31; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, PRIM) + u32 PRIM:3; + u32 IIP:1; + u32 TME:1; + u32 FGE:1; + u32 ABE:1; + u32 AA1:1; + u32 FST:1; + u32 CTXT:1; + u32 FIX:1; + u32 _PAD1:21; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, PRMODE) + u32 _PRIM:3; + u32 IIP:1; + u32 TME:1; + u32 FGE:1; + u32 ABE:1; + u32 AA1:1; + u32 FST:1; + u32 CTXT:1; + u32 FIX:1; + u32 _PAD2:21; + u32 _PAD3:32; +REG_END + +REG64_(GIFReg, PRMODECONT) + u32 AC:1; + u32 _PAD1:31; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, RGBAQ) + u32 R:8; + u32 G:8; + u32 B:8; + u32 A:8; + float Q; +REG_END + +REG64_(GIFReg, SCANMSK) + u32 MSK:2; + u32 _PAD1:30; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, SCISSOR) + u32 SCAX0:11; + u32 _PAD1:5; + u32 SCAX1:11; + u32 _PAD2:5; + u32 SCAY0:11; + u32 _PAD3:5; + u32 SCAY1:11; + u32 _PAD4:5; +REG_END + +REG64_(GIFReg, SIGNAL) + u32 ID:32; + u32 IDMSK:32; +REG_END + +REG64_(GIFReg, ST) + float S; + float T; +REG_END + +REG64_(GIFReg, TEST) + u32 ATE:1; + u32 ATST:3; + u32 AREF:8; + u32 AFAIL:2; + u32 DATE:1; + u32 DATM:1; + u32 ZTE:1; + u32 ZTST:2; + u32 _PAD1:13; + u32 _PAD2:32; +REG_END2 + __forceinline bool DoFirstPass() {return !ATE || ATST != ATST_NEVER;} // not all pixels fail automatically + __forceinline bool DoSecondPass() {return ATE && ATST != ATST_ALWAYS && AFAIL != AFAIL_KEEP;} // pixels may fail, write fb/z + __forceinline bool NoSecondPass() {return ATE && ATST != ATST_ALWAYS && AFAIL == AFAIL_KEEP;} // pixels may fail, no output +REG_END2 + +REG64_(GIFReg, TEX0) +union +{ + struct + { + u32 TBP0:14; + u32 TBW:6; + u32 PSM:6; + u32 TW:4; + u32 _PAD1:2; + u32 _PAD2:2; + u32 TCC:1; + u32 TFX:2; + u32 CBP:14; + u32 CPSM:4; + u32 CSM:1; + u32 CSA:5; + u32 CLD:3; + }; + + struct + { + u64 _PAD3:30; + u64 TH:4; + u64 _PAD4:30; + }; +}; +REG_END2 + __forceinline bool IsRepeating() {return (u32)((u32)1 << TW) > (u32)(TBW << (u32)6);} +REG_END2 + +REG64_(GIFReg, TEX1) + u32 LCM:1; + u32 _PAD1:1; + u32 MXL:3; + u32 MMAG:1; + u32 MMIN:3; + u32 MTBA:1; + u32 _PAD2:9; + u32 L:2; + u32 _PAD3:11; + s32 K:12; // 1:7:4 + u32 _PAD4:20; +REG_END2 + bool IsMinLinear() const {return (MMIN == 1) || (MMIN & 4);} + bool IsMagLinear() const {return MMAG;} +REG_END2 + +REG64_(GIFReg, TEX2) + u32 _PAD1:20; + u32 PSM:6; + u32 _PAD2:6; + u32 _PAD3:5; + u32 CBP:14; + u32 CPSM:4; + u32 CSM:1; + u32 CSA:5; + u32 CLD:3; +REG_END + +REG64_(GIFReg, TEXA) + u32 TA0:8; + u32 _PAD1:7; + u32 AEM:1; + u32 _PAD2:16; + u32 TA1:8; + u32 _PAD3:24; +REG_END + +REG64_(GIFReg, TEXCLUT) + u32 CBW:6; + u32 COU:6; + u32 COV:10; + u32 _PAD1:10; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, TEXFLUSH) + u32 _PAD1:32; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, TRXDIR) + u32 XDIR:2; + u32 _PAD1:30; + u32 _PAD2:32; +REG_END + +REG64_(GIFReg, TRXPOS) + u32 SSAX:11; + u32 _PAD1:5; + u32 SSAY:11; + u32 _PAD2:5; + u32 DSAX:11; + u32 _PAD3:5; + u32 DSAY:11; + u32 DIRY:1; + u32 DIRX:1; + u32 _PAD4:3; +REG_END + +REG64_(GIFReg, TRXREG) + u32 RRW:12; + u32 _PAD1:20; + u32 RRH:12; + u32 _PAD2:20; +REG_END + +// GSState::GIFPackedRegHandlerUV and GSState::GIFRegHandlerUV will make sure that the _PAD1/2 bits are set to zero + +REG64_(GIFReg, UV) + u32 U:14; + u32 _PAD1:2; + u32 V:14; + u32 _PAD2:2; + u32 _PAD3:32; +REG_END + +// GSState::GIFRegHandlerXYOFFSET will make sure that the _PAD1/2 bits are set to zero + +REG64_(GIFReg, XYOFFSET) + u32 OFX; // :16; u32 _PAD1:16; + u32 OFY; // :16; u32 _PAD2:16; +REG_END + +REG64_(GIFReg, XYZ) + u32 X:16; + u32 Y:16; + u32 Z:32; +REG_END + +REG64_(GIFReg, XYZF) + u32 X:16; + u32 Y:16; + u32 Z:24; + u32 F:8; +REG_END + +REG64_(GIFReg, ZBUF) + u32 ZBP:9; + u32 _PAD1:15; + // u32 PSM:4; + // u32 _PAD2:4; + u32 PSM:6; + u32 _PAD2:2; + u32 ZMSK:1; + u32 _PAD3:31; +REG_END2 + u32 Block() const {return ZBP << 5;} +REG_END2 + +REG64_SET(GIFReg) + GIFRegALPHA ALPHA; + GIFRegBITBLTBUF BITBLTBUF; + GIFRegCLAMP CLAMP; + GIFRegCOLCLAMP COLCLAMP; + GIFRegDIMX DIMX; + GIFRegDTHE DTHE; + GIFRegFBA FBA; + GIFRegFINISH FINISH; + GIFRegFOG FOG; + GIFRegFOGCOL FOGCOL; + GIFRegFRAME FRAME; + GIFRegHWREG HWREG; + GIFRegLABEL LABEL; + GIFRegMIPTBP1 MIPTBP1; + GIFRegMIPTBP2 MIPTBP2; + GIFRegNOP NOP; + GIFRegPABE PABE; + GIFRegPRIM PRIM; + GIFRegPRMODE PRMODE; + GIFRegPRMODECONT PRMODECONT; + GIFRegRGBAQ RGBAQ; + GIFRegSCANMSK SCANMSK; + GIFRegSCISSOR SCISSOR; + GIFRegSIGNAL SIGNAL; + GIFRegST ST; + GIFRegTEST TEST; + GIFRegTEX0 TEX0; + GIFRegTEX1 TEX1; + GIFRegTEX2 TEX2; + GIFRegTEXA TEXA; + GIFRegTEXCLUT TEXCLUT; + GIFRegTEXFLUSH TEXFLUSH; + GIFRegTRXDIR TRXDIR; + GIFRegTRXPOS TRXPOS; + GIFRegTRXREG TRXREG; + GIFRegUV UV; + GIFRegXYOFFSET XYOFFSET; + GIFRegXYZ XYZ; + GIFRegXYZF XYZF; + GIFRegZBUF ZBUF; +REG_SET_END + +// GIFPacked + +REG128_(GIFPacked, PRIM) + u32 PRIM:11; + u32 _PAD1:21; + u32 _PAD2:32; + u32 _PAD3:32; + u32 _PAD4:32; +REG_END + +REG128_(GIFPacked, RGBA) + u32 R:8; + u32 _PAD1:24; + u32 G:8; + u32 _PAD2:24; + u32 B:8; + u32 _PAD3:24; + u32 A:8; + u32 _PAD4:24; +REG_END + +REG128_(GIFPacked, STQ) + float S; + float T; + float Q; + u32 _PAD1:32; +REG_END + +REG128_(GIFPacked, UV) + u32 U:14; + u32 _PAD1:18; + u32 V:14; + u32 _PAD2:18; + u32 _PAD3:32; + u32 _PAD4:32; +REG_END + +REG128_(GIFPacked, XYZF2) + u32 X:16; + u32 _PAD1:16; + u32 Y:16; + u32 _PAD2:16; + u32 _PAD3:4; + u32 Z:24; + u32 _PAD4:4; + u32 _PAD5:4; + u32 F:8; + u32 _PAD6:3; + u32 ADC:1; + u32 _PAD7:16; +REG_END + +REG128_(GIFPacked, XYZ2) + u32 X:16; + u32 _PAD1:16; + u32 Y:16; + u32 _PAD2:16; + u32 Z:32; + u32 _PAD3:15; + u32 ADC:1; + u32 _PAD4:16; +REG_END + +REG128_(GIFPacked, FOG) + u32 _PAD1:32; + u32 _PAD2:32; + u32 _PAD3:32; + u32 _PAD4:4; + u32 F:8; + u32 _PAD5:20; +REG_END + +REG128_(GIFPacked, A_D) + u64 DATA:64; + u32 ADDR:8; // enum GIF_A_D_REG + u32 _PAD1:24; + u32 _PAD2:32; +REG_END + +REG128_(GIFPacked, NOP) + u32 _PAD1:32; + u32 _PAD2:32; + u32 _PAD3:32; + u32 _PAD4:32; +REG_END + +REG128_SET(GIFPackedReg) + GIFReg r; + GIFPackedPRIM PRIM; + GIFPackedRGBA RGBA; + GIFPackedSTQ STQ; + GIFPackedUV UV; + GIFPackedXYZF2 XYZF2; + GIFPackedXYZ2 XYZ2; + GIFPackedFOG FOG; + GIFPackedA_D A_D; + GIFPackedNOP NOP; +REG_SET_END + + +REG64_(GSReg, BGCOLOR) + u32 R:8; + u32 G:8; + u32 B:8; + u32 _PAD1:8; + u32 _PAD2:32; +REG_END + +REG64_(GSReg, BUSDIR) + u32 DIR:1; + u32 _PAD1:31; + u32 _PAD2:32; +REG_END + +REG64_(GSReg, CSR) + u32 SIGNAL:1; + u32 FINISH:1; + u32 HSINT:1; + u32 VSINT:1; + u32 EDWINT:1; + u32 ZERO1:1; + u32 ZERO2:1; + u32 _PAD1:1; + u32 FLUSH:1; + u32 RESET:1; + u32 _PAD2:2; + u32 NFIELD:1; + u32 FIELD:1; + u32 FIFO:2; + u32 REV:8; + u32 ID:8; + u32 _PAD3:32; +REG_END + +REG64_(GSReg, DISPFB) // (-1/2) + u32 FBP:9; + u32 FBW:6; + u32 PSM:5; + u32 _PAD:12; + u32 DBX:11; + u32 DBY:11; + u32 _PAD2:10; +REG_END + +REG64_(GSReg, DISPLAY) // (-1/2) + u32 DX:12; + u32 DY:11; + u32 MAGH:4; + u32 MAGV:2; + u32 _PAD:3; + u32 DW:12; + u32 DH:11; + u32 _PAD2:9; +REG_END + +REG64_(GSReg, EXTBUF) + u32 EXBP:14; + u32 EXBW:6; + u32 FBIN:2; + u32 WFFMD:1; + u32 EMODA:2; + u32 EMODC:2; + u32 _PAD1:5; + u32 WDX:11; + u32 WDY:11; + u32 _PAD2:10; +REG_END + +REG64_(GSReg, EXTDATA) + u32 SX:12; + u32 SY:11; + u32 SMPH:4; + u32 SMPV:2; + u32 _PAD1:3; + u32 WW:12; + u32 WH:11; + u32 _PAD2:9; +REG_END + +REG64_(GSReg, EXTWRITE) + u32 WRITE; + u32 _PAD2:32; +REG_END + +REG64_(GSReg, IMR) + u32 _PAD1:8; + u32 SIGMSK:1; + u32 FINISHMSK:1; + u32 HSMSK:1; + u32 VSMSK:1; + u32 EDWMSK:1; + u32 _PAD2:19; + u32 _PAD3:32; +REG_END + +REG64_(GSReg, PMODE) + u32 EN1:1; + u32 EN2:1; + u32 CRTMD:3; + u32 MMOD:1; + u32 AMOD:1; + u32 SLBG:1; + u32 ALP:8; + u32 _PAD:16; + u32 _PAD1:32; +REG_END + +REG64_(GSReg, SIGLBLID) + u32 SIGID:32; + u32 LBLID:32; +REG_END + +REG64_(GSReg, SMODE1) + u32 RC:3; + u32 LC:7; + u32 T1248:2; + u32 SLCK:1; + u32 CMOD:2; + u32 EX:1; + u32 PRST:1; + u32 SINT:1; + u32 XPCK:1; + u32 PCK2:2; + u32 SPML:4; + u32 GCONT:1; + u32 PHS:1; + u32 PVS:1; + u32 PEHS:1; + u32 PEVS:1; + u32 CLKSEL:2; + u32 NVCK:1; + u32 SLCK2:1; + u32 VCKSEL:2; + u32 VHP:1; + u32 _PAD1:27; +REG_END + +REG64_(GSReg, SMODE2) + u32 INT:1; + u32 FFMD:1; + u32 DPMS:2; + u32 _PAD2:28; + u32 _PAD3:32; +REG_END + +REG64_(GSReg, SIGBLID) + u32 SIGID; + u32 LBLID; +REG_END + +#define PMODE ((GSRegPMODE*)(g_pBasePS2Mem+0x0000)) +#define SMODE1 ((GSRegSMODE1*)(g_pBasePS2Mem+0x0010)) +#define SMODE2 ((GSRegSMODE2*)(g_pBasePS2Mem+0x0020)) +// SRFSH +#define SYNCH1 ((GSRegSYNCH1*)(g_pBasePS2Mem+0x0040)) +#define SYNCH2 ((GSRegSYNCH2*)(g_pBasePS2Mem+0x0050)) +#define SYNCV ((GSRegSYNCV*)(g_pBasePS2Mem+0x0060)) +#define DISPFB1 ((GSRegDISPFB*)(g_pBasePS2Mem+0x0070)) +#define DISPLAY1 ((GSRegDISPLAY*)(g_pBasePS2Mem+0x0080)) +#define DISPFB2 ((GSRegDISPFB*)(g_pBasePS2Mem+0x0090)) +#define DISPLAY2 ((GSRegDISPLAY*)(g_pBasePS2Mem+0x00a0)) +#define EXTBUF ((GSRegEXTBUF*)(g_pBasePS2Mem+0x00b0)) +#define EXTDATA ((GSRegEXTDATA*)(g_pBasePS2Mem+0x00c0)) +#define EXTWRITE ((GSRegEXTWRITE*)(g_pBasePS2Mem+0x00d0)) +#define BGCOLOR ((GSRegBGCOLOR*)(g_pBasePS2Mem+0x00e0)) +#define CSR ((GSRegCSR*)(g_pBasePS2Mem+0x1000)) +#define IMR ((GSRegIMR*)(g_pBasePS2Mem+0x1010)) +#define BUSDIR ((GSRegBUSDIR*)(g_pBasePS2Mem+0x1040)) +#define SIGLBLID ((GSRegSIGBLID*)(g_pBasePS2Mem+0x1080)) + +// +// sps2tags.h +// +#define GET_GIF_REG(tag, reg) \ + (((tag).ai32[2 + ((reg) >> 3)] >> (((reg) & 7) << 2)) & 0xf) + +#define GET_GSFPS (((SMODE1->CMOD&1) ? 50 : 60) / (SMODE2->INT ? 1 : 2)) + +extern void WriteTempRegs(); +extern void SetFrameSkip(bool skip); +extern void ResetRegs(); + +extern void SetTexFlush(); +extern void SetFogColor(u32 fog); +extern void SetFogColor(GIFRegFOGCOL* fog); +extern bool CheckChangeInClut(u32 highdword, u32 psm); // returns true if clut will change after this tex0 op + +// flush current vertices, call before setting new registers (the main render method) +void Flush(int context); +void FlushBoth(); + +// called on a primitive switch +void Prim(); + +#else +#include "NewRegs.h" +#endif +#endif diff --git a/plugins/zzogl-pg-cg/opengl/Util.h b/plugins/zzogl-pg-cg/opengl/Util.h new file mode 100644 index 000000000..99c98d80a --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/Util.h @@ -0,0 +1,279 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef UTIL_H_INCLUDED +#define UTIL_H_INCLUDED + + +#ifdef _WIN32 + +#include +#include "Utilities/RedtapeWindows.h" + +//#include +//#include + +#include +#include +#include "glprocs.h" + +#else // linux basic definitions + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#endif + +#define GSdefs + +//Pcsx2Defs is included in Dependencies.h. +#include "Utilities/Dependencies.h" + +#include "CRC.h" +#include "ZZLog.h" + +// need C definitions -- no mangling please! +extern "C" u32 CALLBACK PS2EgetLibType(void); +extern "C" u32 CALLBACK PS2EgetLibVersion2(u32 type); +extern "C" char* CALLBACK PS2EgetLibName(void); + +#include "ZZoglMath.h" +#include "Profile.h" +#include "GSDump.h" + +#include "Utilities/MemcpyFast.h" +#define memcpy_amd memcpy_fast + +extern wxString s_strIniPath; // Air's new (r2361) new constant for ini file path + +typedef struct +{ + int x, y, w, h; +} Rect; + +typedef struct +{ + int x, y; +} Point; + +typedef struct +{ + int w, h; +} Size; + +typedef struct +{ + int x0, y0; + int x1, y1; +} Rect2; + +typedef struct +{ + int x, y, c; +} PointC; + +enum GSWindowDim +{ + + GSDim_640 = 0, + GSDim_800, + GSDim_1024, + GSDim_1280, +}; + +typedef union +{ + struct + { + u32 fullscreen : 1; + u32 tga_snap : 1; + u32 capture_avi : 1; + u32 widescreen : 1; + u32 wireframe : 1; + u32 loaded : 1; + u32 dimensions : 2; + }; + u32 _u32; + + void ZZOptions(u32 value) { _u32 = value; } +} ZZOptions; + +typedef struct +{ + u8 mrtdepth; // write color in render target + u8 interlace; // intelacing mode 0, 1, 3-off + u8 aa; // antialiasing 0 - off, 1 - 2x, 2 - 4x, 3 - 8x, 4 - 16x + u8 bilinear; // set to enable bilinear support. 0 - off, 1 -- on, 2 -- force (use for textures that usually need it) + ZZOptions zz_options; + gameHacks hacks; // game options -- different hacks. + gameHacks def_hacks;// default game settings + int width, height; // View target size, has no impact towards speed + int x, y; // Lets try for a persistant window position. + bool isWideScreen; // Widescreen support + u32 SkipDraw; + u32 log; + u32 disableHacks; + int dump; + + void incAA() { aa++; if (aa > 4) aa = 0; } + void decAA() { aa--; if (aa > 4) aa = 4; } // u8 is unsigned, so negative value is 255. + + gameHacks settings() + { + if (disableHacks) + { + return hacks; + } + else + { + gameHacks tempHack; + tempHack._u32 = (hacks._u32 | def_hacks._u32); + return tempHack; + } + } + + bool fullscreen() { return !!(zz_options.fullscreen); } + bool wireframe() { return !!(zz_options.wireframe); } + bool widescreen() { return !!(zz_options.widescreen); } + bool captureAvi() { return !!(zz_options.capture_avi); } + bool loaded() { return !!(zz_options.loaded); } + + void setFullscreen(bool flag) + { + zz_options.fullscreen = (flag) ? 1 : 0; + } + + void setWireframe(bool flag) + { + zz_options.wireframe = (flag) ? 1 : 0; + } + + void setCaptureAvi(bool flag) + { + zz_options.capture_avi = (flag) ? 1 : 0; + } + + void setLoaded(bool flag) + { + zz_options.loaded = (flag) ? 1 : 0; + } + void set_dimensions(u32 dim) + { + switch (dim) + { + + case GSDim_640: + width = 640; + height = isWideScreen ? 360 : 480; + break; + + case GSDim_800: + width = 800; + height = isWideScreen ? 450 : 600; + break; + + case GSDim_1024: + width = 1024; + height = isWideScreen ? 576 : 768; + break; + + case GSDim_1280: + width = 1280; + height = isWideScreen ? 720 : 960; + break; + + default: + width = 800; + height = 600; + break; + } + } + +} GSconf; +extern GSconf conf; + +// ----------------------- Defines + +#define REG64(name) \ +union name \ +{ \ + u64 i64; \ + u32 ai32[2]; \ + struct { \ + +#define REG128(name)\ +union name \ +{ \ + u64 ai64[2]; \ + u32 ai32[4]; \ + struct { \ + +#define REG64_(prefix, name) REG64(prefix##name) +#define REG128_(prefix, name) REG128(prefix##name) + +#define REG_END }; }; +#define REG_END2 }; + +#define REG64_SET(name) \ +union name \ +{ \ + u64 i64; \ + u32 ai32[2]; \ + +#define REG128_SET(name)\ +union name \ +{ \ + u64 ai64[2]; \ + u32 ai32[4]; \ + +#define REG_SET_END }; + +#define FORIT(it, v) for(it = (v).begin(); it != (v).end(); ++(it)) + +extern void LoadConfig(); +extern void SaveConfig(); + +extern void (*GSirq)(); + +extern void *SysLoadLibrary(char *lib); // Loads Library +extern void *SysLoadSym(void *lib, char *sym); // Loads Symbol from Library +extern char *SysLibError(); // Gets previous error loading sysbols +extern void SysCloseLibrary(void *lib); // Closes Library +extern void SysMessage(const char *fmt, ...); + +#ifdef ZEROGS_DEVBUILD +extern char* EFFECT_NAME; +extern char* EFFECT_DIR; +extern u32 g_nGenVars, g_nTexVars, g_nAlphaVars, g_nResolve; +extern bool g_bSaveTrans, g_bUpdateEffect, g_bSaveTex, g_bSaveResolved; +#endif + +extern bool g_bDisplayFPS; // should we display FPS on screen? + +#endif // UTIL_H_INCLUDED diff --git a/plugins/zzogl-pg-cg/opengl/Win32/Conf.cpp b/plugins/zzogl-pg-cg/opengl/Win32/Conf.cpp new file mode 100644 index 000000000..bd08dd94a --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/Win32/Conf.cpp @@ -0,0 +1,115 @@ +#include + +#include "GS.h" +#include "Win32.h" +#include "Utilities/Path.h" + +extern HINSTANCE hInst; + + +void SaveConfig() +{ + wxChar szValue[256]; + const wxString iniFile(Path::Combine(s_strIniPath, L"zzogl-pg.ini")); + + wxSprintf(szValue, L"%u", conf.interlace); + WritePrivateProfileString(L"Settings", L"Interlace", szValue, iniFile); + wxSprintf(szValue, L"%u", conf.aa); + WritePrivateProfileString(L"Settings", L"Antialiasing", szValue, iniFile); + wxSprintf(szValue, L"%u", conf.bilinear); + WritePrivateProfileString(L"Settings", L"Bilinear", szValue, iniFile); + wxSprintf(szValue, L"%u", conf.zz_options); + WritePrivateProfileString(L"Settings", L"ZZOptions", szValue, iniFile); + wxSprintf(szValue, L"%u", conf.hacks); + WritePrivateProfileString(L"Settings", L"AdvancedOptions", szValue, iniFile); + wxSprintf(szValue, L"%u", conf.width); + WritePrivateProfileString(L"Settings", L"Width", szValue, iniFile); + wxSprintf(szValue, L"%u", conf.height); + WritePrivateProfileString(L"Settings", L"Height", szValue, iniFile); + wxSprintf(szValue, L"%u", conf.SkipDraw); + WritePrivateProfileString(L"Settings", L"SkipDraw", szValue, iniFile); +} + +void LoadConfig() +{ + wxChar szValue[256]; + const wxString iniFile(Path::Combine(s_strIniPath, L"zzogl-pg.ini")); + + memset(&conf, 0, sizeof(conf)); + conf.interlace = 0; // on, mode 1 + conf.mrtdepth = 1; + conf.zz_options._u32 = 0; + conf.hacks._u32 = 0; + conf.bilinear = 1; + conf.width = 640; + conf.height = 480; + conf.SkipDraw = 0; + conf.disableHacks = 0; + + FILE *fp = wxFopen(iniFile, L"rt"); + + if (!fp) + { + SysMessage("Unable to open ZZOgl-PG's ini file!"); + CreateDirectory(s_strIniPath, NULL); + SaveConfig();//save and return + return ; + } + + fclose(fp); + + GetPrivateProfileString(L"Settings", L"Interlace", NULL, szValue, 20, iniFile); + conf.interlace = (u8)wxStrtoul(szValue, NULL, 10); + GetPrivateProfileString(L"Settings", L"Antialiasing", NULL, szValue, 20, iniFile); + conf.aa = (u8)wxStrtoul(szValue, NULL, 10); + GetPrivateProfileString(L"Settings", L"ZZOptions", NULL, szValue, 20, iniFile); + conf.zz_options._u32 = wxStrtoul(szValue, NULL, 10); + GetPrivateProfileString(L"Settings", L"AdvancedOptions", NULL, szValue, 20, iniFile); + conf.hacks._u32 = wxStrtoul(szValue, NULL, 10); + GetPrivateProfileString(L"Settings", L"Bilinear", NULL, szValue, 20, iniFile); + conf.bilinear = (u8)wxStrtoul(szValue, NULL, 10); + GetPrivateProfileString(L"Settings", L"Width", NULL, szValue, 20, iniFile); + conf.width = wxStrtoul(szValue, NULL, 10); + GetPrivateProfileString(L"Settings", L"Height", NULL, szValue, 20, iniFile); + conf.height = wxStrtoul(szValue, NULL, 10); + GetPrivateProfileString(L"Settings", L"SkipDraw", NULL, szValue, 20, iniFile); + conf.SkipDraw = wxStrtoul(szValue, NULL, 10); + + if (conf.aa < 0 || conf.aa > 4) conf.aa = 0; + + conf.isWideScreen = (conf.widescreen() != 0); + + switch (conf.zz_options.dimensions) + { + case GSDim_640: + conf.width = 640; + conf.height = conf.isWideScreen ? 360 : 480; + break; + + case GSDim_800: + conf.width = 800; + conf.height = conf.isWideScreen ? 450 : 600; + break; + + case GSDim_1024: + conf.width = 1024; + conf.height = conf.isWideScreen ? 576 : 768; + break; + + case GSDim_1280: + conf.width = 1280; + conf.height = conf.isWideScreen ? 720 : 960; + break; + } + + // turn off all hacks by default + conf.setWireframe(false); + conf.setCaptureAvi(false); + conf.setLoaded(true); + + if (conf.width <= 0 || conf.height <= 0) + { + conf.width = 640; + conf.height = 480; + } +} diff --git a/plugins/zzogl-pg-cg/opengl/Win32/Win32.cpp b/plugins/zzogl-pg-cg/opengl/Win32/Win32.cpp new file mode 100644 index 000000000..f7cad522d --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/Win32/Win32.cpp @@ -0,0 +1,325 @@ +#include + +#include "Utilities/RedtapeWindows.h" +#include + +#include "resrc1.h" + +#include "GS.h" +#include "ZZoglShaders.h" +#include "Win32.h" + +#include + +using namespace std; + +extern int g_nPixelShaderVer; +static int prevbilinearfilter; +HINSTANCE hInst = NULL; + +void CALLBACK GSkeyEvent(keyEvent *ev) +{ +// switch (ev->event) { +// case KEYPRESS: +// switch (ev->key) { +// case VK_PRIOR: +// if (conf.fps) fpspos++; break; +// case VK_NEXT: +// if (conf.fps) fpspos--; break; +// case VK_END: +// if (conf.fps) fpspress = 1; break; +// case VK_DELETE: +// conf.fps = 1 - conf.fps; +// break; +// } +// break; +// } +} + +#include "Win32/resource.h" + +map mapConfOpts; +#define PUT_CONF(id) mapConfOpts[IDC_CONFOPT_##id] = 0x##id; + +void OnAdvOK(HWND hW) +{ + conf.hacks._u32 = 0; + + for (map::iterator it = mapConfOpts.begin(); it != mapConfOpts.end(); ++it) + { + if (IsDlgButtonChecked(hW, it->first)) conf.hacks._u32 |= it->second; + } + + GSsetGameCRC(g_LastCRC, conf.hacks._u32); + + SaveConfig(); + + EndDialog(hW, false); +} + +void OnInitAdvDialog(HWND hW) +{ + mapConfOpts.clear(); + + PUT_CONF(00000001); + PUT_CONF(00000002); + PUT_CONF(00000004); + PUT_CONF(00000008); + PUT_CONF(00000010); + PUT_CONF(00000020); + PUT_CONF(00000040); + PUT_CONF(00000080); + PUT_CONF(00000100); + PUT_CONF(00000200); + PUT_CONF(00000400); + PUT_CONF(00000800); + PUT_CONF(00001000); + PUT_CONF(00002000); + PUT_CONF(00004000); + PUT_CONF(00008000); + PUT_CONF(00010000); + PUT_CONF(00020000); + PUT_CONF(00040000); + PUT_CONF(00080000); + PUT_CONF(00100000); + PUT_CONF(00200000); + PUT_CONF(00800000); + PUT_CONF(01000000); + PUT_CONF(02000000); + PUT_CONF(04000000); + PUT_CONF(10000000); + + for (map::iterator it = mapConfOpts.begin(); it != mapConfOpts.end(); ++it) + { + CheckDlgButton(hW, it->first, (conf.settings()._u32 & it->second) ? 1 : 0); + } +} + +BOOL CALLBACK AdvancedDialogProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_INITDIALOG: + OnInitAdvDialog(hW); + return true; + + case WM_COMMAND: + + switch (LOWORD(wParam)) + { + case IDCANCEL: + EndDialog(hW, true); + return true; + + case IDOK: + OnAdvOK(hW); + return true; + } + } + + return false; +} + +void CALLBACK AdvancedDialog() +{ + DialogBox(hInst, + MAKEINTRESOURCE(IDD_ADV_OPTIONS), + GetActiveWindow(), + (DLGPROC)AdvancedDialogProc); +} + +void OnInitConfDialog(HWND hW) +{ + if (!(conf.zz_options.loaded)) LoadConfig(); + + TCHAR *aaName[] = {L"None", L"x2", L"x4", L"x8", L"x16"}; + + for(int i=0; i<5; i++) + { + ComboBox_AddString(GetDlgItem(hW, IDC_AA_COMBO), (LPARAM)aaName[i]); + } + ComboBox_SelectString(GetDlgItem(hW, IDC_AA_COMBO), -1, (LPARAM)aaName[conf.aa]); + + TCHAR *sizeName[] = {L"640 x 480", L"800 x 600", L"1024 x 768", L"1280 x 960"}; + + for(int i=0; i<4; i++) + { + ComboBox_AddString(GetDlgItem(hW, IDC_WIN_SIZE_COMBO), (LPARAM)sizeName[i]); + } + ComboBox_SelectString(GetDlgItem(hW, IDC_WIN_SIZE_COMBO), -1, (LPARAM)sizeName[conf.zz_options.dimensions]); + + CheckDlgButton(hW, IDC_CONFIG_INTERLACE, conf.interlace); + CheckDlgButton(hW, IDC_CONFIG_BILINEAR, conf.bilinear); + CheckDlgButton(hW, IDC_CONFIG_DEPTHWRITE, conf.mrtdepth); + CheckDlgButton(hW, IDC_CONFIG_WIREFRAME, (conf.wireframe()) ? 1 : 0); + CheckDlgButton(hW, IDC_CONFIG_CAPTUREAVI, (conf.captureAvi()) ? 1 : 0); + CheckDlgButton(hW, IDC_CONFIG_FULLSCREEN, (conf.fullscreen()) ? 1 : 0); + CheckDlgButton(hW, IDC_CONFIG_WIDESCREEN, (conf.widescreen()) ? 1 : 0); + CheckDlgButton(hW, IDC_CONFIG_BMPSS, (conf.zz_options.tga_snap) ? 1 : 0); + + prevbilinearfilter = conf.bilinear; +} + +void OnConfOK(HWND hW) +{ + u32 newinterlace = IsDlgButtonChecked(hW, IDC_CONFIG_INTERLACE); + + if (!conf.interlace) + conf.interlace = newinterlace; + else if (!newinterlace) + conf.interlace = 2; // off + + conf.bilinear = IsDlgButtonChecked(hW, IDC_CONFIG_BILINEAR); + + // restore + if (conf.bilinear && prevbilinearfilter) conf.bilinear = prevbilinearfilter; + + if (ComboBox_GetCurSel(GetDlgItem(hW, IDC_AA_COMBO)) != -1) + conf.aa = ComboBox_GetCurSel(GetDlgItem(hW, IDC_AA_COMBO)); + + conf.zz_options._u32 = 0; + + conf.zz_options.capture_avi = IsDlgButtonChecked(hW, IDC_CONFIG_CAPTUREAVI) ? 1 : 0; + conf.zz_options.wireframe = IsDlgButtonChecked(hW, IDC_CONFIG_WIREFRAME) ? 1 : 0; + conf.zz_options.fullscreen = IsDlgButtonChecked(hW, IDC_CONFIG_FULLSCREEN) ? 1 : 0; + conf.zz_options.widescreen = IsDlgButtonChecked(hW, IDC_CONFIG_WIDESCREEN) ? 1 : 0; + conf.zz_options.tga_snap = IsDlgButtonChecked(hW, IDC_CONFIG_BMPSS) ? 1 : 0; + + if (ComboBox_GetCurSel(GetDlgItem(hW, IDC_WIN_SIZE_COMBO)) == 0) + conf.zz_options.dimensions = GSDim_640; + else if (ComboBox_GetCurSel(GetDlgItem(hW, IDC_WIN_SIZE_COMBO)) == 1) + conf.zz_options.dimensions = GSDim_800; + else if (ComboBox_GetCurSel(GetDlgItem(hW, IDC_WIN_SIZE_COMBO)) == 2) + conf.zz_options.dimensions = GSDim_1024; + else if (ComboBox_GetCurSel(GetDlgItem(hW, IDC_WIN_SIZE_COMBO)) == 3) + conf.zz_options.dimensions = GSDim_1280; + + SaveConfig(); + + EndDialog(hW, false); +} + +BOOL CALLBACK ConfigureDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_INITDIALOG: + OnInitConfDialog(hW); + return true; + + case WM_COMMAND: + + switch (LOWORD(wParam)) + { + case IDC_AA_COMBO: + break; + + case IDC_ADV_BTN: + AdvancedDialog(); + return true; + + case IDCANCEL: + EndDialog(hW, true); + return true; + + case IDOK: + OnConfOK(hW); + return true; + } + } + + return false; +} + +void CALLBACK GSconfigure() +{ + DialogBox(hInst, + MAKEINTRESOURCE(IDD_CONFIG2), + GetActiveWindow(), + (DLGPROC)ConfigureDlgProc); + + if (g_nPixelShaderVer == SHADER_REDUCED) conf.bilinear = 0; +} + +s32 CALLBACK GStest() +{ + return 0; +} + +BOOL CALLBACK AboutDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_INITDIALOG: + return true; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDOK: + EndDialog(hW, false); + return true; + } + } + + return false; +} + +void CALLBACK GSabout() +{ + DialogBox(hInst, + MAKEINTRESOURCE(IDD_ABOUT), + GetActiveWindow(), + (DLGPROC)AboutDlgProc); +} + +bool APIENTRY DllMain(HANDLE hModule, // DLL INIT + DWORD dwReason, + LPVOID lpReserved) +{ + hInst = (HINSTANCE)hModule; + return true; // very quick :) +} + +static char *err = "Error Loading Symbol"; +static int errval; + +void *SysLoadLibrary(char *lib) +{ + return LoadLibrary(wxString::FromUTF8(lib)); +} + +void *SysLoadSym(void *lib, char *sym) +{ + void *tmp = GetProcAddress((HINSTANCE)lib, sym); + + if (tmp == NULL) + errval = 1; + else + errval = 0; + + return tmp; +} + +char *SysLibError() +{ + if (errval) { errval = 0; return err; } + + return NULL; +} + +void SysCloseLibrary(void *lib) +{ + FreeLibrary((HINSTANCE)lib); +} + +void SysMessage(const char *fmt, ...) +{ + va_list list; + char tmp[512]; + + va_start(list, fmt); + vsprintf(tmp, fmt, list); + va_end(list); + MessageBox(0, wxString::FromUTF8(tmp), L"ZZOgl-PG Msg", 0); +} diff --git a/plugins/zzogl-pg-cg/opengl/Win32/Win32.h b/plugins/zzogl-pg-cg/opengl/Win32/Win32.h new file mode 100644 index 000000000..acea999c8 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/Win32/Win32.h @@ -0,0 +1,9 @@ +#ifndef __WIN32_H__ +#define __WIN32_H__ + +#include "resrc1.h" +#include "Win32/resource.h" + +BOOL CALLBACK ConfigureDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam); + +#endif /* __WIN32_H__ */ diff --git a/plugins/zzogl-pg-cg/opengl/Win32/aviUtil.h b/plugins/zzogl-pg-cg/opengl/Win32/aviUtil.h new file mode 100644 index 000000000..69be284f4 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/Win32/aviUtil.h @@ -0,0 +1,488 @@ +#ifndef __AVIUTIL_H__ +#define __AVIUTIL_H__ + +#define AVIIF_KEYFRAME 0x00000010L // this frame is a key frame. + +#include +using namespace std; + +#include +#include +#include + +BOOL AVI_Init() +{ + /* first let's make sure we are running on 1.1 */ + WORD wVer = HIWORD(VideoForWindowsVersion()); + if (wVer < 0x010a){ + /* oops, we are too old, blow out of here */ + //MessageBeep(MB_ICONHAND); + MessageBox(NULL, L"Cant't init AVI File - Video for Windows version is to old", L"Error", MB_OK|MB_ICONSTOP); + return FALSE; + } + + AVIFileInit(); + + return TRUE; +} + +BOOL AVI_FileOpenWrite(PAVIFILE * pfile, const char *filename) +{ + HRESULT hr = AVIFileOpen(pfile, // returned file pointer + wxString::FromUTF8(filename), // file name + OF_WRITE | OF_CREATE, // mode to open file with + NULL); // use handler determined + // from file extension.... + if (hr != AVIERR_OK) + return FALSE; + + return TRUE; +} + +DWORD getFOURCC(const char* value) +{ + if(_stricmp(value, "DIB") == 0) + { + return mmioFOURCC(value[0],value[1],value[2],' '); + } + else if((_stricmp(value, "CVID") == 0) + || (_stricmp(value, "IV32") == 0) + || (_stricmp(value, "MSVC") == 0) + || (_stricmp(value, "IV50") == 0)) + { + return mmioFOURCC(value[0],value[1],value[2],value[3]); + } + else + { + return NULL; + } +} + +// Fill in the header for the video stream.... +// The video stream will run in rate ths of a second.... +BOOL AVI_CreateStream(PAVIFILE pfile, PAVISTREAM * ps, int rate, // sample/second + unsigned long buffersize, int rectwidth, int rectheight, + const char* _compressor) +{ + AVISTREAMINFO strhdr; + memset(&strhdr, 0, sizeof(strhdr)); + strhdr.fccType = streamtypeVIDEO;// stream type + strhdr.fccHandler = getFOURCC(_compressor); + //strhdr.fccHandler = 0; // no compression! + //strhdr.fccHandler = mmioFOURCC('D','I','B',' '); // Uncompressed + //strhdr.fccHandler = mmioFOURCC('C','V','I','D'); // Cinpak + //strhdr.fccHandler = mmioFOURCC('I','V','3','2'); // Intel video 3.2 + //strhdr.fccHandler = mmioFOURCC('M','S','V','C'); // Microsoft video 1 + //strhdr.fccHandler = mmioFOURCC('I','V','5','0'); // Intel video 5.0 + //strhdr.dwFlags = AVISTREAMINFO_DISABLED; + //strhdr.dwCaps = + //strhdr.wPriority = + //strhdr.wLanguage = + strhdr.dwScale = 1; + strhdr.dwRate = rate; // rate fps + //strhdr.dwStart = + //strhdr.dwLength = + //strhdr.dwInitialFrames = + strhdr.dwSuggestedBufferSize = buffersize; + strhdr.dwQuality = -1; // use the default + //strhdr.dwSampleSize = + SetRect(&strhdr.rcFrame, 0, 0, // rectangle for stream + (int) rectwidth, + (int) rectheight); + //strhdr.dwEditCount = + //strhdr.dwFormatChangeCount = + //strcpy(strhdr.szName, "Full Frames (Uncompressed)"); + + // And create the stream; + HRESULT hr = AVIFileCreateStream(pfile, // file pointer + ps, // returned stream pointer + &strhdr); // stream header + if (hr != AVIERR_OK) { + return FALSE; + } + + return TRUE; +} + +string getFOURCCVAsString(DWORD value) +{ + string returnValue = ""; + if( value == 0 ) + return returnValue; + + DWORD ch0 = value & 0x000000FF; + returnValue.push_back((char) ch0); + DWORD ch1 = (value & 0x0000FF00)>>8; + returnValue.push_back((char) ch1); + DWORD ch2 = (value & 0x00FF0000)>>16; + returnValue.push_back((char) ch2); + DWORD ch3 = (value & 0xFF000000)>>24; + returnValue.push_back((char) ch3); + + return returnValue; +} + +string dumpAVICOMPRESSOPTIONS(AVICOMPRESSOPTIONS opts) +{ + char tmp[255]; + string returnValue = "Dump of AVICOMPRESSOPTIONS\n"; + + returnValue += "DWORD fccType = streamtype("; returnValue += getFOURCCVAsString(opts.fccType); returnValue += ")\n"; + returnValue += "DWORD fccHandler = "; returnValue += getFOURCCVAsString(opts.fccHandler); returnValue += "\n"; + + _snprintf(tmp, 255, "DWORD dwKeyFrameEvery = %d\n", opts.dwKeyFrameEvery); + returnValue += tmp; + + _snprintf(tmp, 255, "DWORD dwQuality = %d\n", opts.dwQuality); + returnValue += tmp; + + _snprintf(tmp, 255, "DWORD dwBytesPerSecond = %d\n", opts.dwBytesPerSecond); + returnValue += tmp; + + if((opts.dwFlags & AVICOMPRESSF_DATARATE) == AVICOMPRESSF_DATARATE){strcpy(tmp, "DWORD fccType = AVICOMPRESSF_DATARATE\n");} + else if((opts.dwFlags & AVICOMPRESSF_INTERLEAVE) == AVICOMPRESSF_INTERLEAVE){strcpy(tmp, "DWORD fccType = AVICOMPRESSF_INTERLEAVE\n");} + else if((opts.dwFlags & AVICOMPRESSF_KEYFRAMES) == AVICOMPRESSF_KEYFRAMES){strcpy(tmp, "DWORD fccType = AVICOMPRESSF_KEYFRAMES\n");} + else if((opts.dwFlags & AVICOMPRESSF_VALID) == AVICOMPRESSF_VALID){strcpy(tmp, "DWORD fccType = AVICOMPRESSF_VALID\n");} + else {_snprintf(tmp, 255, "DWORD dwFlags = Unknown(%d)\n", opts.dwFlags);} + returnValue += tmp; + + _snprintf(tmp, 255, "LPVOID lpFormat = %d\n", (int)opts.lpFormat); + returnValue += tmp; + + _snprintf(tmp, 255, "DWORD cbFormat = %d\n", opts.cbFormat); + returnValue += tmp; + + _snprintf(tmp, 255, "LPVOID lpParms = %d\n", (int)opts.lpParms); + returnValue += tmp; + + _snprintf(tmp, 255, "DWORD cbParms = %d\n", opts.cbParms); + returnValue += tmp; + + _snprintf(tmp, 255, "DWORD dwInterleaveEvery = %d\n", opts.dwInterleaveEvery); + returnValue += tmp; + + return returnValue; +} + +BOOL AVI_SetOptions(PAVISTREAM * ps, PAVISTREAM * psCompressed, LPBITMAPINFOHEADER lpbi, + const char* _compressor) +{ + + AVICOMPRESSOPTIONS opts; + AVICOMPRESSOPTIONS FAR * aopts[1] = {&opts}; + + memset(&opts, 0, sizeof(opts)); + opts.fccType = streamtypeVIDEO; + opts.fccHandler = getFOURCC(_compressor); + //opts.fccHandler = 0; + //opts.fccHandler = mmioFOURCC('D','I','B',' '); // Uncompressed + //opts.fccHandler = mmioFOURCC('C','V','I','D'); // Cinpak + //opts.fccHandler = mmioFOURCC('I','V','3','2'); // Intel video 3.2 + //opts.fccHandler = mmioFOURCC('M','S','V','C'); // Microsoft video 1 + //opts.fccHandler = mmioFOURCC('I','V','5','0'); // Intel video 5.0 + //opts.dwKeyFrameEvery = 5; + //opts.dwQuality + //opts.dwBytesPerSecond + //opts.dwFlags = AVICOMPRESSF_KEYFRAMES; + //opts.lpFormat + //opts.cbFormat + //opts.lpParms + //opts.cbParms + //opts.dwInterleaveEvery + + /* display the compression options dialog box if specified compressor is unknown */ + if(getFOURCC(_compressor) == NULL) + { + if (!AVISaveOptions(NULL, 0, 1, ps, (LPAVICOMPRESSOPTIONS FAR *) &aopts)) + { + return FALSE; + } + + //printf("%s", dumpAVICOMPRESSOPTIONS(opts)); + //MessageBox(NULL, dumpAVICOMPRESSOPTIONS(opts).c_str(), "AVICOMPRESSOPTIONS", MB_OK); + } + + HRESULT hr = AVIMakeCompressedStream(psCompressed, *ps, &opts, NULL); + if (hr != AVIERR_OK) { + return FALSE; + } + + hr = AVIStreamSetFormat(*psCompressed, 0, + lpbi, // stream format + lpbi->biSize // format size + + lpbi->biClrUsed * sizeof(RGBQUAD) + ); + if (hr != AVIERR_OK) { + return FALSE; + } + + return TRUE; +} + +BOOL AVI_SetText(PAVIFILE pfile, PAVISTREAM psText, char *szText, int width, int height, int TextHeight) +{ + // Fill in the stream header for the text stream.... + AVISTREAMINFO strhdr; + DWORD dwTextFormat; + // The text stream is in 60ths of a second.... + + memset(&strhdr, 0, sizeof(strhdr)); + strhdr.fccType = streamtypeTEXT; + strhdr.fccHandler = mmioFOURCC('D', 'R', 'A', 'W'); + strhdr.dwScale = 1; + strhdr.dwRate = 60; + strhdr.dwSuggestedBufferSize = sizeof(szText); + SetRect(&strhdr.rcFrame, 0, (int) height, + (int) width, (int) height + TextHeight); // #define TEXT_HEIGHT 20 + + // ....and create the stream. + HRESULT hr = AVIFileCreateStream(pfile, &psText, &strhdr); + if (hr != AVIERR_OK) { + return FALSE; + } + + dwTextFormat = sizeof(dwTextFormat); + hr = AVIStreamSetFormat(psText, 0, &dwTextFormat, sizeof(dwTextFormat)); + if (hr != AVIERR_OK) { + return FALSE; + } + + return TRUE; +} + +BOOL AVI_AddFrame(PAVISTREAM psCompressed, int time, LPBITMAPINFOHEADER lpbi) +{ + int ImageSize = lpbi->biSizeImage; + if (ImageSize == 0) + { + if (lpbi->biBitCount == 24) + { + ImageSize = lpbi->biWidth * lpbi->biHeight * 3; + } + } + HRESULT hr = AVIStreamWrite(psCompressed, // stream pointer + time, // time of this frame + 1, // number to write + (LPBYTE) lpbi + // pointer to data + lpbi->biSize + + lpbi->biClrUsed * sizeof(RGBQUAD), + ImageSize, // lpbi->biSizeImage, // size of this frame + AVIIF_KEYFRAME, // flags.... + NULL, + NULL); + if (hr != AVIERR_OK) + { + TCHAR strMsg[255]; + _snwprintf(strMsg, 255, L"Error: AVIStreamWrite, error %d",hr); + MessageBox(NULL, strMsg, L"", MB_OK); + return FALSE; + } + + return TRUE; +} + +BOOL AVI_AddText(PAVISTREAM psText, int time, char *szText) +{ + int iLen = (int)strlen(szText); + + HRESULT hr = AVIStreamWrite(psText, + time, + 1, + szText, + iLen + 1, + AVIIF_KEYFRAME, + NULL, + NULL); + if (hr != AVIERR_OK) + return FALSE; + + return TRUE; +} + +BOOL AVI_CloseStream(PAVISTREAM ps, PAVISTREAM psCompressed, PAVISTREAM psText) +{ + if (ps) + AVIStreamClose(ps); + + if (psCompressed) + AVIStreamClose(psCompressed); + + if (psText) + AVIStreamClose(psText); + + + + return TRUE; +} + +BOOL AVI_CloseFile(PAVIFILE pfile) +{ + if (pfile) + AVIFileClose(pfile); + + return TRUE; +} + +BOOL AVI_Exit() +{ + AVIFileExit(); + + return TRUE; +} + + + + + + + + + + + + + + + + +/* Here are the additional functions we need! */ + + +static PAVIFILE pfile = NULL; +static PAVISTREAM ps = NULL; +static PAVISTREAM psCompressed = NULL; +static int avi_count = 0; + + +// Initialization... +bool START_AVI(const char* file_name) +{ + if(! AVI_Init()) + { + //printf("Error - AVI_Init()\n"); + return false; + } + + if(! AVI_FileOpenWrite(&pfile, file_name)) + { + //printf("Error - AVI_FileOpenWrite()\n"); + return false; + } + + return true; +} + +bool ADD_FRAME_FROM_DIB_TO_AVI(const char* _compressor, int _frameRate, int width, int height, int bits, void* pdata) +{ + if(avi_count == 0) + { + if(! AVI_CreateStream(pfile, &ps, _frameRate, + width*height/bits, + width, + height, _compressor)) + { + //printf("Error - AVI_CreateStream()\n"); + return false; + } + + BITMAPINFOHEADER bi; + memset(&bi, 0, sizeof(bi)); + bi.biSize = sizeof(BITMAPINFOHEADER); + bi.biWidth = width; + bi.biHeight = height; + bi.biPlanes = 1; + bi.biBitCount = bits; + bi.biCompression = BI_RGB; + bi.biSizeImage = width * height * bits /8; + if(! AVI_SetOptions(&ps, &psCompressed, &bi, _compressor)) + { + return false; + } + } + + HRESULT hr = AVIStreamWrite(psCompressed, // stream pointer + avi_count, // time of this frame + 1, // number to write + pdata, + width*height/8, // lpbi->biSizeImage, // size of this frame + AVIIF_KEYFRAME, // flags.... + NULL, + NULL); + if (hr != AVIERR_OK) + { + TCHAR strMsg[255]; + _snwprintf(strMsg, 255, L"Error: AVIStreamWrite, error %d",hr); + MessageBox(NULL, strMsg, L"", MB_OK); + return FALSE; + } + + avi_count++; + return true; +} + +//Now we can add frames +// ie. ADD_FRAME_FROM_DIB_TO_AVI(yourDIB, "CVID", 25); +bool ADD_FRAME_FROM_DIB_TO_AVI(HANDLE dib, const char* _compressor, int _frameRate) +{ + LPBITMAPINFOHEADER lpbi; + if(avi_count == 0) + { + lpbi = (LPBITMAPINFOHEADER)GlobalLock(dib); + if(! AVI_CreateStream(pfile, &ps, _frameRate, + (unsigned long) lpbi->biSizeImage, + (int) lpbi->biWidth, + (int) lpbi->biHeight, _compressor)) + { + //printf("Error - AVI_CreateStream()\n"); + GlobalUnlock(lpbi); + return false; + } + + if(! AVI_SetOptions(&ps, &psCompressed, lpbi, _compressor)) + { + //printf("Error - AVI_SetOptions()\n"); + GlobalUnlock(lpbi); + return false; + } + + GlobalUnlock(lpbi); + } + + lpbi = (LPBITMAPINFOHEADER)GlobalLock(dib); + if(! AVI_AddFrame(psCompressed, avi_count * 1, lpbi)) + { + //printf("Error - AVI_AddFrame()\n"); + GlobalUnlock(lpbi); + return false; + } + + GlobalUnlock(lpbi); + avi_count++; + return true; +} + +// The end... +bool STOP_AVI() +{ + if(! AVI_CloseStream(ps, psCompressed, NULL)) + { + //printf("Error - AVI_CloseStream()\n"); + return false; + } + + if(! AVI_CloseFile(pfile)) + { + //printf("Error - AVI_CloseFile()\n"); + return false; + } + + if(! AVI_Exit()) + { + //printf("Error - AVI_Exit()\n"); + return false; + } + + return true; +} + +#endif diff --git a/plugins/zzogl-pg-cg/opengl/Win32/ps2hw.dat b/plugins/zzogl-pg-cg/opengl/Win32/ps2hw.dat new file mode 100644 index 0000000000000000000000000000000000000000..970b7b17e9906e67a7678211bd4e1e1177a01fbb GIT binary patch literal 108445 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 svnrev.h +// +// This file acts as a template for the automatic SVN revision/version tag. +// It is used by the utility SubWCrev.exe to create an "svnrev.h" file for +// whichever project is being compiled (as indicated by command line options +// passed to SubWCRev.exe during the project's pre-build step). +// +// The SubWCRev.exe utility is part of TortoiseSVN and requires several DLLs +// installed by TortoiseSVN, so it will only be available if you have TortoiseSVN +// installed on your system. If you do not have it installed, a generic template +// is used instead (see svnrev_generic.h). Having TortoiseSVN is handy but not +// necessary. If you do not have it installed, everything will still compile +// fine except without the SVN revision tagged to the application/dll version. +// +// TortoiseSVN can be downloaded from http://tortoisesvn.tigris.org + +#define SVN_REV $WCREV$ +#define SVN_MODS $WCMODS?1:0$ diff --git a/plugins/zzogl-pg-cg/opengl/Win32/tsvnrev/svnrev_unknown.h b/plugins/zzogl-pg-cg/opengl/Win32/tsvnrev/svnrev_unknown.h new file mode 100644 index 000000000..684d5f924 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/Win32/tsvnrev/svnrev_unknown.h @@ -0,0 +1,23 @@ +// svnrev_genric.h --> svnrev.h +// +// This file acts as a placebo for people who do not have TortoiseSVN installed. +// It provides "empty" revision information to the Pcsx2 Playground projects in +// the absence of real revisions derived from the repository being built. +// +// This file does not affect application/dll builds in any significant manner, +// other than the lack of automatic revision tags inserted into the app (which +// is very convenient but hardly necessary). +// +// See svn_template.h for more information on how the process of revision +// templating works. +// +// If you would like to enable automatic revisin tagging, TortoiseSVN can be +// downloaded from http://tortoisesvn.tigris.org + +#define SVN_REV_UNKNOWN + +// The following defines are included so that code will still compile even if it +// doesn't check for the SVN_REV_UNKNOWN define. + +#define SVN_REV 0 +#define SVN_MODS "" diff --git a/plugins/zzogl-pg-cg/opengl/Win32/tsvnrev/updateRevision.cmd b/plugins/zzogl-pg-cg/opengl/Win32/tsvnrev/updateRevision.cmd new file mode 100644 index 000000000..0e192e7a9 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/Win32/tsvnrev/updateRevision.cmd @@ -0,0 +1,8 @@ +@echo off +SubWCRev.exe %1 %2\svnrev_template.h %1\svnrev.h +if not ERRORLEVEL 0 ( + echo Automatic revision update unavailable, using generic template instead. + echo You can safely ignore this message - see svnrev.h for details. + copy /Y %3\svnrev_unknown.h %2\svnrev.h +) +set ERRORLEVEL=0 diff --git a/plugins/zzogl-pg-cg/opengl/Win32/wglext.h b/plugins/zzogl-pg-cg/opengl/Win32/wglext.h new file mode 100644 index 000000000..16c9c7037 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/Win32/wglext.h @@ -0,0 +1,813 @@ +#ifndef __wglext_h_ +#define __wglext_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright (c) 2007 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) +#define WIN32_LEAN_AND_MEAN 1 +#include +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif +#ifndef APIENTRYP +#define APIENTRYP APIENTRY * +#endif +#ifndef GLAPI +#define GLAPI extern +#endif + +/*************************************************************/ + +/* Header file version number */ +/* wglext.h last updated 2009/03/03 */ +/* Current version at http://www.opengl.org/registry/ */ +#define WGL_WGLEXT_VERSION 12 + +#ifndef WGL_ARB_buffer_region +#define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001 +#define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002 +#define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004 +#define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008 +#endif + +#ifndef WGL_ARB_multisample +#define WGL_SAMPLE_BUFFERS_ARB 0x2041 +#define WGL_SAMPLES_ARB 0x2042 +#endif + +#ifndef WGL_ARB_extensions_string +#endif + +#ifndef WGL_ARB_pixel_format +#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 +#define WGL_DRAW_TO_WINDOW_ARB 0x2001 +#define WGL_DRAW_TO_BITMAP_ARB 0x2002 +#define WGL_ACCELERATION_ARB 0x2003 +#define WGL_NEED_PALETTE_ARB 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 +#define WGL_SWAP_METHOD_ARB 0x2007 +#define WGL_NUMBER_OVERLAYS_ARB 0x2008 +#define WGL_NUMBER_UNDERLAYS_ARB 0x2009 +#define WGL_TRANSPARENT_ARB 0x200A +#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 +#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 +#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 +#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A +#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B +#define WGL_SHARE_DEPTH_ARB 0x200C +#define WGL_SHARE_STENCIL_ARB 0x200D +#define WGL_SHARE_ACCUM_ARB 0x200E +#define WGL_SUPPORT_GDI_ARB 0x200F +#define WGL_SUPPORT_OPENGL_ARB 0x2010 +#define WGL_DOUBLE_BUFFER_ARB 0x2011 +#define WGL_STEREO_ARB 0x2012 +#define WGL_PIXEL_TYPE_ARB 0x2013 +#define WGL_COLOR_BITS_ARB 0x2014 +#define WGL_RED_BITS_ARB 0x2015 +#define WGL_RED_SHIFT_ARB 0x2016 +#define WGL_GREEN_BITS_ARB 0x2017 +#define WGL_GREEN_SHIFT_ARB 0x2018 +#define WGL_BLUE_BITS_ARB 0x2019 +#define WGL_BLUE_SHIFT_ARB 0x201A +#define WGL_ALPHA_BITS_ARB 0x201B +#define WGL_ALPHA_SHIFT_ARB 0x201C +#define WGL_ACCUM_BITS_ARB 0x201D +#define WGL_ACCUM_RED_BITS_ARB 0x201E +#define WGL_ACCUM_GREEN_BITS_ARB 0x201F +#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 +#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 +#define WGL_DEPTH_BITS_ARB 0x2022 +#define WGL_STENCIL_BITS_ARB 0x2023 +#define WGL_AUX_BUFFERS_ARB 0x2024 +#define WGL_NO_ACCELERATION_ARB 0x2025 +#define WGL_GENERIC_ACCELERATION_ARB 0x2026 +#define WGL_FULL_ACCELERATION_ARB 0x2027 +#define WGL_SWAP_EXCHANGE_ARB 0x2028 +#define WGL_SWAP_COPY_ARB 0x2029 +#define WGL_SWAP_UNDEFINED_ARB 0x202A +#define WGL_TYPE_RGBA_ARB 0x202B +#define WGL_TYPE_COLORINDEX_ARB 0x202C +#endif + +#ifndef WGL_ARB_make_current_read +#define ERROR_INVALID_PIXEL_TYPE_ARB 0x2043 +#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054 +#endif + +#ifndef WGL_ARB_pbuffer +#define WGL_DRAW_TO_PBUFFER_ARB 0x202D +#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E +#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F +#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030 +#define WGL_PBUFFER_LARGEST_ARB 0x2033 +#define WGL_PBUFFER_WIDTH_ARB 0x2034 +#define WGL_PBUFFER_HEIGHT_ARB 0x2035 +#define WGL_PBUFFER_LOST_ARB 0x2036 +#endif + +#ifndef WGL_ARB_render_texture +#define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070 +#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071 +#define WGL_TEXTURE_FORMAT_ARB 0x2072 +#define WGL_TEXTURE_TARGET_ARB 0x2073 +#define WGL_MIPMAP_TEXTURE_ARB 0x2074 +#define WGL_TEXTURE_RGB_ARB 0x2075 +#define WGL_TEXTURE_RGBA_ARB 0x2076 +#define WGL_NO_TEXTURE_ARB 0x2077 +#define WGL_TEXTURE_CUBE_MAP_ARB 0x2078 +#define WGL_TEXTURE_1D_ARB 0x2079 +#define WGL_TEXTURE_2D_ARB 0x207A +#define WGL_MIPMAP_LEVEL_ARB 0x207B +#define WGL_CUBE_MAP_FACE_ARB 0x207C +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080 +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081 +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082 +#define WGL_FRONT_LEFT_ARB 0x2083 +#define WGL_FRONT_RIGHT_ARB 0x2084 +#define WGL_BACK_LEFT_ARB 0x2085 +#define WGL_BACK_RIGHT_ARB 0x2086 +#define WGL_AUX0_ARB 0x2087 +#define WGL_AUX1_ARB 0x2088 +#define WGL_AUX2_ARB 0x2089 +#define WGL_AUX3_ARB 0x208A +#define WGL_AUX4_ARB 0x208B +#define WGL_AUX5_ARB 0x208C +#define WGL_AUX6_ARB 0x208D +#define WGL_AUX7_ARB 0x208E +#define WGL_AUX8_ARB 0x208F +#define WGL_AUX9_ARB 0x2090 +#endif + +#ifndef WGL_ARB_pixel_format_float +#define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0 +#endif + +#ifndef WGL_ARB_create_context +#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 +#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 +#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 +#define WGL_CONTEXT_FLAGS_ARB 0x2094 +#define ERROR_INVALID_VERSION_ARB 0x2095 +#endif + +#ifndef WGL_EXT_make_current_read +#define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043 +#endif + +#ifndef WGL_EXT_pixel_format +#define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000 +#define WGL_DRAW_TO_WINDOW_EXT 0x2001 +#define WGL_DRAW_TO_BITMAP_EXT 0x2002 +#define WGL_ACCELERATION_EXT 0x2003 +#define WGL_NEED_PALETTE_EXT 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006 +#define WGL_SWAP_METHOD_EXT 0x2007 +#define WGL_NUMBER_OVERLAYS_EXT 0x2008 +#define WGL_NUMBER_UNDERLAYS_EXT 0x2009 +#define WGL_TRANSPARENT_EXT 0x200A +#define WGL_TRANSPARENT_VALUE_EXT 0x200B +#define WGL_SHARE_DEPTH_EXT 0x200C +#define WGL_SHARE_STENCIL_EXT 0x200D +#define WGL_SHARE_ACCUM_EXT 0x200E +#define WGL_SUPPORT_GDI_EXT 0x200F +#define WGL_SUPPORT_OPENGL_EXT 0x2010 +#define WGL_DOUBLE_BUFFER_EXT 0x2011 +#define WGL_STEREO_EXT 0x2012 +#define WGL_PIXEL_TYPE_EXT 0x2013 +#define WGL_COLOR_BITS_EXT 0x2014 +#define WGL_RED_BITS_EXT 0x2015 +#define WGL_RED_SHIFT_EXT 0x2016 +#define WGL_GREEN_BITS_EXT 0x2017 +#define WGL_GREEN_SHIFT_EXT 0x2018 +#define WGL_BLUE_BITS_EXT 0x2019 +#define WGL_BLUE_SHIFT_EXT 0x201A +#define WGL_ALPHA_BITS_EXT 0x201B +#define WGL_ALPHA_SHIFT_EXT 0x201C +#define WGL_ACCUM_BITS_EXT 0x201D +#define WGL_ACCUM_RED_BITS_EXT 0x201E +#define WGL_ACCUM_GREEN_BITS_EXT 0x201F +#define WGL_ACCUM_BLUE_BITS_EXT 0x2020 +#define WGL_ACCUM_ALPHA_BITS_EXT 0x2021 +#define WGL_DEPTH_BITS_EXT 0x2022 +#define WGL_STENCIL_BITS_EXT 0x2023 +#define WGL_AUX_BUFFERS_EXT 0x2024 +#define WGL_NO_ACCELERATION_EXT 0x2025 +#define WGL_GENERIC_ACCELERATION_EXT 0x2026 +#define WGL_FULL_ACCELERATION_EXT 0x2027 +#define WGL_SWAP_EXCHANGE_EXT 0x2028 +#define WGL_SWAP_COPY_EXT 0x2029 +#define WGL_SWAP_UNDEFINED_EXT 0x202A +#define WGL_TYPE_RGBA_EXT 0x202B +#define WGL_TYPE_COLORINDEX_EXT 0x202C +#endif + +#ifndef WGL_EXT_pbuffer +#define WGL_DRAW_TO_PBUFFER_EXT 0x202D +#define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E +#define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F +#define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030 +#define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031 +#define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032 +#define WGL_PBUFFER_LARGEST_EXT 0x2033 +#define WGL_PBUFFER_WIDTH_EXT 0x2034 +#define WGL_PBUFFER_HEIGHT_EXT 0x2035 +#endif + +#ifndef WGL_EXT_depth_float +#define WGL_DEPTH_FLOAT_EXT 0x2040 +#endif + +#ifndef WGL_3DFX_multisample +#define WGL_SAMPLE_BUFFERS_3DFX 0x2060 +#define WGL_SAMPLES_3DFX 0x2061 +#endif + +#ifndef WGL_EXT_multisample +#define WGL_SAMPLE_BUFFERS_EXT 0x2041 +#define WGL_SAMPLES_EXT 0x2042 +#endif + +#ifndef WGL_I3D_digital_video_control +#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050 +#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051 +#define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052 +#define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053 +#endif + +#ifndef WGL_I3D_gamma +#define WGL_GAMMA_TABLE_SIZE_I3D 0x204E +#define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F +#endif + +#ifndef WGL_I3D_genlock +#define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044 +#define WGL_GENLOCK_SOURCE_EXTENAL_SYNC_I3D 0x2045 +#define WGL_GENLOCK_SOURCE_EXTENAL_FIELD_I3D 0x2046 +#define WGL_GENLOCK_SOURCE_EXTENAL_TTL_I3D 0x2047 +#define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048 +#define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049 +#define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A +#define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B +#define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C +#endif + +#ifndef WGL_I3D_image_buffer +#define WGL_IMAGE_BUFFER_MIN_ACCESS_I3D 0x00000001 +#define WGL_IMAGE_BUFFER_LOCK_I3D 0x00000002 +#endif + +#ifndef WGL_I3D_swap_frame_lock +#endif + +#ifndef WGL_NV_render_depth_texture +#define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4 +#define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5 +#define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6 +#define WGL_DEPTH_COMPONENT_NV 0x20A7 +#endif + +#ifndef WGL_NV_render_texture_rectangle +#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1 +#define WGL_TEXTURE_RECTANGLE_NV 0x20A2 +#endif + +#ifndef WGL_ATI_pixel_format_float +#define WGL_TYPE_RGBA_FLOAT_ATI 0x21A0 +#endif + +#ifndef WGL_NV_float_buffer +#define WGL_FLOAT_COMPONENTS_NV 0x20B0 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4 +#define WGL_TEXTURE_FLOAT_R_NV 0x20B5 +#define WGL_TEXTURE_FLOAT_RG_NV 0x20B6 +#define WGL_TEXTURE_FLOAT_RGB_NV 0x20B7 +#define WGL_TEXTURE_FLOAT_RGBA_NV 0x20B8 +#endif + +#ifndef WGL_3DL_stereo_control +#define WGL_STEREO_EMITTER_ENABLE_3DL 0x2055 +#define WGL_STEREO_EMITTER_DISABLE_3DL 0x2056 +#define WGL_STEREO_POLARITY_NORMAL_3DL 0x2057 +#define WGL_STEREO_POLARITY_INVERT_3DL 0x2058 +#endif + +#ifndef WGL_EXT_pixel_format_packed_float +#define WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT 0x20A8 +#endif + +#ifndef WGL_EXT_framebuffer_sRGB +#define WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20A9 +#endif + +#ifndef WGL_NV_present_video +#define WGL_NUM_VIDEO_SLOTS_NV 0x20F0 +#endif + +#ifndef WGL_NV_video_out +#define WGL_BIND_TO_VIDEO_RGB_NV 0x20C0 +#define WGL_BIND_TO_VIDEO_RGBA_NV 0x20C1 +#define WGL_BIND_TO_VIDEO_RGB_AND_DEPTH_NV 0x20C2 +#define WGL_VIDEO_OUT_COLOR_NV 0x20C3 +#define WGL_VIDEO_OUT_ALPHA_NV 0x20C4 +#define WGL_VIDEO_OUT_DEPTH_NV 0x20C5 +#define WGL_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6 +#define WGL_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7 +#define WGL_VIDEO_OUT_FRAME 0x20C8 +#define WGL_VIDEO_OUT_FIELD_1 0x20C9 +#define WGL_VIDEO_OUT_FIELD_2 0x20CA +#define WGL_VIDEO_OUT_STACKED_FIELDS_1_2 0x20CB +#define WGL_VIDEO_OUT_STACKED_FIELDS_2_1 0x20CC +#endif + +#ifndef WGL_NV_swap_group +#endif + +#ifndef WGL_NV_gpu_affinity +#define WGL_ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV 0x20D0 +#define WGL_ERROR_MISSING_AFFINITY_MASK_NV 0x20D1 +#endif + +#ifndef WGL_AMD_gpu_association +#define WGL_GPU_VENDOR_AMD 0x1F00 +#define WGL_GPU_RENDERER_STRING_AMD 0x1F01 +#define WGL_GPU_OPENGL_VERSION_STRING_AMD 0x1F02 +#define WGL_GPU_FASTEST_TARGET_GPUS_AMD 0x21A2 +#define WGL_GPU_RAM_AMD 0x21A3 +#define WGL_GPU_CLOCK_AMD 0x21A4 +#define WGL_GPU_NUM_PIPES_AMD 0x21A5 +#define WGL_GPU_NUM_SIMD_AMD 0x21A6 +#define WGL_GPU_NUM_RB_AMD 0x21A7 +#define WGL_GPU_NUM_SPI_AMD 0x21A8 +#endif + + +/*************************************************************/ + +#ifndef WGL_ARB_pbuffer +DECLARE_HANDLE(HPBUFFERARB); +#endif +#ifndef WGL_EXT_pbuffer +DECLARE_HANDLE(HPBUFFEREXT); +#endif +#ifndef WGL_NV_present_video +DECLARE_HANDLE(HVIDEOOUTPUTDEVICENV); +#endif +#ifndef WGL_NV_video_out +DECLARE_HANDLE(HPVIDEODEV); +#endif +#ifndef WGL_NV_gpu_affinity +DECLARE_HANDLE(HPGPUNV); +DECLARE_HANDLE(HGPUNV); + +typedef struct _GPU_DEVICE { + DWORD cb; + CHAR DeviceName[32]; + CHAR DeviceString[128]; + DWORD Flags; + RECT rcVirtualScreen; +} GPU_DEVICE, *PGPU_DEVICE; +#endif + +#ifndef WGL_ARB_buffer_region +#define WGL_ARB_buffer_region 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern HANDLE WINAPI wglCreateBufferRegionARB (HDC, int, UINT); +extern VOID WINAPI wglDeleteBufferRegionARB (HANDLE); +extern BOOL WINAPI wglSaveBufferRegionARB (HANDLE, int, int, int, int); +extern BOOL WINAPI wglRestoreBufferRegionARB (HANDLE, int, int, int, int, int, int); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType); +typedef VOID (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion); +typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height); +typedef BOOL (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc); +#endif + +#ifndef WGL_ARB_multisample +#define WGL_ARB_multisample 1 +#endif + +#ifndef WGL_ARB_extensions_string +#define WGL_ARB_extensions_string 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern const char * WINAPI wglGetExtensionsStringARB (HDC); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc); +#endif + +#ifndef WGL_ARB_pixel_format +#define WGL_ARB_pixel_format 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetPixelFormatAttribivARB (HDC, int, int, UINT, const int *, int *); +extern BOOL WINAPI wglGetPixelFormatAttribfvARB (HDC, int, int, UINT, const int *, FLOAT *); +extern BOOL WINAPI wglChoosePixelFormatARB (HDC, const int *, const FLOAT *, UINT, int *, UINT *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues); +typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +#endif + +#ifndef WGL_ARB_make_current_read +#define WGL_ARB_make_current_read 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglMakeContextCurrentARB (HDC, HDC, HGLRC); +extern HDC WINAPI wglGetCurrentReadDCARB (void); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); +typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (void); +#endif + +#ifndef WGL_ARB_pbuffer +#define WGL_ARB_pbuffer 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern HPBUFFERARB WINAPI wglCreatePbufferARB (HDC, int, int, int, const int *); +extern HDC WINAPI wglGetPbufferDCARB (HPBUFFERARB); +extern int WINAPI wglReleasePbufferDCARB (HPBUFFERARB, HDC); +extern BOOL WINAPI wglDestroyPbufferARB (HPBUFFERARB); +extern BOOL WINAPI wglQueryPbufferARB (HPBUFFERARB, int, int *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); +typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer); +typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC); +typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer); +typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue); +#endif + +#ifndef WGL_ARB_render_texture +#define WGL_ARB_render_texture 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglBindTexImageARB (HPBUFFERARB, int); +extern BOOL WINAPI wglReleaseTexImageARB (HPBUFFERARB, int); +extern BOOL WINAPI wglSetPbufferAttribARB (HPBUFFERARB, const int *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); +typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); +typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int *piAttribList); +#endif + +#ifndef WGL_ARB_pixel_format_float +#define WGL_ARB_pixel_format_float 1 +#endif + +#ifndef WGL_ARB_create_context +#define WGL_ARB_create_context 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern HGLRC WINAPI wglCreateContextAttribsARB (HDC, HGLRC, const int *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int *attribList); +#endif + +#ifndef WGL_EXT_display_color_table +#define WGL_EXT_display_color_table 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern GLboolean WINAPI wglCreateDisplayColorTableEXT (GLushort); +extern GLboolean WINAPI wglLoadDisplayColorTableEXT (const GLushort *, GLuint); +extern GLboolean WINAPI wglBindDisplayColorTableEXT (GLushort); +extern VOID WINAPI wglDestroyDisplayColorTableEXT (GLushort); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef GLboolean (WINAPI * PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) (GLushort id); +typedef GLboolean (WINAPI * PFNWGLLOADDISPLAYCOLORTABLEEXTPROC) (const GLushort *table, GLuint length); +typedef GLboolean (WINAPI * PFNWGLBINDDISPLAYCOLORTABLEEXTPROC) (GLushort id); +typedef VOID (WINAPI * PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) (GLushort id); +#endif + +#ifndef WGL_EXT_extensions_string +#define WGL_EXT_extensions_string 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern const char * WINAPI wglGetExtensionsStringEXT (void); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void); +#endif + +#ifndef WGL_EXT_make_current_read +#define WGL_EXT_make_current_read 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglMakeContextCurrentEXT (HDC, HDC, HGLRC); +extern HDC WINAPI wglGetCurrentReadDCEXT (void); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTEXTPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); +typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCEXTPROC) (void); +#endif + +#ifndef WGL_EXT_pbuffer +#define WGL_EXT_pbuffer 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern HPBUFFEREXT WINAPI wglCreatePbufferEXT (HDC, int, int, int, const int *); +extern HDC WINAPI wglGetPbufferDCEXT (HPBUFFEREXT); +extern int WINAPI wglReleasePbufferDCEXT (HPBUFFEREXT, HDC); +extern BOOL WINAPI wglDestroyPbufferEXT (HPBUFFEREXT); +extern BOOL WINAPI wglQueryPbufferEXT (HPBUFFEREXT, int, int *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef HPBUFFEREXT (WINAPI * PFNWGLCREATEPBUFFEREXTPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); +typedef HDC (WINAPI * PFNWGLGETPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer); +typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer, HDC hDC); +typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer); +typedef BOOL (WINAPI * PFNWGLQUERYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue); +#endif + +#ifndef WGL_EXT_pixel_format +#define WGL_EXT_pixel_format 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetPixelFormatAttribivEXT (HDC, int, int, UINT, int *, int *); +extern BOOL WINAPI wglGetPixelFormatAttribfvEXT (HDC, int, int, UINT, int *, FLOAT *); +extern BOOL WINAPI wglChoosePixelFormatEXT (HDC, const int *, const FLOAT *, UINT, int *, UINT *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues); +typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATEXTPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +#endif + +#ifndef WGL_EXT_swap_control +#define WGL_EXT_swap_control 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglSwapIntervalEXT (int); +extern int WINAPI wglGetSwapIntervalEXT (void); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval); +typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void); +#endif + +#ifndef WGL_EXT_depth_float +#define WGL_EXT_depth_float 1 +#endif + +#ifndef WGL_NV_vertex_array_range +#define WGL_NV_vertex_array_range 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern void* WINAPI wglAllocateMemoryNV (GLsizei, GLfloat, GLfloat, GLfloat); +extern void WINAPI wglFreeMemoryNV (void *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef void* (WINAPI * PFNWGLALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority); +typedef void (WINAPI * PFNWGLFREEMEMORYNVPROC) (void *pointer); +#endif + +#ifndef WGL_3DFX_multisample +#define WGL_3DFX_multisample 1 +#endif + +#ifndef WGL_EXT_multisample +#define WGL_EXT_multisample 1 +#endif + +#ifndef WGL_OML_sync_control +#define WGL_OML_sync_control 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetSyncValuesOML (HDC, INT64 *, INT64 *, INT64 *); +extern BOOL WINAPI wglGetMscRateOML (HDC, INT32 *, INT32 *); +extern INT64 WINAPI wglSwapBuffersMscOML (HDC, INT64, INT64, INT64); +extern INT64 WINAPI wglSwapLayerBuffersMscOML (HDC, int, INT64, INT64, INT64); +extern BOOL WINAPI wglWaitForMscOML (HDC, INT64, INT64, INT64, INT64 *, INT64 *, INT64 *); +extern BOOL WINAPI wglWaitForSbcOML (HDC, INT64, INT64 *, INT64 *, INT64 *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETSYNCVALUESOMLPROC) (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc); +typedef BOOL (WINAPI * PFNWGLGETMSCRATEOMLPROC) (HDC hdc, INT32 *numerator, INT32 *denominator); +typedef INT64 (WINAPI * PFNWGLSWAPBUFFERSMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder); +typedef INT64 (WINAPI * PFNWGLSWAPLAYERBUFFERSMSCOMLPROC) (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder); +typedef BOOL (WINAPI * PFNWGLWAITFORMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc); +typedef BOOL (WINAPI * PFNWGLWAITFORSBCOMLPROC) (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc); +#endif + +#ifndef WGL_I3D_digital_video_control +#define WGL_I3D_digital_video_control 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetDigitalVideoParametersI3D (HDC, int, int *); +extern BOOL WINAPI wglSetDigitalVideoParametersI3D (HDC, int, const int *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int *piValue); +typedef BOOL (WINAPI * PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int *piValue); +#endif + +#ifndef WGL_I3D_gamma +#define WGL_I3D_gamma 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetGammaTableParametersI3D (HDC, int, int *); +extern BOOL WINAPI wglSetGammaTableParametersI3D (HDC, int, const int *); +extern BOOL WINAPI wglGetGammaTableI3D (HDC, int, USHORT *, USHORT *, USHORT *); +extern BOOL WINAPI wglSetGammaTableI3D (HDC, int, const USHORT *, const USHORT *, const USHORT *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int *piValue); +typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int *piValue); +typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, USHORT *puRed, USHORT *puGreen, USHORT *puBlue); +typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, const USHORT *puRed, const USHORT *puGreen, const USHORT *puBlue); +#endif + +#ifndef WGL_I3D_genlock +#define WGL_I3D_genlock 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglEnableGenlockI3D (HDC); +extern BOOL WINAPI wglDisableGenlockI3D (HDC); +extern BOOL WINAPI wglIsEnabledGenlockI3D (HDC, BOOL *); +extern BOOL WINAPI wglGenlockSourceI3D (HDC, UINT); +extern BOOL WINAPI wglGetGenlockSourceI3D (HDC, UINT *); +extern BOOL WINAPI wglGenlockSourceEdgeI3D (HDC, UINT); +extern BOOL WINAPI wglGetGenlockSourceEdgeI3D (HDC, UINT *); +extern BOOL WINAPI wglGenlockSampleRateI3D (HDC, UINT); +extern BOOL WINAPI wglGetGenlockSampleRateI3D (HDC, UINT *); +extern BOOL WINAPI wglGenlockSourceDelayI3D (HDC, UINT); +extern BOOL WINAPI wglGetGenlockSourceDelayI3D (HDC, UINT *); +extern BOOL WINAPI wglQueryGenlockMaxSourceDelayI3D (HDC, UINT *, UINT *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLENABLEGENLOCKI3DPROC) (HDC hDC); +typedef BOOL (WINAPI * PFNWGLDISABLEGENLOCKI3DPROC) (HDC hDC); +typedef BOOL (WINAPI * PFNWGLISENABLEDGENLOCKI3DPROC) (HDC hDC, BOOL *pFlag); +typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEI3DPROC) (HDC hDC, UINT uSource); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEI3DPROC) (HDC hDC, UINT *uSource); +typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT uEdge); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT *uEdge); +typedef BOOL (WINAPI * PFNWGLGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT uRate); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT *uRate); +typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT uDelay); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT *uDelay); +typedef BOOL (WINAPI * PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC) (HDC hDC, UINT *uMaxLineDelay, UINT *uMaxPixelDelay); +#endif + +#ifndef WGL_I3D_image_buffer +#define WGL_I3D_image_buffer 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern LPVOID WINAPI wglCreateImageBufferI3D (HDC, DWORD, UINT); +extern BOOL WINAPI wglDestroyImageBufferI3D (HDC, LPVOID); +extern BOOL WINAPI wglAssociateImageBufferEventsI3D (HDC, const HANDLE *, const LPVOID *, const DWORD *, UINT); +extern BOOL WINAPI wglReleaseImageBufferEventsI3D (HDC, const LPVOID *, UINT); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef LPVOID (WINAPI * PFNWGLCREATEIMAGEBUFFERI3DPROC) (HDC hDC, DWORD dwSize, UINT uFlags); +typedef BOOL (WINAPI * PFNWGLDESTROYIMAGEBUFFERI3DPROC) (HDC hDC, LPVOID pAddress); +typedef BOOL (WINAPI * PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const HANDLE *pEvent, const LPVOID *pAddress, const DWORD *pSize, UINT count); +typedef BOOL (WINAPI * PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const LPVOID *pAddress, UINT count); +#endif + +#ifndef WGL_I3D_swap_frame_lock +#define WGL_I3D_swap_frame_lock 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglEnableFrameLockI3D (void); +extern BOOL WINAPI wglDisableFrameLockI3D (void); +extern BOOL WINAPI wglIsEnabledFrameLockI3D (BOOL *); +extern BOOL WINAPI wglQueryFrameLockMasterI3D (BOOL *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLENABLEFRAMELOCKI3DPROC) (void); +typedef BOOL (WINAPI * PFNWGLDISABLEFRAMELOCKI3DPROC) (void); +typedef BOOL (WINAPI * PFNWGLISENABLEDFRAMELOCKI3DPROC) (BOOL *pFlag); +typedef BOOL (WINAPI * PFNWGLQUERYFRAMELOCKMASTERI3DPROC) (BOOL *pFlag); +#endif + +#ifndef WGL_I3D_swap_frame_usage +#define WGL_I3D_swap_frame_usage 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetFrameUsageI3D (float *); +extern BOOL WINAPI wglBeginFrameTrackingI3D (void); +extern BOOL WINAPI wglEndFrameTrackingI3D (void); +extern BOOL WINAPI wglQueryFrameTrackingI3D (DWORD *, DWORD *, float *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETFRAMEUSAGEI3DPROC) (float *pUsage); +typedef BOOL (WINAPI * PFNWGLBEGINFRAMETRACKINGI3DPROC) (void); +typedef BOOL (WINAPI * PFNWGLENDFRAMETRACKINGI3DPROC) (void); +typedef BOOL (WINAPI * PFNWGLQUERYFRAMETRACKINGI3DPROC) (DWORD *pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage); +#endif + +#ifndef WGL_ATI_pixel_format_float +#define WGL_ATI_pixel_format_float 1 +#endif + +#ifndef WGL_NV_float_buffer +#define WGL_NV_float_buffer 1 +#endif + +#ifndef WGL_EXT_pixel_format_packed_float +#define WGL_EXT_pixel_format_packed_float 1 +#endif + +#ifndef WGL_EXT_framebuffer_sRGB +#define WGL_EXT_framebuffer_sRGB 1 +#endif + +#ifndef WGL_NV_present_video +#define WGL_NV_present_video 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern int WINAPI wglEnumerateVideoDevicesNV (HDC, HVIDEOOUTPUTDEVICENV *); +extern BOOL WINAPI wglBindVideoDeviceNV (HDC, unsigned int, HVIDEOOUTPUTDEVICENV, const int *); +extern BOOL WINAPI wglQueryCurrentContextNV (int, int *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef int (WINAPI * PFNWGLENUMERATEVIDEODEVICESNVPROC) (HDC hDC, HVIDEOOUTPUTDEVICENV *phDeviceList); +typedef BOOL (WINAPI * PFNWGLBINDVIDEODEVICENVPROC) (HDC hDC, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int *piAttribList); +typedef BOOL (WINAPI * PFNWGLQUERYCURRENTCONTEXTNVPROC) (int iAttribute, int *piValue); +#endif + +#ifndef WGL_NV_video_out +#define WGL_NV_video_out 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetVideoDeviceNV (HDC, int, HPVIDEODEV *); +extern BOOL WINAPI wglReleaseVideoDeviceNV (HPVIDEODEV); +extern BOOL WINAPI wglBindVideoImageNV (HPVIDEODEV, HPBUFFERARB, int); +extern BOOL WINAPI wglReleaseVideoImageNV (HPBUFFERARB, int); +extern BOOL WINAPI wglSendPbufferToVideoNV (HPBUFFERARB, int, unsigned long *, BOOL); +extern BOOL WINAPI wglGetVideoInfoNV (HPVIDEODEV, unsigned long *, unsigned long *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETVIDEODEVICENVPROC) (HDC hDC, int numDevices, HPVIDEODEV *hVideoDevice); +typedef BOOL (WINAPI * PFNWGLRELEASEVIDEODEVICENVPROC) (HPVIDEODEV hVideoDevice); +typedef BOOL (WINAPI * PFNWGLBINDVIDEOIMAGENVPROC) (HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer); +typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOIMAGENVPROC) (HPBUFFERARB hPbuffer, int iVideoBuffer); +typedef BOOL (WINAPI * PFNWGLSENDPBUFFERTOVIDEONVPROC) (HPBUFFERARB hPbuffer, int iBufferType, unsigned long *pulCounterPbuffer, BOOL bBlock); +typedef BOOL (WINAPI * PFNWGLGETVIDEOINFONVPROC) (HPVIDEODEV hpVideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo); +#endif + +#ifndef WGL_NV_swap_group +#define WGL_NV_swap_group 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglJoinSwapGroupNV (HDC, GLuint); +extern BOOL WINAPI wglBindSwapBarrierNV (GLuint, GLuint); +extern BOOL WINAPI wglQuerySwapGroupNV (HDC, GLuint *, GLuint *); +extern BOOL WINAPI wglQueryMaxSwapGroupsNV (HDC, GLuint *, GLuint *); +extern BOOL WINAPI wglQueryFrameCountNV (HDC, GLuint *); +extern BOOL WINAPI wglResetFrameCountNV (HDC); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLJOINSWAPGROUPNVPROC) (HDC hDC, GLuint group); +typedef BOOL (WINAPI * PFNWGLBINDSWAPBARRIERNVPROC) (GLuint group, GLuint barrier); +typedef BOOL (WINAPI * PFNWGLQUERYSWAPGROUPNVPROC) (HDC hDC, GLuint *group, GLuint *barrier); +typedef BOOL (WINAPI * PFNWGLQUERYMAXSWAPGROUPSNVPROC) (HDC hDC, GLuint *maxGroups, GLuint *maxBarriers); +typedef BOOL (WINAPI * PFNWGLQUERYFRAMECOUNTNVPROC) (HDC hDC, GLuint *count); +typedef BOOL (WINAPI * PFNWGLRESETFRAMECOUNTNVPROC) (HDC hDC); +#endif + +#ifndef WGL_NV_gpu_affinity +#define WGL_NV_gpu_affinity 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglEnumGpusNV (UINT, HGPUNV *); +extern BOOL WINAPI wglEnumGpuDevicesNV (HGPUNV, UINT, PGPU_DEVICE); +extern HDC WINAPI wglCreateAffinityDCNV (const HGPUNV *); +extern BOOL WINAPI wglEnumGpusFromAffinityDCNV (HDC, UINT, HGPUNV *); +extern BOOL WINAPI wglDeleteDCNV (HDC); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLENUMGPUSNVPROC) (UINT iGpuIndex, HGPUNV *phGpu); +typedef BOOL (WINAPI * PFNWGLENUMGPUDEVICESNVPROC) (HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice); +typedef HDC (WINAPI * PFNWGLCREATEAFFINITYDCNVPROC) (const HGPUNV *phGpuList); +typedef BOOL (WINAPI * PFNWGLENUMGPUSFROMAFFINITYDCNVPROC) (HDC hAffinityDC, UINT iGpuIndex, HGPUNV *hGpu); +typedef BOOL (WINAPI * PFNWGLDELETEDCNVPROC) (HDC hdc); +#endif + +#ifndef WGL_AMD_gpu_association +#define WGL_AMD_gpu_association 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern UINT WINAPI wglGetGPUIDsAMD (UINT, UINT *); +extern INT WINAPI wglGetGPUInfoAMD (UINT, int, GLenum, UINT, void *); +extern UINT WINAPI wglGetContextGPUIDAMD (HGLRC); +extern HGLRC WINAPI wglCreateAssociatedContextAMD (UINT); +extern HGLRC WINAPI wglCreateAssociatedContextAttribsAMD (UINT, HGLRC, const int *); +extern BOOL WINAPI wglDeleteAssociatedContextAMD (HGLRC); +extern BOOL WINAPI wglMakeAssociatedContextCurrentAMD (HGLRC); +extern HGLRC WINAPI wglGetCurrentAssociatedContextAMD (void); +extern VOID WINAPI wglBlitContextFramebufferAMD (HGLRC, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef UINT (WINAPI * PFNWGLGETGPUIDSAMDPROC) (UINT maxCount, UINT *ids); +typedef INT (WINAPI * PFNWGLGETGPUINFOAMDPROC) (UINT id, int property, GLenum dataType, UINT size, void *data); +typedef UINT (WINAPI * PFNWGLGETCONTEXTGPUIDAMDPROC) (HGLRC hglrc); +typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC) (UINT id); +typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC) (UINT id, HGLRC hShareContext, const int *attribList); +typedef BOOL (WINAPI * PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC) (HGLRC hglrc); +typedef BOOL (WINAPI * PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC) (HGLRC hglrc); +typedef HGLRC (WINAPI * PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC) (void); +typedef VOID (WINAPI * PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC) (HGLRC dstCtx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +#endif + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/plugins/zzogl-pg-cg/opengl/Win32/zerogs.bmp b/plugins/zzogl-pg-cg/opengl/Win32/zerogs.bmp new file mode 100644 index 0000000000000000000000000000000000000000..5cf24cf9e09d94de6bb9bc1c0099f1d3d6946632 GIT binary patch literal 921654 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 z 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 + + + + Debug + Win32 + + + Devel + Win32 + + + Release + Win32 + + + + ZZOgl + {2D4E85B2-F47F-4D65-B091-701E5C031DAC} + ZZogl + + + + DynamicLibrary + false + Unicode + true + + + DynamicLibrary + Unicode + + + DynamicLibrary + false + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(ProjectName)-dev + $(SolutionDir)bin\$(PcsxSubsection)\ + $(PlatformName)\$(Configuration)\ + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + + + + + $(ProjectRootDir)\;$(ProjectRootDir)\ZeroGSShaders\;$(ProjectRootDir)\Win32;$(SvnRootDir)\3rdparty\libjpeg;$(SvnRootDir)\3rdparty\zlib;%(AdditionalIncludeDirectories) + NDEBUG;_USRDLL;__i386__;ZEROGS_DEVBUILD;%(PreprocessorDefinitions) + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + winmm.lib;Vfw32.lib;cg.lib;cgGL.lib;opengl32.lib;Comctl32.lib;rpcrt4.lib;%(AdditionalDependencies) + $(OutDir)$(TargetName)$(TargetExt) + ..\;%(AdditionalLibraryDirectories) + .\zerogs.def + + + + + $(ProjectRootDir)\;$(ProjectRootDir)\ZeroGSShaders\;$(ProjectRootDir)\Win32;$(SvnRootDir)\3rdparty\libjpeg;$(SvnRootDir)\3rdparty\zlib;%(AdditionalIncludeDirectories) + _USRDLL;ZEROGS_DEVBUILD;_DEBUG;__i386__;%(PreprocessorDefinitions) + + + winmm.lib;Vfw32.lib;cg.lib;cgGL.lib;opengl32.lib;Comctl32.lib;rpcrt4.lib;%(AdditionalDependencies) + $(OutDir)$(TargetName)$(TargetExt) + ..\;%(AdditionalLibraryDirectories) + %(IgnoreSpecificDefaultLibraries) + .\zerogs.def + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + + + + + $(ProjectRootDir)\;$(ProjectRootDir)\ZeroGSShaders\;$(ProjectRootDir)\Win32;$(SvnRootDir)\3rdparty\libjpeg;$(SvnRootDir)\3rdparty\zlib;%(AdditionalIncludeDirectories) + NDEBUG;_USRDLL;__i386__;ZEROGS_SSE2;RELEASE_TO_PUBLIC;%(PreprocessorDefinitions) + + + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + winmm.lib;Vfw32.lib;cg.lib;cgGL.lib;opengl32.lib;Comctl32.lib;rpcrt4.lib;%(AdditionalDependencies) + $(OutDir)$(TargetName)$(TargetExt) + ..\;%(AdditionalLibraryDirectories) + .\zerogs.def + + + + + + + + + + + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ml /nologo /c /Fo"$(IntDir)%(Filename).obj" "%(FullPath)" + + $(IntDir)%(Filename).obj;%(Outputs) + ml /nologo /c /Fo"$(IntDir)%(Filename).obj" "%(FullPath)" + + $(IntDir)%(Filename).obj;%(Outputs) + ml /nologo /c /Fo"$(IntDir)%(Filename).obj" "%(FullPath)" + + $(IntDir)%(Filename).obj;%(Outputs) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {bc236261-77e8-4567-8d09-45cd02965eb6} + true + false + false + true + false + + + {26511268-2902-4997-8421-ecd7055f9e28} + true + false + false + true + false + + + {7e9b2be7-cec3-4f14-847b-0ab8d562fb86} + true + false + false + true + false + + + {48ad7e0a-25b1-4974-a1e3-03f8c438d34f} + true + false + false + true + false + + + {0318ba30-ef48-441a-9e10-dc85efae39f0} + true + false + false + true + false + + + {2f6c0388-20cb-4242-9f6c-a6ebb6a83f47} + true + false + false + true + false + + + {4639972e-424e-4e13-8b07-ca403c481346} + true + false + false + true + false + + + + + + diff --git a/plugins/zzogl-pg-cg/opengl/Win32/zerogsogl.vcxproj.filters b/plugins/zzogl-pg-cg/opengl/Win32/zerogsogl.vcxproj.filters new file mode 100644 index 000000000..0a0899e27 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/Win32/zerogsogl.vcxproj.filters @@ -0,0 +1,217 @@ + + + + + {db5b3cda-2af3-451d-95a6-1ecd6410acb3} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {609d2fdc-53bd-42af-90ff-793a1107f003} + h;hpp;hxx;hm;inl + + + {a2158e1c-a894-441e-ab9e-e2361e55f009} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + {4755b02f-755a-491e-b851-acab63a59d75} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Source Files + + + Resource Files + + + Resource Files + + + Docs + + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Resource Files + + + + + Source Files + + + diff --git a/plugins/zzogl-pg-cg/opengl/Win32/zerogsogl_2008.sln b/plugins/zzogl-pg-cg/opengl/Win32/zerogsogl_2008.sln new file mode 100644 index 000000000..3e19461ac --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/Win32/zerogsogl_2008.sln @@ -0,0 +1,42 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual C++ Express 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZZOgl", "zerogsogl_2008.vcproj", "{2D4E85B2-F47F-4D65-B091-701E5C031DAC}" + ProjectSection(ProjectDependencies) = postProject + {2F6C0388-20CB-4242-9F6C-A6EBB6A83F47} = {2F6C0388-20CB-4242-9F6C-A6EBB6A83F47} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Utilities", "..\..\..\..\common\build\Utilities\utilities.vcproj", "{4639972E-424E-4E13-8B07-CA403C481346}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "..\..\..\..\3rdparty\zlib\zlib.vcproj", "{2F6C0388-20CB-4242-9F6C-A6EBB6A83F47}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Devel|Win32 = Devel|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Debug|Win32.ActiveCfg = Debug|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Debug|Win32.Build.0 = Debug|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Devel|Win32.ActiveCfg = Devel|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Devel|Win32.Build.0 = Devel|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release|Win32.ActiveCfg = Release|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release|Win32.Build.0 = Release|Win32 + {4639972E-424E-4E13-8B07-CA403C481346}.Debug|Win32.ActiveCfg = Debug|Win32 + {4639972E-424E-4E13-8B07-CA403C481346}.Debug|Win32.Build.0 = Debug|Win32 + {4639972E-424E-4E13-8B07-CA403C481346}.Devel|Win32.ActiveCfg = Devel|Win32 + {4639972E-424E-4E13-8B07-CA403C481346}.Devel|Win32.Build.0 = Devel|Win32 + {4639972E-424E-4E13-8B07-CA403C481346}.Release|Win32.ActiveCfg = Release|Win32 + {4639972E-424E-4E13-8B07-CA403C481346}.Release|Win32.Build.0 = Release|Win32 + {2F6C0388-20CB-4242-9F6C-A6EBB6A83F47}.Debug|Win32.ActiveCfg = Debug|Win32 + {2F6C0388-20CB-4242-9F6C-A6EBB6A83F47}.Debug|Win32.Build.0 = Debug|Win32 + {2F6C0388-20CB-4242-9F6C-A6EBB6A83F47}.Devel|Win32.ActiveCfg = Devel|Win32 + {2F6C0388-20CB-4242-9F6C-A6EBB6A83F47}.Devel|Win32.Build.0 = Devel|Win32 + {2F6C0388-20CB-4242-9F6C-A6EBB6A83F47}.Release|Win32.ActiveCfg = Release|Win32 + {2F6C0388-20CB-4242-9F6C-A6EBB6A83F47}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/plugins/zzogl-pg-cg/opengl/Win32/zerogsogl_2008.vcproj b/plugins/zzogl-pg-cg/opengl/Win32/zerogsogl_2008.vcproj new file mode 100644 index 000000000..4266a05ab --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/Win32/zerogsogl_2008.vcproj @@ -0,0 +1,597 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/zzogl-pg-cg/opengl/ZZClut.cpp b/plugins/zzogl-pg-cg/opengl/ZZClut.cpp new file mode 100644 index 000000000..3ac380c90 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZZClut.cpp @@ -0,0 +1,1083 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "GS.h" +#include "Mem.h" +#include "Util.h" + +#if defined(ZEROGS_SSE2) +#include +#endif + +// Local Clut buffer: +// It supports both 32 bits and 16 bits colors formats. The size of the buffer is 1KBytes. +// The 16 bits entries are arranged in 2 columns. One row is a 32 bits colors. +// 256 0 +// 271 1 +// ... .. +// 510 254 +// 511 255 +// +// CSA -> clut buffer offset: +// 16 bits format: CSA < 32 <=> 16 entries, 16 half-row of the buffer (for example 0 to 15) +// 32 bits format: CSA < 16 <=> 16 entries, 16 full row of the buffer (for example 256|0 to 271|15) + +static const __aligned16 int s_clut_16bits_mask[4] = { 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff }; + +template +__forceinline T* GetClutBufferAddress(u32 csa) { } + +template <> +__forceinline u32* GetClutBufferAddress(u32 csa) +{ + return (u32*)(g_pbyGSClut + 64 * (csa & 15)); +} + +template <> +__forceinline u16* GetClutBufferAddress(u32 csa) +{ + return (u16*)(g_pbyGSClut + 64 * (csa & 15) + (csa >= 16 ? 2 : 0)); +} + +/* ***************************************************************** + * Local memory -> Clut buffer + * *****************************************************************/ + +#ifdef ZEROGS_SSE2 +__forceinline void GSMem_to_ClutBuffer__T32_I8_CSM1_sse2(u32* vm, u32 csa) +{ + u32* clut = GetClutBufferAddress(csa); + + __m128i* src = (__m128i*)vm; + __m128i* dst = (__m128i*)clut; + + for (int j = 0; j < 64; j += 32, src += 32, dst += 32) + { + for (int i = 0; i < 16; i += 4) + { + __m128i r0 = _mm_load_si128(&src[i+0]); + __m128i r1 = _mm_load_si128(&src[i+1]); + __m128i r2 = _mm_load_si128(&src[i+2]); + __m128i r3 = _mm_load_si128(&src[i+3]); + + _mm_store_si128(&dst[i*2+0], _mm_unpacklo_epi64(r0, r1)); + _mm_store_si128(&dst[i*2+1], _mm_unpacklo_epi64(r2, r3)); + _mm_store_si128(&dst[i*2+2], _mm_unpackhi_epi64(r0, r1)); + _mm_store_si128(&dst[i*2+3], _mm_unpackhi_epi64(r2, r3)); + + __m128i r4 = _mm_load_si128(&src[i+0+16]); + __m128i r5 = _mm_load_si128(&src[i+1+16]); + __m128i r6 = _mm_load_si128(&src[i+2+16]); + __m128i r7 = _mm_load_si128(&src[i+3+16]); + + _mm_store_si128(&dst[i*2+4], _mm_unpacklo_epi64(r4, r5)); + _mm_store_si128(&dst[i*2+5], _mm_unpacklo_epi64(r6, r7)); + _mm_store_si128(&dst[i*2+6], _mm_unpackhi_epi64(r4, r5)); + _mm_store_si128(&dst[i*2+7], _mm_unpackhi_epi64(r6, r7)); + } + } +} + +__forceinline void GSMem_to_ClutBuffer__T32_I4_CSM1_sse2(u32* vm, u32 csa) +{ + u32* clut = GetClutBufferAddress(csa); + + __m128i* src = (__m128i*)vm; + __m128i* dst = (__m128i*)clut; + + __m128i r0 = _mm_load_si128(&src[0]); + __m128i r1 = _mm_load_si128(&src[1]); + __m128i r2 = _mm_load_si128(&src[2]); + __m128i r3 = _mm_load_si128(&src[3]); + + _mm_store_si128(&dst[0], _mm_unpacklo_epi64(r0, r1)); + _mm_store_si128(&dst[1], _mm_unpacklo_epi64(r2, r3)); + _mm_store_si128(&dst[2], _mm_unpackhi_epi64(r0, r1)); + _mm_store_si128(&dst[3], _mm_unpackhi_epi64(r2, r3)); +} + + +template +__forceinline void GSMem_to_ClutBuffer__T16_I4_CSM1_core_sse2(u32* vm, u32* clut) +{ + __m128i vm_0; + __m128i vm_1; + __m128i vm_2; + __m128i vm_3; + __m128i clut_0; + __m128i clut_1; + __m128i clut_2; + __m128i clut_3; + + __m128i clut_mask = _mm_load_si128((__m128i*)s_clut_16bits_mask); + + // !HIGH_16BITS_VM + // CSA in 0-15 + // Replace lower 16 bits of clut with lower 16 bits of vm + // CSA in 16-31 + // Replace higher 16 bits of clut with lower 16 bits of vm + + // HIGH_16BITS_VM + // CSA in 0-15 + // Replace lower 16 bits of clut with higher 16 bits of vm + // CSA in 16-31 + // Replace higher 16 bits of clut with higher 16 bits of vm + if(HIGH_16BITS_VM && CSA_0_15) { + // move up to low + vm_0 = _mm_load_si128((__m128i*)vm); // 9 8 1 0 + vm_1 = _mm_load_si128((__m128i*)vm+1); // 11 10 3 2 + vm_2 = _mm_load_si128((__m128i*)vm+2); // 13 12 5 4 + vm_3 = _mm_load_si128((__m128i*)vm+3); // 15 14 7 6 + vm_0 = _mm_srli_epi32(vm_0, 16); + vm_1 = _mm_srli_epi32(vm_1, 16); + vm_2 = _mm_srli_epi32(vm_2, 16); + vm_3 = _mm_srli_epi32(vm_3, 16); + } else if(HIGH_16BITS_VM && !CSA_0_15) { + // Remove lower 16 bits + vm_0 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)vm)); // 9 8 1 0 + vm_1 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)vm+1)); // 11 10 3 2 + vm_2 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)vm+2)); // 13 12 5 4 + vm_3 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)vm+3)); // 15 14 7 6 + } else if(!HIGH_16BITS_VM && CSA_0_15) { + // Remove higher 16 bits + vm_0 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)vm)); // 9 8 1 0 + vm_1 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)vm+1)); // 11 10 3 2 + vm_2 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)vm+2)); // 13 12 5 4 + vm_3 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)vm+3)); // 15 14 7 6 + } else if(!HIGH_16BITS_VM && !CSA_0_15) { + // move low to high + vm_0 = _mm_load_si128((__m128i*)vm); // 9 8 1 0 + vm_1 = _mm_load_si128((__m128i*)vm+1); // 11 10 3 2 + vm_2 = _mm_load_si128((__m128i*)vm+2); // 13 12 5 4 + vm_3 = _mm_load_si128((__m128i*)vm+3); // 15 14 7 6 + vm_0 = _mm_slli_epi32(vm_0, 16); + vm_1 = _mm_slli_epi32(vm_1, 16); + vm_2 = _mm_slli_epi32(vm_2, 16); + vm_3 = _mm_slli_epi32(vm_3, 16); + } + + // Unsizzle the data + __m128i row_0 = _mm_unpacklo_epi64(vm_0, vm_1); // 3 2 1 0 + __m128i row_1 = _mm_unpacklo_epi64(vm_2, vm_3); // 7 6 5 4 + __m128i row_2 = _mm_unpackhi_epi64(vm_0, vm_1); // 11 10 9 8 + __m128i row_3 = _mm_unpackhi_epi64(vm_2, vm_3); // 15 14 13 12 + + // load old data & remove useless part + if(CSA_0_15) { + // Remove lower 16 bits + clut_0 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)clut)); + clut_1 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)clut+1)); + clut_2 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)clut+2)); + clut_3 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)clut+3)); + } else { + // Remove higher 16 bits + clut_0 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)clut)); + clut_1 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)clut+1)); + clut_2 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)clut+2)); + clut_3 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)clut+3)); + } + + // Merge old & new data + clut_0 = _mm_or_si128(clut_0, row_0); + clut_1 = _mm_or_si128(clut_1, row_1); + clut_2 = _mm_or_si128(clut_2, row_2); + clut_3 = _mm_or_si128(clut_3, row_3); + + _mm_store_si128((__m128i*)clut, clut_0); + _mm_store_si128((__m128i*)clut+1, clut_1); + _mm_store_si128((__m128i*)clut+2, clut_2); + _mm_store_si128((__m128i*)clut+3, clut_3); +} + +__forceinline void GSMem_to_ClutBuffer__T16_I4_CSM1_sse2(u32* vm, u32 csa) +{ + u32* clut = GetClutBufferAddress(csa); // Keep aligned version for sse2 + + if (csa > 15) { + GSMem_to_ClutBuffer__T16_I4_CSM1_core_sse2(vm, clut); + } else { + GSMem_to_ClutBuffer__T16_I4_CSM1_core_sse2(vm, clut); + } +} + +__forceinline void GSMem_to_ClutBuffer__T16_I8_CSM1_sse2(u32* vm, u32 csa) +{ + // update the right clut column (csa < 16) + u32* clut = GetClutBufferAddress(csa); // Keep aligned version for sse2 + + u32 csa_right = (csa < 16) ? 16 - csa : 0; + + for(int i = (csa_right/2); i > 0 ; --i) { + GSMem_to_ClutBuffer__T16_I4_CSM1_core_sse2(vm, clut); + clut += 16; + GSMem_to_ClutBuffer__T16_I4_CSM1_core_sse2(vm, clut); + clut += 16; + vm += 16; // go down one column + } + + // update the left clut column + u32 csa_left = (csa >= 16) ? 16 : csa; + + // In case csa_right is odd (so csa_left is also odd), we cross the clut column + if(csa_right & 0x1) { + GSMem_to_ClutBuffer__T16_I4_CSM1_core_sse2(vm, clut); + // go back to the base before processing left clut column + clut = GetClutBufferAddress(0); // Keep aligned version for sse2 + + GSMem_to_ClutBuffer__T16_I4_CSM1_core_sse2(vm, clut); + clut += 16; + vm += 16; // go down one column + } else if(csa_right != 0) { + // go back to the base before processing left clut column + clut = GetClutBufferAddress(0); // Keep aligned version for sse2 + + } + + for(int i = (csa_left/2); i > 0 ; --i) { + GSMem_to_ClutBuffer__T16_I4_CSM1_core_sse2(vm, clut); + clut += 16; + GSMem_to_ClutBuffer__T16_I4_CSM1_core_sse2(vm, clut); + clut += 16; + vm += 16; // go down one column + } +} + +#endif // ZEROGS_SSE2 + +__forceinline void GSMem_to_ClutBuffer__T16_I8_CSM1_c(u32* _vm, u32 csa) +{ + const static u32 map[] = + { + 0, 2, 8, 10, 16, 18, 24, 26, + 4, 6, 12, 14, 20, 22, 28, 30, + 1, 3, 9, 11, 17, 19, 25, 27, + 5, 7, 13, 15, 21, 23, 29, 31 + }; + + u16* vm = (u16*)_vm; + u16* clut = GetClutBufferAddress(csa); + + int left = ((u32)(uptr)clut & 2) ? 512 : 512 - (((u32)(uptr)clut) & 0x3ff) / 2; + + for (int j = 0; j < 8; j++, vm += 32, clut += 64, left -= 32) + { + if (left == 32) + { + assert(left == 32); + + for (int i = 0; i < 16; i++) + clut[2*i] = vm[map[i]]; + + clut = (u16*)((uptr)clut & ~0x3ff) + 1; + + for (int i = 16; i < 32; i++) + clut[2*i] = vm[map[i]]; + } + else + { + if (left == 0) + { + clut = (u16*)((uptr)clut & ~0x3ff) + 1; + left = -1; + } + + for (int i = 0; i < 32; i++) + clut[2*i] = vm[map[i]]; + } + } +} + +__forceinline void GSMem_to_ClutBuffer__T32_I8_CSM1_c(u32* vm, u32 csa) +{ + u64* src = (u64*)vm; + u64* dst = (u64*)GetClutBufferAddress(csa); + + for (int j = 0; j < 2; j++, src += 32) + { + for (int i = 0; i < 4; i++, dst += 16, src += 8) + { + dst[0] = src[0]; + dst[1] = src[2]; + dst[2] = src[4]; + dst[3] = src[6]; + dst[4] = src[1]; + dst[5] = src[3]; + dst[6] = src[5]; + dst[7] = src[7]; + + dst[8] = src[32]; + dst[9] = src[32+2]; + dst[10] = src[32+4]; + dst[11] = src[32+6]; + dst[12] = src[32+1]; + dst[13] = src[32+3]; + dst[14] = src[32+5]; + dst[15] = src[32+7]; + } + } +} + +__forceinline void GSMem_to_ClutBuffer__T16_I4_CSM1_c(u32* _vm, u32 csa) +{ + u16* dst = GetClutBufferAddress(csa); + u16* src = (u16*)_vm; + + dst[0] = src[0]; + dst[2] = src[2]; + dst[4] = src[8]; + dst[6] = src[10]; + dst[8] = src[16]; + dst[10] = src[18]; + dst[12] = src[24]; + dst[14] = src[26]; + dst[16] = src[4]; + dst[18] = src[6]; + dst[20] = src[12]; + dst[22] = src[14]; + dst[24] = src[20]; + dst[26] = src[22]; + dst[28] = src[28]; + dst[30] = src[30]; +} + +__forceinline void GSMem_to_ClutBuffer__T32_I4_CSM1_c(u32* vm, u32 csa) +{ + u64* src = (u64*)vm; + u64* dst = (u64*)GetClutBufferAddress(csa); + + dst[0] = src[0]; + dst[1] = src[2]; + dst[2] = src[4]; + dst[3] = src[6]; + dst[4] = src[1]; + dst[5] = src[3]; + dst[6] = src[5]; + dst[7] = src[7]; +} + +// Main GSmem to Clutbuffer function +/*__forceinline*/ void GSMem_to_ClutBuffer(tex0Info &tex0) +{ + int entries = PSMT_IS8CLUT(tex0.psm) ? 256 : 16; + + u8* _src = g_pbyGSMemory + 256 * tex0.cbp; + + if (tex0.csm) + { + switch (tex0.cpsm) + { + // 16bit psm + // eggomania uses non16bit textures for csm2 + + case PSMCT16: + { + u16* src = (u16*)_src; + u16 *dst = GetClutBufferAddress(tex0.csa); + + for (int i = 0; i < entries; ++i) + { + *dst = src[getPixelAddress16_0(gs.clut.cou+i, gs.clut.cov, gs.clut.cbw)]; + dst += 2; + + // check for wrapping + if (((u32)dst & 0x3ff) == 0) dst = GetClutBufferAddress(16); + } + break; + } + + case PSMCT16S: + { + u16* src = (u16*)_src; + u16 *dst = GetClutBufferAddress(tex0.csa); + + for (int i = 0; i < entries; ++i) + { + *dst = src[getPixelAddress16S_0(gs.clut.cou+i, gs.clut.cov, gs.clut.cbw)]; + dst += 2; + + // check for wrapping + if (((u32)dst & 0x3ff) == 0) dst = GetClutBufferAddress(16); + } + break; + } + + case PSMCT32: + case PSMCT24: + { + u32* src = (u32*)_src; + u32 *dst = GetClutBufferAddress(tex0.csa); + + // check if address exceeds src + + if (src + getPixelAddress32_0(gs.clut.cou + entries - 1, gs.clut.cov, gs.clut.cbw) >= (u32*)g_pbyGSMemory + 0x00100000) + ZZLog::Error_Log("texClutWrite out of bounds."); + else + for (int i = 0; i < entries; ++i) + { + *dst = src[getPixelAddress32_0(gs.clut.cou+i, gs.clut.cov, gs.clut.cbw)]; + dst++; + } + break; + } + + default: + { + //ZZLog::Debug_Log("Unknown cpsm: %x (%x).", tex0.cpsm, tex0.psm); + break; + } + } + } + else + { + u32* src = (u32*)_src; + + if (entries == 16) + { + if (tex0.cpsm < 2) { +#ifdef ZEROGS_SSE2 + GSMem_to_ClutBuffer__T32_I4_CSM1_sse2(src, tex0.csa); +#else + GSMem_to_ClutBuffer__T32_I4_CSM1_c(src, tex0.csa); +#endif + } else { +#ifdef ZEROGS_SSE2 + GSMem_to_ClutBuffer__T16_I4_CSM1_sse2(src, tex0.csa); +#else + GSMem_to_ClutBuffer__T16_I4_CSM1_c(src, tex0.csa); +#endif + } + } + else + { + if (tex0.cpsm < 2) { +#ifdef ZEROGS_SSE2 + GSMem_to_ClutBuffer__T32_I8_CSM1_sse2(src, tex0.csa); +#else + GSMem_to_ClutBuffer__T32_I8_CSM1_c(src, tex0.csa); +#endif + } else { +#ifdef ZEROGS_SSE2 + GSMem_to_ClutBuffer__T16_I8_CSM1_sse2(src, tex0.csa); +#else + GSMem_to_ClutBuffer__T16_I8_CSM1_c(src, tex0.csa); +#endif + } + + } + } +} + +/* ***************************************************************** + * Clut buffer -> local C array (linear) + * *****************************************************************/ +template +/*__forceinline*/ void ClutBuffer_to_Array(T* dst, u32 csa, u32 clutsize) {} + +template <> +/*__forceinline*/ void ClutBuffer_to_Array(u32* dst, u32 csa, u32 clutsize) +{ + u8* clut = (u8*)GetClutBufferAddress(csa); + memcpy_amd((u8*)dst, clut, clutsize); +} + +template <> +/*__forceinline*/ void ClutBuffer_to_Array(u16* dst, u32 csa, u32 clutsize) +{ + u16* clut = (u16*)GetClutBufferAddress(csa); // Keep aligned version for sse2 + + // which side to copy + s32 clutsize_right; + s32 clutsize_left; + if (csa < 16) { + clutsize_right = min(clutsize, (16-csa)*64); + clutsize_left = clutsize - clutsize_right; + } else { + clutsize_right = 0; + clutsize_left = clutsize; + } + + while (clutsize_right > 0) + { +#ifdef ZEROGS_SSE2 + // only lower 16 bits of dword are valid + __m128i clut_0 = _mm_load_si128((__m128i*)clut); + __m128i clut_1 = _mm_load_si128((__m128i*)clut+1); + __m128i clut_2 = _mm_load_si128((__m128i*)clut+2); + __m128i clut_3 = _mm_load_si128((__m128i*)clut+3); + + clut_0 = _mm_shufflelo_epi16(clut_0, 0x88); + clut_1 = _mm_shufflelo_epi16(clut_1, 0x88); + clut_2 = _mm_shufflelo_epi16(clut_2, 0x88); + clut_3 = _mm_shufflelo_epi16(clut_3, 0x88); + + clut_0 = _mm_shufflehi_epi16(clut_0, 0x88); // - - 3 2 1 0 - - + clut_1 = _mm_shufflehi_epi16(clut_1, 0x88); + clut_2 = _mm_shufflehi_epi16(clut_2, 0x88); + clut_3 = _mm_shufflehi_epi16(clut_3, 0x88); + + clut_0 = _mm_srli_si128(clut_0, 4); + clut_1 = _mm_srli_si128(clut_1, 4); + clut_2 = _mm_srli_si128(clut_2, 4); + clut_3 = _mm_srli_si128(clut_3, 4); + + _mm_store_si128((__m128i*)dst, _mm_unpacklo_epi64(clut_0, clut_1)); + _mm_store_si128((__m128i*)dst+1, _mm_unpacklo_epi64(clut_2, clut_3)); +#else + for(int i = 0; i < 16; ++i) + dst[i] = clut[2*i]; +#endif + + dst += 16; + clut += 32; + clutsize_right -= 32; + } + + if(csa < 16) { + // go back to the base before processing left clut column + clut = (u16*)GetClutBufferAddress(0); // Keep aligned version for sse2 + } + + while (clutsize_left > 0) + { +#ifdef ZEROGS_SSE2 + // only higher 16 bits of dword are valid + __m128i clut_0 = _mm_load_si128((__m128i*)clut); + __m128i clut_1 = _mm_load_si128((__m128i*)clut+1); + __m128i clut_2 = _mm_load_si128((__m128i*)clut+2); + __m128i clut_3 = _mm_load_si128((__m128i*)clut+3); + + clut_0 = _mm_shufflelo_epi16(clut_0, 0x88); + clut_1 = _mm_shufflelo_epi16(clut_1, 0x88); + clut_2 = _mm_shufflelo_epi16(clut_2, 0x88); + clut_3 = _mm_shufflelo_epi16(clut_3, 0x88); + + clut_0 = _mm_shufflehi_epi16(clut_0, 0x88); // - - 3 2 1 0 - - + clut_1 = _mm_shufflehi_epi16(clut_1, 0x88); + clut_2 = _mm_shufflehi_epi16(clut_2, 0x88); + clut_3 = _mm_shufflehi_epi16(clut_3, 0x88); + + clut_0 = _mm_srli_si128(clut_0, 4); + clut_1 = _mm_srli_si128(clut_1, 4); + clut_2 = _mm_srli_si128(clut_2, 4); + clut_3 = _mm_srli_si128(clut_3, 4); + + _mm_store_si128((__m128i*)dst, _mm_unpacklo_epi64(clut_0, clut_1)); + _mm_store_si128((__m128i*)dst+1, _mm_unpacklo_epi64(clut_2, clut_3)); +#else + // Note +1 because we change higher 16 bits + for(int i = 0; i < 16; ++i) + dst[i] = clut[2*i+1]; +#endif + + dst += 16; + clut += 32; + clutsize_left -= 32; + } +} + +/* ***************************************************************** + * Compare: Clut buffer <-> Local Memory + * *****************************************************************/ +// false -> identical +// true -> different +template +/*__forceinline*/ bool Cmp_ClutBuffer_GSMem(T* GSmem, u32 csa, u32 clutsize); + +template <> +/*__forceinline*/ bool Cmp_ClutBuffer_GSMem(u32* GSmem, u32 csa, u32 clutsize) +{ + u64* _GSmem = (u64*) GSmem; + u64* clut = (u64*)GetClutBufferAddress(csa); + + while(clutsize > 0) { +#ifdef ZEROGS_SSE2 + // Note: local memory datas are swizzles + __m128i GSmem_0 = _mm_load_si128((__m128i*)_GSmem); // 9 8 1 0 + __m128i GSmem_1 = _mm_load_si128((__m128i*)_GSmem+1); // 11 10 3 2 + __m128i GSmem_2 = _mm_load_si128((__m128i*)_GSmem+2); // 13 12 5 4 + __m128i GSmem_3 = _mm_load_si128((__m128i*)_GSmem+3); // 15 14 7 6 + + __m128i clut_0 = _mm_load_si128((__m128i*)clut); + __m128i clut_1 = _mm_load_si128((__m128i*)clut+1); + __m128i clut_2 = _mm_load_si128((__m128i*)clut+2); + __m128i clut_3 = _mm_load_si128((__m128i*)clut+3); + + __m128i result = _mm_cmpeq_epi32(_mm_unpacklo_epi64(GSmem_0, GSmem_1), clut_0); + + __m128i result_tmp = _mm_cmpeq_epi32(_mm_unpacklo_epi64(GSmem_2, GSmem_3), clut_1); + result = _mm_and_si128(result, result_tmp); + + result_tmp = _mm_cmpeq_epi32(_mm_unpackhi_epi64(GSmem_0, GSmem_1), clut_2); + result = _mm_and_si128(result, result_tmp); + + result_tmp = _mm_cmpeq_epi32(_mm_unpackhi_epi64(GSmem_2, GSmem_3), clut_3); + result = _mm_and_si128(result, result_tmp); + + u32 result_int = _mm_movemask_epi8(result); + if (result_int != 0xFFFF) + return true; +#else + // I see no point to keep an mmx version. SSE2 versions is probably faster. + // Keep a slow portable C version for reference/debug + // Note: local memory datas are swizzles + if (clut[0] != _GSmem[0] || clut[1] != _GSmem[2] || clut[2] != _GSmem[4] || clut[3] != _GSmem[6] + || clut[4] != _GSmem[1] || clut[5] != _GSmem[3] || clut[6] != _GSmem[5] || clut[7] != _GSmem[7]) + return true; +#endif + + // go to the next memory block + _GSmem += 32; + + // go back to the previous memory block then down one memory column + if (clutsize & 0x40) { + _GSmem -= (64-8); + } + // In case previous operation (down one column) cross the block boundary + // Go to the next block + if (clutsize == 0x240) { + _GSmem += 32; + } + + clut += 8; + clutsize -= 64; + } + + return false; +} + +#ifdef ZEROGS_SSE2 +template +__forceinline bool Cmp_ClutBuffer_GSMem_core(u16* GSmem, u16* clut) +{ + __m128i GSmem_0; + __m128i GSmem_1; + __m128i GSmem_2; + __m128i GSmem_3; + __m128i clut_0; + __m128i clut_1; + __m128i clut_2; + __m128i clut_3; + + __m128i clut_mask = _mm_load_si128((__m128i*)s_clut_16bits_mask); + + // !HIGH_16BITS_VM + // CSA in 0-15 + // cmp lower 16 bits of clut with lower 16 bits of GSmem + // CSA in 16-31 + // cmp higher 16 bits of clut with lower 16 bits of GSmem + + // HIGH_16BITS_VM + // CSA in 0-15 + // cmp lower 16 bits of clut with higher 16 bits of GSmem + // CSA in 16-31 + // cmp higher 16 bits of clut with higher 16 bits of GSmem + if(HIGH_16BITS_VM && CSA_0_15) { + // move up to low + GSmem_0 = _mm_load_si128((__m128i*)GSmem); // 9 8 1 0 + GSmem_1 = _mm_load_si128((__m128i*)GSmem+1); // 11 10 3 2 + GSmem_2 = _mm_load_si128((__m128i*)GSmem+2); // 13 12 5 4 + GSmem_3 = _mm_load_si128((__m128i*)GSmem+3); // 15 14 7 6 + GSmem_0 = _mm_srli_epi32(GSmem_0, 16); + GSmem_1 = _mm_srli_epi32(GSmem_1, 16); + GSmem_2 = _mm_srli_epi32(GSmem_2, 16); + GSmem_3 = _mm_srli_epi32(GSmem_3, 16); + } else if(HIGH_16BITS_VM && !CSA_0_15) { + // Remove lower 16 bits + GSmem_0 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)GSmem)); // 9 8 1 0 + GSmem_1 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)GSmem+1)); // 11 10 3 2 + GSmem_2 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)GSmem+2)); // 13 12 5 4 + GSmem_3 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)GSmem+3)); // 15 14 7 6 + } else if(!HIGH_16BITS_VM && CSA_0_15) { + // Remove higher 16 bits + GSmem_0 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)GSmem)); // 9 8 1 0 + GSmem_1 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)GSmem+1)); // 11 10 3 2 + GSmem_2 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)GSmem+2)); // 13 12 5 4 + GSmem_3 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)GSmem+3)); // 15 14 7 6 + } else if(!HIGH_16BITS_VM && !CSA_0_15) { + // move low to high + GSmem_0 = _mm_load_si128((__m128i*)GSmem); // 9 8 1 0 + GSmem_1 = _mm_load_si128((__m128i*)GSmem+1); // 11 10 3 2 + GSmem_2 = _mm_load_si128((__m128i*)GSmem+2); // 13 12 5 4 + GSmem_3 = _mm_load_si128((__m128i*)GSmem+3); // 15 14 7 6 + GSmem_0 = _mm_slli_epi32(GSmem_0, 16); + GSmem_1 = _mm_slli_epi32(GSmem_1, 16); + GSmem_2 = _mm_slli_epi32(GSmem_2, 16); + GSmem_3 = _mm_slli_epi32(GSmem_3, 16); + } + + // Unsizzle the data + __m128i row_0 = _mm_unpacklo_epi64(GSmem_0, GSmem_1); // 3 2 1 0 + __m128i row_1 = _mm_unpacklo_epi64(GSmem_2, GSmem_3); // 7 6 5 4 + __m128i row_2 = _mm_unpackhi_epi64(GSmem_0, GSmem_1); // 11 10 9 8 + __m128i row_3 = _mm_unpackhi_epi64(GSmem_2, GSmem_3); // 15 14 13 12 + + // load old data & remove useless part + if(!CSA_0_15) { + // Remove lower 16 bits + clut_0 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)clut)); + clut_1 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)clut+1)); + clut_2 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)clut+2)); + clut_3 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)clut+3)); + } else { + // Remove higher 16 bits + clut_0 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)clut)); + clut_1 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)clut+1)); + clut_2 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)clut+2)); + clut_3 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)clut+3)); + } + + // Do the comparaison + __m128i result = _mm_cmpeq_epi16(row_0, clut_0); + __m128i result_tmp = _mm_cmpeq_epi16(row_1, clut_1); + result = _mm_and_si128(result, result_tmp); + + result_tmp = _mm_cmpeq_epi16(row_2, clut_2); + result = _mm_and_si128(result, result_tmp); + + result_tmp = _mm_cmpeq_epi16(row_3, clut_3); + result = _mm_and_si128(result, result_tmp); + + u32 result_int = _mm_movemask_epi8(result); + if(CSA_0_15) { + // only lower 16bits must be checked + if ((result_int&0x3333) != 0x3333) + return true; + } else { + // only higher 16bits must be checked + if ((result_int&0xCCCC) != 0xCCCC) + return true; + } + + return false; +} +#endif + +template <> +/*__forceinline*/ bool Cmp_ClutBuffer_GSMem(u16* GSmem, u32 csa, u32 clutsize) +{ +#ifdef ZEROGS_SSE2 + u16* clut = (u16*)GetClutBufferAddress(csa); // Keep aligned version for sse2 + + // Special case only one CSA block to check + if(clutsize == 32) { + if (csa < 16) + return Cmp_ClutBuffer_GSMem_core(GSmem, clut); + else + return Cmp_ClutBuffer_GSMem_core(GSmem, clut); + } + + // which side to cmp + s32 clutsize_right; // Note clutsize_right could be negative ! + u32 clutsize_left; + if (csa < 16) { + // the '-32' is a trick to handle easily when csa is odd + clutsize_right = min(clutsize, (16-csa)*32) -32; + clutsize_left = clutsize - clutsize_right; + } else { + clutsize_right = 0; + clutsize_left = clutsize; + } + + while(clutsize_right > 0) { + if (Cmp_ClutBuffer_GSMem_core(GSmem, clut)) + return true; + clut += 32; + + if (Cmp_ClutBuffer_GSMem_core(GSmem, clut)) + return true; + clut += 32; + + GSmem += 32; // go down one column + clutsize_right -= 64; + } + + if(csa < 16) { + // because of the extra -32, csa_righ is null when csa is odd + if (clutsize_right == 0) { + // cross the clut + if (Cmp_ClutBuffer_GSMem_core(GSmem, clut)) + return true; + clut += 32; + + if (Cmp_ClutBuffer_GSMem_core(GSmem, clut)) + return true; + + GSmem += 32; // go down one column + clutsize_left -= 32; + } + + // go back to the base before processing left clut column + clut = (u16*)GetClutBufferAddress(0); // Keep aligned version for sse2 + } + + while(clutsize_left > 0) { + if (Cmp_ClutBuffer_GSMem_core(GSmem, clut)) + return true; + clut += 32; + + if (Cmp_ClutBuffer_GSMem_core(GSmem, clut)) + return true; + clut += 32; + + GSmem += 32; // go down one column + clutsize_left -= 64; + } + + return false; +#else + // This function is only useful for performance. So just return + // for a plain c build + return true; +#endif +} + +/* ***************************************************************** + * Compare: Clut buffer <-> local C array (linear) + * *****************************************************************/ +// false -> identical +// true -> different +template +/*__forceinline*/ bool Cmp_ClutBuffer_SavedClut(T* saved_clut, u32 csa, u32 clutsize); + +template <> +/*__forceinline*/ bool Cmp_ClutBuffer_SavedClut(u32* saved_clut, u32 csa, u32 clutsize) +{ + u32* clut = GetClutBufferAddress(csa); + return !!memcmp_mmx(saved_clut, clut, clutsize); +} + +template <> +/*__forceinline*/ bool Cmp_ClutBuffer_SavedClut(u16* saved_clut, u32 csa, u32 clutsize) +{ + assert((clutsize&31) == 0); + +#ifdef ZEROGS_SSE2 + __m128i zero_128 = _mm_setzero_si128(); +#endif + u16* clut = (u16*)GetClutBufferAddress(csa); // Keep aligned version for sse2 + + // which side to cmp + u32 clutsize_right; + u32 clutsize_left; + if (csa < 16) { + clutsize_right = min(clutsize, (16-csa)*32); + clutsize_left = clutsize - clutsize_right; + } else { + clutsize_right = 0; + clutsize_left = clutsize; + } + + while (clutsize_right > 0) + { +#ifdef ZEROGS_SSE2 + // only lower 16 bits of dword are valid + __m128i clut_0 = _mm_load_si128((__m128i*)clut); + __m128i clut_1 = _mm_load_si128((__m128i*)clut+1); + __m128i clut_2 = _mm_load_si128((__m128i*)clut+2); + __m128i clut_3 = _mm_load_si128((__m128i*)clut+3); + + // value must converted to 32 bits + __m128i saved_clut_0 = _mm_load_si128((__m128i*)saved_clut); + __m128i saved_clut_1 = _mm_load_si128((__m128i*)saved_clut+1); + + __m128i result = _mm_cmpeq_epi16(_mm_unpacklo_epi16(saved_clut_0, zero_128), clut_0); + __m128i result_tmp = _mm_cmpeq_epi16(_mm_unpackhi_epi16(saved_clut_0, zero_128), clut_1); + result = _mm_and_si128(result, result_tmp); + + result_tmp = _mm_cmpeq_epi16(_mm_unpacklo_epi16(saved_clut_1, zero_128), clut_2); + result = _mm_and_si128(result, result_tmp); + + result_tmp = _mm_cmpeq_epi16(_mm_unpackhi_epi16(saved_clut_1, zero_128), clut_3); + result = _mm_and_si128(result, result_tmp); + + u32 result_int = _mm_movemask_epi8(result); + // only lower 16bits must be checked + if ((result_int&0x3333) != 0x3333) + return true; +#else + for (int i = 0; i < 16; ++i) + if (saved_clut[i] != clut[2*i]) return true; +#endif + + saved_clut += 16; + clut += 32; + clutsize_right -= 32; + } + + if(csa < 16) { + // go back to the base before processing left clut column + clut = (u16*)GetClutBufferAddress(0); // Keep aligned version for sse2 + } + + while (clutsize_left > 0) + { +#ifdef ZEROGS_SSE2 + // only higher 16 bits of dword are valid + __m128i clut_0 = _mm_load_si128((__m128i*)clut); + __m128i clut_1 = _mm_load_si128((__m128i*)clut+1); + __m128i clut_2 = _mm_load_si128((__m128i*)clut+2); + __m128i clut_3 = _mm_load_si128((__m128i*)clut+3); + + // value must converted to 32 bits (with 0 in lower 16 bits) + __m128i saved_clut_0 = _mm_load_si128((__m128i*)saved_clut); + __m128i saved_clut_1 = _mm_load_si128((__m128i*)saved_clut+1); + + __m128i result = _mm_cmpeq_epi16(_mm_unpacklo_epi16(zero_128, saved_clut_0), clut_0); + __m128i result_tmp = _mm_cmpeq_epi16(_mm_unpackhi_epi16(zero_128, saved_clut_0), clut_1); + result = _mm_and_si128(result, result_tmp); + + result_tmp = _mm_cmpeq_epi16(_mm_unpacklo_epi16(zero_128, saved_clut_1), clut_2); + result = _mm_and_si128(result, result_tmp); + + result_tmp = _mm_cmpeq_epi16(_mm_unpackhi_epi16(zero_128, saved_clut_1), clut_3); + result = _mm_and_si128(result, result_tmp); + + u32 result_int = _mm_movemask_epi8(result); + // only higher 16bits must be checked + if ((result_int&0xCCCC) != 0xCCCC) + return true; +#else + // Note +1 because we change higher 16 bits + for (int i = 0; i < 16; ++i) + if (saved_clut[i] != clut[2*i+1]) return true; +#endif + + saved_clut += 16; + clut += 32; + clutsize_left -= 32; + } + + return false; +} + + +/* ***************************************************************** + * Resolve color of clut texture + * *****************************************************************/ + +// used to build clut textures (note that this is for both 16 and 32 bit cluts) +template +/*__forceinline*/ void Build_Clut_Texture(u32 psm, u32 height, T* pclut, u8* psrc, T* pdst) +{ + switch (psm) + { + case PSMT8: + for (u32 i = 0; i < height; ++i) + { + for (int j = 0; j < GPU_TEXWIDTH / 2; ++j) + { + pdst[0] = pclut[psrc[0]]; + pdst[1] = pclut[psrc[1]]; + pdst[2] = pclut[psrc[2]]; + pdst[3] = pclut[psrc[3]]; + pdst[4] = pclut[psrc[4]]; + pdst[5] = pclut[psrc[5]]; + pdst[6] = pclut[psrc[6]]; + pdst[7] = pclut[psrc[7]]; + pdst += 8; + psrc += 8; + } + } + break; + + case PSMT4: + for (u32 i = 0; i < height; ++i) + { + for (int j = 0; j < GPU_TEXWIDTH; ++j) + { + pdst[0] = pclut[psrc[0] & 15]; + pdst[1] = pclut[psrc[0] >> 4]; + pdst[2] = pclut[psrc[1] & 15]; + pdst[3] = pclut[psrc[1] >> 4]; + pdst[4] = pclut[psrc[2] & 15]; + pdst[5] = pclut[psrc[2] >> 4]; + pdst[6] = pclut[psrc[3] & 15]; + pdst[7] = pclut[psrc[3] >> 4]; + + pdst += 8; + psrc += 4; + } + } + break; + + case PSMT8H: + for (u32 i = 0; i < height; ++i) + { + for (int j = 0; j < GPU_TEXWIDTH / 8; ++j) + { + pdst[0] = pclut[psrc[3]]; + pdst[1] = pclut[psrc[7]]; + pdst[2] = pclut[psrc[11]]; + pdst[3] = pclut[psrc[15]]; + pdst[4] = pclut[psrc[19]]; + pdst[5] = pclut[psrc[23]]; + pdst[6] = pclut[psrc[27]]; + pdst[7] = pclut[psrc[31]]; + pdst += 8; + psrc += 32; + } + } + break; + + case PSMT4HH: + for (u32 i = 0; i < height; ++i) + { + for (int j = 0; j < GPU_TEXWIDTH / 8; ++j) + { + pdst[0] = pclut[psrc[3] >> 4]; + pdst[1] = pclut[psrc[7] >> 4]; + pdst[2] = pclut[psrc[11] >> 4]; + pdst[3] = pclut[psrc[15] >> 4]; + pdst[4] = pclut[psrc[19] >> 4]; + pdst[5] = pclut[psrc[23] >> 4]; + pdst[6] = pclut[psrc[27] >> 4]; + pdst[7] = pclut[psrc[31] >> 4]; + pdst += 8; + psrc += 32; + } + } + break; + + case PSMT4HL: + for (u32 i = 0; i < height; ++i) + { + for (int j = 0; j < GPU_TEXWIDTH / 8; ++j) + { + pdst[0] = pclut[psrc[3] & 15]; + pdst[1] = pclut[psrc[7] & 15]; + pdst[2] = pclut[psrc[11] & 15]; + pdst[3] = pclut[psrc[15] & 15]; + pdst[4] = pclut[psrc[19] & 15]; + pdst[5] = pclut[psrc[23] & 15]; + pdst[6] = pclut[psrc[27] & 15]; + pdst[7] = pclut[psrc[31] & 15]; + pdst += 8; + psrc += 32; + } + } + break; + + default: + assert(0); + } +} + +// Instantiate the Build_Clut_Texture template... +template void Build_Clut_Texture(u32 psm, u32 height, u32* pclut, u8* psrc, u32* pdst); +template void Build_Clut_Texture(u32 psm, u32 height, u16* pclut, u8* psrc, u16* pdst); diff --git a/plugins/zzogl-pg-cg/opengl/ZZClut.h b/plugins/zzogl-pg-cg/opengl/ZZClut.h new file mode 100644 index 000000000..f2b0428ca --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZZClut.h @@ -0,0 +1,30 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef CLUT_H_INCLUDED +#define CLUT_H_INCLUDED + +extern void GSMem_to_ClutBuffer(tex0Info &tex0); +template extern void ClutBuffer_to_Array(T* dst, u32 csa, u32 clutsize); +template extern void Build_Clut_Texture(u32 psm, u32 height, T* pclut, u8* psrc, T* pdst); + +template extern bool Cmp_ClutBuffer_GSMem(T* GSmem, u32 csa, u32 clutsize); +template extern bool Cmp_ClutBuffer_SavedClut(T* saved_clut, u32 csa, u32 clutsize); + +#endif // CLUT_H_INCLUDED diff --git a/plugins/zzogl-pg-cg/opengl/ZZGl.h b/plugins/zzogl-pg-cg/opengl/ZZGl.h new file mode 100644 index 000000000..c2979b718 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZZGl.h @@ -0,0 +1,134 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef ZZGL_H_INCLUDED +#define ZZGL_H_INCLUDED + +#include "PS2Etypes.h" +#include "PS2Edefs.h" + +// Need this before gl.h +#ifdef _WIN32 + +#include "Utilities/RedtapeWindows.h" + +#include +#include +#include "glprocs.h" + +#else + +// adding glew support instead of glXGetProcAddress (thanks to scaught) +#include +#include +#include +#include + +inline void* wglGetProcAddress(const char* x) +{ + return (void*)glXGetProcAddress((const GLubyte*)x); +} + +#endif + +extern u32 s_stencilfunc, s_stencilref, s_stencilmask; +// Defines + +#ifndef GL_DEPTH24_STENCIL8_EXT // allows FBOs to support stencils +# define GL_DEPTH_STENCIL_EXT 0x84F9 +# define GL_UNSIGNED_INT_24_8_EXT 0x84FA +# define GL_DEPTH24_STENCIL8_EXT 0x88F0 +# define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1 +#endif + +#define GL_STENCILFUNC(func, ref, mask) { \ + s_stencilfunc = func; \ + s_stencilref = ref; \ + s_stencilmask = mask; \ + glStencilFunc(func, ref, mask); \ +} + +#define GL_STENCILFUNC_SET() glStencilFunc(s_stencilfunc, s_stencilref, s_stencilmask) + + +// sets the data stream +#define SET_STREAM() { \ + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexGPU), (void*)8); \ + glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, sizeof(VertexGPU), (void*)12); \ + glTexCoordPointer(3, GL_FLOAT, sizeof(VertexGPU), (void*)16); \ + glVertexPointer(4, GL_SHORT, sizeof(VertexGPU), (void*)0); \ +} + + +// global alpha blending settings +extern GLenum g_internalRGBAFloat16Fmt; + +#define SAFE_RELEASE_TEX(x) { if( (x) != 0 ) { glDeleteTextures(1, &(x)); x = 0; } } + +// inline for an extremely often used sequence +// This is turning off all gl functions. Safe to do updates. +inline void DisableAllgl() +{ + glDisable(GL_SCISSOR_TEST); + glDisable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + glDisable(GL_DEPTH_TEST); + glDepthMask(0); + glDisable(GL_STENCIL_TEST); + glColorMask(1, 1, 1, 1); +} + +//--------------------- Dummies + +#ifdef _WIN32 +extern void (__stdcall *zgsBlendEquationSeparateEXT)(GLenum, GLenum); +extern void (__stdcall *zgsBlendFuncSeparateEXT)(GLenum, GLenum, GLenum, GLenum); +#else +extern void (APIENTRY *zgsBlendEquationSeparateEXT)(GLenum, GLenum); +extern void (APIENTRY *zgsBlendFuncSeparateEXT)(GLenum, GLenum, GLenum, GLenum); +#endif + + +// ------------------------ Types ------------------------- + +///////////////////// +// graphics resources +extern GLenum s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha; // set by zgsBlendFuncSeparateEXT + +// GL prototypes +extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT; +extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; +extern PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT; +extern PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT; +extern PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT; +extern PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT; +extern PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT; +extern PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT; +extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT; +extern PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT; +extern PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT; +extern PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT; +extern PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT; +extern PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT; +extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT; +extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT; +extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; +extern PFNGLDRAWBUFFERSPROC glDrawBuffers; + +#endif // ZZGL_H_INCLUDED diff --git a/plugins/zzogl-pg-cg/opengl/ZZHacks.cpp b/plugins/zzogl-pg-cg/opengl/ZZHacks.cpp new file mode 100644 index 000000000..183f0fa89 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZZHacks.cpp @@ -0,0 +1,186 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + + #include "Util.h" + #include "ZZHacks.h" + #include "ZZLog.h" + +int CurrentHack = 0; + +// A list of what bit controls each of the current hacks. +u32 hackList[HACK_NUMBER] = +{ + 0, // No hack + 1, //GAME_TEXTURETARGS, + 2, //GAME_AUTORESET, + 3, //GAME_INTERLACE2X, + 4, //GAME_TEXAHACK, + 5, //GAME_NOTARGETRESOLVE, + 6, //GAME_EXACTCOLOR, + //7 //GAME_NOCOLORCLAMP, + //8 //GAME_FFXHACK, + 9, //GAME_NOALPHAFAIL, + 10, //GAME_NODEPTHUPDATE, + 11, //GAME_QUICKRESOLVE1, + 12, //GAME_NOQUICKRESOLVE, + 13, //GAME_NOTARGETCLUT, + 14, //GAME_NOSTENCIL, + 15, //GAME_NODEPTHRESOLVE, + 16, //GAME_FULL16BITRES, + 17, //GAME_RESOLVEPROMOTED, + 18, //GAME_FASTUPDATE, + 19, //GAME_NOALPHATEST, + 20, //GAME_DISABLEMRTDEPTH, + //21 //GAME_32BITTARGS, + //22 //GAME_PATH3HACK, + //23 //GAME_DOPARALLELCTX, + 24, //GAME_XENOSPECHACK, + //25 //GAME_PARTIALPOINTERS, + 26, //GAME_PARTIALDEPTH, + 27, //GAME_REGETHACK, + 28, //GAME_GUSTHACK, + 29, //GAME_NOLOGZ, + 30, //GAME_AUTOSKIPDRAW +}; + + +char hackDesc[32][64] = +{ + "No hack", + "Texture targs", + "Auto reset", + "Interlace 2x", + "Texa", + "No target resolve", + "Exact color", + "No color clamp", + "Final Fantasy X", + "No alpha fail", + "No depth update", + "Quick resolve 1", + "No Quick resolve", + "No target clut", + "No stencil", + "VSS", + "No depth resolve", + "Full 16 bit resolution", + "Resolve promoted", + "Fast update", + "No alpha test", + "Disable mrt depth", + "Args 32 bit", + "", + "Parallel context", + "Xenosaga spec", + "Partial pointers", + "Partial depth", + "Reget", + "Gust", + "No logz", + "Automatic skip draw" +}; + +struct hacks +{ + bool enabled; + char shortDesc[64]; + char longDesc[256]; +}; + +hacks hack_list[32] = +{ + { true, "No hack", "No hack" }, + { true, "Texture targs", "Tex Target checking - 00000001\nLego Racers" }, + { true, "Auto reset", "Auto reset targs - 00000002\nUse when game is slow and toggling AA fixes it. Samurai Warriors. (Automatically on for Shadow Hearts)" }, + { true, "Interlace 2x", "Interlace 2X - 00000004\nFixes 2x bigger screen. Gradius 3." }, + { false, "Texa", "" }, + { true, "No target resolve", "No target resolves - 00000010\nStops all resolving of targets. Try this first for really slow games. (Automatically on for Dark Cloud 1.)" }, + { true, "Exact color", "Exact color testing - 00000020\nFixes overbright or shadow/black artifacts. Crash 'n Burn." }, + { false, "No color clamp", "No color clamping - 00000040\nSpeeds up games, but might be too bright or too dim." }, + { false, "Final Fantasy X", "" }, + { false, "No alpha fail", "Alpha Fail hack - 00000100\nRemove vertical stripes or other coloring artifacts. Breaks Persona 4 and MGS3. (Automatically on for Sonic Unleashed, Shadow the Hedgehog, & Ghost in the Shell.)" }, + { true, "No depth update", "Disable depth updates - 00000200" }, + { true, "Quick resolve 1", "Resolve Hack #1 - 00000400\n Speeds some games. Kingdom Hearts."}, + { true, "No Quick resolve", "Resolve Hack #2 - 00000800\nShadow Hearts, Urbz. Destroys FFX."}, + { true, "No target clut", "No target CLUT - 00001000\nResident Evil 4, or foggy scenes." }, + { true, "No stencil", "Disable stencil buffer - 00002000\nUsually safe to do for simple scenes. Harvest Moon." }, + { false, "VSS", "" }, + { true, "No depth resolve", "No depth resolve - 00008000\nMight give z buffer artifacts." }, + { true, "Full 16 bit resolution", "Full 16 bit resolution - 00010000\nUse when half the screen is missing." }, + { true, "Resolve promoted", "Resolve Hack #3 - 00020000\nNeopets" }, + { true, "Fast update", "Fast Update - 00040000\n Speeds some games. Needed for Sonic Unleashed. Okami." }, + { true, "No alpha test", "Disable alpha testing - 00080000" }, + { true, "Disable mrt depth", "Enable Multiple RTs - 00100000" }, + { false, "Args 32 bit", "" }, + { false, "Path3", "" }, + { false, "Parallel context", "" }, + { true, "Xenosaga spec", "Specular Highlights - 01000000\nMakes graphics faster by removing highlights. (Automatically on for Xenosaga, Okami, & Okage.)" }, + { false, "Partial pointers", "Partial targets - 02000000" }, + { true, "Partial depth", "Partial depth - 04000000" }, + { false, "Reget", "" }, + { true, "Gust", "Gust fix - 10000000. Makes gust games cleaner and faster. (Automatically on for most Gust games)" }, + { true, "No logz", "No logarithmic Z - 20000000. Could decrease number of Z-artifacts." }, + { true, "Automatic skip draw", "Remove blur effect on some games\nSlow games." } +}; + +void ReportHacks(gameHacks hacks) +{ + for(int i = 0; i < 32; i++) + { + if (hacks._u32 & (1 << i)) + { + ZZLog::WriteLn("'%s' hack enabled.", hackDesc[i+1]); + } + } +} + +void ListHacks() +{ + if ((!conf.disableHacks) && (conf.def_hacks._u32 != 0)) + { + ZZLog::WriteLn("Auto-enabling these hacks:"); + ReportHacks(conf.def_hacks); + } + + if (conf.hacks._u32 != 0) + { + ZZLog::WriteLn("You've manually enabled these hacks:"); + ReportHacks(conf.hacks); + } +} + +void DisplayHack(int hack) +{ + ZZLog::WriteToScreen2("***%d %s", hack, hackDesc[hackList[hack]]); +} + +void ChangeCurrentHack(int hack) +{ + FUNCLOG + + conf.hacks._u32 &= !(hackList[CurrentHack]); + conf.hacks._u32 |= hackList[hack]; + + DisplayHack(hack); + + CurrentHack = hack; + SaveConfig(); + +} + diff --git a/plugins/zzogl-pg-cg/opengl/ZZHacks.h b/plugins/zzogl-pg-cg/opengl/ZZHacks.h new file mode 100644 index 000000000..b4bf03b28 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZZHacks.h @@ -0,0 +1,118 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef ZZHACKS_H_INCLUDED +#define ZZHACKS_H_INCLUDED + +#include "PS2Edefs.h" + +// This is a list of the various hacks, and what bit controls them. +// Changing these is not advised unless you know what you are doing. +enum GAME_HACK_OPTIONS +{ + GAME_TEXTURETARGS = 0x00000001, + GAME_AUTORESET = 0x00000002, + GAME_INTERLACE2X = 0x00000004, + GAME_TEXAHACK = 0x00000008, // apply texa to non textured polys + GAME_NOTARGETRESOLVE = 0x00000010, + GAME_EXACTCOLOR = 0x00000020, + GAME_NOCOLORCLAMP = 0x00000040, + GAME_FFXHACK = 0x00000080, + GAME_NOALPHAFAIL = 0x00000100, + GAME_NODEPTHUPDATE = 0x00000200, + GAME_QUICKRESOLVE1 = 0x00000400, + GAME_NOQUICKRESOLVE = 0x00000800, + GAME_NOTARGETCLUT = 0x00001000, // full 16 bit resolution + GAME_NOSTENCIL = 0x00002000, + GAME_VSSHACKOFF = 0x00004000, // vertical stripe syndrome + GAME_NODEPTHRESOLVE = 0x00008000, + GAME_FULL16BITRES = 0x00010000, + GAME_RESOLVEPROMOTED = 0x00020000, + GAME_FASTUPDATE = 0x00040000, + GAME_NOALPHATEST = 0x00080000, + GAME_DISABLEMRTDEPTH = 0x00100000, + GAME_32BITTARGS = 0x00200000, + GAME_PATH3HACK = 0x00400000, + GAME_DOPARALLELCTX = 0x00800000, // tries to parallelize both contexts so that render calls are reduced (xenosaga) + // makes the game faster, but can be buggy + GAME_XENOSPECHACK = 0x01000000, // xenosaga specularity hack (ignore any zmask=1 draws) + GAME_PARTIALPOINTERS = 0x02000000, // whenver the texture or render target are small, tries to look for bigger ones to read from + GAME_PARTIALDEPTH = 0x04000000, // tries to save depth targets as much as possible across height changes + GAME_REGETHACK = 0x08000000, // some sort of weirdness in ReGet() code + GAME_GUSTHACK = 0x10000000, // Needed for Gustgames fast update. + GAME_NOLOGZ = 0x20000000, // Intended for linux -- not logarithmic Z. + GAME_AUTOSKIPDRAW = 0x40000000, // Remove blur effect on some games + GAME_RESERVED_HACK = 0x80000000 +}; + +#define USEALPHATESTING (!(conf.settings().no_alpha_test)) + +typedef union +{ + struct + { + u32 texture_targs : 1; + u32 auto_reset : 1; + u32 interlace_2x : 1; + u32 texa : 1; // apply texa to non textured polys + u32 no_target_resolve : 1; + u32 exact_color : 1; + u32 no_color_clamp : 1; + u32 ffx : 1; + u32 no_alpha_fail : 1; + u32 no_depth_update : 1; + u32 quick_resolve_1 : 1; + u32 no_quick_resolve : 1; + u32 no_target_clut : 1; // full 16 bit resolution + u32 no_stencil : 1; + u32 vss_hack_off : 1; // vertical stripe syndrome + u32 no_depth_resolve : 1; + u32 full_16_bit_res : 1; + u32 resolve_promoted : 1; + u32 fast_update : 1; + u32 no_alpha_test : 1; + u32 disable_mrt_depth : 1; + u32 args_32_bit : 1; + u32 path3 : 1; + u32 parallel_context : 1; // tries to parallelize both contexts so that render calls are reduced (xenosaga) + // makes the game faster, but can be buggy + u32 xenosaga_spec : 1; // xenosaga specularity hack (ignore any zmask=1 draws) + u32 partial_pointers : 1; // whenver the texture or render target are small, tries to look for bigger ones to read from + u32 partial_depth : 1; // tries to save depth targets as much as possible across height changes + u32 reget : 1; // some sort of weirdness in ReGet() code + u32 gust : 1; // Needed for Gustgames fast update. + u32 no_logz : 1; // Intended for linux -- not logarithmic Z. + u32 automatic_skip_draw :1; // allow debug of the automatic skip draw option + u32 reserved2 :1; + }; + u32 _u32; +} gameHacks; + +#define HACK_NUMBER 25 +extern u32 hackList[HACK_NUMBER]; +extern char hackDesc[32][64]; +extern int CurrentHack; + +extern void ReportHacks(gameHacks hacks); +extern void ListHacks(); + +extern void DisplayHack(int hack); +extern void ChangeCurrentHack(int hack); + +#endif // ZZHACKS_H_INCLUDED diff --git a/plugins/zzogl-pg-cg/opengl/ZZKeyboard.cpp b/plugins/zzogl-pg-cg/opengl/ZZKeyboard.cpp new file mode 100644 index 000000000..138ed302f --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZZKeyboard.cpp @@ -0,0 +1,247 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +// keyboard functions + +#include "Util.h" +#include "GS.h" +#include "ZZoglShaders.h" +#include "Profile.h" +#include "GLWin.h" + +extern int CurrentSavestate, g_GSMultiThreaded, g_nPixelShaderVer; +extern char *libraryName; +extern const unsigned char zgsversion; +extern unsigned char zgsrevision, zgsbuild, zgsminor; + +extern bool SaveStateExists; + +const char* s_aa[5] = { "AA none |", "AA 2x |", "AA 4x |", "AA 8x |", "AA 16x |" }; +const char* pbilinear[] = { "off", "normal", "forced" }; + +extern void SetAA(int mode); + +extern bool dump_enable; + +void ProcessBilinear() +{ + FUNCLOG + char strtitle[256]; + + if (g_nPixelShaderVer == SHADER_REDUCED) + { + conf.bilinear = 0; + sprintf(strtitle, "reduced shaders don't support bilinear filtering"); + } + else + { + conf.bilinear = (conf.bilinear + 1) % 3; + sprintf(strtitle, "bilinear filtering - %s", pbilinear[conf.bilinear]); + } + ZZLog::WriteToScreen(strtitle); + SaveConfig(); +} + +void ProcessInterlace() +{ + FUNCLOG + + char strtitle[256]; + conf.interlace++; + + if (conf.interlace > 2) conf.interlace = 0; + + if (conf.interlace < 2) + sprintf(strtitle, "interlace on - mode %d", conf.interlace); + else + sprintf(strtitle, "interlace off"); + + ZZLog::WriteToScreen(strtitle); + SaveConfig(); +} + +void ProcessAASetting(bool reverse) +{ + FUNCLOG + + char strtitle[256]; + + if (reverse) + conf.decAA(); + else + conf.incAA(); + + sprintf(strtitle, "anti-aliasing - %s", s_aa[conf.aa]); + SetAA(conf.aa); + ZZLog::WriteToScreen(strtitle); + + SaveConfig(); +} + +void ProcessFPS() +{ + FUNCLOG + g_bDisplayFPS ^= 1; + ZZLog::Debug_Log("Toggled FPS."); +} + +void ProcessWireFrame() +{ + FUNCLOG + char strtitle[256]; + + conf.zz_options.wireframe = !conf.zz_options.wireframe; + glPolygonMode(GL_FRONT_AND_BACK, (conf.wireframe()) ? GL_LINE : GL_FILL); + sprintf(strtitle, "wireframe rendering - %s", (conf.wireframe()) ? "on" : "off"); + ZZLog::WriteToScreen(strtitle); +} + +void ProcessFrameDump() +{ + FUNCLOG + + conf.dump = 1; + + char strtitle[256]; + sprintf(strtitle, "GS dump-frame"); + + ZZLog::WriteToScreen(strtitle); + SaveConfig(); +} + +void ProcessVideoDump() +{ + FUNCLOG + + char strtitle[256]; + + if (conf.dump != 0) { + sprintf(strtitle, "Stop GS dump-video"); + conf.dump = 0; + } else { + sprintf(strtitle, "Start GS dump-video"); + conf.dump = 3; + } + + ZZLog::WriteToScreen(strtitle); + SaveConfig(); +} + +void ProcessHackSetting(bool reverse) +{ + FUNCLOG + + int hack = CurrentHack; + + if (reverse) + { + hack--; + + if (hack < 0) hack = HACK_NUMBER - 1; + } + else + { + hack++; + + if (hack >= HACK_NUMBER) hack = 0; + } + ChangeCurrentHack(hack); + + SaveConfig(); +} + +void ProcessSaveState() +{ + FUNCLOG + char strtitle[256]; + sprintf(strtitle, "Saving in savestate %d", CurrentSavestate); + SaveStateExists = true; + if (CurrentHack != 0) DisplayHack(CurrentHack); +} + +void OnFKey(int key, int shift) +{ + switch(key) + { + //case 1: + // ProcessSaveState(); + // break; + case 5: + if (shift) + ProcessBilinear(); + else + ProcessInterlace(); + break; + case 6: + if (shift) + ProcessAASetting(true); + else + ProcessAASetting(false); + break; + case 7: + if (!shift) + ProcessFPS(); + else + ProcessWireFrame(); + break; + case 9: +#ifdef _DEBUG + // Fn keys are a bit overload... I don't have a better idea --Gregory + if (shift) + ProcessVideoDump(); + else + ProcessFrameDump(); +#else + if (shift) + ProcessHackSetting(true); + else + ProcessHackSetting(false); + break; +#endif + default: + break; + } +} + +void WriteAA() +{ + if (conf.aa != 0) + { + char strtitle[64]; + sprintf(strtitle, "anti-aliasing - %s", s_aa[conf.aa]); + ZZLog::WriteToScreen(strtitle, 1000); + } +} + +void WriteBilinear() +{ + switch (conf.bilinear) + { + case 2: + ZZLog::WriteToScreen("bilinear filtering - forced", 1000); + break; + + case 1: + ZZLog::WriteToScreen("bilinear filtering - normal", 1000); + break; + + default: + break; + } +} diff --git a/plugins/zzogl-pg-cg/opengl/ZZLog.cpp b/plugins/zzogl-pg-cg/opengl/ZZLog.cpp new file mode 100644 index 000000000..668a0d6db --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZZLog.cpp @@ -0,0 +1,354 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include "ZZLog.h" +#include +#include + +extern GSconf conf; + +using namespace std; + +static list listMsgs; + +void ProcessMessages() +{ + FUNCLOG + + if (listMsgs.size() > 0) + { + int left = 25, top = 15; + list::iterator it = listMsgs.begin(); + + while (it != listMsgs.end()) + { + DrawText(it->str, left + 1, top + 1, 0xff000000); + DrawText(it->str, left, top, 0xffffff30); + top += 15; + + if ((int)(it->dwTimeStamp - timeGetTime()) < 0) + it = listMsgs.erase(it); + else ++it; + } + } +} + +void ZZAddMessage(const char* pstr, u32 ms) +{ + FUNCLOG + listMsgs.push_back(MESSAGE(pstr, timeGetTime() + ms)); + ZZLog::Log("%s\n", pstr); +} + +namespace ZZLog +{ +std::string s_strLogPath("logs"); +FILE *gsLog; + +bool IsLogging() +{ + // gsLog can be null if the config dialog is used prior to Pcsx2 starting an emulation session. + // (GSinit won't have been called then) + return (gsLog != NULL && conf.log); +} + +void Open() +{ + const std::string LogFile(s_strLogPath + "/GSzzogl.log"); + + gsLog = fopen(LogFile.c_str(), "w"); + if (gsLog != NULL) + setvbuf(gsLog, NULL, _IONBF, 0); + else + SysMessage("Can't create log file %s\n", LogFile.c_str()); + +} + +void Close() +{ + if (gsLog != NULL) { + fclose(gsLog); + gsLog = NULL; + } +} + +void SetDir(const char* dir) +{ + // Get the path to the log directory. + s_strLogPath = (dir==NULL) ? "logs" : dir; + + // Reload previously open log file + if (gsLog) { + Close(); + Open(); + } +} + +void WriteToScreen(const char* pstr, u32 ms) +{ + ZZAddMessage(pstr, ms); +} + +void WriteToScreen2(const char* fmt, ...) +{ + va_list list; + char tmp[512]; + + va_start(list, fmt); + vsprintf(tmp, fmt, list); + va_end(list); + + ZZAddMessage(tmp, 5000); +} + +void _Message(const char *str) +{ + SysMessage(str); +} + +void _Log(const char *str) +{ + if (IsLogging()) fprintf(gsLog, str); +} + +void _WriteToConsole(const char *str) +{ + fprintf(stderr,"ZZogl-PG: %s", str); +} + +void _Print(const char *str) +{ + fprintf(stderr,"ZZogl-PG: %s", str); + + if (IsLogging()) fprintf(gsLog, str); +} + +void Message(const char *fmt, ...) +{ + va_list list; + char tmp[512]; + + va_start(list, fmt); + vsprintf(tmp, fmt, list); + va_end(list); + + SysMessage(tmp); +} + +void Log(const char *fmt, ...) +{ + va_list list; + + va_start(list, fmt); + + if (IsLogging()) vfprintf(gsLog, fmt, list); + + va_end(list); +} + +void WriteToConsole(const char *fmt, ...) +{ + va_list list; + + va_start(list, fmt); + + fprintf(stderr, "ZZogl-PG: "); + vfprintf(stderr, fmt, list); + va_end(list); +} + +void Print(const char *fmt, ...) +{ + va_list list; + + va_start(list, fmt); + + if (IsLogging()) vfprintf(gsLog, fmt, list); + + fprintf(stderr, "ZZogl-PG: "); + vfprintf(stderr, fmt, list); + + va_end(list); +} + + +void WriteLn(const char *fmt, ...) +{ + va_list list; + + va_start(list, fmt); + + if (IsLogging()) vfprintf(gsLog, fmt, list); + + fprintf(stderr, "ZZogl-PG: "); + vfprintf(stderr, fmt, list); + va_end(list); + fprintf(stderr,"\n"); +} + +void Greg_Log(const char *fmt, ...) +{ +#if defined(WRITE_GREG_LOGS) + va_list list; + char tmp[512]; + + va_start(list, fmt); + + if (IsLogging()) { + fprintf(gsLog, "GRegs: "); + vfprintf(gsLog, fmt, list); + } + //fprintf(stderr,"GRegs: "); + //vfprintf(stderr, fmt, list); + + va_end(list); + + if (IsLogging()) fprintf(gsLog, "\n"); + //fprintf(stderr,"\n"); +#endif +} + +void Prim_Log(const char *fmt, ...) +{ +#if defined(ZEROGS_DEVBUILD) && defined(WRITE_PRIM_LOGS) + va_list list; + char tmp[512]; + + va_start(list, fmt); + + if (conf.log /*& 0x00000010*/) + { + if (IsLogging()) vfprintf(gsLog, fmt, list); + + fprintf(stderr, "ZZogl-PG(PRIM): "); + vfprintf(stderr, fmt, list); + + vprintf(fmt, list); + } + + va_end(list); + fprintf(stderr,"\n"); + +#endif +} + +void GS_Log(const char *fmt, ...) +{ +#ifdef ZEROGS_DEVBUILD + va_list list; + + va_start(list, fmt); + + if (IsLogging()) + { + vfprintf(gsLog, fmt, list); + fprintf(gsLog, "\n"); + } + + fprintf(stderr, "ZZogl-PG: "); + vfprintf(stderr, fmt, list); + fprintf(stderr, "\n"); + + va_end(list); +#endif +} + +void Warn_Log(const char *fmt, ...) +{ +#ifdef ZEROGS_DEVBUILD + va_list list; + + va_start(list, fmt); + + if (IsLogging()) + { + vfprintf(gsLog, fmt, list); + fprintf(gsLog, "\n"); + } + + fprintf(stderr, "ZZogl-PG: "); + vfprintf(stderr, fmt, list); + fprintf(stderr, "\n"); + + va_end(list); +#endif +} + +void Dev_Log(const char *fmt, ...) +{ +#ifdef ZEROGS_DEVBUILD + va_list list; + + va_start(list, fmt); + + if (IsLogging()) + { + vfprintf(gsLog, fmt, list); + fprintf(gsLog, "\n"); + } + + fprintf(stderr, "ZZogl-PG: "); + vfprintf(stderr, fmt, list); + fprintf(stderr, "\n"); + + va_end(list); +#endif +} + +void Debug_Log(const char *fmt, ...) +{ +#ifdef _DEBUG + va_list list; + + va_start(list, fmt); + + if (IsLogging()) + { + vfprintf(gsLog, fmt, list); + fprintf(gsLog, "\n"); + } + + fprintf(stderr, "ZZogl-PG: "); + vfprintf(stderr, fmt, list); + fprintf(stderr, "\n"); + + va_end(list); +#endif +} + +void Error_Log(const char *fmt, ...) +{ + va_list list; + + va_start(list, fmt); + + if (IsLogging()) + { + vfprintf(gsLog, fmt, list); + fprintf(gsLog, "\n"); + } + + fprintf(stderr, "ZZogl-PG: "); + vfprintf(stderr, fmt, list); + fprintf(stderr, "\n"); + + va_end(list); +} +}; diff --git a/plugins/zzogl-pg-cg/opengl/ZZLog.h b/plugins/zzogl-pg-cg/opengl/ZZLog.h new file mode 100644 index 000000000..2dbc60b9e --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZZLog.h @@ -0,0 +1,201 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef ZZLOG_H_INCLUDED +#define ZZLOG_H_INCLUDED + +#include "Util.h" +#include + +extern void HandleGLError(); + +//Logging for errors that are called often should have a time counter. +#ifdef __LINUX__ +static u32 __attribute__((unused)) lasttime = 0; +static u32 __attribute__((unused)) BigTime = 5000; +static bool __attribute__((unused)) SPAM_PASS; +#else +static u32 lasttime = 0; +static u32 BigTime = 5000; +static bool SPAM_PASS; +#endif + +#define ERROR_LOG_SPAM(text) { \ + if( timeGetTime() - lasttime > BigTime ) { \ + ZZLog::Error_Log(text); \ + lasttime = timeGetTime(); \ + } \ +} +// The same macro with one-argument substitution. +#define ERROR_LOG_SPAMA(fmt, value) { \ + if( timeGetTime() - lasttime > BigTime ) { \ + ZZLog::Error_Log(fmt, value); \ + lasttime = timeGetTime(); \ + } \ +} + +#define ERROR_LOG_SPAM_TEST(text) {\ + if( timeGetTime() - lasttime > BigTime ) { \ + ZZLog::Error_Log(text); \ + lasttime = timeGetTime(); \ + SPAM_PASS = true; \ + } \ + else \ + SPAM_PASS = false; \ +} + +#if DEBUG_PROF +#define FILE_IS_IN_CHECK ((strcmp(__FILE__, "targets.cpp") == 0) || (strcmp(__FILE__, "ZZoglFlush.cpp") == 0)) + +#define FUNCLOG {\ + static bool Was_Here = false; \ + static unsigned long int waslasttime = 0; \ + if (!Was_Here && FILE_IS_IN_CHECK) { \ + Was_Here = true;\ + ZZLog::Error_Log("%s:%d %s", __FILE__, __LINE__, __func__); \ + waslasttime = timeGetTime(); \ + } \ + if (FILE_IS_IN_CHECK && (timeGetTime() - waslasttime > BigTime )) { \ + Was_Here = false; \ + } \ +} +#else +#define FUNCLOG +#endif + +//#define WRITE_GREG_LOGS +//#define WRITE_PRIM_LOGS +#if defined(_DEBUG) && !defined(ZEROGS_DEVBUILD) +#define ZEROGS_DEVBUILD +#endif + + +// sends a message to output window if assert fails +#define BMSG(x, str) { if( !(x) ) { ZZLog::Log(str); ZZLog::Log(str); } } +#define BMSG_RETURN(x, str) { if( !(x) ) { ZZLog::Log(str); ZZLog::Log(str); return; } } +#define BMSG_RETURNX(x, str, rtype) { if( !(x) ) { ZZLog::Log(str); ZZLog::Log(str); return (##rtype); } } +#define B(x) { if( !(x) ) { ZZLog::Log(_#x"\n"); ZZLog::Log(#x"\n"); } } +#define B_RETURN(x) { if( !(x) ) { ZZLog::Error_Log("%s:%d: %s", __FILE__, (u32)__LINE__, #x); return; } } +#define B_RETURNX(x, rtype) { if( !(x) ) { ZZLog::Error_Log("%s:%d: %s", __FILE__, (u32)__LINE__, #x); return (##rtype); } } +#define B_G(x, action) { if( !(x) ) { ZZLog::Error_Log("%s:%d: %s", __FILE__, (u32)__LINE__, #x); action; } } + +#define GL_REPORT_ERROR() \ +{ \ + GLenum err = glGetError(); \ + if( err != GL_NO_ERROR ) \ + { \ + ZZLog::Error_Log("%s:%d: gl error %s(0x%x)", __FILE__, (int)__LINE__, error_name(err), err); \ + HandleGLError(); \ + } \ +} + +#ifdef _DEBUG +# define GL_REPORT_ERRORD() \ +{ \ + GLenum err = glGetError(); \ + if( err != GL_NO_ERROR ) \ + { \ + ZZLog::Error_Log("%s:%d: gl error %s (0x%x)", __FILE__, (int)__LINE__, error_name(err), err); \ + /* HandleGLError();*/ \ + } \ +} +#else +# define GL_REPORT_ERRORD() +#endif + + +inline const char *error_name(int err) +{ + switch (err) + { + case GL_NO_ERROR: + return "GL_NO_ERROR"; + + case GL_INVALID_ENUM: + return "GL_INVALID_ENUM"; + + case GL_INVALID_VALUE: + return "GL_INVALID_VALUE"; + + case GL_INVALID_OPERATION: + return "GL_INVALID_OPERATION"; + + case GL_STACK_OVERFLOW: + return "GL_STACK_OVERFLOW"; + + case GL_STACK_UNDERFLOW: + return "GL_STACK_UNDERFLOW"; + + case GL_OUT_OF_MEMORY: + return "GL_OUT_OF_MEMORY"; + + case GL_TABLE_TOO_LARGE: + return "GL_TABLE_TOO_LARGE"; + + case GL_INVALID_FRAMEBUFFER_OPERATION: + return "GL_INVALID_FRAMEBUFFER_OPERATION"; + + default: + return "Unknown GL error"; + } +} + +struct MESSAGE +{ + MESSAGE() {} + + MESSAGE(const char* p, u32 dw) { strcpy(str, p); dwTimeStamp = dw; } + + char str[255]; + u32 dwTimeStamp; +}; + +extern void DrawText(const char* pstr, int left, int top, u32 color); +extern void __LogToConsole(const char *fmt, ...); + +extern void ZZAddMessage(const char* pstr, u32 ms = 5000); +extern void StartCapture(); +extern void StopCapture(); + + +namespace ZZLog +{ +extern bool IsLogging(); +void SetDir(const char* dir); +extern void Open(); +extern void Close(); +extern void Message(const char *fmt, ...); +extern void Log(const char *fmt, ...); +void WriteToScreen(const char* pstr, u32 ms = 5000); +void WriteToScreen2(const char* pstr, ...); +extern void WriteToConsole(const char *fmt, ...); +extern void Print(const char *fmt, ...); +extern void WriteLn(const char *fmt, ...); + +extern void Greg_Log(const char *fmt, ...); +extern void Prim_Log(const char *fmt, ...); +extern void GS_Log(const char *fmt, ...); + +extern void Debug_Log(const char *fmt, ...); +extern void Dev_Log(const char *fmt, ...); +extern void Warn_Log(const char *fmt, ...); +extern void Error_Log(const char *fmt, ...); +}; + +#endif // ZZLOG_H_INCLUDED diff --git a/plugins/zzogl-pg-cg/opengl/ZZoglCRTC.cpp b/plugins/zzogl-pg-cg/opengl/ZZoglCRTC.cpp new file mode 100644 index 000000000..152601321 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZZoglCRTC.cpp @@ -0,0 +1,895 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +// Realisation of RenderCRTC function ONLY. +// It draw picture direct on screen, so here we have interlacing and frame skipping. + +//------------------ Includes + #include "Util.h" +#include "ZZoglCRTC.h" +#include "GLWin.h" +#include "ZZoglShaders.h" +#include "ZZoglShoots.h" +#include "ZZoglDrawing.h" +#include "rasterfont.h" // simple font +#include +#include "ZZoglVB.h" + +//------------------ Defines +#if !defined(ZEROGS_DEVBUILD) +#define g_bSaveFrame 0 +#define g_bSaveFinalFrame 0 +#else +bool g_bSaveFrame = 0; // saves the current psurfTarget +bool g_bSaveFinalFrame = 0; // saves the input to the CRTC +#endif // !defined(ZEROGS_DEVBUILD) + +extern int maxmin; +extern bool g_bCRTCBilinear; +bool g_bDisplayFPS = false; +int g_nFrameRender = 10, g_nFramesSkipped = 0, s_nResolved = 0; // s_nResolved == number of targets resolved this frame +// Helper for skip frames. +int TimeLastSkip = 0; + +vector s_vecTempTextures; // temporary textures, released at the end of every frame + +// Snapshot variables. +extern bool g_bMakeSnapshot; +extern string strSnapshot; + +extern void ExtWrite(); +extern void ZZDestroy(); +extern void ChangeDeviceSize(int nNewWidth, int nNewHeight); + +extern GLuint vboRect; +// Adjusts vertex shader BitBltPos vector v to preserve aspect ratio. It used to emulate 4:3 or 16:9. +void AdjustTransToAspect(float4& v) +{ + double temp; + float f; + const float mult = 1 / 32767.0f; + + if (conf.width * GLWin.backbuffer.h > conf.height * GLWin.backbuffer.w) // limited by width + { + // change in ratio + f = ((float)GLWin.backbuffer.w / (float)conf.width) / ((float)GLWin.backbuffer.h / (float)conf.height); + v.y *= f; + v.w *= f; + + // scanlines mess up when not aligned right + v.y += (1 - (float)modf(v.y * (float)GLWin.backbuffer.h * 0.5f + 0.05f, &temp)) * 2.0f / (float)GLWin.backbuffer.h; + v.w += (1 - (float)modf(v.w * (float)GLWin.backbuffer.h * 0.5f + 0.05f, &temp)) * 2.0f / (float)GLWin.backbuffer.h; + } + else // limited by height + { + f = ((float)GLWin.backbuffer.h / (float)conf.height) / ((float)GLWin.backbuffer.w / (float)conf.width); + f -= (float)modf(f * GLWin.backbuffer.w, &temp) / (float)GLWin.backbuffer.w; + v.x *= f; + v.z *= f; + } + + v *= mult; +} + +inline bool FrameSkippingHelper() +{ + bool ShouldSkip = false; + + if (g_nFrameRender > 0) + { + if (g_nFrameRender < 8) + { + g_nFrameRender++; + + if (g_nFrameRender <= 3) + { + g_nFramesSkipped++; + ShouldSkip = true; + } + } + } + else + { + if (g_nFrameRender < -1) + { + g_nFramesSkipped++; + ShouldSkip = true; + } + + g_nFrameRender--; + } + +#if defined _DEBUG + if (timeGetTime() - TimeLastSkip > 15000 && ShouldSkip) + { + ZZLog::Debug_Log("ZZogl Skipped frames."); + TimeLastSkip = timeGetTime(); + } +#endif + + return ShouldSkip; +} + +// helper function for save frame in picture. +inline void FrameSavingHelper() +{ + if (g_bSaveFrame) + { + if (vb[0].prndr != NULL) + { + SaveTexture("frame1.tga", GL_TEXTURE_RECTANGLE_NV, vb[0].prndr->ptex, RW(vb[0].prndr->fbw), RH(vb[0].prndr->fbh)); + } + + if (vb[1].prndr != NULL && vb[0].prndr != vb[1].prndr) + { + SaveTexture("frame2.tga", GL_TEXTURE_RECTANGLE_NV, vb[1].prndr->ptex, RW(vb[1].prndr->fbw), RH(vb[1].prndr->fbh)); + } + +#ifdef _WIN32 + else + { + DeleteFile(L"frame2.tga"); + } +#endif + } +} + +// Function populated tex0Info[2] array +inline void FrameObtainDispinfo(u32 bInterlace, tex0Info* dispinfo) +{ + for (int i = 0; i < 2; ++i) + { + + if (!(*(u32*)(PMODE) & (1 << i))) + { + dispinfo[i].tw = 0; + dispinfo[i].th = 0; + continue; + } + + GSRegDISPFB* pfb = i ? DISPFB2 : DISPFB1; + GSRegDISPLAY* pd = i ? DISPLAY2 : DISPLAY1; + int magh = pd->MAGH + 1; + int magv = pd->MAGV + 1; + + dispinfo[i].tbp0 = pfb->FBP << 5; + dispinfo[i].tbw = pfb->FBW << 6; + dispinfo[i].tw = (pd->DW + 1) / magh; + dispinfo[i].th = (pd->DH + 1) / magv; + dispinfo[i].psm = pfb->PSM; + + // hack!! + // 2 * dispinfo[i].tw / dispinfo[i].th <= 1, metal slug 4 + + if (bInterlace && 2 * dispinfo[i].tw / dispinfo[i].th <= 1 && !(conf.settings().interlace_2x)) + { + dispinfo[i].th >>= 1; + } + } +} + +extern bool s_bWriteDepth; + +// Something should be done before Renderering the picture. +inline void RenderStartHelper(u32 bInterlace) +{ + if (conf.mrtdepth && pvs[8] == NULL) + { + conf.mrtdepth = 0; + s_bWriteDepth = false; + + ZZLog::Debug_Log("Disabling MRT depth writing\n"); + } + + FlushBoth(); + + FrameSavingHelper(); + + if (s_RangeMngr.ranges.size() > 0) FlushTransferRanges(NULL); + + SetShaderCaller("RenderStartHelper"); + + // reset fba after every frame + vb[0].fba.fba = 0; + vb[1].fba.fba = 0; + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the backbuffer + + glViewport(0, 0, GLWin.backbuffer.w, GLWin.backbuffer.h); + + // if interlace, only clear every other vsync + if (!bInterlace) + { + //u32 color = COLOR_ARGB(0, BGCOLOR->R, BGCOLOR->G, BGCOLOR->B); + glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + } + + ZZshSetVertexShader(pvsBitBlt.prog); + + glBindBuffer(GL_ARRAY_BUFFER, vboRect); + SET_STREAM(); + GL_REPORT_ERRORD(); + + if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + DisableAllgl(); + + GL_REPORT_ERRORD(); + + if (bInterlace) g_PrevBitwiseTexX = -1; // reset since will be using +} + +// Settings for interlace texture multiplied vector; +// The idea is: (x, y) -- position on screen, then interlaced texture get F = 1 or 0 depending +// on image y coords. So if we write valpha.z * F + valpha.w + 0.5, it would be switching odd +// and even strings at each frame. +// valpha.x and y are used for image blending. +inline float4 RenderGetForClip(u32 bInterlace, int interlace, int psm, FRAGMENTSHADER* prog) +{ + SetShaderCaller("RenderGetForClip"); + + float4 valpha; + // first render the current render targets, then from ptexMem + + if (psm == 1) + { + valpha.x = 1; + valpha.y = 0; + } + else + { + valpha.x = 0; + valpha.y = 1; + } + + if (bInterlace) + { + if (interlace == (conf.interlace & 1)) + { + // pass if odd + valpha.z = 1.0f; + valpha.w = -0.4999f; + } + else + { + // pass if even + valpha.z = -1.0f; + valpha.w = 0.5001f; + } + } + else + { + // always pass interlace test + valpha.z = 0; + valpha.w = 1; + } + + ZZshSetParameter4fv(prog->prog, prog->sOneColor, valpha, "g_fOneColor"); + + return valpha; +} + +// Put interlaced texture in use for shader prog. +// Note: if frame interlaced it's th is halved, so we should x2 it. +inline void RenderCreateInterlaceTex(u32 bInterlace, int th, FRAGMENTSHADER* prog) +{ + if (!bInterlace) return; + + int interlacetex = CreateInterlaceTex(2 * th); + + ZZshGLSetTextureParameter(prog->prog, prog->sInterlace, interlacetex, "Interlace"); +} + +// Well, do blending setup prior to second pass of half-frame drawing +inline void RenderSetupBlending() +{ + // setup right blending + glEnable(GL_BLEND); + zgsBlendEquationSeparateEXT(GL_FUNC_ADD, GL_FUNC_ADD); + + if (PMODE->MMOD) + { + glBlendColorEXT(PMODE->ALP*(1 / 255.0f), PMODE->ALP*(1 / 255.0f), PMODE->ALP*(1 / 255.0f), 0.5f); + s_srcrgb = GL_CONSTANT_COLOR_EXT; + s_dstrgb = GL_ONE_MINUS_CONSTANT_COLOR_EXT; + } + else + { + s_srcrgb = GL_SRC_ALPHA; + s_dstrgb = GL_ONE_MINUS_SRC_ALPHA; + } + + if (PMODE->AMOD) + { + s_srcalpha = GL_ZERO; + s_dstalpha = GL_ONE; + } + else + { + s_srcalpha = GL_ONE; + s_dstalpha = GL_ZERO; + } + + zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); +} + +// each frame could be drawn in two stages, so blending should be different for them +inline void RenderSetupStencil(int i) +{ + glStencilMask(1 << i); + s_stencilmask = 1 << i; + GL_STENCILFUNC_SET(); +} + +// do stencil check for each found target i -- texturing stage +inline void RenderUpdateStencil(int i, bool* bUsingStencil) +{ + if (!(*bUsingStencil)) glClear(GL_STENCIL_BUFFER_BIT); + + *bUsingStencil = 1; + + glEnable(GL_STENCIL_TEST); + GL_STENCILFUNC(GL_NOTEQUAL, 3, 1 << i); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + glStencilMask(1 << i); +} + +// CRTC24 could not be rendered +inline void RenderCRTC24helper(u32 bInterlace, int interlace, int psm) +{ + ZZLog::Debug_Log("ZZogl: CRTC24!!! I'm trying to show something."); + SetShaderCaller("RenderCRTC24helper"); + // assume that data is already in ptexMem (do Resolve?) + RenderGetForClip(bInterlace, interlace, psm, &ppsCRTC24[bInterlace]); + ZZshSetPixelShader(ppsCRTC24[bInterlace].prog); + + DrawTriangleArray(); +} + +// Maybe I do this function global-defined. Calculate bits per pixel for +// each psm. It's the only place with PSMCT16 which have a different bpp. +// FIXME: check PSMCT16S +inline int RenderGetBpp(int psm) +{ + if (psm == PSMCT16S) + { + //ZZLog::Debug_Log("ZZogl: 16S target."); + return 3; + } + + if (PSMT_ISHALF(psm)) return 2; + + return 4; +} + +// We want to draw ptarg on screen, that could be disaligned to viewport. +// So we do aligning it by height. +inline int RenderGetOffsets(int* dby, int* movy, tex0Info& texframe, CRenderTarget* ptarg, int bpp) +{ + *dby += (256 / bpp) * (texframe.tbp0 - ptarg->fbp) / texframe.tbw; + + if (*dby < 0) + { + *movy = -*dby; + *dby = 0; + } + + return min(ptarg->fbh - *dby, texframe.th - *movy); +} + +// BltBit shader calculate vertex (4 coord's pixel) position at the viewport. +inline float4 RenderSetTargetBitPos(int dh, int th, int movy, bool isInterlace) +{ + SetShaderCaller("RenderSetTargetBitPos"); + float4 v; + // dest rect + v.x = 1; + v.y = dh / (float)th; + v.z = 0; + v.w = 1 - v.y; + + if (movy > 0) v.w -= movy / (float)th; + + AdjustTransToAspect(v); + + if (isInterlace) + { + // move down by 1 pixel + v.w += 1.0f / (float)dh ; + } + + ZZshSetParameter4fv(pvsBitBlt.prog, pvsBitBlt.sBitBltPos, v, "g_fBitBltPos"); + + return v; +} + +// Important stuff. We could use these coordinates to change viewport position on the frame. +// For example, use tw / X and tw / X magnify the viewport. +// Interlaced output is little out of VB, it could be seen as an evil blinking line on top +// and bottom, so we try to remove it. +inline float4 RenderSetTargetBitTex(float th, float tw, float dh, float dw, bool isInterlace) +{ + SetShaderCaller("RenderSetTargetBitTex"); + + float4 v; + v = float4(th, tw, dh, dw); + + // Incorrect Aspect ratio on interlaced frames + + if (isInterlace) + { + v.y -= 1.0f / conf.height; + v.w += 1.0f / conf.height; + } + + ZZshSetParameter4fv(pvsBitBlt.prog, pvsBitBlt.sBitBltTex, v, "g_fBitBltTex"); + + return v; +} + +// Translator for POSITION coordinates (-1.0:+1.0f at x axis, +1.0f:-1.0y at y) into target frame ones. +// We don't need x coordinate, because interlacing is y-axis only. +inline float4 RenderSetTargetBitTrans(int th) +{ + SetShaderCaller("RenderSetTargetBitTrans"); + float4 v = float4(float(th), -float(th), float(th), float(th)); + ZZshSetParameter4fv(pvsBitBlt.prog, pvsBitBlt.fBitBltTrans, v, "g_fBitBltTrans"); + return v; +} + +// use g_fInvTexDims to store inverse texture dims +// Seems, that Targ shader does not use it +inline float4 RenderSetTargetInvTex(int bInterlace, int tw, int th, FRAGMENTSHADER* prog) +{ + SetShaderCaller("RenderSetTargetInvTex"); + + float4 v = float4(0, 0, 0, 0); + + if (prog->sInvTexDims) + { + v.x = 1.0f / (float)tw; + v.y = 1.0f / (float)th; + v.z = (float)0.0; + v.w = -0.5f / (float)th; + ZZshSetParameter4fv(prog->prog, prog->sInvTexDims, v, "g_fInvTexDims"); + } + + return v; +} + +// Metal Slug 5 hack (as was written). If target tbp not equal to framed fbp, than we look for a better possibility, +// Note, than after true result iterator it could not be used. +inline bool RenderLookForABetterTarget(int fbp, int tbp, list& listTargs, list::iterator& it) +{ + if (fbp == tbp) return false; + + // look for a better target (metal slug 5) + list::iterator itbetter; + + for (itbetter = listTargs.begin(); itbetter != listTargs.end(); ++itbetter) + { + if ((*itbetter)->fbp == tbp) break; + } + + if (itbetter != listTargs.end()) + { + it = listTargs.erase(it); + return true; + } + + return false; +} + +inline void RenderCheckForMemory(tex0Info& texframe, list& listTargs, int i, bool* bUsingStencil, int interlace, int bInterlace); + +// First try to draw frame from targets. +inline void RenderCheckForTargets(tex0Info& texframe, list& listTargs, int i, bool* bUsingStencil, int interlace, int bInterlace) +{ + // get the start and end addresses of the buffer + int bpp = RenderGetBpp(texframe.psm); + GSRegDISPFB* pfb = i ? DISPFB2 : DISPFB1; + + int start, end; + GetRectMemAddress(start, end, texframe.psm, 0, 0, texframe.tw, texframe.th, texframe.tbp0, texframe.tbw); + + // We need share list of targets between functions + s_RTs.GetTargs(start, end, listTargs); + + for (list::iterator it = listTargs.begin(); it != listTargs.end();) + { + CRenderTarget* ptarg = *it; + + if (ptarg->fbw == texframe.tbw && !(ptarg->status&CRenderTarget::TS_NeedUpdate) && ((256 / bpp)*(texframe.tbp0 - ptarg->fbp)) % texframe.tbw == 0) + { + int dby = pfb->DBY; + int movy = 0; + + if (RenderLookForABetterTarget(ptarg->fbp, texframe.tbp0, listTargs, it)) continue; + + if (g_bSaveFinalFrame) SaveTexture("frame1.tga", GL_TEXTURE_RECTANGLE_NV, ptarg->ptex, RW(ptarg->fbw), RH(ptarg->fbh)); + + // determine the rectangle to render + int dh = RenderGetOffsets(&dby, &movy, texframe, ptarg, bpp); + + if (dh >= 64) + { + + if (ptarg->fbh - dby < texframe.th - movy && !(*bUsingStencil)) + RenderUpdateStencil(i, bUsingStencil); + else if (ptarg->fbh - dby > 2 * ( texframe.th - movy )) + { + // Sometimes calculated position onscreen is misaligned, ie in FFX-2 intro. In such case some part of image are out of + // border's and we should move it manually. + dby -= ((ptarg->fbh - dby) >> 2) - ((texframe.th + movy) >> 1) ; + } + + SetShaderCaller("RenderCheckForTargets"); + + // Texture + float4 v = RenderSetTargetBitTex((float)RW(texframe.tw), (float)RH(dh), (float)RW(pfb->DBX), (float)RH(dby), INTERLACE_COUNT); + + // dest rect + v = RenderSetTargetBitPos(dh, texframe.th, movy, INTERLACE_COUNT); + v = RenderSetTargetBitTrans(ptarg->fbh); + v = RenderSetTargetInvTex(bInterlace, texframe.tbw, ptarg->fbh, &ppsCRTCTarg[bInterlace]) ; // FIXME. This is no use + + float4 valpha = RenderGetForClip(bInterlace, interlace, texframe.psm, &ppsCRTCTarg[bInterlace]); + + // inside vb[0]'s target area, so render that region only + ZZshGLSetTextureParameter(ppsCRTCTarg[bInterlace].prog, ppsCRTCTarg[bInterlace].sFinal, ptarg->ptex, "CRTC target"); + RenderCreateInterlaceTex(bInterlace, texframe.th, &ppsCRTCTarg[bInterlace]); + + ZZshSetPixelShader(ppsCRTCTarg[bInterlace].prog); + + DrawTriangleArray(); + + if (abs(dh - (int)texframe.th) <= 1) return; + + if (abs(dh - (int)ptarg->fbh) <= 1) + { + it = listTargs.erase(it); + continue; + } + } + } + + ++it; + } + RenderCheckForMemory(texframe, listTargs, i, bUsingStencil, interlace, bInterlace); +} + + +// The same as the previous, but from memory. +// If you ever wondered why a picture from a minute ago suddenly flashes on the screen (say, in Mana Khemia), +// this is the function that does it. +inline void RenderCheckForMemory(tex0Info& texframe, list& listTargs, int i, bool* bUsingStencil, int interlace, int bInterlace) +{ + float4 v; + + for (list::iterator it = listTargs.begin(); it != listTargs.end(); ++it) + { + (*it)->Resolve(); + } + + // context has to be 0 + if (bInterlace >= 2) ZZLog::Error_Log("CRCR Check for memory shader fault."); + + //if (!(*bUsingStencil)) RenderUpdateStencil(i, bUsingStencil); + + SetShaderCaller("RenderCheckForMemory"); + + float w1, h1, w2, h2; + if (g_bCRTCBilinear) + { + w1 = texframe.tw; + h1 = texframe.th; + w2 = -0.5f; + h2 = -0.5f; + SetTexVariablesInt(0, 2, texframe, false, &ppsCRTC[bInterlace], 1); + } + else + { + w1 = 1; + h1 = 1; + w2 = -0.5f / (float)texframe.tw; + h2 = -0.5f / (float)texframe.th; + SetTexVariablesInt(0, 0, texframe, false, &ppsCRTC[bInterlace], 1); + } + + if (g_bSaveFinalFrame) SaveTex(&texframe, g_bSaveFinalFrame - 1 > 0); + + // Fixme: Why is this here? + // We should probably call RenderSetTargetBitTex instead. + v = RenderSetTargetBitTex(w1, h1, w2, h2, INTERLACE_COUNT); + + // finally render from the memory (note that the stencil buffer will keep previous regions) + v = RenderSetTargetBitPos(1, 1, 0, INTERLACE_COUNT); + v = RenderSetTargetBitTrans(texframe.th); + v = RenderSetTargetInvTex(bInterlace, texframe.tw, texframe.th, &ppsCRTC[bInterlace]); + float4 valpha = RenderGetForClip(bInterlace, interlace, texframe.psm, &ppsCRTC[bInterlace]); + + ZZshGLSetTextureParameter(ppsCRTC[bInterlace].prog, ppsCRTC[bInterlace].sMemory, vb[0].pmemtarg->ptex->tex, "CRTC memory"); + RenderCreateInterlaceTex(bInterlace, texframe.th, &ppsCRTC[bInterlace]); + ZZshSetPixelShader(ppsCRTC[bInterlace].prog); + + DrawTriangleArray(); +} + +extern RasterFont* font_p; + +void DrawText(const char* pstr, int left, int top, u32 color) +{ + FUNCLOG + ZZshGLDisableProfile(); + + float4 v; + v.SetColor(color); + glColor3f(v.z, v.y, v.x); + + font_p->printString(pstr, left * 2.0f / (float)GLWin.backbuffer.w - 1, 1 - top * 2.0f / (float)GLWin.backbuffer.h, 0); + ZZshGLEnableProfile(); +} + +// Put FPS counter on screen (not in window title) +inline void DisplayFPS() +{ + char str[64]; + int left = 10, top = 15; + sprintf(str, "%.1f fps", fFPS); + + DrawText(str, left + 1, top + 1, 0xff000000); + DrawText(str, left, top, 0xffc0ffff); +} + +// SnapeShoot helper +inline void MakeSnapshot() +{ + + if (!g_bMakeSnapshot) return; + + char str[64]; + int left = 200, top = 15; + sprintf(str, "ZeroGS %d.%d.%d - %.1f fps %s", zgsrevision, zgsbuild, zgsminor, fFPS, s_frameskipping ? " - frameskipping" : ""); + + DrawText(str, left + 1, top + 1, 0xff000000); + DrawText(str, left, top, 0xffc0ffff); + + if (SaveRenderTarget(strSnapshot != "" ? strSnapshot.c_str() : "temp.jpg", GLWin.backbuffer.w, -GLWin.backbuffer.h, 0)) //(conf.options.tga_snap)?0:1) ) { + { + char str[255]; + sprintf(str, "saved %s\n", strSnapshot.c_str()); + ZZAddMessage(str, 500); + } + + g_bMakeSnapshot = false; +} + +// call to destroy video resources +void ZZReset() +{ + FUNCLOG + s_RTs.ResolveAll(); + s_DepthRTs.ResolveAll(); + + vb[0].nCount = 0; + vb[1].nCount = 0; + + memset(s_nResolveCounts, 0, sizeof(s_nResolveCounts)); + s_nLastResolveReset = 0; + + icurctx = -1; + g_vsprog = g_psprog = 0; + + ZZGSStateReset(); + ZZDestroy(); + //clear_drawfn(); + if (ZZKick != NULL) delete ZZKick; +} + +// Put new values on statistic variable +inline void CountStatistics() +{ + if (s_nWriteDepthCount > 0) + { + assert(conf.mrtdepth); + + if (--s_nWriteDepthCount <= 0) + { + s_bWriteDepth = false; + } + } + + if (s_nWriteDestAlphaTest > 0) + { + if (--s_nWriteDestAlphaTest <= 0) + { + s_bDestAlphaTest = false; + } + } + + if (g_nDepthUsed > 0) --g_nDepthUsed; + + s_ClutResolve = 0; + g_nDepthUpdateCount = 0; +} + +// This all could be easily forefeit +inline void AfterRendererUnimportantJob() +{ + ProcessMessages(); + + if (g_bDisplayFPS) DisplayFPS(); + + // Swapping buffers, so we could use another window + GLWin.SwapGLBuffers(); + + // clear all targets + if (conf.wireframe()) s_nWireframeCount = 1; + + if (g_bMakeSnapshot) MakeSnapshot(); + + CaptureFrame(); + CountStatistics(); + + if (s_nNewWidth >= 0 && s_nNewHeight >= 0) + { + // If needed reset + ZZReset(); + + ChangeDeviceSize(s_nNewWidth, s_nNewHeight); + s_nNewWidth = s_nNewHeight = -1; + } + + maxmin = 608; +} + +extern u32 s_uFramebuffer; + +// Swich Framebuffers +inline void AfterRendererSwitchBackToTextures() +{ + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, s_uFramebuffer); + + g_MemTargs.DestroyCleared(); + + if (s_vecTempTextures.size() > 0) + glDeleteTextures((GLsizei)s_vecTempTextures.size(), &s_vecTempTextures[0]); + + s_vecTempTextures.clear(); + + if (EXTWRITE->WRITE & 1) + { + ZZLog::Warn_Log("EXTWRITE!"); + ExtWrite(); + EXTWRITE->WRITE = 0; + } + + if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + glEnable(GL_SCISSOR_TEST); + + if (icurctx >= 0) + { + vb[icurctx].bVarsSetTarg = false; + vb[icurctx].bVarsTexSync = false; + vb[0].bVarsTexSync = false; + } +} + +// Reset Targets Helper, for hack. +inline void AfterRendererAutoresetTargets() +{ + if (conf.settings().auto_reset) + { + s_nResolveCounts[s_nCurResolveIndex] = s_nResolved; + s_nCurResolveIndex = (s_nCurResolveIndex + 1) % ArraySize(s_nResolveCounts); + + int total = 0; + + for (int i = 0; i < ArraySize(s_nResolveCounts); ++i) total += s_nResolveCounts[i]; + + if (total / ArraySize(s_nResolveCounts) > 3) + { + if (s_nLastResolveReset > (int)(fFPS * 8)) + { + // reset + ZZLog::Error_Log("Video memory reset."); + s_nLastResolveReset = 0; + memset(s_nResolveCounts, 0, sizeof(s_nResolveCounts)); + + s_RTs.ResolveAll(); + return; +// s_RTs.Destroy(); +// s_DepthRTs.ResolveAll(); +// s_DepthRTs.Destroy(); +// +// vb[0].prndr = NULL; +// vb[0].pdepth = NULL; +// vb[0].bNeedFrameCheck = 1; +// vb[0].bNeedZCheck = 1; +// vb[1].prndr = NULL; +// vb[1].pdepth = NULL; +// vb[1].bNeedFrameCheck = 1; +// vb[1].bNeedZCheck = 1; + } + } + + s_nLastResolveReset++; + } + + if (s_nResolved > 8) + s_nResolved = 2; + else if (s_nResolved > 0) + --s_nResolved; +} + +int count = 0; +// The main renderer function +void RenderCRTC(int interlace) +{ + if (FrameSkippingHelper()) return; + + u32 bInterlace = SMODE2->INT && SMODE2->FFMD && (conf.interlace < 2); + + RenderStartHelper(bInterlace); + + bool bUsingStencil = false; + tex0Info dispinfo[2]; + + FrameObtainDispinfo(bInterlace, dispinfo); + + // start from the last circuit + for (int i = !PMODE->SLBG; i >= 0; --i) + { + tex0Info& texframe = dispinfo[i]; + + if (texframe.th <= 1) continue; + if (SMODE2->INT && SMODE2->FFMD) + { + texframe.th >>= 1; + + // Final Fantasy X-2 issue here. + if (conf.interlace == 2 && texframe.th >= 512) + texframe.th >>= 1; + } + + if (i == 0) RenderSetupBlending(); + if (bUsingStencil) RenderSetupStencil(i); + + if (texframe.psm == 0x12) + { + RenderCRTC24helper(bInterlace, interlace, texframe.psm); + continue; + } + + // We shader targets between two functions, so declare it here; + list listTargs; + + // if we could not draw image from target's do it from memory + RenderCheckForTargets(texframe, listTargs, i, &bUsingStencil, interlace, bInterlace); + } + + GL_REPORT_ERRORD(); + + glDisable(GL_BLEND); + + AfterRendererUnimportantJob(); + AfterRendererSwitchBackToTextures(); + AfterRendererAutoresetTargets(); +} diff --git a/plugins/zzogl-pg-cg/opengl/ZZoglCRTC.h b/plugins/zzogl-pg-cg/opengl/ZZoglCRTC.h new file mode 100644 index 000000000..5ca9830e7 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZZoglCRTC.h @@ -0,0 +1,97 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef ZZOGLCRTC_H_INCLUDED +#define ZZOGLCRTC_H_INCLUDED + +#include + +#include "targets.h" + +#define INTERLACE_COUNT (bInterlace && interlace == (conf.interlace)) + +#ifdef _WIN32 +extern HDC hDC; // Private GDI Device Context +extern HGLRC hRC; // Permanent Rendering Context +#endif + +extern int s_frameskipping; +extern float fFPS; +extern unsigned char zgsrevision, zgsbuild, zgsminor; + +extern int s_nWriteDepthCount; +extern int s_nWireframeCount; +extern int s_nWriteDestAlphaTest; + +extern int g_PrevBitwiseTexX, g_PrevBitwiseTexY; // textures stored in SAMP_BITWISEANDX and SAMP_BITWISEANDY + + +extern bool s_bDestAlphaTest; +extern int s_ClutResolve; +extern int s_nLastResolveReset; +extern int g_nDepthUpdateCount; +extern int s_nResolveCounts[30]; // resolve counts for last 30 frames +static int s_nCurResolveIndex = 0; +extern int g_nDepthUsed; // ffx2 pal movies + +//------------------ Namespace + +extern u32 s_ptexInterlace; // holds interlace fields + +extern int s_nNewWidth, s_nNewHeight; + +extern CRangeManager s_RangeMngr; // manages overwritten memory +extern void FlushTransferRanges(const tex0Info* ptex); +extern void ProcessMessages(); +void AdjustTransToAspect(float4& v); + +void ZZGSStateReset(); + +// Interlace texture is lazy 1*(height) array of 1 and 0. +// If its height (named s_nInterlaceTexWidth here) is hanging we must redo +// the texture. +// FIXME: If this function were spammed too often, we could use +// width < s_nInterlaceTexWidth as correct for old texture +static int s_nInterlaceTexWidth = 0; // width of texture + +inline u32 CreateInterlaceTex(int width) +{ + if (width == s_nInterlaceTexWidth && s_ptexInterlace != 0) return s_ptexInterlace; + + SAFE_RELEASE_TEX(s_ptexInterlace); + + s_nInterlaceTexWidth = width; + + vector data(width); + + for (int i = 0; i < width; ++i) + { + data[i] = (i & 1) ? 0xffffffff : 0; + } + + glGenTextures(1, &s_ptexInterlace); + glBindTexture(GL_TEXTURE_RECTANGLE_NV, s_ptexInterlace); + TextureRect(GL_RGBA, width, 1, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); + setRectFilters(GL_NEAREST); + GL_REPORT_ERRORD(); + + return s_ptexInterlace; +} + +#endif // ZZOGLCRTC_H_INCLUDED diff --git a/plugins/zzogl-pg-cg/opengl/ZZoglCreate.cpp b/plugins/zzogl-pg-cg/opengl/ZZoglCreate.cpp new file mode 100644 index 000000000..5de08ab18 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZZoglCreate.cpp @@ -0,0 +1,877 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +// Create and Destroy function. They would be called once per session. + +//------------------ Includes +#include "GS.h" +#include "Mem.h" +#include "GLWin.h" +#include "ZZoglShaders.h" + +#include "targets.h" +#include "rasterfont.h" // simple font +#include "ZZoglDrawing.h" +#include "ZZoglVB.h" + +// This include for windows resource file with Shaders +#ifdef _WIN32 +# include "Win32.h" +#endif + +//------------------ Defines + +#ifdef _WIN32 +#define GL_LOADFN(name) { \ + if( (*(void**)&name = (void*)wglGetProcAddress(#name)) == NULL ) { \ + ZZLog::Error_Log("Failed to find %s, exiting.", #name); \ + } \ +} +#else +// let GLEW take care of it +#define GL_LOADFN(name) +#endif + +#define GL_BLEND_RGB(src, dst) { \ + s_srcrgb = src; \ + s_dstrgb = dst; \ + zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \ +} + +#define GL_BLEND_ALPHA(src, dst) { \ + s_srcalpha = src; \ + s_dstalpha = dst; \ + zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \ +} + +#define GL_BLEND_ALL(srcrgb, dstrgb, srcalpha, dstalpha) { \ + s_srcrgb = srcrgb; \ + s_dstrgb = dstrgb; \ + s_srcalpha = srcalpha; \ + s_dstalpha = dstalpha; \ + zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \ +} + +#define GL_BLEND_SET() zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha) +#define VB_NUMBUFFERS 512 + +// ----------------- Types +typedef void (APIENTRYP _PFNSWAPINTERVAL)(int); + +map mapGLExtensions; + +extern bool LoadEffects(); +extern bool ZZshLoadExtraEffects(); +extern FRAGMENTSHADER* ZZshLoadShadeEffect(int type, int texfilter, int fog, int testaem, int exactcolor, const clampInfo& clamp, int context, bool* pbFailed); + +GLuint vboRect = 0; +vector g_vboBuffers; // VBOs for all drawing commands +int g_nCurVBOIndex = 0; + +inline bool CreateImportantCheck(); +inline void CreateOtherCheck(); +inline bool CreateOpenShadersFile(); + +void ZZGSStateReset(); + +//------------------ Dummies +#ifdef _WIN32 +void __stdcall glBlendFuncSeparateDummy(GLenum e1, GLenum e2, GLenum e3, GLenum e4) +#else +void APIENTRY glBlendFuncSeparateDummy(GLenum e1, GLenum e2, GLenum e3, GLenum e4) +#endif +{ + glBlendFunc(e1, e2); +} + +#ifdef _WIN32 +void __stdcall glBlendEquationSeparateDummy(GLenum e1, GLenum e2) +#else +void APIENTRY glBlendEquationSeparateDummy(GLenum e1, GLenum e2) +#endif +{ + glBlendEquation(e1); +} + +#ifdef _WIN32 +extern HINSTANCE hInst; +void (__stdcall *zgsBlendEquationSeparateEXT)(GLenum, GLenum) = NULL; +void (__stdcall *zgsBlendFuncSeparateEXT)(GLenum, GLenum, GLenum, GLenum) = NULL; +#else +void (APIENTRY *zgsBlendEquationSeparateEXT)(GLenum, GLenum) = NULL; +void (APIENTRY *zgsBlendFuncSeparateEXT)(GLenum, GLenum, GLenum, GLenum) = NULL; +#endif + +//------------------ variables +//////////////////////////// +// State parameters + +extern u8* s_lpShaderResources; + +// String's for shader file in developer mode +#ifdef ZEROGS_DEVBUILD +char* EFFECT_NAME = ""; +char* EFFECT_DIR = ""; +#endif + +///////////////////// +// graphics resources +GLenum s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha; // set by zgsBlendFuncSeparateEXT +u32 s_stencilfunc, s_stencilref, s_stencilmask; +GLenum s_drawbuffers[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT }; + +GLenum g_internalFloatFmt = GL_ALPHA_FLOAT32_ATI; +GLenum g_internalRGBAFloatFmt = GL_RGBA_FLOAT32_ATI; +GLenum g_internalRGBAFloat16Fmt = GL_RGBA_FLOAT16_ATI; + +u32 ptexLogo = 0; +int nLogoWidth, nLogoHeight; +u32 s_ptexInterlace = 0; // holds interlace fields + +//------------------ Global Variables +int GPU_TEXWIDTH = 512; +float g_fiGPU_TEXWIDTH = 1/512.0f; +int g_MaxTexWidth = 4096, g_MaxTexHeight = 4096; +u32 s_uFramebuffer = 0; + +RasterFont* font_p = NULL; +float g_fBlockMult = 1; +//int s_nFullscreen = 0; + +u32 ptexBlocks = 0, ptexConv16to32 = 0; // holds information on block tiling +u32 ptexBilinearBlocks = 0; +u32 ptexConv32to16 = 0; +int g_nDepthBias = 0; + +extern void Delete_Avi_Capture(); +extern void ZZDestroy(); +extern void SetAA(int mode); + +//------------------ Code + +///< returns true if the the opengl extension is supported +bool IsGLExt(const char* szTargetExtension) +{ + return mapGLExtensions.find(string(szTargetExtension)) != mapGLExtensions.end(); +} + +// Function asks about different OGL extensions, that are required to setup accordingly. Return false if checks failed +inline bool CreateImportantCheck() +{ + bool bSuccess = true; +#ifndef _WIN32 + int const glew_ok = glewInit(); + + if (glew_ok != GLEW_OK) + { + ZZLog::Error_Log("glewInit() is not ok!"); + bSuccess = false; + } + +#endif + + if (!IsGLExt("GL_EXT_framebuffer_object")) + { + ZZLog::Error_Log("*********\nZZogl: ERROR: Need GL_EXT_framebuffer_object for multiple render targets\nZZogl: *********"); + bSuccess = false; + } + + if (!IsGLExt("GL_EXT_secondary_color")) + { + ZZLog::Error_Log("*********\nZZogl: OGL WARNING: Need GL_EXT_secondary_color\nZZogl: *********"); + bSuccess = false; + } + + bSuccess &= ZZshCheckProfilesSupport(); + + return bSuccess; +} + +// This is a check for less important open gl extensions. +inline void CreateOtherCheck() +{ + if (!IsGLExt("GL_EXT_blend_equation_separate") || glBlendEquationSeparateEXT == NULL) + { + ZZLog::Error_Log("*********\nZZogl: OGL WARNING: Need GL_EXT_blend_equation_separate\nZZogl: *********"); + zgsBlendEquationSeparateEXT = glBlendEquationSeparateDummy; + } + else + zgsBlendEquationSeparateEXT = glBlendEquationSeparateEXT; + + if (!IsGLExt("GL_EXT_blend_func_separate") || glBlendFuncSeparateEXT == NULL) + { + ZZLog::Error_Log("*********\nZZogl: OGL WARNING: Need GL_EXT_blend_func_separate\nZZogl: *********"); + zgsBlendFuncSeparateEXT = glBlendFuncSeparateDummy; + } + else + zgsBlendFuncSeparateEXT = glBlendFuncSeparateEXT; + + if (!IsGLExt("GL_ARB_draw_buffers") && !IsGLExt("GL_ATI_draw_buffers")) + { + ZZLog::Error_Log("*********\nZZogl: OGL WARNING: multiple render targets not supported, some effects might look bad\nZZogl: *********"); + conf.mrtdepth = 0; + } + + if (IsGLExt("GL_ARB_draw_buffers")) + glDrawBuffers = (PFNGLDRAWBUFFERSPROC)wglGetProcAddress("glDrawBuffers"); + else if (IsGLExt("GL_ATI_draw_buffers")) + glDrawBuffers = (PFNGLDRAWBUFFERSPROC)wglGetProcAddress("glDrawBuffersATI"); + + + if (!IsGLExt("GL_ARB_multitexture")) + ZZLog::Error_Log("No multitexturing."); + else + ZZLog::Error_Log("Using multitexturing."); + + GLint Max_Texture_Size_NV = 0; + + GLint Max_Texture_Size_2d = 0; + + glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_NV, &Max_Texture_Size_NV); + + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &Max_Texture_Size_2d); + + ZZLog::Error_Log("Maximum texture size is %d for Tex_2d and %d for Tex_NV.", Max_Texture_Size_2d, Max_Texture_Size_NV); + + if (Max_Texture_Size_NV < 1024) + ZZLog::Error_Log("Could not properly make bitmasks, so some textures will be missed."); + +#ifdef _WIN32 + if (IsGLExt("WGL_EXT_swap_control") || IsGLExt("EXT_swap_control")) + wglSwapIntervalEXT(0); + +#else + if (IsGLExt("GLX_SGI_swap_control")) + { + _PFNSWAPINTERVAL swapinterval = (_PFNSWAPINTERVAL)wglGetProcAddress("glXSwapInterval"); + + if (!swapinterval) + swapinterval = (_PFNSWAPINTERVAL)wglGetProcAddress("glXSwapIntervalSGI"); + + if (!swapinterval) + swapinterval = (_PFNSWAPINTERVAL)wglGetProcAddress("glXSwapIntervalEXT"); + + if (swapinterval) + swapinterval(0); + else + ZZLog::Error_Log("No support for SwapInterval (framerate clamped to monitor refresh rate),"); + } + +#endif +} + + +#ifdef _WIN32 +__forceinline bool LoadShadersFromRes() +{ + HRSRC hShaderSrc = FindResource(hInst, MAKEINTRESOURCE(IDR_SHADERS), RT_RCDATA); + assert(hShaderSrc != NULL); + HGLOBAL hShaderGlob = LoadResource(hInst, hShaderSrc); + assert(hShaderGlob != NULL); + s_lpShaderResources = (u8*)LockResource(hShaderGlob); + return true; +} +#else + +__forceinline bool LoadShadersFromDat() +{ + FILE* fres = fopen("ps2hw.dat", "rb"); + + if (fres == NULL) + { + fres = fopen("plugins/ps2hw.dat", "rb"); + + if (fres == NULL) + { + // Each linux distributions have his rules for path so we give them the possibility to + // change it with compilation flags. -- Gregory +#ifdef PLUGIN_DIR_COMPILATION +#define xPLUGIN_DIR_str(s) PLUGIN_DIR_str(s) +#define PLUGIN_DIR_str(s) #s + const std::string shader_file = string(xPLUGIN_DIR_str(PLUGIN_DIR_COMPILATION)) + "/ps2hw.dat"; + fres = fopen(shader_file.c_str(), "rb"); +#endif + if (fres == NULL) + { + ZZLog::Error_Log("Cannot find ps2hw.dat in working directory. Exiting."); + return false; + } + } + } + + fseek(fres, 0, SEEK_END); + + size_t s = ftell(fres); + s_lpShaderResources = new u8[s+1]; + fseek(fres, 0, SEEK_SET); + fread(s_lpShaderResources, s, 1, fres); + s_lpShaderResources[s] = 0; + + return true; +} + +#ifdef DEVBUILD +__forceinline bool LoadShadersFromFX() +{ + // test if ps2hw.fx exists + char tempstr[255]; + char curwd[255]; + getcwd(curwd, ArraySize(curwd)); + + strcpy(tempstr, "/plugins/"); + sprintf(EFFECT_NAME, "%sps2hw.fx", tempstr); + FILE* f = fopen(EFFECT_NAME, "r"); + + if (f == NULL) + { + + strcpy(tempstr, "../../plugins/zzogl-pg/opengl/"); + sprintf(EFFECT_NAME, "%sps2hw.fx", tempstr); + f = fopen(EFFECT_NAME, "r"); + + if (f == NULL) + { + ZZLog::Error_Log("Failed to find %s, try compiling a non-devbuild.", EFFECT_NAME); + return false; + } + } + + fclose(f); + + sprintf(EFFECT_DIR, "%s/%s", curwd, tempstr); + sprintf(EFFECT_NAME, "%sps2hw.fx", EFFECT_DIR); + + return true; +} +#endif +#endif + + +// open shader file according to build target + +inline bool CreateOpenShadersFile() +{ +#ifndef DEVBUILD +# ifdef _WIN32 + return LoadShadersFromRes(); +# else // not _WIN32 + return LoadShadersFromDat(); +# endif // _WIN32 +#else // defined(ZEROGS_DEVBUILD) +# ifndef _WIN32 // NOT WINDOWS + return LoadShadersFromFX(); + + // No else clause? +#endif +#endif // !defined(ZEROGS_DEVBUILD) +} + +// Read all extensions name and fill mapGLExtensions +inline bool CreateFillExtensionsMap() +{ + int max_ext = 0; + string all_ext(""); + + PFNGLGETSTRINGIPROC glGetStringi = 0; + glGetStringi = (PFNGLGETSTRINGIPROC)wglGetProcAddress("glGetStringi"); + glGetIntegerv(GL_NUM_EXTENSIONS, &max_ext); + + if (glGetStringi && max_ext) { + // Get opengl extension (opengl3) + for (GLint i = 0; i < max_ext; i++) + { + string extension((const char*)glGetStringi(GL_EXTENSIONS, i)); + mapGLExtensions[extension]; + + all_ext += extension; + if (i != (max_ext - 1)) all_ext += ", "; + } + } else { + // fallback to old method (pre opengl3, intel gma, geforce 7 ...) + ZZLog::Error_Log("glGetStringi opengl 3 interface not supported, fallback to opengl 2"); + + const char* ptoken = (const char*)glGetString(GL_EXTENSIONS); + if (ptoken == NULL) return false; + + all_ext = string(ptoken); // save the string to print a nice debug message + + const char* pend = NULL; + while (ptoken != NULL) + { + pend = strchr(ptoken, ' '); + + if (pend != NULL) + { + max_ext++; + mapGLExtensions[string(ptoken, pend-ptoken)]; + } + else + { + max_ext++; + mapGLExtensions[string(ptoken)]; + break; + } + + ptoken = pend; + while (*ptoken == ' ') ++ptoken; + } + } + + +#ifndef _DEBUG + ZZLog::Log("%d supported OpenGL Extensions: %s\n", max_ext, all_ext.c_str()); +#endif + ZZLog::Debug_Log("%d supported OpenGL Extensions: %s\n", max_ext, all_ext.c_str()); + + return true; +} + +void LoadglFunctions() +{ + GL_LOADFN(glIsRenderbufferEXT); + GL_LOADFN(glBindRenderbufferEXT); + GL_LOADFN(glDeleteRenderbuffersEXT); + GL_LOADFN(glGenRenderbuffersEXT); + GL_LOADFN(glRenderbufferStorageEXT); + GL_LOADFN(glGetRenderbufferParameterivEXT); + GL_LOADFN(glIsFramebufferEXT); + GL_LOADFN(glBindFramebufferEXT); + GL_LOADFN(glDeleteFramebuffersEXT); + GL_LOADFN(glGenFramebuffersEXT); + GL_LOADFN(glCheckFramebufferStatusEXT); + GL_LOADFN(glFramebufferTexture1DEXT); + GL_LOADFN(glFramebufferTexture2DEXT); + GL_LOADFN(glFramebufferTexture3DEXT); + GL_LOADFN(glFramebufferRenderbufferEXT); + GL_LOADFN(glGetFramebufferAttachmentParameterivEXT); + GL_LOADFN(glGenerateMipmapEXT); +} + +inline bool TryBlockFormat(GLint fmt, const GLvoid* vBlockData) { + g_internalFloatFmt = fmt; + glTexImage2D(GL_TEXTURE_2D, 0, g_internalFloatFmt, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, GL_ALPHA, GL_FLOAT, vBlockData); + return (glGetError() == GL_NO_ERROR); +} + +inline bool TryBlinearFormat(GLint fmt32, GLint fmt16, const GLvoid* vBilinearData) { + g_internalRGBAFloatFmt = fmt32; + g_internalRGBAFloat16Fmt = fmt16; + glTexImage2D(GL_TEXTURE_2D, 0, g_internalRGBAFloatFmt, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, GL_RGBA, GL_FLOAT, vBilinearData); + return (glGetError() == GL_NO_ERROR); +} + + +bool ZZCreate(int _width, int _height) +{ + GLenum err = GL_NO_ERROR; + bool bSuccess = true; + + ZZDestroy(); + ZZGSStateReset(); + + if (!GLWin.DisplayWindow(_width, _height)) return false; + + conf.mrtdepth = 0; // for now + + if (!CreateFillExtensionsMap()) return false; + if (!CreateImportantCheck()) return false; + + CreateOtherCheck(); + + // check the max texture width and height + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &g_MaxTexWidth); + // Limit the texture size supported to 8192. We do not need bigger texture. + // Besides the following assertion is false when texture are too big. + // ZZoglFlush.cpp:2349: assert(fblockstride >= 1.0f) + //g_MaxTexWidth = min(8192, g_MaxTexWidth); + + g_MaxTexHeight = g_MaxTexWidth / 4; + GPU_TEXWIDTH = min (g_MaxTexWidth/8, 1024); + g_fiGPU_TEXWIDTH = 1.0f / GPU_TEXWIDTH; + + if (!CreateOpenShadersFile()) return false; + + GL_REPORT_ERROR(); + + if (err != GL_NO_ERROR) bSuccess = false; + + s_srcrgb = s_dstrgb = s_srcalpha = s_dstalpha = GL_ONE; + + LoadglFunctions(); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + GL_REPORT_ERROR(); + + if (err != GL_NO_ERROR) bSuccess = false; + + glGenFramebuffersEXT(1, &s_uFramebuffer); + + if (s_uFramebuffer == 0) + { + ZZLog::Error_Log("Failed to create the renderbuffer."); + } + + GL_REPORT_ERRORD(); + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, s_uFramebuffer); + + DrawBuffers(s_drawbuffers); + + GL_REPORT_ERROR(); + + if (err != GL_NO_ERROR) bSuccess = false; + + font_p = new RasterFont(); + GL_REPORT_ERROR(); + + if (err != GL_NO_ERROR) bSuccess = false; + + // init draw fns + //init_drawfn(); + if (ZZKick != NULL) delete ZZKick; + ZZKick = new Kick; + + SetAA(conf.aa); + + GSsetGameCRC(g_LastCRC, conf.settings()._u32); + + GL_STENCILFUNC(GL_ALWAYS, 0, 0); + + //s_bWriteDepth = true; + + GL_BLEND_ALL(GL_ONE, GL_ONE, GL_ONE, GL_ONE); + glViewport(0, 0, GLWin.backbuffer.w, GLWin.backbuffer.h); // Reset The Current Viewport + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glShadeModel(GL_SMOOTH); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClearDepth(1.0f); + + glEnable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + + glDepthFunc(GL_LEQUAL); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations + glGenTextures(1, &ptexLogo); + glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptexLogo); + +#ifdef _WIN32 + HRSRC hBitmapSrc = FindResource(hInst, MAKEINTRESOURCE(IDB_ZEROGSLOGO), RT_BITMAP); + assert(hBitmapSrc != NULL); + + HGLOBAL hBitmapGlob = LoadResource(hInst, hBitmapSrc); + assert(hBitmapGlob != NULL); + + PBITMAPINFO pinfo = (PBITMAPINFO)LockResource(hBitmapGlob); + + GLenum tempFmt = (pinfo->bmiHeader.biBitCount == 32) ? GL_RGBA : GL_RGB; + TextureRect(GL_RGBA, pinfo->bmiHeader.biWidth, pinfo->bmiHeader.biHeight, tempFmt, GL_UNSIGNED_BYTE, (u8*)pinfo + pinfo->bmiHeader.biSize); + + nLogoWidth = pinfo->bmiHeader.biWidth; + nLogoHeight = pinfo->bmiHeader.biHeight; + + setRectFilters(GL_LINEAR); + +#else +#endif + + GL_REPORT_ERROR(); + + g_nCurVBOIndex = 0; + + g_vboBuffers.resize(VB_NUMBUFFERS); + glGenBuffers((GLsizei)g_vboBuffers.size(), &g_vboBuffers[0]); + + for (int i = 0; i < (int)g_vboBuffers.size(); ++i) + { + glBindBuffer(GL_ARRAY_BUFFER, g_vboBuffers[i]); + glBufferData(GL_ARRAY_BUFFER, 0x100*sizeof(VertexGPU), NULL, GL_STREAM_DRAW); + } + + GL_REPORT_ERROR(); + if (err != GL_NO_ERROR) bSuccess = false; + + // create the blocks texture + g_fBlockMult = 1; + bool do_not_use_billinear = false; + + vector vBlockData, vBilinearData; + BLOCK::FillBlocks(vBlockData, vBilinearData, 1); + + glGenTextures(1, &ptexBlocks); + glBindTexture(GL_TEXTURE_2D, ptexBlocks); + + if (TryBlockFormat(GL_RGBA32F, &vBlockData[0])) + ZZLog::Error_Log("Use GL_RGBA32F for blockdata."); + else if (TryBlockFormat(GL_ALPHA_FLOAT32_ATI, &vBlockData[0])) + ZZLog::Error_Log("Use ATI_texture_float for blockdata."); + else if (TryBlockFormat(GL_ALPHA32F_ARB, &vBlockData[0])) + ZZLog::Error_Log("Use ARB_texture_float for blockdata."); + else + { // This case is bad. But for really old cards it could be nice. + g_fBlockMult = 65535.0f*(float)g_fiGPU_TEXWIDTH; + BLOCK::FillBlocks(vBlockData, vBilinearData, 0); + g_internalFloatFmt = GL_ALPHA16; + + // We store block data on u16 rather float numbers. It's not so preciese, but ALPHA16 is OpenGL 2.0 standart + // and use only 16 bit. Old zerogs use red channel, but it does not work. + + glTexImage2D(GL_TEXTURE_2D, 0, g_internalFloatFmt, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, GL_ALPHA, GL_UNSIGNED_SHORT, &vBlockData[0]); + if( glGetError() != GL_NO_ERROR ) { + ZZLog::Error_Log("ZZogl ERROR: could not fill blocks"); + return false; + } + + do_not_use_billinear = true; + conf.bilinear = 0; + ZZLog::Error_Log("Using non-bilinear fill, quallity is outdated!"); + } + + setTex2DFilters(GL_NEAREST); + setTex2DWrap(GL_REPEAT); + + if (!do_not_use_billinear) + { + // fill in the bilinear blocks (main variant). + glGenTextures(1, &ptexBilinearBlocks); + glBindTexture(GL_TEXTURE_2D, ptexBilinearBlocks); + + if (TryBlinearFormat(GL_RGBA32F, GL_RGBA16F, &vBilinearData[0])) + ZZLog::Error_Log("Fill bilinear blocks OK.!"); + else if (TryBlinearFormat(GL_RGBA_FLOAT32_ATI, GL_RGBA_FLOAT16_ATI, &vBilinearData[0])) + ZZLog::Error_Log("Fill bilinear blocks with ATI_texture_float."); + else if (TryBlinearFormat(GL_FLOAT_RGBA32_NV, GL_FLOAT_RGBA16_NV, &vBilinearData[0])) + ZZLog::Error_Log("ZZogl Fill bilinear blocks with NVidia_float."); + else + ZZLog::Error_Log("Fill bilinear blocks failed."); + + setTex2DFilters(GL_NEAREST); + setTex2DWrap(GL_REPEAT); + } + + float fpri = 1; + + glPrioritizeTextures(1, &ptexBlocks, &fpri); + + if (ptexBilinearBlocks != 0) glPrioritizeTextures(1, &ptexBilinearBlocks, &fpri); + + GL_REPORT_ERROR(); + + // fill a simple rect + glGenBuffers(1, &vboRect); + glBindBuffer(GL_ARRAY_BUFFER, vboRect); + + vector verts(4); + + VertexGPU* pvert = &verts[0]; + + pvert->set_xyzst(-0x7fff, 0x7fff, 0, 0, 0); + pvert++; + + pvert->set_xyzst(0x7fff, 0x7fff, 0, 1, 0); + pvert++; + + pvert->set_xyzst(-0x7fff, -0x7fff, 0, 0, 1); + pvert++; + + pvert->set_xyzst(0x7fff, -0x7fff, 0, 1, 1); + pvert++; + + glBufferDataARB(GL_ARRAY_BUFFER, 4*sizeof(VertexGPU), &verts[0], GL_STATIC_DRAW); + + // setup the default vertex declaration + glEnableClientState(GL_VERTEX_ARRAY); + glClientActiveTexture(GL_TEXTURE0); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_SECONDARY_COLOR_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + GL_REPORT_ERROR(); + + // some cards don't support this +// glClientActiveTexture(GL_TEXTURE0); +// glEnableClientState(GL_TEXTURE_COORD_ARRAY); +// glTexCoordPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexGPU), (void*)12); + + // create the conversion textures + glGenTextures(1, &ptexConv16to32); + glBindTexture(GL_TEXTURE_2D, ptexConv16to32); + + vector conv16to32data(256*256); + + for (int i = 0; i < 256*256; ++i) + { + u32 tempcol = RGBA16to32(i); + // have to flip r and b + conv16to32data[i] = (tempcol & 0xff00ff00) | ((tempcol & 0xff) << 16) | ((tempcol & 0xff0000) >> 16); + } + + Texture2D(4, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, &conv16to32data[0]); + + setTex2DFilters(GL_NEAREST); + setTex2DWrap(GL_CLAMP); + + GL_REPORT_ERROR(); + + if (err != GL_NO_ERROR) bSuccess = false; + + vector conv32to16data(32*32*32); + + glGenTextures(1, &ptexConv32to16); + + glBindTexture(GL_TEXTURE_3D, ptexConv32to16); + + u32* dst = &conv32to16data[0]; + + for (int i = 0; i < 32; ++i) + { + for (int j = 0; j < 32; ++j) + { + for (int k = 0; k < 32; ++k) + { + u32 col = (i << 10) | (j << 5) | k; + *dst++ = ((col & 0xff) << 16) | (col & 0xff00); + } + } + } + + Texture3D(4, 32, 32, 32, GL_RGBA, GL_UNSIGNED_BYTE, &conv32to16data[0]); + setTex3DFilters(GL_NEAREST); + setTex3DWrap(GL_CLAMP); + GL_REPORT_ERROR(); + + if (err != GL_NO_ERROR) bSuccess = false; + + if (!ZZshStartUsingShaders()) bSuccess = false; + + GL_REPORT_ERROR(); + + if (err != GL_NO_ERROR) bSuccess = false; + + glDisable(GL_STENCIL_TEST); + glEnable(GL_SCISSOR_TEST); + + GL_BLEND_ALPHA(GL_ONE, GL_ZERO); + + glBlendColorEXT(0, 0, 0, 0.5f); + + glDisable(GL_CULL_FACE); + + // points + // This was changed in SetAA - should we be changing it back? + glPointSize(1.0f); + + g_nDepthBias = 0; + + glEnable(GL_POLYGON_OFFSET_FILL); + glEnable(GL_POLYGON_OFFSET_LINE); + + glPolygonOffset(0, 1); + + vb[0].Init(VB_BUFFERSIZE); + vb[1].Init(VB_BUFFERSIZE); + + g_vsprog = g_psprog = 0; + + if (glGetError() == GL_NO_ERROR) + { + return bSuccess; + } + else + { + ZZLog::Debug_Log("In final init!"); + return false; + } +} + +void ZZDestroy() +{ + Delete_Avi_Capture(); + + g_MemTargs.Destroy(); + + s_RTs.Destroy(); + s_DepthRTs.Destroy(); + s_BitwiseTextures.Destroy(); + + SAFE_RELEASE_TEX(s_ptexInterlace); + SAFE_RELEASE_TEX(ptexBlocks); + SAFE_RELEASE_TEX(ptexBilinearBlocks); + SAFE_RELEASE_TEX(ptexConv16to32); + SAFE_RELEASE_TEX(ptexConv32to16); + + vb[0].Destroy(); + vb[1].Destroy(); + + if (g_vboBuffers.size() > 0) + { + glDeleteBuffers((GLsizei)g_vboBuffers.size(), &g_vboBuffers[0]); + g_vboBuffers.clear(); + } + + g_nCurVBOIndex = 0; + + if (pvs != NULL) + { + for (int i = 0; i < ArraySize(pvs); ++i) + { + SAFE_RELEASE_PROG(pvs[i]); + } + } + + if (ppsRegular != NULL) + { + for (int i = 0; i < ArraySize(ppsRegular); ++i) + { + SAFE_RELEASE_PROG(ppsRegular[i].prog); + } + } + + if (ppsTexture != NULL) + { + for (int i = 0; i < ArraySize(ppsTexture); ++i) + { + SAFE_RELEASE_PROG(ppsTexture[i].prog); + } + } + + SAFE_RELEASE_PROG(pvsBitBlt.prog); + + SAFE_RELEASE_PROG(ppsBitBlt[0].prog); + SAFE_RELEASE_PROG(ppsBitBlt[1].prog); + SAFE_RELEASE_PROG(ppsBitBltDepth.prog); + SAFE_RELEASE_PROG(ppsCRTCTarg[0].prog); + SAFE_RELEASE_PROG(ppsCRTCTarg[1].prog); + SAFE_RELEASE_PROG(ppsCRTC[0].prog); + SAFE_RELEASE_PROG(ppsCRTC[1].prog); + SAFE_RELEASE_PROG(ppsCRTC24[0].prog); + SAFE_RELEASE_PROG(ppsCRTC24[1].prog); + SAFE_RELEASE_PROG(ppsOne.prog); + + safe_delete(font_p); + + GLWin.ReleaseContext(); + + mapGLExtensions.clear(); +} + diff --git a/plugins/zzogl-pg-cg/opengl/ZZoglDrawing.cpp b/plugins/zzogl-pg-cg/opengl/ZZoglDrawing.cpp new file mode 100644 index 000000000..dacabc149 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZZoglDrawing.cpp @@ -0,0 +1,255 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "ZZoglDrawing.h" +#include "ZZoglVB.h" + +Kick* ZZKick; + +const u32 g_primmult[8] = { 1, 2, 2, 3, 3, 3, 2, 0xff }; +const u32 g_primsub[8] = { 1, 2, 1, 3, 1, 1, 2, 0 }; + +const GLenum primtype[8] = { GL_POINTS, GL_LINES, GL_LINES, GL_TRIANGLES, GL_TRIANGLES, GL_TRIANGLES, GL_TRIANGLES, 0xffffffff }; + +extern float fiTexWidth[2], fiTexHeight[2]; // current tex width and height + +// Still thinking about the best place to put this. +// called on a primitive switch +void Prim() +{ + FUNCLOG + + VB& curvb = vb[prim->ctxt]; + + if (curvb.CheckPrim()) Flush(prim->ctxt); + curvb.SetCurrentPrim(); +} + +// Replaced by a macro -> see ZZoglDrawing.h +// return true if triangle SHOULD be painted. +// Hackish and should be replaced. +// bool __forceinline NoHighlights(int i) +// { +// //Old code +// return (!(conf.settings().xenosaga_spec) || !vb[i].zbuf.zmsk || prim->iip) ; +// } + +// Not inlining for the moment to avoid getting 'unresolved external symbol' errors in Windows. +// This could also be resolved by moving the function into the header... +void Kick::KickVertex(bool adc) +{ + FUNCLOG + if (++gs.primC >= (int)g_primmult[prim->prim]) + { + if (!adc && NoHighlights(prim->ctxt)) DrawPrim(prim->prim); + else DirtyValidPrevPrim(); + + gs.primC -= g_primsub[prim->prim]; + } + gs.primIndex = gs.primNext(); +} + +template +void Kick::Set_Vertex(VertexGPU *p, Vertex & gsvertex) +{ + VB& curvb = vb[prim->ctxt]; + + p->move_x(gsvertex, curvb.offset.x); + p->move_y(gsvertex, curvb.offset.y); + if(DO_Z_FOG) { + p->move_z(gsvertex, curvb.zprimmask); + p->move_fog(gsvertex); + } + + p->rgba = prim->iip ? gsvertex.rgba : gs.rgba; + + if (conf.settings().texa) + { + u32 B = ((p->rgba & 0xfe000000) >> 1) + (0x01000000 * vb[prim->ctxt].fba.fba); + p->rgba = (p->rgba & 0xffffff) + B; + } + + if (prim->tme) + { + if (prim->fst) + { + p->s = (float)gsvertex.u * fiTexWidth[prim->ctxt]; + p->t = (float)gsvertex.v * fiTexHeight[prim->ctxt]; + p->q = 1; + } + else + { + p->s = gsvertex.s; + p->t = gsvertex.t; + p->q = gsvertex.q; + } + } +} + +__forceinline void Kick::Output_Vertex(VertexGPU vert, u32 id) +{ +#ifdef WRITE_PRIM_LOGS + ZZLog::Prim_Log("%c%d(%d): xyzf=(%4d,%4d,0x%x,%3d), rgba=0x%8.8x, stq = (%2.5f,%2.5f,%2.5f)", + id == 0 ? '*' : ' ', id, prim->prim, vert.x / 8, vert.y / 8, vert.z, vert.f / 128, + vert.rgba, Clamp(vert.s, -10, 10), Clamp(vert.t, -10, 10), Clamp(vert.q, -10, 10)); +#endif +} + +void Kick::DrawPrim(u32 prim_type) +{ + VB& curvb = vb[prim->ctxt]; + + curvb.FlushTexData(); + + if ((vb[!prim->ctxt].nCount > 0) && (vb[prim->ctxt].gsfb.fbp == vb[!prim->ctxt].gsfb.fbp)) + { + assert(vb[prim->ctxt].nCount == 0); + Flush(!prim->ctxt); + } + + // check enough place is left for the biggest primitive (sprite) + // This function is unlikely to be called so do not inline it. + if (unlikely(curvb.nCount + 6 > curvb.nNumVertices)) + curvb.IncreaseVertexBuffer(); + + VertexGPU* p = curvb.pBufferData + curvb.nCount; + + u32 prev; + u32 last; + switch(prim_type) { + case PRIM_POINT: + Set_Vertex(&p[0], gs.gsvertex[gs.primIndex]); + curvb.nCount ++; + break; + + case PRIM_LINE: + Set_Vertex(&p[0], gs.gsvertex[gs.primPrev()]); + Set_Vertex(&p[1], gs.gsvertex[gs.primIndex]); + curvb.nCount += 2; + break; + + case PRIM_LINE_STRIP: + if (likely(ValidPrevPrim)) { + assert(curvb.nCount >= 1); + p[0] = p[-1]; + } else { + Set_Vertex(&p[0], gs.gsvertex[gs.primPrev()]); + ValidPrevPrim = true; + } + + Set_Vertex(&p[1], gs.gsvertex[gs.primIndex]); + curvb.nCount += 2; + break; + + case PRIM_TRIANGLE: + Set_Vertex(&p[0], gs.gsvertex[gs.primPrev(2)]); + Set_Vertex(&p[1], gs.gsvertex[gs.primPrev()]); + Set_Vertex(&p[2], gs.gsvertex[gs.primIndex]); + curvb.nCount += 3; + break; + + case PRIM_TRIANGLE_STRIP: + if (likely(ValidPrevPrim)) { + assert(curvb.nCount >= 2); + p[0] = p[-2]; + p[1] = p[-1]; + } else { + Set_Vertex(&p[0], gs.gsvertex[gs.primPrev(2)]); + Set_Vertex(&p[1], gs.gsvertex[gs.primPrev()]); + ValidPrevPrim = true; + } + + Set_Vertex(&p[2], gs.gsvertex[gs.primIndex]); + curvb.nCount += 3; + break; + + case PRIM_TRIANGLE_FAN: + if (likely(ValidPrevPrim)) { + assert(curvb.nCount >= 2); + VertexGPU* TriFanVert = curvb.pBufferData + gs.nTriFanVert; + p[0] = TriFanVert[0]; + p[1] = p[-1]; + } else { + Set_Vertex(&p[0], gs.gsTriFanVertex); + Set_Vertex(&p[1], gs.gsvertex[gs.primPrev(1)]); + ValidPrevPrim = true; + // Remenber the base for future processing + gs.nTriFanVert = curvb.nCount; + } + + Set_Vertex(&p[2], gs.gsvertex[gs.primIndex]); + curvb.nCount += 3; + break; + + case PRIM_SPRITE: + prev = gs.primPrev(); + last = gs.primIndex; + + // sprite is too small and AA shows lines (tek4, Mana Khemia) + gs.gsvertex[last].x += (4 * AA.x); + gs.gsvertex[last].y += (4 * AA.y); + + // might be bad sprite (KH dialog text) + //if( gs.gsvertex[prev].x == gs.gsvertex[last].x || gs.gsvertex[prev].y == gs.gsvertex[last].y ) + //return; + + // process sprite as 2 triangles. The common diagonal is 0,1 and 3,4 + Set_Vertex(&p[0], gs.gsvertex[prev]); + Set_Vertex(&p[1], gs.gsvertex[last]); + + // Only fog and Z of last vertex is valid + p[0].z = p[1].z; + p[0].f = p[1].f; + + // Duplicate the vertex + p[3] = p[0]; + p[2] = p[0]; + p[4] = p[1]; + p[5] = p[1]; + + // Move some vertex x coord to create the others corners of the sprite + p[2].s = p[1].s; + p[2].x = p[1].x; + p[5].s = p[0].s; + p[5].x = p[0].x; + + curvb.nCount += 6; + break; + + default: break; + } + + // Print DEBUG info and code assertion + switch(prim_type) { + case PRIM_TRIANGLE: + case PRIM_TRIANGLE_STRIP: + case PRIM_TRIANGLE_FAN: + assert(gs.primC >= 3); + Output_Vertex(p[2],2); + case PRIM_LINE: + case PRIM_LINE_STRIP: + case PRIM_SPRITE: + assert(gs.primC >= 2); + Output_Vertex(p[1],1); + case PRIM_POINT: + assert(gs.primC >= 1); + Output_Vertex(p[0],0); + default: break; + } +} diff --git a/plugins/zzogl-pg-cg/opengl/ZZoglDrawing.h b/plugins/zzogl-pg-cg/opengl/ZZoglDrawing.h new file mode 100644 index 000000000..c9387b791 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZZoglDrawing.h @@ -0,0 +1,67 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef ZZOGLDRAWING_H_INCLUDED +#define ZZOGLDRAWING_H_INCLUDED + +#include "Util.h" +#include "GS.h" + +// extern bool __forceinline NoHighlights(int i); + +// return true if triangle SHOULD be painted. +// Hackish and should be replaced. +// Previous version was an inlined function but gcc-4.6 does not want to inline it. +// Because the code is in the middle of vertex which are very often call, +// a basic macro is more effective -- Gregory +#define NoHighlights(I) (!(conf.settings().xenosaga_spec) || !vb[(I)].zbuf.zmsk || prim->iip) + +enum PRIM_TYPE { + PRIM_POINT = 0, + PRIM_LINE, + PRIM_LINE_STRIP, + PRIM_TRIANGLE, + PRIM_TRIANGLE_STRIP, + PRIM_TRIANGLE_FAN, + PRIM_SPRITE, + PRIM_DUMMY +}; + +class Kick +{ + private: + // template void Set_Vertex(VertexGPU *p, int i); + template void Set_Vertex(VertexGPU *p, Vertex &gsvertex); + void Output_Vertex(VertexGPU vert, u32 id); + bool ValidPrevPrim; + public: + Kick() { } + ~Kick() { } + + void KickVertex(bool adc); + + void DrawPrim(u32 i); + + inline void DirtyValidPrevPrim() { + ValidPrevPrim = 0; + } +}; +extern Kick* ZZKick; + +#endif // ZZOGLDRAWING_H_INCLUDED diff --git a/plugins/zzogl-pg-cg/opengl/ZZoglFlush.cpp b/plugins/zzogl-pg-cg/opengl/ZZoglFlush.cpp new file mode 100644 index 000000000..bbe3e2a00 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZZoglFlush.cpp @@ -0,0 +1,2874 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +// Realization of Flush -- drawing function of GS + +#include + +#include "GS.h" +#include "Mem.h" +#include "targets.h" +#include "ZZoglFlushHack.h" +#include "ZZoglShaders.h" +#include "ZZClut.h" +#include + +//------------------ Defines +#ifndef ZEROGS_DEVBUILD + +#define INC_GENVARS() +#define INC_TEXVARS() +#define INC_ALPHAVARS() +#define INC_RESOLVE() + +#define g_bUpdateEffect 0 +#define g_bSaveTex 0 +bool g_bSaveTrans = 0; +#define g_bSaveResolved 0 + +#else // defined(ZEROGS_DEVBUILD) + +#define INC_GENVARS() ++g_nGenVars +#define INC_TEXVARS() ++g_nTexVars +#define INC_ALPHAVARS() ++g_nAlphaVars +#define INC_RESOLVE() ++g_nResolve + +bool g_bSaveTrans = 0; +bool g_bUpdateEffect = 0; +bool g_bSaveTex = 0; // saves the curent texture +bool g_bSaveResolved = 0; +#endif // !defined(ZEROGS_DEVBUILD) + +#define STENCIL_ALPHABIT 1 // if set, dest alpha >= 0x80 +#define STENCIL_PIXELWRITE 2 // if set, pixel just written (reset after every Flush) +#define STENCIL_FBA 4 // if set, just written pixel's alpha >= 0 (reset after every Flush) +#define STENCIL_SPECIAL 8 // if set, indicates that pixel passed its alpha test (reset after every Flush) +//#define STENCIL_PBE 16 +#define STENCIL_CLEAR (2|4|8|16) + +void Draw(const VB& curvb) +{ + glDrawArrays(primtype[curvb.curprim.prim], 0, curvb.nCount); +} + +#define GL_BLEND_RGB(src, dst) { \ + s_srcrgb = src; \ + s_dstrgb = dst; \ + zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \ +} + +#define GL_BLEND_ALPHA(src, dst) { \ + s_srcalpha = src; \ + s_dstalpha = dst; \ + zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \ +} + +#define GL_BLEND_ALL(srcrgb, dstrgb, srcalpha, dstalpha) { \ + s_srcrgb = srcrgb; \ + s_dstrgb = dstrgb; \ + s_srcalpha = srcalpha; \ + s_dstalpha = dstalpha; \ + zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \ +} + +#define GL_ZTEST(enable) { \ + if (enable) glEnable(GL_DEPTH_TEST); \ + else glDisable(GL_DEPTH_TEST); \ +} + +#define GL_ALPHATEST(enable) { \ + if( enable ) glEnable(GL_ALPHA_TEST); \ + else glDisable(GL_ALPHA_TEST); \ +} + +#define GL_BLENDEQ_RGB(eq) { \ + s_rgbeq = eq; \ + zgsBlendEquationSeparateEXT(s_rgbeq, s_alphaeq); \ +} + +#define GL_BLENDEQ_ALPHA(eq) { \ + s_alphaeq = eq; \ + zgsBlendEquationSeparateEXT(s_rgbeq, s_alphaeq); \ +} + +#define COLORMASK_RED 1 +#define COLORMASK_GREEN 2 +#define COLORMASK_BLUE 4 +#define COLORMASK_ALPHA 8 +#define GL_COLORMASK(mask) glColorMask(!!((mask)&COLORMASK_RED), !!((mask)&COLORMASK_GREEN), !!((mask)&COLORMASK_BLUE), !!((mask)&COLORMASK_ALPHA)) + +// ----------------- Types +//------------------ Dummies + +//------------------ variables + +extern int g_nDepthBias; +extern float g_fBlockMult; // used for old cards, that do not support Alpha-32float textures. We store block data in u16 and use it. +bool g_bUpdateStencil = 1; + +extern ZZshProgram g_psprog; // 2 -- ZZ + +// local alpha blending settings +static GLenum s_rgbeq, s_alphaeq; // set by zgsBlendEquationSeparateEXT // ZZ + + +static const u32 blendalpha[3] = { GL_SRC_ALPHA, GL_DST_ALPHA, GL_CONSTANT_COLOR_EXT }; // ZZ +static const u32 blendinvalpha[3] = { GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_CONSTANT_COLOR_EXT }; //ZZ +static const u32 g_dwAlphaCmp[] = { GL_NEVER, GL_ALWAYS, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL }; // ZZ + +// used for afail case +static const u32 g_dwReverseAlphaCmp[] = { GL_ALWAYS, GL_NEVER, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL, GL_LESS, GL_LEQUAL, GL_EQUAL }; +static const u32 g_dwZCmp[] = { GL_NEVER, GL_ALWAYS, GL_GEQUAL, GL_GREATER }; + +///////////////////// +// graphics resources +#define s_bForceTexFlush 1 // ZZ +static u32 s_ptexCurSet[2] = {0}; +static u32 s_ptexNextSet[2] = {0}; // ZZ + + +extern vector s_vecTempTextures; // temporary textures, released at the end of every frame +extern bool s_bTexFlush; +extern int g_nCurVBOIndex; +bool s_bWriteDepth = false; +bool s_bDestAlphaTest = false; +int s_ClutResolve = 0; // ZZ +int g_nDepthUsed = 0; // ffx2 pal movies +int s_nWriteDepthCount = 0; // ZZ +int s_nWriteDestAlphaTest = 0; // ZZ + +//////////////////// +// State parameters +static float4 vAlphaBlendColor; // used for GPU_COLOR + +static bool bNeedBlendFactorInAlpha; // set if the output source alpha is different from the real source alpha (only when blend factor > 0x80) +static u32 s_dwColorWrite = 0xf; // the color write mask of the current target + +typedef union +{ + struct + { + u8 _bNeedAlphaColor; // set if vAlphaBlendColor needs to be set + u8 _b2XAlphaTest; // Only valid when bNeedAlphaColor is set. if 1st bit set set, double all alpha testing values + // otherwise alpha testing needs to be done separately. + u8 _bDestAlphaColor; // set to 1 if blending with dest color (process only one tri at a time). If 2, dest alpha is always 1. + u8 _bAlphaClamping; // if first bit is set, do min; if second bit, do max + }; + + u32 _bAlphaState; +} g_flag_vars; + +g_flag_vars g_vars; + +//#define bNeedAlphaColor g_vars._bNeedAlphaColor +#define b2XAlphaTest g_vars._b2XAlphaTest +#define bDestAlphaColor g_vars._bDestAlphaColor +#define bAlphaClamping g_vars._bAlphaClamping + +int g_PrevBitwiseTexX = -1, g_PrevBitwiseTexY = -1; // textures stored in SAMP_BITWISEANDX and SAMP_BITWISEANDY // ZZ + +//static alphaInfo s_alphaInfo; // ZZ + +extern u8* g_pbyGSClut; +extern int ppf; + +int s_nWireframeCount = 0; + +//------------------ Namespace + +VB vb[2]; +float fiTexWidth[2], fiTexHeight[2]; // current tex width and height +extern vector g_vboBuffers; // VBOs for all drawing commands + +//u8 s_AAx = 0, s_AAy = 0; // if AAy is set, then AAx has to be set +Point AA = {0,0}; + +int icurctx = -1; + +extern CRangeManager s_RangeMngr; // manages overwritten memory // zz +void FlushTransferRanges(const tex0Info* ptex); //zz + +// use to update the state +void SetTexVariables(int context, FRAGMENTSHADER* pfragment); // zz +void SetTexInt(int context, FRAGMENTSHADER* pfragment, int settexint); // zz +void SetAlphaVariables(const alphaInfo& ainfo); // zzz +//void ResetAlphaVariables(); + +inline void SetAlphaTestInt(pixTest curtest); + +inline void RenderAlphaTest(const VB& curvb, ZZshParameter sOneColor); +inline void RenderStencil(const VB& curvb, u32 dwUsingSpecialTesting); +inline void ProcessStencil(const VB& curvb); +inline void RenderFBA(const VB& curvb, ZZshParameter sOneColor); +inline void ProcessFBA(const VB& curvb, ZZshParameter sOneColor); // zz + +void SetContextTarget(int context); + +void SetWriteDepth(); +bool IsWriteDepth(); +void SetDestAlphaTest(); + +//------------------ Code + +inline float AlphaReferedValue(int aref) +{ + return b2XAlphaTest ? min(1.0f, (float)aref / 127.5f) : (float)aref / 255.0f ; +} + +inline void SetAlphaTest(const pixTest& curtest) +{ + // if s_dwColorWrite is nontrivial, than we should not off alphatest. + // This fix GOW and Okami. + if (!curtest.ate && USEALPHATESTING && (s_dwColorWrite != 2 && s_dwColorWrite != 14)) + { + glDisable(GL_ALPHA_TEST); + } + else + { + glEnable(GL_ALPHA_TEST); + glAlphaFunc(g_dwAlphaCmp[curtest.atst], AlphaReferedValue(curtest.aref)); + } +} + +// Return, if tcc, aem or psm mode told us, than Alpha test should be used +// if tcc == 0 than no alpha used, aem used for alpha expanding and I am not sure +// that it's correct, psm -- color mode, +inline bool IsAlphaTestExpansion(tex0Info tex0) +{ + return (tex0.tcc && gs.texa.aem && PSMT_ALPHAEXP(PIXEL_STORAGE_FORMAT(tex0))); +} + +// Switch wireframe rendering off for first flush, so it's draw few solid primitives +inline void SwitchWireframeOff() +{ + if (conf.wireframe()) + { + if (s_nWireframeCount > 0) + { + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } + } +} + +// Switch wireframe rendering on, look at previous function +inline void SwitchWireframeOn() +{ + if (conf.wireframe()) + { + if (s_nWireframeCount > 0) + { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + --s_nWireframeCount; + } + } +} + +extern u32 ptexBilinearBlocks; + +int GetTexFilter(const tex1Info& tex1) +{ + // always force + if (conf.bilinear == 2) return 1; + + int texfilter = 0; + + if (conf.bilinear && ptexBilinearBlocks != 0) + { + if (tex1.mmin <= 1) + texfilter = tex1.mmin | tex1.mmag; + else + texfilter = tex1.mmag ? ((tex1.mmin + 2) & 5) : tex1.mmin; + + texfilter = texfilter == 1 || texfilter == 4 || texfilter == 5; + } + + return texfilter; +} + +void ReloadEffects() +{ +#ifdef ZEROGS_DEVBUILD + + for (int i = 0; i < ArraySize(ppsTexture); ++i) + { + SAFE_RELEASE_PROG(ppsTexture[i].prog); + } + + memset(ppsTexture, 0, sizeof(ppsTexture)); + + ZZshLoadExtraEffects(); +#endif +} + +long BufferNumber = 0; + +// This is a debug function. It prints all buffer info and save current texture into the file, then prints the file name. +inline void VisualBufferMessage(int context) +{ +#if defined(WRITE_PRIM_LOGS) && defined(_DEBUG) + BufferNumber++; + VB& curvb = vb[context]; + static const char* patst[8] = { "NEVER", "ALWAYS", "LESS", "LEQUAL", "EQUAL", "GEQUAL", "GREATER", "NOTEQUAL"}; + static const char* pztst[4] = { "NEVER", "ALWAYS", "GEQUAL", "GREATER" }; + static const char* pafail[4] = { "KEEP", "FB_ONLY", "ZB_ONLY", "RGB_ONLY" }; + ZZLog::Debug_Log("**Drawing ctx %d, num %d, fbp: 0x%x, zbp: 0x%x, fpsm: %d, zpsm: %d, fbw: %d", context, vb[context].nCount, curvb.prndr->fbp, curvb.zbuf.zbp, curvb.prndr->psm, curvb.zbuf.psm, curvb.prndr->fbw); + ZZLog::Debug_Log("prim: prim=%x iip=%x tme=%x fge=%x abe=%x aa1=%x fst=%x ctxt=%x fix=%x", + curvb.curprim.prim, curvb.curprim.iip, curvb.curprim.tme, curvb.curprim.fge, curvb.curprim.abe, curvb.curprim.aa1, curvb.curprim.fst, curvb.curprim.ctxt, curvb.curprim.fix); + ZZLog::Debug_Log("test: ate:%d, atst: %s, aref: %d, afail: %s, date: %d, datm: %d, zte: %d, ztst: %s, fba: %d", + curvb.test.ate, patst[curvb.test.atst], curvb.test.aref, pafail[curvb.test.afail], curvb.test.date, curvb.test.datm, curvb.test.zte, pztst[curvb.test.ztst], curvb.fba.fba); + ZZLog::Debug_Log("alpha: A%d B%d C%d D%d FIX:%d pabe: %d; aem: %d, ta0: %d, ta1: %d\n", curvb.alpha.a, curvb.alpha.b, curvb.alpha.c, curvb.alpha.d, curvb.alpha.fix, gs.pabe, gs.texa.aem, gs.texa.ta[0], gs.texa.ta[1]); + ZZLog::Debug_Log("tex0: tbp0=0x%x, tbw=%d, psm=0x%x, tw=%d, th=%d, tcc=%d, tfx=%d, cbp=0x%x, cpsm=0x%x, csm=%d, csa=%d, cld=%d", + curvb.tex0.tbp0, curvb.tex0.tbw, curvb.tex0.psm, curvb.tex0.tw, + curvb.tex0.th, curvb.tex0.tcc, curvb.tex0.tfx, curvb.tex0.cbp, + curvb.tex0.cpsm, curvb.tex0.csm, curvb.tex0.csa, curvb.tex0.cld); + char* Name; + Name = NamedSaveTex(&curvb.tex0, 1); + ZZLog::Error_Log("TGA name '%s'.", Name); + free(Name); + ZZLog::Debug_Log("buffer %ld.\n", BufferNumber); +#endif +} + +inline void SaveRendererTarget(VB& curvb) +{ +#ifdef _DEBUG + +// Needs a # after rndr to work... +// char str[255]; +// sprintf(str, "rndr.tga"); +// SaveRenderTarget(str, curvb.prndr->fbw, curvb.prndr->fbh, 0); + +#endif +} + +// Stop effects in Developers mode +inline void FlushUpdateEffect() +{ +#if defined(DEVBUILD) + + if (g_bUpdateEffect) + { + ReloadEffects(); + g_bUpdateEffect = 0; + } + +#endif +} + +// Check, maybe we cold skip flush +inline bool IsFlushNoNeed(VB& curvb, const pixTest& curtest) +{ + if (curvb.nCount == 0 || (curtest.zte && curtest.ztst == 0) || IsBadFrame(curvb)) + { + curvb.nCount = 0; + return true; + } + + return false; +} + +// Transfer targets, that are located in current texture. +inline void FlushTransferRangesHelper(VB& curvb) +{ + if (s_RangeMngr.ranges.size() > 0) + { + // don't want infinite loop, so set nCount to 0. + u32 prevcount = curvb.nCount; + curvb.nCount = 0; + + FlushTransferRanges(curvb.curprim.tme ? &curvb.tex0 : NULL); + + curvb.nCount += prevcount; + } +} + +// If set bit for texture checking, do it. Maybe it's all. +inline bool FushTexDataHelper(VB& curvb) +{ + if (curvb.bNeedFrameCheck || curvb.bNeedZCheck) + { + curvb.CheckFrame(curvb.curprim.tme ? curvb.tex0.tbp0 : 0); + } + + if (curvb.bNeedTexCheck) // Zeydlitz want to try this + { + curvb.FlushTexData(); + + if (curvb.nCount == 0) return true; + } + + return false; +} + +// Null target mean that we do something really bad. +inline bool FlushCheckForNULLTarget(VB& curvb, int context) +{ + if ((curvb.prndr == NULL) || (curvb.pdepth == NULL)) + { + ERROR_LOG_SPAMA("Current render target NULL (ctx: %d)", context); + curvb.nCount = 0; + return true; + } + + return false; +} + +// O.k. A set of resolutions, we do before real flush. We do RangeManager, FrameCheck and +// ZCheck before this. +inline bool FlushInitialTest(VB& curvb, const pixTest& curtest, int context) +{ + GL_REPORT_ERRORD(); + assert(context >= 0 && context <= 1); + + FlushUpdateEffect(); + + if (IsFlushNoNeed(curvb, curtest)) return true; + + FlushTransferRangesHelper(curvb); + + if (FushTexDataHelper(curvb)) return true; + + GL_REPORT_ERRORD(); + + if (FlushCheckForNULLTarget(curvb, context)) return true; + + return false; +} + +inline void TargetLog(int& tbw, int& tbp0, int& tpsm, VB& curvb, bool miss) +{ +#ifdef _DEBUG + if (tbp0 == 0x3600 && tbw == 0x100) + { + if (miss) + { + ZZLog::Debug_Log("Miss %x 0x%x %d", tbw, tbp0, tpsm); + + typedef map MAPTARGETS; + + for (MAPTARGETS::iterator itnew = s_RTs.mapTargets.begin(); itnew != s_RTs.mapTargets.end(); ++itnew) + { + ZZLog::Debug_Log("\tRender %x 0x%x %x", itnew->second->fbw, itnew->second->fbp, itnew->second->psm); + } + + for (MAPTARGETS::iterator itnew = s_DepthRTs.mapTargets.begin(); itnew != s_DepthRTs.mapTargets.end(); ++itnew) + { + ZZLog::Debug_Log("\tDepth %x 0x%x %x", itnew->second->fbw, itnew->second->fbp, itnew->second->psm); + } + + ZZLog::Debug_Log("\tCurvb 0x%x 0x%x 0x%x %x", curvb.frame.fbp, curvb.prndr->end, curvb.prndr->fbp, curvb.prndr->fbw); + } + else + ZZLog::Debug_Log("Hit %x 0x%x %x", tbw, tbp0, tpsm); + } +#endif +} + +// Try to different approach if texture target was not found +inline CRenderTarget* FlushReGetTarget(int& tbw, int& tbp0, int& tpsm, VB& curvb) +{ + // This was incorrect code + CRenderTarget* ptextarg = NULL; + + if (PSMT_ISZTEX(tpsm)) + { + // try depth + ptextarg = s_DepthRTs.GetTarg(tbp0, tbw); + } + + // I wonder if either of these hacks are useful, or if I can just remove them? + if ((conf.settings().reget) && (tpsm == PSMT8)) + { + // check for targets with half the width. Break Valkyrie Chronicles + ptextarg = s_RTs.GetTarg(tbp0, tbw / 2); + + if (ptextarg == NULL) + { + tbp0 &= ~0x7ff; + ptextarg = s_RTs.GetTarg(tbp0, tbw / 2); // mgs3 hack + + if (ptextarg == NULL) + { + // check the next level (mgs3) + tbp0 &= ~0xfff; + ptextarg = s_RTs.GetTarg(tbp0, tbw / 2); // mgs3 hack + } + + if (ptextarg != NULL && ptextarg->start > tbp0*256) + { + // target beyond range, so ignore + ptextarg = NULL; + } + } + } + + if ((conf.settings().texture_targs) && (ptextarg == NULL)) + { + // check if any part of the texture intersects the current target + if (!PSMT_ISCLUT(tpsm) && (curvb.tex0.tbp0 >= curvb.frame.fbp) && ((curvb.tex0.tbp0) < curvb.prndr->end)) + { + ptextarg = curvb.prndr; + } + } + + TargetLog(tbw, tbp0, tpsm, curvb, (ptextarg == NULL)); + + return ptextarg; +} + +// Find target to draw a texture. +inline CRenderTarget* FlushGetTarget(VB& curvb) +{ + int tbw, tbp0, tpsm; + + CRenderTarget* ptextarg = NULL; + + if (!curvb.curprim.tme) return ptextarg; // Which would be NULL, currently. + + if (curvb.bNeedTexCheck) + { + ZZLog::Error_Log("How it is possible?"); + // not yet initied, but still need to get correct target! (xeno3 ingame) + tbp0 = ZZOglGet_tbp0_TexBits(curvb.uNextTex0Data[0]); + tbw = ZZOglGet_tbw_TexBitsMult(curvb.uNextTex0Data[0]); + tpsm = ZZOglGet_psm_TexBitsFix(curvb.uNextTex0Data[0]); + } + else + { + tbw = curvb.tex0.tbw; + tbp0 = curvb.tex0.tbp0; + tpsm = curvb.tex0.psm; + } + + ptextarg = s_RTs.GetTarg(tbp0, tbw); + + if (ptextarg == NULL) ptextarg = FlushReGetTarget(tbw, tbp0, tpsm, curvb); + + if ((ptextarg != NULL) && !(ptextarg->status & CRenderTarget::TS_NeedUpdate)) + { + if (PSMT_BITMODE(tpsm) == 4) // handle 8h cluts + { + // don't support clut targets, read from mem + // 4hl - kh2 check - from dx version -- arcum42 + + if (tpsm == PSMT4 && s_ClutResolve <= 1) + { + // xenosaga requires 2 resolves + u32 prevcount = curvb.nCount; + curvb.nCount = 0; + ptextarg->Resolve(); + s_ClutResolve++; + curvb.nCount += prevcount; + } + + ptextarg = NULL; + } + else + { + if (ptextarg == curvb.prndr) + { + // need feedback + curvb.prndr->CreateFeedback(); + + if (s_bWriteDepth && (curvb.pdepth != NULL)) + curvb.pdepth->SetRenderTarget(1); + else + ResetRenderTarget(1); + } + } + } + else + { + // If a texture needs updating, clear it. + ptextarg = NULL; + } + + return ptextarg; +} + +// Set target for current context +inline void FlushSetContextTarget(VB& curvb, int context) +{ + if (!curvb.bVarsSetTarg) + { + SetContextTarget(context); + } + else + { + assert(curvb.pdepth != NULL); + + if (curvb.pdepth->status & CRenderTarget::TS_Virtual) + { + if (!curvb.zbuf.zmsk) + { + CRenderTarget* ptemp = s_DepthRTs.Promote(GetFrameKey(curvb.pdepth)); + assert(ptemp == curvb.pdepth); + } + else + { + curvb.pdepth->status &= ~CRenderTarget::TS_NeedUpdate; + } + } + + if ((curvb.pdepth->status & CRenderTarget::TS_NeedUpdate) || (curvb.prndr->status & CRenderTarget::TS_NeedUpdate)) + SetContextTarget(context); + } + + assert(!(curvb.prndr->status&CRenderTarget::TS_NeedUpdate)); + + curvb.prndr->status = 0; + + if (curvb.pdepth != NULL) + { +#ifdef _DEBUG + // Reduce an assert to a warning. + if (curvb.pdepth->status & CRenderTarget::TS_NeedUpdate) + { + ZZLog::Debug_Log("In FlushSetContextTarget, pdepth has TS_NeedUpdate set."); + } +#endif + if (!curvb.zbuf.zmsk) + { + assert(!(curvb.pdepth->status & CRenderTarget::TS_Virtual)); + curvb.pdepth->status = 0; + } + } +} + +inline void FlushSetStream(VB& curvb) +{ + glBindBuffer(GL_ARRAY_BUFFER, g_vboBuffers[g_nCurVBOIndex]); + g_nCurVBOIndex = (g_nCurVBOIndex + 1) % g_vboBuffers.size(); + glBufferData(GL_ARRAY_BUFFER, curvb.nCount * sizeof(VertexGPU), curvb.pBufferData, GL_STREAM_DRAW); +// void* pdata = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); +// memcpy_amd(pdata, curvb.pBufferData, curvb.nCount * sizeof(VertexGPU)); +// glUnmapBuffer(GL_ARRAY_BUFFER); + SET_STREAM(); + + GL_REPORT_ERRORD(); +} + +int SetMaskR = 0x0; +int SetMaskG = 0x0; +int SetMaskB = 0x0; +// Set color mask. Really, it's not as good as PS2 one. +inline void FlushSetColorMask(VB& curvb) +{ + s_dwColorWrite = (PSMT_BITMODE(curvb.prndr->psm) == 1) ? (COLORMASK_BLUE | COLORMASK_GREEN | COLORMASK_RED) : 0xf; + + int maskR = ZZOglGet_fbmRed_FrameBits(curvb.frame.fbm); + int maskG = ZZOglGet_fbmGreen_FrameBits(curvb.frame.fbm); + int maskB = ZZOglGet_fbmBlue_FrameBits(curvb.frame.fbm); + int maskA = ZZOglGet_fbmAlpha_FrameBits(curvb.frame.fbm); + + if (maskR == 0xff) s_dwColorWrite &= ~COLORMASK_RED; + if (maskG == 0xff) s_dwColorWrite &= ~COLORMASK_GREEN; + if (maskB == 0xff) s_dwColorWrite &= ~COLORMASK_BLUE; + + if ((maskA == 0xff) || (curvb.curprim.abe && (curvb.test.atst == 2 && curvb.test.aref == 128))) + s_dwColorWrite &= ~COLORMASK_ALPHA; + + GL_COLORMASK(s_dwColorWrite); +} + +// Set Scissors for scissor test. +inline void FlushSetScissorRect(VB& curvb) +{ + Rect& scissor = curvb.prndr->scissorrect; + glScissor(scissor.x, scissor.y, scissor.w, scissor.h); +} + +// Prior really doing something check context +inline void FlushDoContextJob(VB& curvb, int context) +{ + SaveRendererTarget(curvb); + + FlushSetContextTarget(curvb, context); + icurctx = context; + + FlushSetStream(curvb); + FlushSetColorMask(curvb); + FlushSetScissorRect(curvb); +} + +// Set 1 is Alpha test is EQUAL and alpha should be proceed with care. +inline int FlushGetExactcolor(const pixTest curtest) +{ + if (!(g_nPixelShaderVer&SHADER_REDUCED)) + // ffx2 breaks when ==7 + return ((curtest.ate && curtest.aref <= 128) && (curtest.atst == 4));//||curtest.atst==7); + + return 0; +} + +// fill the buffer by decoding the clut +inline void FlushDecodeClut(VB& curvb, GLuint& ptexclut) +{ + glGenTextures(1, &ptexclut); + glBindTexture(GL_TEXTURE_2D, ptexclut); + + if (ptexclut != 0) + { + int clutsize; + int entries = PSMT_IS8CLUT(curvb.tex0.psm) ? 256 : 16; + + if (curvb.tex0.csm && curvb.tex0.csa) ZZLog::Debug_Log("ERROR, csm1."); + + if (PSMT_IS32BIT(curvb.tex0.cpsm)) { + __aligned16 u32 data[256]; + clutsize = min(entries, 256 - curvb.tex0.csa * 16) * 4; + + ClutBuffer_to_Array((u32*)data, curvb.tex0.csa, clutsize); + + Texture2D(4, 256, 1, GL_RGBA, GL_UNSIGNED_BYTE, data); + } else { + __aligned16 u16 data[256]; + clutsize = min(entries, 512 - curvb.tex0.csa * 16) * 2; + + ClutBuffer_to_Array((u16*)data, curvb.tex0.csa, clutsize); + + Texture2D(4, 256, 1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, data); + } + + s_vecTempTextures.push_back(ptexclut); + + if (g_bSaveTex) SaveTexture("clut.tga", GL_TEXTURE_2D, ptexclut, 256, 1); + + setTex2DWrap(GL_REPEAT); + setTex2DFilters(GL_LINEAR); + } +} + +inline int FlushGetShaderType(VB& curvb, CRenderTarget* ptextarg, GLuint& ptexclut) +{ + if (PSMT_ISCLUT(curvb.tex0.psm) && !(conf.settings().no_target_clut)) + { + FlushDecodeClut(curvb, ptexclut); + + if (!(g_nPixelShaderVer&SHADER_REDUCED) && PSMT_ISHALF(ptextarg->psm)) + { + return 4; + } + else + { + // Valkyrie + return 2; + } + } + + if (PSMT_ISHALF_STORAGE(curvb.tex0) != PSMT_ISHALF(ptextarg->psm) && (!(g_nPixelShaderVer&SHADER_REDUCED) || !curvb.curprim.fge)) + { + if (PSMT_ISHALF_STORAGE(curvb.tex0)) + { + // converting from 32->16 + // Radiata Chronicles + return 3; + } + else + { + // converting from 16->32 + // Star Ward: Force + return 0; + } + } + + return 1; +} + + +//Set page offsets depends on shader type. +inline float4 FlushSetPageOffset(FRAGMENTSHADER* pfragment, int shadertype, CRenderTarget* ptextarg) +{ + SetShaderCaller("FlushSetPageOffset"); + + float4 vpageoffset; + vpageoffset.w = 0; + + switch (shadertype) + { + case 3: + vpageoffset.x = -0.1f / 256.0f; + vpageoffset.y = -0.001f / 256.0f; + vpageoffset.z = -0.1f / (ptextarg->fbh); + vpageoffset.w = 0.0f; + break; + + case 4: + vpageoffset.x = 2; + vpageoffset.y = 1; + vpageoffset.z = 0; + vpageoffset.w = 0.0001f; + break; + } + + // zoe2 + if (PSMT_ISZTEX(ptextarg->psm)) vpageoffset.w = -1.0f; + + ZZshSetParameter4fv(pfragment->fPageOffset, vpageoffset, "g_fPageOffset"); + + return vpageoffset; +} + +//Set texture offsets depends omn shader type. +inline float4 FlushSetTexOffset(FRAGMENTSHADER* pfragment, int shadertype, VB& curvb, CRenderTarget* ptextarg) +{ + SetShaderCaller("FlushSetTexOffset"); + float4 v; + + if (shadertype == 3) + { + float4 v; + v.x = 16.0f / (float)curvb.tex0.tw; + v.y = 16.0f / (float)curvb.tex0.th; + v.z = 0.5f * v.x; + v.w = 0.5f * v.y; + ZZshSetParameter4fv(pfragment->fTexOffset, v, "g_fTexOffset"); + } + else if (shadertype == 4) + { + float4 v; + v.x = 16.0f / (float)ptextarg->fbw; + v.y = 16.0f / (float)ptextarg->fbh; + v.z = -1; + v.w = 8.0f / (float)ptextarg->fbh; + ZZshSetParameter4fv(pfragment->fTexOffset, v, "g_fTexOffset"); + } + + return v; +} + +// Set dimension (Real!) of texture. z and w +inline float4 FlushTextureDims(FRAGMENTSHADER* pfragment, int shadertype, VB& curvb, CRenderTarget* ptextarg) +{ + SetShaderCaller("FlushTextureDims"); + float4 vTexDims; + vTexDims.x = (float)RW(curvb.tex0.tw) ; + vTexDims.y = (float)RH(curvb.tex0.th) ; + + // look at the offset of tbp0 from fbp + + if (curvb.tex0.tbp0 <= ptextarg->fbp) + { + vTexDims.z = 0;//-0.5f/(float)ptextarg->fbw; + vTexDims.w = 0;//0.2f/(float)ptextarg->fbh; + } + else + { + //u32 tbp0 = curvb.tex0.tbp0 >> 5; // align to a page + int blockheight = PSMT_ISHALF(ptextarg->psm) ? 64 : 32; + int ycoord = ((curvb.tex0.tbp0 - ptextarg->fbp) / (32 * (ptextarg->fbw >> 6))) * blockheight; + int xcoord = (((curvb.tex0.tbp0 - ptextarg->fbp) % (32 * (ptextarg -> fbw >> 6)))) * 2; + vTexDims.z = (float)xcoord; + vTexDims.w = (float)ycoord; + } + + if (shadertype == 4) + vTexDims.z += 8.0f; + + ZZshSetParameter4fv(pfragment->fTexDims, vTexDims, "g_fTexDims"); + + return vTexDims; +} + +// Apply TEX1 mmag and mmin -- filter for expanding/reducing texture +// We ignore all settings, only NEAREST (0) is used +inline void FlushApplyResizeFilter(VB& curvb, u32& dwFilterOpts, CRenderTarget* ptextarg, int context) +{ + u32 ptexset = (ptextarg == curvb.prndr) ? ptextarg->ptexFeedback : ptextarg->ptex; + s_ptexCurSet[context] = ptexset; + + if ((!curvb.tex1.mmag) || (!curvb.tex1.mmin)) + glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptexset); + + if (!curvb.tex1.mmag) + { + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + dwFilterOpts |= 1; + } + + if (!curvb.tex1.mmin) + { + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + dwFilterOpts |= 2; + } +} + + +// Usage existing targets depends on several tricks, 32-16 conversion and CLUTing, so we need to handle it. +inline FRAGMENTSHADER* FlushUseExistRenderTarget(VB& curvb, CRenderTarget* ptextarg, u32& dwFilterOpts, int exactcolor, int context) +{ + if (ptextarg->IsDepth()) + SetWriteDepth(); + + GLuint ptexclut = 0; + + //int psm = PIXEL_STORAGE_FORMAT(curvb.tex0); + int shadertype = FlushGetShaderType(curvb, ptextarg, ptexclut); + + FRAGMENTSHADER* pfragment = ZZshLoadShadeEffect(shadertype, 0, curvb.curprim.fge, + IsAlphaTestExpansion(curvb.tex0), exactcolor, curvb.clamp, context, NULL); + + float4 vpageoffset = FlushSetPageOffset(pfragment, shadertype, ptextarg); + + float4 v = FlushSetTexOffset(pfragment, shadertype, curvb, ptextarg); + + float4 vTexDims = FlushTextureDims(pfragment, shadertype, curvb, ptextarg); + + if (pfragment->sCLUT != NULL && ptexclut != 0) + ZZshGLSetTextureParameter(pfragment->sCLUT, ptexclut, "CLUT"); + + FlushApplyResizeFilter(curvb, dwFilterOpts, ptextarg, context); + + if (g_bSaveTex) + SaveTexture("tex.tga", GL_TEXTURE_RECTANGLE_NV, + ptextarg == curvb.prndr ? ptextarg->ptexFeedback : ptextarg->ptex, RW(ptextarg->fbw), RH(ptextarg->fbh)); + + return pfragment; +} + +// Usage most major shader. +inline FRAGMENTSHADER* FlushMadeNewTarget(VB& curvb, int exactcolor, int context) +{ + // save the texture + if (g_bSaveTex) + { + // FIXME: I suspect one of g_bSaveTex test variable is wrong + if (g_bSaveTex == 1) + { + SaveTex(&curvb.tex0, 1); + /*CMemoryTarget* pmemtarg = */ + g_MemTargs.GetMemoryTarget(curvb.tex0, 0); + } + else + { + SaveTex(&curvb.tex0, 0); + } + } + + FRAGMENTSHADER* pfragment = ZZshLoadShadeEffect(0, GetTexFilter(curvb.tex1), curvb.curprim.fge, + IsAlphaTestExpansion(curvb.tex0), exactcolor, curvb.clamp, context, NULL); + + if (pfragment == NULL) + ZZLog::Error_Log("Could not find memory target shader."); + + return pfragment; +} + +// We made an shader, so now need to put all common variables. +inline void FlushSetTexture(VB& curvb, FRAGMENTSHADER* pfragment, CRenderTarget* ptextarg, int context) +{ + SetTexVariables(context, pfragment); + SetTexInt(context, pfragment, ptextarg == NULL); + + // have to enable the texture parameters(curtest.atst) + if( curvb.ptexClamp[0] != 0 ) + ZZshGLSetTextureParameter(pfragment->sBitwiseANDX, curvb.ptexClamp[0], "Clamp 0"); + + if( curvb.ptexClamp[1] != 0 ) + ZZshGLSetTextureParameter(pfragment->sBitwiseANDY, curvb.ptexClamp[1], "Clamp 1"); + + if( pfragment->sMemory != NULL && s_ptexCurSet[context] != 0) + ZZshGLSetTextureParameter(pfragment->sMemory, s_ptexCurSet[context], "Clamp memory"); + +} + +// Reset program and texture variables; +inline void FlushBindProgramm(FRAGMENTSHADER* pfragment, int context) +{ + vb[context].bTexConstsSync = 0; + vb[context].bVarsTexSync = 0; + + ZZshSetPixelShader(pfragment->prog); +} + +inline FRAGMENTSHADER* FlushRendererStage(VB& curvb, u32& dwFilterOpts, CRenderTarget* ptextarg, int exactcolor, int context) +{ + + FRAGMENTSHADER* pfragment = NULL; + + // set the correct pixel shaders + + if (curvb.curprim.tme) + { + if (ptextarg != NULL) + pfragment = FlushUseExistRenderTarget(curvb, ptextarg, dwFilterOpts, exactcolor, context); + else + pfragment = FlushMadeNewTarget(curvb, exactcolor, context); + + if (pfragment == NULL) + { + ZZLog::Error_Log("Shader is not found."); +// return NULL; + } + + FlushSetTexture(curvb, pfragment, ptextarg, context); + } + else + { + pfragment = &ppsRegular[curvb.curprim.fge + 2 * s_bWriteDepth]; + } + + GL_REPORT_ERRORD(); + + // set the shaders + SetShaderCaller("FlushRendererStage"); + ZZshSetVertexShader(pvs[2 * ((curvb.curprim._val >> 1) & 3) + 8 * s_bWriteDepth + context]); + FlushBindProgramm(pfragment, context); + + GL_REPORT_ERRORD(); + return pfragment; +} + +inline bool AlphaCanRenderStencil(VB& curvb) +{ + return g_bUpdateStencil && (PSMT_BITMODE(curvb.prndr->psm) != 1) && + !ZZOglGet_fbmHighByte(curvb.frame.fbm) && !(conf.settings().no_stencil); +} + +inline void AlphaSetStencil(bool DoIt) +{ + if (DoIt) + { + glEnable(GL_STENCIL_TEST); + GL_STENCILFUNC(GL_ALWAYS, 0, 0); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + } + else glDisable(GL_STENCIL_TEST); +} + +//inline u32 FtoDW(float f) { return (*((u32*)&f)); } + +inline void AlphaSetDepthTest(VB& curvb, const pixTest curtest, FRAGMENTSHADER* pfragment) +{ + glDepthMask(!curvb.zbuf.zmsk && curtest.zte); + // && curtest.zte && (curtest.ztst > 1) ); + + if (curtest.zte) + { + if (curtest.ztst > 1) g_nDepthUsed = 2; + if ((curtest.ztst == 2) ^(g_nDepthBias != 0)) + { + g_nDepthBias = (curtest.ztst == 2); + //SETRS(D3DRS_DEPTHBIAS, g_nDepthBias?FtoDW(0.0003f):FtoDW(0.000015f)); + } + + glDepthFunc(g_dwZCmp[curtest.ztst]); + } + + GL_ZTEST(curtest.zte); + + if (s_bWriteDepth) + { + if (!curvb.zbuf.zmsk) + curvb.pdepth->SetRenderTarget(1); + else + ResetRenderTarget(1); + } +} + +inline u32 AlphaSetupBlendTest(VB& curvb) +{ + if (curvb.curprim.abe) + SetAlphaVariables(curvb.alpha); + else + glDisable(GL_BLEND); + + u32 oldabe = curvb.curprim.abe; + + if (gs.pabe) + { + //ZZLog::Error_Log("PABE!"); + curvb.curprim.abe = 1; + glEnable(GL_BLEND); + } + + return oldabe; +} + +inline void AlphaRenderFBA(VB& curvb, FRAGMENTSHADER* pfragment, bool s_bDestAlphaTest, bool bCanRenderStencil) +{ + // needs to be before RenderAlphaTest + if ((gs.pabe) || (curvb.fba.fba && !ZZOglGet_fbmHighByte(curvb.frame.fbm)) || (s_bDestAlphaTest && bCanRenderStencil)) + { + RenderFBA(curvb, pfragment->sOneColor); + } + +} + +inline u32 AlphaRenderAlpha(VB& curvb, const pixTest curtest, FRAGMENTSHADER* pfragment, int exactcolor) +{ + SetShaderCaller("AlphaRenderAlpha"); + u32 dwUsingSpecialTesting = 0; + + if (curvb.curprim.abe) + { + if ((bNeedBlendFactorInAlpha || ((curtest.ate && curtest.atst > 1) && (curtest.aref > 0x80)))) + { + // need special stencil processing for the alpha + RenderAlphaTest(curvb, pfragment->sOneColor); + dwUsingSpecialTesting = 1; + } + + // harvest fishing + float4 v = vAlphaBlendColor; + + if (exactcolor) + { + v.y *= 255; + v.w *= 255; + } + + ZZshSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor"); + } + else + { + // not using blending so set to defaults + float4 v = exactcolor ? float4(1, 510 * 255.0f / 256.0f, 0, 0) : float4(1, 2 * 255.0f / 256.0f, 0, 0); + ZZshSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor"); + + } + + return dwUsingSpecialTesting; +} + +inline void AlphaRenderStencil(VB& curvb, bool s_bDestAlphaTest, bool bCanRenderStencil, u32 dwUsingSpecialTesting) +{ + if (s_bDestAlphaTest && bCanRenderStencil) + { + // if not 24bit and can write to high alpha bit + RenderStencil(curvb, dwUsingSpecialTesting); + } + else + { + s_stencilref = STENCIL_SPECIAL; + s_stencilmask = STENCIL_SPECIAL; + + // setup the stencil to only accept the test pixels + + if (dwUsingSpecialTesting) + { + glEnable(GL_STENCIL_TEST); + glStencilMask(STENCIL_PIXELWRITE); + GL_STENCILFUNC(GL_EQUAL, STENCIL_SPECIAL | STENCIL_PIXELWRITE, STENCIL_SPECIAL); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + } + } + +#ifdef _DEBUG + if (bDestAlphaColor == 1) + { + ZZLog::Debug_Log("Dest alpha blending! Manipulate alpha here."); + } + +#endif + + if (bCanRenderStencil && gs.pabe) + { + // only render the pixels with alpha values >= 0x80 + GL_STENCILFUNC(GL_EQUAL, s_stencilref | STENCIL_FBA, s_stencilmask | STENCIL_FBA); + } + + GL_REPORT_ERRORD(); +} + +inline void AlphaTest(VB& curvb) +{ +// ZZLog::Debug_Log("%d %d %d %d %d", curvb.test.date, curvb.test.datm, gs.texa.aem, curvb.test.ate, curvb.test.atst ); + +// return; + // Zeydlitz changed this with a reason! It's an "Alpha more than 1 hack." + if (curvb.test.ate == 1 && curvb.test.atst == 1 && curvb.test.date == 1) + { + if (curvb.test.datm == 1) + { + glAlphaFunc(GL_GREATER, 1.0f); + } + else + { + glAlphaFunc(GL_LESS, 1.0f); + ZZLog::Debug_Log("%d %d %d", curvb.test.date, curvb.test.datm, gs.texa.aem); + } + } + + if (!curvb.test.ate || curvb.test.atst > 0) + { + Draw(curvb); + } + + GL_REPORT_ERRORD(); +} + +inline void AlphaPabe(VB& curvb, FRAGMENTSHADER* pfragment, int exactcolor) +{ + if (gs.pabe) + { + SetShaderCaller("AlphaPabe"); + // only render the pixels with alpha values < 0x80 + glDisable(GL_BLEND); + GL_STENCILFUNC_SET(); + + float4 v; + v.x = 1; + v.y = 2; + v.z = 0; + v.w = 0; + + if (exactcolor) v.y *= 255; + + ZZshSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor"); + + Draw(curvb); + + // reset + if (!s_stencilmask) s_stencilfunc = GL_ALWAYS; + + GL_STENCILFUNC_SET(); + } + + GL_REPORT_ERRORD(); +} + +// Alpha Failure does not work properly on this cases. True means that no failure job should be done. +// First three cases are trivial manual. +inline bool AlphaFailureIgnore(const pixTest curtest) +{ + if ((!curtest.ate) || (curtest.atst == 1) || (curtest.afail == 0)) return true; + + if (conf.settings().no_alpha_fail && ((s_dwColorWrite < 8) || (s_dwColorWrite == 15 && curtest.atst == 5 && (curtest.aref == 64)))) + return true; + +// old and seemingly incorrect code. +// if ((s_dwColorWrite < 8 && s_dwColorWrite !=8) && curtest.afail == 1) +// return true; +// if ((s_dwColorWrite == 0xf) && curtest.atst == 5 && curtest.afail == 1 && !(conf.settings() & GAME_REGETHACK)) +// return true; + return false; +} + +// more work on alpha failure case +inline void AlphaFailureTestJob(VB& curvb, const pixTest curtest, FRAGMENTSHADER* pfragment, int exactcolor, bool bCanRenderStencil, int oldabe) +{ + // Note, case when ate == 1, atst == 0 and afail > 0 in documentation wrote as failure case. But it seems that + // either doc's are incorrect or this case has some issues. + if (AlphaFailureIgnore(curtest)) return; + +#ifdef NOALFAFAIL + ZZLog::Error_Log("Alpha job here %d %d %d %d %d %d", s_dwColorWrite, curtest.atst, curtest.afail, curtest.aref, gs.pabe, s_bWriteDepth); + +// return; +#endif + + SetShaderCaller("AlphaFailureTestJob"); + + // need to reverse the test and disable some targets + glAlphaFunc(g_dwReverseAlphaCmp[curtest.atst], AlphaReferedValue(curtest.aref)); + + if (curtest.afail & 1) // front buffer update only + { + if (curtest.afail == 3) glColorMask(1, 1, 1, 0);// disable alpha + + glDepthMask(0); + + if (s_bWriteDepth) ResetRenderTarget(1); + } + else + { + // zbuffer update only + glColorMask(0, 0, 0, 0); + } + + if (gs.pabe && bCanRenderStencil) + { + // only render the pixels with alpha values >= 0x80 + float4 v = vAlphaBlendColor; + + if (exactcolor) { v.y *= 255; v.w *= 255; } + + ZZshSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor"); + + glEnable(GL_BLEND); + GL_STENCILFUNC(GL_EQUAL, s_stencilref | STENCIL_FBA, s_stencilmask | STENCIL_FBA); + } + + Draw(curvb); + + GL_REPORT_ERRORD(); + + if (gs.pabe) + { + // only render the pixels with alpha values < 0x80 + glDisable(GL_BLEND); + GL_STENCILFUNC_SET(); + + float4 v; + v.x = 1; + v.y = 2; + v.z = 0; + v.w = 0; + + if (exactcolor) v.y *= 255; + + ZZshSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor"); + + Draw(curvb); + + // reset + if (oldabe) glEnable(GL_BLEND); + + if (!s_stencilmask) s_stencilfunc = GL_ALWAYS; + + GL_STENCILFUNC_SET(); + } + + // restore + if ((curtest.afail & 1) && !curvb.zbuf.zmsk) + { + glDepthMask(1); + + if (s_bWriteDepth) + { + assert(curvb.pdepth != NULL); + curvb.pdepth->SetRenderTarget(1); + } + } + + GL_COLORMASK(s_dwColorWrite); + + // not needed anymore since rest of ops concentrate on image processing + + GL_REPORT_ERRORD(); +} + +inline void AlphaSpecialTesting(VB& curvb, FRAGMENTSHADER* pfragment, u32 dwUsingSpecialTesting, int exactcolor) +{ + if (dwUsingSpecialTesting) + { + SetShaderCaller("AlphaSpecialTesting"); + + // render the real alpha + glDisable(GL_ALPHA_TEST); + glColorMask(0, 0, 0, 1); + + if (s_bWriteDepth) + { + ResetRenderTarget(1); + } + + glDepthMask(0); + + glStencilFunc(GL_EQUAL, STENCIL_SPECIAL | STENCIL_PIXELWRITE, STENCIL_SPECIAL | STENCIL_PIXELWRITE); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + + float4 v = float4(0, exactcolor ? 510.0f : 2.0f, 0, 0); + ZZshSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor"); + Draw(curvb); + + // don't need to restore + } + + GL_REPORT_ERRORD(); +} + +inline void AlphaDestinationTest(VB& curvb, FRAGMENTSHADER* pfragment, bool s_bDestAlphaTest, bool bCanRenderStencil) +{ + if (s_bDestAlphaTest) + { + if ((s_dwColorWrite & COLORMASK_ALPHA)) + { + if (curvb.fba.fba) + ProcessFBA(curvb, pfragment->sOneColor); + else if (bCanRenderStencil) + // finally make sure all entries are 1 when the dest alpha >= 0x80 (if fba is 1, this is already the case) + ProcessStencil(curvb); + } + } + else if ((s_dwColorWrite & COLORMASK_ALPHA) && curvb.fba.fba) + ProcessFBA(curvb, pfragment->sOneColor); + + if (bDestAlphaColor == 1) + { + // need to reset the dest colors to their original counter parts + //WARN_LOG("Need to reset dest alpha color\n"); + } +} + +inline void AlphaSaveTarget(VB& curvb) +{ +#ifdef _DEBUG + return; // Do nothing + +//#ifdef _WIN32 +// CreateDirectory("frames", NULL); +//#else +// char* strdir=""; +// sprintf(strdir, "mkdir %s", "frames"); +// system(strdir); +//#endif +// char str[255]; + +// Needs a # after frame to work properly. +// sprintf(str, "frames/frame.tga"); + +// //glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // switch to the backbuffer +// //glFlush(); +// //SaveTexture("tex.jpg", GL_TEXTURE_RECTANGLE_NV, curvb.prndr->ptex, RW(curvb.prndr->fbw), RH(curvb.prndr->fbh)); +// SaveRenderTarget(str, RW(curvb.prndr->fbw), RH(curvb.prndr->fbh), 0); +#endif +} + +inline void FlushUndoFiter(u32 dwFilterOpts) +{ + if (dwFilterOpts) + { + // undo filter changes (binding didn't change) + if (dwFilterOpts & 1) glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + if (dwFilterOpts & 2) glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } +} + +// This is the most important function! It draws all collected info onscreen. +void Flush(int context) +{ + FUNCLOG + VB& curvb = vb[context]; + const pixTest curtest = curvb.test; + + if (FlushInitialTest(curvb, curtest, context)) return; + + VisualBufferMessage(context); + + GL_REPORT_ERRORD(); + + CRenderTarget* ptextarg = FlushGetTarget(curvb); + + SwitchWireframeOff(); + FlushDoContextJob(curvb, context); + + u32 dwUsingSpecialTesting = 0, dwFilterOpts = 0; + int exactcolor = FlushGetExactcolor(curtest); + + FRAGMENTSHADER* pfragment = FlushRendererStage(curvb, dwFilterOpts, ptextarg, exactcolor, context); + + bool bCanRenderStencil = AlphaCanRenderStencil(curvb); + + if (curtest.date || gs.pabe) SetDestAlphaTest(); + + AlphaSetStencil(s_bDestAlphaTest && bCanRenderStencil); + AlphaSetDepthTest(curvb, curtest, pfragment); // Error! + SetAlphaTest(curtest); + + u32 oldabe = AlphaSetupBlendTest(curvb); // Unavoidable + + // needs to be before RenderAlphaTest + AlphaRenderFBA(curvb, pfragment, s_bDestAlphaTest, bCanRenderStencil); + + dwUsingSpecialTesting = AlphaRenderAlpha(curvb, curtest, pfragment, exactcolor); // Unavoidable + AlphaRenderStencil(curvb, s_bDestAlphaTest, bCanRenderStencil, dwUsingSpecialTesting); + AlphaTest(curvb); // Unavoidable + AlphaPabe(curvb, pfragment, exactcolor); + AlphaFailureTestJob(curvb, curtest, pfragment, exactcolor, bCanRenderStencil, oldabe); + AlphaSpecialTesting(curvb, pfragment, dwUsingSpecialTesting, exactcolor); + AlphaDestinationTest(curvb, pfragment, s_bDestAlphaTest, bCanRenderStencil); + AlphaSaveTarget(curvb); + + GL_REPORT_ERRORD(); + + FlushUndoFiter(dwFilterOpts); + + ppf += curvb.nCount + 0x100000; + + curvb.nCount = 0; + curvb.curprim.abe = oldabe; + + SwitchWireframeOn(); + + GL_REPORT_ERRORD(); +} + +void FlushBoth() +{ + Flush(0); + Flush(1); +} + +inline void RenderFBA(const VB& curvb, ZZshParameter sOneColor) +{ + // add fba to all pixels + GL_STENCILFUNC(GL_ALWAYS, STENCIL_FBA, 0xff); + glStencilMask(STENCIL_CLEAR); + glStencilOp(GL_ZERO, GL_KEEP, GL_REPLACE); + + glDisable(GL_DEPTH_TEST); + glDepthMask(0); + glColorMask(0, 0, 0, 0); + + if (s_bWriteDepth) ResetRenderTarget(1); + + SetShaderCaller("RenderFBA"); + + glEnable(GL_ALPHA_TEST); + + glAlphaFunc(GL_GEQUAL, 1); + + float4 v(1,2,0,0); + + ZZshSetParameter4fv(sOneColor, v, "g_fOneColor"); + + Draw(curvb); + + SetAlphaTest(curvb.test); + + // reset (not necessary) + GL_COLORMASK(s_dwColorWrite); + + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + if (!curvb.zbuf.zmsk) + { + glDepthMask(1); + + assert(curvb.pdepth != NULL); + + if (s_bWriteDepth) curvb.pdepth->SetRenderTarget(1); + } + + GL_ZTEST(curvb.test.zte); +} + +__forceinline void RenderAlphaTest(const VB& curvb, ZZshParameter sOneColor) +{ + if (!g_bUpdateStencil) return; + + if ((curvb.test.ate) && (curvb.test.afail == 1)) glDisable(GL_ALPHA_TEST); + + glDepthMask(0); + + glColorMask(0, 0, 0, 0); + + if (s_bWriteDepth) ResetRenderTarget(1); + + SetShaderCaller("RenderAlphaTest"); + + float4 v(1,2,0,0); + + ZZshSetParameter4fv(sOneColor, v, "g_fOneColor"); + + // or a 1 to the stencil buffer wherever alpha passes + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + s_stencilfunc = GL_ALWAYS; + + glEnable(GL_STENCIL_TEST); + + if (!s_bDestAlphaTest) + { + // clear everything + s_stencilref = 0; + glStencilMask(STENCIL_CLEAR); + glDisable(GL_ALPHA_TEST); + GL_STENCILFUNC_SET(); + Draw(curvb); + + if (curvb.test.ate && curvb.test.afail != 1 && USEALPHATESTING) glEnable(GL_ALPHA_TEST); + } + + if (curvb.test.ate && curvb.test.atst > 1 && curvb.test.aref > 0x80) + { + v = float4(1,1,0,0); + ZZshSetParameter4fv(sOneColor, v, "g_fOneColor"); + glAlphaFunc(g_dwAlphaCmp[curvb.test.atst], AlphaReferedValue(curvb.test.aref)); + } + + s_stencilref = STENCIL_SPECIAL; + + glStencilMask(STENCIL_SPECIAL); + GL_STENCILFUNC_SET(); + glDisable(GL_DEPTH_TEST); + + Draw(curvb); + + if (curvb.test.zte) glEnable(GL_DEPTH_TEST); + + GL_ALPHATEST(0); + + GL_COLORMASK(s_dwColorWrite); + + if (!curvb.zbuf.zmsk) + { + glDepthMask(1); + + // set rt next level + + if (s_bWriteDepth) curvb.pdepth->SetRenderTarget(1); + } +} + +inline void RenderStencil(const VB& curvb, u32 dwUsingSpecialTesting) +{ + //NOTE: This stencil hack for dest alpha testing ONLY works when + // the geometry in one DrawPrimitive call does not overlap + + // mark the stencil buffer for the new data's bits (mark 4 if alpha is >= 0xff) + // mark 4 if a pixel was written (so that the stencil buf can be changed with new values) + glStencilMask(STENCIL_PIXELWRITE); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + s_stencilmask = (curvb.test.date ? STENCIL_ALPHABIT : 0) | (dwUsingSpecialTesting ? STENCIL_SPECIAL : 0); + s_stencilfunc = s_stencilmask ? GL_EQUAL : GL_ALWAYS; + + s_stencilref = curvb.test.date * curvb.test.datm | STENCIL_PIXELWRITE | (dwUsingSpecialTesting ? STENCIL_SPECIAL : 0); + GL_STENCILFUNC_SET(); +} + +inline void ProcessStencil(const VB& curvb) +{ + assert(!curvb.fba.fba); + + // set new alpha bit + glStencilMask(STENCIL_ALPHABIT); + GL_STENCILFUNC(GL_EQUAL, STENCIL_PIXELWRITE, STENCIL_PIXELWRITE | STENCIL_FBA); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + glDisable(GL_DEPTH_TEST); + glDepthMask(0); + glColorMask(0, 0, 0, 0); + + if (s_bWriteDepth) ResetRenderTarget(1); + + GL_ALPHATEST(0); + + SetShaderCaller("ProcessStencil"); + + ZZshSetPixelShader(ppsOne.prog); + Draw(curvb); + + // process when alpha >= 0xff + GL_STENCILFUNC(GL_EQUAL, STENCIL_PIXELWRITE | STENCIL_FBA | STENCIL_ALPHABIT, STENCIL_PIXELWRITE | STENCIL_FBA); + Draw(curvb); + + // clear STENCIL_PIXELWRITE bit + glStencilMask(STENCIL_CLEAR); + + GL_STENCILFUNC(GL_ALWAYS, 0, STENCIL_PIXELWRITE | STENCIL_FBA); + Draw(curvb); + + // restore state + GL_COLORMASK(s_dwColorWrite); + + if (curvb.test.ate && USEALPHATESTING) glEnable(GL_ALPHA_TEST); + + if (!curvb.zbuf.zmsk) + { + glDepthMask(1); + + if (s_bWriteDepth) + { + assert(curvb.pdepth != NULL); + curvb.pdepth->SetRenderTarget(1); + } + } + + GL_ZTEST(curvb.test.zte); + + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); +} + +__forceinline void ProcessFBA(const VB& curvb, ZZshParameter sOneColor) +{ + if ((curvb.frame.fbm&0x80000000)) return; + + // add fba to all pixels that were written and alpha was less than 0xff + glStencilMask(STENCIL_ALPHABIT); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + GL_STENCILFUNC(GL_EQUAL, STENCIL_FBA | STENCIL_PIXELWRITE | STENCIL_ALPHABIT, STENCIL_PIXELWRITE | STENCIL_FBA); + glDisable(GL_DEPTH_TEST); + + glDepthMask(0); + glColorMask(0, 0, 0, 1); + + if (s_bWriteDepth) ResetRenderTarget(1); + + SetShaderCaller("ProcessFBA"); + + // processes the pixels with ALPHA < 0x80*2 + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_LEQUAL, 1); + + // add 1 to dest + GL_BLEND_ALPHA(GL_ONE, GL_ONE); + GL_BLENDEQ_ALPHA(GL_FUNC_ADD); + + float f = 1; + ZZshSetParameter4fv(sOneColor, &f, "g_fOneColor"); + ZZshSetPixelShader(ppsOne.prog); + Draw(curvb); + glDisable(GL_ALPHA_TEST); + + // reset bits + glStencilMask(STENCIL_CLEAR); + GL_STENCILFUNC(GL_GREATER, 0, STENCIL_PIXELWRITE | STENCIL_FBA); + glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO); + Draw(curvb); + + if (curvb.test.atst && USEALPHATESTING) + { + glEnable(GL_ALPHA_TEST); + glAlphaFunc(g_dwAlphaCmp[curvb.test.atst], AlphaReferedValue(curvb.test.aref)); + } + + // restore (SetAlphaVariables) + GL_BLEND_ALPHA(GL_ONE, GL_ZERO); + + if (vAlphaBlendColor.y < 0) GL_BLENDEQ_ALPHA(GL_FUNC_REVERSE_SUBTRACT); + + // reset (not necessary) + GL_COLORMASK(s_dwColorWrite); + + if (!curvb.zbuf.zmsk) + { + glDepthMask(1); + + if (s_bWriteDepth) curvb.pdepth->SetRenderTarget(1); + } + + GL_ZTEST(curvb.test.zte); +} + +void SetContextTarget(int context) +{ + FUNCLOG + VB& curvb = vb[context]; + GL_REPORT_ERRORD(); + + if (curvb.prndr == NULL) + curvb.prndr = s_RTs.GetTarg(curvb.frame, 0, get_maxheight(curvb.gsfb.fbp, curvb.gsfb.fbw, curvb.gsfb.psm)); + + // make sure targets are valid + if (curvb.pdepth == NULL) + { + frameInfo f; + f.fbp = curvb.zbuf.zbp; + f.fbw = curvb.frame.fbw; + f.fbh = curvb.prndr->fbh; + f.psm = curvb.zbuf.psm; + f.fbm = 0; + curvb.pdepth = (CDepthTarget*)s_DepthRTs.GetTarg(f, CRenderTargetMngr::TO_DepthBuffer | CRenderTargetMngr::TO_StrictHeight | + (curvb.zbuf.zmsk ? CRenderTargetMngr::TO_Virtual : 0), get_maxheight(curvb.zbuf.zbp, curvb.gsfb.fbw, 0)); + } + + assert(curvb.prndr != NULL && curvb.pdepth != NULL); + + if (curvb.pdepth->fbh != curvb.prndr->fbh) ZZLog::Debug_Log("(curvb.pdepth->fbh(0x%x) != curvb.prndr->fbh(0x%x))", curvb.pdepth->fbh, curvb.prndr->fbh); + //assert(curvb.pdepth->fbh == curvb.prndr->fbh); + + if (curvb.pdepth->status & CRenderTarget::TS_Virtual) + { + + if (!curvb.zbuf.zmsk) + { + CRenderTarget* ptemp = s_DepthRTs.Promote(curvb.pdepth->fbp | (curvb.pdepth->fbw << 16)); + assert(ptemp == curvb.pdepth); + } + else + { + curvb.pdepth->status &= ~CRenderTarget::TS_NeedUpdate; + } + } + + bool bSetTarg = 1; + + if (curvb.pdepth->status & CRenderTarget::TS_NeedUpdate) + { + assert(!(curvb.pdepth->status & CRenderTarget::TS_Virtual)); + + // don't update if virtual + curvb.pdepth->Update(context, curvb.prndr); + bSetTarg = 0; + } + + GL_REPORT_ERRORD(); + + if (curvb.prndr->status & CRenderTarget::TS_NeedUpdate) + { + /* if(bSetTarg) { + * ZZLog::Debug_Log( " Here "); + * if(s_bWriteDepth) { + * curvb.pdepth->SetRenderTarget(1); + * curvb.pdepth->SetDepthStencilSurface(); + * } + * else + * curvb.pdepth->SetDepthStencilSurface(); + * }*/ + curvb.prndr->Update(context, curvb.pdepth); + } + else + { + + //if( (vb[0].prndr != vb[1].prndr && vb[!context].bVarsSetTarg) || !vb[context].bVarsSetTarg ) + curvb.prndr->SetRenderTarget(0); + //if( bSetTarg && ((vb[0].pdepth != vb[1].pdepth && vb[!context].bVarsSetTarg) || !vb[context].bVarsSetTarg) ) + curvb.pdepth->SetDepthStencilSurface(); + + if (conf.mrtdepth && IsWriteDepth()) curvb.pdepth->SetRenderTarget(1); + if (s_ptexCurSet[0] == curvb.prndr->ptex) s_ptexCurSet[0] = 0; + if (s_ptexCurSet[1] == curvb.prndr->ptex) s_ptexCurSet[1] = 0; + + curvb.prndr->SetViewport(); + } + + curvb.prndr->SetTarget(curvb.frame.fbp, curvb.scissor, context); + + if ((curvb.zbuf.zbp - curvb.pdepth->fbp) != (curvb.frame.fbp - curvb.prndr->fbp) && curvb.test.zte) + ZZLog::Warn_Log("Frame and zbuf not aligned."); + + curvb.bVarsSetTarg = true; + + if (vb[!context].prndr != curvb.prndr) vb[!context].bVarsSetTarg = false; + +#ifdef _DEBUG + // These conditions happen often enough that we'll just warn about it rather then abort in Debug mode. + if (curvb.prndr->status & CRenderTarget::TS_NeedUpdate) + { + ZZLog::Debug_Log("In SetContextTarget, prndr is ending with TS_NeedUpdate set."); + } + + if (curvb.pdepth != NULL && (curvb.pdepth->status & CRenderTarget::TS_NeedUpdate)) + { + ZZLog::Debug_Log("In SetContextTarget, pdepth is ending with TS_NeedUpdate set."); + } +#endif + + GL_REPORT_ERRORD(); +} + + +void SetTexInt(int context, FRAGMENTSHADER* pfragment, int settexint) +{ + FUNCLOG + + if (settexint) + { + tex0Info& tex0 = vb[context].tex0; + + if (vb[context].bVarsTexSync) { + SetTexVariablesInt(context, GetTexFilter(vb[context].tex1), tex0, true, pfragment, s_bForceTexFlush); + } else { + SetTexVariablesInt(context, GetTexFilter(vb[context].tex1), tex0, false, pfragment, s_bForceTexFlush); + + INC_TEXVARS(); + } + vb[context].bVarsTexSync = true; + } + else + { + vb[context].bVarsTexSync = false; + } +} + +// clamp relies on texture width +void SetTexClamping(int context, FRAGMENTSHADER* pfragment) +{ + FUNCLOG + SetShaderCaller("SetTexClamping"); + clampInfo* pclamp = &vb[context].clamp; + float4 v, v2; + v.x = v.y = 0; + u32* ptex = vb[context].ptexClamp; + ptex[0] = ptex[1] = 0; + + float fw = vb[context].tex0.tw ; + float fh = vb[context].tex0.th ; + + switch (pclamp->wms) + { + case 0: + v2.x = -1e10; + v2.z = 1e10; + break; + + case 1: // pclamp + // suikoden5 movie text + v2.x = 0; + v2.z = 1 - 0.5f / fw; + break; + + case 2: // reg pclamp + v2.x = (pclamp->minu + 0.5f) / fw; + v2.z = (pclamp->maxu - 0.5f) / fw; + break; + + case 3: // region rep x + v.x = 0.9999f; + v.z = (float)fw; + v2.x = (float)GPU_TEXMASKWIDTH / fw; + v2.z = pclamp->maxu / fw; + int correctMinu = pclamp->minu & (~pclamp->maxu); // (A && B) || C == (A && (B && !C)) + C + + if (correctMinu != g_PrevBitwiseTexX) + { + g_PrevBitwiseTexX = correctMinu; + ptex[0] = s_BitwiseTextures.GetTex(correctMinu, 0); + } + + break; + } + + switch (pclamp->wmt) + { + + case 0: + v2.y = -1e10; + v2.w = 1e10; + break; + + case 1: // pclamp + // suikoden5 movie text + v2.y = 0; + v2.w = 1 - 0.5f / fh; + break; + + case 2: // reg pclamp + v2.y = (pclamp->minv + 0.5f) / fh; + v2.w = (pclamp->maxv - 0.5f) / fh; + break; + + case 3: // region rep y + v.y = 0.9999f; + v.w = (float)fh; + v2.y = (float)GPU_TEXMASKWIDTH / fh; + v2.w = pclamp->maxv / fh; + int correctMinv = pclamp->minv & (~pclamp->maxv); // (A && B) || C == (A && (B && !C)) + C + + if (correctMinv != g_PrevBitwiseTexY) + { + g_PrevBitwiseTexY = correctMinv; + ptex[1] = s_BitwiseTextures.GetTex(correctMinv, ptex[0]); + } + break; + } + + if (pfragment->fTexWrapMode != 0) + ZZshSetParameter4fv(pfragment->fTexWrapMode, v, "g_fTexWrapMode"); + + if (pfragment->fClampExts != 0) + ZZshSetParameter4fv(pfragment->fClampExts, v2, "g_fClampExts"); + + +} + +int CheckTexArray[4][2][2][2] = {{{{0, }}}}; +void SetTexVariables(int context, FRAGMENTSHADER* pfragment) +{ + FUNCLOG + + if (!vb[context].curprim.tme) return; + + assert(!vb[context].bNeedTexCheck); + + float4 v, v2; + + tex0Info& tex0 = vb[context].tex0; + + //float fw = (float)tex0.tw; + //float fh = (float)tex0.th; + + if (!vb[context].bTexConstsSync) + { + SetShaderCaller("SetTexVariables"); + + // alpha and texture highlighting + float4 valpha, valpha2 ; + + // if clut, use the frame format + int psm = PIXEL_STORAGE_FORMAT(tex0); + +// ZZLog::Error_Log( "A %d psm, is-clut %d. cpsm %d | %d %d", psm, PSMT_ISCLUT(psm), tex0.cpsm, tex0.tfx, tex0.tcc ); + + float4 vblack; + vblack.x = vblack.y = vblack.z = vblack.w = 10; + + /* tcc -- Tecture Color Component 0=RGB, 1=RGBA + use Alpha from TEXA reg when not in PSM + * tfx -- Texture Function (0=modulate, 1=decal, 2=hilight, 3=hilight2) + * + * valpha2 = 0 0 2 1 0 0 2 1 + * 1 0 0 0 1 1 0 0 + * 0 0 2 0 0 1 2 0 + * 0 0 2 0 0 1 2 0 + * + * 0 1,!nNeed 1, psm=2, 10 1, psm=1 + * valpha = 0 0 0 1 0 2 0 0 2ta0 2ta1-2ta0 0 0 2ta0 0 0 0 + * 0 0 0 1 0 1 0 0 ta0 ta1-ta0 0 0 ta0 0 0 0 + * 0 0 1 1 0 1 1 1 1 1 ta0 0 1 1 + * 0 0 1 1 0 1 1 0 1 0 ta0 0 1 0 + */ + + valpha2.x = (tex0.tfx == 1) ; + valpha2.y = (tex0.tcc == 1) && (tex0.tfx != 0) ; + valpha2.z = (tex0.tfx != 1) * 2 ; + valpha2.w = (tex0.tfx == 0) ; + + if (tex0.tcc == 0 || !PSMT_ALPHAEXP(psm)) + { + valpha.x = 0 ; + valpha.y = (!!tex0.tcc) * (1 + (tex0.tfx == 0)) ; + } + else + { + valpha.x = (gs.texa.fta[0]) * (1 + (tex0.tfx == 0)) ; + valpha.y = (gs.texa.fta[psm != PSMCT24] - gs.texa.fta[0]) * (1 + (tex0.tfx == 0)) ; + + } + + valpha.z = (tex0.tfx >= 3) ; + + valpha.w = (tex0.tcc == 0) || (tex0.tcc == 1 && tex0.tfx == 2) ; + + if (tex0.tcc && gs.texa.aem && psm == PSMCT24) + vblack.w = 0; + + /* + // Test, old code. + float4 valpha3, valpha4; + switch(tex0.tfx) { + case 0: + valpha3.z = 0; valpha3.w = 0; + valpha4.x = 0; valpha4.y = 0; + valpha4.z = 2; valpha4.w = 1; + + break; + case 1: + valpha3.z = 0; valpha3.w = 1; + valpha4.x = 1; valpha4.y = 0; + valpha4.z = 0; valpha4.w = 0; + + break; + case 2: + valpha3.z = 1; valpha3.w = 1.0f; + valpha4.x = 0; valpha4.y = tex0.tcc ? 1.0f : 0.0f; + valpha4.z = 2; valpha4.w = 0; + + break; + + case 3: + valpha3.z = 1; valpha3.w = tex0.tcc ? 0.0f : 1.0f; + valpha4.x = 0; valpha4.y = tex0.tcc ? 1.0f : 0.0f; + valpha4.z = 2; valpha4.w = 0; + + break; + } + if( tex0.tcc ) { + + if( tex0.tfx == 1 ) { + //mode.x = 10; + valpha3.z = 0; valpha3.w = 0; + valpha4.x = 1; valpha4.y = 1; + valpha4.z = 0; valpha4.w = 0; + } + + if( PSMT_ALPHAEXP(psm) ) { + + if( tex0.tfx == 0 ) { + // make sure alpha is mult by two when the output is Cv = Ct*Cf + valpha3.x = 2*gs.texa.fta[0]; + // if 24bit, always choose ta[0] + valpha3.y = 2*gs.texa.fta[psm != 1]; + valpha3.y -= valpha.x; + } + else { + valpha3.x = gs.texa.fta[0]; + // if 24bit, always choose ta[0] + valpha3.y = gs.texa.fta[psm != 1]; + valpha3.y -= valpha.x; + } + } + else { + if( tex0.tfx == 0 ) { + valpha3.x = 0; + valpha3.y = 2; + } + else { + valpha3.x = 0; + valpha3.y = 1; + } + } + } + else { + + // reset alpha to color + valpha3.x = valpha3.y = 0; + valpha3.w = 1; + } + + if ( equal_vectors(valpha, valpha3) && equal_vectors(valpha2, valpha4) ) { + if (CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][PSMT_ALPHAEXP(psm)] == 0) { + ZZLog::Debug_Log ( "Good issue %d %d %d %d", tex0.tfx, tex0.tcc, psm, PSMT_ALPHAEXP(psm) ); + CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][PSMT_ALPHAEXP(psm) ] = 1; + } + } + else if (CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][PSMT_ALPHAEXP(psm)] == -1) { + ZZLog::Debug_Log ("Bad array, %d %d %d %d\n\tolf valpha %f, %f, %f, %f : valpha2 %f %f %f %f\n\tnew valpha %f, %f, %f, %f : valpha2 %f %f %f %f", + tex0.tfx, tex0.tcc, psm, PSMT_ALPHAEXP(psm), + valpha3.x, valpha3.y, valpha3.z, valpha3.w, valpha4.x, valpha4.y, valpha4.z, valpha4.w, + valpha.x, valpha.y, valpha.z, valpha.w, valpha2.x, valpha2.y, valpha2.z, valpha2.w); + CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][PSMT_ALPHAEXP(psm)] = -1 ; + } + + // Test;*/ + + ZZshSetParameter4fv(pfragment->fTexAlpha, valpha, "g_fTexAlpha"); + ZZshSetParameter4fv(pfragment->fTexAlpha2, valpha2, "g_fTexAlpha2"); + + if (IsAlphaTestExpansion(tex0)) + ZZshSetParameter4fv(pfragment->fTestBlack, vblack, "g_fTestBlack"); + + SetTexClamping(context, pfragment); + + vb[context].bTexConstsSync = true; + } + + if (s_bTexFlush) + { + if (PSMT_ISCLUT(tex0.psm)) + texClutWrite(context); + else + s_bTexFlush = false; + } +} + +void SetTexVariablesInt(int context, int bilinear, const tex0Info& tex0, bool CheckVB, FRAGMENTSHADER* pfragment, int force) +{ + FUNCLOG + float4 v; + CMemoryTarget* pmemtarg = g_MemTargs.GetMemoryTarget(tex0, 1); + + assert( pmemtarg != NULL && pfragment != NULL && pmemtarg->ptex != NULL); + if (pmemtarg == NULL || pfragment == NULL || pmemtarg->ptex == NULL) + { + ZZLog::Error_Log("SetTexVariablesInt error."); + return; + } + + if (CheckVB && vb[context].pmemtarg == pmemtarg) return; + + SetShaderCaller("SetTexVariablesInt"); + + float fw = (float)tex0.tw; + float fh = (float)tex0.th; + + bool bUseBilinear = bilinear > 1 || (bilinear && conf.bilinear); + + if (bUseBilinear) + { + v.x = (float)fw; + v.y = (float)fh; + v.z = 1.0f / (float)fw; + v.w = 1.0f / (float)fh; + + if (pfragment->fRealTexDims) + ZZshSetParameter4fv(pfragment->fRealTexDims, v, "g_fRealTexDims"); + else + ZZshSetParameter4fv(cgGetNamedParameter(pfragment->prog,"g_fRealTexDims"),v, "g_fRealTexDims"); + } + + if (m_Blocks[tex0.psm].bpp == 0) + { + ZZLog::Error_Log("Undefined tex psm 0x%x!", tex0.psm); + return; + } + + const BLOCK& b = m_Blocks[tex0.psm]; + + float fbw = (float)tex0.tbw; + + float4 vTexDims; + + vTexDims.x = b.vTexDims.x * (fw); + vTexDims.y = b.vTexDims.y * (fh); + vTexDims.z = (float)BLOCK_TEXWIDTH * (0.002f / 64.0f + 0.01f / 128.0f); + vTexDims.w = (float)BLOCK_TEXHEIGHT * 0.1f / 512.0f; + + if (bUseBilinear) + { + vTexDims.x *= 1 / 128.0f; + vTexDims.y *= 1 / 512.0f; + vTexDims.z *= 1 / 128.0f; + vTexDims.w *= 1 / 512.0f; + } + + float g_fitexwidth = g_fiGPU_TEXWIDTH / (float)pmemtarg->widthmult; + + //float g_texwidth = GPU_TEXWIDTH*(float)pmemtarg->widthmult; + + float fpage = tex0.tbp0 * (64.0f * g_fitexwidth);// + 0.05f * g_fitexwidth; + float fpageint = floorf(fpage); + //int starttbp = (int)fpage; + + // 2048 is number of words to span one page + //float fblockstride = (2048.0f /(float)(g_texwidth*BLOCK_TEXWIDTH)) * b.vTexDims.x * fbw; + + float fblockstride = (2048.0f / (float)(GPU_TEXWIDTH * (float)pmemtarg->widthmult * BLOCK_TEXWIDTH)) * b.vTexDims.x * fbw; + + assert(fblockstride >= 1.0f); + + v.x = (float)(2048 * g_fitexwidth); + v.y = fblockstride; + v.z = g_fBlockMult / (float)pmemtarg->widthmult; + v.w = fpage - fpageint ; + + if (g_fBlockMult > 1) + { + // make sure to divide by mult (since the G16R16 texture loses info) + v.z *= b.bpp * (1 / 32.0f); + } + + ZZshSetParameter4fv(pfragment->fTexDims, vTexDims, "g_fTexDims"); + +// ZZshSetParameter4fv(pfragment->fTexBlock, b.vTexBlock, "g_fTexBlock"); // I change it, and it's working. Seems casting from float4 to float[4] is ok. + ZZshSetParameter4fv(pfragment->fTexBlock, &b.vTexBlock.x, "g_fTexBlock"); + ZZshSetParameter4fv(pfragment->fTexOffset, v, "g_fTexOffset"); + + // get hardware texture dims + //int texheight = pmemtarg->texH; + int texwidth = pmemtarg->texW; + + v.y = 1.0f; + v.x = (fpageint - (float)pmemtarg->realy / (float)pmemtarg->widthmult + 0.5f);//*v.y; + v.z = (float)texwidth; + + /* if( !(g_nPixelShaderVer & SHADER_ACCURATE) || bUseBilinear ) { + if (tex0.psm == PSMT4 ) + v.w = 0.0f; + else + v.w = 0.25f; + } + else + v.w = 0.5f;*/ + v.w = 0.5f; + + ZZshSetParameter4fv(pfragment->fPageOffset, v, "g_fPageOffset"); + + if (force) + s_ptexCurSet[context] = pmemtarg->ptex->tex; + else + s_ptexNextSet[context] = pmemtarg->ptex->tex; + + vb[context].pmemtarg = pmemtarg; + + vb[context].bVarsTexSync = false; +} + +#define SET_ALPHA_COLOR_FACTOR(sign) \ +{ \ + switch(a.c) \ + { \ + case 0: \ + vAlphaBlendColor.y = (sign) ? 2.0f*255.0f/256.0f : -2.0f*255.0f/256.0f; \ + s_srcalpha = GL_ONE; \ + s_alphaeq = (sign) ? GL_FUNC_ADD : GL_FUNC_REVERSE_SUBTRACT; \ + break; \ + \ + case 1: \ + /* if in 24 bit mode, dest alpha should be one */ \ + switch(PSMT_BITMODE(vb[icurctx].prndr->psm)) \ + { \ + case 0: \ + bDestAlphaColor = (a.d!=2)&&((a.a==a.d)||(a.b==a.d)); \ + break; \ + \ + case 1: \ + /* dest alpha should be one */ \ + bDestAlphaColor = 2; \ + break; \ + /* default: 16bit surface, so returned alpha is ok */ \ + } \ + break; \ + \ + case 2: \ + bNeedBlendFactorInAlpha = true; /* should disable alpha channel writing */ \ + vAlphaBlendColor.y = 0; \ + vAlphaBlendColor.w = (sign) ? (float)a.fix * (2.0f/255.0f) : (float)a.fix * (-2.0f/255.0f); \ + usec = 0; /* change so that alpha comes from source*/ \ + break; \ + } \ +} \ + +//if( a.fix <= 0x80 ) { \ +// dwTemp = (a.fix*2)>255?255:(a.fix*2); \ +// dwTemp = dwTemp|(dwTemp<<8)|(dwTemp<<16)|0x80000000; \ +// ZZLog::Debug_Log("bfactor: %8.8x", dwTemp); \ +// glBlendColorEXT(dwTemp); \ +// } \ +// else { \ + +//void ResetAlphaVariables() { +// FUNCLOG +//} + +inline void NeedFactor(int w) +{ + if (bDestAlphaColor == 2) + { + bNeedBlendFactorInAlpha = (w + 1) ? true : false; + vAlphaBlendColor.y = 0; + vAlphaBlendColor.w = (float)w; + } +} + +//static int CheckArray[48][2] = {{0,}}; + +void SetAlphaVariables(const alphaInfo& a) +{ + FUNCLOG + bool alphaenable = true; + + // TODO: negative color when not clamping turns to positive??? + g_vars._bAlphaState = 0; // set all to zero + bNeedBlendFactorInAlpha = false; + b2XAlphaTest = 1; + //u32 dwTemp = 0xffffffff; + bDestAlphaColor = 0; + + // default + s_srcalpha = GL_ONE; + s_dstalpha = GL_ZERO; + s_alphaeq = GL_FUNC_ADD; + s_rgbeq = 1; + +// s_alphaInfo = a; + vAlphaBlendColor = float4(1, 2 * 255.0f / 256.0f, 0, 0); + u32 usec = a.c; + + + /* + * Alpha table + * a + b + d + * S D + * 0 a -a 1 | 0 0 0 + * 1 0 0 0 | a -a 1 + * 2 0 0 0 | 0 0 0 + * + * d = 0 Cs + * a b 0 Cs 1 Cd 2 0 + * | | + * 0 000: a+-a+ 1 | 0+ 0+ 0 = 1 | 010: a+ 0+ 1 | 0+-a+ 0 = 1-(-a)(+)(-a) | 020: a+ 0+ 1 | 0+ 0+ 0 = 1-(-a) (+) 0 + * 1 100: 0+-a+ 1 | a+ 0+ 0 = 1-a (+) a | 110: 0+ 0+ 1 | a+-a+ 0 = 1 | 120: 0+ 0+ 1 | a+ 0+ 0 = 1 (+) a + * 2 200: 0+-a+ 1 | 0+ 0+ 0 = 1-a (+) 0 | 210: 0+ 0+ 1 | 0+-a+ 0 = 1 (-) a | 220: 0+ 0+ 1 | 0+ 0+ 0 = 1 + * + * d = 1 Cd + * 0 | 1 | 2 + * 0 001: a+-a+ 0 | 0+ 0+ 1 = 0 (+) 1 | 011: a+ 0+ 0 | 0+-a+ 1 = a (+) 1-a | 021: a+ 0+ 0 | 0+ 0+ 1 = a (+) 1 + * 1 101: 0+-a+ 0 | a+ 0+ 1 = (-a)(+) 1-(-a) | 111: 0+ 0+ 0 | a+-a+ 1 = 0 (+) 1 | 121: 0+ 0+ 0 | a+ 0+ 1 = 0 (+) 1-(-a) + * 2 201: 0+-a+ 0 | 0+ 0+ 1 = a (R-)1 | 211: 0+ 0+ 0 | 0+-a+ 1 = 0 (+) 1-a | 221: 0+ 0+ 0 | 0+ 0+ 1 = 0 (+) 1 + * + * d = 2 0 + * 0 | 1 | 2 + * 0 002: a+-a+ 0 | 0+ 0+ 0 = 0 | 012: a+ 0+ 0 | 0+-a+ 0 = a (-) a | 022: a+ 0+ 0 | 0+ 0+ 0 = a (+) 0 + * 1 102: 0+-a+ 0 | a+ 0+ 0 = a (R-) a | 112: 0+ 0+ 0 | a+-a+ 0 = 0 | 122: 0+ 0+ 0 | a+ 0+ 0 = 0 (+) a + * 2 202: 0+-a+ 0 | 0+ 0+ 0 = a (R-) 0 | 212: 0+ 0+ 0 | 0+-a+ 0 = 0 (-) a | 222: 0+ 0+ 0 | 0+ 0+ 0 = 0 + * + * Formulae is: (a-b) * (c /32) + d + * 0 1 2 + * a Cs Cd 0 + * b Cs Cd 0 + * c As Ad ALPHA.FIX + * d Cs Cd 0 + * + * We want to emulate Cs * F1(alpha) + Cd * F2(alpha) by OpenGl blending: (Cs * Ss (+,-,R-) Cd * Sd) + * SET_ALPHA_COLOR_FACTOR(sign) set Set A (as As>>7, Ad>>7 or FIX>>7) with sign. + * So we could use 1+a as one_minus_alpha and -a as alpha. + * + */ + int code = (a.a * 16) + (a.b * 4) + a.d ; + +#define one_minus_alpha (bDestAlphaColor == 2) ? GL_ONE_MINUS_SRC_ALPHA : blendinvalpha[usec] +#define alpha (bDestAlphaColor == 2) ? GL_SRC_ALPHA : blendalpha[usec] +#define one (bDestAlphaColor == 2) ? GL_ONE : blendalpha[usec] +#define zero (bDestAlphaColor == 2) ? GL_ZERO : blendinvalpha[usec] + + switch (code) + { + + case 0: // 000 // Cs -- nothing changed + case 20: // 110 = 16+4=20 // Cs + case 40: // 220 = 32+8=40 // Cs + { + alphaenable = false; + break; + } + + case 2: //002 // 0 -- should be zero + case 22: //112 // 0 + case 42: //222 = 32+8+2 =42 // 0 + { + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = GL_ZERO; + s_dstrgb = GL_ZERO; + break; + } + + case 1: //001 // Cd -- Should be destination alpha + case 21: //111, // Cd -- 0*Source + 1*Desrinarion + case 41: //221 = 32+8+1=41 // Cd -- + { + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = GL_ZERO; + s_dstrgb = GL_ONE; + break; + } + + case 4: // 010 // (Cs-Cd)*A+Cs = Cs * (A + 1) - Cd * A + { + bAlphaClamping = 3; + SET_ALPHA_COLOR_FACTOR(0); // a = -A + + s_rgbeq = GL_FUNC_ADD; // Cs*(1-a)+Cd*a + s_srcrgb = one_minus_alpha ; + s_dstrgb = alpha; + + NeedFactor(-1); + break; + } + + case 5: // 011 // (Cs-Cd)*A+Cs = Cs * A + Cd * (1-A) + { + bAlphaClamping = 3; // all testing + SET_ALPHA_COLOR_FACTOR(1); + + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = alpha; + s_dstrgb = one_minus_alpha; + + NeedFactor(1); + break; + } + + case 6: //012 // (Cs-Cd)*FIX + { + bAlphaClamping = 3; + SET_ALPHA_COLOR_FACTOR(1); + + s_rgbeq = GL_FUNC_SUBTRACT; + s_srcrgb = alpha; + s_dstrgb = alpha; + + break; + } + + case 8: //020 // Cs*A+Cs = Cs * (1+A) + { + bAlphaClamping = 2; // max testing + SET_ALPHA_COLOR_FACTOR(0); // Zeyflitz change this! a = -A + + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = one_minus_alpha; // Cs*(1-a). + s_dstrgb = GL_ZERO; + +// NeedFactor(1); + break; + } + + case 9: //021 // Cs*A+Cd + { + bAlphaClamping = 2; // max testing + SET_ALPHA_COLOR_FACTOR(1); + + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = alpha; // ZZ change it to. + s_dstrgb = GL_ONE; + break; + } + + case 10: //022 // Cs*A + { + bAlphaClamping = 2; // max testing + SET_ALPHA_COLOR_FACTOR(1); + + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = alpha; + s_dstrgb = GL_ZERO; + break; + } + + case 16: //100 + { + bAlphaClamping = 3; + SET_ALPHA_COLOR_FACTOR(1); + + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = one_minus_alpha; + s_dstrgb = alpha; + + NeedFactor(1); + break; + } + + case 17: //101 + { + bAlphaClamping = 3; // all testing + SET_ALPHA_COLOR_FACTOR(0); + + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = alpha; + s_dstrgb = one_minus_alpha; + + NeedFactor(-1); + break; + } + + case 18: //102 + { + bAlphaClamping = 3; + SET_ALPHA_COLOR_FACTOR(1); + + s_rgbeq = GL_FUNC_REVERSE_SUBTRACT; + s_srcrgb = alpha; + s_dstrgb = alpha; + + break; + } + + case 24: //120 = 16+8 + { + bAlphaClamping = 2; // max testing + SET_ALPHA_COLOR_FACTOR(1); + + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = GL_ONE; + s_dstrgb = alpha; + break; + } + + case 25: //121 // Cd*(1+A) + { + bAlphaClamping = 2; // max testing + SET_ALPHA_COLOR_FACTOR(0); + + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = GL_ZERO; + s_dstrgb = one_minus_alpha; + +// NeedFactor(-1); + break; + } + + case 26: //122 + { + bAlphaClamping = 2; + SET_ALPHA_COLOR_FACTOR(1); + + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = GL_ZERO; + s_dstrgb = alpha; + break; + } + + case 32: // 200 = 32 + { + bAlphaClamping = 1; // min testing + SET_ALPHA_COLOR_FACTOR(1); + + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = one_minus_alpha; + s_dstrgb = GL_ZERO; + break; + } + + case 33: //201 // -Cs*A + Cd + { + bAlphaClamping = 1; // min testing + SET_ALPHA_COLOR_FACTOR(1); + + s_rgbeq = GL_FUNC_REVERSE_SUBTRACT; + s_srcrgb = alpha; + s_dstrgb = GL_ONE; + break; + } + + case 34: //202 + case 38: //212 + { + bAlphaClamping = 1; // min testing -- negative values + + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = GL_ZERO; + s_dstrgb = GL_ZERO; + break; + } + + case 36: //210 + { + bAlphaClamping = 1; // min testing + SET_ALPHA_COLOR_FACTOR(1); + + s_rgbeq = GL_FUNC_SUBTRACT; + s_srcrgb = GL_ONE; + s_dstrgb = alpha; + break; + } + + case 37: //211 + { + bAlphaClamping = 1; // min testing + SET_ALPHA_COLOR_FACTOR(1); + + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = GL_ZERO; + s_dstrgb = one_minus_alpha; + break; + } + + default: + { + ZZLog::Error_Log("Bad alpha code %d | %d %d %d", code, a.a, a.b, a.d); + } + } + + /* + int t_rgbeq = GL_FUNC_ADD; + int t_srcrgb = GL_ONE; + int t_dstrgb = GL_ZERO; + int tAlphaClamping = 0; + + if( a.a == a.b ) + { // just d remains + if( a.d == 0 ) {} + else + { + t_dstrgb = a.d == 1 ? GL_ONE : GL_ZERO; + t_srcrgb = GL_ZERO; + t_rgbeq = GL_FUNC_ADD; //a) (001) (111) (221) b) (002) (112) (222) + } + goto EndSetAlpha; + } + else if( a.d == 2 ) + { // zero + if( a.a == 2 ) + { + // zero all color + t_srcrgb = GL_ZERO; + t_dstrgb = GL_ZERO; + goto EndSetAlpha; // (202) (212) + } + else if( a.b == 2 ) + { + //b2XAlphaTest = 1; // a) (022) // b) (122) + SET_ALPHA_COLOR_FACTOR(1); + + if( bDestAlphaColor == 2 ) + { + t_rgbeq = GL_FUNC_ADD; + t_srcrgb = a.a == 0 ? GL_ONE : GL_ZERO; + t_dstrgb = a.a == 0 ? GL_ZERO : GL_ONE; + } + else + { + tAlphaClamping = 2; + t_rgbeq = GL_FUNC_ADD; + t_srcrgb = a.a == 0 ? blendalpha[usec] : GL_ZERO; + t_dstrgb = a.a == 0 ? GL_ZERO : blendalpha[usec]; + } + + goto EndSetAlpha; + } + + // nothing is zero, so must do some real blending //b2XAlphaTest = 1; //a) (012) //b) (102) + tAlphaClamping = 3; + + SET_ALPHA_COLOR_FACTOR(1); + + t_rgbeq = a.a == 0 ? GL_FUNC_SUBTRACT : GL_FUNC_REVERSE_SUBTRACT; + t_srcrgb = bDestAlphaColor == 2 ? GL_ONE : blendalpha[usec]; + t_dstrgb = bDestAlphaColor == 2 ? GL_ONE : blendalpha[usec]; + } + else if( a.a == 2 ) + { // zero + + //b2XAlphaTest = 1; + tAlphaClamping = 1; // min testing + + SET_ALPHA_COLOR_FACTOR(1); + + if( a.b == a.d ) + { + // can get away with 1-A + // a.a == a.d == 2!! (200) (211) + t_rgbeq = GL_FUNC_ADD; + t_srcrgb = (a.b == 0 && bDestAlphaColor != 2) ? blendinvalpha[usec] : GL_ZERO; + t_dstrgb = (a.b == 0 || bDestAlphaColor == 2) ? GL_ZERO : blendinvalpha[usec]; + } + else + { + // a) (201) b)(210) + t_rgbeq = a.b==0 ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_SUBTRACT; + t_srcrgb = (a.b == 0 && bDestAlphaColor != 2) ? blendalpha[usec] : GL_ONE; + t_dstrgb = (a.b == 0 || bDestAlphaColor == 2 ) ? GL_ONE : blendalpha[usec]; + } + } + else if( a.b == 2 ) + { + tAlphaClamping = 2; // max testing + + SET_ALPHA_COLOR_FACTOR(a.a!=a.d); + + if( a.a == a.d ) + { + // can get away with 1+A, but need to set alpha to negative + // a)(020) + // b)(121) + t_rgbeq = GL_FUNC_ADD; + + if( bDestAlphaColor == 2 ) + { + t_srcrgb = (a.a == 0) ? GL_ONE_MINUS_SRC_ALPHA : GL_ZERO; + t_dstrgb = (a.a == 0) ? GL_ZERO : GL_ONE_MINUS_SRC_ALPHA; + } + else + { + t_srcrgb = a.a == 0 ? blendinvalpha[usec] : GL_ZERO; + t_dstrgb = a.a == 0 ? GL_ZERO : blendinvalpha[usec]; + } + } + else + { + //a)(021) //b)(120) //b2XAlphaTest = 1; + t_rgbeq = GL_FUNC_ADD; + t_srcrgb = (a.a == 0 && bDestAlphaColor != 2) ? blendalpha[usec] : GL_ONE; + t_dstrgb = (a.a == 0 || bDestAlphaColor == 2) ? GL_ONE : blendalpha[usec]; + } + } + else + { + // all 3 components are valid! + tAlphaClamping = 3; // all testing + SET_ALPHA_COLOR_FACTOR(a.a!=a.d); + + if( a.a == a.d ) + { + // can get away with 1+A, but need to set alpha to negative // a) 010, // b) 101 + t_rgbeq = GL_FUNC_ADD; + + if( bDestAlphaColor == 2 ) + { + // all ones + t_srcrgb = a.a == 0 ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA; + t_dstrgb = a.a == 0 ? GL_SRC_ALPHA : GL_ONE_MINUS_SRC_ALPHA; + } + else + { + t_srcrgb = a.a == 0 ? blendinvalpha[usec] : blendalpha[usec]; + t_dstrgb = a.a == 0 ? blendalpha[usec] : blendinvalpha[usec]; + } + } + else + { + t_rgbeq = GL_FUNC_ADD; // a) 011 // b) 100 // + if( bDestAlphaColor == 2 ) + { + // all ones + t_srcrgb = a.a != 0 ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA; + t_dstrgb = a.a != 0 ? GL_SRC_ALPHA : GL_ONE_MINUS_SRC_ALPHA; + } + else + { + //b2XAlphaTest = 1; + t_srcrgb = a.a != 0 ? blendinvalpha[usec] : blendalpha[usec]; + t_dstrgb = a.a != 0 ? blendalpha[usec] : blendinvalpha[usec]; + } + } + } + EndSetAlpha: + + + if ( alphaenable && (t_rgbeq != s_rgbeq || s_srcrgb != t_srcrgb || t_dstrgb != s_dstrgb || tAlphaClamping != bAlphaClamping)) { + if (CheckArray[code][(bDestAlphaColor==2)] != -1) { + ZZLog::Debug_Log( "A code %d, 0x%x, 0x%x, 0x%x, 0x%x %d", code, alpha, one_minus_alpha, one, zero, bDestAlphaColor ); + ZZLog::Debug_Log( " Difference %d %d %d %d | 0x%x 0x%x | 0x%x 0x%x | 0x%x 0x%x | %d %d", + code, a.a, a.b, a.d, + t_rgbeq, s_rgbeq, t_srcrgb, s_srcrgb, t_dstrgb, s_dstrgb, tAlphaClamping, bAlphaClamping); + CheckArray[code][(bDestAlphaColor==2)] = -1; + } + } + else + if (CheckArray[code][(bDestAlphaColor==2)] == 0){ + ZZLog::Debug_Log( "Add good code %d %d, psm %d destA %d", code, a.c, vb[icurctx].prndr->psm, bDestAlphaColor); + CheckArray[code][(bDestAlphaColor==2)] = 1; + }*/ + + + if (alphaenable) + { + zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); + zgsBlendEquationSeparateEXT(s_rgbeq, s_alphaeq); + glEnable(GL_BLEND); // always set + } + else + { + glDisable(GL_BLEND); + } + + INC_ALPHAVARS(); +} + +void SetWriteDepth() +{ + FUNCLOG + + if (conf.mrtdepth) + { + s_bWriteDepth = true; + s_nWriteDepthCount = 4; + } +} + +bool IsWriteDepth() +{ + FUNCLOG + return s_bWriteDepth; +} + +bool IsWriteDestAlphaTest() +{ + FUNCLOG + return s_bDestAlphaTest; +} + +void SetDestAlphaTest() +{ + FUNCLOG + s_bDestAlphaTest = true; + s_nWriteDestAlphaTest = 4; +} + +void SetTexFlush() +{ + FUNCLOG + s_bTexFlush = true; + +// if( PSMT_ISCLUT(vb[0].tex0.psm) ) +// texClutWrite(0); +// if( PSMT_ISCLUT(vb[1].tex0.psm) ) +// texClutWrite(1); + + if (!s_bForceTexFlush) + { + if (s_ptexCurSet[0] != s_ptexNextSet[0]) s_ptexCurSet[0] = s_ptexNextSet[0]; + if (s_ptexCurSet[1] != s_ptexNextSet[1]) s_ptexCurSet[1] = s_ptexNextSet[1]; + } +} + diff --git a/plugins/zzogl-pg-cg/opengl/ZZoglFlushHack.cpp b/plugins/zzogl-pg-cg/opengl/ZZoglFlushHack.cpp new file mode 100644 index 000000000..b1e311a5d --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZZoglFlushHack.cpp @@ -0,0 +1,531 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2010 gregory.hainaut@gmail.com, zeydlitz@gmail.com + * Based on GSdx Copyright (C) 2007-2009 Gabest + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* This file is a collection of hack for removing the blur effect on some games + * The blur renders very badly on high screen flat panel. + * + * To avoid severals combo-box, the hack detects the game based on crc + */ + +#include "ZZoglFlushHack.h" + +inline bool GABEST_HAS_SHARED_BITS (int fbp, int fpsm, int tbp, int tpsm) +{ + if ( !PSMT_HAS_SHARED_BITS (fpsm, tpsm) ) + return ((fbp ^ tbp) == 0); + else + return false; +} + + +// GSC_... function has been imported from GSdx +void GSC_Okami(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && fi.FBP == 0x00e00 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x00000 && fi.TPSM == PSMCT32) + skip = 1000; + } + else + { + if(fi.TME && fi.FBP == 0x00e00 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x03800 && fi.TPSM == PSMT4) + skip = 0; + } +} + +void GSC_MetalGearSolid3(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && fi.FBP == 0x02000 && fi.FPSM == PSMCT32 && (fi.TBP0 == 0x00000 || fi.TBP0 == 0x01000) && fi.TPSM == PSMCT24) + skip = 1000; // 76, 79 + else if(fi.TME && fi.FBP == 0x02800 && fi.FPSM == PSMCT24 && (fi.TBP0 == 0x00000 || fi.TBP0 == 0x01000) && fi.TPSM == PSMCT32) + skip = 1000; // 69 + } + else + { + if(!fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x01000) && fi.FPSM == PSMCT32) + skip = 0; + } +} + +void GSC_DBZBT2(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && /*fi.FBP == 0x00000 && fi.FPSM == PSMCT16 &&*/ fi.TBP0 == 0x02000 && fi.TPSM == PSMT16Z) + skip = 27; + else if(!fi.TME && fi.FBP == 0x03000 && fi.FPSM == PSMCT16) + skip = 10; + } +} + +void GSC_DBZBT3(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && fi.FBP == 0x01c00 && fi.FPSM == PSMCT32 && (fi.TBP0 == 0x00000 || fi.TBP0 == 0x00e00) && fi.TPSM == PSMT8H) + skip = 24; // blur + else if(fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x00e00) && fi.FPSM == PSMCT32 && fi.TPSM == PSMT8H) + skip = 28; // outline + } +} + +void GSC_SFEX3(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && fi.FBP == 0x00500 && fi.FPSM == PSMCT16 && fi.TBP0 == 0x00f00 && fi.TPSM == PSMCT16) + skip = 2; // blur + } +} + +void GSC_Bully(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + // Test is useless ! + // if(fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x01180) && (fi.TBP0 == 0x00000 || fi.TBP0 == 0x01180) && fi.FBP == fi.TBP0 && fi.FPSM == PSMCT32 && fi.FPSM == fi.TPSM) + // return; // allowed + if(fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x01180) && fi.FPSM == PSMCT16S && fi.TBP0 == 0x02300 && fi.TPSM == PSMT16SZ) + skip = 6; + } + else + { + if(!fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x01180) && fi.FPSM == PSMCT32) + skip = 0; + } +} + +void GSC_BullyCC(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + // Test is useless ! + // if(fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x01180) && (fi.TBP0 == 0x00000 || fi.TBP0 == 0x01180) && fi.FBP == fi.TBP0 && fi.FPSM == PSMCT32 && fi.FPSM == fi.TPSM) + // return; // allowed + + if(!fi.TME && fi.FBP == 0x02800 && fi.FPSM == PSMCT24) + skip = 9; + } +} + +void GSC_SoTC(const GSFrameInfo& fi, int& skip) +{ + // Not needed anymore? What did it fix anyway? (rama) + /*if(skip == 0) + { + if(fi.TME && fi.FBP == 0x02b80 && fi.FPSM == PSMCT24 && fi.TBP0 == 0x01e80 && fi.TPSM == PSMCT24) + skip = 9; + else if(fi.TME && fi.FBP == 0x01c00 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x03800 && fi.TPSM == PSMCT32) + skip = 8; + else if(fi.TME && fi.FBP == 0x01e80 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x03880 && fi.TPSM == PSMCT32) + skip = 8; + }*/ +} + +void GSC_OnePieceGrandAdventure(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && fi.FBP == 0x02d00 && fi.FPSM == PSMCT16 && (fi.TBP0 == 0x00000 || fi.TBP0 == 0x00e00 || fi.TBP0 == 0x00f00) && fi.TPSM == PSMCT16) + skip = 4; + } +} + +void GSC_OnePieceGrandBattle(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && fi.FBP == 0x02d00 && fi.FPSM == PSMCT16 && (fi.TBP0 == 0x00000 || fi.TBP0 == 0x00f00) && fi.TPSM == PSMCT16) + skip = 4; + } +} + +void GSC_ICO(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && fi.FBP == 0x00800 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x03d00 && fi.TPSM == PSMCT32) + skip = 3; + else if(fi.TME && fi.FBP == 0x00800 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x02800 && fi.TPSM == PSMT8H) + skip = 1; + } + else + { + if(fi.TME && fi.TBP0 == 0x00800 && fi.TPSM == PSMCT32) + skip = 0; + } +} + +void GSC_GT4(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && (fi.FBP == 0x03440 || fi.FBP >= 0x03e00) && fi.FPSM == PSMCT32 && (fi.TBP0 == 0x00000 || fi.TBP0 == 0x01400) && fi.TPSM == PSMT8) + skip = 880; + else if(fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x01400) && fi.FPSM == PSMCT24 && fi.TBP0 >= 0x03420 && fi.TPSM == PSMT8) + { + // TODO: removes gfx from where it is not supposed to (garage) + // skip = 58; + } + } +} + +void GSC_WildArms4(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && fi.FBP == 0x03100 && fi.FPSM == PSMT32Z && fi.TBP0 == 0x01c00 && fi.TPSM == PSMT32Z) + skip = 100; + } + else + { + if(fi.TME && fi.FBP == 0x00e00 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x02a00 && fi.TPSM == PSMCT32) + skip = 1; + } +} + +void GSC_WildArms5(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && fi.FBP == 0x03100 && fi.FPSM == PSMT32Z && fi.TBP0 == 0x01c00 && fi.TPSM == PSMT32Z) + skip = 100; + } + else + { + if(fi.TME && fi.FBP == 0x00e00 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x02a00 && fi.TPSM == PSMCT32) + skip = 1; + } +} + +void GSC_Manhunt2(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && fi.FBP == 0x03c20 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x01400 && fi.TPSM == PSMT8) + skip = 640; + } +} + +void GSC_CrashBandicootWoC(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + // Test is useless ! + // if(fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x00a00) && (fi.TBP0 == 0x00000 || fi.TBP0 == 0x00a00) && fi.FBP == fi.TBP0 && fi.FPSM == PSMCT32 && fi.FPSM == fi.TPSM) + // return false; // allowed + + if(fi.TME && fi.FBP == 0x02200 && fi.FPSM == PSMT24Z && fi.TBP0 == 0x01400 && fi.TPSM == PSMT24Z) + skip = 41; + } + else + { + if(fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x00a00) && fi.FPSM == PSMCT32 && fi.TBP0 == 0x03c00 && fi.TPSM == PSMCT32) + skip = 0; + else if(!fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x00a00)) + skip = 0; + } +} + +void GSC_ResidentEvil4(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && fi.FBP == 0x03100 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x01c00 && fi.TPSM == PSMT24Z) + skip = 176; + } +} + +void GSC_Spartan(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && fi.FBP == 0x02000 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x00000 && fi.TPSM == PSMCT32) + skip = 107; + } +} + +void GSC_AceCombat4(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && fi.FBP == 0x02a00 && fi.FPSM == PSMT24Z && fi.TBP0 == 0x01600 && fi.TPSM == PSMT24Z) + skip = 71; // clouds (z, 16-bit) + else if(fi.TME && fi.FBP == 0x02900 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x00000 && fi.TPSM == PSMCT24) + skip = 28; // blur + } +} + +void GSC_Drakengard2(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && fi.FBP == 0x026c0 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x00a00 && fi.TPSM == PSMCT32) + skip = 64; + } +} + +void GSC_Tekken5(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && fi.FBP == 0x02ea0 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x00000 && fi.TPSM == PSMCT32) + skip = 95; + } +} + +void GSC_IkkiTousen(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && fi.FBP == 0x00a80 && fi.FPSM == PSMT24Z && fi.TBP0 == 0x01180 && fi.TPSM == PSMT24Z) + skip = 1000; // shadow (result is broken without depth copy, also includes 16 bit) + else if(fi.TME && fi.FBP == 0x00700 && fi.FPSM == PSMT24Z && fi.TBP0 == 0x01180 && fi.TPSM == PSMT24Z) + skip = 11; // blur + } + else if(skip > 7) + { + if(fi.TME && fi.FBP == 0x00700 && fi.FPSM == PSMCT16 && fi.TBP0 == 0x00700 && fi.TPSM == PSMCT16) + skip = 7; // the last steps of shadow drawing + } +} + +void GSC_GodOfWar(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && fi.FBP == 0x00000 && fi.FPSM == PSMCT16 && fi.TBP0 == 0x00000 && fi.TPSM == PSMCT16) + { + // skip = 30; //GSdx + skip = 4; // 23 or 4 need more testing + } + else if(fi.TME && fi.FBP == 0x00000 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x00000 && fi.TPSM == PSMCT32 && fi.FBMSK == 0xff000000) + skip = 1; // blur + else if(fi.FBP == 0x00000 && fi.FPSM == PSMCT32 && fi.TPSM == PSMT8 + && ((fi.TZTST == 2 && fi.FBMSK == 0x00FFFFFF) || (fi.TZTST == 1 && fi.FBMSK == 0x00FFFFFF) || (fi.TZTST == 3 && fi.FBMSK == 0xFF000000))) + skip = 1; // wall of fog + } +} + +void GSC_GodOfWar2(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME) + { + if((fi.FBP == 0x00100 && fi.FPSM == PSMCT16 && fi.TBP0 == 0x00100 && fi.TPSM == PSMCT16) // ntsc + || (fi.FBP == 0x02100 && fi.FPSM == PSMCT16 && fi.TBP0 == 0x02100 && fi.TPSM == PSMCT16)) // pal + skip = 29; // shadows + if(fi.FBP == 0x00100 && fi.FPSM == PSMCT32 && (fi.TBP0 & 0x03000) == 0x03000 + && (fi.TPSM == PSMT8 || fi.TPSM == PSMT4) + && ((fi.TZTST == 2 && fi.FBMSK == 0x00FFFFFF) || (fi.TZTST == 1 && fi.FBMSK == 0x00FFFFFF) || (fi.TZTST == 3 && fi.FBMSK == 0xFF000000))) + skip = 1; // wall of fog + } + } +} + +void GSC_GiTS(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && fi.FBP == 0x01400 && fi.FPSM == PSMCT16 && fi.TBP0 == 0x02e40 && fi.TPSM == PSMCT16) + skip = 1315; + } +} + +void GSC_Onimusha3(const GSFrameInfo& fi, int& skip) +{ + if(fi.TME /*&& (fi.FBP == 0x00000 || fi.FBP == 0x00700)*/ && (fi.TBP0 == 0x01180 || fi.TBP0 == 0x00e00 || fi.TBP0 == 0x01000 || fi.TBP0 == 0x01200) && (fi.TPSM == PSMCT32 || fi.TPSM == PSMCT24)) + skip = 1; +} + +void GSC_TalesOfAbyss(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x00e00) && fi.TBP0 == 0x01c00 && fi.TPSM == PSMT8) // copies the z buffer to the alpha channel of the fb + skip = 1000; + else if(fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x00e00) && (fi.TBP0 == 0x03560 || fi.TBP0 == 0x038e0) && fi.TPSM == PSMCT32) + skip = 1; + } + else + { + if(fi.TME && fi.TPSM != PSMT8) + skip = 0; + } +} + +void GSC_SonicUnleashed(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && fi.FBP == 0x02200 && fi.FPSM == PSMCT16S && fi.TBP0 == 0x00000 && fi.TPSM == PSMCT16) + skip = 1000; // shadow + } + else + { + if(fi.TME && fi.FBP == 0x00000 && fi.FPSM == PSMCT16 && fi.TBP0 == 0x02200 && fi.TPSM == PSMCT16S) + skip = 2; + } +} + +void GSC_Genji(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && fi.FBP == 0x01500 && fi.FPSM == PSMCT16 && fi.TBP0 == 0x00e00 && fi.TPSM == PSMT16Z) + skip = 6; // + } +} + +void GSC_StarOcean3(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && fi.FBP == fi.TBP0 && fi.FPSM == PSMCT32 && fi.TPSM == PSMT4HH) + skip = 1000; // + } + else + { + if(!(fi.TME && fi.FBP == fi.TBP0 && fi.FPSM == PSMCT32 && fi.TPSM == PSMT4HH)) + skip = 0; + } +} + +void GSC_ValkyrieProfile2(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && fi.FBP == fi.TBP0 && fi.FPSM == PSMCT32 && fi.TPSM == PSMT4HH) + skip = 1000; // + } + else + { + if(!(fi.TME && fi.FBP == fi.TBP0 && fi.FPSM == PSMCT32 && fi.TPSM == PSMT4HH)) + skip = 0; + } +} + +void GSC_RadiataStories(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && fi.FBP == fi.TBP0 && fi.FPSM == PSMCT32 && fi.TPSM == PSMT4HH) + skip = 1000; // Shadows + else if (fi.TME && fi.FBP == fi.TBP0 && (fi.TBP0 == 0x3700 || fi.TBP0 == 0x3400) && fi.TZTST == 1) + skip = 1; // Start manu issue; + } + else + { + if(!(fi.TME && fi.FBP == fi.TBP0 && fi.FPSM == PSMCT32 && fi.TPSM == PSMT4HH)) + skip = 0; + } +} + +bool GSC_HauntingGround(const GSFrameInfo& fi, int& skip) +{ + // Note GSdx seems to use invert somewhere FBMSK. So values were inverted + if(skip == 0) + { + if(fi.TME && fi.FPSM == fi.TPSM && fi.TPSM == PSMCT16S && fi.FBMSK == ~(0x03FFF)) + skip = 1; + else if(fi.TME && fi.FBP == 0x3000 && fi.TBP0 == 0x3380) + skip = 1; // bloom + else if(fi.TME && fi.FBP == fi.TBP0 && fi.TBP0 == 0x3000 && fi.FBMSK == ~(0xFFFFFF) && + GABEST_HAS_SHARED_BITS(fi.FBP, fi.FPSM, fi.TBP0, fi.TPSM)) + skip = 1; + } + + return true; +} + +// Record skipped frame to allow better analysis +// #define FRAME_RECORDING_ON 1 +#ifdef FRAME_RECORDING_ON +static const u32 MAX_FRAMES = 500; +static GSFrameInfo FrameAppear[MAX_FRAMES]; +static u32 Rec_Numbers = 0; + +void RecordNewFrames(VB& curvb, GSFrameInfo fi) { + if (Rec_Numbers >= MAX_FRAMES) + return; + + u32 i; + bool was_recorded = false; + for (i = 0; i < Rec_Numbers; i++ ) { + if (FrameAppear[i].FBP == fi.FBP && FrameAppear[i].FPSM == fi.FPSM + && FrameAppear[i].TBP0 == fi.TBP0 && FrameAppear[i].TPSM == fi.TPSM) { + was_recorded = true; + break; + } + } + if (!was_recorded) { + FrameAppear[Rec_Numbers] = fi; + Rec_Numbers++; + ZZLog::Print( "New frame %d, skip %d | fpb: %x fpsm: %d fpmsk: %x tme: %x tbp0: %x tpsm: %d tztst: %x | bits %d\n", \ + Rec_Numbers, g_SkipFlushFrame, fi.FBP, fi.FPSM, fi.FBMSK, fi.TME, fi.TBP0, fi.TPSM, fi.TZTST, GABEST_HAS_SHARED_BITS(fi.FBP, fi.FPSM, fi.TBP0, fi.TPSM) ); + + // Dump a nice picture of the frame + char filename[255]; + sprintf(filename, "SkipFlushFrame_%d__%d.tga", g_SkipFlushFrame, Rec_Numbers); + SaveRenderTarget(filename, curvb.prndr->fbw, curvb.prndr->fbh, 0); + } +} +#endif + +__forceinline bool IsBadFrame(VB& curvb) +{ + GSFrameInfo fi; + + // Keep GSdx naming convention to ease sharing code + fi.FBP = curvb.frame.fbp; + fi.FPSM = curvb.frame.psm; + fi.FBMSK = ~curvb.frame.fbm; + fi.TME = curvb.curprim.tme; + fi.TBP0 = curvb.tex0.tbp0; + fi.TPSM = curvb.tex0.psm; + fi.TZTST = curvb.test.ztst; + + if (GetSkipCount_Handler && conf.settings().automatic_skip_draw) + GetSkipCount_Handler(fi, g_SkipFlushFrame); + + if(g_SkipFlushFrame == 0 && (conf.SkipDraw > 0)) + { + if(fi.TME) + { + // depth textures (bully, mgs3s1 intro, Front Mission 5) + // Or General, often problematic post processing + if (PSMT_ISZTEX(fi.TPSM) || (GABEST_HAS_SHARED_BITS(fi.FBP, fi.FPSM, fi.TBP0, fi.TPSM))) + g_SkipFlushFrame = conf.SkipDraw; + } + } + + if(g_SkipFlushFrame > 0) + { +#ifdef FRAME_RECORDING_ON + RecordNewFrames(curvb, fi); +#endif + g_SkipFlushFrame--; + return true; + } + + return false; +} diff --git a/plugins/zzogl-pg-cg/opengl/ZZoglFlushHack.h b/plugins/zzogl-pg-cg/opengl/ZZoglFlushHack.h new file mode 100644 index 000000000..ef501296c --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZZoglFlushHack.h @@ -0,0 +1,84 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2010 gregory.hainaut@gmail.com + * Based on GSdx Copyright (C) 2007-2009 Gabest + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* This file is a collection of hack for removing the blur effect on some games + * The blur renders very badly on high screen flat panel. + * + * To avoid severals combo-box, the hack detects the game based on crc + */ + +#ifndef ZZOGL_FLUSH_HACK_H_INCLUDED +#define ZZOGL_FLUSH_HACK_H_INCLUDED + +#include "GS.h" +#include "targets.h" +#include "ZZoglVB.h" + +extern int g_SkipFlushFrame; + +struct GSFrameInfo +{ + u32 FBP; + u32 FPSM; + u32 FBMSK; + u32 TBP0; + u32 TPSM; + u32 TZTST; + bool TME; +}; + +typedef void (*GetSkipCount)(const GSFrameInfo& fi, int& skip); + +extern GetSkipCount GetSkipCount_Handler; + +void GSC_Okami(const GSFrameInfo& fi, int& skip); +void GSC_MetalGearSolid3(const GSFrameInfo& fi, int& skip); +void GSC_DBZBT2(const GSFrameInfo& fi, int& skip); +void GSC_DBZBT3(const GSFrameInfo& fi, int& skip); +void GSC_SFEX3(const GSFrameInfo& fi, int& skip); +void GSC_Bully(const GSFrameInfo& fi, int& skip); +void GSC_BullyCC(const GSFrameInfo& fi, int& skip); +void GSC_SoTC(const GSFrameInfo& fi, int& skip); +void GSC_OnePieceGrandAdventure(const GSFrameInfo& fi, int& skip); +void GSC_OnePieceGrandBattle(const GSFrameInfo& fi, int& skip); +void GSC_ICO(const GSFrameInfo& fi, int& skip); +void GSC_GT4(const GSFrameInfo& fi, int& skip); +void GSC_WildArms4(const GSFrameInfo& fi, int& skip); +void GSC_WildArms5(const GSFrameInfo& fi, int& skip); +void GSC_Manhunt2(const GSFrameInfo& fi, int& skip); +void GSC_CrashBandicootWoC(const GSFrameInfo& fi, int& skip); +void GSC_ResidentEvil4(const GSFrameInfo& fi, int& skip); +void GSC_Spartan(const GSFrameInfo& fi, int& skip); +void GSC_AceCombat4(const GSFrameInfo& fi, int& skip); +void GSC_Drakengard2(const GSFrameInfo& fi, int& skip); +void GSC_Tekken5(const GSFrameInfo& fi, int& skip); +void GSC_IkkiTousen(const GSFrameInfo& fi, int& skip); +void GSC_GodOfWar(const GSFrameInfo& fi, int& skip); +void GSC_GodOfWar2(const GSFrameInfo& fi, int& skip); +void GSC_GiTS(const GSFrameInfo& fi, int& skip); +void GSC_Onimusha3(const GSFrameInfo& fi, int& skip); +void GSC_TalesOfAbyss(const GSFrameInfo& fi, int& skip); +void GSC_SonicUnleashed(const GSFrameInfo& fi, int& skip); +void GSC_Genji(const GSFrameInfo& fi, int& skip); +void GSC_StarOcean3(const GSFrameInfo& fi, int& skip); +void GSC_ValkyrieProfile2(const GSFrameInfo& fi, int& skip); +void GSC_RadiataStories(const GSFrameInfo& fi, int& skip); + +extern bool IsBadFrame(VB& curvb); +#endif diff --git a/plugins/zzogl-pg-cg/opengl/ZZoglMath.h b/plugins/zzogl-pg-cg/opengl/ZZoglMath.h new file mode 100644 index 000000000..2e31aebb9 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZZoglMath.h @@ -0,0 +1,511 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef ZZOGLMATH_H_INCLUDED +#define ZZOGLMATH_H_INCLUDED + +//Remind me to check and see if this is necessary, and what uses it. --arcum42 +#ifndef _WIN32 +#include +#endif + +#include +#include "Pcsx2Defs.h" + +//#define ZZ_MMATH + +#ifndef ZZ_MMATH + +template +class Vector4 +{ + public: + T x, y, z, w; + + Vector4(T x1 = 0, T y1 = 0, T z1 = 0, T w1 = 0) + { + x = x1; + y = y1; + z = z1; + w = w1; + } + + Vector4(Vector4 &f) + { + x = f.x; + y = f.y; + z = f.z; + w = f.w; + } + + Vector4(T* f) + { + x = f[0]; + y = f[1]; + z = f[2]; + w = f[3]; // For some reason, the old code set this to 0. + } + + T& operator[](int i) + { + switch(i) + { + case 0: return x; + case 1: return y; + case 2: return z; + case 3: return w; + default: assert(0); + } + } + + operator T*() + { + return (T*) this; + } + + operator const T*() const + { + return (const T*) this; + } + + Vector4& operator =(const Vector4& v) + { + x = v.x; + y = v.y; + z = v.z; + w = v.w; + return *this; + } + + bool operator ==(const Vector4& v) + { + return !!( x == v.x && + y == v.y && + z == v.z && + w == v.w ); + } + + Vector4 operator +(const Vector4& v) const + { + return Vector4(x + v.x, y + v.y, z + v.z, w + v.w); + } + + Vector4 operator -(const Vector4& v) const + { + return Vector4(x - v.x, y - v.y, z - v.z, w - v.w); + } + + Vector4 operator *(const Vector4& v) const + { + return Vector4(x * v.x, y * v.y, z * v.z, w * v.w); + } + + Vector4 operator /(const Vector4& v) const + { + return Vector4(x / v.x, y / v.y, z / v.z, w / v.w); + } + Vector4 operator +(T val) const + { + return Vector4(x + val, y + val, z + val, w + val); + } + + Vector4 operator -(T val) const + { + return Vector4(x - val, y - val, z - val, w - val); + } + + Vector4 operator *(T val) const + { + return Vector4(x * val, y * val, z * val, w * val); + } + + Vector4 operator /(T val) const + { + return Vector4(x / val, y / val, z / val, w / val); + } + + Vector4& operator +=(const Vector4& v) + { + *this = *this + v; + return *this; + } + + Vector4& operator -=(const Vector4& v) + { + *this = *this - v; + return *this; + } + + Vector4& operator *=(const Vector4& v) + { + *this = *this * v; + return *this; + } + + Vector4& operator /=(const Vector4& v) + { + *this = *this - v; + return *this; + } + + Vector4& operator +=(T val) + { + *this = *this + (T)val; + return *this; + } + + Vector4& operator -=(T val) + { + *this = *this - (T)val; + return *this; + } + + Vector4& operator *=(T val) + { + *this = *this * (T)val; + return *this; + } + + Vector4& operator /=(T val) + { + *this = *this / (T)val; + return *this; + } + + // Probably doesn't belong here, but I'll leave it in for the moment. + void SetColor(u32 color) + { + x = (color & 0xff) / 255.0f; + y = ((color >> 8) & 0xff) / 255.0f; + z = ((color >> 16) & 0xff) / 255.0f; + } + + bool equal_vectors(const Vector4& v) + { + if (abs(x - v.x) + abs(y - v.y) + abs(z - v.z) + abs(w - v.w) < 0.01) + return true; + else + return false; + } + +}; + +typedef Vector4 float4; + +#else + +// Reimplement, swiping a bunch of code from GSdx and adapting it. (specifically GSVector.h) +// This doesn't include more then half of the functions in there, as well as some of the structs... +#include + +#include "Pcsx2Types.h" + +class float4 +{ + public: + union + { + struct {float x, y, z, w;}; + struct {float r, g, b, a;}; + struct {float left, top, right, bottom;}; + float v[4]; + float f32[4]; + s8 _s8[16]; + s16 _s16[8]; + s32 _s32[4]; + s64 _s64[2]; + u8 _u8[16]; + u16 _u16[8]; + u32 _u32[4]; + u64 _u64[2]; + __m128 m; + }; + + float4() + { + m = _mm_setzero_ps(); + } + + float4(float x, float y, float z, float w = 0) + { + m = _mm_set_ps(w, z, y, x); + } + + float4(float4 &f) + { + m = f.m; + } + + float4(float x, float y) + { + m = _mm_unpacklo_ps(_mm_load_ss(&x), _mm_load_ss(&y)); + } + + float4(int x, int y) + { + m = _mm_cvtepi32_ps(_mm_unpacklo_epi32(_mm_cvtsi32_si128(x), _mm_cvtsi32_si128(y))); + } + + explicit float4(float f) + { + m = _mm_set1_ps(f); + } + + explicit float4(__m128 m) + { + this->m = m; + } + + float4(float* f) + { + x = f[0]; + y = f[1]; + z = f[2]; + w = f[3]; // For some reason, the old code set this to 0. + } + + float& operator[](int i) + { + switch(i) + { + case 0: return x; + case 1: return y; + case 2: return z; + case 3: return w; + default: assert(0); + } + } + + operator float*() + { + return (float*) this; + } + + operator const float*() const + { + return (const float*) this; + } + + void operator = (float f) + { + m = _mm_set1_ps(f); + } + + void operator = (__m128 m) + { + this->m = m; + } + + + void operator += (const float4& v) + { + m = _mm_add_ps(m, v.m); + } + + void operator -= (const float4& v) + { + m = _mm_sub_ps(m, v.m); + } + + void operator *= (const float4& v) + { + m = _mm_mul_ps(m, v.m); + } + + void operator /= (const float4& v) + { + m = _mm_div_ps(m, v.m); + } + + void operator += (float f) + { + *this += float4(f); + } + + void operator -= (float f) + { + *this -= float4(f); + } + + void operator *= (float f) + { + *this *= float4(f); + } + + void operator /= (float f) + { + *this /= float4(f); + } + + void operator &= (const float4& v) + { + m = _mm_and_ps(m, v.m); + } + + void operator |= (const float4& v) + { + m = _mm_or_ps(m, v.m); + } + + void operator ^= (const float4& v) + { + m = _mm_xor_ps(m, v.m); + } + + friend float4 operator + (const float4& v1, const float4& v2) + { + return float4(_mm_add_ps(v1.m, v2.m)); + } + + friend float4 operator - (const float4& v1, const float4& v2) + { + return float4(_mm_sub_ps(v1.m, v2.m)); + } + + friend float4 operator * (const float4& v1, const float4& v2) + { + return float4(_mm_mul_ps(v1.m, v2.m)); + } + + friend float4 operator / (const float4& v1, const float4& v2) + { + return float4(_mm_div_ps(v1.m, v2.m)); + } + + friend float4 operator + (const float4& v, float f) + { + return v + float4(f); + } + + friend float4 operator - (const float4& v, float f) + { + return v - float4(f); + } + + friend float4 operator * (const float4& v, float f) + { + return v * float4(f); + } + + friend float4 operator / (const float4& v, float f) + { + return v / float4(f); + } + + friend float4 operator & (const float4& v1, const float4& v2) + { + return float4(_mm_and_ps(v1.m, v2.m)); + } + + friend float4 operator | (const float4& v1, const float4& v2) + { + return float4(_mm_or_ps(v1.m, v2.m)); + } + + friend float4 operator ^ (const float4& v1, const float4& v2) + { + return float4(_mm_xor_ps(v1.m, v2.m)); + } + + friend float4 operator == (const float4& v1, const float4& v2) + { + return float4(_mm_cmpeq_ps(v1.m, v2.m)); + } + + friend float4 operator != (const float4& v1, const float4& v2) + { + return float4(_mm_cmpneq_ps(v1.m, v2.m)); + } + + friend float4 operator > (const float4& v1, const float4& v2) + { + return float4(_mm_cmpgt_ps(v1.m, v2.m)); + } + + friend float4 operator < (const float4& v1, const float4& v2) + { + return float4(_mm_cmplt_ps(v1.m, v2.m)); + } + + friend float4 operator >= (const float4& v1, const float4& v2) + { + return float4(_mm_cmpge_ps(v1.m, v2.m)); + } + + friend float4 operator <= (const float4& v1, const float4& v2) + { + return float4(_mm_cmple_ps(v1.m, v2.m)); + } + + bool equal_vectors(const float4& v) + { + if (abs(x - v.x) + abs(y - v.y) + abs(z - v.z) + abs(w - v.w) < 0.01) + return true; + else + return false; + } + + // This looked interesting, so I thought I'd include it... + + template float4 shuffle() const + { + return float4(_mm_shuffle_ps(m, m, _MM_SHUFFLE(i, i, i, i))); + } + + #define VECTOR4_SHUFFLE_4(xs, xn, ys, yn, zs, zn, ws, wn) \ + float4 xs##ys##zs##ws() const {return float4(_mm_shuffle_ps(m, m, _MM_SHUFFLE(wn, zn, yn, xn)));} \ + float4 xs##ys##zs##ws(const float4& v) const {return float4(_mm_shuffle_ps(m, v.m, _MM_SHUFFLE(wn, zn, yn, xn)));} \ + + #define VECTOR4_SHUFFLE_3(xs, xn, ys, yn, zs, zn) \ + VECTOR4_SHUFFLE_4(xs, xn, ys, yn, zs, zn, x, 0) \ + VECTOR4_SHUFFLE_4(xs, xn, ys, yn, zs, zn, y, 1) \ + VECTOR4_SHUFFLE_4(xs, xn, ys, yn, zs, zn, z, 2) \ + VECTOR4_SHUFFLE_4(xs, xn, ys, yn, zs, zn, w, 3) \ + + #define VECTOR4_SHUFFLE_2(xs, xn, ys, yn) \ + VECTOR4_SHUFFLE_3(xs, xn, ys, yn, x, 0) \ + VECTOR4_SHUFFLE_3(xs, xn, ys, yn, y, 1) \ + VECTOR4_SHUFFLE_3(xs, xn, ys, yn, z, 2) \ + VECTOR4_SHUFFLE_3(xs, xn, ys, yn, w, 3) \ + + #define VECTOR4_SHUFFLE_1(xs, xn) \ + float4 xs##4() const {return float4(_mm_shuffle_ps(m, m, _MM_SHUFFLE(xn, xn, xn, xn)));} \ + float4 xs##4(const float4& v) const {return float4(_mm_shuffle_ps(m, v.m, _MM_SHUFFLE(xn, xn, xn, xn)));} \ + VECTOR4_SHUFFLE_2(xs, xn, x, 0) \ + VECTOR4_SHUFFLE_2(xs, xn, y, 1) \ + VECTOR4_SHUFFLE_2(xs, xn, z, 2) \ + VECTOR4_SHUFFLE_2(xs, xn, w, 3) \ + + VECTOR4_SHUFFLE_1(x, 0) + VECTOR4_SHUFFLE_1(y, 1) + VECTOR4_SHUFFLE_1(z, 2) + VECTOR4_SHUFFLE_1(w, 3) + + // Probably doesn't belong here, but I'll leave it in for the moment. + void SetColor(u32 color) + { + x = (color & 0xff) / 255.0f; + y = ((color >> 8) & 0xff) / 255.0f; + z = ((color >> 16) & 0xff) / 255.0f; + } +}; + +#endif + +#endif diff --git a/plugins/zzogl-pg-cg/opengl/ZZoglSave.cpp b/plugins/zzogl-pg-cg/opengl/ZZoglSave.cpp new file mode 100644 index 000000000..b0e2ebc00 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZZoglSave.cpp @@ -0,0 +1,175 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +// Save and Load. + +//------------------ Includes + #include "Util.h" +#include "ZZoglVB.h" + +extern void ZZGSStateReset(); +//----------------------- Defines + +#define VBSAVELIMIT ((u32)((u8*)&vb[0].nNextFrameHeight-(u8*)&vb[0])) +#define ZEROGS_SAVEVER 0xaa000005 + +//------------------ Variables + +// Hack for save game compatible! +#ifdef _DEBUG +char *libraryNameX = "ZeroGS-Pg OpenGL (Debug) "; +#elif defined(ZEROGS_DEVBUILD) +char *libraryNameX = "ZeroGS-Pg OpenGL (Dev) "; +#else +char *libraryNameX = "ZeroGS Playground OpenGL "; +#endif + +//------------------ Code + +extern char *libraryName; +extern u32 s_uTex1Data[2][2], s_uClampData[2]; + +void SetFogColor(u32 fog); +void SetFogColor(GIFRegFOGCOL* fog); + +int ZZSave(s8* pbydata) +{ + if (pbydata == NULL) + return 40 + MEMORY_END + sizeof(gs) + 2*VBSAVELIMIT + 2*sizeof(frameInfo) + 4 + 256*4; + + s_RTs.ResolveAll(); + s_DepthRTs.ResolveAll(); + + strcpy((char*)pbydata, libraryNameX); + + *(u32*)(pbydata + 16) = ZEROGS_SAVEVER; + + pbydata += 32; + *(int*)pbydata = icurctx; + + pbydata += 4; + *(int*)pbydata = VBSAVELIMIT; + + pbydata += 4; + + memcpy(pbydata, g_pbyGSMemory, MEMORY_END); + pbydata += MEMORY_END; + + memcpy(pbydata, g_pbyGSClut, 256*4); + pbydata += 256 * 4; + + *(int*)pbydata = sizeof(gs); + pbydata += 4; + + memcpy(pbydata, &gs, sizeof(gs)); + pbydata += sizeof(gs); + + for (int i = 0; i < 2; ++i) + { + memcpy(pbydata, &vb[i], VBSAVELIMIT); + pbydata += VBSAVELIMIT; + } + + return 0; +} + +extern u32 s_uFramebuffer; +extern int g_nCurVBOIndex; + +bool ZZLoad(s8* pbydata) +{ + memset(s_uTex1Data, 0, sizeof(s_uTex1Data)); + memset(s_uClampData, 0, sizeof(s_uClampData)); + + g_nCurVBOIndex = 0; + + // first 32 bytes are the id + u32 savever = *(u32*)(pbydata + 16); + + if (strncmp((char*)pbydata, libraryNameX, 6) == 0 && (savever == ZEROGS_SAVEVER || savever == 0xaa000004)) + { + g_MemTargs.Destroy(); + + ZZGSStateReset(); + pbydata += 32; + + //int context = *(int*)pbydata; + pbydata += 4; + u32 savelimit = VBSAVELIMIT; + + savelimit = *(u32*)pbydata; + pbydata += 4; + + memcpy(g_pbyGSMemory, pbydata, MEMORY_END); + pbydata += MEMORY_END; + + memcpy(g_pbyGSClut, pbydata, 256*4); + pbydata += 256 * 4; + + memset(&gs, 0, sizeof(gs)); + + int savedgssize; + + if (savever == 0xaa000004) + { + savedgssize = 0x1d0; + } + else + { + savedgssize = *(int*)pbydata; + pbydata += 4; + } + + memcpy(&gs, pbydata, savedgssize); + + pbydata += savedgssize; + prim = &gs._prim[gs.prac]; + + vb[0].Destroy(); + memcpy(&vb[0], pbydata, min(savelimit, VBSAVELIMIT)); + pbydata += savelimit; + vb[0].pBufferData = NULL; + + vb[1].Destroy(); + memcpy(&vb[1], pbydata, min(savelimit, VBSAVELIMIT)); + pbydata += savelimit; + vb[1].pBufferData = NULL; + + for (int i = 0; i < 2; ++i) + { + vb[i].Init(VB_BUFFERSIZE); + vb[i].bNeedZCheck = vb[i].bNeedFrameCheck = 1; + + vb[i].bSyncVars = 0; + vb[i].bNeedTexCheck = 1; + memset(vb[i].uCurTex0Data, 0, sizeof(vb[i].uCurTex0Data)); + } + + icurctx = -1; + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, s_uFramebuffer); // switch to the backbuffer + SetFogColor(gs.fogcol); + + GL_REPORT_ERRORD(); + return true; + } + + return false; +} + diff --git a/plugins/zzogl-pg-cg/opengl/ZZoglShaders.cpp b/plugins/zzogl-pg-cg/opengl/ZZoglShaders.cpp new file mode 100644 index 000000000..dfe69c44e --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZZoglShaders.cpp @@ -0,0 +1,889 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009 zeydlitz@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +//#ifdef NVIDIA_CG_API // This code is only for NVIDIA cg-toolkit API +// ZZogl Shader manipulation functions. + +//------------------- Includes +#include "Util.h" +#include "ZZoglShaders.h" +#include "zpipe.h" +#include +#include + +#ifdef _WIN32 +# include "Win32.h" +extern HINSTANCE hInst; +#endif + +// ----------------- Defines + +#define TEXWRAP_REPEAT 0 +#define TEXWRAP_CLAMP 1 +#define TEXWRAP_REGION_REPEAT 2 +#define TEXWRAP_REPEAT_CLAMP 3 + +#define SH_WRITEDEPTH 0x2000 // depth is written +#define SH_CONTEXT1 0x1000 // context1 is used +#define SH_REGULARVS 0x8000 +#define SH_TEXTUREVS 0x8001 +#define SH_REGULARFOGVS 0x8002 +#define SH_TEXTUREFOGVS 0x8003 +#define SH_REGULARPS 0x8004 +#define SH_REGULARFOGPS 0x8005 +#define SH_BITBLTVS 0x8006 +#define SH_BITBLTPS 0x8007 +#define SH_BITBLTDEPTHPS 0x8009 +#define SH_CRTCTARGPS 0x800a +#define SH_CRTCPS 0x800b +#define SH_CRTC24PS 0x800c +#define SH_ZEROPS 0x800e +#define SH_BASETEXTUREPS 0x800f +#define SH_BITBLTAAPS 0x8010 +#define SH_CRTCTARGINTERPS 0x8012 +#define SH_CRTCINTERPS 0x8013 +#define SH_CRTC24INTERPS 0x8014 +#define SH_BITBLTDEPTHMRTPS 0x8016 +#define SH_CONVERT16TO32PS 0x8020 +#define SH_CONVERT32TO16PS 0x8021 +#define SH_CRTC_NEARESTPS 0x8022 +#define SH_CRTCINTER_NEARESTPS 0x8023 + +//------------------ Constants + +// Used in a logarithmic Z-test, as (1-o(1))/log(MAX_U32). +const float g_filog32 = 0.999f / (32.0f * logf(2.0f)); + +#ifdef _DEBUG +const static char* g_pTexTypes[] = { "32", "tex32", "clut32", "tex32to16", "tex16to8h" }; +#endif +const char* g_pShaders[4] = { "full", "reduced", "accurate", "accurate-reduced" }; + +// ----------------- Global Variables + +ZZshContext g_cgcontext; +ZZshProfile cgvProf, cgfProf; +int g_nPixelShaderVer = 0; // default +u8* s_lpShaderResources = NULL; +ZZshProgram pvs[16] = {NULL}; +ZZshProgram g_vsprog = 0, g_psprog = 0; // 2 -- ZZ +ZZshParameter g_vparamPosXY[2] = {0}, g_fparamFogColor = 0; + +#ifdef DEVBUILD +char* EFFECT_NAME; // All this variables used for testing and set manually +char* EFFECT_DIR; +#endif + +bool g_bCRTCBilinear = true; + +float4 g_vdepth, vlogz; +FRAGMENTSHADER ppsBitBlt[2], ppsBitBltDepth, ppsOne; +FRAGMENTSHADER ppsBaseTexture, ppsConvert16to32, ppsConvert32to16; +FRAGMENTSHADER ppsRegular[4], ppsTexture[NUM_SHADERS]; +FRAGMENTSHADER ppsCRTC[2], ppsCRTC24[2], ppsCRTCTarg[2]; +VERTEXSHADER pvsBitBlt; + +extern u32 ptexBlocks; // holds information on block tiling. It's texture number in OpenGL -- if 0 than such texture +extern u32 ptexConv16to32; // does not exists. This textures should be created on start and released on finish. +extern u32 ptexBilinearBlocks; +extern u32 ptexConv32to16; + +inline bool LoadEffects(); +extern bool s_bWriteDepth; + +struct SHADERHEADER +{ + unsigned int index, offset, size; // if highest bit of index is set, pixel shader +}; +map mapShaderResources; + +// Debug variable, store name of the function that call the shader. +const char* ShaderCallerName = ""; +const char* ShaderHandleName = ""; + +//------------------ Code + +inline int GET_SHADER_INDEX(int type, int texfilter, int texwrap, int fog, int writedepth, int testaem, int exactcolor, int context, int ps) { + return type + texfilter*NUM_TYPES + NUM_FILTERS*NUM_TYPES*texwrap + NUM_TEXWRAPS*NUM_FILTERS*NUM_TYPES*(fog+2*writedepth+4*testaem+8*exactcolor+16*context+32*ps) ; +} + +bool ZZshCheckProfilesSupport() { + // load the effect, find the best profiles (if any) + if (cgGLIsProfileSupported(CG_PROFILE_ARBVP1) != CG_TRUE) { + ZZLog::Error_Log("arbvp1 not supported."); + return false; + } + if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1) != CG_TRUE) { + ZZLog::Error_Log("arbfp1 not supported."); + return false; + } + return true; +} + +// Error handler. Setup in ZZogl_Create once. +void HandleCgError(ZZshContext ctx, ZZshError err, void* appdata) +{ + ZZLog::Error_Log("%s->%s: %s\n", ShaderCallerName, ShaderHandleName, cgGetErrorString(err)); + const char* listing = cgGetLastListing(g_cgcontext); + if (listing != NULL) + ZZLog::Debug_Log(" last listing: %s\n", listing); +} + +bool ZZshStartUsingShaders() { + cgSetErrorHandler(HandleCgError, NULL); + g_cgcontext = cgCreateContext(); + + cgvProf = CG_PROFILE_ARBVP1; + cgfProf = CG_PROFILE_ARBFP1; + cgGLEnableProfile(cgvProf); + cgGLEnableProfile(cgfProf); + cgGLSetOptimalOptions(cgvProf); + cgGLSetOptimalOptions(cgfProf); + + cgGLSetManageTextureParameters(g_cgcontext, CG_FALSE); + //cgSetAutoCompile(g_cgcontext, CG_COMPILE_IMMEDIATE); + + g_fparamFogColor = cgCreateParameter(g_cgcontext, CG_FLOAT4); + g_vparamPosXY[0] = cgCreateParameter(g_cgcontext, CG_FLOAT4); + g_vparamPosXY[1] = cgCreateParameter(g_cgcontext, CG_FLOAT4); + + + ZZLog::GS_Log("Creating effects."); + B_G(LoadEffects(), return false); + + // create a sample shader + clampInfo temp; + memset(&temp, 0, sizeof(temp)); + temp.wms = 3; temp.wmt = 3; + + g_nPixelShaderVer = 0;//SHADER_ACCURATE; + // test + bool bFailed; + FRAGMENTSHADER* pfrag = ZZshLoadShadeEffect(0, 1, 1, 1, 1, temp, 0, &bFailed); + if( bFailed || pfrag == NULL ) { + g_nPixelShaderVer = SHADER_ACCURATE|SHADER_REDUCED; + + pfrag = ZZshLoadShadeEffect(0, 0, 1, 1, 0, temp, 0, &bFailed); + if( pfrag != NULL ) + cgGLLoadProgram(pfrag->prog); + if( bFailed || pfrag == NULL || cgGetError() != CG_NO_ERROR ) { + g_nPixelShaderVer = SHADER_REDUCED; + ZZLog::Error_Log("Basic shader test failed."); + } + } + + if (g_nPixelShaderVer & SHADER_REDUCED) + conf.bilinear = 0; + + ZZLog::GS_Log("Creating extra effects."); + B_G(ZZshLoadExtraEffects(), return false); + + ZZLog::GS_Log("using %s shaders\n", g_pShaders[g_nPixelShaderVer]); + return true; +} + +// open shader file according to build target +bool ZZshCreateOpenShadersFile() { +#ifndef DEVBUILD +# ifdef _WIN32 + HRSRC hShaderSrc = FindResource(hInst, MAKEINTRESOURCE(IDR_SHADERS), RT_RCDATA); + assert( hShaderSrc != NULL ); + HGLOBAL hShaderGlob = LoadResource(hInst, hShaderSrc); + assert( hShaderGlob != NULL ); + s_lpShaderResources = (u8*)LockResource(hShaderGlob); +# else // not _WIN32 + FILE* fres = fopen("ps2hw.dat", "rb"); + if( fres == NULL ) { + fres = fopen("plugins/ps2hw.dat", "rb"); + if( fres == NULL ) { + ZZLog::Error_Log("Cannot find ps2hw.dat in working directory. Exiting."); + return false; + } + } + fseek(fres, 0, SEEK_END); + size_t s = ftell(fres); + s_lpShaderResources = new u8[s+1]; + fseek(fres, 0, SEEK_SET); + fread(s_lpShaderResources, s, 1, fres); + s_lpShaderResources[s] = 0; +# endif // _WIN32 +#else // NOT RELEASE_TO_PUBLIC +# ifndef _WIN32 // NOT WINDOWS + // test if ps2hw.fx exists + char tempstr[255]; + char curwd[255]; + getcwd(curwd, ArraySize(curwd)); + + strcpy(tempstr, "/plugins/"); + sprintf(EFFECT_NAME, "%sps2hw.fx", tempstr); + FILE* f = fopen(EFFECT_NAME, "r"); + if( f == NULL ) { + + strcpy(tempstr, "../../plugins/zzogl-pg/opengl/"); + sprintf(EFFECT_NAME, "%sps2hw.fx", tempstr); + f = fopen(EFFECT_NAME, "r"); + + if( f == NULL ) { + ZZLog::Error_Log("Failed to find %s, try compiling a non-devbuild\n", EFFECT_NAME); + return false; + } + } + fclose(f); + + sprintf(EFFECT_DIR, "%s/%s", curwd, tempstr); + sprintf(EFFECT_NAME, "%sps2hw.fx", EFFECT_DIR); + #endif +#endif // RELEASE_TO_PUBLIC + return true; +} + +// Disable CG +void ZZshGLDisableProfile() { + cgGLDisableProfile(cgvProf); + cgGLDisableProfile(cgfProf); +} +//Enable CG +void ZZshGLEnableProfile() { + cgGLEnableProfile(cgvProf); + cgGLEnableProfile(cgfProf); +} + +// This is helper of cgGLSetParameter4fv, made for debug purpose. +// Name could be any string. We must use it on compilation time, because erroneus handler does not +// return name +void ZZshSetParameter4fv(ZZshParameter param, const float* v, const char* name) { + ShaderHandleName = name; + cgGLSetParameter4fv(param, v); +} + +void ZZshSetParameter4fv(ZZshProgram prog, ZZshParameter param, const float* v, const char* name) { + ShaderHandleName = name; + cgGLSetParameter4fv(param, v); +} + +// The same stuff, but also with retry of param, name should be USED name of param for prog. +void ZZshSetParameter4fvWithRetry(ZZshParameter* param, ZZshProgram prog, const float* v, const char* name) { + if (param != NULL) + ZZshSetParameter4fv(prog, param[0], v, name); + else + ZZshSetParameter4fv(prog, cgGetNamedParameter(prog, name), v, name); +} + +void ZZshGLSetTextureParameter(ZZshParameter param, GLuint texobj, const char* name) { + ShaderHandleName = name; + cgGLSetTextureParameter(param, texobj); + cgGLEnableTextureParameter(param); +} + +// The same function for texture, also to cgGLEnable +void ZZshGLSetTextureParameter(ZZshProgram prog, ZZshParameter param, GLuint texobj, const char* name) { + ShaderHandleName = name; + cgGLSetTextureParameter(param, texobj); + cgGLEnableTextureParameter(param); +} + +// Used sometimes for color 1. +void ZZshDefaultOneColor( FRAGMENTSHADER ptr ) { + ShaderHandleName = "Set Default One color"; + float4 v = float4 ( 1, 1, 1, 1 ); + ZZshSetParameter4fv( ptr.prog, ptr.sOneColor, v, "DefaultOne"); +} + +#define SET_UNIFORMPARAM(var, name) { \ + p = cgGetNamedParameter(pf->prog, name); \ + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) \ + pf->var = p; \ +} \ + +void ZZshSetVertexShader(ZZshProgram prog) { + if ((prog) != g_vsprog) { + cgGLBindProgram(prog); + g_vsprog = prog; + } +} + +void ZZshSetPixelShader(ZZshProgram prog) { + if ((prog) != g_psprog) { + cgGLBindProgram(prog); + g_psprog = prog; + } +} + +void SetupFragmentProgramParameters(FRAGMENTSHADER* pf, int context, int type) +{ + // uniform parameters + ZZshParameter p; + + p = cgGetNamedParameter(pf->prog, "g_fFogColor"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + cgConnectParameter(g_fparamFogColor, p); + } + + SET_UNIFORMPARAM(sOneColor, "g_fOneColor"); + SET_UNIFORMPARAM(sBitBltZ, "g_fBitBltZ"); + SET_UNIFORMPARAM(sInvTexDims, "g_fInvTexDims"); + SET_UNIFORMPARAM(fTexAlpha2, "fTexAlpha2"); + SET_UNIFORMPARAM(fTexOffset, "g_fTexOffset"); + SET_UNIFORMPARAM(fTexDims, "g_fTexDims"); + SET_UNIFORMPARAM(fTexBlock, "g_fTexBlock"); + SET_UNIFORMPARAM(fClampExts, "g_fClampExts"); + SET_UNIFORMPARAM(fTexWrapMode, "TexWrapMode"); + SET_UNIFORMPARAM(fRealTexDims, "g_fRealTexDims"); + SET_UNIFORMPARAM(fTestBlack, "g_fTestBlack"); + SET_UNIFORMPARAM(fPageOffset, "g_fPageOffset"); + SET_UNIFORMPARAM(fTexAlpha, "fTexAlpha"); + + // textures + p = cgGetNamedParameter(pf->prog, "g_sBlocks"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + cgGLSetTextureParameter(p, ptexBlocks); + cgGLEnableTextureParameter(p); + } + + // cg parameter usage is wrong, so do it manually + if( type == 3 ) { + p = cgGetNamedParameter(pf->prog, "g_sConv16to32"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + cgGLSetTextureParameter(p, ptexConv16to32); + cgGLEnableTextureParameter(p); + } + } + else if( type == 4 ) { + p = cgGetNamedParameter(pf->prog, "g_sConv32to16"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + cgGLSetTextureParameter(p, ptexConv32to16); + cgGLEnableTextureParameter(p); + } + } + else { + p = cgGetNamedParameter(pf->prog, "g_sBilinearBlocks"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + cgGLSetTextureParameter(p, ptexBilinearBlocks); + cgGLEnableTextureParameter(p); + } + } + + p = cgGetNamedParameter(pf->prog, "g_sMemory"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + //cgGLEnableTextureParameter(p); + pf->sMemory = p; + } + p = cgGetNamedParameter(pf->prog, "g_sSrcFinal"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + //cgGLEnableTextureParameter(p); + pf->sFinal = p; + } + p = cgGetNamedParameter(pf->prog, "g_sBitwiseANDX"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + //cgGLEnableTextureParameter(p); + pf->sBitwiseANDX = p; + } + p = cgGetNamedParameter(pf->prog, "g_sBitwiseANDY"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + //cgGLEnableTextureParameter(p); + pf->sBitwiseANDY = p; + } + p = cgGetNamedParameter(pf->prog, "g_sCLUT"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + //cgGLEnableTextureParameter(p); + pf->sCLUT = p; + } + p = cgGetNamedParameter(pf->prog, "g_sInterlace"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + //cgGLEnableTextureParameter(p); + pf->sInterlace = p; + } + + // set global shader constants + p = cgGetNamedParameter(pf->prog, "g_fExactColor"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + cgGLSetParameter4fv(p, float4(0.5f, (conf.settings().exact_color)?0.9f/256.0f:0.5f/256.0f, 0,1/255.0f)); + } + + p = cgGetNamedParameter(pf->prog, "g_fBilinear"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) + cgGLSetParameter4fv(p, float4(-0.2f, -0.65f, 0.9f, 1.0f / 32767.0f )); + + p = cgGetNamedParameter(pf->prog, "g_fZBias"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) + cgGLSetParameter4fv(p, float4(1.0f/256.0f, 1.0004f, 1, 0.5f)); + + p = cgGetNamedParameter(pf->prog, "g_fc0"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) + cgGLSetParameter4fv(p, float4(0,1, 0.001f, 0.5f)); + + p = cgGetNamedParameter(pf->prog, "g_fMult"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) + cgGLSetParameter4fv(p, float4(1/1024.0f, 0.2f/1024.0f, 1/128.0f, 1/512.0f)); +} + +void SetupVertexProgramParameters(ZZshProgram prog, int context) +{ + ZZshParameter p; + + p = cgGetNamedParameter(prog, "g_fPosXY"); + if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE ) + cgConnectParameter(g_vparamPosXY[context], p); + + // Set Z-test, log or no log; + if (conf.settings().no_logz) { + g_vdepth = float4( 255.0 /256.0f, 255.0/65536.0f, 255.0f/(65535.0f*256.0f), 1.0f/(65536.0f*65536.0f)); + vlogz = float4( 1.0f, 0.0f, 0.0f, 0.0f); + } + else { + g_vdepth = float4( 256.0f*65536.0f, 65536.0f, 256.0f, 65536.0f*65536.0f); + vlogz = float4( 0.0f, 1.0f, 0.0f, 0.0f); + } + + p = cgGetNamedParameter(prog, "g_fZ"); + if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE ) { + cgGLSetParameter4fv(p, g_vdepth); + + p = cgGetNamedParameter(prog, "g_fZMin"); // Switch to flat-z when needed + if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE ) { + //ZZLog::Error_Log("Use flat-z\n"); + cgGLSetParameter4fv(p, vlogz); + } + else + ZZLog::Error_Log("Shader file version is outdated! Only log-Z is possible."); + } + + float4 vnorm = float4(g_filog32, 0, 0,0); + p = cgGetNamedParameter(prog, "g_fZNorm"); + if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE ) + cgGLSetParameter4fv(p, vnorm); + + p = cgGetNamedParameter(prog, "g_fBilinear"); + if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE ) + cgGLSetParameter4fv(p, float4(-0.2f, -0.65f, 0.9f, 1.0f / 32767.0f )); + + p = cgGetNamedParameter(prog, "g_fZBias"); + if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE ) + cgGLSetParameter4fv(p, float4(1.0f/256.0f, 1.0004f, 1, 0.5f)); + + p = cgGetNamedParameter(prog, "g_fc0"); + if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE ) + cgGLSetParameter4fv(p, float4(0,1, 0.001f, 0.5f)); +} + +#ifndef DEVBUILD + +#define LOAD_VS(Index, prog) { \ + assert( mapShaderResources.find(Index) != mapShaderResources.end() ); \ + header = mapShaderResources[Index]; \ + assert( (header) != NULL && (header)->index == (Index) ); \ + prog = cgCreateProgram(g_cgcontext, CG_OBJECT, (char*)(s_lpShaderResources + (header)->offset), cgvProf, NULL, NULL); \ + if( !cgIsProgram(prog) ) { \ + ZZLog::Error_Log("Failed to load vs %d: \n%s", Index, cgGetLastListing(g_cgcontext)); \ + return false; \ + } \ + cgGLLoadProgram(prog); \ + if( cgGetError() != CG_NO_ERROR ) ZZLog::Error_Log("Failed to load program %d.", Index); \ + SetupVertexProgramParameters(prog, !!(Index&SH_CONTEXT1)); \ +} \ + +#define LOAD_PS(Index, fragment) { \ + bLoadSuccess = true; \ + assert( mapShaderResources.find(Index) != mapShaderResources.end() ); \ + header = mapShaderResources[Index]; \ + fragment.prog = cgCreateProgram(g_cgcontext, CG_OBJECT, (char*)(s_lpShaderResources + (header)->offset), cgfProf, NULL, NULL); \ + if( !cgIsProgram(fragment.prog) ) { \ + ZZLog::Error_Log("Failed to load ps %d: \n%s", Index, cgGetLastListing(g_cgcontext)); \ + return false; \ + } \ + cgGLLoadProgram(fragment.prog); \ + if( cgGetError() != CG_NO_ERROR ) { \ + ZZLog::Error_Log("failed to load program %d.", Index); \ + bLoadSuccess = false; \ + } \ + SetupFragmentProgramParameters(&fragment, !!(Index&SH_CONTEXT1), 0); \ +} \ + +inline bool LoadEffects() +{ + assert( s_lpShaderResources != NULL ); + + // process the header + u32 num = *(u32*)s_lpShaderResources; + int compressed_size = *(int*)(s_lpShaderResources+4); + int real_size = *(int*)(s_lpShaderResources+8); + int out; + + char* pbuffer = (char*)malloc(real_size); + inf((char*)s_lpShaderResources+12, &pbuffer[0], compressed_size, real_size, &out); + assert(out == real_size); + + s_lpShaderResources = (u8*)pbuffer; + SHADERHEADER* header = (SHADERHEADER*)s_lpShaderResources; + + mapShaderResources.clear(); + while(num-- > 0 ) { + mapShaderResources[header->index] = header; + ++header; + } + + // clear the textures + for(u16 i = 0; i < ArraySize(ppsTexture); ++i) { + SAFE_RELEASE_PROG(ppsTexture[i].prog); + ppsTexture[i].prog = NULL; + } +#ifndef _DEBUG + memset(ppsTexture, 0, sizeof(ppsTexture)); +#endif + + return true; +} + +// called +bool ZZshLoadExtraEffects() +{ + SHADERHEADER* header; + bool bLoadSuccess = true; + + const int vsshaders[4] = { SH_REGULARVS, SH_TEXTUREVS, SH_REGULARFOGVS, SH_TEXTUREFOGVS }; + + for(int i = 0; i < 4; ++i) { + LOAD_VS(vsshaders[i], pvs[2*i]); + LOAD_VS((vsshaders[i] | SH_CONTEXT1), pvs[2*i+1]); + //if( conf.mrtdepth ) { + LOAD_VS((vsshaders[i] | SH_WRITEDEPTH), pvs[2*i+8]); + LOAD_VS((vsshaders[i] | SH_WRITEDEPTH | SH_CONTEXT1), pvs[2*i+8+1]); +// } +// else { +// pvs[2*i+8] = pvs[2*i+8+1] = NULL; +// } + } + + LOAD_VS(SH_BITBLTVS, pvsBitBlt.prog); + pvsBitBlt.sBitBltPos = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltPos"); + pvsBitBlt.sBitBltTex = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltTex"); + pvsBitBlt.fBitBltTrans = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltTrans"); + + LOAD_PS(SH_REGULARPS, ppsRegular[0]); + LOAD_PS(SH_REGULARFOGPS, ppsRegular[1]); + + if( conf.mrtdepth ) { + LOAD_PS(SH_REGULARPS, ppsRegular[2]); + if( !bLoadSuccess ) + conf.mrtdepth = 0; + LOAD_PS(SH_REGULARFOGPS, ppsRegular[3]); + if( !bLoadSuccess ) + conf.mrtdepth = 0; + } + + LOAD_PS(SH_BITBLTPS, ppsBitBlt[0]); + LOAD_PS(SH_BITBLTAAPS, ppsBitBlt[1]); + if( !bLoadSuccess ) { + ZZLog::Error_Log("Failed to load BitBltAAPS, using BitBltPS."); + LOAD_PS(SH_BITBLTPS, ppsBitBlt[1]); + } + LOAD_PS(SH_BITBLTDEPTHPS, ppsBitBltDepth); + LOAD_PS(SH_CRTCTARGPS, ppsCRTCTarg[0]); + LOAD_PS(SH_CRTCTARGINTERPS, ppsCRTCTarg[1]); + + g_bCRTCBilinear = true; + LOAD_PS(SH_CRTCPS, ppsCRTC[0]); + if( !bLoadSuccess ) { + // switch to simpler + g_bCRTCBilinear = false; + LOAD_PS(SH_CRTC_NEARESTPS, ppsCRTC[0]); + LOAD_PS(SH_CRTCINTER_NEARESTPS, ppsCRTC[0]); + } + else { + LOAD_PS(SH_CRTCINTERPS, ppsCRTC[1]); + } + + if( !bLoadSuccess ) + ZZLog::Error_Log("Failed to create CRTC shaders."); + + LOAD_PS(SH_CRTC24PS, ppsCRTC24[0]); + LOAD_PS(SH_CRTC24INTERPS, ppsCRTC24[1]); + LOAD_PS(SH_ZEROPS, ppsOne); + LOAD_PS(SH_BASETEXTUREPS, ppsBaseTexture); + LOAD_PS(SH_CONVERT16TO32PS, ppsConvert16to32); + LOAD_PS(SH_CONVERT32TO16PS, ppsConvert32to16); + + return true; +} + +FRAGMENTSHADER* ZZshLoadShadeEffect(int type, int texfilter, int fog, int testaem, int exactcolor, const clampInfo& clamp, int context, bool* pbFailed) +{ + int texwrap; + assert( texfilter < NUM_FILTERS ); + + if(g_nPixelShaderVer&SHADER_REDUCED) + texfilter = 0; + assert(!(g_nPixelShaderVer&SHADER_REDUCED) || !exactcolor); + + if( clamp.wms == clamp.wmt ) { + switch( clamp.wms ) { + case 0: texwrap = TEXWRAP_REPEAT; break; + case 1: texwrap = TEXWRAP_CLAMP; break; + case 2: texwrap = TEXWRAP_CLAMP; break; + default: texwrap = TEXWRAP_REGION_REPEAT; break; + } + } + else if( clamp.wms==3||clamp.wmt==3) + texwrap = TEXWRAP_REGION_REPEAT; + else + texwrap = TEXWRAP_REPEAT_CLAMP; + + int index = GET_SHADER_INDEX(type, texfilter, texwrap, fog, s_bWriteDepth, testaem, exactcolor, context, 0); + + assert( index < ArraySize(ppsTexture) ); + FRAGMENTSHADER* pf = ppsTexture+index; + + if( pbFailed != NULL ) *pbFailed = false; + + if( pf->prog != NULL ) + return pf; + + if( (g_nPixelShaderVer & SHADER_ACCURATE) && mapShaderResources.find(index+NUM_SHADERS*SHADER_ACCURATE) != mapShaderResources.end() ) + index += NUM_SHADERS*SHADER_ACCURATE; + + assert( mapShaderResources.find(index) != mapShaderResources.end() ); + SHADERHEADER* header = mapShaderResources[index]; + if( header == NULL ) + ZZLog::Error_Log("%d %d", index, g_nPixelShaderVer); + assert( header != NULL ); + + //DEBUG_LOG("shader:\n%s\n", (char*)(s_lpShaderResources + (header)->offset)); + pf->prog = cgCreateProgram(g_cgcontext, CG_OBJECT, (char*)(s_lpShaderResources + (header)->offset), cgfProf, NULL, NULL); + if( pf->prog != NULL && cgIsProgram(pf->prog) && cgGetError() == CG_NO_ERROR ) { + SetupFragmentProgramParameters(pf, context, type); + cgGLLoadProgram(pf->prog); + if( cgGetError() != CG_NO_ERROR ) { +// cgGLLoadProgram(pf->prog); +// if( cgGetError() != CG_NO_ERROR ) { + ZZLog::Error_Log("Failed to load shader %d,%d,%d,%d.", type, fog, texfilter, 4*clamp.wms+clamp.wmt); + if( pbFailed != NULL ) *pbFailed = true; + return pf; +// } + } + return pf; + } + + ZZLog::Error_Log("Failed to create shader %d,%d,%d,%d", type, fog, texfilter, 4*clamp.wms+clamp.wmt); + if( pbFailed != NULL ) *pbFailed = true; + + return NULL; +} + +#else // not RELEASE_TO_PUBLIC + +#define LOAD_VS(name, prog, shaderver) { \ + prog = cgCreateProgramFromFile(g_cgcontext, CG_SOURCE, EFFECT_NAME, shaderver, name, args); \ + if( !cgIsProgram(prog) ) { \ + ZZLog::Error_Log("Failed to load vs %s: \n%s", name, cgGetLastListing(g_cgcontext)); \ + return false; \ + } \ + cgGLLoadProgram(prog); \ + if( cgGetError() != CG_NO_ERROR ) ZZLog::Error_Log("failed to load program %s", name); \ + SetupVertexProgramParameters(prog, args[0]==context1); \ +} \ + +#ifdef _DEBUG +#define SET_PSFILENAME(frag, name) frag.filename = name +#else +#define SET_PSFILENAME(frag, name) +#endif + +#define LOAD_PS(name, fragment, shaderver) { \ + bLoadSuccess = true; \ + fragment.prog = cgCreateProgramFromFile(g_cgcontext, CG_SOURCE, EFFECT_NAME, shaderver, name, args); \ + if( !cgIsProgram(fragment.prog) ) { \ + ZZLog::Error_Log("Failed to load ps %s: \n%s", name, cgGetLastListing(g_cgcontext)); \ + return false; \ + } \ + cgGLLoadProgram(fragment.prog); \ + if( cgGetError() != CG_NO_ERROR ) { \ + ZZLog::Error_Log("failed to load program %s", name); \ + bLoadSuccess = false; \ + } \ + SetupFragmentProgramParameters(&fragment, args[0]==context1, 0); \ + SET_PSFILENAME(fragment, name); \ +} \ + +inline bool LoadEffects() +{ + // clear the textures + for(int i = 0; i < ArraySize(ppsTexture); ++i) { + SAFE_RELEASE_PROG(ppsTexture[i].prog); + } + +#ifndef _DEBUG + memset(ppsTexture, 0, sizeof(ppsTexture)); +#endif + + return true; +} + +bool ZZshLoadExtraEffects() +{ + const char* args[] = { NULL , NULL, NULL, NULL }; + char context0[255], context1[255]; + sprintf(context0, "-I%sctx0", EFFECT_DIR); + sprintf(context1, "-I%sctx1", EFFECT_DIR); + char* write_depth = "-DWRITE_DEPTH"; + bool bLoadSuccess = true; + + const char* pvsshaders[4] = { "RegularVS", "TextureVS", "RegularFogVS", "TextureFogVS" }; + + for(int i = 0; i < 4; ++i) { + args[0] = context0; + args[1] = NULL; + LOAD_VS(pvsshaders[i], pvs[2*i], cgvProf); + args[0] = context1; + LOAD_VS(pvsshaders[i], pvs[2*i+1], cgvProf); + + //if( conf.mrtdepth ) { + args[0] = context0; + args[1] = write_depth; + LOAD_VS(pvsshaders[i], pvs[2*i+8], cgvProf); + args[0] = context1; + LOAD_VS(pvsshaders[i], pvs[2*i+8+1], cgvProf); +// } +// else { +// pvs[2*i+8] = pvs[2*i+8+1] = NULL; +// } + } + + args[0] = context0; + args[1] = NULL; + LOAD_VS("BitBltVS", pvsBitBlt.prog, cgvProf); + pvsBitBlt.sBitBltPos = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltPos"); + pvsBitBlt.sBitBltTex = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltTex"); + pvsBitBlt.fBitBltTrans = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltTrans"); + + LOAD_PS("RegularPS", ppsRegular[0], cgfProf); + LOAD_PS("RegularFogPS", ppsRegular[1], cgfProf); + + if( conf.mrtdepth ) { + args[0] = context0; + args[1] = write_depth; + LOAD_PS("RegularPS", ppsRegular[2], cgfProf); + if( !bLoadSuccess ) + conf.mrtdepth = 0; + LOAD_PS("RegularFogPS", ppsRegular[3], cgfProf); + if( !bLoadSuccess ) + conf.mrtdepth = 0; + } + + LOAD_PS("BitBltPS", ppsBitBlt[0], cgfProf); + LOAD_PS("BitBltAAPS", ppsBitBlt[1], cgfProf); + if( !bLoadSuccess ) { + ZZLog::Error_Log("Failed to load BitBltAAPS, using BitBltPS."); + LOAD_PS("BitBltPS", ppsBitBlt[1], cgfProf); + } + + LOAD_PS("BitBltDepthPS", ppsBitBltDepth, cgfProf); + LOAD_PS("CRTCTargPS", ppsCRTCTarg[0], cgfProf); + LOAD_PS("CRTCTargInterPS", ppsCRTCTarg[1], cgfProf); + + g_bCRTCBilinear = true; + LOAD_PS("CRTCPS", ppsCRTC[0], cgfProf); + if( !bLoadSuccess ) { + // switch to simpler + g_bCRTCBilinear = false; + LOAD_PS("CRTCPS_Nearest", ppsCRTC[0], cgfProf); + LOAD_PS("CRTCInterPS_Nearest", ppsCRTC[0], cgfProf); + } + else { + LOAD_PS("CRTCInterPS", ppsCRTC[1], cgfProf); + } + + if( !bLoadSuccess ) + ZZLog::Error_Log("Failed to create CRTC shaders."); + + LOAD_PS("CRTC24PS", ppsCRTC24[0], cgfProf); LOAD_PS("CRTC24InterPS", ppsCRTC24[1], cgfProf); + LOAD_PS("ZeroPS", ppsOne, cgfProf); + LOAD_PS("BaseTexturePS", ppsBaseTexture, cgfProf); + LOAD_PS("Convert16to32PS", ppsConvert16to32, cgfProf); + LOAD_PS("Convert32to16PS", ppsConvert32to16, cgfProf); + +// if( !conf.mrtdepth ) { +// ZZLog::Error_Log("Disabling MRT depth writing,"); +// s_bWriteDepth = FALSE; +// } + + return true; +} + +FRAGMENTSHADER* ZZshLoadShadeEffect(int type, int texfilter, int fog, int testaem, int exactcolor, const clampInfo& clamp, int context, bool* pbFailed) +{ + int texwrap; + + assert( texfilter < NUM_FILTERS ); + //assert( g_nPixelShaderVer == SHADER_30 ); + if( clamp.wms == clamp.wmt ) { + switch( clamp.wms ) { + case 0: texwrap = TEXWRAP_REPEAT; break; + case 1: texwrap = TEXWRAP_CLAMP; break; + case 2: texwrap = TEXWRAP_CLAMP; break; + default: + texwrap = TEXWRAP_REGION_REPEAT; break; + } + } + else if( clamp.wms==3||clamp.wmt==3) + texwrap = TEXWRAP_REGION_REPEAT; + else + texwrap = TEXWRAP_REPEAT_CLAMP; + + int index = GET_SHADER_INDEX(type, texfilter, texwrap, fog, s_bWriteDepth, testaem, exactcolor, context, 0); + + if( pbFailed != NULL ) *pbFailed = false; + + FRAGMENTSHADER* pf = ppsTexture+index; + + if( pf->prog != NULL ) + return pf; + + pf->prog = LoadShaderFromType(EFFECT_DIR, EFFECT_NAME, type, texfilter, texwrap, fog, s_bWriteDepth, testaem, exactcolor, g_nPixelShaderVer, context); + + if( pf->prog != NULL ) { +#ifdef _DEBUG + char str[255]; + sprintf(str, "Texture%s%d_%sPS", fog?"Fog":"", texfilter, g_pTexTypes[type]); + pf->filename = str; +#endif + SetupFragmentProgramParameters(pf, context, type); + cgGLLoadProgram(pf->prog); + if( cgGetError() != CG_NO_ERROR ) { + // try again +// cgGLLoadProgram(pf->prog); +// if( cgGetError() != CG_NO_ERROR ) { + ZZLog::Error_Log("Failed to load shader %d,%d,%d,%d", type, fog, texfilter, 4*clamp.wms+clamp.wmt); + if( pbFailed != NULL ) *pbFailed = true; + //assert(0); + // NULL makes things crash + return pf; +// } + } + return pf; + } + + ZZLog::Error_Log("Failed to create shader %d,%d,%d,%d", type, fog, texfilter, 4*clamp.wms+clamp.wmt); + if( pbFailed != NULL ) *pbFailed = true; + + return NULL; +} + +#endif // RELEASE_TO_PUBLIC + +//#endif // NVIDIA_CG_API diff --git a/plugins/zzogl-pg-cg/opengl/ZZoglShaders.h b/plugins/zzogl-pg-cg/opengl/ZZoglShaders.h new file mode 100644 index 000000000..a44781414 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZZoglShaders.h @@ -0,0 +1,231 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __ZEROGS_SHADERS_H__ +#define __ZEROGS_SHADERS_H__ + +// -- Not very important things, but we keep it to enumerate shader +#define NUM_FILTERS 2 // texture filtering +#define NUM_TYPES 5 // types of texture read modes +#define NUM_TEXWRAPS 4 // texture wrapping +#define NUM_SHADERS (NUM_FILTERS*NUM_TYPES*NUM_TEXWRAPS*32) // # shaders for a given ps + +// Just bitmask for different type of shaders +#define SHADER_REDUCED 1 // equivalent to ps2.0 +#define SHADER_ACCURATE 2 // for older cards with less accurate math (ps2.x+) + +#include "ZZoglMath.h" +#include "GS.h" + +// For output +#define NVIDIA_CG_API +// --------------------------- API abstraction level -------------------------------- + +#ifdef NVIDIA_CG_API // Code for NVIDIA cg-toolkit API + +#include +#include +#define ZZshProgram CGprogram +#define ZZshShader CGprogram +#define ZZshShaderLink CGprogram +#define ZZshParameter CGparameter +#define ZZshContext CGcontext +#define ZZshProfile CGprofile +#define ZZshError CGerror +#define pZero 0 // Zero parameter +#define sZero 0 // Zero program + +#define SAFE_RELEASE_PROG(x) { if( (x) != NULL ) { cgDestroyProgram(x); x = NULL; } } +inline bool ZZshActiveParameter(ZZshParameter param) {return (param !=NULL); } + +#endif // end NVIDIA cg-toolkit API + +//const static char* g_pPsTexWrap[] = { "-DREPEAT", "-DCLAMP", "-DREGION_REPEAT", NULL }; + +enum ZZshShaderType {ZZ_SH_ZERO, ZZ_SH_REGULAR, ZZ_SH_REGULAR_FOG, ZZ_SH_TEXTURE, ZZ_SH_TEXTURE_FOG, ZZ_SH_CRTC}; +// We have "compatible" shaders, as RegularFogVS and RegularFogPS. if don't need to wory about incompatible shaders +// It used only in GLSL mode. + +// ------------------------- Variables ------------------------------- + +extern int g_nPixelShaderVer; +extern ZZshShaderLink pvs[16], g_vsprog, g_psprog; +extern ZZshParameter g_vparamPosXY[2], g_fparamFogColor; + +#define MAX_ACTIVE_UNIFORMS 600 +#define MAX_ACTIVE_SHADERS 400 + +struct FRAGMENTSHADER +{ + FRAGMENTSHADER() : prog(sZero), Shader(0), sMemory(pZero), sFinal(pZero), sBitwiseANDX(pZero), sBitwiseANDY(pZero), sInterlace(pZero), sCLUT(pZero), sOneColor(pZero), sBitBltZ(pZero), + fTexAlpha2(pZero), fTexOffset(pZero), fTexDims(pZero), fTexBlock(pZero), fClampExts(pZero), fTexWrapMode(pZero), + fRealTexDims(pZero), fTestBlack(pZero), fPageOffset(pZero), fTexAlpha(pZero) {} + + ZZshShaderLink prog; // it link to FRAGMENTSHADER structure, for compability between GLSL and CG + ZZshShader Shader; // GLSL store shader's not as ready programs, but as shaders compilated object. VS and PS should be linked together to + // made a program. + ZZshShaderType ShaderType; // Not every PS and VS are used together, only compatible ones. + + ZZshParameter sMemory, sFinal, sBitwiseANDX, sBitwiseANDY, sInterlace, sCLUT; + ZZshParameter sOneColor, sBitBltZ, sInvTexDims; + ZZshParameter fTexAlpha2, fTexOffset, fTexDims, fTexBlock, fClampExts, fTexWrapMode, fRealTexDims, fTestBlack, fPageOffset, fTexAlpha; + + int ParametersStart, ParametersFinish; // this is part of UniformsIndex array in which parameters of this shader stored. Last one is ParametersFinish-1 + +#ifdef _DEBUG + string filename; +#endif + + void set_uniform_param(ZZshParameter &var, const char *name) + { + ZZshParameter p; + p = cgGetNamedParameter(prog, name); + + if (p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE) var = p; + } + + bool set_texture(GLuint texobj, const char *name) + { + ZZshParameter p; + + p = cgGetNamedParameter(prog, name); + + if (p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE) + { + cgGLSetTextureParameter(p, texobj); + cgGLEnableTextureParameter(p); + return true; + } + + return false; + } + + bool connect(ZZshParameter &tex, const char *name) + { + ZZshParameter p; + + p = cgGetNamedParameter(prog, name); + + if (p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE) + { + cgConnectParameter(tex, p); + return true; + } + + return false; + } + + bool set_texture(ZZshParameter &tex, const char *name) + { + ZZshParameter p; + + p = cgGetNamedParameter(prog, name); + + if (p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE) + { + //cgGLEnableTextureParameter(p); + tex = p; + return true; + } + + return false; + } + + bool set_shader_const(float4 v, const char *name) + { + ZZshParameter p; + + p = cgGetNamedParameter(prog, name); + + if (p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE) + { + cgGLSetParameter4fv(p, v); + return true; + } + + return false; + } +}; + +struct VERTEXSHADER +{ + VERTEXSHADER() : prog(sZero), Shader(0), sBitBltPos(pZero), sBitBltTex(pZero) {} + + ZZshShaderLink prog; + ZZshShader Shader; + ZZshShaderType ShaderType; + + ZZshParameter sBitBltPos, sBitBltTex, fBitBltTrans; // vertex shader constants + + int ParametersStart, ParametersFinish; +}; + + extern float4 g_vdepth; + extern float4 vlogz; + extern VERTEXSHADER pvsBitBlt; + extern FRAGMENTSHADER ppsBitBlt[2], ppsBitBltDepth, ppsOne; // ppsOne used to stop using shaders for draw + extern FRAGMENTSHADER ppsBaseTexture, ppsConvert16to32, ppsConvert32to16; + + extern FRAGMENTSHADER ppsRegular[4], ppsTexture[NUM_SHADERS]; + extern FRAGMENTSHADER ppsCRTC[2], ppsCRTC24[2], ppsCRTCTarg[2]; + +// ------------------------- Functions ------------------------------- + +#ifdef NVIDIA_CG_API +inline bool ZZshExistProgram(FRAGMENTSHADER* pf) {return (pf->prog != NULL); }; // We don't check ps != NULL, so be warned, +inline bool ZZshExistProgram(VERTEXSHADER* pf) {return (pf->prog != NULL); }; +inline bool ZZshExistProgram(ZZshShaderLink prog) {return (prog != NULL); }; +#endif + +extern const char* ShaderCallerName; +extern const char* ShaderHandleName; + +inline void SetShaderCaller(const char* Name) { + ShaderCallerName = Name; +} + +inline void SetHandleName(const char* Name) { + ShaderHandleName = Name; +} + +inline void ResetShaderCounters() { +// g_vsprog = g_psprog = sZero; +} + +extern bool ZZshCheckProfilesSupport(); +extern bool ZZshStartUsingShaders(); +extern bool ZZshCreateOpenShadersFile(); +extern void ZZshGLDisableProfile(); +extern void ZZshGLEnableProfile(); +extern void ZZshSetParameter4fv(ZZshShaderLink prog, ZZshParameter param, const float* v, const char* name); +extern void ZZshSetParameter4fv(ZZshParameter param, const float* v, const char* name); +extern void ZZshSetParameter4fvWithRetry(ZZshParameter* param, ZZshShaderLink prog, const float* v, const char* name); +extern void ZZshGLSetTextureParameter(ZZshShaderLink prog, ZZshParameter param, GLuint texobj, const char* name); +extern void ZZshGLSetTextureParameter(ZZshParameter param, GLuint texobj, const char* name); +extern void ZZshDefaultOneColor( FRAGMENTSHADER ptr ); +extern void ZZshSetVertexShader(ZZshShaderLink prog); +extern void ZZshSetPixelShader(ZZshShaderLink prog); +extern bool ZZshLoadExtraEffects(); + +extern FRAGMENTSHADER* ZZshLoadShadeEffect(int type, int texfilter, int fog, int testaem, int exactcolor, const clampInfo& clamp, int context, bool* pbFailed); + + // only sets a limited amount of state (for Update) + void SetTexVariablesInt(int context, int bilinear, const tex0Info& tex0, bool CheckVB, FRAGMENTSHADER* pfragment, int force); + +#endif diff --git a/plugins/zzogl-pg-cg/opengl/ZZoglShoots.cpp b/plugins/zzogl-pg-cg/opengl/ZZoglShoots.cpp new file mode 100644 index 000000000..b43c64d94 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZZoglShoots.cpp @@ -0,0 +1,655 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +// Texture and avi saving to file functions + +//------------------ Includes + #include "Util.h" +#if defined(_WIN32) +# include "Utilities/RedtapeWindows.h" +# include +# include "resource.h" +#endif +#include + +#include "targets.h" +#include "Mem.h" +#include "ZZoglShoots.h" + +// AVI Capture +int s_avicapturing = 0; +bool g_bMakeSnapshot = false; + +extern "C" +{ +#ifdef _WIN32 +# define XMD_H +# undef FAR +#define HAVE_BOOLEAN +#endif + +#include "jpeglib.h" +} + +//------------------ Defines +#define TGA_FILE_NAME_MAX_LENGTH 20 +#define MAX_NUMBER_SAVED_TGA 200 + +//Windows have no snprintf +#if defined(_WIN32) +# define snprintf sprintf_s +#endif +//------------------ Constants + +//------------------ Global Variables +int TexNumber = 0; +int s_aviinit = 0; + +string strSnapshot; + +//------------------ Code + +// Set variables need to made a snapshoot when it's possible +void SaveSnapshot(const char* filename) +{ + g_bMakeSnapshot = true; + strSnapshot = filename; +} + +// Save curent renderer in jpeg or TGA format +bool SaveRenderTarget(const char* filename, int width, int height, int jpeg) +{ + bool bflip = height < 0; + height = abs(height); + vector data(width*height); + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); + + if (glGetError() != GL_NO_ERROR) return false; + + if (bflip) + { + // swap scanlines + vector scanline(width); + + for (int i = 0; i < height / 2; ++i) + { + memcpy(&scanline[0], &data[i * width], width * 4); + memcpy(&data[i * width], &data[(height - i - 1) * width], width * 4); + memcpy(&data[(height - i - 1) * width], &scanline[0], width * 4); + } + } + + if (jpeg) return SaveJPEG(filename, width, height, &data[0], 70); + + return SaveTGA(filename, width, height, &data[0]); +} + +// Save selected texture as TGA +bool SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height) +{ + vector data(width*height); + glBindTexture(textarget, tex); + glGetTexImage(textarget, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); + + if (glGetError() != GL_NO_ERROR) return false; + + return SaveTGA(filename, width, height, &data[0]); +} + +// save image as JPEG +bool SaveJPEG(const char* filename, int image_width, int image_height, const void* pdata, int quality) +{ + u8* image_buffer = new u8[image_width * image_height * 3]; + u8* psrc = (u8*)pdata; + + // input data is rgba format, so convert to rgb + u8* p = image_buffer; + + for (int i = 0; i < image_height; ++i) + { + for (int j = 0; j < image_width; ++j) + { + p[0] = psrc[0]; + p[1] = psrc[1]; + p[2] = psrc[2]; + p += 3; + psrc += 4; + } + } + + /* This struct contains the JPEG compression parameters and pointers to + * working space (which is allocated as needed by the JPEG library). + * It is possible to have several such structures, representing multiple + * compression/decompression processes, in existence at once. We refer + * to any one struct (and its associated working data) as a "JPEG object". + */ + + struct jpeg_compress_struct cinfo; + + /* This struct represents a JPEG error handler. It is declared separately + * because applications often want to supply a specialized error handler + * (see the second half of this file for an example). But here we just + * take the easy way out and use the standard error handler, which will + * print a message on stderr and call exit() if compression fails. + * Note that this struct must live as long as the main JPEG parameter + * struct, to avoid dangling-pointer problems. + */ + + struct jpeg_error_mgr jerr; + + /* More stuff */ + FILE * outfile; /* target file */ + + JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ + + int row_stride; /* physical row width in image buffer */ + + /* Step 1: allocate and initialize JPEG compression object */ + + /* We have to set up the error handler first, in case the initialization + * step fails. (Unlikely, but it could happen if you are out of memory.) + * This routine fills in the contents of struct jerr, and returns jerr's + * address which we place into the link field in cinfo. + */ + cinfo.err = jpeg_std_error(&jerr); + + /* Now we can initialize the JPEG compression object. */ + jpeg_create_compress(&cinfo); + + /* Step 2: specify data destination (eg, a file) */ + /* Note: steps 2 and 3 can be done in either order. */ + + /* Here we use the library-supplied code to send compressed data to a + * stdio stream. You can also write your own code to do something else. + * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that + * requires it in order to write binary files. + */ + if ((outfile = fopen(filename, "wb")) == NULL) + { + fprintf(stderr, "can't open %s\n", filename); + exit(1); + } + + jpeg_stdio_dest(&cinfo, outfile); + + /* Step 3: set parameters for compression */ + + /* First we supply a description of the input image. + * Four fields of the cinfo struct must be filled in: + */ + cinfo.image_width = image_width; /* image width and height, in pixels */ + cinfo.image_height = image_height; + cinfo.input_components = 3; /* # of color components per pixel */ + cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ + /* Now use the library's routine to set default compression parameters. + * (You must set at least cinfo.in_color_space before calling this, + * since the defaults depend on the source color space.) + */ + jpeg_set_defaults(&cinfo); + /* Now you can set any non-default parameters you wish to. + * Here we just illustrate the use of quality (quantization table) scaling: + */ + jpeg_set_quality(&cinfo, quality, true /* limit to baseline-JPEG values */); + + /* Step 4: Start compressor */ + + /* true ensures that we will write a complete interchange-JPEG file. + * Pass true unless you are very sure of what you're doing. + */ + jpeg_start_compress(&cinfo, true); + + /* Step 5: while (scan lines remain to be written) */ + /* jpeg_write_scanlines(...); */ + + /* Here we use the library's state variable cinfo.next_scanline as the + * loop counter, so that we don't have to keep track ourselves. + * To keep things simple, we pass one scanline per call; you can pass + * more if you wish, though. + */ + row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */ + + while (cinfo.next_scanline < cinfo.image_height) + { + /* jpeg_write_scanlines expects an array of pointers to scanlines. + * Here the array is only one element long, but you could pass + * more than one scanline at a time if that's more convenient. + */ + row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride]; + (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); + } + + /* Step 6: Finish compression */ + + jpeg_finish_compress(&cinfo); + + /* After finish_compress, we can close the output file. */ + fclose(outfile); + + /* Step 7: release JPEG compression object */ + + /* This is an important step since it will release a good deal of memory. */ + jpeg_destroy_compress(&cinfo); + + delete image_buffer; + + /* And we're done! */ + return true; +} + +#if defined(_MSC_VER) +# pragma pack(push, 1) +#endif + +// This is the defenition of TGA header. We need it to function bellow + +struct TGA_HEADER +{ + u8 identsize; // size of ID field that follows 18 u8 header (0 usually) + u8 colourmaptype; // type of colour map 0=none, 1=has palette + u8 imagetype; // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed + + s16 colourmapstart; // first colour map entry in palette + s16 colourmaplength; // number of colours in palette + u8 colourmapbits; // number of bits per palette entry 15,16,24,32 + + s16 xstart; // image x origin + s16 ystart; // image y origin + s16 width; // image width in pixels + s16 height; // image height in pixels + u8 bits; // image bits per pixel 8,16,24,32 + u8 descriptor; // image descriptor bits (vh flip bits) + + // pixel data follows header +#if defined(_MSC_VER) +}; + +# pragma pack(pop) +# else +} + +__attribute__((packed)); +#endif + +// Save image as TGA +bool SaveTGA(const char* filename, int width, int height, void* pdata) +{ + int err = 0; + TGA_HEADER hdr; + FILE* f = fopen(filename, "wb"); + + if (f == NULL) return false; + + assert(sizeof(TGA_HEADER) == 18 && sizeof(hdr) == 18); + + memset(&hdr, 0, sizeof(hdr)); + + hdr.imagetype = 2; + hdr.bits = 32; + hdr.width = width; + hdr.height = height; + hdr.descriptor |= 8 | (1 << 5); // 8bit alpha, flip vertical + + err = fwrite(&hdr, sizeof(hdr), 1, f); + err = fwrite(pdata, width * height * 4, 1, f); + + fclose(f); + + return true; +} + +// AVI capture stuff +// AVI start -- set needed global variables +void StartCapture() +{ + if (conf.captureAvi()) return; + if (!s_aviinit) + { +#ifdef _WIN32 + START_AVI("zerogs.avi"); +#else // linux + //TODO +#endif + s_aviinit = 1; + } + else + { + ZZLog::Error_Log("Continuing from previous capture."); + } + + s_avicapturing = 1; + conf.setCaptureAvi(true); + ZZLog::Warn_Log("Started recording zerogs.avi."); + +} + +// Stop. +void StopCapture() +{ + if (!conf.captureAvi()) return; + s_avicapturing = 0; + conf.setCaptureAvi(false); + ZZLog::Warn_Log("Stopped recording."); +} + +// And capture frame does not work on linux. +void CaptureFrame() +{ + if ((!s_avicapturing) || (!s_aviinit)) return; + + vector data(GLWin.backbuffer.w * GLWin.backbuffer.h); + glReadPixels(0, 0, GLWin.backbuffer.w, GLWin.backbuffer.h, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); + + if (glGetError() != GL_NO_ERROR) return; + +#ifdef _WIN32 + int fps = SMODE1->CMOD == 3 ? 50 : 60; + + bool bSuccess = ADD_FRAME_FROM_DIB_TO_AVI("AAAA", fps, GLWin.backbuffer.w, GLWin.backbuffer.h, 32, &data[0]); + + if (!bSuccess) + { + s_avicapturing = 0; + STOP_AVI(); + ZZAddMessage("Failed to create avi"); + return; + } + +#else // linux + //TODO +#endif // _WIN32 +} + +// It's nearly the same as save texture +void +SaveTex(tex0Info* ptex, int usevid) +{ + vector data(ptex->tw*ptex->th); + vector srcdata; + + u32* dst = &data[0]; + u8* psrc = g_pbyGSMemory; + + CMemoryTarget* pmemtarg = NULL; + + if (usevid) + { + pmemtarg = g_MemTargs.GetMemoryTarget(*ptex, 0); + assert(pmemtarg != NULL); + + glBindTexture(GL_TEXTURE_RECTANGLE_NV, pmemtarg->ptex->tex); + srcdata.resize(4 * pmemtarg->texW * pmemtarg->texH); + + // FIXME strangely this function call seem to crash pcsx2 on atelier of iris 1 + // Note: fmt is GL_UNSIGNED_SHORT_1_5_5_5_REV + glGetTexImage(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA, pmemtarg->fmt, &srcdata[0]); + + u32 offset = MemorySize(pmemtarg->realy); + + if (ptex->psm == PSMT8) + offset *= CLUT_PIXEL_SIZE(ptex->cpsm); + else if (ptex->psm == PSMT4) + offset *= CLUT_PIXEL_SIZE(ptex->cpsm) * 2; + + psrc = &srcdata[0] - offset; + } + + for (int i = 0; i < ptex->th; ++i) + { + for (int j = 0; j < ptex->tw; ++j) + { + u32 u = 0; + u32 addr; + + switch (ptex->psm) + { + case PSMCT32: + addr = getPixelAddress32(j, i, ptex->tbp0, ptex->tbw); + if (addr * 4 < MEMORY_END) + u = readPixel32(psrc, j, i, ptex->tbp0, ptex->tbw); + else + u = 0; + break; + + case PSMCT24: + addr = getPixelAddress24(j, i, ptex->tbp0, ptex->tbw); + if (addr * 4 < MEMORY_END) + u = readPixel24(psrc, j, i, ptex->tbp0, ptex->tbw); + else + u = 0; + break; + + case PSMCT16: + addr = getPixelAddress16(j, i, ptex->tbp0, ptex->tbw); + if (addr * 2 < MEMORY_END) + { + u = readPixel16(psrc, j, i, ptex->tbp0, ptex->tbw); + u = RGBA16to32(u); + } + else + { + u = 0; + } + break; + + case PSMCT16S: + addr = getPixelAddress16(j, i, ptex->tbp0, ptex->tbw); + if (addr * 2 < MEMORY_END) + { + u = readPixel16S(psrc, j, i, ptex->tbp0, ptex->tbw); + u = RGBA16to32(u); + } + else + { + u = 0; + } + break; + + case PSMT8: + addr = getPixelAddress8(j, i, ptex->tbp0, ptex->tbw); + if (addr < MEMORY_END) + { + if (usevid) + { + if (PSMT_IS32BIT(ptex->cpsm)) + u = *(u32*)(psrc + 4 * addr); + else + u = RGBA16to32(*(u16*)(psrc + 2 * addr)); + } + else + { + u = readPixel8(psrc, j, i, ptex->tbp0, ptex->tbw); + } + } + else + { + u = 0; + } + break; + + case PSMT4: + addr = getPixelAddress4(j, i, ptex->tbp0, ptex->tbw); + if (addr < 2*MEMORY_END) + { + if (usevid) + { + if (PSMT_IS32BIT(ptex->cpsm)) + u = *(u32*)(psrc + 4 * addr); + else + u = RGBA16to32(*(u16*)(psrc + 2 * addr)); + } + else + { + u = readPixel4(psrc, j, i, ptex->tbp0, ptex->tbw); + } + } + else + { + u = 0; + } + + break; + + case PSMT8H: + addr = getPixelAddress8H(j, i, ptex->tbp0, ptex->tbw); + if (4*addr < MEMORY_END) + { + if (usevid) + { + if (PSMT_IS32BIT(ptex->cpsm)) + u = *(u32*)(psrc + 4 * addr); + else + u = RGBA16to32(*(u16*)(psrc + 2 * addr)); + } + else + { + u = readPixel8H(psrc, j, i, ptex->tbp0, ptex->tbw); + } + } + else + { + u = 0; + } + break; + + case PSMT4HL: + addr = getPixelAddress4HL(j, i, ptex->tbp0, ptex->tbw); + if (4*addr < MEMORY_END) + { + if (usevid) + { + if (PSMT_IS32BIT(ptex->cpsm)) + u = *(u32*)(psrc + 4 * addr); + else + u = RGBA16to32(*(u16*)(psrc + 2 * addr)); + } + else + { + u = readPixel4HL(psrc, j, i, ptex->tbp0, ptex->tbw); + } + } + else + { + u = 0; + } + break; + + case PSMT4HH: + addr = getPixelAddress4HH(j, i, ptex->tbp0, ptex->tbw); + if (4*addr < MEMORY_END) + { + if (usevid) + { + if (PSMT_IS32BIT(ptex->cpsm)) + u = *(u32*)(psrc + 4 * addr); + else + u = RGBA16to32(*(u16*)(psrc + 2 * addr)); + } + else + { + u = readPixel4HH(psrc, j, i, ptex->tbp0, ptex->tbw); + } + } + else + { + u = 0; + } + break; + + case PSMT32Z: + addr = getPixelAddress32Z(j, i, ptex->tbp0, ptex->tbw); + if (4*addr < MEMORY_END) + u = readPixel32Z(psrc, j, i, ptex->tbp0, ptex->tbw); + else + u = 0; + break; + + case PSMT24Z: + addr = getPixelAddress24Z(j, i, ptex->tbp0, ptex->tbw); + if (4*addr < MEMORY_END) + u = readPixel24Z(psrc, j, i, ptex->tbp0, ptex->tbw); + else + u = 0; + break; + + case PSMT16Z: + addr = getPixelAddress16Z(j, i, ptex->tbp0, ptex->tbw); + if (2*addr < MEMORY_END) + u = readPixel16Z(psrc, j, i, ptex->tbp0, ptex->tbw); + else + u = 0; + break; + + case PSMT16SZ: + addr = getPixelAddress16SZ(j, i, ptex->tbp0, ptex->tbw); + if (2*addr < MEMORY_END) + u = readPixel16SZ(psrc, j, i, ptex->tbp0, ptex->tbw); + else + u = 0; + break; + + default: + assert(0); + } + + *dst++ = u; + } + } + + char Name[TGA_FILE_NAME_MAX_LENGTH]; + + snprintf(Name, TGA_FILE_NAME_MAX_LENGTH, "Tex.%d.tga", TexNumber); + SaveTGA(Name, ptex->tw, ptex->th, &data[0]); + + TexNumber++; + if (TexNumber > MAX_NUMBER_SAVED_TGA) TexNumber = 0; +} + + +// Do the save texture and return file name of it +// Do not forget to call free(), other wise there would be memory leak! +char* NamedSaveTex(tex0Info* ptex, int usevid) +{ + SaveTex(ptex, usevid); + + char* Name = (char*)malloc(TGA_FILE_NAME_MAX_LENGTH); + snprintf(Name, TGA_FILE_NAME_MAX_LENGTH, "Tex.%d.tga", TexNumber); + + return Name; +} + +// Special function, which is safe to call from any other file, without aviutils problems. +void Stop_Avi() +{ +#ifdef _WIN32 + STOP_AVI(); +#else +// Does not support yet +#endif +} + +void Delete_Avi_Capture() +{ + if (s_aviinit) + { + StopCapture(); + Stop_Avi(); + ZZLog::Error_Log("zerogs.avi stopped."); + s_aviinit = 0; + } +} diff --git a/plugins/zzogl-pg-cg/opengl/ZZoglShoots.h b/plugins/zzogl-pg-cg/opengl/ZZoglShoots.h new file mode 100644 index 000000000..98bb1383d --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZZoglShoots.h @@ -0,0 +1,35 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef ZZOGLSHOOTS_H_INCLUDED +#define ZZOGLSHOOTS_H_INCLUDED + +void SaveSnapshot(const char* filename); +bool SaveRenderTarget(const char* filename, int width, int height, int jpeg); +bool SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height); +bool SaveJPEG(const char* filename, int width, int height, const void* pdata, int quality); +bool SaveTGA(const char* filename, int width, int height, void* pdata); +void Stop_Avi(); +void Delete_Avi_Capture(); + +void StartCapture(); +void StopCapture(); +void CaptureFrame(); + +#endif // ZZOGLSHOOTS_H_INCLUDED diff --git a/plugins/zzogl-pg-cg/opengl/ZZoglVB.cpp b/plugins/zzogl-pg-cg/opengl/ZZoglVB.cpp new file mode 100644 index 000000000..a1604b2be --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZZoglVB.cpp @@ -0,0 +1,506 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +// Zerogs:VB implementation. +// VB stands for Visual Buffer, as I think + +//------------------- Includes + #include "Util.h" +#include "targets.h" +#include "ZZoglVB.h" +#include "GS.h" +#include "Mem.h" +extern float fiTexWidth[2], fiTexHeight[2]; // current tex width and height + +// ----------------- Defines +#define MINMAX_SHIFT 3 + +//------------------ Constants + +// ----------------- Global Variables +int maxmin = 608; +// ----------------- Code + +// Constructor. Set width and height to 1 +VB::VB() +{ + memset(this, 0, sizeof(VB)); + tex0.tw = 1; + tex0.th = 1; +} + +// Destructor +VB::~VB() +{ + Destroy(); +} + +void VB::Destroy() +{ + _aligned_free(pBufferData); + pBufferData = NULL; + nNumVertices = 0; + + prndr = NULL; + pdepth = NULL; +} + +int ConstraintReason; + +// Return number of 64-pixels block, that guaranted could be hold in memory +// from gsfb.fbp and tbp (textrure pase), zbuf.zbp (Z-buffer), frame.fbp +// (previous frame). +inline int VB::FindMinimalMemoryConstrain(int tbp, int maxpos) +{ + int MinConstraint = maxpos; + + // make sure texture is far away from tbp + { + int Constraint = tbp - gsfb.fbp; + + if ((0 < Constraint) && (Constraint < MinConstraint)) + { + MinConstraint = Constraint; + ConstraintReason = 1; + } + } + + // offroad uses 0x80 fbp which messes up targets + // special case when double buffering (hamsterball) + // Suikoden 3 require e00 have this issue too. P3 - 0x1000. + + if (prndr != NULL) + { + int Constraint = frame.fbp - gsfb.fbp; + + if ((0x0 < Constraint) && (Constraint < MinConstraint)) + { + MinConstraint = Constraint; + ConstraintReason = 2; + } + } + + // old caching method + // zmsk necessary for KH movie + if (!zbuf.zmsk) + { + int Constraint = zbuf.zbp - gsfb.fbp; + + if ((0 < Constraint) && (Constraint < MinConstraint)) + { + MinConstraint = Constraint; + ConstraintReason = 3; + } + } + + // In 16Bit mode in one Word frame stored 2 pixels + if (PSMT_ISHALF(gsfb.psm)) MinConstraint *= 2; + + return MinConstraint ; +} + +// Return number of 64 pizel words that could be placed in Z-Buffer +// If no Z-buffer present return old constraint +inline int VB::FindZbufferMemoryConstrain(int tbp, int maxpos) +{ + int MinConstraint = maxpos; + + // Check tbp / zbuffer constraint + if (!zbuf.zmsk) + { + int Constraint = (tbp - zbuf.zbp) * (PSMT_ISHALF(zbuf.psm) ? 2 : 1); + + if ((0 < Constraint) && (Constraint < MinConstraint)) + { + MinConstraint = Constraint; + ConstraintReason = 4; + } + } + + return MinConstraint; +} + +// Return heights limiter from scissor... +inline int GetScissorY(int y) +{ + int fbh = (y >> MINMAX_SHIFT) + 1; + + if (fbh > 2 && (fbh & 1)) fbh -= 1; + + return fbh; +} + +//There is several reasons to limit a height of frame: maximum buffer size, calculated size +//from fbw and fbh and scissoring. +inline int VB::FindMinimalHeightConstrain(int maxpos) +{ + int MinConstraint = maxpos; + + if (maxmin < MinConstraint) + { + MinConstraint = maxmin; + ConstraintReason = 5; + } + + if (gsfb.fbh < MinConstraint) + { + MinConstraint = gsfb.fbh; + ConstraintReason = 6; + } + + int ScissorConstraint = GetScissorY(scissor.y1) ; + + if (ScissorConstraint < MinConstraint) + { + MinConstraint = ScissorConstraint; + ConstraintReason = 7; + } + + return MinConstraint; +} + +// 32 bit frames have additional constraints to frame +// maxpos was maximum length of frame at normal constraints +inline void VB::CheckFrame32bitRes(int maxpos) +{ + int fbh = frame.fbh; + + if (frame.fbh >= 512) + { + // neopets hack + maxmin = min(maxmin, frame.fbh); + frame.fbh = maxmin; + ConstraintReason = 8; + } + + // ffxii hack to stop resolving + if (frame.fbp >= 0x3000 && fbh >= 0x1a0) + { + int endfbp = frame.fbp + frame.fbw * fbh / (PSMT_ISHALF(gsfb.psm) ? 128 : 64); + + // see if there is a previous render target in the way, reduce + + for (CRenderTargetMngr::MAPTARGETS::iterator itnew = s_RTs.mapTargets.begin(); itnew != s_RTs.mapTargets.end(); ++itnew) + { + if (itnew->second->fbp > frame.fbp && endfbp > itnew->second->fbp) + { + endfbp = itnew->second->fbp; + } + } + + frame.fbh = (endfbp - frame.fbp) * (PSMT_ISHALF(gsfb.psm) ? 128 : 64) / frame.fbw; + + if (frame.fbh < fbh) ConstraintReason = 9; + } + +} + +// This is the main code for frame resizing. +// It checks for several reasons to resize and resizes if it needs to. +// 4Mb memory in 64 bit (4 bytes) words. +// |------------------------|---------------------|----------|----------|---------------------| +// 0 gsfb.fbp zbuff.zpb tbp frame.fbp 2^20/64 +inline int VB::CheckFrameAddConstraints(int tbp) +{ + if (gsfb.fbw <= 0) + { + ERROR_LOG_SPAM("render target null, no constraints. Ignoring\n"); + return -1; + } + + // Memory region after fbp + int maxmemorypos = 0x4000 - gsfb.fbp; + + ConstraintReason = 0; + + maxmemorypos = FindMinimalMemoryConstrain(tbp, maxmemorypos); + maxmemorypos = FindZbufferMemoryConstrain(tbp, maxmemorypos); + + int maxpos = 64 * maxmemorypos ; + + maxpos /= gsfb.fbw; + + //? atelier iris crashes without it + if (maxpos > 256) maxpos &= ~0x1f; + +#ifdef DEVBUILD + int noscissorpos = maxpos; + int ConstrainR1 = ConstraintReason; +#endif + + maxpos = FindMinimalHeightConstrain(maxpos); + + frame = gsfb; + frame.fbh = maxpos; + + if (!PSMT_ISHALF(frame.psm) || !(conf.settings().full_16_bit_res)) CheckFrame32bitRes(maxpos); + +#ifdef DEVBUILD + if (frame.fbh == 0xe2) + ZZLog::Debug_Log("Const: %x %x %d| %x %d %x %x", frame.fbh, frame.fbw, ConstraintReason, noscissorpos, ConstrainR1, tbp, frame.fbp); +#endif + +// Fixme: Reserved psm for framebuffers +// gsfb.psm &= 0xf; // shadow tower + + return 0; +} + +// Check if after resizing new depth target is needed to be used. +// it returns 2 if a new depth target is used. +inline int VB::CheckFrameResolveDepth(int tbp) +{ + int result = 0; + CDepthTarget* pprevdepth = pdepth; + pdepth = NULL; + + // just z changed + frameInfo f = CreateFrame(zbuf.zbp, prndr->fbw, prndr->fbh, zbuf.psm, (zbuf.psm == 0x31) ? 0xff000000 : 0); + + CDepthTarget* pnewdepth = (CDepthTarget*)s_DepthRTs.GetTarg(f, CRenderTargetMngr::TO_DepthBuffer | CRenderTargetMngr::TO_StrictHeight | + (zbuf.zmsk ? CRenderTargetMngr::TO_Virtual : 0), get_maxheight(zbuf.zbp, gsfb.fbw, 0)); + + assert(pnewdepth != NULL && prndr != NULL); + if (pnewdepth->fbh != prndr->fbh) ZZLog::Debug_Log("pnewdepth->fbh(0x%x) != prndr->fbh(0x%x)", pnewdepth->fbh, prndr->fbh); + //assert(pnewdepth->fbh == prndr->fbh); + + if ((pprevdepth != pnewdepth) || (pprevdepth != NULL && (pprevdepth->status & CRenderTarget::TS_NeedUpdate))) + result = 2; + + pdepth = pnewdepth; + + return result; +} + +// Check if after resizing, a new render target is needed to be used. Also perform deptarget check. +// Returns 1 if only 1 render target is changed and 3 -- if both. +inline int VB::CheckFrameResolveRender(int tbp) +{ + int result = 0; + + CRenderTarget* pprevrndr = prndr; + prndr = NULL; + CDepthTarget* pprevdepth = pdepth; + pdepth = NULL; + // Set renderes to NULL to prevent Flushing. + + CRenderTarget* pnewtarg = s_RTs.GetTarg(frame, 0, maxmin); + assert(pnewtarg != NULL); + + // pnewtarg->fbh >= 0x1c0 needed for ffx + + if ((pnewtarg->fbh >= 0x1c0) && pnewtarg->fbh > frame.fbh && zbuf.zbp < tbp && !zbuf.zmsk) + { + // check if zbuf is in the way of the texture (suikoden5) + int maxallowedfbh = (tbp - zbuf.zbp) * (PSMT_ISHALF(zbuf.psm) ? 128 : 64) / gsfb.fbw; + + if (PSMT_ISHALF(gsfb.psm)) maxallowedfbh *= 2; + + if (pnewtarg->fbh > maxallowedfbh + 32) // +32 needed for ffx2 + { + // destroy and recreate + s_RTs.DestroyAllTargs(0, 0x100, pnewtarg->fbw); + pnewtarg = s_RTs.GetTarg(frame, 0, maxmin); + assert(pnewtarg != NULL); + } + } + + ZZLog::Prim_Log("frame_%d: fbp=0x%x fbw=%d fbh=%d(%d) psm=0x%x fbm=0x%x\n", ictx, gsfb.fbp, gsfb.fbw, gsfb.fbh, pnewtarg->fbh, gsfb.psm, gsfb.fbm); + + if ((pprevrndr != pnewtarg) || (pprevrndr != NULL && (pprevrndr->status & CRenderTarget::TS_NeedUpdate))) + result = 1; + + prndr = pnewtarg; + + pdepth = pprevdepth; + + result |= CheckFrameResolveDepth(tbp); + + return result; +} + +// After frame resetting, it is possible that 16 to 32 or 32 to 16 (color bits) conversion should be made. +inline void VB::CheckFrame16vs32Conversion() +{ + if (prndr->status & CRenderTarget::TS_NeedConvert32) + { + if (pdepth->pdepth != 0) pdepth->SetDepthStencilSurface(); + + prndr->fbh *= 2; + prndr->ConvertTo32(); + prndr->status &= ~CRenderTarget::TS_NeedConvert32; + } + else if (prndr->status & CRenderTarget::TS_NeedConvert16) + { + if (pdepth->pdepth != 0) pdepth->SetDepthStencilSurface(); + + prndr->fbh /= 2; + prndr->ConvertTo16(); + prndr->status &= ~CRenderTarget::TS_NeedConvert16; + } +} + +void SetContextTarget(int context); + +// A lot of times, the target is too big and overwrites the texture. +// If tbp != 0, use it to bound. +void VB::CheckFrame(int tbp) +{ + GL_REPORT_ERRORD(); + + static int bChanged; + + if (bNeedZCheck) + { + ZZLog::Prim_Log("zbuf_%d: zbp=0x%x psm=0x%x, zmsk=%d\n", ictx, zbuf.zbp, zbuf.psm, zbuf.zmsk); + //zbuf = *zb; + } + + if (m_Blocks[gsfb.psm].bpp == 0) + { + ZZLog::Error_Log("CheckFrame invalid bpp %d.", gsfb.psm); + return; + } + + bChanged = 0; + + if (bNeedFrameCheck) + { + // important to set before calling GetTarg + bNeedFrameCheck = 0; + bNeedZCheck = 0; + + if (CheckFrameAddConstraints(tbp) == -1) return; + + if ((prndr != NULL) && (prndr->psm != gsfb.psm)) + { + // behavior for dest alpha varies +// ResetAlphaVariables(); + } + + bChanged = CheckFrameResolveRender(tbp); + + CheckFrame16vs32Conversion(); + } + else if (bNeedZCheck) + { + bNeedZCheck = 0; + + if (prndr != NULL && gsfb.fbw > 0) CheckFrameResolveDepth(tbp); + } + + if (prndr != NULL) SetContextTarget(ictx); + GL_REPORT_ERRORD(); +} + +// This is the case, most easy to perform, when nothing was changed +inline void VB::FlushTexUnchangedClutDontUpdate() +{ + if (ZZOglGet_cld_TexBits(uNextTex0Data[1])) + { + texClutWrite(ictx); + // invalidate to make sure target didn't change! + bVarsTexSync = false; + } +} + +// The second of easy branch. We does not change storage model, so we don't need to +// update anything except texture itself +inline void VB::FlushTexClutDontUpdate() +{ + if (!ZZOglClutStorageUnchanged(uCurTex0Data, uNextTex0Data)) Flush(ictx); + + // clut memory isn't going to be loaded so can ignore, but at least update CSA and CPSM! + uCurTex0Data[1] = (uCurTex0Data[1] & CPSM_CSA_NOTMASK) | (uNextTex0Data[1] & CPSM_CSA_BITMASK); + + tex0.csa = ZZOglGet_csa_TexBits(uNextTex0Data[1]); + tex0.cpsm = ZZOglGet_cpsm_TexBits(uNextTex0Data[1]); + + texClutWrite(ictx); + + bVarsTexSync = false; +} + + +// Set texture variables after big change +inline void VB::FlushTexSetNewVars(u32 psm) +{ + tex0.tbp0 = ZZOglGet_tbp0_TexBits(uNextTex0Data[0]); + tex0.tbw = ZZOglGet_tbw_TexBitsMult(uNextTex0Data[0]); + tex0.psm = psm; + tex0.tw = ZZOglGet_tw_TexBitsExp(uNextTex0Data[0]); + tex0.th = ZZOglGet_th_TexBitsExp(uNextTex0Data[0], uNextTex0Data[1]); + + tex0.tcc = ZZOglGet_tcc_TexBits(uNextTex0Data[1]); + tex0.tfx = ZZOglGet_tfx_TexBits(uNextTex0Data[1]); + + fiTexWidth[ictx] = (1 / 16.0f) / tex0.tw; + fiTexHeight[ictx] = (1 / 16.0f) / tex0.th; +} + +// Flush == draw on screen +// This function made VB state consistant before real Flush. +void VB::FlushTexData() +{ + GL_REPORT_ERRORD(); + + //assert(bNeedTexCheck); + if (bNeedTexCheck) + { + bNeedTexCheck = 0; + + u32 psm = ZZOglGet_psm_TexBitsFix(uNextTex0Data[0]); + + // don't update unless necessary + + if (ZZOglAllExceptClutIsSame(uCurTex0Data, uNextTex0Data)) + { + // Don't need to do anything if there is no clutting and VB tex data was not changed + if (!PSMT_ISCLUT(psm)) return; + + // have to write the CLUT again if only CLD was changed + if (ZZOglClutMinusCLDunchanged(uCurTex0Data, uNextTex0Data)) + { + FlushTexUnchangedClutDontUpdate(); + return; + } + + // Cld bit is 0 means that clut buffer stay unchanged + if (ZZOglGet_cld_TexBits(uNextTex0Data[1]) == 0) + { + FlushTexClutDontUpdate(); + return; + } + } + + // Made the full update + Flush(ictx); + + bVarsTexSync = false; + bTexConstsSync = false; + + uCurTex0Data[0] = uNextTex0Data[0]; + uCurTex0Data[1] = uNextTex0Data[1]; + + FlushTexSetNewVars(psm); + + if (PSMT_ISCLUT(psm)) CluttingForFlushedTex(&tex0, uNextTex0Data[1], ictx) ; + GL_REPORT_ERRORD(); + } +} diff --git a/plugins/zzogl-pg-cg/opengl/ZZoglVB.h b/plugins/zzogl-pg-cg/opengl/ZZoglVB.h new file mode 100644 index 000000000..890d98541 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZZoglVB.h @@ -0,0 +1,158 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +// Zerogs:VB implementation. +// VB stands for Visual Buffer, as I think + +#ifndef ZZOGLVB_H_INCLUDED +#define ZZOGLVB_H_INCLUDED + +#include "targets.h" + +extern const GLenum primtype[8]; + +class VB +{ + public: + VB(); + ~VB(); + + void Destroy(); + + inline bool CheckPrim() + { + static const int PRIMMASK = 0x0e; // for now ignore 0x10 (AA) + + if ((PRIMMASK & prim->_val) != (PRIMMASK & curprim._val) || primtype[prim->prim] != primtype[curprim.prim]) + return nCount > 0; + + return false; + } + + void SetCurrentPrim() + { + curprim._val = prim->_val; + curprim.prim = prim->prim; + } + + void CheckFrame(int tbp); + + // context specific state + Point offset; + Rect2 scissor; + tex0Info tex0; + tex1Info tex1; + miptbpInfo miptbp0; + miptbpInfo miptbp1; + alphaInfo alpha; + fbaInfo fba; + clampInfo clamp; + pixTest test; + u32 ptexClamp[2]; // textures for x and y dir region clamping + + void FlushTexData(); + inline int CheckFrameAddConstraints(int tbp); + inline void CheckScissors(int maxpos); + inline void CheckFrame32bitRes(int maxpos); + inline int FindMinimalMemoryConstrain(int tbp, int maxpos); + inline int FindZbufferMemoryConstrain(int tbp, int maxpos); + inline int FindMinimalHeightConstrain(int maxpos); + + inline int CheckFrameResolveRender(int tbp); + inline void CheckFrame16vs32Conversion(); + inline int CheckFrameResolveDepth(int tbp); + + inline void FlushTexUnchangedClutDontUpdate() ; + inline void FlushTexClutDontUpdate() ; + inline void FlushTexClutting() ; + inline void FlushTexSetNewVars(u32 psm) ; + + // Increase the size of pbuf + void IncreaseVertexBuffer() + { + assert(pBufferData != NULL); + nNumVertices *= 2; + VertexGPU* ptemp = (VertexGPU*)_aligned_malloc(sizeof(VertexGPU) * nNumVertices, 256); + memcpy_amd(ptemp, pBufferData, sizeof(VertexGPU) * nCount); + assert(nCount <= nNumVertices); + _aligned_free(pBufferData); + pBufferData = ptemp; + } + + void Init(int nVerts) + { + if (pBufferData == NULL && nVerts > 0) + { + pBufferData = (VertexGPU*)_aligned_malloc(sizeof(VertexGPU) * nVerts, 256); + nNumVertices = nVerts; + } + + nCount = 0; + } + + u8 bNeedFrameCheck; + u8 bNeedZCheck; + u8 bNeedTexCheck; + u8 dummy0; + + union + { + struct + { + u8 bTexConstsSync; // only pixel shader constants that context owns + u8 bVarsTexSync; // texture info + u8 bVarsSetTarg; + u8 dummy1; + }; + + u32 bSyncVars; + }; + + int ictx; + VertexGPU* pBufferData; // current allocated data + + int nNumVertices; // size of pBufferData in terms of VertexGPU objects + int nCount; + primInfo curprim; // the previous prim the current buffers are set to + + zbufInfo zbuf; + frameInfo gsfb; // the real info set by FRAME cmd + frameInfo frame; + int zprimmask; // zmask for incoming points + + union + { + u32 uCurTex0Data[2]; // current tex0 data + GIFRegTEX0 uCurTex0; + }; + u32 uNextTex0Data[2]; // tex0 data that has to be applied if bNeedTexCheck is 1 + + //int nFrameHeights[8]; // frame heights for the past frame changes + int nNextFrameHeight; + + CMemoryTarget* pmemtarg; // the current mem target set + CRenderTarget* prndr; + CDepthTarget* pdepth; + +}; + +// VB variables +extern VB vb[2]; + +#endif // ZZOGLVB_H_INCLUDED diff --git a/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/CMakeLists.txt b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/CMakeLists.txt new file mode 100644 index 000000000..9aa62a3bc --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/CMakeLists.txt @@ -0,0 +1,75 @@ +# Check that people use the good file +if(NOT TOP_CMAKE_WAS_SOURCED) + message(FATAL_ERROR " + You did not 'cmake' the good CMakeLists.txt file. Use the one in the top dir. + It is advice to delete all wrongly generated cmake stuff => CMakeFiles & CMakeCache.txt") +endif(NOT TOP_CMAKE_WAS_SOURCED) + + +# plugin name +set(Output zzogl-shader) + +set(CommonFlags + -pthread + -DZEROGS_SSE2 + -fno-strict-aliasing + -Wstrict-aliasing # Allow to track strict aliasing issue. + -Wunused-variable + -DNVIDIA_CG_API + ) + +set(OptimizationFlags + -O2 + -DNDEBUG + ) + +# Debug - Build +if(CMAKE_BUILD_TYPE STREQUAL Debug) + # add defines + add_definitions(${CommonFlags} -g -Wall -D_DEBUG) +endif(CMAKE_BUILD_TYPE STREQUAL Debug) + +# Devel - Build +if(CMAKE_BUILD_TYPE STREQUAL Devel) + # add defines + add_definitions(${CommonFlags} ${OptimizationFlags} -g -W -DZEROGS_DEVBUILD) +endif(CMAKE_BUILD_TYPE STREQUAL Devel) + +# Release - Build +if(CMAKE_BUILD_TYPE STREQUAL Release) + # add defines + add_definitions(${CommonFlags} ${OptimizationFlags} -W) +endif(CMAKE_BUILD_TYPE STREQUAL Release) + +include_directories(.) + +# add library +add_executable(${Output} zerogsshaders.cpp zpipe.cpp) + +# link target with zlib +target_link_libraries(${Output} ${ZLIB_LIBRARIES}) + +# link target with Cg +target_link_libraries(${Output} ${CG_LIBRARIES}) + +# link target with opengl +target_link_libraries(${Output} ${OPENGL_LIBRARIES}) + +# User flags options +if(NOT USER_CMAKE_LD_FLAGS STREQUAL "") + target_link_libraries(${Output} "${USER_CMAKE_LD_FLAGS}") +endif(NOT USER_CMAKE_LD_FLAGS STREQUAL "") + +# Now build the shader +add_custom_command(TARGET ${Output} POST_BUILD + COMMAND ${Output} ps2hw.fx ${CMAKE_CURRENT_BINARY_DIR}/ps2hw_cmake.dat + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/plugins/zzogl-pg/opengl + ) + +if(PACKAGE_MODE) + install(TARGETS ${Output} DESTINATION bin) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ps2hw_cmake.dat DESTINATION ${PLUGIN_DIR}) +else(PACKAGE_MODE) + install(TARGETS ${Output} DESTINATION ${CMAKE_SOURCE_DIR}/bin) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ps2hw_cmake.dat DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins) +endif(PACKAGE_MODE) diff --git a/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/ZeroGSShaders.vcproj b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/ZeroGSShaders.vcproj new file mode 100644 index 000000000..613909eab --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/ZeroGSShaders.vcproj @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/ZeroGSShaders_2005.sln b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/ZeroGSShaders_2005.sln new file mode 100644 index 000000000..45a5aa122 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/ZeroGSShaders_2005.sln @@ -0,0 +1,23 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZeroGSShaders", "ZeroGSShaders_2005.vcproj", "{811D47CC-E5F0-456A-918E-5908005E8FC0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release (to Public)|Win32 = Release (to Public)|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {811D47CC-E5F0-456A-918E-5908005E8FC0}.Debug|Win32.ActiveCfg = Debug|Win32 + {811D47CC-E5F0-456A-918E-5908005E8FC0}.Debug|Win32.Build.0 = Debug|Win32 + {811D47CC-E5F0-456A-918E-5908005E8FC0}.Release (to Public)|Win32.ActiveCfg = Release (to Public)|Win32 + {811D47CC-E5F0-456A-918E-5908005E8FC0}.Release (to Public)|Win32.Build.0 = Release (to Public)|Win32 + {811D47CC-E5F0-456A-918E-5908005E8FC0}.Release|Win32.ActiveCfg = Release|Win32 + {811D47CC-E5F0-456A-918E-5908005E8FC0}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/ZeroGSShaders_2005.vcproj b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/ZeroGSShaders_2005.vcproj new file mode 100644 index 000000000..0dfc9ad0c --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/ZeroGSShaders_2005.vcproj @@ -0,0 +1,335 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/copytozerogs.bat b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/copytozerogs.bat new file mode 100644 index 000000000..32c982060 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/copytozerogs.bat @@ -0,0 +1 @@ +copy .\Release\ZeroGSShaders.exe ..\ \ No newline at end of file diff --git a/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zerogsshaders.cpp b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zerogsshaders.cpp new file mode 100644 index 000000000..e9de68639 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zerogsshaders.cpp @@ -0,0 +1,362 @@ +/* ZZ Open GL graphics plugin + * Copyright on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define _CRT_SECURE_NO_DEPRECATE + +// Builds all possible shader files from ps2hw.fx and stores them in +// a preprocessed database +#include +#include +#include +#include + +#ifdef _WIN32 +# include +#else +# include +#endif + +#include "zpipe.h" + +#include +#include + +#define SAFE_RELEASE(x) { if( (x) != NULL ) { (x)->Release(); x = NULL; } } + +#include +#include + +using namespace std; + +#include "zerogsshaders.h" + +char* srcfilename = "ps2hw.fx"; +char* dstfilename = "ps2hw.dat"; + +#ifndef ArraySize +#define ArraySize(x) (sizeof(x) / sizeof((x)[0])) +#endif + +struct SHADERINFO +{ + int type; + vector buf; +}; + +map mapShaders; +CGcontext g_cgcontext; + +void LoadShader(int index, const char* pshader, CGprofile prof, vector& vargs, int context) +{ + vector realargs; + realargs.reserve(16); + realargs.resize(vargs.size()); + if( vargs.size() > 0 ) + memcpy(&realargs[0], &vargs[0], realargs.size() * sizeof(realargs[0])); + realargs.push_back(context ? "-Ictx1" : "-Ictx0"); + realargs.push_back(NULL); + + CGprogram prog = cgCreateProgramFromFile(g_cgcontext, CG_SOURCE, srcfilename, prof, pshader, &realargs[0]); + if( !cgIsProgram(prog) ) { + printf("Failed to load shader %s: \n%s\n", pshader, cgGetLastListing(g_cgcontext)); + return; + } + + if( mapShaders.find(index) != mapShaders.end() ) { + printf("error: two shaders share the same index %d\n", index); + exit(0); + } + + if( !cgIsProgramCompiled(prog) ) + cgCompileProgram(prog); + + const char* pstr = cgGetProgramString(prog, CG_COMPILED_PROGRAM); + + const char* pprog = strstr(pstr, "#program"); + if( pprog == NULL ) { + printf("program field not found!\n"); + return; + } + pprog += 9; + const char* progend = strchr(pprog, '\r'); + if( progend == NULL ) progend = strchr(pprog, '\n'); + + if( progend == NULL ) { + printf("prog end not found!\n"); + return; + } + + const char* defname = "main"; + + SHADERINFO info; + info.type = 0; + info.buf.resize(strlen(pstr)+1); + + // change the program name to main + memset(&info.buf[0], 0, info.buf.size()); + memcpy(&info.buf[0], pstr, pprog-pstr); + memcpy(&info.buf[pprog-pstr], defname, 4); + memcpy(&info.buf[pprog-pstr+4], progend, strlen(pstr)-(progend-pstr)); + + if( mapShaders.find(index) != mapShaders.end() ) + printf("same shader\n"); + assert( mapShaders.find(index) == mapShaders.end() ); + mapShaders[index] = info; + + cgDestroyProgram(prog); +} + +int main(int argc, char** argv) +{ + printf("usage: [src] [dst] [opts]\n"); + + if( argc >= 2 ) srcfilename = argv[1]; + if( argc >= 3 ) dstfilename = argv[2]; + + FILE* fsrc = fopen(srcfilename, "r"); + if( fsrc == NULL ) { + printf("cannot open %s\n", srcfilename); + return 0; + } + fclose(fsrc); + + g_cgcontext = cgCreateContext(); + if( !cgIsContext(g_cgcontext) ) { + printf("failed to create cg context\n"); + return -1; + } + + CGprofile cgvProf = CG_PROFILE_ARBVP1; + CGprofile cgfProf = CG_PROFILE_ARBFP1; + if( !cgGLIsProfileSupported(cgvProf) != CG_TRUE ) { + printf("arbvp1 not supported\n"); + return 0; + } + if( !cgGLIsProfileSupported(cgfProf) != CG_TRUE ) { + printf("arbfp1 not supported\n"); + return 0; + } + + cgGLEnableProfile(cgvProf); + cgGLEnableProfile(cgfProf); + cgGLSetOptimalOptions(cgvProf); + cgGLSetOptimalOptions(cgfProf); + + vector vmacros; + + LoadShader(SH_BITBLTVS, "BitBltVS", cgvProf, vmacros, 0); + LoadShader(SH_BITBLTPS, "BitBltPS", cgfProf, vmacros, 0); + LoadShader(SH_BITBLTDEPTHPS, "BitBltDepthPS", cgfProf, vmacros, 0); + LoadShader(SH_BITBLTDEPTHMRTPS, "BitBltDepthMRTPS", cgfProf, vmacros, 0); + LoadShader(SH_CRTCTARGPS, "CRTCTargPS", cgfProf, vmacros, 0); + LoadShader(SH_CRTCPS, "CRTCPS", cgfProf, vmacros, 0); + LoadShader(SH_CRTC_NEARESTPS, "CRTCPS_Nearest", cgfProf, vmacros, 0); + LoadShader(SH_CRTC24PS, "CRTC24PS", cgfProf, vmacros, 0); + LoadShader(SH_ZEROPS, "ZeroPS", cgfProf, vmacros, 0); + LoadShader(SH_BASETEXTUREPS, "BaseTexturePS", cgfProf, vmacros, 0); + LoadShader(SH_BITBLTAAPS, "BitBltPS", cgfProf, vmacros, 0); + LoadShader(SH_CRTCTARGINTERPS, "CRTCTargInterPS", cgfProf, vmacros, 0); + LoadShader(SH_CRTCINTERPS, "CRTCInterPS", cgfProf, vmacros, 0); + LoadShader(SH_CRTCINTER_NEARESTPS, "CRTCInterPS_Nearest", cgfProf, vmacros, 0); + LoadShader(SH_CRTC24INTERPS, "CRTC24InterPS", cgfProf, vmacros, 0); + LoadShader(SH_CONVERT16TO32PS, "Convert16to32PS", cgfProf, vmacros, 0); + LoadShader(SH_CONVERT32TO16PS, "Convert32to16PS", cgfProf, vmacros, 0); + + const int vsshaders[4] = { SH_REGULARVS, SH_TEXTUREVS, SH_REGULARFOGVS, SH_TEXTUREFOGVS }; + const char* pvsshaders[4] = { "RegularVS", "TextureVS", "RegularFogVS", "TextureFogVS" }; + + // load the texture shaders + char str[255], strdir[255]; + + strcpy(strdir, srcfilename); + int i = (int)strlen(strdir); + while(i > 0) { + if( strdir[i-1] == '/' || strdir[i-1] == '\\' ) + break; + --i; + } + + strdir[i] = 0; + + for(i = 0; i < ArraySize(vsshaders); ++i) { + for(int writedepth = 0; writedepth < 2; ++writedepth ) { + + if( writedepth ) vmacros.push_back("-DWRITE_DEPTH"); + LoadShader(vsshaders[i]|(writedepth?SH_WRITEDEPTH:0), pvsshaders[i], cgvProf, vmacros, 0); + LoadShader(vsshaders[i]|(writedepth?SH_WRITEDEPTH:0)|SH_CONTEXT1, pvsshaders[i], cgvProf, vmacros, 1); + if( writedepth ) vmacros.pop_back(); + } + } + + const int psshaders[2] = { SH_REGULARPS, SH_REGULARFOGPS }; + const char* ppsshaders[2] = { "RegularPS", "RegularFogPS" }; + + for(i = 0; i < ArraySize(psshaders); ++i) { + for(int writedepth = 0; writedepth < 2; ++writedepth ) { + if( writedepth ) vmacros.push_back("-DWRITE_DEPTH"); + LoadShader(psshaders[i]|(writedepth?SH_WRITEDEPTH:0), ppsshaders[i], cgfProf, vmacros, 0); + if( writedepth ) vmacros.pop_back(); + } + } + + printf("creating shaders, note that ctx0/ps2hw_ctx.fx, and ctx1/ps2hw_ctx.fx are required\n"); + vmacros.resize(0); + + for(int texwrap = 0; texwrap < NUM_TEXWRAPS; ++texwrap ) { + + if( g_pPsTexWrap[texwrap] != NULL ) + vmacros.push_back(g_pPsTexWrap[texwrap]); + + for(int context = 0; context < 2; ++context) { + + for(int texfilter = 0; texfilter < NUM_FILTERS; ++texfilter) { + for(int fog = 0; fog < 2; ++fog ) { + for(int writedepth = 0; writedepth < 2; ++writedepth ) { + + if( writedepth ) + vmacros.push_back("-DWRITE_DEPTH"); + + for(int testaem = 0; testaem < 2; ++testaem ) { + + if( testaem ) + vmacros.push_back("-DTEST_AEM"); + + for(int exactcolor = 0; exactcolor < 2; ++exactcolor ) { + + if( exactcolor ) + vmacros.push_back("-DEXACT_COLOR"); + + // 32 + sprintf(str, "Texture%s%d_32PS", fog?"Fog":"", texfilter); + + vmacros.push_back("-DACCURATE_DECOMPRESSION"); + LoadShader(GET_SHADER_INDEX(0, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_ACCURATE), str, cgfProf, vmacros, context); + vmacros.pop_back(); + + LoadShader(GET_SHADER_INDEX(0, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, 0), str, cgfProf, vmacros, context); + + if( texfilter == 0 ) { + // tex32 + sprintf(str, "Texture%s%d_tex32PS", fog?"Fog":"", texfilter); + +// vmacros.push_back("-DACCURATE_DECOMPRESSION"); +// LoadShader(GET_SHADER_INDEX(1, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_ACCURATE), str, cgfProf, vmacros, context); +// vmacros.pop_back(); + + LoadShader(GET_SHADER_INDEX(1, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, 0), str, cgfProf, vmacros, context); + + // clut32 + sprintf(str, "Texture%s%d_clut32PS", fog?"Fog":"", texfilter); + +// vmacros.push_back("-DACCURATE_DECOMPRESSION"); +// LoadShader(GET_SHADER_INDEX(2, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_ACCURATE), str, cgfProf, vmacros, context); +// vmacros.pop_back(); + + LoadShader(GET_SHADER_INDEX(2, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, 0), str, cgfProf, vmacros, context); + + // tex32to16 + sprintf(str, "Texture%s%d_tex32to16PS", fog?"Fog":"", texfilter); + +// vmacros.push_back("-DACCURATE_DECOMPRESSION"); +// LoadShader(GET_SHADER_INDEX(3, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_ACCURATE), str, cgfProf, vmacros, context); +// vmacros.pop_back(); + + LoadShader(GET_SHADER_INDEX(3, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, 0), str, cgfProf, vmacros, context); + + // tex16to8h + sprintf(str, "Texture%s%d_tex16to8hPS", fog?"Fog":"", texfilter); + +// vmacros.push_back("-DACCURATE_DECOMPRESSION"); +// LoadShader(GET_SHADER_INDEX(4, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_ACCURATE), str, cgfProf, vmacros, context); +// vmacros.pop_back(); + + LoadShader(GET_SHADER_INDEX(4, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, 0), str, cgfProf, vmacros, context); + } + + if( exactcolor ) + vmacros.pop_back(); + } + + if( testaem ) + vmacros.pop_back(); + } + + if( writedepth ) + vmacros.pop_back(); + } + } + } + } + + if( g_pPsTexWrap[texwrap] != NULL ) + vmacros.pop_back(); + } + + if( vmacros.size() != 0 ) + printf("error with macros!\n"); + + // create the database + + int num = (int)mapShaders.size(); + + // first compress + vector buffer; + buffer.reserve(10000000); // 10mb + buffer.resize(sizeof(SHADERHEADER)*num); + + i = 0; + for(map::iterator it = mapShaders.begin(); it != mapShaders.end(); ++it, ++i) { + SHADERHEADER h; + h.index = it->first | it->second.type; + h.offset = (int)buffer.size(); + h.size = (int)it->second.buf.size(); + + memcpy(&buffer[0] + i*sizeof(SHADERHEADER), &h, sizeof(SHADERHEADER)); + + size_t cur = buffer.size(); + buffer.resize(cur + it->second.buf.size()); + memcpy(&buffer[cur], &it->second.buf[0], it->second.buf.size()); + } + + int compressed_size; + int real_size = (int)buffer.size(); + vector dst; + dst.resize(buffer.size()); + def(&buffer[0], &dst[0], (int)buffer.size(), &compressed_size); + + // write to file + // fmt: num shaders, size of compressed, compressed data + FILE* fdst = fopen(dstfilename, "wb"); + if( fdst == NULL ) { + printf("failed to open %s\n", dstfilename); + return 0; + } + + fwrite(&num, 4, 1, fdst); + fwrite(&compressed_size, 4, 1, fdst); + fwrite(&real_size, 4, 1, fdst); + fwrite(&dst[0], compressed_size, 1, fdst); + + fclose(fdst); + + printf("wrote %s\n", dstfilename); + + cgDestroyContext(g_cgcontext); + + return 0; +} diff --git a/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zerogsshaders.h b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zerogsshaders.h new file mode 100644 index 000000000..388bd1c7a --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zerogsshaders.h @@ -0,0 +1,120 @@ +/* ZZ Open GL graphics plugin + * Copyright on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __ZEROGS_SHADERS_H__ +#define __ZEROGS_SHADERS_H__ + +#include +#include +#include "PS2Edefs.h" + +#include +#include + +#define ZZshProgram CGprogram +#define ZZshContext CGcontext + +using namespace std; + +#define NUM_FILTERS 2 // texture filtering +#define NUM_TYPES 5 // types of texture read modes +#define NUM_TEXWRAPS 4 // texture wrapping + +#define SHADER_REDUCED 1 // equivalent to ps2.0 +#define SHADER_ACCURATE 2 // for older cards with less accurate math (ps2.x+) + +#define NUM_SHADERS (NUM_FILTERS*NUM_TYPES*NUM_TEXWRAPS*32) // # shaders for a given ps + +const static char* g_pPsTexWrap[] = { "-DREPEAT", "-DCLAMP", "-DREGION_REPEAT", NULL }; +const static char* g_pTexTypes[] = { "32", "tex32", "clut32", "tex32to16", "tex16to8h" }; + +#define TEXWRAP_REPEAT 0 +#define TEXWRAP_CLAMP 1 +#define TEXWRAP_REGION_REPEAT 2 +#define TEXWRAP_REPEAT_CLAMP 3 + +static __forceinline int GET_SHADER_INDEX(int type, int texfilter, int texwrap, int fog, int writedepth, int testaem, int exactcolor, int context, int ps) +{ + return type + texfilter*NUM_TYPES + NUM_FILTERS*NUM_TYPES*texwrap + NUM_TEXWRAPS*NUM_FILTERS*NUM_TYPES*(fog+2*writedepth+4*testaem+8*exactcolor+16*context+32*ps); +} + +extern ZZshContext g_cgcontext; + +static __forceinline CGprogram LoadShaderFromType(const char* srcdir, const char* srcfile, int type, int texfilter, int texwrap, int fog, int writedepth, int testaem, int exactcolor, int ps, int context) +{ + assert( texwrap < NUM_TEXWRAPS); + assert( type < NUM_TYPES ); + + char str[255], strctx[255]; + sprintf(str, "Texture%s%d_%sPS", fog?"Fog":"", texfilter, g_pTexTypes[type]); + sprintf(strctx, "-I%s%s", srcdir, context?"ctx1":"ctx0"); + + vector macros; + macros.push_back(strctx); +#ifdef _DEBUG + macros.push_back("-bestprecision"); +#endif + if( g_pPsTexWrap[texwrap] != NULL ) macros.push_back(g_pPsTexWrap[texwrap]); + if( writedepth ) macros.push_back("-DWRITE_DEPTH"); + if( testaem ) macros.push_back("-DTEST_AEM"); + if( exactcolor ) macros.push_back("-DEXACT_COLOR"); + if( ps & SHADER_ACCURATE ) macros.push_back("-DACCURATE_DECOMPRESSION"); + macros.push_back(NULL); + + ZZshProgram prog = cgCreateProgramFromFile(g_cgcontext, CG_SOURCE, srcfile, CG_PROFILE_ARBFP1, str, ¯os[0]); + if( !cgIsProgram(prog) ) { + printf("Failed to load shader %s: \n%s\n", str, cgGetLastListing(g_cgcontext)); + return NULL; + } + + return prog; +} + +struct SHADERHEADER +{ + unsigned int index, offset, size; // if highest bit of index is set, pixel shader +}; + +#define SH_WRITEDEPTH 0x2000 // depth is written +#define SH_CONTEXT1 0x1000 // context1 is used + +#define SH_REGULARVS 0x8000 +#define SH_TEXTUREVS 0x8001 +#define SH_REGULARFOGVS 0x8002 +#define SH_TEXTUREFOGVS 0x8003 +#define SH_REGULARPS 0x8004 +#define SH_REGULARFOGPS 0x8005 +#define SH_BITBLTVS 0x8006 +#define SH_BITBLTPS 0x8007 +#define SH_BITBLTDEPTHPS 0x8009 +#define SH_CRTCTARGPS 0x800a +#define SH_CRTCPS 0x800b +#define SH_CRTC24PS 0x800c +#define SH_ZEROPS 0x800e +#define SH_BASETEXTUREPS 0x800f +#define SH_BITBLTAAPS 0x8010 +#define SH_CRTCTARGINTERPS 0x8012 +#define SH_CRTCINTERPS 0x8013 +#define SH_CRTC24INTERPS 0x8014 +#define SH_BITBLTDEPTHMRTPS 0x8016 +#define SH_CONVERT16TO32PS 0x8020 +#define SH_CONVERT32TO16PS 0x8021 +#define SH_CRTC_NEARESTPS 0x8022 +#define SH_CRTCINTER_NEARESTPS 0x8023 + +#endif diff --git a/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/crc32.h b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/crc32.h new file mode 100644 index 000000000..8053b6117 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/deflate.h b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/deflate.h new file mode 100644 index 000000000..804d3abe8 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/deflate.h @@ -0,0 +1,331 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2004 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: deflate.h,v 1.2 2006/03/02 00:10:34 zerocool Exp $ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define EXTRA_STATE 69 +#define NAME_STATE 73 +#define COMMENT_STATE 91 +#define HCRC_STATE 103 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + uInt pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + gz_headerp gzhead; /* gzip header information to write */ + uInt gzindex; /* where in extra, name, or comment */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/inffast.h b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/inffast.h new file mode 100644 index 000000000..1e88d2d97 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/inffixed.h b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/inffixed.h new file mode 100644 index 000000000..75ed4b597 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/inflate.h b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/inflate.h new file mode 100644 index 000000000..07bd3e78a --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/inflate.h @@ -0,0 +1,115 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN, /* i: waiting for length/lit code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD or MEM mode -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME + NAME -> COMMENT -> HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or CHECK + STORED -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; diff --git a/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/inftrees.h b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/inftrees.h new file mode 100644 index 000000000..b1104c87e --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/inftrees.h @@ -0,0 +1,55 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1444 code structures (852 for length/literals + and 592 for distances, the latter actually the result of an + exhaustive search). The true maximum is not known, but the value + below is more than safe. */ +#define ENOUGH 2048 +#define MAXD 592 + +/* Type of code to build for inftable() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +extern int inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/trees.h b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/trees.h new file mode 100644 index 000000000..72facf900 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/zconf.h b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/zconf.h new file mode 100644 index 000000000..5bdcd2c56 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/zconf.h @@ -0,0 +1,332 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zconf.h,v 1.2 2006/03/02 00:10:34 zerocool Exp $ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define deflatePrime z_deflatePrime +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table +# define zError z_zError + +# define alloc_func z_alloc_func +# define free_func z_free_func +# define in_func z_in_func +# define out_func z_out_func +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/zconf.in.h b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/zconf.in.h new file mode 100644 index 000000000..f7176a3b6 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/zconf.in.h @@ -0,0 +1,332 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zconf.in.h,v 1.2 2006/03/02 00:10:34 zerocool Exp $ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define deflatePrime z_deflatePrime +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table +# define zError z_zError + +# define alloc_func z_alloc_func +# define free_func z_free_func +# define in_func z_in_func +# define out_func z_out_func +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/zlib.h b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/zlib.h new file mode 100644 index 000000000..022817927 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/zlib.h @@ -0,0 +1,1357 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.3, July 18th, 2005 + + Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.3" +#define ZLIB_VERNUM 0x1230 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumualte before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it gets to the next deflate block boundary. When decoding the + zlib or gzip format, this will cause inflate() to return immediately after + the header and before the first block. When doing a raw inflate, inflate() + will go ahead and process the first block, and will return when it gets to + the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. Z_FIXED prevents the + use of dynamic Huffman codes, allowing for a simpler decoder for special + applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. In addition, the + current implementation of deflate will use at most the window size minus + 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is + a crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg + is set to null if there is no error message. inflateInit2 does not perform + any decompression apart from reading the zlib header if present: this will + be done by inflate(). (So next_in and avail_in may be modified, but next_out + and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK can be used to + force inflate() to return immediately after header processing is complete + and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When + any of extra, name, or comment are not Z_NULL and the respective field is + not present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns 1 if file is being read directly without decompression, otherwise + zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); +/* + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is NULL, this function returns the required initial + value for the for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + +/* + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/zutil.h b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/zutil.h new file mode 100644 index 000000000..ecfeb756e --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zlib/zutil.h @@ -0,0 +1,269 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: zutil.h,v 1.2 2006/03/02 00:10:34 zerocool Exp $ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#define ZLIB_INTERNAL +#include "zlib.h" + +#ifdef STDC +# ifndef _WIN32_WCE +# include +# endif +# include +# include +#endif +#ifdef NO_ERRNO_H +# ifdef _WIN32_WCE + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. We rename it to + * avoid conflict with other libraries that use the same workaround. + */ +# define errno z_errno +# endif + extern int errno; +#else +# ifndef _WIN32_WCE +# include +# endif +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +# ifdef M_I86 + #include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# define vsnprintf _vsnprintf +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif +#ifdef VMS +# define NO_vsnprintf +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ diff --git a/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zpipe.cpp b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zpipe.cpp new file mode 100644 index 000000000..f4e946849 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zpipe.cpp @@ -0,0 +1,122 @@ +/* The file is based of zpipe.c + minor rename and minor adaptation + * + * zpipe.c: example of proper use of zlib's inflate() and deflate() + * Not copyrighted -- provided to the public domain + * Version 1.4 11 December 2005 Mark Adler + */ + +// zpipe.cpp : Defines the entry point for the console application. +// + +#include + +#include +#include +#include + +//#define ZLIB_WINAPI +#include + +int def(char *src, char *dst, int bytes_to_compress, int *bytes_after_compressed) ; +int inf(char *src, char *dst, int bytes_to_decompress, int maximum_after_decompress) ; + +int def(char *src, char *dst, int bytes_to_compress, int *bytes_after_compressed) +{ + z_stream strm; + + int ret;//, flush; + unsigned have; + + /* allocate deflate state */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + ret = deflateInit(&strm, Z_DEFAULT_COMPRESSION) ; + if (ret != Z_OK) + return ret; + + /* compress */ + strm.avail_in = bytes_to_compress ; + strm.avail_out = bytes_to_compress ; + strm.next_in = (Bytef *)src ; + strm.next_out = (Bytef *)dst ; + + ret = deflate(&strm, Z_FINISH) ; + have = bytes_to_compress - strm.avail_out ; + *bytes_after_compressed = have ; + + assert(ret == Z_STREAM_END); /* stream will be complete */ + + /* clean up and return */ + (void)deflateEnd(&strm); + return Z_OK; +} + +int inf(char *src, char *dst, int bytes_to_decompress, int maximum_after_decompress, int* outbytes) +{ + z_stream strm; + + int ret; + //unsigned have; + + /* allocate inflate state */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit(&strm); + if (ret != Z_OK) + return ret; + + /* decompress */ + strm.avail_in = bytes_to_decompress ; + strm.next_in = (Bytef *)src ; + strm.next_out = (Bytef *)dst ; + strm.avail_out = maximum_after_decompress ; + + ret = inflate(&strm, Z_NO_FLUSH) ; + assert(ret != Z_STREAM_ERROR); /* state not clobbered */ + switch (ret) { + case Z_NEED_DICT: + ret = Z_DATA_ERROR; /* and fall through */ + case Z_DATA_ERROR: + case Z_MEM_ERROR: + (void)inflateEnd(&strm); + return ret; + } + + assert(strm.avail_in == 0); /* all input will be used */ + + if( outbytes != NULL ) + *outbytes = strm.total_out; + + /* clean up and return */ + (void)inflateEnd(&strm); + return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR; +} + +/* report a zlib or i/o error */ +void zerr(int ret) +{ + fputs("zpipe: ", stderr); + switch (ret) { + case Z_ERRNO: + if (ferror(stdin)) + fputs("error reading stdin\n", stderr); + if (ferror(stdout)) + fputs("error writing stdout\n", stderr); + break; + case Z_STREAM_ERROR: + fputs("invalid compression level\n", stderr); + break; + case Z_DATA_ERROR: + fputs("invalid or incomplete deflate data\n", stderr); + break; + case Z_MEM_ERROR: + fputs("out of memory\n", stderr); + break; + case Z_VERSION_ERROR: + fputs("zlib version mismatch!\n", stderr); + } +} diff --git a/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zpipe.h b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zpipe.h new file mode 100644 index 000000000..6562c7b5d --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ZeroGSShaders/zpipe.h @@ -0,0 +1,26 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef zpipe_h +#define zpipe_h + +int def(char *src, char *dst, int bytes_to_compress, int *bytes_after_compressed) ; +int inf(char *src, char *dst, int bytes_to_decompress, int maximum_after_decompress, int* outbytes); + +#endif diff --git a/plugins/zzogl-pg-cg/opengl/buildshaders.bat b/plugins/zzogl-pg-cg/opengl/buildshaders.bat new file mode 100644 index 000000000..a2ceb68b6 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/buildshaders.bat @@ -0,0 +1,3 @@ +ZeroGSShaders.exe ps2hw.fx ps2hw.dat +del Win32\ps2hw.dat Win32\Release\*.res Win32\Debug\*.res +move /y ps2hw.dat Win32\ps2hw.dat \ No newline at end of file diff --git a/plugins/zzogl-pg-cg/opengl/common.h b/plugins/zzogl-pg-cg/opengl/common.h new file mode 100644 index 000000000..5202a6350 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/common.h @@ -0,0 +1,1164 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2005-2008 Zerofrog's ZeroGS KOSMOS + * + * Based on the ffmpeg program, (c)2006 Michael Niedermayer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file common.h + * common internal api header. + */ + +#ifndef COMMON_H +#define COMMON_H + +#if defined(WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__) +# define CONFIG_WIN32 +#endif + +//#define ALT_BITSTREAM_WRITER +//#define ALIGNED_BITSTREAM_WRITER + +#define ALT_BITSTREAM_READER +//#define LIBMPEG2_BITSTREAM_READER +//#define A32_BITSTREAM_READER +#define LIBMPEG2_BITSTREAM_READER_HACK //add BERO + +#ifdef HAVE_AV_CONFIG_H +/* only include the following when compiling package */ +# include "config.h" + +# include +# include +# include +# include +# ifndef __BEOS__ +# include +# else +# include "berrno.h" +# endif +# include + +# ifndef ENODATA +# define ENODATA 61 +# endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#include +#ifndef offsetof +# define offsetof(T,F) ((unsigned int)((char *)&((T *)0)->F)) +#endif + +#define AVOPTION_CODEC_BOOL(name, help, field) \ + { name, help, offsetof(AVCodecContext, field), FF_OPT_TYPE_BOOL } +#define AVOPTION_CODEC_DOUBLE(name, help, field, minv, maxv, defval) \ + { name, help, offsetof(AVCodecContext, field), FF_OPT_TYPE_DOUBLE, minv, maxv, defval } +#define AVOPTION_CODEC_FLAG(name, help, field, flag, defval) \ + { name, help, offsetof(AVCodecContext, field), FF_OPT_TYPE_FLAG, flag, 0, defval } +#define AVOPTION_CODEC_INT(name, help, field, minv, maxv, defval) \ + { name, help, offsetof(AVCodecContext, field), FF_OPT_TYPE_INT, minv, maxv, defval } +#define AVOPTION_CODEC_STRING(name, help, field, str, val) \ + { name, help, offsetof(AVCodecContext, field), FF_OPT_TYPE_STRING, .defval = val, .defstr = str } +#define AVOPTION_CODEC_RCOVERRIDE(name, help, field) \ + { name, help, offsetof(AVCodecContext, field), FF_OPT_TYPE_RCOVERRIDE, .defval = 0, .defstr = NULL } +#define AVOPTION_SUB(ptr) { .name = NULL, .help = (const char*)ptr } +#define AVOPTION_END() AVOPTION_SUB(NULL) + +struct AVOption; +#ifdef HAVE_MMX +extern const struct AVOption avoptions_common[3 + 5]; +#else +extern const struct AVOption avoptions_common[3]; +#endif +extern const struct AVOption avoptions_workaround_bug[11]; + +#endif /* HAVE_AV_CONFIG_H */ + +/* Suppress restrict if it was not defined in config.h. */ +#ifndef restrict +# define restrict +#endif + +#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0) +# define always_inline __attribute__((always_inline)) inline +#else +# define always_inline inline +#endif + +#ifdef CONFIG_WIN32 + +/* windows */ + +typedef unsigned short uint16_t; +typedef signed short int16_t; +typedef unsigned char uint8_t; +typedef unsigned int uint32_t; +typedef unsigned __int64 uint64_t; +typedef signed char int8_t; +typedef signed int int32_t; +typedef signed __int64 int64_t; + +# ifndef __MINGW32__ +# define int64_t_C(c) (c ## i64) +# define uint64_t_C(c) (c ## i64) + +# define inline __inline + +# else +# define int64_t_C(c) (c ## LL) +# define uint64_t_C(c) (c ## ULL) +# endif /* __MINGW32__ */ + +# ifdef _DEBUG +# define DEBUG +# endif + +# define snprintf _snprintf +# define vsnprintf _vsnprintf + +/* CONFIG_WIN32 end */ +#elif defined (CONFIG_OS2) +/* OS/2 EMX */ + +#include + +#ifndef int64_t_C +#define int64_t_C(c) (c ## LL) +#define uint64_t_C(c) (c ## ULL) +#endif + +#ifdef HAVE_AV_CONFIG_H + +#ifdef USE_FASTMEMCPY +#include "fastmemcpy.h" +#endif + +#include + +#endif /* HAVE_AV_CONFIG_H */ + +/* CONFIG_OS2 end */ +#else + +/* unix */ + +#include + +#ifndef int64_t_C +#define int64_t_C(c) (c ## LL) +#define uint64_t_C(c) (c ## ULL) +#endif + +#ifdef HAVE_AV_CONFIG_H + +# ifdef USE_FASTMEMCPY +# include "fastmemcpy.h" +# endif +# endif /* HAVE_AV_CONFIG_H */ + +#endif /* !CONFIG_WIN32 && !CONFIG_OS2 */ + +#ifdef HAVE_AV_CONFIG_H + +# include "bswap.h" + +# if defined(__MINGW32__) || defined(__CYGWIN__) || \ + defined(__OS2__) || (defined (__OpenBSD__) && !defined(__ELF__)) +# define MANGLE(a) "_" #a +# else +# define MANGLE(a) #a +# endif + +/* debug stuff */ + +# ifndef DEBUG +# define NDEBUG +# endif +# include + +/* dprintf macros */ +# if defined(CONFIG_WIN32) && !defined(__MINGW32__) + +inline void dprintf(const char* fmt,...) {} + +# else + +# ifdef DEBUG +# define dprintf(fmt,args...) printf(fmt, ## args) +# else +# define dprintf(fmt,args...) +# endif + +# endif /* !CONFIG_WIN32 */ + +# define av_abort() do { fprintf(stderr, "Abort at %s:%d\n", __FILE__, __LINE__); abort(); } while (0) + +//rounded divison & shift +#define RSHIFT(a,b) ((a) > 0 ? ((a) + (1<<((b)-1)))>>(b) : ((a) + (1<<((b)-1))-1)>>(b)) +/* assume b>0 */ +#define ROUNDED_DIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b)) +#define ABS(a) ((a) >= 0 ? (a) : (-(a))) + +#define FFMAX(a,b) ((a) > (b) ? (a) : (b)) +#define FFMIN(a,b) ((a) > (b) ? (b) : (a)) + +extern const uint32_t inverse[256]; + +#ifdef ARCH_X86 +# define FASTDIV(a,b) \ + ({\ + int ret,dmy;\ + asm volatile(\ + "mull %3"\ + :"=d"(ret),"=a"(dmy)\ + :"1"(a),"g"(inverse[b])\ + );\ + ret;\ + }) +#elif defined(CONFIG_FASTDIV) +# define FASTDIV(a,b) ((uint32_t)((((uint64_t)a)*inverse[b])>>32)) +#else +# define FASTDIV(a,b) ((a)/(b)) +#endif + +#ifdef ARCH_X86 +// avoid +32 for shift optimization (gcc should do that ...) +static inline int32_t NEG_SSR32( int32_t a, int8_t s){ + asm ("sarl %1, %0\n\t" + : "+r" (a) + : "ic" ((uint8_t)(-s)) + ); + return a; +} +static inline uint32_t NEG_USR32(uint32_t a, int8_t s){ + asm ("shrl %1, %0\n\t" + : "+r" (a) + : "ic" ((uint8_t)(-s)) + ); + return a; +} +#else +# define NEG_SSR32(a,s) ((( int32_t)(a))>>(32-(s))) +# define NEG_USR32(a,s) (((uint32_t)(a))>>(32-(s))) +#endif + +/* bit output */ + +struct PutBitContext; + +typedef void (*WriteDataFunc)(void *, uint8_t *, int); + +typedef struct PutBitContext { +#ifdef ALT_BITSTREAM_WRITER + uint8_t *buf, *buf_end; + int index; +#else + uint32_t bit_buf; + int bit_left; + uint8_t *buf, *buf_ptr, *buf_end; +#endif + int64_t data_out_size; /* in bytes */ +} PutBitContext; + +void init_put_bits(PutBitContext *s, + uint8_t *buffer, int buffer_size, + void *opaque, + void (*write_data)(void *, uint8_t *, int)); + +int64_t get_bit_count(PutBitContext *s); /* XXX: change function name */ +void align_put_bits(PutBitContext *s); +void flush_put_bits(PutBitContext *s); +void put_string(PutBitContext * pbc, char *s); + +/* bit input */ + +typedef struct GetBitContext { + const uint8_t *buffer, *buffer_end; +#ifdef ALT_BITSTREAM_READER + int index; +#elif defined LIBMPEG2_BITSTREAM_READER + uint8_t *buffer_ptr; + uint32_t cache; + int bit_count; +#elif defined A32_BITSTREAM_READER + uint32_t *buffer_ptr; + uint32_t cache0; + uint32_t cache1; + int bit_count; +#endif + int size_in_bits; +} GetBitContext; + +static inline int get_bits_count(GetBitContext *s); + +#define VLC_TYPE int16_t + +typedef struct VLC { + int bits; + VLC_TYPE (*table)[2]; ///< code, bits + int table_size, table_allocated; +} VLC; + +typedef struct RL_VLC_ELEM { + int16_t level; + int8_t len; + uint8_t run; +} RL_VLC_ELEM; + +#ifdef ARCH_SPARC64 +#define UNALIGNED_STORES_ARE_BAD +#endif + +/* used to avoid missaligned exceptions on some archs (alpha, ...) */ +#ifdef ARCH_X86 +# define unaligned32(a) (*(uint32_t*)(a)) +#else +# ifdef __GNUC__ +static inline uint32_t unaligned32(const void *v) { + struct Unaligned { + uint32_t i; + } __attribute__((packed)); + + return ((const struct Unaligned *) v)->i; +} +# elif defined(__DECC) +static inline uint32_t unaligned32(const void *v) { + return *(const __unaligned uint32_t *) v; +} +# else +static inline uint32_t unaligned32(const void *v) { + return *(const uint32_t *) v; +} +# endif +#endif //!ARCH_X86 + +#ifndef ALT_BITSTREAM_WRITER +static inline void put_bits(PutBitContext *s, int n, unsigned int value) +{ + unsigned int bit_buf; + int bit_left; + +#ifdef STATS + st_out_bit_counts[st_current_index] += n; +#endif + // ZZLog::Debug_Log("put_bits=%d %x.", n, value); + assert(n == 32 || value < (1U << n)); + + bit_buf = s->bit_buf; + bit_left = s->bit_left; + + // ZZLog::Debug_Log("n=%d value=%x cnt=%d buf=%x.", n, value, bit_cnt, bit_buf); + /* XXX: optimize */ + if (n < bit_left) { + bit_buf = (bit_buf<> (n - bit_left); +#ifdef UNALIGNED_STORES_ARE_BAD + if (3 & (int) s->buf_ptr) { + s->buf_ptr[0] = bit_buf >> 24; + s->buf_ptr[1] = bit_buf >> 16; + s->buf_ptr[2] = bit_buf >> 8; + s->buf_ptr[3] = bit_buf ; + } else +#endif + *(uint32_t *)s->buf_ptr = be2me_32(bit_buf); + //ZZLog::Debug_Log("bitbuf = %08x.", bit_buf); + s->buf_ptr+=4; + bit_left+=32 - n; + bit_buf = value; + } + + s->bit_buf = bit_buf; + s->bit_left = bit_left; +} +#endif + + +#ifdef ALT_BITSTREAM_WRITER +static inline void put_bits(PutBitContext *s, int n, unsigned int value) +{ +# ifdef ALIGNED_BITSTREAM_WRITER +# ifdef ARCH_X86 + asm volatile( + "movl %0, %%ecx \n\t" + "xorl %%eax, %%eax \n\t" + "shrdl %%cl, %1, %%eax \n\t" + "shrl %%cl, %1 \n\t" + "movl %0, %%ecx \n\t" + "shrl $3, %%ecx \n\t" + "andl $0xFFFFFFFC, %%ecx \n\t" + "bswapl %1 \n\t" + "orl %1, (%2, %%ecx) \n\t" + "bswapl %%eax \n\t" + "addl %3, %0 \n\t" + "movl %%eax, 4(%2, %%ecx) \n\t" + : "=&r" (s->index), "=&r" (value) + : "r" (s->buf), "r" (n), "0" (s->index), "1" (value<<(-n)) + : "%eax", "%ecx" + ); +# else + int index= s->index; + uint32_t *ptr= ((uint32_t *)s->buf)+(index>>5); + + value<<= 32-n; + + ptr[0] |= be2me_32(value>>(index&31)); + ptr[1] = be2me_32(value<<(32-(index&31))); +// if (n > 24) ZZLog::Debug_Log("%d %d", n, value); + index+= n; + s->index= index; +# endif +# else //ALIGNED_BITSTREAM_WRITER +# ifdef ARCH_X86 + asm volatile( + "movl $7, %%ecx \n\t" + "andl %0, %%ecx \n\t" + "addl %3, %%ecx \n\t" + "negl %%ecx \n\t" + "shll %%cl, %1 \n\t" + "bswapl %1 \n\t" + "movl %0, %%ecx \n\t" + "shrl $3, %%ecx \n\t" + "orl %1, (%%ecx, %2) \n\t" + "addl %3, %0 \n\t" + "movl $0, 4(%%ecx, %2) \n\t" + : "=&r" (s->index), "=&r" (value) + : "r" (s->buf), "r" (n), "0" (s->index), "1" (value) + : "%ecx" + ); +# else + int index= s->index; + uint32_t *ptr= (uint32_t*)(((uint8_t *)s->buf)+(index>>3)); + + ptr[0] |= be2me_32(value<<(32-n-(index&7) )); + ptr[1] = 0; +// if (n > 24) ZZLog::Debug_Log("%d %d", n, value); + index+= n; + s->index= index; +# endif +# endif //!ALIGNED_BITSTREAM_WRITER +} +#endif + + +static inline uint8_t* pbBufPtr(PutBitContext *s) +{ +#ifdef ALT_BITSTREAM_WRITER + return s->buf + (s->index>>3); +#else + return s->buf_ptr; +#endif +} + +/* Bitstream reader API docs: +name + abritary name which is used as prefix for the internal variables + +gb + getbitcontext + +OPEN_READER(name, gb) + loads gb into local variables + +CLOSE_READER(name, gb) + stores local vars in gb + +UPDATE_CACHE(name, gb) + refills the internal cache from the bitstream + after this call at least MIN_CACHE_BITS will be available, + +GET_CACHE(name, gb) + will output the contents of the internal cache, next bit is MSB of 32 or 64 bit (FIXME 64bit) + +SHOW_UBITS(name, gb, num) + will return the nest num bits + +SHOW_SBITS(name, gb, num) + will return the nest num bits and do sign extension + +SKIP_BITS(name, gb, num) + will skip over the next num bits + note, this is equinvalent to SKIP_CACHE; SKIP_COUNTER + +SKIP_CACHE(name, gb, num) + will remove the next num bits from the cache (note SKIP_COUNTER MUST be called before UPDATE_CACHE / CLOSE_READER) + +SKIP_COUNTER(name, gb, num) + will increment the internal bit counter (see SKIP_CACHE & SKIP_BITS) + +LAST_SKIP_CACHE(name, gb, num) + will remove the next num bits from the cache if it is needed for UPDATE_CACHE otherwise it will do nothing + +LAST_SKIP_BITS(name, gb, num) + is equinvalent to SKIP_LAST_CACHE; SKIP_COUNTER + +for examples see get_bits, show_bits, skip_bits, get_vlc +*/ + +static inline int unaligned32_be(const void *v) +{ +#ifdef CONFIG_ALIGN + const uint8_t *p=v; + return (((p[0]<<8) | p[1])<<16) | (p[2]<<8) | (p[3]); +#else + return be2me_32( unaligned32(v)); //original +#endif +} + +#ifdef ALT_BITSTREAM_READER +# define MIN_CACHE_BITS 25 + +# define OPEN_READER(name, gb)\ + int name##_index= (gb)->index;\ + int name##_cache= 0;\ + +# define CLOSE_READER(name, gb)\ + (gb)->index= name##_index;\ + +# define UPDATE_CACHE(name, gb)\ + name##_cache= unaligned32_be( ((uint8_t *)(gb)->buffer)+(name##_index>>3) ) << (name##_index&0x07);\ + +# define SKIP_CACHE(name, gb, num)\ + name##_cache <<= (num);\ + +// FIXME name? +# define SKIP_COUNTER(name, gb, num)\ + name##_index += (num);\ + +# define SKIP_BITS(name, gb, num)\ + {\ + SKIP_CACHE(name, gb, num)\ + SKIP_COUNTER(name, gb, num)\ + }\ + +# define LAST_SKIP_BITS(name, gb, num) SKIP_COUNTER(name, gb, num) +# define LAST_SKIP_CACHE(name, gb, num) ; + +# define SHOW_UBITS(name, gb, num)\ + NEG_USR32(name##_cache, num) + +# define SHOW_SBITS(name, gb, num)\ + NEG_SSR32(name##_cache, num) + +# define GET_CACHE(name, gb)\ + ((uint32_t)name##_cache) + +static inline int get_bits_count(GetBitContext *s){ + return s->index; +} +#elif defined LIBMPEG2_BITSTREAM_READER +//libmpeg2 like reader + +# define MIN_CACHE_BITS 17 + +# define OPEN_READER(name, gb)\ + int name##_bit_count=(gb)->bit_count;\ + int name##_cache= (gb)->cache;\ + uint8_t * name##_buffer_ptr=(gb)->buffer_ptr;\ + +# define CLOSE_READER(name, gb)\ + (gb)->bit_count= name##_bit_count;\ + (gb)->cache= name##_cache;\ + (gb)->buffer_ptr= name##_buffer_ptr;\ + +#ifdef LIBMPEG2_BITSTREAM_READER_HACK + +# define UPDATE_CACHE(name, gb)\ + if(name##_bit_count >= 0){\ + name##_cache+= (int)be2me_16(*(uint16_t*)name##_buffer_ptr) << name##_bit_count;\ + ((uint16_t*)name##_buffer_ptr)++;\ + name##_bit_count-= 16;\ + }\ + +#else + +# define UPDATE_CACHE(name, gb)\ + if(name##_bit_count >= 0){\ + name##_cache+= ((name##_buffer_ptr[0]<<8) + name##_buffer_ptr[1]) << name##_bit_count;\ + name##_buffer_ptr+=2;\ + name##_bit_count-= 16;\ + }\ + +#endif + +# define SKIP_CACHE(name, gb, num)\ + name##_cache <<= (num);\ + +# define SKIP_COUNTER(name, gb, num)\ + name##_bit_count += (num);\ + +# define SKIP_BITS(name, gb, num)\ + {\ + SKIP_CACHE(name, gb, num)\ + SKIP_COUNTER(name, gb, num)\ + }\ + +# define LAST_SKIP_BITS(name, gb, num) SKIP_BITS(name, gb, num) +# define LAST_SKIP_CACHE(name, gb, num) SKIP_CACHE(name, gb, num) + +# define SHOW_UBITS(name, gb, num)\ + NEG_USR32(name##_cache, num) + +# define SHOW_SBITS(name, gb, num)\ + NEG_SSR32(name##_cache, num) + +# define GET_CACHE(name, gb)\ + ((uint32_t)name##_cache) + +static inline int get_bits_count(GetBitContext *s){ + return (s->buffer_ptr - s->buffer)*8 - 16 + s->bit_count; +} + +#elif defined A32_BITSTREAM_READER + +# define MIN_CACHE_BITS 32 + +# define OPEN_READER(name, gb)\ + int name##_bit_count=(gb)->bit_count;\ + uint32_t name##_cache0= (gb)->cache0;\ + uint32_t name##_cache1= (gb)->cache1;\ + uint32_t * name##_buffer_ptr=(gb)->buffer_ptr;\ + +# define CLOSE_READER(name, gb)\ + (gb)->bit_count= name##_bit_count;\ + (gb)->cache0= name##_cache0;\ + (gb)->cache1= name##_cache1;\ + (gb)->buffer_ptr= name##_buffer_ptr;\ + +# define UPDATE_CACHE(name, gb)\ + if(name##_bit_count > 0){\ + const uint32_t next= be2me_32( *name##_buffer_ptr );\ + name##_cache0 |= NEG_USR32(next,name##_bit_count);\ + name##_cache1 |= next<buffer_ptr - s->buffer)*8 - 32 + s->bit_count; +} + +#endif + +/** + * read mpeg1 dc style vlc (sign bit + mantisse with no MSB). + * if MSB not set it is negative + * @param n length in bits + * @author BERO + */ +static inline int get_xbits(GetBitContext *s, int n){ + register int tmp; + register int32_t cache; + OPEN_READER(re, s) + UPDATE_CACHE(re, s) + cache = GET_CACHE(re,s); + if ((int32_t)cache<0) { //MSB=1 + tmp = NEG_USR32(cache,n); + } else { + // tmp = (-1<index+=n for the ALT_READER :)) + OPEN_READER(re, s) + UPDATE_CACHE(re, s) + LAST_SKIP_BITS(re, s, n) + CLOSE_READER(re, s) +} + +static inline unsigned int get_bits1(GetBitContext *s){ +#ifdef ALT_BITSTREAM_READER + int index= s->index; + uint8_t result= s->buffer[ index>>3 ]; + result<<= (index&0x07); + result>>= 8 - 1; + index++; + s->index= index; + + return result; +#else + return get_bits(s, 1); +#endif +} + +static inline unsigned int show_bits1(GetBitContext *s){ + return show_bits(s, 1); +} + +static inline void skip_bits1(GetBitContext *s){ + skip_bits(s, 1); +} + +void init_get_bits(GetBitContext *s, + const uint8_t *buffer, int buffer_size); + +int check_marker(GetBitContext *s, const char *msg); +void align_get_bits(GetBitContext *s); +int init_vlc(VLC *vlc, int nb_bits, int nb_codes, + const void *bits, int bits_wrap, int bits_size, + const void *codes, int codes_wrap, int codes_size); +void free_vlc(VLC *vlc); + +/** + * + * if the vlc code is invalid and max_depth=1 than no bits will be removed + * if the vlc code is invalid and max_depth>1 than the number of bits removed + * is undefined + */ +#define GET_VLC(code, name, gb, table, bits, max_depth)\ +{\ + int n, index, nb_bits;\ +\ + index= SHOW_UBITS(name, gb, bits);\ + code = table[index][0];\ + n = table[index][1];\ +\ + if(max_depth > 1 && n < 0){\ + LAST_SKIP_BITS(name, gb, bits)\ + UPDATE_CACHE(name, gb)\ +\ + nb_bits = -n;\ +\ + index= SHOW_UBITS(name, gb, nb_bits) + code;\ + code = table[index][0];\ + n = table[index][1];\ + if(max_depth > 2 && n < 0){\ + LAST_SKIP_BITS(name, gb, nb_bits)\ + UPDATE_CACHE(name, gb)\ +\ + nb_bits = -n;\ +\ + index= SHOW_UBITS(name, gb, nb_bits) + code;\ + code = table[index][0];\ + n = table[index][1];\ + }\ + }\ + SKIP_BITS(name, gb, n)\ +} + +#define GET_RL_VLC(level, run, name, gb, table, bits, max_depth)\ +{\ + int n, index, nb_bits;\ +\ + index= SHOW_UBITS(name, gb, bits);\ + level = table[index].level;\ + n = table[index].len;\ +\ + if(max_depth > 1 && n < 0){\ + LAST_SKIP_BITS(name, gb, bits)\ + UPDATE_CACHE(name, gb)\ +\ + nb_bits = -n;\ +\ + index= SHOW_UBITS(name, gb, nb_bits) + level;\ + level = table[index].level;\ + n = table[index].len;\ + }\ + run= table[index].run;\ + SKIP_BITS(name, gb, n)\ +} + +// deprecated, dont use get_vlc for new code, use get_vlc2 instead or use GET_VLC directly +static inline int get_vlc(GetBitContext *s, VLC *vlc) +{ + int code; + VLC_TYPE (*table)[2]= vlc->table; + + OPEN_READER(re, s) + UPDATE_CACHE(re, s) + + GET_VLC(code, re, s, table, vlc->bits, 3) + + CLOSE_READER(re, s) + return code; +} + +/** + * parses a vlc code, faster then get_vlc() + * @param bits is the number of bits which will be read at once, must be + * identical to nb_bits in init_vlc() + * @param max_depth is the number of times bits bits must be readed to completly + * read the longest vlc code + * = (max_vlc_length + bits - 1) / bits + */ +static always_inline int get_vlc2(GetBitContext *s, VLC_TYPE (*table)[2], + int bits, int max_depth) +{ + int code; + + OPEN_READER(re, s) + UPDATE_CACHE(re, s) + + GET_VLC(code, re, s, table, bits, max_depth) + + CLOSE_READER(re, s) + return code; +} + +//#define TRACE + +#ifdef TRACE + +static inline void print_bin(int bits, int n){ +#if _DEBUG + int i; + + for(i=n-1; i>=0; i--){ + ZZLog::Log("%d", (bits>>i)&1); + } + for(i=n; i<24; i++) + ZZLog::Log(" "); +#endif +} + +static inline int get_bits_trace(GetBitContext *s, int n, char *file, char *func, int line){ + int r= get_bits(s, n); + + print_bin(r, n); + ZZLog::Debug_Log("%5d %2d %3d bit @%5d in %s %s:%d", r, n, r, get_bits_count(s)-n, file, func, line); + return r; +} +static inline int get_vlc_trace(GetBitContext *s, VLC_TYPE (*table)[2], int bits, int max_depth, char *file, char *func, int line){ + int show= show_bits(s, 24); + int pos= get_bits_count(s); + int r= get_vlc2(s, table, bits, max_depth); + int len= get_bits_count(s) - pos; + int bits2= show>>(24-len); + + print_bin(bits2, len); + + ZZLog::Debug_Log("%5d %2d %3d vlc @%5d in %s %s:%d", bits2, len, r, pos, file, func, line); + return r; +} +static inline int get_xbits_trace(GetBitContext *s, int n, char *file, char *func, int line){ + int show= show_bits(s, n); + int r= get_xbits(s, n); + + print_bin(show, n); + ZZLog::Debug_Log("%5d %2d %3d xbt @%5d in %s %s:%d", show, n, r, get_bits_count(s)-n, file, func, line); + return r; +} + +#define get_bits(s, n) get_bits_trace(s, n, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_bits1(s) get_bits_trace(s, 1, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_xbits(s, n) get_xbits_trace(s, n, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_vlc(s, vlc) get_vlc_trace(s, (vlc)->table, (vlc)->bits, 3, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_vlc2(s, tab, bits, max) get_vlc_trace(s, tab, bits, max, __FILE__, __PRETTY_FUNCTION__, __LINE__) + +#define tprintf printf + +#else //TRACE +#define tprintf(_arg...) {} +#endif + +/* define it to include statistics code (useful only for optimizing + codec efficiency */ +//#define STATS + +#ifdef STATS + +enum { + ST_UNKNOWN, + ST_DC, + ST_INTRA_AC, + ST_INTER_AC, + ST_INTRA_MB, + ST_INTER_MB, + ST_MV, + ST_NB, +}; + +extern int st_current_index; +extern unsigned int st_bit_counts[ST_NB]; +extern unsigned int st_out_bit_counts[ST_NB]; + +void print_stats(void); +#endif + +/* misc math functions */ +extern const uint8_t ff_log2_tab[256]; + +static inline int av_log2(unsigned int v) +{ + int n; + + n = 0; + if (v & 0xffff0000) { + v >>= 16; + n += 16; + } + if (v & 0xff00) { + v >>= 8; + n += 8; + } + n += ff_log2_tab[v]; + + return n; +} + +static inline int av_log2_16bit(unsigned int v) +{ + int n; + + n = 0; + if (v & 0xff00) { + v >>= 8; + n += 8; + } + n += ff_log2_tab[v]; + + return n; +} + + +/* median of 3 */ +static inline int mid_pred(int a, int b, int c) +{ + int vmin, vmax; + vmax = vmin = a; + if (b < vmin) + vmin = b; + else + vmax = b; + + if (c < vmin) + vmin = c; + else if (c > vmax) + vmax = c; + + return a + b + c - vmin - vmax; +} + +static inline int clip(int a, int amin, int amax) +{ + if (a < amin) + return amin; + else if (a > amax) + return amax; + else + return a; +} + +/* math */ +extern const uint8_t ff_sqrt_tab[128]; + +int64_t ff_gcd(int64_t a, int64_t b); + +static inline int ff_sqrt(int a) +{ + int ret=0; + int s; + int ret_sq=0; + + if(a<128) return ff_sqrt_tab[a]; + + for(s=15; s>=0; s--){ + int b= ret_sq + (1<<(s*2)) + (ret<>31;\ + level= (level^mask)-mask; +#endif + + +#if __CPU__ >= 686 && !defined(RUNTIME_CPUDETECT) +#define COPY3_IF_LT(x,y,a,b,c,d)\ +asm volatile (\ + "cmpl %0, %3 \n\t"\ + "cmovl %3, %0 \n\t"\ + "cmovl %4, %1 \n\t"\ + "cmovl %5, %2 \n\t"\ + : "+r" (x), "+r" (a), "+r" (c)\ + : "r" (y), "r" (b), "r" (d)\ +); +#else +#define COPY3_IF_LT(x,y,a,b,c,d)\ +if((y)<(x)){\ + (x)=(y);\ + (a)=(b);\ + (c)=(d);\ +} +#endif + +#ifdef ARCH_X86 +static inline long long rdtsc() +{ + long long l; + asm volatile( "rdtsc\n\t" + : "=A" (l) + ); + return l; +} + +#define START_TIMER \ +static uint64_t tsum=0;\ +static int tcount=0;\ +static int tskip_count=0;\ +uint64_t tend;\ +uint64_t tstart= rdtsc();\ + +#define STOP_TIMER(id) \ +tend= rdtsc();\ +if(tcount<2 || tend - tstart < 4*tsum/tcount){\ + tsum+= tend - tstart;\ + tcount++;\ +}else\ + tskip_count++;\ +if(256*256*256*64%(tcount+tskip_count)==0){\ + fprintf(stderr, "%Ld dezicycles in %s, %d runs, %d skips\n", tsum*10/tcount, id, tcount, tskip_count);\ +} +#endif + +#define CLAMP_TO_8BIT(d) ((d > 0xff) ? 0xff : (d < 0) ? 0 : d) + +/* avoid usage of various functions */ +#define malloc please_use_av_malloc +#define free please_use_av_free +#define realloc please_use_av_realloc + +#define CHECKED_ALLOCZ(p, size)\ +{\ + p= av_mallocz(size);\ + if(p==NULL && (size)!=0){\ + perror("malloc");\ + goto fail;\ + }\ +} + +#endif /* HAVE_AV_CONFIG_H */ + +#endif /* COMMON_H */ diff --git a/plugins/zzogl-pg-cg/opengl/ctx0/ps2hw_ctx.fx b/plugins/zzogl-pg-cg/opengl/ctx0/ps2hw_ctx.fx new file mode 100644 index 000000000..60e37ac4c --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ctx0/ps2hw_ctx.fx @@ -0,0 +1,24 @@ +// main ps2 memory, each pixel is stored in 32bit color +uniform samplerRECT g_sMemory : register(s0); + +// per context pixel shader constants +uniform half4 fTexAlpha2 : register(c2); + +uniform float4 g_fTexOffset : register(c4); // converts the page and block offsets into the mem addr/1024 +uniform float4 g_fTexDims : register(c6); // mult by tex dims when accessing the block texture +uniform float4 g_fTexBlock : register(c8); + +uniform float4 g_fClampExts : register(c10); // if clamping the texture, use (minu, minv, maxu, maxv) +uniform float4 TexWrapMode : register(c12); // 0 - repeat/clamp, 1 - region rep (use fRegRepMask) + +uniform float4 g_fRealTexDims : register(c14); // tex dims used for linear filtering (w,h,1/w,1/h) + +// (alpha0, alpha1, 1 if highlight2 and tcc is rgba, 1-y) +uniform half4 g_fTestBlack : register(c16); // used for aem bit + +uniform float4 g_fPageOffset : register(c18); + +uniform half4 fTexAlpha : register(c20); + +// vertex shader constants +uniform float4 g_fPosXY : register(c2); \ No newline at end of file diff --git a/plugins/zzogl-pg-cg/opengl/ctx1/ps2hw_ctx.fx b/plugins/zzogl-pg-cg/opengl/ctx1/ps2hw_ctx.fx new file mode 100644 index 000000000..58c755ea9 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/ctx1/ps2hw_ctx.fx @@ -0,0 +1,23 @@ +uniform samplerRECT g_sMemory : register(s1); + +// per context pixel shader constants +uniform half4 fTexAlpha2 : register(c3); + +uniform float4 g_fTexOffset : register(c5); // converts the page and block offsets into the mem addr/1024 +uniform float4 g_fTexDims : register(c7); // mult by tex dims when accessing the block texture +uniform float4 g_fTexBlock : register(c9); + +uniform float4 g_fClampExts : register(c11); // if clamping the texture, use (minu, minv, maxu, maxv) +uniform float4 TexWrapMode : register(c13); // 0 - repeat/clamp, 1 - region rep (use fRegRepMask) + +uniform float4 g_fRealTexDims : register(c15); // tex dims used for linear filtering (w,h,1/w,1/h) + +// (alpha0, alpha1, 1 if highlight2 and tcc is rgba, 1-y) +uniform half4 g_fTestBlack : register(c17); // used for aem bit + +uniform float4 g_fPageOffset : register(c19); + +uniform half4 fTexAlpha : register(c21); + +// vertex shader constants +uniform float4 g_fPosXY : register(c3); \ No newline at end of file diff --git a/plugins/zzogl-pg-cg/opengl/glprocs.c b/plugins/zzogl-pg-cg/opengl/glprocs.c new file mode 100644 index 000000000..60fd5eec5 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/glprocs.c @@ -0,0 +1,17868 @@ +/* +** GLprocs utility for getting function addresses for OpenGL(R) 1.2, +** OpenGL 1.3, OpenGL 1.4, OpenGL 1.5 and OpenGL extension functions. +** +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and associated documentation files (the "Software"), +** to deal in the Software without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Software, and to permit persons to whom the +** Software is furnished to do so, subject to the following conditions: +** +** The above copyright notice including the dates of first publication and +** either this permission notice or a reference to +** http://oss.sgi.com/projects/FreeB/ +** shall be included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +** WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +** OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +** SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. +** shall not be used in advertising or otherwise to promote the sale, use or +** other dealings in this Software without prior written authorization from +** Silicon Graphics, Inc. +** +** Additional Notice Provisions: This software was created using the +** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has +** not been independently verified as being compliant with the OpenGL(R) +** version 1.2.1 Specification. +** +** Initial version of glprocs.{c,h} contributed by Intel(R) Corporation. +*/ + +#include +#include + +#ifdef _WIN32 + #include "Utilities/RedtapeWindows.h" + #include //"gl.h" /* Include local "gl.h". Don't include vc32 . */ + #include "glprocs.h" +#else /* GLX */ + #include + #include + #include +#include "glprocs.h"// +// #define wglGetProcAddress glXGetProcAddress +inline void* wglGetProcAddress(const char* x) { + return (void*)glXGetProcAddress((const GLubyte*)x); +} + +#endif + +#define _ASSERT(a) assert(a) + +static void APIENTRY InitBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBlendColor"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBlendColor = extproc; + + glBlendColor(red, green, blue, alpha); +} + +static void APIENTRY InitBlendEquation (GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBlendEquation"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBlendEquation = extproc; + + glBlendEquation(mode); +} + +static void APIENTRY InitDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawRangeElements"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawRangeElements = extproc; + + glDrawRangeElements(mode, start, end, count, type, indices); +} + +static void APIENTRY InitColorTable (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorTable"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorTable = extproc; + + glColorTable(target, internalformat, width, format, type, table); +} + +static void APIENTRY InitColorTableParameterfv (GLenum target, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorTableParameterfv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorTableParameterfv = extproc; + + glColorTableParameterfv(target, pname, params); +} + +static void APIENTRY InitColorTableParameteriv (GLenum target, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorTableParameteriv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorTableParameteriv = extproc; + + glColorTableParameteriv(target, pname, params); +} + +static void APIENTRY InitCopyColorTable (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyColorTable"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyColorTable = extproc; + + glCopyColorTable(target, internalformat, x, y, width); +} + +static void APIENTRY InitGetColorTable (GLenum target, GLenum format, GLenum type, GLvoid *table) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTable"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTable = extproc; + + glGetColorTable(target, format, type, table); +} + +static void APIENTRY InitGetColorTableParameterfv (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTableParameterfv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTableParameterfv = extproc; + + glGetColorTableParameterfv(target, pname, params); +} + +static void APIENTRY InitGetColorTableParameteriv (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTableParameteriv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTableParameteriv = extproc; + + glGetColorTableParameteriv(target, pname, params); +} + +static void APIENTRY InitColorSubTable (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorSubTable"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorSubTable = extproc; + + glColorSubTable(target, start, count, format, type, data); +} + +static void APIENTRY InitCopyColorSubTable (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyColorSubTable"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyColorSubTable = extproc; + + glCopyColorSubTable(target, start, x, y, width); +} + +static void APIENTRY InitConvolutionFilter1D (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionFilter1D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionFilter1D = extproc; + + glConvolutionFilter1D(target, internalformat, width, format, type, image); +} + +static void APIENTRY InitConvolutionFilter2D (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionFilter2D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionFilter2D = extproc; + + glConvolutionFilter2D(target, internalformat, width, height, format, type, image); +} + +static void APIENTRY InitConvolutionParameterf (GLenum target, GLenum pname, GLfloat params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionParameterf"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionParameterf = extproc; + + glConvolutionParameterf(target, pname, params); +} + +static void APIENTRY InitConvolutionParameterfv (GLenum target, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionParameterfv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionParameterfv = extproc; + + glConvolutionParameterfv(target, pname, params); +} + +static void APIENTRY InitConvolutionParameteri (GLenum target, GLenum pname, GLint params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionParameteri"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionParameteri = extproc; + + glConvolutionParameteri(target, pname, params); +} + +static void APIENTRY InitConvolutionParameteriv (GLenum target, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionParameteriv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionParameteriv = extproc; + + glConvolutionParameteriv(target, pname, params); +} + +static void APIENTRY InitCopyConvolutionFilter1D (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyConvolutionFilter1D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyConvolutionFilter1D = extproc; + + glCopyConvolutionFilter1D(target, internalformat, x, y, width); +} + +static void APIENTRY InitCopyConvolutionFilter2D (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyConvolutionFilter2D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyConvolutionFilter2D = extproc; + + glCopyConvolutionFilter2D(target, internalformat, x, y, width, height); +} + +static void APIENTRY InitGetConvolutionFilter (GLenum target, GLenum format, GLenum type, GLvoid *image) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetConvolutionFilter"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetConvolutionFilter = extproc; + + glGetConvolutionFilter(target, format, type, image); +} + +static void APIENTRY InitGetConvolutionParameterfv (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetConvolutionParameterfv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetConvolutionParameterfv = extproc; + + glGetConvolutionParameterfv(target, pname, params); +} + +static void APIENTRY InitGetConvolutionParameteriv (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetConvolutionParameteriv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetConvolutionParameteriv = extproc; + + glGetConvolutionParameteriv(target, pname, params); +} + +static void APIENTRY InitGetSeparableFilter (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetSeparableFilter"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetSeparableFilter = extproc; + + glGetSeparableFilter(target, format, type, row, column, span); +} + +static void APIENTRY InitSeparableFilter2D (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSeparableFilter2D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSeparableFilter2D = extproc; + + glSeparableFilter2D(target, internalformat, width, height, format, type, row, column); +} + +static void APIENTRY InitGetHistogram (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetHistogram"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetHistogram = extproc; + + glGetHistogram(target, reset, format, type, values); +} + +static void APIENTRY InitGetHistogramParameterfv (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetHistogramParameterfv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetHistogramParameterfv = extproc; + + glGetHistogramParameterfv(target, pname, params); +} + +static void APIENTRY InitGetHistogramParameteriv (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetHistogramParameteriv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetHistogramParameteriv = extproc; + + glGetHistogramParameteriv(target, pname, params); +} + +static void APIENTRY InitGetMinmax (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMinmax"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMinmax = extproc; + + glGetMinmax(target, reset, format, type, values); +} + +static void APIENTRY InitGetMinmaxParameterfv (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMinmaxParameterfv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMinmaxParameterfv = extproc; + + glGetMinmaxParameterfv(target, pname, params); +} + +static void APIENTRY InitGetMinmaxParameteriv (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMinmaxParameteriv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMinmaxParameteriv = extproc; + + glGetMinmaxParameteriv(target, pname, params); +} + +static void APIENTRY InitHistogram (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glHistogram"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glHistogram = extproc; + + glHistogram(target, width, internalformat, sink); +} + +static void APIENTRY InitMinmax (GLenum target, GLenum internalformat, GLboolean sink) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMinmax"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMinmax = extproc; + + glMinmax(target, internalformat, sink); +} + +static void APIENTRY InitResetHistogram (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glResetHistogram"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glResetHistogram = extproc; + + glResetHistogram(target); +} + +static void APIENTRY InitResetMinmax (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glResetMinmax"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glResetMinmax = extproc; + + glResetMinmax(target); +} + +static void APIENTRY InitTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexImage3D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexImage3D = extproc; + + glTexImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels); +} + +static void APIENTRY InitTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexSubImage3D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexSubImage3D = extproc; + + glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); +} + +static void APIENTRY InitCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyTexSubImage3D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyTexSubImage3D = extproc; + + glCopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height); +} + +static void APIENTRY InitActiveTexture (GLenum texture) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glActiveTexture"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glActiveTexture = extproc; + + glActiveTexture(texture); +} + +static void APIENTRY InitClientActiveTexture (GLenum texture) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glClientActiveTexture"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glClientActiveTexture = extproc; + + glClientActiveTexture(texture); +} + +static void APIENTRY InitMultiTexCoord1d (GLenum target, GLdouble s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1d"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1d = extproc; + + glMultiTexCoord1d(target, s); +} + +static void APIENTRY InitMultiTexCoord1dv (GLenum target, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1dv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1dv = extproc; + + glMultiTexCoord1dv(target, v); +} + +static void APIENTRY InitMultiTexCoord1f (GLenum target, GLfloat s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1f"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1f = extproc; + + glMultiTexCoord1f(target, s); +} + +static void APIENTRY InitMultiTexCoord1fv (GLenum target, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1fv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1fv = extproc; + + glMultiTexCoord1fv(target, v); +} + +static void APIENTRY InitMultiTexCoord1i (GLenum target, GLint s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1i"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1i = extproc; + + glMultiTexCoord1i(target, s); +} + +static void APIENTRY InitMultiTexCoord1iv (GLenum target, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1iv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1iv = extproc; + + glMultiTexCoord1iv(target, v); +} + +static void APIENTRY InitMultiTexCoord1s (GLenum target, GLshort s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1s"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1s = extproc; + + glMultiTexCoord1s(target, s); +} + +static void APIENTRY InitMultiTexCoord1sv (GLenum target, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1sv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1sv = extproc; + + glMultiTexCoord1sv(target, v); +} + +static void APIENTRY InitMultiTexCoord2d (GLenum target, GLdouble s, GLdouble t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2d"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2d = extproc; + + glMultiTexCoord2d(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2dv (GLenum target, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2dv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2dv = extproc; + + glMultiTexCoord2dv(target, v); +} + +static void APIENTRY InitMultiTexCoord2f (GLenum target, GLfloat s, GLfloat t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2f"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2f = extproc; + + glMultiTexCoord2f(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2fv (GLenum target, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2fv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2fv = extproc; + + glMultiTexCoord2fv(target, v); +} + +static void APIENTRY InitMultiTexCoord2i (GLenum target, GLint s, GLint t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2i"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2i = extproc; + + glMultiTexCoord2i(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2iv (GLenum target, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2iv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2iv = extproc; + + glMultiTexCoord2iv(target, v); +} + +static void APIENTRY InitMultiTexCoord2s (GLenum target, GLshort s, GLshort t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2s"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2s = extproc; + + glMultiTexCoord2s(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2sv (GLenum target, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2sv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2sv = extproc; + + glMultiTexCoord2sv(target, v); +} + +static void APIENTRY InitMultiTexCoord3d (GLenum target, GLdouble s, GLdouble t, GLdouble r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3d"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3d = extproc; + + glMultiTexCoord3d(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3dv (GLenum target, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3dv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3dv = extproc; + + glMultiTexCoord3dv(target, v); +} + +static void APIENTRY InitMultiTexCoord3f (GLenum target, GLfloat s, GLfloat t, GLfloat r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3f"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3f = extproc; + + glMultiTexCoord3f(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3fv (GLenum target, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3fv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3fv = extproc; + + glMultiTexCoord3fv(target, v); +} + +static void APIENTRY InitMultiTexCoord3i (GLenum target, GLint s, GLint t, GLint r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3i"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3i = extproc; + + glMultiTexCoord3i(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3iv (GLenum target, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3iv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3iv = extproc; + + glMultiTexCoord3iv(target, v); +} + +static void APIENTRY InitMultiTexCoord3s (GLenum target, GLshort s, GLshort t, GLshort r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3s"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3s = extproc; + + glMultiTexCoord3s(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3sv (GLenum target, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3sv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3sv = extproc; + + glMultiTexCoord3sv(target, v); +} + +static void APIENTRY InitMultiTexCoord4d (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4d"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4d = extproc; + + glMultiTexCoord4d(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4dv (GLenum target, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4dv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4dv = extproc; + + glMultiTexCoord4dv(target, v); +} + +static void APIENTRY InitMultiTexCoord4f (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4f"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4f = extproc; + + glMultiTexCoord4f(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4fv (GLenum target, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4fv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4fv = extproc; + + glMultiTexCoord4fv(target, v); +} + +static void APIENTRY InitMultiTexCoord4i (GLenum target, GLint s, GLint t, GLint r, GLint q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4i"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4i = extproc; + + glMultiTexCoord4i(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4iv (GLenum target, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4iv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4iv = extproc; + + glMultiTexCoord4iv(target, v); +} + +static void APIENTRY InitMultiTexCoord4s (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4s"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4s = extproc; + + glMultiTexCoord4s(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4sv (GLenum target, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4sv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4sv = extproc; + + glMultiTexCoord4sv(target, v); +} + +static void APIENTRY InitLoadTransposeMatrixf (const GLfloat *m) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLoadTransposeMatrixf"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLoadTransposeMatrixf = extproc; + + glLoadTransposeMatrixf(m); +} + +static void APIENTRY InitLoadTransposeMatrixd (const GLdouble *m) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLoadTransposeMatrixd"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLoadTransposeMatrixd = extproc; + + glLoadTransposeMatrixd(m); +} + +static void APIENTRY InitMultTransposeMatrixf (const GLfloat *m) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultTransposeMatrixf"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultTransposeMatrixf = extproc; + + glMultTransposeMatrixf(m); +} + +static void APIENTRY InitMultTransposeMatrixd (const GLdouble *m) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultTransposeMatrixd"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultTransposeMatrixd = extproc; + + glMultTransposeMatrixd(m); +} + +static void APIENTRY InitSampleCoverage (GLclampf value, GLboolean invert) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSampleCoverage"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSampleCoverage = extproc; + + glSampleCoverage(value, invert); +} + +static void APIENTRY InitCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexImage3D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexImage3D = extproc; + + glCompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data); +} + +static void APIENTRY InitCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexImage2D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexImage2D = extproc; + + glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); +} + +static void APIENTRY InitCompressedTexImage1D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexImage1D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexImage1D = extproc; + + glCompressedTexImage1D(target, level, internalformat, width, border, imageSize, data); +} + +static void APIENTRY InitCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexSubImage3D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexSubImage3D = extproc; + + glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); +} + +static void APIENTRY InitCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexSubImage2D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexSubImage2D = extproc; + + glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); +} + +static void APIENTRY InitCompressedTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexSubImage1D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexSubImage1D = extproc; + + glCompressedTexSubImage1D(target, level, xoffset, width, format, imageSize, data); +} + +static void APIENTRY InitGetCompressedTexImage (GLenum target, GLint level, GLvoid *img) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetCompressedTexImage"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetCompressedTexImage = extproc; + + glGetCompressedTexImage(target, level, img); +} + +static void APIENTRY InitBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBlendFuncSeparate"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBlendFuncSeparate = extproc; + + glBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); +} + +static void APIENTRY InitFogCoordf (GLfloat coord) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordf"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordf = extproc; + + glFogCoordf(coord); +} + +static void APIENTRY InitFogCoordfv (const GLfloat *coord) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordfv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordfv = extproc; + + glFogCoordfv(coord); +} + +static void APIENTRY InitFogCoordd (GLdouble coord) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordd"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordd = extproc; + + glFogCoordd(coord); +} + +static void APIENTRY InitFogCoorddv (const GLdouble *coord) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoorddv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoorddv = extproc; + + glFogCoorddv(coord); +} + +static void APIENTRY InitFogCoordPointer (GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordPointer"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordPointer = extproc; + + glFogCoordPointer(type, stride, pointer); +} + +static void APIENTRY InitMultiDrawArrays (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiDrawArrays"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiDrawArrays = extproc; + + glMultiDrawArrays(mode, first, count, primcount); +} + +static void APIENTRY InitMultiDrawElements (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiDrawElements"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiDrawElements = extproc; + + glMultiDrawElements(mode, count, type, indices, primcount); +} + +static void APIENTRY InitPointParameterf (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterf"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterf = extproc; + + glPointParameterf(pname, param); +} + +static void APIENTRY InitPointParameterfv (GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterfv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterfv = extproc; + + glPointParameterfv(pname, params); +} + +static void APIENTRY InitPointParameteri (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameteri"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameteri = extproc; + + glPointParameteri(pname, param); +} + +static void APIENTRY InitPointParameteriv (GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameteriv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameteriv = extproc; + + glPointParameteriv(pname, params); +} + +static void APIENTRY InitSecondaryColor3b (GLbyte red, GLbyte green, GLbyte blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3b"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3b = extproc; + + glSecondaryColor3b(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3bv (const GLbyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3bv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3bv = extproc; + + glSecondaryColor3bv(v); +} + +static void APIENTRY InitSecondaryColor3d (GLdouble red, GLdouble green, GLdouble blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3d"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3d = extproc; + + glSecondaryColor3d(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3dv (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3dv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3dv = extproc; + + glSecondaryColor3dv(v); +} + +static void APIENTRY InitSecondaryColor3f (GLfloat red, GLfloat green, GLfloat blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3f"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3f = extproc; + + glSecondaryColor3f(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3fv (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3fv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3fv = extproc; + + glSecondaryColor3fv(v); +} + +static void APIENTRY InitSecondaryColor3i (GLint red, GLint green, GLint blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3i"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3i = extproc; + + glSecondaryColor3i(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3iv (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3iv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3iv = extproc; + + glSecondaryColor3iv(v); +} + +static void APIENTRY InitSecondaryColor3s (GLshort red, GLshort green, GLshort blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3s"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3s = extproc; + + glSecondaryColor3s(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3sv (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3sv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3sv = extproc; + + glSecondaryColor3sv(v); +} + +static void APIENTRY InitSecondaryColor3ub (GLubyte red, GLubyte green, GLubyte blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3ub"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3ub = extproc; + + glSecondaryColor3ub(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3ubv (const GLubyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3ubv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3ubv = extproc; + + glSecondaryColor3ubv(v); +} + +static void APIENTRY InitSecondaryColor3ui (GLuint red, GLuint green, GLuint blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3ui"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3ui = extproc; + + glSecondaryColor3ui(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3uiv (const GLuint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3uiv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3uiv = extproc; + + glSecondaryColor3uiv(v); +} + +static void APIENTRY InitSecondaryColor3us (GLushort red, GLushort green, GLushort blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3us"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3us = extproc; + + glSecondaryColor3us(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3usv (const GLushort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3usv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3usv = extproc; + + glSecondaryColor3usv(v); +} + +static void APIENTRY InitSecondaryColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColorPointer"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColorPointer = extproc; + + glSecondaryColorPointer(size, type, stride, pointer); +} + +static void APIENTRY InitWindowPos2d (GLdouble x, GLdouble y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2d"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2d = extproc; + + glWindowPos2d(x, y); +} + +static void APIENTRY InitWindowPos2dv (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2dv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2dv = extproc; + + glWindowPos2dv(v); +} + +static void APIENTRY InitWindowPos2f (GLfloat x, GLfloat y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2f"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2f = extproc; + + glWindowPos2f(x, y); +} + +static void APIENTRY InitWindowPos2fv (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2fv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2fv = extproc; + + glWindowPos2fv(v); +} + +static void APIENTRY InitWindowPos2i (GLint x, GLint y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2i"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2i = extproc; + + glWindowPos2i(x, y); +} + +static void APIENTRY InitWindowPos2iv (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2iv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2iv = extproc; + + glWindowPos2iv(v); +} + +static void APIENTRY InitWindowPos2s (GLshort x, GLshort y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2s"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2s = extproc; + + glWindowPos2s(x, y); +} + +static void APIENTRY InitWindowPos2sv (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2sv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2sv = extproc; + + glWindowPos2sv(v); +} + +static void APIENTRY InitWindowPos3d (GLdouble x, GLdouble y, GLdouble z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3d"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3d = extproc; + + glWindowPos3d(x, y, z); +} + +static void APIENTRY InitWindowPos3dv (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3dv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3dv = extproc; + + glWindowPos3dv(v); +} + +static void APIENTRY InitWindowPos3f (GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3f"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3f = extproc; + + glWindowPos3f(x, y, z); +} + +static void APIENTRY InitWindowPos3fv (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3fv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3fv = extproc; + + glWindowPos3fv(v); +} + +static void APIENTRY InitWindowPos3i (GLint x, GLint y, GLint z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3i"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3i = extproc; + + glWindowPos3i(x, y, z); +} + +static void APIENTRY InitWindowPos3iv (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3iv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3iv = extproc; + + glWindowPos3iv(v); +} + +static void APIENTRY InitWindowPos3s (GLshort x, GLshort y, GLshort z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3s"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3s = extproc; + + glWindowPos3s(x, y, z); +} + +static void APIENTRY InitWindowPos3sv (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3sv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3sv = extproc; + + glWindowPos3sv(v); +} + +static void APIENTRY InitGenQueries (GLsizei n, GLuint *ids) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenQueries"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenQueries = extproc; + + glGenQueries(n, ids); +} + +static void APIENTRY InitDeleteQueries (GLsizei n, const GLuint *ids) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteQueries"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteQueries = extproc; + + glDeleteQueries(n, ids); +} + +static GLboolean APIENTRY InitIsQuery (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsQuery"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsQuery = extproc; + + return glIsQuery(id); +} + +static void APIENTRY InitBeginQuery (GLenum target, GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBeginQuery"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBeginQuery = extproc; + + glBeginQuery(target, id); +} + +static void APIENTRY InitEndQuery (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEndQuery"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEndQuery = extproc; + + glEndQuery(target); +} + +static void APIENTRY InitGetQueryiv (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetQueryiv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetQueryiv = extproc; + + glGetQueryiv(target, pname, params); +} + +static void APIENTRY InitGetQueryObjectiv (GLuint id, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetQueryObjectiv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetQueryObjectiv = extproc; + + glGetQueryObjectiv(id, pname, params); +} + +static void APIENTRY InitGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetQueryObjectuiv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetQueryObjectuiv = extproc; + + glGetQueryObjectuiv(id, pname, params); +} + +static void APIENTRY InitBindBuffer (GLenum target, GLuint buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindBuffer"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindBuffer = extproc; + + glBindBuffer(target, buffer); +} + +static void APIENTRY InitDeleteBuffers (GLsizei n, const GLuint *buffers) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteBuffers"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteBuffers = extproc; + + glDeleteBuffers(n, buffers); +} + +static void APIENTRY InitGenBuffers (GLsizei n, GLuint *buffers) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenBuffers"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenBuffers = extproc; + + glGenBuffers(n, buffers); +} + +static GLboolean APIENTRY InitIsBuffer (GLuint buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsBuffer"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsBuffer = extproc; + + return glIsBuffer(buffer); +} + +static void APIENTRY InitBufferData (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBufferData"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBufferData = extproc; + + glBufferData(target, size, data, usage); +} + +static void APIENTRY InitBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBufferSubData"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBufferSubData = extproc; + + glBufferSubData(target, offset, size, data); +} + +static void APIENTRY InitGetBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetBufferSubData"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetBufferSubData = extproc; + + glGetBufferSubData(target, offset, size, data); +} + +static GLvoid* APIENTRY InitMapBuffer (GLenum target, GLenum access) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMapBuffer"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glMapBuffer = extproc; + + return glMapBuffer(target, access); +} + +static GLboolean APIENTRY InitUnmapBuffer (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUnmapBuffer"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glUnmapBuffer = extproc; + + return glUnmapBuffer(target); +} + +static void APIENTRY InitGetBufferParameteriv (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetBufferParameteriv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetBufferParameteriv = extproc; + + glGetBufferParameteriv(target, pname, params); +} + +static void APIENTRY InitGetBufferPointerv (GLenum target, GLenum pname, GLvoid* *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetBufferPointerv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetBufferPointerv = extproc; + + glGetBufferPointerv(target, pname, params); +} + +static void APIENTRY InitActiveTextureARB (GLenum texture) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glActiveTextureARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glActiveTextureARB = extproc; + + glActiveTextureARB(texture); +} + +static void APIENTRY InitClientActiveTextureARB (GLenum texture) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glClientActiveTextureARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glClientActiveTextureARB = extproc; + + glClientActiveTextureARB(texture); +} + +static void APIENTRY InitMultiTexCoord1dARB (GLenum target, GLdouble s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1dARB = extproc; + + glMultiTexCoord1dARB(target, s); +} + +static void APIENTRY InitMultiTexCoord1dvARB (GLenum target, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1dvARB = extproc; + + glMultiTexCoord1dvARB(target, v); +} + +static void APIENTRY InitMultiTexCoord1fARB (GLenum target, GLfloat s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1fARB = extproc; + + glMultiTexCoord1fARB(target, s); +} + +static void APIENTRY InitMultiTexCoord1fvARB (GLenum target, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1fvARB = extproc; + + glMultiTexCoord1fvARB(target, v); +} + +static void APIENTRY InitMultiTexCoord1iARB (GLenum target, GLint s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1iARB = extproc; + + glMultiTexCoord1iARB(target, s); +} + +static void APIENTRY InitMultiTexCoord1ivARB (GLenum target, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1ivARB = extproc; + + glMultiTexCoord1ivARB(target, v); +} + +static void APIENTRY InitMultiTexCoord1sARB (GLenum target, GLshort s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1sARB = extproc; + + glMultiTexCoord1sARB(target, s); +} + +static void APIENTRY InitMultiTexCoord1svARB (GLenum target, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1svARB = extproc; + + glMultiTexCoord1svARB(target, v); +} + +static void APIENTRY InitMultiTexCoord2dARB (GLenum target, GLdouble s, GLdouble t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2dARB = extproc; + + glMultiTexCoord2dARB(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2dvARB (GLenum target, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2dvARB = extproc; + + glMultiTexCoord2dvARB(target, v); +} + +static void APIENTRY InitMultiTexCoord2fARB (GLenum target, GLfloat s, GLfloat t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2fARB = extproc; + + glMultiTexCoord2fARB(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2fvARB (GLenum target, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2fvARB = extproc; + + glMultiTexCoord2fvARB(target, v); +} + +static void APIENTRY InitMultiTexCoord2iARB (GLenum target, GLint s, GLint t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2iARB = extproc; + + glMultiTexCoord2iARB(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2ivARB (GLenum target, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2ivARB = extproc; + + glMultiTexCoord2ivARB(target, v); +} + +static void APIENTRY InitMultiTexCoord2sARB (GLenum target, GLshort s, GLshort t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2sARB = extproc; + + glMultiTexCoord2sARB(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2svARB (GLenum target, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2svARB = extproc; + + glMultiTexCoord2svARB(target, v); +} + +static void APIENTRY InitMultiTexCoord3dARB (GLenum target, GLdouble s, GLdouble t, GLdouble r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3dARB = extproc; + + glMultiTexCoord3dARB(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3dvARB (GLenum target, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3dvARB = extproc; + + glMultiTexCoord3dvARB(target, v); +} + +static void APIENTRY InitMultiTexCoord3fARB (GLenum target, GLfloat s, GLfloat t, GLfloat r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3fARB = extproc; + + glMultiTexCoord3fARB(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3fvARB (GLenum target, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3fvARB = extproc; + + glMultiTexCoord3fvARB(target, v); +} + +static void APIENTRY InitMultiTexCoord3iARB (GLenum target, GLint s, GLint t, GLint r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3iARB = extproc; + + glMultiTexCoord3iARB(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3ivARB (GLenum target, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3ivARB = extproc; + + glMultiTexCoord3ivARB(target, v); +} + +static void APIENTRY InitMultiTexCoord3sARB (GLenum target, GLshort s, GLshort t, GLshort r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3sARB = extproc; + + glMultiTexCoord3sARB(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3svARB (GLenum target, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3svARB = extproc; + + glMultiTexCoord3svARB(target, v); +} + +static void APIENTRY InitMultiTexCoord4dARB (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4dARB = extproc; + + glMultiTexCoord4dARB(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4dvARB (GLenum target, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4dvARB = extproc; + + glMultiTexCoord4dvARB(target, v); +} + +static void APIENTRY InitMultiTexCoord4fARB (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4fARB = extproc; + + glMultiTexCoord4fARB(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4fvARB (GLenum target, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4fvARB = extproc; + + glMultiTexCoord4fvARB(target, v); +} + +static void APIENTRY InitMultiTexCoord4iARB (GLenum target, GLint s, GLint t, GLint r, GLint q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4iARB = extproc; + + glMultiTexCoord4iARB(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4ivARB (GLenum target, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4ivARB = extproc; + + glMultiTexCoord4ivARB(target, v); +} + +static void APIENTRY InitMultiTexCoord4sARB (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4sARB = extproc; + + glMultiTexCoord4sARB(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4svARB (GLenum target, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4svARB = extproc; + + glMultiTexCoord4svARB(target, v); +} + +static void APIENTRY InitLoadTransposeMatrixfARB (const GLfloat *m) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLoadTransposeMatrixfARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLoadTransposeMatrixfARB = extproc; + + glLoadTransposeMatrixfARB(m); +} + +static void APIENTRY InitLoadTransposeMatrixdARB (const GLdouble *m) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLoadTransposeMatrixdARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLoadTransposeMatrixdARB = extproc; + + glLoadTransposeMatrixdARB(m); +} + +static void APIENTRY InitMultTransposeMatrixfARB (const GLfloat *m) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultTransposeMatrixfARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultTransposeMatrixfARB = extproc; + + glMultTransposeMatrixfARB(m); +} + +static void APIENTRY InitMultTransposeMatrixdARB (const GLdouble *m) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultTransposeMatrixdARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultTransposeMatrixdARB = extproc; + + glMultTransposeMatrixdARB(m); +} + +static void APIENTRY InitSampleCoverageARB (GLclampf value, GLboolean invert) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSampleCoverageARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSampleCoverageARB = extproc; + + glSampleCoverageARB(value, invert); +} + +static void APIENTRY InitCompressedTexImage3DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexImage3DARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexImage3DARB = extproc; + + glCompressedTexImage3DARB(target, level, internalformat, width, height, depth, border, imageSize, data); +} + +static void APIENTRY InitCompressedTexImage2DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexImage2DARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexImage2DARB = extproc; + + glCompressedTexImage2DARB(target, level, internalformat, width, height, border, imageSize, data); +} + +static void APIENTRY InitCompressedTexImage1DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexImage1DARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexImage1DARB = extproc; + + glCompressedTexImage1DARB(target, level, internalformat, width, border, imageSize, data); +} + +static void APIENTRY InitCompressedTexSubImage3DARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexSubImage3DARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexSubImage3DARB = extproc; + + glCompressedTexSubImage3DARB(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); +} + +static void APIENTRY InitCompressedTexSubImage2DARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexSubImage2DARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexSubImage2DARB = extproc; + + glCompressedTexSubImage2DARB(target, level, xoffset, yoffset, width, height, format, imageSize, data); +} + +static void APIENTRY InitCompressedTexSubImage1DARB (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexSubImage1DARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexSubImage1DARB = extproc; + + glCompressedTexSubImage1DARB(target, level, xoffset, width, format, imageSize, data); +} + +static void APIENTRY InitGetCompressedTexImageARB (GLenum target, GLint level, GLvoid *img) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetCompressedTexImageARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetCompressedTexImageARB = extproc; + + glGetCompressedTexImageARB(target, level, img); +} + +static void APIENTRY InitPointParameterfARB (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterfARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterfARB = extproc; + + glPointParameterfARB(pname, param); +} + +static void APIENTRY InitPointParameterfvARB (GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterfvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterfvARB = extproc; + + glPointParameterfvARB(pname, params); +} + +static void APIENTRY InitWeightbvARB (GLint size, const GLbyte *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightbvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightbvARB = extproc; + + glWeightbvARB(size, weights); +} + +static void APIENTRY InitWeightsvARB (GLint size, const GLshort *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightsvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightsvARB = extproc; + + glWeightsvARB(size, weights); +} + +static void APIENTRY InitWeightivARB (GLint size, const GLint *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightivARB = extproc; + + glWeightivARB(size, weights); +} + +static void APIENTRY InitWeightfvARB (GLint size, const GLfloat *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightfvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightfvARB = extproc; + + glWeightfvARB(size, weights); +} + +static void APIENTRY InitWeightdvARB (GLint size, const GLdouble *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightdvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightdvARB = extproc; + + glWeightdvARB(size, weights); +} + +static void APIENTRY InitWeightubvARB (GLint size, const GLubyte *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightubvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightubvARB = extproc; + + glWeightubvARB(size, weights); +} + +static void APIENTRY InitWeightusvARB (GLint size, const GLushort *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightusvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightusvARB = extproc; + + glWeightusvARB(size, weights); +} + +static void APIENTRY InitWeightuivARB (GLint size, const GLuint *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightuivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightuivARB = extproc; + + glWeightuivARB(size, weights); +} + +static void APIENTRY InitWeightPointerARB (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightPointerARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightPointerARB = extproc; + + glWeightPointerARB(size, type, stride, pointer); +} + +static void APIENTRY InitVertexBlendARB (GLint count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexBlendARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexBlendARB = extproc; + + glVertexBlendARB(count); +} + +static void APIENTRY InitCurrentPaletteMatrixARB (GLint index) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCurrentPaletteMatrixARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCurrentPaletteMatrixARB = extproc; + + glCurrentPaletteMatrixARB(index); +} + +static void APIENTRY InitMatrixIndexubvARB (GLint size, const GLubyte *indices) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMatrixIndexubvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMatrixIndexubvARB = extproc; + + glMatrixIndexubvARB(size, indices); +} + +static void APIENTRY InitMatrixIndexusvARB (GLint size, const GLushort *indices) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMatrixIndexusvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMatrixIndexusvARB = extproc; + + glMatrixIndexusvARB(size, indices); +} + +static void APIENTRY InitMatrixIndexuivARB (GLint size, const GLuint *indices) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMatrixIndexuivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMatrixIndexuivARB = extproc; + + glMatrixIndexuivARB(size, indices); +} + +static void APIENTRY InitMatrixIndexPointerARB (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMatrixIndexPointerARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMatrixIndexPointerARB = extproc; + + glMatrixIndexPointerARB(size, type, stride, pointer); +} + +static void APIENTRY InitWindowPos2dARB (GLdouble x, GLdouble y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2dARB = extproc; + + glWindowPos2dARB(x, y); +} + +static void APIENTRY InitWindowPos2dvARB (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2dvARB = extproc; + + glWindowPos2dvARB(v); +} + +static void APIENTRY InitWindowPos2fARB (GLfloat x, GLfloat y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2fARB = extproc; + + glWindowPos2fARB(x, y); +} + +static void APIENTRY InitWindowPos2fvARB (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2fvARB = extproc; + + glWindowPos2fvARB(v); +} + +static void APIENTRY InitWindowPos2iARB (GLint x, GLint y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2iARB = extproc; + + glWindowPos2iARB(x, y); +} + +static void APIENTRY InitWindowPos2ivARB (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2ivARB = extproc; + + glWindowPos2ivARB(v); +} + +static void APIENTRY InitWindowPos2sARB (GLshort x, GLshort y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2sARB = extproc; + + glWindowPos2sARB(x, y); +} + +static void APIENTRY InitWindowPos2svARB (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2svARB = extproc; + + glWindowPos2svARB(v); +} + +static void APIENTRY InitWindowPos3dARB (GLdouble x, GLdouble y, GLdouble z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3dARB = extproc; + + glWindowPos3dARB(x, y, z); +} + +static void APIENTRY InitWindowPos3dvARB (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3dvARB = extproc; + + glWindowPos3dvARB(v); +} + +static void APIENTRY InitWindowPos3fARB (GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3fARB = extproc; + + glWindowPos3fARB(x, y, z); +} + +static void APIENTRY InitWindowPos3fvARB (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3fvARB = extproc; + + glWindowPos3fvARB(v); +} + +static void APIENTRY InitWindowPos3iARB (GLint x, GLint y, GLint z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3iARB = extproc; + + glWindowPos3iARB(x, y, z); +} + +static void APIENTRY InitWindowPos3ivARB (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3ivARB = extproc; + + glWindowPos3ivARB(v); +} + +static void APIENTRY InitWindowPos3sARB (GLshort x, GLshort y, GLshort z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3sARB = extproc; + + glWindowPos3sARB(x, y, z); +} + +static void APIENTRY InitWindowPos3svARB (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3svARB = extproc; + + glWindowPos3svARB(v); +} + +static void APIENTRY InitVertexAttrib1dARB (GLuint index, GLdouble x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1dARB = extproc; + + glVertexAttrib1dARB(index, x); +} + +static void APIENTRY InitVertexAttrib1dvARB (GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1dvARB = extproc; + + glVertexAttrib1dvARB(index, v); +} + +static void APIENTRY InitVertexAttrib1fARB (GLuint index, GLfloat x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1fARB = extproc; + + glVertexAttrib1fARB(index, x); +} + +static void APIENTRY InitVertexAttrib1fvARB (GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1fvARB = extproc; + + glVertexAttrib1fvARB(index, v); +} + +static void APIENTRY InitVertexAttrib1sARB (GLuint index, GLshort x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1sARB = extproc; + + glVertexAttrib1sARB(index, x); +} + +static void APIENTRY InitVertexAttrib1svARB (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1svARB = extproc; + + glVertexAttrib1svARB(index, v); +} + +static void APIENTRY InitVertexAttrib2dARB (GLuint index, GLdouble x, GLdouble y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2dARB = extproc; + + glVertexAttrib2dARB(index, x, y); +} + +static void APIENTRY InitVertexAttrib2dvARB (GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2dvARB = extproc; + + glVertexAttrib2dvARB(index, v); +} + +static void APIENTRY InitVertexAttrib2fARB (GLuint index, GLfloat x, GLfloat y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2fARB = extproc; + + glVertexAttrib2fARB(index, x, y); +} + +static void APIENTRY InitVertexAttrib2fvARB (GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2fvARB = extproc; + + glVertexAttrib2fvARB(index, v); +} + +static void APIENTRY InitVertexAttrib2sARB (GLuint index, GLshort x, GLshort y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2sARB = extproc; + + glVertexAttrib2sARB(index, x, y); +} + +static void APIENTRY InitVertexAttrib2svARB (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2svARB = extproc; + + glVertexAttrib2svARB(index, v); +} + +static void APIENTRY InitVertexAttrib3dARB (GLuint index, GLdouble x, GLdouble y, GLdouble z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3dARB = extproc; + + glVertexAttrib3dARB(index, x, y, z); +} + +static void APIENTRY InitVertexAttrib3dvARB (GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3dvARB = extproc; + + glVertexAttrib3dvARB(index, v); +} + +static void APIENTRY InitVertexAttrib3fARB (GLuint index, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3fARB = extproc; + + glVertexAttrib3fARB(index, x, y, z); +} + +static void APIENTRY InitVertexAttrib3fvARB (GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3fvARB = extproc; + + glVertexAttrib3fvARB(index, v); +} + +static void APIENTRY InitVertexAttrib3sARB (GLuint index, GLshort x, GLshort y, GLshort z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3sARB = extproc; + + glVertexAttrib3sARB(index, x, y, z); +} + +static void APIENTRY InitVertexAttrib3svARB (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3svARB = extproc; + + glVertexAttrib3svARB(index, v); +} + +static void APIENTRY InitVertexAttrib4NbvARB (GLuint index, const GLbyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4NbvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4NbvARB = extproc; + + glVertexAttrib4NbvARB(index, v); +} + +static void APIENTRY InitVertexAttrib4NivARB (GLuint index, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4NivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4NivARB = extproc; + + glVertexAttrib4NivARB(index, v); +} + +static void APIENTRY InitVertexAttrib4NsvARB (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4NsvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4NsvARB = extproc; + + glVertexAttrib4NsvARB(index, v); +} + +static void APIENTRY InitVertexAttrib4NubARB (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4NubARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4NubARB = extproc; + + glVertexAttrib4NubARB(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4NubvARB (GLuint index, const GLubyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4NubvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4NubvARB = extproc; + + glVertexAttrib4NubvARB(index, v); +} + +static void APIENTRY InitVertexAttrib4NuivARB (GLuint index, const GLuint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4NuivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4NuivARB = extproc; + + glVertexAttrib4NuivARB(index, v); +} + +static void APIENTRY InitVertexAttrib4NusvARB (GLuint index, const GLushort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4NusvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4NusvARB = extproc; + + glVertexAttrib4NusvARB(index, v); +} + +static void APIENTRY InitVertexAttrib4bvARB (GLuint index, const GLbyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4bvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4bvARB = extproc; + + glVertexAttrib4bvARB(index, v); +} + +static void APIENTRY InitVertexAttrib4dARB (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4dARB = extproc; + + glVertexAttrib4dARB(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4dvARB (GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4dvARB = extproc; + + glVertexAttrib4dvARB(index, v); +} + +static void APIENTRY InitVertexAttrib4fARB (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4fARB = extproc; + + glVertexAttrib4fARB(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4fvARB (GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4fvARB = extproc; + + glVertexAttrib4fvARB(index, v); +} + +static void APIENTRY InitVertexAttrib4ivARB (GLuint index, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4ivARB = extproc; + + glVertexAttrib4ivARB(index, v); +} + +static void APIENTRY InitVertexAttrib4sARB (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4sARB = extproc; + + glVertexAttrib4sARB(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4svARB (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4svARB = extproc; + + glVertexAttrib4svARB(index, v); +} + +static void APIENTRY InitVertexAttrib4ubvARB (GLuint index, const GLubyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4ubvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4ubvARB = extproc; + + glVertexAttrib4ubvARB(index, v); +} + +static void APIENTRY InitVertexAttrib4uivARB (GLuint index, const GLuint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4uivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4uivARB = extproc; + + glVertexAttrib4uivARB(index, v); +} + +static void APIENTRY InitVertexAttrib4usvARB (GLuint index, const GLushort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4usvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4usvARB = extproc; + + glVertexAttrib4usvARB(index, v); +} + +static void APIENTRY InitVertexAttribPointerARB (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribPointerARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribPointerARB = extproc; + + glVertexAttribPointerARB(index, size, type, normalized, stride, pointer); +} + +static void APIENTRY InitEnableVertexAttribArrayARB (GLuint index) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEnableVertexAttribArrayARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEnableVertexAttribArrayARB = extproc; + + glEnableVertexAttribArrayARB(index); +} + +static void APIENTRY InitDisableVertexAttribArrayARB (GLuint index) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDisableVertexAttribArrayARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDisableVertexAttribArrayARB = extproc; + + glDisableVertexAttribArrayARB(index); +} + +static void APIENTRY InitProgramStringARB (GLenum target, GLenum format, GLsizei len, const GLvoid *string) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramStringARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramStringARB = extproc; + + glProgramStringARB(target, format, len, string); +} + +static void APIENTRY InitBindProgramARB (GLenum target, GLuint program) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindProgramARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindProgramARB = extproc; + + glBindProgramARB(target, program); +} + +static void APIENTRY InitDeleteProgramsARB (GLsizei n, const GLuint *programs) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteProgramsARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteProgramsARB = extproc; + + glDeleteProgramsARB(n, programs); +} + +static void APIENTRY InitGenProgramsARB (GLsizei n, GLuint *programs) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenProgramsARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenProgramsARB = extproc; + + glGenProgramsARB(n, programs); +} + +static void APIENTRY InitProgramEnvParameter4dARB (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramEnvParameter4dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramEnvParameter4dARB = extproc; + + glProgramEnvParameter4dARB(target, index, x, y, z, w); +} + +static void APIENTRY InitProgramEnvParameter4dvARB (GLenum target, GLuint index, const GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramEnvParameter4dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramEnvParameter4dvARB = extproc; + + glProgramEnvParameter4dvARB(target, index, params); +} + +static void APIENTRY InitProgramEnvParameter4fARB (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramEnvParameter4fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramEnvParameter4fARB = extproc; + + glProgramEnvParameter4fARB(target, index, x, y, z, w); +} + +static void APIENTRY InitProgramEnvParameter4fvARB (GLenum target, GLuint index, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramEnvParameter4fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramEnvParameter4fvARB = extproc; + + glProgramEnvParameter4fvARB(target, index, params); +} + +static void APIENTRY InitProgramLocalParameter4dARB (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramLocalParameter4dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramLocalParameter4dARB = extproc; + + glProgramLocalParameter4dARB(target, index, x, y, z, w); +} + +static void APIENTRY InitProgramLocalParameter4dvARB (GLenum target, GLuint index, const GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramLocalParameter4dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramLocalParameter4dvARB = extproc; + + glProgramLocalParameter4dvARB(target, index, params); +} + +static void APIENTRY InitProgramLocalParameter4fARB (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramLocalParameter4fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramLocalParameter4fARB = extproc; + + glProgramLocalParameter4fARB(target, index, x, y, z, w); +} + +static void APIENTRY InitProgramLocalParameter4fvARB (GLenum target, GLuint index, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramLocalParameter4fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramLocalParameter4fvARB = extproc; + + glProgramLocalParameter4fvARB(target, index, params); +} + +static void APIENTRY InitGetProgramEnvParameterdvARB (GLenum target, GLuint index, GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramEnvParameterdvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramEnvParameterdvARB = extproc; + + glGetProgramEnvParameterdvARB(target, index, params); +} + +static void APIENTRY InitGetProgramEnvParameterfvARB (GLenum target, GLuint index, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramEnvParameterfvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramEnvParameterfvARB = extproc; + + glGetProgramEnvParameterfvARB(target, index, params); +} + +static void APIENTRY InitGetProgramLocalParameterdvARB (GLenum target, GLuint index, GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramLocalParameterdvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramLocalParameterdvARB = extproc; + + glGetProgramLocalParameterdvARB(target, index, params); +} + +static void APIENTRY InitGetProgramLocalParameterfvARB (GLenum target, GLuint index, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramLocalParameterfvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramLocalParameterfvARB = extproc; + + glGetProgramLocalParameterfvARB(target, index, params); +} + +static void APIENTRY InitGetProgramivARB (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramivARB = extproc; + + glGetProgramivARB(target, pname, params); +} + +static void APIENTRY InitGetProgramStringARB (GLenum target, GLenum pname, GLvoid *string) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramStringARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramStringARB = extproc; + + glGetProgramStringARB(target, pname, string); +} + +static void APIENTRY InitGetVertexAttribdvARB (GLuint index, GLenum pname, GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribdvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribdvARB = extproc; + + glGetVertexAttribdvARB(index, pname, params); +} + +static void APIENTRY InitGetVertexAttribfvARB (GLuint index, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribfvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribfvARB = extproc; + + glGetVertexAttribfvARB(index, pname, params); +} + +static void APIENTRY InitGetVertexAttribivARB (GLuint index, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribivARB = extproc; + + glGetVertexAttribivARB(index, pname, params); +} + +static void APIENTRY InitGetVertexAttribPointervARB (GLuint index, GLenum pname, GLvoid* *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribPointervARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribPointervARB = extproc; + + glGetVertexAttribPointervARB(index, pname, pointer); +} + +static GLboolean APIENTRY InitIsProgramARB (GLuint program) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsProgramARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsProgramARB = extproc; + + return glIsProgramARB(program); +} + +static void APIENTRY InitBindBufferARB (GLenum target, GLuint buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindBufferARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindBufferARB = extproc; + + glBindBufferARB(target, buffer); +} + +static void APIENTRY InitDeleteBuffersARB (GLsizei n, const GLuint *buffers) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteBuffersARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteBuffersARB = extproc; + + glDeleteBuffersARB(n, buffers); +} + +static void APIENTRY InitGenBuffersARB (GLsizei n, GLuint *buffers) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenBuffersARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenBuffersARB = extproc; + + glGenBuffersARB(n, buffers); +} + +static GLboolean APIENTRY InitIsBufferARB (GLuint buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsBufferARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsBufferARB = extproc; + + return glIsBufferARB(buffer); +} + +static void APIENTRY InitBufferDataARB (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBufferDataARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBufferDataARB = extproc; + + glBufferDataARB(target, size, data, usage); +} + +static void APIENTRY InitBufferSubDataARB (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBufferSubDataARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBufferSubDataARB = extproc; + + glBufferSubDataARB(target, offset, size, data); +} + +static void APIENTRY InitGetBufferSubDataARB (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetBufferSubDataARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetBufferSubDataARB = extproc; + + glGetBufferSubDataARB(target, offset, size, data); +} + +static GLvoid* APIENTRY InitMapBufferARB (GLenum target, GLenum access) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMapBufferARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glMapBufferARB = extproc; + + return glMapBufferARB(target, access); +} + +static GLboolean APIENTRY InitUnmapBufferARB (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUnmapBufferARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glUnmapBufferARB = extproc; + + return glUnmapBufferARB(target); +} + +static void APIENTRY InitGetBufferParameterivARB (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetBufferParameterivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetBufferParameterivARB = extproc; + + glGetBufferParameterivARB(target, pname, params); +} + +static void APIENTRY InitGetBufferPointervARB (GLenum target, GLenum pname, GLvoid* *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetBufferPointervARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetBufferPointervARB = extproc; + + glGetBufferPointervARB(target, pname, params); +} + +static void APIENTRY InitGenQueriesARB (GLsizei n, GLuint *ids) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenQueriesARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenQueriesARB = extproc; + + glGenQueriesARB(n, ids); +} + +static void APIENTRY InitDeleteQueriesARB (GLsizei n, const GLuint *ids) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteQueriesARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteQueriesARB = extproc; + + glDeleteQueriesARB(n, ids); +} + +static GLboolean APIENTRY InitIsQueryARB (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsQueryARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsQueryARB = extproc; + + return glIsQueryARB(id); +} + +static void APIENTRY InitBeginQueryARB (GLenum target, GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBeginQueryARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBeginQueryARB = extproc; + + glBeginQueryARB(target, id); +} + +static void APIENTRY InitEndQueryARB (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEndQueryARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEndQueryARB = extproc; + + glEndQueryARB(target); +} + +static void APIENTRY InitGetQueryivARB (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetQueryivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetQueryivARB = extproc; + + glGetQueryivARB(target, pname, params); +} + +static void APIENTRY InitGetQueryObjectivARB (GLuint id, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetQueryObjectivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetQueryObjectivARB = extproc; + + glGetQueryObjectivARB(id, pname, params); +} + +static void APIENTRY InitGetQueryObjectuivARB (GLuint id, GLenum pname, GLuint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetQueryObjectuivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetQueryObjectuivARB = extproc; + + glGetQueryObjectuivARB(id, pname, params); +} + +static void APIENTRY InitDeleteObjectARB (GLhandleARB obj) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteObjectARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteObjectARB = extproc; + + glDeleteObjectARB(obj); +} + +static GLhandleARB APIENTRY InitGetHandleARB (GLenum pname) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetHandleARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glGetHandleARB = extproc; + + return glGetHandleARB(pname); +} + +static void APIENTRY InitDetachObjectARB (GLhandleARB containerObj, GLhandleARB attachedObj) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDetachObjectARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDetachObjectARB = extproc; + + glDetachObjectARB(containerObj, attachedObj); +} + +static GLhandleARB APIENTRY InitCreateShaderObjectARB (GLenum shaderType) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCreateShaderObjectARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glCreateShaderObjectARB = extproc; + + return glCreateShaderObjectARB(shaderType); +} + +static void APIENTRY InitShaderSourceARB (GLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glShaderSourceARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glShaderSourceARB = extproc; + + glShaderSourceARB(shaderObj, count, string, length); +} + +static void APIENTRY InitCompileShaderARB (GLhandleARB shaderObj) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompileShaderARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompileShaderARB = extproc; + + glCompileShaderARB(shaderObj); +} + +static GLhandleARB APIENTRY InitCreateProgramObjectARB (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCreateProgramObjectARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glCreateProgramObjectARB = extproc; + + return glCreateProgramObjectARB(); +} + +static void APIENTRY InitAttachObjectARB (GLhandleARB containerObj, GLhandleARB obj) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glAttachObjectARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glAttachObjectARB = extproc; + + glAttachObjectARB(containerObj, obj); +} + +static void APIENTRY InitLinkProgramARB (GLhandleARB programObj) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLinkProgramARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLinkProgramARB = extproc; + + glLinkProgramARB(programObj); +} + +static void APIENTRY InitUseProgramObjectARB (GLhandleARB programObj) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUseProgramObjectARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUseProgramObjectARB = extproc; + + glUseProgramObjectARB(programObj); +} + +static void APIENTRY InitValidateProgramARB (GLhandleARB programObj) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glValidateProgramARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glValidateProgramARB = extproc; + + glValidateProgramARB(programObj); +} + +static void APIENTRY InitUniform1fARB (GLint location, GLfloat v0) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform1fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform1fARB = extproc; + + glUniform1fARB(location, v0); +} + +static void APIENTRY InitUniform2fARB (GLint location, GLfloat v0, GLfloat v1) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform2fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform2fARB = extproc; + + glUniform2fARB(location, v0, v1); +} + +static void APIENTRY InitUniform3fARB (GLint location, GLfloat v0, GLfloat v1, GLfloat v2) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform3fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform3fARB = extproc; + + glUniform3fARB(location, v0, v1, v2); +} + +static void APIENTRY InitUniform4fARB (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform4fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform4fARB = extproc; + + glUniform4fARB(location, v0, v1, v2, v3); +} + +static void APIENTRY InitUniform1iARB (GLint location, GLint v0) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform1iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform1iARB = extproc; + + glUniform1iARB(location, v0); +} + +static void APIENTRY InitUniform2iARB (GLint location, GLint v0, GLint v1) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform2iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform2iARB = extproc; + + glUniform2iARB(location, v0, v1); +} + +static void APIENTRY InitUniform3iARB (GLint location, GLint v0, GLint v1, GLint v2) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform3iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform3iARB = extproc; + + glUniform3iARB(location, v0, v1, v2); +} + +static void APIENTRY InitUniform4iARB (GLint location, GLint v0, GLint v1, GLint v2, GLint v3) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform4iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform4iARB = extproc; + + glUniform4iARB(location, v0, v1, v2, v3); +} + +static void APIENTRY InitUniform1fvARB (GLint location, GLsizei count, const GLfloat *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform1fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform1fvARB = extproc; + + glUniform1fvARB(location, count, value); +} + +static void APIENTRY InitUniform2fvARB (GLint location, GLsizei count, const GLfloat *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform2fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform2fvARB = extproc; + + glUniform2fvARB(location, count, value); +} + +static void APIENTRY InitUniform3fvARB (GLint location, GLsizei count, const GLfloat *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform3fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform3fvARB = extproc; + + glUniform3fvARB(location, count, value); +} + +static void APIENTRY InitUniform4fvARB (GLint location, GLsizei count, const GLfloat *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform4fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform4fvARB = extproc; + + glUniform4fvARB(location, count, value); +} + +static void APIENTRY InitUniform1ivARB (GLint location, GLsizei count, const GLint *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform1ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform1ivARB = extproc; + + glUniform1ivARB(location, count, value); +} + +static void APIENTRY InitUniform2ivARB (GLint location, GLsizei count, const GLint *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform2ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform2ivARB = extproc; + + glUniform2ivARB(location, count, value); +} + +static void APIENTRY InitUniform3ivARB (GLint location, GLsizei count, const GLint *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform3ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform3ivARB = extproc; + + glUniform3ivARB(location, count, value); +} + +static void APIENTRY InitUniform4ivARB (GLint location, GLsizei count, const GLint *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform4ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform4ivARB = extproc; + + glUniform4ivARB(location, count, value); +} + +static void APIENTRY InitUniformMatrix2fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniformMatrix2fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniformMatrix2fvARB = extproc; + + glUniformMatrix2fvARB(location, count, transpose, value); +} + +static void APIENTRY InitUniformMatrix3fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniformMatrix3fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniformMatrix3fvARB = extproc; + + glUniformMatrix3fvARB(location, count, transpose, value); +} + +static void APIENTRY InitUniformMatrix4fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniformMatrix4fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniformMatrix4fvARB = extproc; + + glUniformMatrix4fvARB(location, count, transpose, value); +} + +static void APIENTRY InitGetObjectParameterfvARB (GLhandleARB obj, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetObjectParameterfvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetObjectParameterfvARB = extproc; + + glGetObjectParameterfvARB(obj, pname, params); +} + +static void APIENTRY InitGetObjectParameterivARB (GLhandleARB obj, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetObjectParameterivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetObjectParameterivARB = extproc; + + glGetObjectParameterivARB(obj, pname, params); +} + +static void APIENTRY InitGetInfoLogARB (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetInfoLogARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetInfoLogARB = extproc; + + glGetInfoLogARB(obj, maxLength, length, infoLog); +} + +static void APIENTRY InitGetAttachedObjectsARB (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetAttachedObjectsARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetAttachedObjectsARB = extproc; + + glGetAttachedObjectsARB(containerObj, maxCount, count, obj); +} + +static GLint APIENTRY InitGetUniformLocationARB (GLhandleARB programObj, const GLcharARB *name) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetUniformLocationARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glGetUniformLocationARB = extproc; + + return glGetUniformLocationARB(programObj, name); +} + +static void APIENTRY InitGetActiveUniformARB (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetActiveUniformARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetActiveUniformARB = extproc; + + glGetActiveUniformARB(programObj, index, maxLength, length, size, type, name); +} + +static void APIENTRY InitGetUniformfvARB (GLhandleARB programObj, GLint location, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetUniformfvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetUniformfvARB = extproc; + + glGetUniformfvARB(programObj, location, params); +} + +static void APIENTRY InitGetUniformivARB (GLhandleARB programObj, GLint location, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetUniformivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetUniformivARB = extproc; + + glGetUniformivARB(programObj, location, params); +} + +static void APIENTRY InitGetShaderSourceARB (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetShaderSourceARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetShaderSourceARB = extproc; + + glGetShaderSourceARB(obj, maxLength, length, source); +} + +static void APIENTRY InitBindAttribLocationARB (GLhandleARB programObj, GLuint index, const GLcharARB *name) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindAttribLocationARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindAttribLocationARB = extproc; + + glBindAttribLocationARB(programObj, index, name); +} + +static void APIENTRY InitGetActiveAttribARB (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetActiveAttribARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetActiveAttribARB = extproc; + + glGetActiveAttribARB(programObj, index, maxLength, length, size, type, name); +} + +static GLint APIENTRY InitGetAttribLocationARB (GLhandleARB programObj, const GLcharARB *name) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetAttribLocationARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glGetAttribLocationARB = extproc; + + return glGetAttribLocationARB(programObj, name); +} + +static void APIENTRY InitBlendColorEXT (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBlendColorEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBlendColorEXT = extproc; + + glBlendColorEXT(red, green, blue, alpha); +} + +static void APIENTRY InitPolygonOffsetEXT (GLfloat factor, GLfloat bias) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPolygonOffsetEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPolygonOffsetEXT = extproc; + + glPolygonOffsetEXT(factor, bias); +} + +static void APIENTRY InitTexImage3DEXT (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexImage3DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexImage3DEXT = extproc; + + glTexImage3DEXT(target, level, internalformat, width, height, depth, border, format, type, pixels); +} + +static void APIENTRY InitTexSubImage3DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexSubImage3DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexSubImage3DEXT = extproc; + + glTexSubImage3DEXT(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); +} + +static void APIENTRY InitGetTexFilterFuncSGIS (GLenum target, GLenum filter, GLfloat *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetTexFilterFuncSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetTexFilterFuncSGIS = extproc; + + glGetTexFilterFuncSGIS(target, filter, weights); +} + +static void APIENTRY InitTexFilterFuncSGIS (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexFilterFuncSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexFilterFuncSGIS = extproc; + + glTexFilterFuncSGIS(target, filter, n, weights); +} + +static void APIENTRY InitTexSubImage1DEXT (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexSubImage1DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexSubImage1DEXT = extproc; + + glTexSubImage1DEXT(target, level, xoffset, width, format, type, pixels); +} + +static void APIENTRY InitTexSubImage2DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexSubImage2DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexSubImage2DEXT = extproc; + + glTexSubImage2DEXT(target, level, xoffset, yoffset, width, height, format, type, pixels); +} + +static void APIENTRY InitCopyTexImage1DEXT (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyTexImage1DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyTexImage1DEXT = extproc; + + glCopyTexImage1DEXT(target, level, internalformat, x, y, width, border); +} + +static void APIENTRY InitCopyTexImage2DEXT (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyTexImage2DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyTexImage2DEXT = extproc; + + glCopyTexImage2DEXT(target, level, internalformat, x, y, width, height, border); +} + +static void APIENTRY InitCopyTexSubImage1DEXT (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyTexSubImage1DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyTexSubImage1DEXT = extproc; + + glCopyTexSubImage1DEXT(target, level, xoffset, x, y, width); +} + +static void APIENTRY InitCopyTexSubImage2DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyTexSubImage2DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyTexSubImage2DEXT = extproc; + + glCopyTexSubImage2DEXT(target, level, xoffset, yoffset, x, y, width, height); +} + +static void APIENTRY InitCopyTexSubImage3DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyTexSubImage3DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyTexSubImage3DEXT = extproc; + + glCopyTexSubImage3DEXT(target, level, xoffset, yoffset, zoffset, x, y, width, height); +} + +static void APIENTRY InitGetHistogramEXT (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetHistogramEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetHistogramEXT = extproc; + + glGetHistogramEXT(target, reset, format, type, values); +} + +static void APIENTRY InitGetHistogramParameterfvEXT (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetHistogramParameterfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetHistogramParameterfvEXT = extproc; + + glGetHistogramParameterfvEXT(target, pname, params); +} + +static void APIENTRY InitGetHistogramParameterivEXT (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetHistogramParameterivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetHistogramParameterivEXT = extproc; + + glGetHistogramParameterivEXT(target, pname, params); +} + +static void APIENTRY InitGetMinmaxEXT (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMinmaxEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMinmaxEXT = extproc; + + glGetMinmaxEXT(target, reset, format, type, values); +} + +static void APIENTRY InitGetMinmaxParameterfvEXT (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMinmaxParameterfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMinmaxParameterfvEXT = extproc; + + glGetMinmaxParameterfvEXT(target, pname, params); +} + +static void APIENTRY InitGetMinmaxParameterivEXT (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMinmaxParameterivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMinmaxParameterivEXT = extproc; + + glGetMinmaxParameterivEXT(target, pname, params); +} + +static void APIENTRY InitHistogramEXT (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glHistogramEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glHistogramEXT = extproc; + + glHistogramEXT(target, width, internalformat, sink); +} + +static void APIENTRY InitMinmaxEXT (GLenum target, GLenum internalformat, GLboolean sink) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMinmaxEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMinmaxEXT = extproc; + + glMinmaxEXT(target, internalformat, sink); +} + +static void APIENTRY InitResetHistogramEXT (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glResetHistogramEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glResetHistogramEXT = extproc; + + glResetHistogramEXT(target); +} + +static void APIENTRY InitResetMinmaxEXT (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glResetMinmaxEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glResetMinmaxEXT = extproc; + + glResetMinmaxEXT(target); +} + +static void APIENTRY InitConvolutionFilter1DEXT (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionFilter1DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionFilter1DEXT = extproc; + + glConvolutionFilter1DEXT(target, internalformat, width, format, type, image); +} + +static void APIENTRY InitConvolutionFilter2DEXT (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionFilter2DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionFilter2DEXT = extproc; + + glConvolutionFilter2DEXT(target, internalformat, width, height, format, type, image); +} + +static void APIENTRY InitConvolutionParameterfEXT (GLenum target, GLenum pname, GLfloat params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionParameterfEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionParameterfEXT = extproc; + + glConvolutionParameterfEXT(target, pname, params); +} + +static void APIENTRY InitConvolutionParameterfvEXT (GLenum target, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionParameterfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionParameterfvEXT = extproc; + + glConvolutionParameterfvEXT(target, pname, params); +} + +static void APIENTRY InitConvolutionParameteriEXT (GLenum target, GLenum pname, GLint params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionParameteriEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionParameteriEXT = extproc; + + glConvolutionParameteriEXT(target, pname, params); +} + +static void APIENTRY InitConvolutionParameterivEXT (GLenum target, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionParameterivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionParameterivEXT = extproc; + + glConvolutionParameterivEXT(target, pname, params); +} + +static void APIENTRY InitCopyConvolutionFilter1DEXT (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyConvolutionFilter1DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyConvolutionFilter1DEXT = extproc; + + glCopyConvolutionFilter1DEXT(target, internalformat, x, y, width); +} + +static void APIENTRY InitCopyConvolutionFilter2DEXT (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyConvolutionFilter2DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyConvolutionFilter2DEXT = extproc; + + glCopyConvolutionFilter2DEXT(target, internalformat, x, y, width, height); +} + +static void APIENTRY InitGetConvolutionFilterEXT (GLenum target, GLenum format, GLenum type, GLvoid *image) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetConvolutionFilterEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetConvolutionFilterEXT = extproc; + + glGetConvolutionFilterEXT(target, format, type, image); +} + +static void APIENTRY InitGetConvolutionParameterfvEXT (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetConvolutionParameterfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetConvolutionParameterfvEXT = extproc; + + glGetConvolutionParameterfvEXT(target, pname, params); +} + +static void APIENTRY InitGetConvolutionParameterivEXT (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetConvolutionParameterivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetConvolutionParameterivEXT = extproc; + + glGetConvolutionParameterivEXT(target, pname, params); +} + +static void APIENTRY InitGetSeparableFilterEXT (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetSeparableFilterEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetSeparableFilterEXT = extproc; + + glGetSeparableFilterEXT(target, format, type, row, column, span); +} + +static void APIENTRY InitSeparableFilter2DEXT (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSeparableFilter2DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSeparableFilter2DEXT = extproc; + + glSeparableFilter2DEXT(target, internalformat, width, height, format, type, row, column); +} + +static void APIENTRY InitColorTableSGI (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorTableSGI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorTableSGI = extproc; + + glColorTableSGI(target, internalformat, width, format, type, table); +} + +static void APIENTRY InitColorTableParameterfvSGI (GLenum target, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorTableParameterfvSGI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorTableParameterfvSGI = extproc; + + glColorTableParameterfvSGI(target, pname, params); +} + +static void APIENTRY InitColorTableParameterivSGI (GLenum target, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorTableParameterivSGI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorTableParameterivSGI = extproc; + + glColorTableParameterivSGI(target, pname, params); +} + +static void APIENTRY InitCopyColorTableSGI (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyColorTableSGI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyColorTableSGI = extproc; + + glCopyColorTableSGI(target, internalformat, x, y, width); +} + +static void APIENTRY InitGetColorTableSGI (GLenum target, GLenum format, GLenum type, GLvoid *table) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTableSGI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTableSGI = extproc; + + glGetColorTableSGI(target, format, type, table); +} + +static void APIENTRY InitGetColorTableParameterfvSGI (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTableParameterfvSGI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTableParameterfvSGI = extproc; + + glGetColorTableParameterfvSGI(target, pname, params); +} + +static void APIENTRY InitGetColorTableParameterivSGI (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTableParameterivSGI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTableParameterivSGI = extproc; + + glGetColorTableParameterivSGI(target, pname, params); +} + +static void APIENTRY InitPixelTexGenSGIX (GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTexGenSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTexGenSGIX = extproc; + + glPixelTexGenSGIX(mode); +} + +static void APIENTRY InitPixelTexGenParameteriSGIS (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTexGenParameteriSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTexGenParameteriSGIS = extproc; + + glPixelTexGenParameteriSGIS(pname, param); +} + +static void APIENTRY InitPixelTexGenParameterivSGIS (GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTexGenParameterivSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTexGenParameterivSGIS = extproc; + + glPixelTexGenParameterivSGIS(pname, params); +} + +static void APIENTRY InitPixelTexGenParameterfSGIS (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTexGenParameterfSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTexGenParameterfSGIS = extproc; + + glPixelTexGenParameterfSGIS(pname, param); +} + +static void APIENTRY InitPixelTexGenParameterfvSGIS (GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTexGenParameterfvSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTexGenParameterfvSGIS = extproc; + + glPixelTexGenParameterfvSGIS(pname, params); +} + +static void APIENTRY InitGetPixelTexGenParameterivSGIS (GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetPixelTexGenParameterivSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetPixelTexGenParameterivSGIS = extproc; + + glGetPixelTexGenParameterivSGIS(pname, params); +} + +static void APIENTRY InitGetPixelTexGenParameterfvSGIS (GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetPixelTexGenParameterfvSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetPixelTexGenParameterfvSGIS = extproc; + + glGetPixelTexGenParameterfvSGIS(pname, params); +} + +static void APIENTRY InitTexImage4DSGIS (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const GLvoid *pixels) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexImage4DSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexImage4DSGIS = extproc; + + glTexImage4DSGIS(target, level, internalformat, width, height, depth, size4d, border, format, type, pixels); +} + +static void APIENTRY InitTexSubImage4DSGIS (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const GLvoid *pixels) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexSubImage4DSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexSubImage4DSGIS = extproc; + + glTexSubImage4DSGIS(target, level, xoffset, yoffset, zoffset, woffset, width, height, depth, size4d, format, type, pixels); +} + +static GLboolean APIENTRY InitAreTexturesResidentEXT (GLsizei n, const GLuint *textures, GLboolean *residences) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glAreTexturesResidentEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glAreTexturesResidentEXT = extproc; + + return glAreTexturesResidentEXT(n, textures, residences); +} + +static void APIENTRY InitBindTextureEXT (GLenum target, GLuint texture) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindTextureEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindTextureEXT = extproc; + + glBindTextureEXT(target, texture); +} + +static void APIENTRY InitDeleteTexturesEXT (GLsizei n, const GLuint *textures) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteTexturesEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteTexturesEXT = extproc; + + glDeleteTexturesEXT(n, textures); +} + +static void APIENTRY InitGenTexturesEXT (GLsizei n, GLuint *textures) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenTexturesEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenTexturesEXT = extproc; + + glGenTexturesEXT(n, textures); +} + +static GLboolean APIENTRY InitIsTextureEXT (GLuint texture) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsTextureEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsTextureEXT = extproc; + + return glIsTextureEXT(texture); +} + +static void APIENTRY InitPrioritizeTexturesEXT (GLsizei n, const GLuint *textures, const GLclampf *priorities) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPrioritizeTexturesEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPrioritizeTexturesEXT = extproc; + + glPrioritizeTexturesEXT(n, textures, priorities); +} + +static void APIENTRY InitDetailTexFuncSGIS (GLenum target, GLsizei n, const GLfloat *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDetailTexFuncSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDetailTexFuncSGIS = extproc; + + glDetailTexFuncSGIS(target, n, points); +} + +static void APIENTRY InitGetDetailTexFuncSGIS (GLenum target, GLfloat *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetDetailTexFuncSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetDetailTexFuncSGIS = extproc; + + glGetDetailTexFuncSGIS(target, points); +} + +static void APIENTRY InitSharpenTexFuncSGIS (GLenum target, GLsizei n, const GLfloat *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSharpenTexFuncSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSharpenTexFuncSGIS = extproc; + + glSharpenTexFuncSGIS(target, n, points); +} + +static void APIENTRY InitGetSharpenTexFuncSGIS (GLenum target, GLfloat *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetSharpenTexFuncSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetSharpenTexFuncSGIS = extproc; + + glGetSharpenTexFuncSGIS(target, points); +} + +static void APIENTRY InitSampleMaskSGIS (GLclampf value, GLboolean invert) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSampleMaskSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSampleMaskSGIS = extproc; + + glSampleMaskSGIS(value, invert); +} + +static void APIENTRY InitSamplePatternSGIS (GLenum pattern) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSamplePatternSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSamplePatternSGIS = extproc; + + glSamplePatternSGIS(pattern); +} + +static void APIENTRY InitArrayElementEXT (GLint i) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glArrayElementEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glArrayElementEXT = extproc; + + glArrayElementEXT(i); +} + +static void APIENTRY InitColorPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorPointerEXT = extproc; + + glColorPointerEXT(size, type, stride, count, pointer); +} + +static void APIENTRY InitDrawArraysEXT (GLenum mode, GLint first, GLsizei count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawArraysEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawArraysEXT = extproc; + + glDrawArraysEXT(mode, first, count); +} + +static void APIENTRY InitEdgeFlagPointerEXT (GLsizei stride, GLsizei count, const GLboolean *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEdgeFlagPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEdgeFlagPointerEXT = extproc; + + glEdgeFlagPointerEXT(stride, count, pointer); +} + +static void APIENTRY InitGetPointervEXT (GLenum pname, GLvoid* *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetPointervEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetPointervEXT = extproc; + + glGetPointervEXT(pname, params); +} + +static void APIENTRY InitIndexPointerEXT (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIndexPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glIndexPointerEXT = extproc; + + glIndexPointerEXT(type, stride, count, pointer); +} + +static void APIENTRY InitNormalPointerEXT (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalPointerEXT = extproc; + + glNormalPointerEXT(type, stride, count, pointer); +} + +static void APIENTRY InitTexCoordPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoordPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoordPointerEXT = extproc; + + glTexCoordPointerEXT(size, type, stride, count, pointer); +} + +static void APIENTRY InitVertexPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexPointerEXT = extproc; + + glVertexPointerEXT(size, type, stride, count, pointer); +} + +static void APIENTRY InitBlendEquationEXT (GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBlendEquationEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBlendEquationEXT = extproc; + + glBlendEquationEXT(mode); +} + +static void APIENTRY InitSpriteParameterfSGIX (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSpriteParameterfSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSpriteParameterfSGIX = extproc; + + glSpriteParameterfSGIX(pname, param); +} + +static void APIENTRY InitSpriteParameterfvSGIX (GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSpriteParameterfvSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSpriteParameterfvSGIX = extproc; + + glSpriteParameterfvSGIX(pname, params); +} + +static void APIENTRY InitSpriteParameteriSGIX (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSpriteParameteriSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSpriteParameteriSGIX = extproc; + + glSpriteParameteriSGIX(pname, param); +} + +static void APIENTRY InitSpriteParameterivSGIX (GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSpriteParameterivSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSpriteParameterivSGIX = extproc; + + glSpriteParameterivSGIX(pname, params); +} + +static void APIENTRY InitPointParameterfEXT (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterfEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterfEXT = extproc; + + glPointParameterfEXT(pname, param); +} + +static void APIENTRY InitPointParameterfvEXT (GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterfvEXT = extproc; + + glPointParameterfvEXT(pname, params); +} + +static void APIENTRY InitPointParameterfSGIS (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterfSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterfSGIS = extproc; + + glPointParameterfSGIS(pname, param); +} + +static void APIENTRY InitPointParameterfvSGIS (GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterfvSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterfvSGIS = extproc; + + glPointParameterfvSGIS(pname, params); +} + +static GLint APIENTRY InitGetInstrumentsSGIX (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetInstrumentsSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glGetInstrumentsSGIX = extproc; + + return glGetInstrumentsSGIX(); +} + +static void APIENTRY InitInstrumentsBufferSGIX (GLsizei size, GLint *buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glInstrumentsBufferSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glInstrumentsBufferSGIX = extproc; + + glInstrumentsBufferSGIX(size, buffer); +} + +static GLint APIENTRY InitPollInstrumentsSGIX (GLint *marker_p) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPollInstrumentsSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glPollInstrumentsSGIX = extproc; + + return glPollInstrumentsSGIX(marker_p); +} + +static void APIENTRY InitReadInstrumentsSGIX (GLint marker) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReadInstrumentsSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReadInstrumentsSGIX = extproc; + + glReadInstrumentsSGIX(marker); +} + +static void APIENTRY InitStartInstrumentsSGIX (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glStartInstrumentsSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glStartInstrumentsSGIX = extproc; + + glStartInstrumentsSGIX(); +} + +static void APIENTRY InitStopInstrumentsSGIX (GLint marker) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glStopInstrumentsSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glStopInstrumentsSGIX = extproc; + + glStopInstrumentsSGIX(marker); +} + +static void APIENTRY InitFrameZoomSGIX (GLint factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFrameZoomSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFrameZoomSGIX = extproc; + + glFrameZoomSGIX(factor); +} + +static void APIENTRY InitTagSampleBufferSGIX (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTagSampleBufferSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTagSampleBufferSGIX = extproc; + + glTagSampleBufferSGIX(); +} + +static void APIENTRY InitDeformationMap3dSGIX (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeformationMap3dSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeformationMap3dSGIX = extproc; + + glDeformationMap3dSGIX(target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, w1, w2, wstride, worder, points); +} + +static void APIENTRY InitDeformationMap3fSGIX (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeformationMap3fSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeformationMap3fSGIX = extproc; + + glDeformationMap3fSGIX(target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, w1, w2, wstride, worder, points); +} + +static void APIENTRY InitDeformSGIX (GLbitfield mask) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeformSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeformSGIX = extproc; + + glDeformSGIX(mask); +} + +static void APIENTRY InitLoadIdentityDeformationMapSGIX (GLbitfield mask) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLoadIdentityDeformationMapSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLoadIdentityDeformationMapSGIX = extproc; + + glLoadIdentityDeformationMapSGIX(mask); +} + +static void APIENTRY InitReferencePlaneSGIX (const GLdouble *equation) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReferencePlaneSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReferencePlaneSGIX = extproc; + + glReferencePlaneSGIX(equation); +} + +static void APIENTRY InitFlushRasterSGIX (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFlushRasterSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFlushRasterSGIX = extproc; + + glFlushRasterSGIX(); +} + +static void APIENTRY InitFogFuncSGIS (GLsizei n, const GLfloat *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogFuncSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogFuncSGIS = extproc; + + glFogFuncSGIS(n, points); +} + +static void APIENTRY InitGetFogFuncSGIS (GLfloat *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetFogFuncSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetFogFuncSGIS = extproc; + + glGetFogFuncSGIS(points); +} + +static void APIENTRY InitImageTransformParameteriHP (GLenum target, GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glImageTransformParameteriHP"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glImageTransformParameteriHP = extproc; + + glImageTransformParameteriHP(target, pname, param); +} + +static void APIENTRY InitImageTransformParameterfHP (GLenum target, GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glImageTransformParameterfHP"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glImageTransformParameterfHP = extproc; + + glImageTransformParameterfHP(target, pname, param); +} + +static void APIENTRY InitImageTransformParameterivHP (GLenum target, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glImageTransformParameterivHP"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glImageTransformParameterivHP = extproc; + + glImageTransformParameterivHP(target, pname, params); +} + +static void APIENTRY InitImageTransformParameterfvHP (GLenum target, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glImageTransformParameterfvHP"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glImageTransformParameterfvHP = extproc; + + glImageTransformParameterfvHP(target, pname, params); +} + +static void APIENTRY InitGetImageTransformParameterivHP (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetImageTransformParameterivHP"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetImageTransformParameterivHP = extproc; + + glGetImageTransformParameterivHP(target, pname, params); +} + +static void APIENTRY InitGetImageTransformParameterfvHP (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetImageTransformParameterfvHP"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetImageTransformParameterfvHP = extproc; + + glGetImageTransformParameterfvHP(target, pname, params); +} + +static void APIENTRY InitColorSubTableEXT (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorSubTableEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorSubTableEXT = extproc; + + glColorSubTableEXT(target, start, count, format, type, data); +} + +static void APIENTRY InitCopyColorSubTableEXT (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyColorSubTableEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyColorSubTableEXT = extproc; + + glCopyColorSubTableEXT(target, start, x, y, width); +} + +static void APIENTRY InitHintPGI (GLenum target, GLint mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glHintPGI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glHintPGI = extproc; + + glHintPGI(target, mode); +} + +static void APIENTRY InitColorTableEXT (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *table) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorTableEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorTableEXT = extproc; + + glColorTableEXT(target, internalFormat, width, format, type, table); +} + +static void APIENTRY InitGetColorTableEXT (GLenum target, GLenum format, GLenum type, GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTableEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTableEXT = extproc; + + glGetColorTableEXT(target, format, type, data); +} + +static void APIENTRY InitGetColorTableParameterivEXT (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTableParameterivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTableParameterivEXT = extproc; + + glGetColorTableParameterivEXT(target, pname, params); +} + +static void APIENTRY InitGetColorTableParameterfvEXT (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTableParameterfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTableParameterfvEXT = extproc; + + glGetColorTableParameterfvEXT(target, pname, params); +} + +static void APIENTRY InitGetListParameterfvSGIX (GLuint list, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetListParameterfvSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetListParameterfvSGIX = extproc; + + glGetListParameterfvSGIX(list, pname, params); +} + +static void APIENTRY InitGetListParameterivSGIX (GLuint list, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetListParameterivSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetListParameterivSGIX = extproc; + + glGetListParameterivSGIX(list, pname, params); +} + +static void APIENTRY InitListParameterfSGIX (GLuint list, GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glListParameterfSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glListParameterfSGIX = extproc; + + glListParameterfSGIX(list, pname, param); +} + +static void APIENTRY InitListParameterfvSGIX (GLuint list, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glListParameterfvSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glListParameterfvSGIX = extproc; + + glListParameterfvSGIX(list, pname, params); +} + +static void APIENTRY InitListParameteriSGIX (GLuint list, GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glListParameteriSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glListParameteriSGIX = extproc; + + glListParameteriSGIX(list, pname, param); +} + +static void APIENTRY InitListParameterivSGIX (GLuint list, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glListParameterivSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glListParameterivSGIX = extproc; + + glListParameterivSGIX(list, pname, params); +} + +static void APIENTRY InitIndexMaterialEXT (GLenum face, GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIndexMaterialEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glIndexMaterialEXT = extproc; + + glIndexMaterialEXT(face, mode); +} + +static void APIENTRY InitIndexFuncEXT (GLenum func, GLclampf ref) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIndexFuncEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glIndexFuncEXT = extproc; + + glIndexFuncEXT(func, ref); +} + +static void APIENTRY InitLockArraysEXT (GLint first, GLsizei count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLockArraysEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLockArraysEXT = extproc; + + glLockArraysEXT(first, count); +} + +static void APIENTRY InitUnlockArraysEXT (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUnlockArraysEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUnlockArraysEXT = extproc; + + glUnlockArraysEXT(); +} + +static void APIENTRY InitCullParameterdvEXT (GLenum pname, GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCullParameterdvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCullParameterdvEXT = extproc; + + glCullParameterdvEXT(pname, params); +} + +static void APIENTRY InitCullParameterfvEXT (GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCullParameterfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCullParameterfvEXT = extproc; + + glCullParameterfvEXT(pname, params); +} + +static void APIENTRY InitFragmentColorMaterialSGIX (GLenum face, GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentColorMaterialSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentColorMaterialSGIX = extproc; + + glFragmentColorMaterialSGIX(face, mode); +} + +static void APIENTRY InitFragmentLightfSGIX (GLenum light, GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentLightfSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentLightfSGIX = extproc; + + glFragmentLightfSGIX(light, pname, param); +} + +static void APIENTRY InitFragmentLightfvSGIX (GLenum light, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentLightfvSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentLightfvSGIX = extproc; + + glFragmentLightfvSGIX(light, pname, params); +} + +static void APIENTRY InitFragmentLightiSGIX (GLenum light, GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentLightiSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentLightiSGIX = extproc; + + glFragmentLightiSGIX(light, pname, param); +} + +static void APIENTRY InitFragmentLightivSGIX (GLenum light, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentLightivSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentLightivSGIX = extproc; + + glFragmentLightivSGIX(light, pname, params); +} + +static void APIENTRY InitFragmentLightModelfSGIX (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentLightModelfSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentLightModelfSGIX = extproc; + + glFragmentLightModelfSGIX(pname, param); +} + +static void APIENTRY InitFragmentLightModelfvSGIX (GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentLightModelfvSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentLightModelfvSGIX = extproc; + + glFragmentLightModelfvSGIX(pname, params); +} + +static void APIENTRY InitFragmentLightModeliSGIX (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentLightModeliSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentLightModeliSGIX = extproc; + + glFragmentLightModeliSGIX(pname, param); +} + +static void APIENTRY InitFragmentLightModelivSGIX (GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentLightModelivSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentLightModelivSGIX = extproc; + + glFragmentLightModelivSGIX(pname, params); +} + +static void APIENTRY InitFragmentMaterialfSGIX (GLenum face, GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentMaterialfSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentMaterialfSGIX = extproc; + + glFragmentMaterialfSGIX(face, pname, param); +} + +static void APIENTRY InitFragmentMaterialfvSGIX (GLenum face, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentMaterialfvSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentMaterialfvSGIX = extproc; + + glFragmentMaterialfvSGIX(face, pname, params); +} + +static void APIENTRY InitFragmentMaterialiSGIX (GLenum face, GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentMaterialiSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentMaterialiSGIX = extproc; + + glFragmentMaterialiSGIX(face, pname, param); +} + +static void APIENTRY InitFragmentMaterialivSGIX (GLenum face, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentMaterialivSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentMaterialivSGIX = extproc; + + glFragmentMaterialivSGIX(face, pname, params); +} + +static void APIENTRY InitGetFragmentLightfvSGIX (GLenum light, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetFragmentLightfvSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetFragmentLightfvSGIX = extproc; + + glGetFragmentLightfvSGIX(light, pname, params); +} + +static void APIENTRY InitGetFragmentLightivSGIX (GLenum light, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetFragmentLightivSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetFragmentLightivSGIX = extproc; + + glGetFragmentLightivSGIX(light, pname, params); +} + +static void APIENTRY InitGetFragmentMaterialfvSGIX (GLenum face, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetFragmentMaterialfvSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetFragmentMaterialfvSGIX = extproc; + + glGetFragmentMaterialfvSGIX(face, pname, params); +} + +static void APIENTRY InitGetFragmentMaterialivSGIX (GLenum face, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetFragmentMaterialivSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetFragmentMaterialivSGIX = extproc; + + glGetFragmentMaterialivSGIX(face, pname, params); +} + +static void APIENTRY InitLightEnviSGIX (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLightEnviSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLightEnviSGIX = extproc; + + glLightEnviSGIX(pname, param); +} + +static void APIENTRY InitDrawRangeElementsEXT (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawRangeElementsEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawRangeElementsEXT = extproc; + + glDrawRangeElementsEXT(mode, start, end, count, type, indices); +} + +static void APIENTRY InitApplyTextureEXT (GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glApplyTextureEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glApplyTextureEXT = extproc; + + glApplyTextureEXT(mode); +} + +static void APIENTRY InitTextureLightEXT (GLenum pname) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTextureLightEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTextureLightEXT = extproc; + + glTextureLightEXT(pname); +} + +static void APIENTRY InitTextureMaterialEXT (GLenum face, GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTextureMaterialEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTextureMaterialEXT = extproc; + + glTextureMaterialEXT(face, mode); +} + +static void APIENTRY InitAsyncMarkerSGIX (GLuint marker) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glAsyncMarkerSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glAsyncMarkerSGIX = extproc; + + glAsyncMarkerSGIX(marker); +} + +static GLint APIENTRY InitFinishAsyncSGIX (GLuint *markerp) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFinishAsyncSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glFinishAsyncSGIX = extproc; + + return glFinishAsyncSGIX(markerp); +} + +static GLint APIENTRY InitPollAsyncSGIX (GLuint *markerp) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPollAsyncSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glPollAsyncSGIX = extproc; + + return glPollAsyncSGIX(markerp); +} + +static GLuint APIENTRY InitGenAsyncMarkersSGIX (GLsizei range) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenAsyncMarkersSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glGenAsyncMarkersSGIX = extproc; + + return glGenAsyncMarkersSGIX(range); +} + +static void APIENTRY InitDeleteAsyncMarkersSGIX (GLuint marker, GLsizei range) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteAsyncMarkersSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteAsyncMarkersSGIX = extproc; + + glDeleteAsyncMarkersSGIX(marker, range); +} + +static GLboolean APIENTRY InitIsAsyncMarkerSGIX (GLuint marker) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsAsyncMarkerSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsAsyncMarkerSGIX = extproc; + + return glIsAsyncMarkerSGIX(marker); +} + +static void APIENTRY InitVertexPointervINTEL (GLint size, GLenum type, const GLvoid* *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexPointervINTEL"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexPointervINTEL = extproc; + + glVertexPointervINTEL(size, type, pointer); +} + +static void APIENTRY InitNormalPointervINTEL (GLenum type, const GLvoid* *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalPointervINTEL"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalPointervINTEL = extproc; + + glNormalPointervINTEL(type, pointer); +} + +static void APIENTRY InitColorPointervINTEL (GLint size, GLenum type, const GLvoid* *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorPointervINTEL"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorPointervINTEL = extproc; + + glColorPointervINTEL(size, type, pointer); +} + +static void APIENTRY InitTexCoordPointervINTEL (GLint size, GLenum type, const GLvoid* *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoordPointervINTEL"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoordPointervINTEL = extproc; + + glTexCoordPointervINTEL(size, type, pointer); +} + +static void APIENTRY InitPixelTransformParameteriEXT (GLenum target, GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTransformParameteriEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTransformParameteriEXT = extproc; + + glPixelTransformParameteriEXT(target, pname, param); +} + +static void APIENTRY InitPixelTransformParameterfEXT (GLenum target, GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTransformParameterfEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTransformParameterfEXT = extproc; + + glPixelTransformParameterfEXT(target, pname, param); +} + +static void APIENTRY InitPixelTransformParameterivEXT (GLenum target, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTransformParameterivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTransformParameterivEXT = extproc; + + glPixelTransformParameterivEXT(target, pname, params); +} + +static void APIENTRY InitPixelTransformParameterfvEXT (GLenum target, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTransformParameterfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTransformParameterfvEXT = extproc; + + glPixelTransformParameterfvEXT(target, pname, params); +} + +static void APIENTRY InitSecondaryColor3bEXT (GLbyte red, GLbyte green, GLbyte blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3bEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3bEXT = extproc; + + glSecondaryColor3bEXT(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3bvEXT (const GLbyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3bvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3bvEXT = extproc; + + glSecondaryColor3bvEXT(v); +} + +static void APIENTRY InitSecondaryColor3dEXT (GLdouble red, GLdouble green, GLdouble blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3dEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3dEXT = extproc; + + glSecondaryColor3dEXT(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3dvEXT (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3dvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3dvEXT = extproc; + + glSecondaryColor3dvEXT(v); +} + +static void APIENTRY InitSecondaryColor3fEXT (GLfloat red, GLfloat green, GLfloat blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3fEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3fEXT = extproc; + + glSecondaryColor3fEXT(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3fvEXT (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3fvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3fvEXT = extproc; + + glSecondaryColor3fvEXT(v); +} + +static void APIENTRY InitSecondaryColor3iEXT (GLint red, GLint green, GLint blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3iEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3iEXT = extproc; + + glSecondaryColor3iEXT(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3ivEXT (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3ivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3ivEXT = extproc; + + glSecondaryColor3ivEXT(v); +} + +static void APIENTRY InitSecondaryColor3sEXT (GLshort red, GLshort green, GLshort blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3sEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3sEXT = extproc; + + glSecondaryColor3sEXT(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3svEXT (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3svEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3svEXT = extproc; + + glSecondaryColor3svEXT(v); +} + +static void APIENTRY InitSecondaryColor3ubEXT (GLubyte red, GLubyte green, GLubyte blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3ubEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3ubEXT = extproc; + + glSecondaryColor3ubEXT(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3ubvEXT (const GLubyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3ubvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3ubvEXT = extproc; + + glSecondaryColor3ubvEXT(v); +} + +static void APIENTRY InitSecondaryColor3uiEXT (GLuint red, GLuint green, GLuint blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3uiEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3uiEXT = extproc; + + glSecondaryColor3uiEXT(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3uivEXT (const GLuint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3uivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3uivEXT = extproc; + + glSecondaryColor3uivEXT(v); +} + +static void APIENTRY InitSecondaryColor3usEXT (GLushort red, GLushort green, GLushort blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3usEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3usEXT = extproc; + + glSecondaryColor3usEXT(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3usvEXT (const GLushort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3usvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3usvEXT = extproc; + + glSecondaryColor3usvEXT(v); +} + +static void APIENTRY InitSecondaryColorPointerEXT (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColorPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColorPointerEXT = extproc; + + glSecondaryColorPointerEXT(size, type, stride, pointer); +} + +static void APIENTRY InitTextureNormalEXT (GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTextureNormalEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTextureNormalEXT = extproc; + + glTextureNormalEXT(mode); +} + +static void APIENTRY InitMultiDrawArraysEXT (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiDrawArraysEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiDrawArraysEXT = extproc; + + glMultiDrawArraysEXT(mode, first, count, primcount); +} + +static void APIENTRY InitMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiDrawElementsEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiDrawElementsEXT = extproc; + + glMultiDrawElementsEXT(mode, count, type, indices, primcount); +} + +static void APIENTRY InitFogCoordfEXT (GLfloat coord) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordfEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordfEXT = extproc; + + glFogCoordfEXT(coord); +} + +static void APIENTRY InitFogCoordfvEXT (const GLfloat *coord) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordfvEXT = extproc; + + glFogCoordfvEXT(coord); +} + +static void APIENTRY InitFogCoorddEXT (GLdouble coord) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoorddEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoorddEXT = extproc; + + glFogCoorddEXT(coord); +} + +static void APIENTRY InitFogCoorddvEXT (const GLdouble *coord) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoorddvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoorddvEXT = extproc; + + glFogCoorddvEXT(coord); +} + +static void APIENTRY InitFogCoordPointerEXT (GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordPointerEXT = extproc; + + glFogCoordPointerEXT(type, stride, pointer); +} + +static void APIENTRY InitTangent3bEXT (GLbyte tx, GLbyte ty, GLbyte tz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3bEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3bEXT = extproc; + + glTangent3bEXT(tx, ty, tz); +} + +static void APIENTRY InitTangent3bvEXT (const GLbyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3bvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3bvEXT = extproc; + + glTangent3bvEXT(v); +} + +static void APIENTRY InitTangent3dEXT (GLdouble tx, GLdouble ty, GLdouble tz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3dEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3dEXT = extproc; + + glTangent3dEXT(tx, ty, tz); +} + +static void APIENTRY InitTangent3dvEXT (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3dvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3dvEXT = extproc; + + glTangent3dvEXT(v); +} + +static void APIENTRY InitTangent3fEXT (GLfloat tx, GLfloat ty, GLfloat tz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3fEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3fEXT = extproc; + + glTangent3fEXT(tx, ty, tz); +} + +static void APIENTRY InitTangent3fvEXT (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3fvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3fvEXT = extproc; + + glTangent3fvEXT(v); +} + +static void APIENTRY InitTangent3iEXT (GLint tx, GLint ty, GLint tz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3iEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3iEXT = extproc; + + glTangent3iEXT(tx, ty, tz); +} + +static void APIENTRY InitTangent3ivEXT (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3ivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3ivEXT = extproc; + + glTangent3ivEXT(v); +} + +static void APIENTRY InitTangent3sEXT (GLshort tx, GLshort ty, GLshort tz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3sEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3sEXT = extproc; + + glTangent3sEXT(tx, ty, tz); +} + +static void APIENTRY InitTangent3svEXT (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3svEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3svEXT = extproc; + + glTangent3svEXT(v); +} + +static void APIENTRY InitBinormal3bEXT (GLbyte bx, GLbyte by, GLbyte bz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3bEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3bEXT = extproc; + + glBinormal3bEXT(bx, by, bz); +} + +static void APIENTRY InitBinormal3bvEXT (const GLbyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3bvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3bvEXT = extproc; + + glBinormal3bvEXT(v); +} + +static void APIENTRY InitBinormal3dEXT (GLdouble bx, GLdouble by, GLdouble bz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3dEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3dEXT = extproc; + + glBinormal3dEXT(bx, by, bz); +} + +static void APIENTRY InitBinormal3dvEXT (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3dvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3dvEXT = extproc; + + glBinormal3dvEXT(v); +} + +static void APIENTRY InitBinormal3fEXT (GLfloat bx, GLfloat by, GLfloat bz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3fEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3fEXT = extproc; + + glBinormal3fEXT(bx, by, bz); +} + +static void APIENTRY InitBinormal3fvEXT (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3fvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3fvEXT = extproc; + + glBinormal3fvEXT(v); +} + +static void APIENTRY InitBinormal3iEXT (GLint bx, GLint by, GLint bz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3iEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3iEXT = extproc; + + glBinormal3iEXT(bx, by, bz); +} + +static void APIENTRY InitBinormal3ivEXT (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3ivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3ivEXT = extproc; + + glBinormal3ivEXT(v); +} + +static void APIENTRY InitBinormal3sEXT (GLshort bx, GLshort by, GLshort bz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3sEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3sEXT = extproc; + + glBinormal3sEXT(bx, by, bz); +} + +static void APIENTRY InitBinormal3svEXT (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3svEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3svEXT = extproc; + + glBinormal3svEXT(v); +} + +static void APIENTRY InitTangentPointerEXT (GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangentPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangentPointerEXT = extproc; + + glTangentPointerEXT(type, stride, pointer); +} + +static void APIENTRY InitBinormalPointerEXT (GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormalPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormalPointerEXT = extproc; + + glBinormalPointerEXT(type, stride, pointer); +} + +static void APIENTRY InitFinishTextureSUNX (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFinishTextureSUNX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFinishTextureSUNX = extproc; + + glFinishTextureSUNX(); +} + +static void APIENTRY InitGlobalAlphaFactorbSUN (GLbyte factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGlobalAlphaFactorbSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGlobalAlphaFactorbSUN = extproc; + + glGlobalAlphaFactorbSUN(factor); +} + +static void APIENTRY InitGlobalAlphaFactorsSUN (GLshort factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGlobalAlphaFactorsSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGlobalAlphaFactorsSUN = extproc; + + glGlobalAlphaFactorsSUN(factor); +} + +static void APIENTRY InitGlobalAlphaFactoriSUN (GLint factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGlobalAlphaFactoriSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGlobalAlphaFactoriSUN = extproc; + + glGlobalAlphaFactoriSUN(factor); +} + +static void APIENTRY InitGlobalAlphaFactorfSUN (GLfloat factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGlobalAlphaFactorfSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGlobalAlphaFactorfSUN = extproc; + + glGlobalAlphaFactorfSUN(factor); +} + +static void APIENTRY InitGlobalAlphaFactordSUN (GLdouble factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGlobalAlphaFactordSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGlobalAlphaFactordSUN = extproc; + + glGlobalAlphaFactordSUN(factor); +} + +static void APIENTRY InitGlobalAlphaFactorubSUN (GLubyte factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGlobalAlphaFactorubSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGlobalAlphaFactorubSUN = extproc; + + glGlobalAlphaFactorubSUN(factor); +} + +static void APIENTRY InitGlobalAlphaFactorusSUN (GLushort factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGlobalAlphaFactorusSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGlobalAlphaFactorusSUN = extproc; + + glGlobalAlphaFactorusSUN(factor); +} + +static void APIENTRY InitGlobalAlphaFactoruiSUN (GLuint factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGlobalAlphaFactoruiSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGlobalAlphaFactoruiSUN = extproc; + + glGlobalAlphaFactoruiSUN(factor); +} + +static void APIENTRY InitReplacementCodeuiSUN (GLuint code) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiSUN = extproc; + + glReplacementCodeuiSUN(code); +} + +static void APIENTRY InitReplacementCodeusSUN (GLushort code) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeusSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeusSUN = extproc; + + glReplacementCodeusSUN(code); +} + +static void APIENTRY InitReplacementCodeubSUN (GLubyte code) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeubSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeubSUN = extproc; + + glReplacementCodeubSUN(code); +} + +static void APIENTRY InitReplacementCodeuivSUN (const GLuint *code) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuivSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuivSUN = extproc; + + glReplacementCodeuivSUN(code); +} + +static void APIENTRY InitReplacementCodeusvSUN (const GLushort *code) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeusvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeusvSUN = extproc; + + glReplacementCodeusvSUN(code); +} + +static void APIENTRY InitReplacementCodeubvSUN (const GLubyte *code) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeubvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeubvSUN = extproc; + + glReplacementCodeubvSUN(code); +} + +static void APIENTRY InitReplacementCodePointerSUN (GLenum type, GLsizei stride, const GLvoid* *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodePointerSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodePointerSUN = extproc; + + glReplacementCodePointerSUN(type, stride, pointer); +} + +static void APIENTRY InitColor4ubVertex2fSUN (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor4ubVertex2fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor4ubVertex2fSUN = extproc; + + glColor4ubVertex2fSUN(r, g, b, a, x, y); +} + +static void APIENTRY InitColor4ubVertex2fvSUN (const GLubyte *c, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor4ubVertex2fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor4ubVertex2fvSUN = extproc; + + glColor4ubVertex2fvSUN(c, v); +} + +static void APIENTRY InitColor4ubVertex3fSUN (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor4ubVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor4ubVertex3fSUN = extproc; + + glColor4ubVertex3fSUN(r, g, b, a, x, y, z); +} + +static void APIENTRY InitColor4ubVertex3fvSUN (const GLubyte *c, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor4ubVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor4ubVertex3fvSUN = extproc; + + glColor4ubVertex3fvSUN(c, v); +} + +static void APIENTRY InitColor3fVertex3fSUN (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor3fVertex3fSUN = extproc; + + glColor3fVertex3fSUN(r, g, b, x, y, z); +} + +static void APIENTRY InitColor3fVertex3fvSUN (const GLfloat *c, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor3fVertex3fvSUN = extproc; + + glColor3fVertex3fvSUN(c, v); +} + +static void APIENTRY InitNormal3fVertex3fSUN (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormal3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormal3fVertex3fSUN = extproc; + + glNormal3fVertex3fSUN(nx, ny, nz, x, y, z); +} + +static void APIENTRY InitNormal3fVertex3fvSUN (const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormal3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormal3fVertex3fvSUN = extproc; + + glNormal3fVertex3fvSUN(n, v); +} + +static void APIENTRY InitColor4fNormal3fVertex3fSUN (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor4fNormal3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor4fNormal3fVertex3fSUN = extproc; + + glColor4fNormal3fVertex3fSUN(r, g, b, a, nx, ny, nz, x, y, z); +} + +static void APIENTRY InitColor4fNormal3fVertex3fvSUN (const GLfloat *c, const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor4fNormal3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor4fNormal3fVertex3fvSUN = extproc; + + glColor4fNormal3fVertex3fvSUN(c, n, v); +} + +static void APIENTRY InitTexCoord2fVertex3fSUN (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fVertex3fSUN = extproc; + + glTexCoord2fVertex3fSUN(s, t, x, y, z); +} + +static void APIENTRY InitTexCoord2fVertex3fvSUN (const GLfloat *tc, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fVertex3fvSUN = extproc; + + glTexCoord2fVertex3fvSUN(tc, v); +} + +static void APIENTRY InitTexCoord4fVertex4fSUN (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord4fVertex4fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord4fVertex4fSUN = extproc; + + glTexCoord4fVertex4fSUN(s, t, p, q, x, y, z, w); +} + +static void APIENTRY InitTexCoord4fVertex4fvSUN (const GLfloat *tc, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord4fVertex4fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord4fVertex4fvSUN = extproc; + + glTexCoord4fVertex4fvSUN(tc, v); +} + +static void APIENTRY InitTexCoord2fColor4ubVertex3fSUN (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fColor4ubVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fColor4ubVertex3fSUN = extproc; + + glTexCoord2fColor4ubVertex3fSUN(s, t, r, g, b, a, x, y, z); +} + +static void APIENTRY InitTexCoord2fColor4ubVertex3fvSUN (const GLfloat *tc, const GLubyte *c, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fColor4ubVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fColor4ubVertex3fvSUN = extproc; + + glTexCoord2fColor4ubVertex3fvSUN(tc, c, v); +} + +static void APIENTRY InitTexCoord2fColor3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fColor3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fColor3fVertex3fSUN = extproc; + + glTexCoord2fColor3fVertex3fSUN(s, t, r, g, b, x, y, z); +} + +static void APIENTRY InitTexCoord2fColor3fVertex3fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fColor3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fColor3fVertex3fvSUN = extproc; + + glTexCoord2fColor3fVertex3fvSUN(tc, c, v); +} + +static void APIENTRY InitTexCoord2fNormal3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fNormal3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fNormal3fVertex3fSUN = extproc; + + glTexCoord2fNormal3fVertex3fSUN(s, t, nx, ny, nz, x, y, z); +} + +static void APIENTRY InitTexCoord2fNormal3fVertex3fvSUN (const GLfloat *tc, const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fNormal3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fNormal3fVertex3fvSUN = extproc; + + glTexCoord2fNormal3fVertex3fvSUN(tc, n, v); +} + +static void APIENTRY InitTexCoord2fColor4fNormal3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fColor4fNormal3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fColor4fNormal3fVertex3fSUN = extproc; + + glTexCoord2fColor4fNormal3fVertex3fSUN(s, t, r, g, b, a, nx, ny, nz, x, y, z); +} + +static void APIENTRY InitTexCoord2fColor4fNormal3fVertex3fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fColor4fNormal3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fColor4fNormal3fVertex3fvSUN = extproc; + + glTexCoord2fColor4fNormal3fVertex3fvSUN(tc, c, n, v); +} + +static void APIENTRY InitTexCoord4fColor4fNormal3fVertex4fSUN (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord4fColor4fNormal3fVertex4fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord4fColor4fNormal3fVertex4fSUN = extproc; + + glTexCoord4fColor4fNormal3fVertex4fSUN(s, t, p, q, r, g, b, a, nx, ny, nz, x, y, z, w); +} + +static void APIENTRY InitTexCoord4fColor4fNormal3fVertex4fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord4fColor4fNormal3fVertex4fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord4fColor4fNormal3fVertex4fvSUN = extproc; + + glTexCoord4fColor4fNormal3fVertex4fvSUN(tc, c, n, v); +} + +static void APIENTRY InitReplacementCodeuiVertex3fSUN (GLuint rc, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiVertex3fSUN = extproc; + + glReplacementCodeuiVertex3fSUN(rc, x, y, z); +} + +static void APIENTRY InitReplacementCodeuiVertex3fvSUN (const GLuint *rc, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiVertex3fvSUN = extproc; + + glReplacementCodeuiVertex3fvSUN(rc, v); +} + +static void APIENTRY InitReplacementCodeuiColor4ubVertex3fSUN (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiColor4ubVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiColor4ubVertex3fSUN = extproc; + + glReplacementCodeuiColor4ubVertex3fSUN(rc, r, g, b, a, x, y, z); +} + +static void APIENTRY InitReplacementCodeuiColor4ubVertex3fvSUN (const GLuint *rc, const GLubyte *c, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiColor4ubVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiColor4ubVertex3fvSUN = extproc; + + glReplacementCodeuiColor4ubVertex3fvSUN(rc, c, v); +} + +static void APIENTRY InitReplacementCodeuiColor3fVertex3fSUN (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiColor3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiColor3fVertex3fSUN = extproc; + + glReplacementCodeuiColor3fVertex3fSUN(rc, r, g, b, x, y, z); +} + +static void APIENTRY InitReplacementCodeuiColor3fVertex3fvSUN (const GLuint *rc, const GLfloat *c, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiColor3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiColor3fVertex3fvSUN = extproc; + + glReplacementCodeuiColor3fVertex3fvSUN(rc, c, v); +} + +static void APIENTRY InitReplacementCodeuiNormal3fVertex3fSUN (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiNormal3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiNormal3fVertex3fSUN = extproc; + + glReplacementCodeuiNormal3fVertex3fSUN(rc, nx, ny, nz, x, y, z); +} + +static void APIENTRY InitReplacementCodeuiNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiNormal3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiNormal3fVertex3fvSUN = extproc; + + glReplacementCodeuiNormal3fVertex3fvSUN(rc, n, v); +} + +static void APIENTRY InitReplacementCodeuiColor4fNormal3fVertex3fSUN (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiColor4fNormal3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiColor4fNormal3fVertex3fSUN = extproc; + + glReplacementCodeuiColor4fNormal3fVertex3fSUN(rc, r, g, b, a, nx, ny, nz, x, y, z); +} + +static void APIENTRY InitReplacementCodeuiColor4fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiColor4fNormal3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiColor4fNormal3fVertex3fvSUN = extproc; + + glReplacementCodeuiColor4fNormal3fVertex3fvSUN(rc, c, n, v); +} + +static void APIENTRY InitReplacementCodeuiTexCoord2fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiTexCoord2fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiTexCoord2fVertex3fSUN = extproc; + + glReplacementCodeuiTexCoord2fVertex3fSUN(rc, s, t, x, y, z); +} + +static void APIENTRY InitReplacementCodeuiTexCoord2fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiTexCoord2fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiTexCoord2fVertex3fvSUN = extproc; + + glReplacementCodeuiTexCoord2fVertex3fvSUN(rc, tc, v); +} + +static void APIENTRY InitReplacementCodeuiTexCoord2fNormal3fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN = extproc; + + glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN(rc, s, t, nx, ny, nz, x, y, z); +} + +static void APIENTRY InitReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN = extproc; + + glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN(rc, tc, n, v); +} + +static void APIENTRY InitReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN = extproc; + + glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN(rc, s, t, r, g, b, a, nx, ny, nz, x, y, z); +} + +static void APIENTRY InitReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN = extproc; + + glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN(rc, tc, c, n, v); +} + +static void APIENTRY InitBlendFuncSeparateEXT (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBlendFuncSeparateEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBlendFuncSeparateEXT = extproc; + + glBlendFuncSeparateEXT(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); +} + +static void APIENTRY InitBlendFuncSeparateINGR (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBlendFuncSeparateINGR"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBlendFuncSeparateINGR = extproc; + + glBlendFuncSeparateINGR(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); +} + +static void APIENTRY InitVertexWeightfEXT (GLfloat weight) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexWeightfEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexWeightfEXT = extproc; + + glVertexWeightfEXT(weight); +} + +static void APIENTRY InitVertexWeightfvEXT (const GLfloat *weight) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexWeightfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexWeightfvEXT = extproc; + + glVertexWeightfvEXT(weight); +} + +static void APIENTRY InitVertexWeightPointerEXT (GLsizei size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexWeightPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexWeightPointerEXT = extproc; + + glVertexWeightPointerEXT(size, type, stride, pointer); +} + +static void APIENTRY InitFlushVertexArrayRangeNV (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFlushVertexArrayRangeNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFlushVertexArrayRangeNV = extproc; + + glFlushVertexArrayRangeNV(); +} + +static void APIENTRY InitVertexArrayRangeNV (GLsizei length, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexArrayRangeNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexArrayRangeNV = extproc; + + glVertexArrayRangeNV(length, pointer); +} + +static void APIENTRY InitCombinerParameterfvNV (GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCombinerParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCombinerParameterfvNV = extproc; + + glCombinerParameterfvNV(pname, params); +} + +static void APIENTRY InitCombinerParameterfNV (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCombinerParameterfNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCombinerParameterfNV = extproc; + + glCombinerParameterfNV(pname, param); +} + +static void APIENTRY InitCombinerParameterivNV (GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCombinerParameterivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCombinerParameterivNV = extproc; + + glCombinerParameterivNV(pname, params); +} + +static void APIENTRY InitCombinerParameteriNV (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCombinerParameteriNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCombinerParameteriNV = extproc; + + glCombinerParameteriNV(pname, param); +} + +static void APIENTRY InitCombinerInputNV (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCombinerInputNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCombinerInputNV = extproc; + + glCombinerInputNV(stage, portion, variable, input, mapping, componentUsage); +} + +static void APIENTRY InitCombinerOutputNV (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCombinerOutputNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCombinerOutputNV = extproc; + + glCombinerOutputNV(stage, portion, abOutput, cdOutput, sumOutput, scale, bias, abDotProduct, cdDotProduct, muxSum); +} + +static void APIENTRY InitFinalCombinerInputNV (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFinalCombinerInputNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFinalCombinerInputNV = extproc; + + glFinalCombinerInputNV(variable, input, mapping, componentUsage); +} + +static void APIENTRY InitGetCombinerInputParameterfvNV (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetCombinerInputParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetCombinerInputParameterfvNV = extproc; + + glGetCombinerInputParameterfvNV(stage, portion, variable, pname, params); +} + +static void APIENTRY InitGetCombinerInputParameterivNV (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetCombinerInputParameterivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetCombinerInputParameterivNV = extproc; + + glGetCombinerInputParameterivNV(stage, portion, variable, pname, params); +} + +static void APIENTRY InitGetCombinerOutputParameterfvNV (GLenum stage, GLenum portion, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetCombinerOutputParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetCombinerOutputParameterfvNV = extproc; + + glGetCombinerOutputParameterfvNV(stage, portion, pname, params); +} + +static void APIENTRY InitGetCombinerOutputParameterivNV (GLenum stage, GLenum portion, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetCombinerOutputParameterivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetCombinerOutputParameterivNV = extproc; + + glGetCombinerOutputParameterivNV(stage, portion, pname, params); +} + +static void APIENTRY InitGetFinalCombinerInputParameterfvNV (GLenum variable, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetFinalCombinerInputParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetFinalCombinerInputParameterfvNV = extproc; + + glGetFinalCombinerInputParameterfvNV(variable, pname, params); +} + +static void APIENTRY InitGetFinalCombinerInputParameterivNV (GLenum variable, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetFinalCombinerInputParameterivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetFinalCombinerInputParameterivNV = extproc; + + glGetFinalCombinerInputParameterivNV(variable, pname, params); +} + +static void APIENTRY InitResizeBuffersMESA (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glResizeBuffersMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glResizeBuffersMESA = extproc; + + glResizeBuffersMESA(); +} + +static void APIENTRY InitWindowPos2dMESA (GLdouble x, GLdouble y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2dMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2dMESA = extproc; + + glWindowPos2dMESA(x, y); +} + +static void APIENTRY InitWindowPos2dvMESA (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2dvMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2dvMESA = extproc; + + glWindowPos2dvMESA(v); +} + +static void APIENTRY InitWindowPos2fMESA (GLfloat x, GLfloat y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2fMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2fMESA = extproc; + + glWindowPos2fMESA(x, y); +} + +static void APIENTRY InitWindowPos2fvMESA (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2fvMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2fvMESA = extproc; + + glWindowPos2fvMESA(v); +} + +static void APIENTRY InitWindowPos2iMESA (GLint x, GLint y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2iMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2iMESA = extproc; + + glWindowPos2iMESA(x, y); +} + +static void APIENTRY InitWindowPos2ivMESA (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2ivMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2ivMESA = extproc; + + glWindowPos2ivMESA(v); +} + +static void APIENTRY InitWindowPos2sMESA (GLshort x, GLshort y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2sMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2sMESA = extproc; + + glWindowPos2sMESA(x, y); +} + +static void APIENTRY InitWindowPos2svMESA (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2svMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2svMESA = extproc; + + glWindowPos2svMESA(v); +} + +static void APIENTRY InitWindowPos3dMESA (GLdouble x, GLdouble y, GLdouble z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3dMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3dMESA = extproc; + + glWindowPos3dMESA(x, y, z); +} + +static void APIENTRY InitWindowPos3dvMESA (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3dvMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3dvMESA = extproc; + + glWindowPos3dvMESA(v); +} + +static void APIENTRY InitWindowPos3fMESA (GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3fMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3fMESA = extproc; + + glWindowPos3fMESA(x, y, z); +} + +static void APIENTRY InitWindowPos3fvMESA (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3fvMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3fvMESA = extproc; + + glWindowPos3fvMESA(v); +} + +static void APIENTRY InitWindowPos3iMESA (GLint x, GLint y, GLint z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3iMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3iMESA = extproc; + + glWindowPos3iMESA(x, y, z); +} + +static void APIENTRY InitWindowPos3ivMESA (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3ivMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3ivMESA = extproc; + + glWindowPos3ivMESA(v); +} + +static void APIENTRY InitWindowPos3sMESA (GLshort x, GLshort y, GLshort z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3sMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3sMESA = extproc; + + glWindowPos3sMESA(x, y, z); +} + +static void APIENTRY InitWindowPos3svMESA (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3svMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3svMESA = extproc; + + glWindowPos3svMESA(v); +} + +static void APIENTRY InitWindowPos4dMESA (GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos4dMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos4dMESA = extproc; + + glWindowPos4dMESA(x, y, z, w); +} + +static void APIENTRY InitWindowPos4dvMESA (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos4dvMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos4dvMESA = extproc; + + glWindowPos4dvMESA(v); +} + +static void APIENTRY InitWindowPos4fMESA (GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos4fMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos4fMESA = extproc; + + glWindowPos4fMESA(x, y, z, w); +} + +static void APIENTRY InitWindowPos4fvMESA (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos4fvMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos4fvMESA = extproc; + + glWindowPos4fvMESA(v); +} + +static void APIENTRY InitWindowPos4iMESA (GLint x, GLint y, GLint z, GLint w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos4iMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos4iMESA = extproc; + + glWindowPos4iMESA(x, y, z, w); +} + +static void APIENTRY InitWindowPos4ivMESA (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos4ivMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos4ivMESA = extproc; + + glWindowPos4ivMESA(v); +} + +static void APIENTRY InitWindowPos4sMESA (GLshort x, GLshort y, GLshort z, GLshort w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos4sMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos4sMESA = extproc; + + glWindowPos4sMESA(x, y, z, w); +} + +static void APIENTRY InitWindowPos4svMESA (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos4svMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos4svMESA = extproc; + + glWindowPos4svMESA(v); +} + +static void APIENTRY InitMultiModeDrawArraysIBM (const GLenum *mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiModeDrawArraysIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiModeDrawArraysIBM = extproc; + + glMultiModeDrawArraysIBM(mode, first, count, primcount, modestride); +} + +static void APIENTRY InitMultiModeDrawElementsIBM (const GLenum *mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei primcount, GLint modestride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiModeDrawElementsIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiModeDrawElementsIBM = extproc; + + glMultiModeDrawElementsIBM(mode, count, type, indices, primcount, modestride); +} + +static void APIENTRY InitColorPointerListIBM (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorPointerListIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorPointerListIBM = extproc; + + glColorPointerListIBM(size, type, stride, pointer, ptrstride); +} + +static void APIENTRY InitSecondaryColorPointerListIBM (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColorPointerListIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColorPointerListIBM = extproc; + + glSecondaryColorPointerListIBM(size, type, stride, pointer, ptrstride); +} + +static void APIENTRY InitEdgeFlagPointerListIBM (GLint stride, const GLboolean* *pointer, GLint ptrstride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEdgeFlagPointerListIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEdgeFlagPointerListIBM = extproc; + + glEdgeFlagPointerListIBM(stride, pointer, ptrstride); +} + +static void APIENTRY InitFogCoordPointerListIBM (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordPointerListIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordPointerListIBM = extproc; + + glFogCoordPointerListIBM(type, stride, pointer, ptrstride); +} + +static void APIENTRY InitIndexPointerListIBM (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIndexPointerListIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glIndexPointerListIBM = extproc; + + glIndexPointerListIBM(type, stride, pointer, ptrstride); +} + +static void APIENTRY InitNormalPointerListIBM (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalPointerListIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalPointerListIBM = extproc; + + glNormalPointerListIBM(type, stride, pointer, ptrstride); +} + +static void APIENTRY InitTexCoordPointerListIBM (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoordPointerListIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoordPointerListIBM = extproc; + + glTexCoordPointerListIBM(size, type, stride, pointer, ptrstride); +} + +static void APIENTRY InitVertexPointerListIBM (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexPointerListIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexPointerListIBM = extproc; + + glVertexPointerListIBM(size, type, stride, pointer, ptrstride); +} + +static void APIENTRY InitTbufferMask3DFX (GLuint mask) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTbufferMask3DFX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTbufferMask3DFX = extproc; + + glTbufferMask3DFX(mask); +} + +static void APIENTRY InitSampleMaskEXT (GLclampf value, GLboolean invert) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSampleMaskEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSampleMaskEXT = extproc; + + glSampleMaskEXT(value, invert); +} + +static void APIENTRY InitSamplePatternEXT (GLenum pattern) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSamplePatternEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSamplePatternEXT = extproc; + + glSamplePatternEXT(pattern); +} + +static void APIENTRY InitTextureColorMaskSGIS (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTextureColorMaskSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTextureColorMaskSGIS = extproc; + + glTextureColorMaskSGIS(red, green, blue, alpha); +} + +static void APIENTRY InitIglooInterfaceSGIX (GLenum pname, const GLvoid *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIglooInterfaceSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glIglooInterfaceSGIX = extproc; + + glIglooInterfaceSGIX(pname, params); +} + +static void APIENTRY InitDeleteFencesNV (GLsizei n, const GLuint *fences) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteFencesNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteFencesNV = extproc; + + glDeleteFencesNV(n, fences); +} + +static void APIENTRY InitGenFencesNV (GLsizei n, GLuint *fences) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenFencesNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenFencesNV = extproc; + + glGenFencesNV(n, fences); +} + +static GLboolean APIENTRY InitIsFenceNV (GLuint fence) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsFenceNV"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsFenceNV = extproc; + + return glIsFenceNV(fence); +} + +static GLboolean APIENTRY InitTestFenceNV (GLuint fence) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTestFenceNV"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glTestFenceNV = extproc; + + return glTestFenceNV(fence); +} + +static void APIENTRY InitGetFenceivNV (GLuint fence, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetFenceivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetFenceivNV = extproc; + + glGetFenceivNV(fence, pname, params); +} + +static void APIENTRY InitFinishFenceNV (GLuint fence) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFinishFenceNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFinishFenceNV = extproc; + + glFinishFenceNV(fence); +} + +static void APIENTRY InitSetFenceNV (GLuint fence, GLenum condition) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSetFenceNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSetFenceNV = extproc; + + glSetFenceNV(fence, condition); +} + +static void APIENTRY InitMapControlPointsNV (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const GLvoid *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMapControlPointsNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMapControlPointsNV = extproc; + + glMapControlPointsNV(target, index, type, ustride, vstride, uorder, vorder, packed, points); +} + +static void APIENTRY InitMapParameterivNV (GLenum target, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMapParameterivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMapParameterivNV = extproc; + + glMapParameterivNV(target, pname, params); +} + +static void APIENTRY InitMapParameterfvNV (GLenum target, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMapParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMapParameterfvNV = extproc; + + glMapParameterfvNV(target, pname, params); +} + +static void APIENTRY InitGetMapControlPointsNV (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, GLvoid *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMapControlPointsNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMapControlPointsNV = extproc; + + glGetMapControlPointsNV(target, index, type, ustride, vstride, packed, points); +} + +static void APIENTRY InitGetMapParameterivNV (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMapParameterivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMapParameterivNV = extproc; + + glGetMapParameterivNV(target, pname, params); +} + +static void APIENTRY InitGetMapParameterfvNV (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMapParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMapParameterfvNV = extproc; + + glGetMapParameterfvNV(target, pname, params); +} + +static void APIENTRY InitGetMapAttribParameterivNV (GLenum target, GLuint index, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMapAttribParameterivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMapAttribParameterivNV = extproc; + + glGetMapAttribParameterivNV(target, index, pname, params); +} + +static void APIENTRY InitGetMapAttribParameterfvNV (GLenum target, GLuint index, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMapAttribParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMapAttribParameterfvNV = extproc; + + glGetMapAttribParameterfvNV(target, index, pname, params); +} + +static void APIENTRY InitEvalMapsNV (GLenum target, GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEvalMapsNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEvalMapsNV = extproc; + + glEvalMapsNV(target, mode); +} + +static void APIENTRY InitCombinerStageParameterfvNV (GLenum stage, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCombinerStageParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCombinerStageParameterfvNV = extproc; + + glCombinerStageParameterfvNV(stage, pname, params); +} + +static void APIENTRY InitGetCombinerStageParameterfvNV (GLenum stage, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetCombinerStageParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetCombinerStageParameterfvNV = extproc; + + glGetCombinerStageParameterfvNV(stage, pname, params); +} + +static GLboolean APIENTRY InitAreProgramsResidentNV (GLsizei n, const GLuint *programs, GLboolean *residences) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glAreProgramsResidentNV"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glAreProgramsResidentNV = extproc; + + return glAreProgramsResidentNV(n, programs, residences); +} + +static void APIENTRY InitBindProgramNV (GLenum target, GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindProgramNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindProgramNV = extproc; + + glBindProgramNV(target, id); +} + +static void APIENTRY InitDeleteProgramsNV (GLsizei n, const GLuint *programs) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteProgramsNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteProgramsNV = extproc; + + glDeleteProgramsNV(n, programs); +} + +static void APIENTRY InitExecuteProgramNV (GLenum target, GLuint id, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glExecuteProgramNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glExecuteProgramNV = extproc; + + glExecuteProgramNV(target, id, params); +} + +static void APIENTRY InitGenProgramsNV (GLsizei n, GLuint *programs) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenProgramsNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenProgramsNV = extproc; + + glGenProgramsNV(n, programs); +} + +static void APIENTRY InitGetProgramParameterdvNV (GLenum target, GLuint index, GLenum pname, GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramParameterdvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramParameterdvNV = extproc; + + glGetProgramParameterdvNV(target, index, pname, params); +} + +static void APIENTRY InitGetProgramParameterfvNV (GLenum target, GLuint index, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramParameterfvNV = extproc; + + glGetProgramParameterfvNV(target, index, pname, params); +} + +static void APIENTRY InitGetProgramivNV (GLuint id, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramivNV = extproc; + + glGetProgramivNV(id, pname, params); +} + +static void APIENTRY InitGetProgramStringNV (GLuint id, GLenum pname, GLubyte *program) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramStringNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramStringNV = extproc; + + glGetProgramStringNV(id, pname, program); +} + +static void APIENTRY InitGetTrackMatrixivNV (GLenum target, GLuint address, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetTrackMatrixivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetTrackMatrixivNV = extproc; + + glGetTrackMatrixivNV(target, address, pname, params); +} + +static void APIENTRY InitGetVertexAttribdvNV (GLuint index, GLenum pname, GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribdvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribdvNV = extproc; + + glGetVertexAttribdvNV(index, pname, params); +} + +static void APIENTRY InitGetVertexAttribfvNV (GLuint index, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribfvNV = extproc; + + glGetVertexAttribfvNV(index, pname, params); +} + +static void APIENTRY InitGetVertexAttribivNV (GLuint index, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribivNV = extproc; + + glGetVertexAttribivNV(index, pname, params); +} + +static void APIENTRY InitGetVertexAttribPointervNV (GLuint index, GLenum pname, GLvoid* *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribPointervNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribPointervNV = extproc; + + glGetVertexAttribPointervNV(index, pname, pointer); +} + +static GLboolean APIENTRY InitIsProgramNV (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsProgramNV"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsProgramNV = extproc; + + return glIsProgramNV(id); +} + +static void APIENTRY InitLoadProgramNV (GLenum target, GLuint id, GLsizei len, const GLubyte *program) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLoadProgramNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLoadProgramNV = extproc; + + glLoadProgramNV(target, id, len, program); +} + +static void APIENTRY InitProgramParameter4dNV (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramParameter4dNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramParameter4dNV = extproc; + + glProgramParameter4dNV(target, index, x, y, z, w); +} + +static void APIENTRY InitProgramParameter4dvNV (GLenum target, GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramParameter4dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramParameter4dvNV = extproc; + + glProgramParameter4dvNV(target, index, v); +} + +static void APIENTRY InitProgramParameter4fNV (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramParameter4fNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramParameter4fNV = extproc; + + glProgramParameter4fNV(target, index, x, y, z, w); +} + +static void APIENTRY InitProgramParameter4fvNV (GLenum target, GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramParameter4fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramParameter4fvNV = extproc; + + glProgramParameter4fvNV(target, index, v); +} + +static void APIENTRY InitProgramParameters4dvNV (GLenum target, GLuint index, GLuint count, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramParameters4dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramParameters4dvNV = extproc; + + glProgramParameters4dvNV(target, index, count, v); +} + +static void APIENTRY InitProgramParameters4fvNV (GLenum target, GLuint index, GLuint count, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramParameters4fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramParameters4fvNV = extproc; + + glProgramParameters4fvNV(target, index, count, v); +} + +static void APIENTRY InitRequestResidentProgramsNV (GLsizei n, const GLuint *programs) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glRequestResidentProgramsNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glRequestResidentProgramsNV = extproc; + + glRequestResidentProgramsNV(n, programs); +} + +static void APIENTRY InitTrackMatrixNV (GLenum target, GLuint address, GLenum matrix, GLenum transform) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTrackMatrixNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTrackMatrixNV = extproc; + + glTrackMatrixNV(target, address, matrix, transform); +} + +static void APIENTRY InitVertexAttribPointerNV (GLuint index, GLint fsize, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribPointerNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribPointerNV = extproc; + + glVertexAttribPointerNV(index, fsize, type, stride, pointer); +} + +static void APIENTRY InitVertexAttrib1dNV (GLuint index, GLdouble x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1dNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1dNV = extproc; + + glVertexAttrib1dNV(index, x); +} + +static void APIENTRY InitVertexAttrib1dvNV (GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1dvNV = extproc; + + glVertexAttrib1dvNV(index, v); +} + +static void APIENTRY InitVertexAttrib1fNV (GLuint index, GLfloat x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1fNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1fNV = extproc; + + glVertexAttrib1fNV(index, x); +} + +static void APIENTRY InitVertexAttrib1fvNV (GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1fvNV = extproc; + + glVertexAttrib1fvNV(index, v); +} + +static void APIENTRY InitVertexAttrib1sNV (GLuint index, GLshort x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1sNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1sNV = extproc; + + glVertexAttrib1sNV(index, x); +} + +static void APIENTRY InitVertexAttrib1svNV (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1svNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1svNV = extproc; + + glVertexAttrib1svNV(index, v); +} + +static void APIENTRY InitVertexAttrib2dNV (GLuint index, GLdouble x, GLdouble y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2dNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2dNV = extproc; + + glVertexAttrib2dNV(index, x, y); +} + +static void APIENTRY InitVertexAttrib2dvNV (GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2dvNV = extproc; + + glVertexAttrib2dvNV(index, v); +} + +static void APIENTRY InitVertexAttrib2fNV (GLuint index, GLfloat x, GLfloat y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2fNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2fNV = extproc; + + glVertexAttrib2fNV(index, x, y); +} + +static void APIENTRY InitVertexAttrib2fvNV (GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2fvNV = extproc; + + glVertexAttrib2fvNV(index, v); +} + +static void APIENTRY InitVertexAttrib2sNV (GLuint index, GLshort x, GLshort y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2sNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2sNV = extproc; + + glVertexAttrib2sNV(index, x, y); +} + +static void APIENTRY InitVertexAttrib2svNV (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2svNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2svNV = extproc; + + glVertexAttrib2svNV(index, v); +} + +static void APIENTRY InitVertexAttrib3dNV (GLuint index, GLdouble x, GLdouble y, GLdouble z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3dNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3dNV = extproc; + + glVertexAttrib3dNV(index, x, y, z); +} + +static void APIENTRY InitVertexAttrib3dvNV (GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3dvNV = extproc; + + glVertexAttrib3dvNV(index, v); +} + +static void APIENTRY InitVertexAttrib3fNV (GLuint index, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3fNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3fNV = extproc; + + glVertexAttrib3fNV(index, x, y, z); +} + +static void APIENTRY InitVertexAttrib3fvNV (GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3fvNV = extproc; + + glVertexAttrib3fvNV(index, v); +} + +static void APIENTRY InitVertexAttrib3sNV (GLuint index, GLshort x, GLshort y, GLshort z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3sNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3sNV = extproc; + + glVertexAttrib3sNV(index, x, y, z); +} + +static void APIENTRY InitVertexAttrib3svNV (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3svNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3svNV = extproc; + + glVertexAttrib3svNV(index, v); +} + +static void APIENTRY InitVertexAttrib4dNV (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4dNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4dNV = extproc; + + glVertexAttrib4dNV(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4dvNV (GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4dvNV = extproc; + + glVertexAttrib4dvNV(index, v); +} + +static void APIENTRY InitVertexAttrib4fNV (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4fNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4fNV = extproc; + + glVertexAttrib4fNV(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4fvNV (GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4fvNV = extproc; + + glVertexAttrib4fvNV(index, v); +} + +static void APIENTRY InitVertexAttrib4sNV (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4sNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4sNV = extproc; + + glVertexAttrib4sNV(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4svNV (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4svNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4svNV = extproc; + + glVertexAttrib4svNV(index, v); +} + +static void APIENTRY InitVertexAttrib4ubNV (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4ubNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4ubNV = extproc; + + glVertexAttrib4ubNV(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4ubvNV (GLuint index, const GLubyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4ubvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4ubvNV = extproc; + + glVertexAttrib4ubvNV(index, v); +} + +static void APIENTRY InitVertexAttribs1dvNV (GLuint index, GLsizei count, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs1dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs1dvNV = extproc; + + glVertexAttribs1dvNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs1fvNV (GLuint index, GLsizei count, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs1fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs1fvNV = extproc; + + glVertexAttribs1fvNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs1svNV (GLuint index, GLsizei count, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs1svNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs1svNV = extproc; + + glVertexAttribs1svNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs2dvNV (GLuint index, GLsizei count, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs2dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs2dvNV = extproc; + + glVertexAttribs2dvNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs2fvNV (GLuint index, GLsizei count, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs2fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs2fvNV = extproc; + + glVertexAttribs2fvNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs2svNV (GLuint index, GLsizei count, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs2svNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs2svNV = extproc; + + glVertexAttribs2svNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs3dvNV (GLuint index, GLsizei count, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs3dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs3dvNV = extproc; + + glVertexAttribs3dvNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs3fvNV (GLuint index, GLsizei count, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs3fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs3fvNV = extproc; + + glVertexAttribs3fvNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs3svNV (GLuint index, GLsizei count, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs3svNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs3svNV = extproc; + + glVertexAttribs3svNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs4dvNV (GLuint index, GLsizei count, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs4dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs4dvNV = extproc; + + glVertexAttribs4dvNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs4fvNV (GLuint index, GLsizei count, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs4fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs4fvNV = extproc; + + glVertexAttribs4fvNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs4svNV (GLuint index, GLsizei count, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs4svNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs4svNV = extproc; + + glVertexAttribs4svNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs4ubvNV (GLuint index, GLsizei count, const GLubyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs4ubvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs4ubvNV = extproc; + + glVertexAttribs4ubvNV(index, count, v); +} + +static void APIENTRY InitTexBumpParameterivATI (GLenum pname, const GLint *param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexBumpParameterivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexBumpParameterivATI = extproc; + + glTexBumpParameterivATI(pname, param); +} + +static void APIENTRY InitTexBumpParameterfvATI (GLenum pname, const GLfloat *param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexBumpParameterfvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexBumpParameterfvATI = extproc; + + glTexBumpParameterfvATI(pname, param); +} + +static void APIENTRY InitGetTexBumpParameterivATI (GLenum pname, GLint *param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetTexBumpParameterivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetTexBumpParameterivATI = extproc; + + glGetTexBumpParameterivATI(pname, param); +} + +static void APIENTRY InitGetTexBumpParameterfvATI (GLenum pname, GLfloat *param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetTexBumpParameterfvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetTexBumpParameterfvATI = extproc; + + glGetTexBumpParameterfvATI(pname, param); +} + +static GLuint APIENTRY InitGenFragmentShadersATI (GLuint range) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenFragmentShadersATI"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glGenFragmentShadersATI = extproc; + + return glGenFragmentShadersATI(range); +} + +static void APIENTRY InitBindFragmentShaderATI (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindFragmentShaderATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindFragmentShaderATI = extproc; + + glBindFragmentShaderATI(id); +} + +static void APIENTRY InitDeleteFragmentShaderATI (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteFragmentShaderATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteFragmentShaderATI = extproc; + + glDeleteFragmentShaderATI(id); +} + +static void APIENTRY InitBeginFragmentShaderATI (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBeginFragmentShaderATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBeginFragmentShaderATI = extproc; + + glBeginFragmentShaderATI(); +} + +static void APIENTRY InitEndFragmentShaderATI (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEndFragmentShaderATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEndFragmentShaderATI = extproc; + + glEndFragmentShaderATI(); +} + +static void APIENTRY InitPassTexCoordATI (GLuint dst, GLuint coord, GLenum swizzle) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPassTexCoordATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPassTexCoordATI = extproc; + + glPassTexCoordATI(dst, coord, swizzle); +} + +static void APIENTRY InitSampleMapATI (GLuint dst, GLuint interp, GLenum swizzle) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSampleMapATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSampleMapATI = extproc; + + glSampleMapATI(dst, interp, swizzle); +} + +static void APIENTRY InitColorFragmentOp1ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorFragmentOp1ATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorFragmentOp1ATI = extproc; + + glColorFragmentOp1ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod); +} + +static void APIENTRY InitColorFragmentOp2ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorFragmentOp2ATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorFragmentOp2ATI = extproc; + + glColorFragmentOp2ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod); +} + +static void APIENTRY InitColorFragmentOp3ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorFragmentOp3ATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorFragmentOp3ATI = extproc; + + glColorFragmentOp3ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod); +} + +static void APIENTRY InitAlphaFragmentOp1ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glAlphaFragmentOp1ATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glAlphaFragmentOp1ATI = extproc; + + glAlphaFragmentOp1ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod); +} + +static void APIENTRY InitAlphaFragmentOp2ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glAlphaFragmentOp2ATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glAlphaFragmentOp2ATI = extproc; + + glAlphaFragmentOp2ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod); +} + +static void APIENTRY InitAlphaFragmentOp3ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glAlphaFragmentOp3ATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glAlphaFragmentOp3ATI = extproc; + + glAlphaFragmentOp3ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod); +} + +static void APIENTRY InitSetFragmentShaderConstantATI (GLuint dst, const GLfloat *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSetFragmentShaderConstantATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSetFragmentShaderConstantATI = extproc; + + glSetFragmentShaderConstantATI(dst, value); +} + +static void APIENTRY InitPNTrianglesiATI (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPNTrianglesiATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPNTrianglesiATI = extproc; + + glPNTrianglesiATI(pname, param); +} + +static void APIENTRY InitPNTrianglesfATI (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPNTrianglesfATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPNTrianglesfATI = extproc; + + glPNTrianglesfATI(pname, param); +} + +static GLuint APIENTRY InitNewObjectBufferATI (GLsizei size, const GLvoid *pointer, GLenum usage) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNewObjectBufferATI"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glNewObjectBufferATI = extproc; + + return glNewObjectBufferATI(size, pointer, usage); +} + +static GLboolean APIENTRY InitIsObjectBufferATI (GLuint buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsObjectBufferATI"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsObjectBufferATI = extproc; + + return glIsObjectBufferATI(buffer); +} + +static void APIENTRY InitUpdateObjectBufferATI (GLuint buffer, GLuint offset, GLsizei size, const GLvoid *pointer, GLenum preserve) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUpdateObjectBufferATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUpdateObjectBufferATI = extproc; + + glUpdateObjectBufferATI(buffer, offset, size, pointer, preserve); +} + +static void APIENTRY InitGetObjectBufferfvATI (GLuint buffer, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetObjectBufferfvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetObjectBufferfvATI = extproc; + + glGetObjectBufferfvATI(buffer, pname, params); +} + +static void APIENTRY InitGetObjectBufferivATI (GLuint buffer, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetObjectBufferivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetObjectBufferivATI = extproc; + + glGetObjectBufferivATI(buffer, pname, params); +} + +static void APIENTRY InitFreeObjectBufferATI (GLuint buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFreeObjectBufferATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFreeObjectBufferATI = extproc; + + glFreeObjectBufferATI(buffer); +} + +static void APIENTRY InitArrayObjectATI (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glArrayObjectATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glArrayObjectATI = extproc; + + glArrayObjectATI(array, size, type, stride, buffer, offset); +} + +static void APIENTRY InitGetArrayObjectfvATI (GLenum array, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetArrayObjectfvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetArrayObjectfvATI = extproc; + + glGetArrayObjectfvATI(array, pname, params); +} + +static void APIENTRY InitGetArrayObjectivATI (GLenum array, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetArrayObjectivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetArrayObjectivATI = extproc; + + glGetArrayObjectivATI(array, pname, params); +} + +static void APIENTRY InitVariantArrayObjectATI (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantArrayObjectATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantArrayObjectATI = extproc; + + glVariantArrayObjectATI(id, type, stride, buffer, offset); +} + +static void APIENTRY InitGetVariantArrayObjectfvATI (GLuint id, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVariantArrayObjectfvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVariantArrayObjectfvATI = extproc; + + glGetVariantArrayObjectfvATI(id, pname, params); +} + +static void APIENTRY InitGetVariantArrayObjectivATI (GLuint id, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVariantArrayObjectivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVariantArrayObjectivATI = extproc; + + glGetVariantArrayObjectivATI(id, pname, params); +} + +static void APIENTRY InitBeginVertexShaderEXT (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBeginVertexShaderEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBeginVertexShaderEXT = extproc; + + glBeginVertexShaderEXT(); +} + +static void APIENTRY InitEndVertexShaderEXT (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEndVertexShaderEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEndVertexShaderEXT = extproc; + + glEndVertexShaderEXT(); +} + +static void APIENTRY InitBindVertexShaderEXT (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindVertexShaderEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindVertexShaderEXT = extproc; + + glBindVertexShaderEXT(id); +} + +static GLuint APIENTRY InitGenVertexShadersEXT (GLuint range) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenVertexShadersEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glGenVertexShadersEXT = extproc; + + return glGenVertexShadersEXT(range); +} + +static void APIENTRY InitDeleteVertexShaderEXT (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteVertexShaderEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteVertexShaderEXT = extproc; + + glDeleteVertexShaderEXT(id); +} + +static void APIENTRY InitShaderOp1EXT (GLenum op, GLuint res, GLuint arg1) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glShaderOp1EXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glShaderOp1EXT = extproc; + + glShaderOp1EXT(op, res, arg1); +} + +static void APIENTRY InitShaderOp2EXT (GLenum op, GLuint res, GLuint arg1, GLuint arg2) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glShaderOp2EXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glShaderOp2EXT = extproc; + + glShaderOp2EXT(op, res, arg1, arg2); +} + +static void APIENTRY InitShaderOp3EXT (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glShaderOp3EXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glShaderOp3EXT = extproc; + + glShaderOp3EXT(op, res, arg1, arg2, arg3); +} + +static void APIENTRY InitSwizzleEXT (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSwizzleEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSwizzleEXT = extproc; + + glSwizzleEXT(res, in, outX, outY, outZ, outW); +} + +static void APIENTRY InitWriteMaskEXT (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWriteMaskEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWriteMaskEXT = extproc; + + glWriteMaskEXT(res, in, outX, outY, outZ, outW); +} + +static void APIENTRY InitInsertComponentEXT (GLuint res, GLuint src, GLuint num) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glInsertComponentEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glInsertComponentEXT = extproc; + + glInsertComponentEXT(res, src, num); +} + +static void APIENTRY InitExtractComponentEXT (GLuint res, GLuint src, GLuint num) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glExtractComponentEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glExtractComponentEXT = extproc; + + glExtractComponentEXT(res, src, num); +} + +static GLuint APIENTRY InitGenSymbolsEXT (GLenum datatype, GLenum storagetype, GLenum range, GLuint components) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenSymbolsEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glGenSymbolsEXT = extproc; + + return glGenSymbolsEXT(datatype, storagetype, range, components); +} + +static void APIENTRY InitSetInvariantEXT (GLuint id, GLenum type, const GLvoid *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSetInvariantEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSetInvariantEXT = extproc; + + glSetInvariantEXT(id, type, addr); +} + +static void APIENTRY InitSetLocalConstantEXT (GLuint id, GLenum type, const GLvoid *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSetLocalConstantEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSetLocalConstantEXT = extproc; + + glSetLocalConstantEXT(id, type, addr); +} + +static void APIENTRY InitVariantbvEXT (GLuint id, const GLbyte *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantbvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantbvEXT = extproc; + + glVariantbvEXT(id, addr); +} + +static void APIENTRY InitVariantsvEXT (GLuint id, const GLshort *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantsvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantsvEXT = extproc; + + glVariantsvEXT(id, addr); +} + +static void APIENTRY InitVariantivEXT (GLuint id, const GLint *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantivEXT = extproc; + + glVariantivEXT(id, addr); +} + +static void APIENTRY InitVariantfvEXT (GLuint id, const GLfloat *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantfvEXT = extproc; + + glVariantfvEXT(id, addr); +} + +static void APIENTRY InitVariantdvEXT (GLuint id, const GLdouble *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantdvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantdvEXT = extproc; + + glVariantdvEXT(id, addr); +} + +static void APIENTRY InitVariantubvEXT (GLuint id, const GLubyte *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantubvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantubvEXT = extproc; + + glVariantubvEXT(id, addr); +} + +static void APIENTRY InitVariantusvEXT (GLuint id, const GLushort *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantusvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantusvEXT = extproc; + + glVariantusvEXT(id, addr); +} + +static void APIENTRY InitVariantuivEXT (GLuint id, const GLuint *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantuivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantuivEXT = extproc; + + glVariantuivEXT(id, addr); +} + +static void APIENTRY InitVariantPointerEXT (GLuint id, GLenum type, GLuint stride, const GLvoid *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantPointerEXT = extproc; + + glVariantPointerEXT(id, type, stride, addr); +} + +static void APIENTRY InitEnableVariantClientStateEXT (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEnableVariantClientStateEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEnableVariantClientStateEXT = extproc; + + glEnableVariantClientStateEXT(id); +} + +static void APIENTRY InitDisableVariantClientStateEXT (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDisableVariantClientStateEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDisableVariantClientStateEXT = extproc; + + glDisableVariantClientStateEXT(id); +} + +static GLuint APIENTRY InitBindLightParameterEXT (GLenum light, GLenum value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindLightParameterEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glBindLightParameterEXT = extproc; + + return glBindLightParameterEXT(light, value); +} + +static GLuint APIENTRY InitBindMaterialParameterEXT (GLenum face, GLenum value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindMaterialParameterEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glBindMaterialParameterEXT = extproc; + + return glBindMaterialParameterEXT(face, value); +} + +static GLuint APIENTRY InitBindTexGenParameterEXT (GLenum unit, GLenum coord, GLenum value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindTexGenParameterEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glBindTexGenParameterEXT = extproc; + + return glBindTexGenParameterEXT(unit, coord, value); +} + +static GLuint APIENTRY InitBindTextureUnitParameterEXT (GLenum unit, GLenum value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindTextureUnitParameterEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glBindTextureUnitParameterEXT = extproc; + + return glBindTextureUnitParameterEXT(unit, value); +} + +static GLuint APIENTRY InitBindParameterEXT (GLenum value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindParameterEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glBindParameterEXT = extproc; + + return glBindParameterEXT(value); +} + +static GLboolean APIENTRY InitIsVariantEnabledEXT (GLuint id, GLenum cap) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsVariantEnabledEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsVariantEnabledEXT = extproc; + + return glIsVariantEnabledEXT(id, cap); +} + +static void APIENTRY InitGetVariantBooleanvEXT (GLuint id, GLenum value, GLboolean *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVariantBooleanvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVariantBooleanvEXT = extproc; + + glGetVariantBooleanvEXT(id, value, data); +} + +static void APIENTRY InitGetVariantIntegervEXT (GLuint id, GLenum value, GLint *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVariantIntegervEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVariantIntegervEXT = extproc; + + glGetVariantIntegervEXT(id, value, data); +} + +static void APIENTRY InitGetVariantFloatvEXT (GLuint id, GLenum value, GLfloat *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVariantFloatvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVariantFloatvEXT = extproc; + + glGetVariantFloatvEXT(id, value, data); +} + +static void APIENTRY InitGetVariantPointervEXT (GLuint id, GLenum value, GLvoid* *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVariantPointervEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVariantPointervEXT = extproc; + + glGetVariantPointervEXT(id, value, data); +} + +static void APIENTRY InitGetInvariantBooleanvEXT (GLuint id, GLenum value, GLboolean *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetInvariantBooleanvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetInvariantBooleanvEXT = extproc; + + glGetInvariantBooleanvEXT(id, value, data); +} + +static void APIENTRY InitGetInvariantIntegervEXT (GLuint id, GLenum value, GLint *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetInvariantIntegervEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetInvariantIntegervEXT = extproc; + + glGetInvariantIntegervEXT(id, value, data); +} + +static void APIENTRY InitGetInvariantFloatvEXT (GLuint id, GLenum value, GLfloat *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetInvariantFloatvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetInvariantFloatvEXT = extproc; + + glGetInvariantFloatvEXT(id, value, data); +} + +static void APIENTRY InitGetLocalConstantBooleanvEXT (GLuint id, GLenum value, GLboolean *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetLocalConstantBooleanvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetLocalConstantBooleanvEXT = extproc; + + glGetLocalConstantBooleanvEXT(id, value, data); +} + +static void APIENTRY InitGetLocalConstantIntegervEXT (GLuint id, GLenum value, GLint *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetLocalConstantIntegervEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetLocalConstantIntegervEXT = extproc; + + glGetLocalConstantIntegervEXT(id, value, data); +} + +static void APIENTRY InitGetLocalConstantFloatvEXT (GLuint id, GLenum value, GLfloat *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetLocalConstantFloatvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetLocalConstantFloatvEXT = extproc; + + glGetLocalConstantFloatvEXT(id, value, data); +} + +static void APIENTRY InitVertexStream1sATI (GLenum stream, GLshort x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream1sATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream1sATI = extproc; + + glVertexStream1sATI(stream, x); +} + +static void APIENTRY InitVertexStream1svATI (GLenum stream, const GLshort *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream1svATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream1svATI = extproc; + + glVertexStream1svATI(stream, coords); +} + +static void APIENTRY InitVertexStream1iATI (GLenum stream, GLint x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream1iATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream1iATI = extproc; + + glVertexStream1iATI(stream, x); +} + +static void APIENTRY InitVertexStream1ivATI (GLenum stream, const GLint *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream1ivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream1ivATI = extproc; + + glVertexStream1ivATI(stream, coords); +} + +static void APIENTRY InitVertexStream1fATI (GLenum stream, GLfloat x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream1fATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream1fATI = extproc; + + glVertexStream1fATI(stream, x); +} + +static void APIENTRY InitVertexStream1fvATI (GLenum stream, const GLfloat *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream1fvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream1fvATI = extproc; + + glVertexStream1fvATI(stream, coords); +} + +static void APIENTRY InitVertexStream1dATI (GLenum stream, GLdouble x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream1dATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream1dATI = extproc; + + glVertexStream1dATI(stream, x); +} + +static void APIENTRY InitVertexStream1dvATI (GLenum stream, const GLdouble *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream1dvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream1dvATI = extproc; + + glVertexStream1dvATI(stream, coords); +} + +static void APIENTRY InitVertexStream2sATI (GLenum stream, GLshort x, GLshort y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream2sATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream2sATI = extproc; + + glVertexStream2sATI(stream, x, y); +} + +static void APIENTRY InitVertexStream2svATI (GLenum stream, const GLshort *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream2svATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream2svATI = extproc; + + glVertexStream2svATI(stream, coords); +} + +static void APIENTRY InitVertexStream2iATI (GLenum stream, GLint x, GLint y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream2iATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream2iATI = extproc; + + glVertexStream2iATI(stream, x, y); +} + +static void APIENTRY InitVertexStream2ivATI (GLenum stream, const GLint *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream2ivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream2ivATI = extproc; + + glVertexStream2ivATI(stream, coords); +} + +static void APIENTRY InitVertexStream2fATI (GLenum stream, GLfloat x, GLfloat y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream2fATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream2fATI = extproc; + + glVertexStream2fATI(stream, x, y); +} + +static void APIENTRY InitVertexStream2fvATI (GLenum stream, const GLfloat *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream2fvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream2fvATI = extproc; + + glVertexStream2fvATI(stream, coords); +} + +static void APIENTRY InitVertexStream2dATI (GLenum stream, GLdouble x, GLdouble y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream2dATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream2dATI = extproc; + + glVertexStream2dATI(stream, x, y); +} + +static void APIENTRY InitVertexStream2dvATI (GLenum stream, const GLdouble *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream2dvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream2dvATI = extproc; + + glVertexStream2dvATI(stream, coords); +} + +static void APIENTRY InitVertexStream3sATI (GLenum stream, GLshort x, GLshort y, GLshort z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream3sATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream3sATI = extproc; + + glVertexStream3sATI(stream, x, y, z); +} + +static void APIENTRY InitVertexStream3svATI (GLenum stream, const GLshort *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream3svATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream3svATI = extproc; + + glVertexStream3svATI(stream, coords); +} + +static void APIENTRY InitVertexStream3iATI (GLenum stream, GLint x, GLint y, GLint z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream3iATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream3iATI = extproc; + + glVertexStream3iATI(stream, x, y, z); +} + +static void APIENTRY InitVertexStream3ivATI (GLenum stream, const GLint *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream3ivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream3ivATI = extproc; + + glVertexStream3ivATI(stream, coords); +} + +static void APIENTRY InitVertexStream3fATI (GLenum stream, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream3fATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream3fATI = extproc; + + glVertexStream3fATI(stream, x, y, z); +} + +static void APIENTRY InitVertexStream3fvATI (GLenum stream, const GLfloat *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream3fvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream3fvATI = extproc; + + glVertexStream3fvATI(stream, coords); +} + +static void APIENTRY InitVertexStream3dATI (GLenum stream, GLdouble x, GLdouble y, GLdouble z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream3dATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream3dATI = extproc; + + glVertexStream3dATI(stream, x, y, z); +} + +static void APIENTRY InitVertexStream3dvATI (GLenum stream, const GLdouble *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream3dvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream3dvATI = extproc; + + glVertexStream3dvATI(stream, coords); +} + +static void APIENTRY InitVertexStream4sATI (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream4sATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream4sATI = extproc; + + glVertexStream4sATI(stream, x, y, z, w); +} + +static void APIENTRY InitVertexStream4svATI (GLenum stream, const GLshort *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream4svATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream4svATI = extproc; + + glVertexStream4svATI(stream, coords); +} + +static void APIENTRY InitVertexStream4iATI (GLenum stream, GLint x, GLint y, GLint z, GLint w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream4iATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream4iATI = extproc; + + glVertexStream4iATI(stream, x, y, z, w); +} + +static void APIENTRY InitVertexStream4ivATI (GLenum stream, const GLint *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream4ivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream4ivATI = extproc; + + glVertexStream4ivATI(stream, coords); +} + +static void APIENTRY InitVertexStream4fATI (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream4fATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream4fATI = extproc; + + glVertexStream4fATI(stream, x, y, z, w); +} + +static void APIENTRY InitVertexStream4fvATI (GLenum stream, const GLfloat *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream4fvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream4fvATI = extproc; + + glVertexStream4fvATI(stream, coords); +} + +static void APIENTRY InitVertexStream4dATI (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream4dATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream4dATI = extproc; + + glVertexStream4dATI(stream, x, y, z, w); +} + +static void APIENTRY InitVertexStream4dvATI (GLenum stream, const GLdouble *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream4dvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream4dvATI = extproc; + + glVertexStream4dvATI(stream, coords); +} + +static void APIENTRY InitNormalStream3bATI (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3bATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3bATI = extproc; + + glNormalStream3bATI(stream, nx, ny, nz); +} + +static void APIENTRY InitNormalStream3bvATI (GLenum stream, const GLbyte *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3bvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3bvATI = extproc; + + glNormalStream3bvATI(stream, coords); +} + +static void APIENTRY InitNormalStream3sATI (GLenum stream, GLshort nx, GLshort ny, GLshort nz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3sATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3sATI = extproc; + + glNormalStream3sATI(stream, nx, ny, nz); +} + +static void APIENTRY InitNormalStream3svATI (GLenum stream, const GLshort *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3svATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3svATI = extproc; + + glNormalStream3svATI(stream, coords); +} + +static void APIENTRY InitNormalStream3iATI (GLenum stream, GLint nx, GLint ny, GLint nz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3iATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3iATI = extproc; + + glNormalStream3iATI(stream, nx, ny, nz); +} + +static void APIENTRY InitNormalStream3ivATI (GLenum stream, const GLint *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3ivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3ivATI = extproc; + + glNormalStream3ivATI(stream, coords); +} + +static void APIENTRY InitNormalStream3fATI (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3fATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3fATI = extproc; + + glNormalStream3fATI(stream, nx, ny, nz); +} + +static void APIENTRY InitNormalStream3fvATI (GLenum stream, const GLfloat *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3fvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3fvATI = extproc; + + glNormalStream3fvATI(stream, coords); +} + +static void APIENTRY InitNormalStream3dATI (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3dATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3dATI = extproc; + + glNormalStream3dATI(stream, nx, ny, nz); +} + +static void APIENTRY InitNormalStream3dvATI (GLenum stream, const GLdouble *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3dvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3dvATI = extproc; + + glNormalStream3dvATI(stream, coords); +} + +static void APIENTRY InitClientActiveVertexStreamATI (GLenum stream) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glClientActiveVertexStreamATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glClientActiveVertexStreamATI = extproc; + + glClientActiveVertexStreamATI(stream); +} + +static void APIENTRY InitVertexBlendEnviATI (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexBlendEnviATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexBlendEnviATI = extproc; + + glVertexBlendEnviATI(pname, param); +} + +static void APIENTRY InitVertexBlendEnvfATI (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexBlendEnvfATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexBlendEnvfATI = extproc; + + glVertexBlendEnvfATI(pname, param); +} + +static void APIENTRY InitElementPointerATI (GLenum type, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glElementPointerATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glElementPointerATI = extproc; + + glElementPointerATI(type, pointer); +} + +static void APIENTRY InitDrawElementArrayATI (GLenum mode, GLsizei count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawElementArrayATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawElementArrayATI = extproc; + + glDrawElementArrayATI(mode, count); +} + +static void APIENTRY InitDrawRangeElementArrayATI (GLenum mode, GLuint start, GLuint end, GLsizei count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawRangeElementArrayATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawRangeElementArrayATI = extproc; + + glDrawRangeElementArrayATI(mode, start, end, count); +} + +static void APIENTRY InitDrawMeshArraysSUN (GLenum mode, GLint first, GLsizei count, GLsizei width) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawMeshArraysSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawMeshArraysSUN = extproc; + + glDrawMeshArraysSUN(mode, first, count, width); +} + +static void APIENTRY InitGenOcclusionQueriesNV (GLsizei n, GLuint *ids) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenOcclusionQueriesNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenOcclusionQueriesNV = extproc; + + glGenOcclusionQueriesNV(n, ids); +} + +static void APIENTRY InitDeleteOcclusionQueriesNV (GLsizei n, const GLuint *ids) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteOcclusionQueriesNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteOcclusionQueriesNV = extproc; + + glDeleteOcclusionQueriesNV(n, ids); +} + +static GLboolean APIENTRY InitIsOcclusionQueryNV (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsOcclusionQueryNV"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsOcclusionQueryNV = extproc; + + return glIsOcclusionQueryNV(id); +} + +static void APIENTRY InitBeginOcclusionQueryNV (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBeginOcclusionQueryNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBeginOcclusionQueryNV = extproc; + + glBeginOcclusionQueryNV(id); +} + +static void APIENTRY InitEndOcclusionQueryNV (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEndOcclusionQueryNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEndOcclusionQueryNV = extproc; + + glEndOcclusionQueryNV(); +} + +static void APIENTRY InitGetOcclusionQueryivNV (GLuint id, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetOcclusionQueryivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetOcclusionQueryivNV = extproc; + + glGetOcclusionQueryivNV(id, pname, params); +} + +static void APIENTRY InitGetOcclusionQueryuivNV (GLuint id, GLenum pname, GLuint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetOcclusionQueryuivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetOcclusionQueryuivNV = extproc; + + glGetOcclusionQueryuivNV(id, pname, params); +} + +static void APIENTRY InitPointParameteriNV (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameteriNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameteriNV = extproc; + + glPointParameteriNV(pname, param); +} + +static void APIENTRY InitPointParameterivNV (GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterivNV = extproc; + + glPointParameterivNV(pname, params); +} + +static void APIENTRY InitActiveStencilFaceEXT (GLenum face) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glActiveStencilFaceEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glActiveStencilFaceEXT = extproc; + + glActiveStencilFaceEXT(face); +} + +static void APIENTRY InitElementPointerAPPLE (GLenum type, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glElementPointerAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glElementPointerAPPLE = extproc; + + glElementPointerAPPLE(type, pointer); +} + +static void APIENTRY InitDrawElementArrayAPPLE (GLenum mode, GLint first, GLsizei count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawElementArrayAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawElementArrayAPPLE = extproc; + + glDrawElementArrayAPPLE(mode, first, count); +} + +static void APIENTRY InitDrawRangeElementArrayAPPLE (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawRangeElementArrayAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawRangeElementArrayAPPLE = extproc; + + glDrawRangeElementArrayAPPLE(mode, start, end, first, count); +} + +static void APIENTRY InitMultiDrawElementArrayAPPLE (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiDrawElementArrayAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiDrawElementArrayAPPLE = extproc; + + glMultiDrawElementArrayAPPLE(mode, first, count, primcount); +} + +static void APIENTRY InitMultiDrawRangeElementArrayAPPLE (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiDrawRangeElementArrayAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiDrawRangeElementArrayAPPLE = extproc; + + glMultiDrawRangeElementArrayAPPLE(mode, start, end, first, count, primcount); +} + +static void APIENTRY InitGenFencesAPPLE (GLsizei n, GLuint *fences) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenFencesAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenFencesAPPLE = extproc; + + glGenFencesAPPLE(n, fences); +} + +static void APIENTRY InitDeleteFencesAPPLE (GLsizei n, const GLuint *fences) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteFencesAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteFencesAPPLE = extproc; + + glDeleteFencesAPPLE(n, fences); +} + +static void APIENTRY InitSetFenceAPPLE (GLuint fence) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSetFenceAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSetFenceAPPLE = extproc; + + glSetFenceAPPLE(fence); +} + +static GLboolean APIENTRY InitIsFenceAPPLE (GLuint fence) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsFenceAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsFenceAPPLE = extproc; + + return glIsFenceAPPLE(fence); +} + +static GLboolean APIENTRY InitTestFenceAPPLE (GLuint fence) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTestFenceAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glTestFenceAPPLE = extproc; + + return glTestFenceAPPLE(fence); +} + +static void APIENTRY InitFinishFenceAPPLE (GLuint fence) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFinishFenceAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFinishFenceAPPLE = extproc; + + glFinishFenceAPPLE(fence); +} + +static GLboolean APIENTRY InitTestObjectAPPLE (GLenum object, GLuint name) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTestObjectAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glTestObjectAPPLE = extproc; + + return glTestObjectAPPLE(object, name); +} + +static void APIENTRY InitFinishObjectAPPLE (GLenum object, GLint name) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFinishObjectAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFinishObjectAPPLE = extproc; + + glFinishObjectAPPLE(object, name); +} + +static void APIENTRY InitBindVertexArrayAPPLE (GLuint array) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindVertexArrayAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindVertexArrayAPPLE = extproc; + + glBindVertexArrayAPPLE(array); +} + +static void APIENTRY InitDeleteVertexArraysAPPLE (GLsizei n, const GLuint *arrays) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteVertexArraysAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteVertexArraysAPPLE = extproc; + + glDeleteVertexArraysAPPLE(n, arrays); +} + +static void APIENTRY InitGenVertexArraysAPPLE (GLsizei n, const GLuint *arrays) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenVertexArraysAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenVertexArraysAPPLE = extproc; + + glGenVertexArraysAPPLE(n, arrays); +} + +static GLboolean APIENTRY InitIsVertexArrayAPPLE (GLuint array) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsVertexArrayAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsVertexArrayAPPLE = extproc; + + return glIsVertexArrayAPPLE(array); +} + +static void APIENTRY InitVertexArrayRangeAPPLE (GLsizei length, GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexArrayRangeAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexArrayRangeAPPLE = extproc; + + glVertexArrayRangeAPPLE(length, pointer); +} + +static void APIENTRY InitFlushVertexArrayRangeAPPLE (GLsizei length, GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFlushVertexArrayRangeAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFlushVertexArrayRangeAPPLE = extproc; + + glFlushVertexArrayRangeAPPLE(length, pointer); +} + +static void APIENTRY InitVertexArrayParameteriAPPLE (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexArrayParameteriAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexArrayParameteriAPPLE = extproc; + + glVertexArrayParameteriAPPLE(pname, param); +} + +static void APIENTRY InitDrawBuffersATI (GLsizei n, const GLenum *bufs) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawBuffersATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawBuffersATI = extproc; + + glDrawBuffersATI(n, bufs); +} + +static void APIENTRY InitProgramNamedParameter4fNV (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramNamedParameter4fNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramNamedParameter4fNV = extproc; + + glProgramNamedParameter4fNV(id, len, name, x, y, z, w); +} + +static void APIENTRY InitProgramNamedParameter4dNV (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramNamedParameter4dNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramNamedParameter4dNV = extproc; + + glProgramNamedParameter4dNV(id, len, name, x, y, z, w); +} + +static void APIENTRY InitProgramNamedParameter4fvNV (GLuint id, GLsizei len, const GLubyte *name, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramNamedParameter4fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramNamedParameter4fvNV = extproc; + + glProgramNamedParameter4fvNV(id, len, name, v); +} + +static void APIENTRY InitProgramNamedParameter4dvNV (GLuint id, GLsizei len, const GLubyte *name, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramNamedParameter4dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramNamedParameter4dvNV = extproc; + + glProgramNamedParameter4dvNV(id, len, name, v); +} + +static void APIENTRY InitGetProgramNamedParameterfvNV (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramNamedParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramNamedParameterfvNV = extproc; + + glGetProgramNamedParameterfvNV(id, len, name, params); +} + +static void APIENTRY InitGetProgramNamedParameterdvNV (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramNamedParameterdvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramNamedParameterdvNV = extproc; + + glGetProgramNamedParameterdvNV(id, len, name, params); +} + +static void APIENTRY InitVertex2hNV (GLhalfNV x, GLhalfNV y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertex2hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertex2hNV = extproc; + + glVertex2hNV(x, y); +} + +static void APIENTRY InitVertex2hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertex2hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertex2hvNV = extproc; + + glVertex2hvNV(v); +} + +static void APIENTRY InitVertex3hNV (GLhalfNV x, GLhalfNV y, GLhalfNV z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertex3hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertex3hNV = extproc; + + glVertex3hNV(x, y, z); +} + +static void APIENTRY InitVertex3hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertex3hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertex3hvNV = extproc; + + glVertex3hvNV(v); +} + +static void APIENTRY InitVertex4hNV (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertex4hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertex4hNV = extproc; + + glVertex4hNV(x, y, z, w); +} + +static void APIENTRY InitVertex4hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertex4hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertex4hvNV = extproc; + + glVertex4hvNV(v); +} + +static void APIENTRY InitNormal3hNV (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormal3hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormal3hNV = extproc; + + glNormal3hNV(nx, ny, nz); +} + +static void APIENTRY InitNormal3hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormal3hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormal3hvNV = extproc; + + glNormal3hvNV(v); +} + +static void APIENTRY InitColor3hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor3hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor3hNV = extproc; + + glColor3hNV(red, green, blue); +} + +static void APIENTRY InitColor3hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor3hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor3hvNV = extproc; + + glColor3hvNV(v); +} + +static void APIENTRY InitColor4hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor4hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor4hNV = extproc; + + glColor4hNV(red, green, blue, alpha); +} + +static void APIENTRY InitColor4hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor4hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor4hvNV = extproc; + + glColor4hvNV(v); +} + +static void APIENTRY InitTexCoord1hNV (GLhalfNV s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord1hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord1hNV = extproc; + + glTexCoord1hNV(s); +} + +static void APIENTRY InitTexCoord1hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord1hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord1hvNV = extproc; + + glTexCoord1hvNV(v); +} + +static void APIENTRY InitTexCoord2hNV (GLhalfNV s, GLhalfNV t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2hNV = extproc; + + glTexCoord2hNV(s, t); +} + +static void APIENTRY InitTexCoord2hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2hvNV = extproc; + + glTexCoord2hvNV(v); +} + +static void APIENTRY InitTexCoord3hNV (GLhalfNV s, GLhalfNV t, GLhalfNV r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord3hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord3hNV = extproc; + + glTexCoord3hNV(s, t, r); +} + +static void APIENTRY InitTexCoord3hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord3hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord3hvNV = extproc; + + glTexCoord3hvNV(v); +} + +static void APIENTRY InitTexCoord4hNV (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord4hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord4hNV = extproc; + + glTexCoord4hNV(s, t, r, q); +} + +static void APIENTRY InitTexCoord4hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord4hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord4hvNV = extproc; + + glTexCoord4hvNV(v); +} + +static void APIENTRY InitMultiTexCoord1hNV (GLenum target, GLhalfNV s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1hNV = extproc; + + glMultiTexCoord1hNV(target, s); +} + +static void APIENTRY InitMultiTexCoord1hvNV (GLenum target, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1hvNV = extproc; + + glMultiTexCoord1hvNV(target, v); +} + +static void APIENTRY InitMultiTexCoord2hNV (GLenum target, GLhalfNV s, GLhalfNV t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2hNV = extproc; + + glMultiTexCoord2hNV(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2hvNV (GLenum target, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2hvNV = extproc; + + glMultiTexCoord2hvNV(target, v); +} + +static void APIENTRY InitMultiTexCoord3hNV (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3hNV = extproc; + + glMultiTexCoord3hNV(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3hvNV (GLenum target, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3hvNV = extproc; + + glMultiTexCoord3hvNV(target, v); +} + +static void APIENTRY InitMultiTexCoord4hNV (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4hNV = extproc; + + glMultiTexCoord4hNV(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4hvNV (GLenum target, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4hvNV = extproc; + + glMultiTexCoord4hvNV(target, v); +} + +static void APIENTRY InitFogCoordhNV (GLhalfNV fog) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordhNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordhNV = extproc; + + glFogCoordhNV(fog); +} + +static void APIENTRY InitFogCoordhvNV (const GLhalfNV *fog) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordhvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordhvNV = extproc; + + glFogCoordhvNV(fog); +} + +static void APIENTRY InitSecondaryColor3hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3hNV = extproc; + + glSecondaryColor3hNV(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3hvNV = extproc; + + glSecondaryColor3hvNV(v); +} + +static void APIENTRY InitVertexWeighthNV (GLhalfNV weight) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexWeighthNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexWeighthNV = extproc; + + glVertexWeighthNV(weight); +} + +static void APIENTRY InitVertexWeighthvNV (const GLhalfNV *weight) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexWeighthvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexWeighthvNV = extproc; + + glVertexWeighthvNV(weight); +} + +static void APIENTRY InitVertexAttrib1hNV (GLuint index, GLhalfNV x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1hNV = extproc; + + glVertexAttrib1hNV(index, x); +} + +static void APIENTRY InitVertexAttrib1hvNV (GLuint index, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1hvNV = extproc; + + glVertexAttrib1hvNV(index, v); +} + +static void APIENTRY InitVertexAttrib2hNV (GLuint index, GLhalfNV x, GLhalfNV y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2hNV = extproc; + + glVertexAttrib2hNV(index, x, y); +} + +static void APIENTRY InitVertexAttrib2hvNV (GLuint index, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2hvNV = extproc; + + glVertexAttrib2hvNV(index, v); +} + +static void APIENTRY InitVertexAttrib3hNV (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3hNV = extproc; + + glVertexAttrib3hNV(index, x, y, z); +} + +static void APIENTRY InitVertexAttrib3hvNV (GLuint index, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3hvNV = extproc; + + glVertexAttrib3hvNV(index, v); +} + +static void APIENTRY InitVertexAttrib4hNV (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4hNV = extproc; + + glVertexAttrib4hNV(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4hvNV (GLuint index, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4hvNV = extproc; + + glVertexAttrib4hvNV(index, v); +} + +static void APIENTRY InitVertexAttribs1hvNV (GLuint index, GLsizei n, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs1hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs1hvNV = extproc; + + glVertexAttribs1hvNV(index, n, v); +} + +static void APIENTRY InitVertexAttribs2hvNV (GLuint index, GLsizei n, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs2hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs2hvNV = extproc; + + glVertexAttribs2hvNV(index, n, v); +} + +static void APIENTRY InitVertexAttribs3hvNV (GLuint index, GLsizei n, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs3hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs3hvNV = extproc; + + glVertexAttribs3hvNV(index, n, v); +} + +static void APIENTRY InitVertexAttribs4hvNV (GLuint index, GLsizei n, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs4hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs4hvNV = extproc; + + glVertexAttribs4hvNV(index, n, v); +} + +static void APIENTRY InitPixelDataRangeNV (GLenum target, GLsizei length, GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelDataRangeNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelDataRangeNV = extproc; + + glPixelDataRangeNV(target, length, pointer); +} + +static void APIENTRY InitFlushPixelDataRangeNV (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFlushPixelDataRangeNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFlushPixelDataRangeNV = extproc; + + glFlushPixelDataRangeNV(target); +} + +static void APIENTRY InitPrimitiveRestartNV (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPrimitiveRestartNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPrimitiveRestartNV = extproc; + + glPrimitiveRestartNV(); +} + +static void APIENTRY InitPrimitiveRestartIndexNV (GLuint index) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPrimitiveRestartIndexNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPrimitiveRestartIndexNV = extproc; + + glPrimitiveRestartIndexNV(index); +} + +static GLvoid* APIENTRY InitMapObjectBufferATI (GLuint buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMapObjectBufferATI"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glMapObjectBufferATI = extproc; + + return glMapObjectBufferATI(buffer); +} + +static void APIENTRY InitUnmapObjectBufferATI (GLuint buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUnmapObjectBufferATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUnmapObjectBufferATI = extproc; + + glUnmapObjectBufferATI(buffer); +} + +static void APIENTRY InitStencilOpSeparateATI (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glStencilOpSeparateATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glStencilOpSeparateATI = extproc; + + glStencilOpSeparateATI(face, sfail, dpfail, dppass); +} + +static void APIENTRY InitStencilFuncSeparateATI (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glStencilFuncSeparateATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glStencilFuncSeparateATI = extproc; + + glStencilFuncSeparateATI(frontfunc, backfunc, ref, mask); +} + +static void APIENTRY InitVertexAttribArrayObjectATI (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribArrayObjectATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribArrayObjectATI = extproc; + + glVertexAttribArrayObjectATI(index, size, type, normalized, stride, buffer, offset); +} + +static void APIENTRY InitGetVertexAttribArrayObjectfvATI (GLuint index, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribArrayObjectfvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribArrayObjectfvATI = extproc; + + glGetVertexAttribArrayObjectfvATI(index, pname, params); +} + +static void APIENTRY InitGetVertexAttribArrayObjectivATI (GLuint index, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribArrayObjectivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribArrayObjectivATI = extproc; + + glGetVertexAttribArrayObjectivATI(index, pname, params); +} + +static void APIENTRY InitDepthBoundsEXT (GLclampd zmin, GLclampd zmax) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDepthBoundsEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDepthBoundsEXT = extproc; + + glDepthBoundsEXT(zmin, zmax); +} + +static void APIENTRY InitBlendEquationSeparateEXT (GLenum modeRGB, GLenum modeAlpha) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBlendEquationSeparateEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBlendEquationSeparateEXT = extproc; + + glBlendEquationSeparateEXT(modeRGB, modeAlpha); +} + +static void APIENTRY InitAddSwapHintRectWIN (GLint x, GLint y, GLsizei width, GLsizei height) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glAddSwapHintRectWIN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glAddSwapHintRectWIN = extproc; + + glAddSwapHintRectWIN(x, y, width, height); +} + +#ifdef _WIN32 + +static HANDLE WINAPI InitCreateBufferRegionARB (HDC hDC, int iLayerPlane, UINT uType) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglCreateBufferRegionARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglCreateBufferRegionARB = extproc; + + return wglCreateBufferRegionARB(hDC, iLayerPlane, uType); +} + +static VOID WINAPI InitDeleteBufferRegionARB (HANDLE hRegion) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglDeleteBufferRegionARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + wglDeleteBufferRegionARB = extproc; + + wglDeleteBufferRegionARB(hRegion); +} + +static BOOL WINAPI InitSaveBufferRegionARB (HANDLE hRegion, int x, int y, int width, int height) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglSaveBufferRegionARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglSaveBufferRegionARB = extproc; + + return wglSaveBufferRegionARB(hRegion, x, y, width, height); +} + +static BOOL WINAPI InitRestoreBufferRegionARB (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglRestoreBufferRegionARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglRestoreBufferRegionARB = extproc; + + return wglRestoreBufferRegionARB(hRegion, x, y, width, height, xSrc, ySrc); +} + +static const WINAPI InitGetExtensionsStringARB (HDC hdc) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetExtensionsStringARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetExtensionsStringARB = extproc; + + return wglGetExtensionsStringARB(hdc); +} + +static BOOL WINAPI InitGetPixelFormatAttribivARB (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetPixelFormatAttribivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetPixelFormatAttribivARB = extproc; + + return wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues); +} + +static BOOL WINAPI InitGetPixelFormatAttribfvARB (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetPixelFormatAttribfvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetPixelFormatAttribfvARB = extproc; + + return wglGetPixelFormatAttribfvARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues); +} + +static BOOL WINAPI InitChoosePixelFormatARB (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglChoosePixelFormatARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglChoosePixelFormatARB = extproc; + + return wglChoosePixelFormatARB(hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats); +} + +static BOOL WINAPI InitMakeContextCurrentARB (HDC hDrawDC, HDC hReadDC, HGLRC hglrc) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglMakeContextCurrentARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglMakeContextCurrentARB = extproc; + + return wglMakeContextCurrentARB(hDrawDC, hReadDC, hglrc); +} + +static HDC WINAPI InitGetCurrentReadDCARB (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetCurrentReadDCARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetCurrentReadDCARB = extproc; + + return wglGetCurrentReadDCARB(); +} + +static HPBUFFERARB WINAPI InitCreatePbufferARB (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglCreatePbufferARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglCreatePbufferARB = extproc; + + return wglCreatePbufferARB(hDC, iPixelFormat, iWidth, iHeight, piAttribList); +} + +static HDC WINAPI InitGetPbufferDCARB (HPBUFFERARB hPbuffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetPbufferDCARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetPbufferDCARB = extproc; + + return wglGetPbufferDCARB(hPbuffer); +} + +static int WINAPI InitReleasePbufferDCARB (HPBUFFERARB hPbuffer, HDC hDC) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglReleasePbufferDCARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglReleasePbufferDCARB = extproc; + + return wglReleasePbufferDCARB(hPbuffer, hDC); +} + +static BOOL WINAPI InitDestroyPbufferARB (HPBUFFERARB hPbuffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglDestroyPbufferARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglDestroyPbufferARB = extproc; + + return wglDestroyPbufferARB(hPbuffer); +} + +static BOOL WINAPI InitQueryPbufferARB (HPBUFFERARB hPbuffer, int iAttribute, int *piValue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglQueryPbufferARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglQueryPbufferARB = extproc; + + return wglQueryPbufferARB(hPbuffer, iAttribute, piValue); +} + +static BOOL WINAPI InitBindTexImageARB (HPBUFFERARB hPbuffer, int iBuffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglBindTexImageARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglBindTexImageARB = extproc; + + return wglBindTexImageARB(hPbuffer, iBuffer); +} + +static BOOL WINAPI InitReleaseTexImageARB (HPBUFFERARB hPbuffer, int iBuffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglReleaseTexImageARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglReleaseTexImageARB = extproc; + + return wglReleaseTexImageARB(hPbuffer, iBuffer); +} + +static BOOL WINAPI InitSetPbufferAttribARB (HPBUFFERARB hPbuffer, const int *piAttribList) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglSetPbufferAttribARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglSetPbufferAttribARB = extproc; + + return wglSetPbufferAttribARB(hPbuffer, piAttribList); +} + +static GLboolean WINAPI InitCreateDisplayColorTableEXT (GLushort id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglCreateDisplayColorTableEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglCreateDisplayColorTableEXT = extproc; + + return wglCreateDisplayColorTableEXT(id); +} + +static GLboolean WINAPI InitLoadDisplayColorTableEXT (const GLushort *table, GLuint length) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglLoadDisplayColorTableEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglLoadDisplayColorTableEXT = extproc; + + return wglLoadDisplayColorTableEXT(table, length); +} + +static GLboolean WINAPI InitBindDisplayColorTableEXT (GLushort id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglBindDisplayColorTableEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglBindDisplayColorTableEXT = extproc; + + return wglBindDisplayColorTableEXT(id); +} + +static VOID WINAPI InitDestroyDisplayColorTableEXT (GLushort id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglDestroyDisplayColorTableEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + wglDestroyDisplayColorTableEXT = extproc; + + wglDestroyDisplayColorTableEXT(id); +} + +static const WINAPI InitGetExtensionsStringEXT (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetExtensionsStringEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetExtensionsStringEXT = extproc; + + return wglGetExtensionsStringEXT(); +} + +static BOOL WINAPI InitMakeContextCurrentEXT (HDC hDrawDC, HDC hReadDC, HGLRC hglrc) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglMakeContextCurrentEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglMakeContextCurrentEXT = extproc; + + return wglMakeContextCurrentEXT(hDrawDC, hReadDC, hglrc); +} + +static HDC WINAPI InitGetCurrentReadDCEXT (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetCurrentReadDCEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetCurrentReadDCEXT = extproc; + + return wglGetCurrentReadDCEXT(); +} + +static HPBUFFEREXT WINAPI InitCreatePbufferEXT (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglCreatePbufferEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglCreatePbufferEXT = extproc; + + return wglCreatePbufferEXT(hDC, iPixelFormat, iWidth, iHeight, piAttribList); +} + +static HDC WINAPI InitGetPbufferDCEXT (HPBUFFEREXT hPbuffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetPbufferDCEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetPbufferDCEXT = extproc; + + return wglGetPbufferDCEXT(hPbuffer); +} + +static int WINAPI InitReleasePbufferDCEXT (HPBUFFEREXT hPbuffer, HDC hDC) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglReleasePbufferDCEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglReleasePbufferDCEXT = extproc; + + return wglReleasePbufferDCEXT(hPbuffer, hDC); +} + +static BOOL WINAPI InitDestroyPbufferEXT (HPBUFFEREXT hPbuffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglDestroyPbufferEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglDestroyPbufferEXT = extproc; + + return wglDestroyPbufferEXT(hPbuffer); +} + +static BOOL WINAPI InitQueryPbufferEXT (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglQueryPbufferEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglQueryPbufferEXT = extproc; + + return wglQueryPbufferEXT(hPbuffer, iAttribute, piValue); +} + +static BOOL WINAPI InitGetPixelFormatAttribivEXT (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetPixelFormatAttribivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetPixelFormatAttribivEXT = extproc; + + return wglGetPixelFormatAttribivEXT(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues); +} + +static BOOL WINAPI InitGetPixelFormatAttribfvEXT (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetPixelFormatAttribfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetPixelFormatAttribfvEXT = extproc; + + return wglGetPixelFormatAttribfvEXT(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues); +} + +static BOOL WINAPI InitChoosePixelFormatEXT (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglChoosePixelFormatEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglChoosePixelFormatEXT = extproc; + + return wglChoosePixelFormatEXT(hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats); +} + +static BOOL WINAPI InitSwapIntervalEXT (int interval) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglSwapIntervalEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglSwapIntervalEXT = extproc; + + return wglSwapIntervalEXT(interval); +} + +static int WINAPI InitGetSwapIntervalEXT (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetSwapIntervalEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetSwapIntervalEXT = extproc; + + return wglGetSwapIntervalEXT(); +} + +static void* WINAPI InitAllocateMemoryNV (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglAllocateMemoryNV"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglAllocateMemoryNV = extproc; + + return wglAllocateMemoryNV(size, readfreq, writefreq, priority); +} + +static void WINAPI InitFreeMemoryNV (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglFreeMemoryNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + wglFreeMemoryNV = extproc; + + wglFreeMemoryNV(); +} + +static BOOL WINAPI InitGetSyncValuesOML (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetSyncValuesOML"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetSyncValuesOML = extproc; + + return wglGetSyncValuesOML(hdc, ust, msc, sbc); +} + +static BOOL WINAPI InitGetMscRateOML (HDC hdc, INT32 *numerator, INT32 *denominator) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetMscRateOML"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetMscRateOML = extproc; + + return wglGetMscRateOML(hdc, numerator, denominator); +} + +static INT64 WINAPI InitSwapBuffersMscOML (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglSwapBuffersMscOML"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglSwapBuffersMscOML = extproc; + + return wglSwapBuffersMscOML(hdc, target_msc, divisor, remainder); +} + +static INT64 WINAPI InitSwapLayerBuffersMscOML (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglSwapLayerBuffersMscOML"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglSwapLayerBuffersMscOML = extproc; + + return wglSwapLayerBuffersMscOML(hdc, fuPlanes, target_msc, divisor, remainder); +} + +static BOOL WINAPI InitWaitForMscOML (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglWaitForMscOML"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglWaitForMscOML = extproc; + + return wglWaitForMscOML(hdc, target_msc, divisor, remainder, ust, msc, sbc); +} + +static BOOL WINAPI InitWaitForSbcOML (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglWaitForSbcOML"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglWaitForSbcOML = extproc; + + return wglWaitForSbcOML(hdc, target_sbc, ust, msc, sbc); +} + +static BOOL WINAPI InitGetDigitalVideoParametersI3D (HDC hDC, int iAttribute, int *piValue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetDigitalVideoParametersI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetDigitalVideoParametersI3D = extproc; + + return wglGetDigitalVideoParametersI3D(hDC, iAttribute, piValue); +} + +static BOOL WINAPI InitSetDigitalVideoParametersI3D (HDC hDC, int iAttribute, const int *piValue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglSetDigitalVideoParametersI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglSetDigitalVideoParametersI3D = extproc; + + return wglSetDigitalVideoParametersI3D(hDC, iAttribute, piValue); +} + +static BOOL WINAPI InitGetGammaTableParametersI3D (HDC hDC, int iAttribute, int *piValue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetGammaTableParametersI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetGammaTableParametersI3D = extproc; + + return wglGetGammaTableParametersI3D(hDC, iAttribute, piValue); +} + +static BOOL WINAPI InitSetGammaTableParametersI3D (HDC hDC, int iAttribute, const int *piValue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglSetGammaTableParametersI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglSetGammaTableParametersI3D = extproc; + + return wglSetGammaTableParametersI3D(hDC, iAttribute, piValue); +} + +static BOOL WINAPI InitGetGammaTableI3D (HDC hDC, int iEntries, USHORT *puRed, USHORT *puGreen, USHORT *puBlue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetGammaTableI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetGammaTableI3D = extproc; + + return wglGetGammaTableI3D(hDC, iEntries, puRed, puGreen, puBlue); +} + +static BOOL WINAPI InitSetGammaTableI3D (HDC hDC, int iEntries, const USHORT *puRed, const USHORT *puGreen, const USHORT *puBlue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglSetGammaTableI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglSetGammaTableI3D = extproc; + + return wglSetGammaTableI3D(hDC, iEntries, puRed, puGreen, puBlue); +} + +static BOOL WINAPI InitEnableGenlockI3D (HDC hDC) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglEnableGenlockI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglEnableGenlockI3D = extproc; + + return wglEnableGenlockI3D(hDC); +} + +static BOOL WINAPI InitDisableGenlockI3D (HDC hDC) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglDisableGenlockI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglDisableGenlockI3D = extproc; + + return wglDisableGenlockI3D(hDC); +} + +static BOOL WINAPI InitIsEnabledGenlockI3D (HDC hDC, BOOL *pFlag) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglIsEnabledGenlockI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglIsEnabledGenlockI3D = extproc; + + return wglIsEnabledGenlockI3D(hDC, pFlag); +} + +static BOOL WINAPI InitGenlockSourceI3D (HDC hDC, UINT uSource) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGenlockSourceI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGenlockSourceI3D = extproc; + + return wglGenlockSourceI3D(hDC, uSource); +} + +static BOOL WINAPI InitGetGenlockSourceI3D (HDC hDC, UINT *uSource) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetGenlockSourceI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetGenlockSourceI3D = extproc; + + return wglGetGenlockSourceI3D(hDC, uSource); +} + +static BOOL WINAPI InitGenlockSourceEdgeI3D (HDC hDC, UINT uEdge) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGenlockSourceEdgeI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGenlockSourceEdgeI3D = extproc; + + return wglGenlockSourceEdgeI3D(hDC, uEdge); +} + +static BOOL WINAPI InitGetGenlockSourceEdgeI3D (HDC hDC, UINT *uEdge) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetGenlockSourceEdgeI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetGenlockSourceEdgeI3D = extproc; + + return wglGetGenlockSourceEdgeI3D(hDC, uEdge); +} + +static BOOL WINAPI InitGenlockSampleRateI3D (HDC hDC, UINT uRate) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGenlockSampleRateI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGenlockSampleRateI3D = extproc; + + return wglGenlockSampleRateI3D(hDC, uRate); +} + +static BOOL WINAPI InitGetGenlockSampleRateI3D (HDC hDC, UINT *uRate) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetGenlockSampleRateI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetGenlockSampleRateI3D = extproc; + + return wglGetGenlockSampleRateI3D(hDC, uRate); +} + +static BOOL WINAPI InitGenlockSourceDelayI3D (HDC hDC, UINT uDelay) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGenlockSourceDelayI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGenlockSourceDelayI3D = extproc; + + return wglGenlockSourceDelayI3D(hDC, uDelay); +} + +static BOOL WINAPI InitGetGenlockSourceDelayI3D (HDC hDC, UINT *uDelay) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetGenlockSourceDelayI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetGenlockSourceDelayI3D = extproc; + + return wglGetGenlockSourceDelayI3D(hDC, uDelay); +} + +static BOOL WINAPI InitQueryGenlockMaxSourceDelayI3D (HDC hDC, UINT *uMaxLineDelay, UINT *uMaxPixelDelay) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglQueryGenlockMaxSourceDelayI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglQueryGenlockMaxSourceDelayI3D = extproc; + + return wglQueryGenlockMaxSourceDelayI3D(hDC, uMaxLineDelay, uMaxPixelDelay); +} + +static LPVOID WINAPI InitCreateImageBufferI3D (HDC hDC, DWORD dwSize, UINT uFlags) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglCreateImageBufferI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglCreateImageBufferI3D = extproc; + + return wglCreateImageBufferI3D(hDC, dwSize, uFlags); +} + +static BOOL WINAPI InitDestroyImageBufferI3D (HDC hDC, LPVOID pAddress) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglDestroyImageBufferI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglDestroyImageBufferI3D = extproc; + + return wglDestroyImageBufferI3D(hDC, pAddress); +} + +static BOOL WINAPI InitAssociateImageBufferEventsI3D (HDC hDC, const HANDLE *pEvent, const LPVOID *pAddress, const DWORD *pSize, UINT count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglAssociateImageBufferEventsI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglAssociateImageBufferEventsI3D = extproc; + + return wglAssociateImageBufferEventsI3D(hDC, pEvent, pAddress, pSize, count); +} + +static BOOL WINAPI InitReleaseImageBufferEventsI3D (HDC hDC, const LPVOID *pAddress, UINT count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglReleaseImageBufferEventsI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglReleaseImageBufferEventsI3D = extproc; + + return wglReleaseImageBufferEventsI3D(hDC, pAddress, count); +} + +static BOOL WINAPI InitEnableFrameLockI3D (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglEnableFrameLockI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglEnableFrameLockI3D = extproc; + + return wglEnableFrameLockI3D(); +} + +static BOOL WINAPI InitDisableFrameLockI3D (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglDisableFrameLockI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglDisableFrameLockI3D = extproc; + + return wglDisableFrameLockI3D(); +} + +static BOOL WINAPI InitIsEnabledFrameLockI3D (BOOL *pFlag) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglIsEnabledFrameLockI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglIsEnabledFrameLockI3D = extproc; + + return wglIsEnabledFrameLockI3D(pFlag); +} + +static BOOL WINAPI InitQueryFrameLockMasterI3D (BOOL *pFlag) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglQueryFrameLockMasterI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglQueryFrameLockMasterI3D = extproc; + + return wglQueryFrameLockMasterI3D(pFlag); +} + +static BOOL WINAPI InitGetFrameUsageI3D (float *pUsage) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetFrameUsageI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetFrameUsageI3D = extproc; + + return wglGetFrameUsageI3D(pUsage); +} + +static BOOL WINAPI InitBeginFrameTrackingI3D (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglBeginFrameTrackingI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglBeginFrameTrackingI3D = extproc; + + return wglBeginFrameTrackingI3D(); +} + +static BOOL WINAPI InitEndFrameTrackingI3D (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglEndFrameTrackingI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglEndFrameTrackingI3D = extproc; + + return wglEndFrameTrackingI3D(); +} + +static BOOL WINAPI InitQueryFrameTrackingI3D (DWORD *pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglQueryFrameTrackingI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglQueryFrameTrackingI3D = extproc; + + return wglQueryFrameTrackingI3D(pFrameCount, pMissedFrames, pLastMissedUsage); +} + +#endif /* _WIN32 */ + +_GLextensionProcs _extensionProcs = { + InitBlendColor, + InitBlendEquation, + InitDrawRangeElements, + InitColorTable, + InitColorTableParameterfv, + InitColorTableParameteriv, + InitCopyColorTable, + InitGetColorTable, + InitGetColorTableParameterfv, + InitGetColorTableParameteriv, + InitColorSubTable, + InitCopyColorSubTable, + InitConvolutionFilter1D, + InitConvolutionFilter2D, + InitConvolutionParameterf, + InitConvolutionParameterfv, + InitConvolutionParameteri, + InitConvolutionParameteriv, + InitCopyConvolutionFilter1D, + InitCopyConvolutionFilter2D, + InitGetConvolutionFilter, + InitGetConvolutionParameterfv, + InitGetConvolutionParameteriv, + InitGetSeparableFilter, + InitSeparableFilter2D, + InitGetHistogram, + InitGetHistogramParameterfv, + InitGetHistogramParameteriv, + InitGetMinmax, + InitGetMinmaxParameterfv, + InitGetMinmaxParameteriv, + InitHistogram, + InitMinmax, + InitResetHistogram, + InitResetMinmax, + InitTexImage3D, + InitTexSubImage3D, + InitCopyTexSubImage3D, + InitActiveTexture, + InitClientActiveTexture, + InitMultiTexCoord1d, + InitMultiTexCoord1dv, + InitMultiTexCoord1f, + InitMultiTexCoord1fv, + InitMultiTexCoord1i, + InitMultiTexCoord1iv, + InitMultiTexCoord1s, + InitMultiTexCoord1sv, + InitMultiTexCoord2d, + InitMultiTexCoord2dv, + InitMultiTexCoord2f, + InitMultiTexCoord2fv, + InitMultiTexCoord2i, + InitMultiTexCoord2iv, + InitMultiTexCoord2s, + InitMultiTexCoord2sv, + InitMultiTexCoord3d, + InitMultiTexCoord3dv, + InitMultiTexCoord3f, + InitMultiTexCoord3fv, + InitMultiTexCoord3i, + InitMultiTexCoord3iv, + InitMultiTexCoord3s, + InitMultiTexCoord3sv, + InitMultiTexCoord4d, + InitMultiTexCoord4dv, + InitMultiTexCoord4f, + InitMultiTexCoord4fv, + InitMultiTexCoord4i, + InitMultiTexCoord4iv, + InitMultiTexCoord4s, + InitMultiTexCoord4sv, + InitLoadTransposeMatrixf, + InitLoadTransposeMatrixd, + InitMultTransposeMatrixf, + InitMultTransposeMatrixd, + InitSampleCoverage, + InitCompressedTexImage3D, + InitCompressedTexImage2D, + InitCompressedTexImage1D, + InitCompressedTexSubImage3D, + InitCompressedTexSubImage2D, + InitCompressedTexSubImage1D, + InitGetCompressedTexImage, + InitBlendFuncSeparate, + InitFogCoordf, + InitFogCoordfv, + InitFogCoordd, + InitFogCoorddv, + InitFogCoordPointer, + InitMultiDrawArrays, + InitMultiDrawElements, + InitPointParameterf, + InitPointParameterfv, + InitPointParameteri, + InitPointParameteriv, + InitSecondaryColor3b, + InitSecondaryColor3bv, + InitSecondaryColor3d, + InitSecondaryColor3dv, + InitSecondaryColor3f, + InitSecondaryColor3fv, + InitSecondaryColor3i, + InitSecondaryColor3iv, + InitSecondaryColor3s, + InitSecondaryColor3sv, + InitSecondaryColor3ub, + InitSecondaryColor3ubv, + InitSecondaryColor3ui, + InitSecondaryColor3uiv, + InitSecondaryColor3us, + InitSecondaryColor3usv, + InitSecondaryColorPointer, + InitWindowPos2d, + InitWindowPos2dv, + InitWindowPos2f, + InitWindowPos2fv, + InitWindowPos2i, + InitWindowPos2iv, + InitWindowPos2s, + InitWindowPos2sv, + InitWindowPos3d, + InitWindowPos3dv, + InitWindowPos3f, + InitWindowPos3fv, + InitWindowPos3i, + InitWindowPos3iv, + InitWindowPos3s, + InitWindowPos3sv, + InitGenQueries, + InitDeleteQueries, + InitIsQuery, + InitBeginQuery, + InitEndQuery, + InitGetQueryiv, + InitGetQueryObjectiv, + InitGetQueryObjectuiv, + InitBindBuffer, + InitDeleteBuffers, + InitGenBuffers, + InitIsBuffer, + InitBufferData, + InitBufferSubData, + InitGetBufferSubData, + InitMapBuffer, + InitUnmapBuffer, + InitGetBufferParameteriv, + InitGetBufferPointerv, + InitActiveTextureARB, + InitClientActiveTextureARB, + InitMultiTexCoord1dARB, + InitMultiTexCoord1dvARB, + InitMultiTexCoord1fARB, + InitMultiTexCoord1fvARB, + InitMultiTexCoord1iARB, + InitMultiTexCoord1ivARB, + InitMultiTexCoord1sARB, + InitMultiTexCoord1svARB, + InitMultiTexCoord2dARB, + InitMultiTexCoord2dvARB, + InitMultiTexCoord2fARB, + InitMultiTexCoord2fvARB, + InitMultiTexCoord2iARB, + InitMultiTexCoord2ivARB, + InitMultiTexCoord2sARB, + InitMultiTexCoord2svARB, + InitMultiTexCoord3dARB, + InitMultiTexCoord3dvARB, + InitMultiTexCoord3fARB, + InitMultiTexCoord3fvARB, + InitMultiTexCoord3iARB, + InitMultiTexCoord3ivARB, + InitMultiTexCoord3sARB, + InitMultiTexCoord3svARB, + InitMultiTexCoord4dARB, + InitMultiTexCoord4dvARB, + InitMultiTexCoord4fARB, + InitMultiTexCoord4fvARB, + InitMultiTexCoord4iARB, + InitMultiTexCoord4ivARB, + InitMultiTexCoord4sARB, + InitMultiTexCoord4svARB, + InitLoadTransposeMatrixfARB, + InitLoadTransposeMatrixdARB, + InitMultTransposeMatrixfARB, + InitMultTransposeMatrixdARB, + InitSampleCoverageARB, + InitCompressedTexImage3DARB, + InitCompressedTexImage2DARB, + InitCompressedTexImage1DARB, + InitCompressedTexSubImage3DARB, + InitCompressedTexSubImage2DARB, + InitCompressedTexSubImage1DARB, + InitGetCompressedTexImageARB, + InitPointParameterfARB, + InitPointParameterfvARB, + InitWeightbvARB, + InitWeightsvARB, + InitWeightivARB, + InitWeightfvARB, + InitWeightdvARB, + InitWeightubvARB, + InitWeightusvARB, + InitWeightuivARB, + InitWeightPointerARB, + InitVertexBlendARB, + InitCurrentPaletteMatrixARB, + InitMatrixIndexubvARB, + InitMatrixIndexusvARB, + InitMatrixIndexuivARB, + InitMatrixIndexPointerARB, + InitWindowPos2dARB, + InitWindowPos2dvARB, + InitWindowPos2fARB, + InitWindowPos2fvARB, + InitWindowPos2iARB, + InitWindowPos2ivARB, + InitWindowPos2sARB, + InitWindowPos2svARB, + InitWindowPos3dARB, + InitWindowPos3dvARB, + InitWindowPos3fARB, + InitWindowPos3fvARB, + InitWindowPos3iARB, + InitWindowPos3ivARB, + InitWindowPos3sARB, + InitWindowPos3svARB, + InitVertexAttrib1dARB, + InitVertexAttrib1dvARB, + InitVertexAttrib1fARB, + InitVertexAttrib1fvARB, + InitVertexAttrib1sARB, + InitVertexAttrib1svARB, + InitVertexAttrib2dARB, + InitVertexAttrib2dvARB, + InitVertexAttrib2fARB, + InitVertexAttrib2fvARB, + InitVertexAttrib2sARB, + InitVertexAttrib2svARB, + InitVertexAttrib3dARB, + InitVertexAttrib3dvARB, + InitVertexAttrib3fARB, + InitVertexAttrib3fvARB, + InitVertexAttrib3sARB, + InitVertexAttrib3svARB, + InitVertexAttrib4NbvARB, + InitVertexAttrib4NivARB, + InitVertexAttrib4NsvARB, + InitVertexAttrib4NubARB, + InitVertexAttrib4NubvARB, + InitVertexAttrib4NuivARB, + InitVertexAttrib4NusvARB, + InitVertexAttrib4bvARB, + InitVertexAttrib4dARB, + InitVertexAttrib4dvARB, + InitVertexAttrib4fARB, + InitVertexAttrib4fvARB, + InitVertexAttrib4ivARB, + InitVertexAttrib4sARB, + InitVertexAttrib4svARB, + InitVertexAttrib4ubvARB, + InitVertexAttrib4uivARB, + InitVertexAttrib4usvARB, + InitVertexAttribPointerARB, + InitEnableVertexAttribArrayARB, + InitDisableVertexAttribArrayARB, + InitProgramStringARB, + InitBindProgramARB, + InitDeleteProgramsARB, + InitGenProgramsARB, + InitProgramEnvParameter4dARB, + InitProgramEnvParameter4dvARB, + InitProgramEnvParameter4fARB, + InitProgramEnvParameter4fvARB, + InitProgramLocalParameter4dARB, + InitProgramLocalParameter4dvARB, + InitProgramLocalParameter4fARB, + InitProgramLocalParameter4fvARB, + InitGetProgramEnvParameterdvARB, + InitGetProgramEnvParameterfvARB, + InitGetProgramLocalParameterdvARB, + InitGetProgramLocalParameterfvARB, + InitGetProgramivARB, + InitGetProgramStringARB, + InitGetVertexAttribdvARB, + InitGetVertexAttribfvARB, + InitGetVertexAttribivARB, + InitGetVertexAttribPointervARB, + InitIsProgramARB, + InitBindBufferARB, + InitDeleteBuffersARB, + InitGenBuffersARB, + InitIsBufferARB, + InitBufferDataARB, + InitBufferSubDataARB, + InitGetBufferSubDataARB, + InitMapBufferARB, + InitUnmapBufferARB, + InitGetBufferParameterivARB, + InitGetBufferPointervARB, + InitGenQueriesARB, + InitDeleteQueriesARB, + InitIsQueryARB, + InitBeginQueryARB, + InitEndQueryARB, + InitGetQueryivARB, + InitGetQueryObjectivARB, + InitGetQueryObjectuivARB, + InitDeleteObjectARB, + InitGetHandleARB, + InitDetachObjectARB, + InitCreateShaderObjectARB, + InitShaderSourceARB, + InitCompileShaderARB, + InitCreateProgramObjectARB, + InitAttachObjectARB, + InitLinkProgramARB, + InitUseProgramObjectARB, + InitValidateProgramARB, + InitUniform1fARB, + InitUniform2fARB, + InitUniform3fARB, + InitUniform4fARB, + InitUniform1iARB, + InitUniform2iARB, + InitUniform3iARB, + InitUniform4iARB, + InitUniform1fvARB, + InitUniform2fvARB, + InitUniform3fvARB, + InitUniform4fvARB, + InitUniform1ivARB, + InitUniform2ivARB, + InitUniform3ivARB, + InitUniform4ivARB, + InitUniformMatrix2fvARB, + InitUniformMatrix3fvARB, + InitUniformMatrix4fvARB, + InitGetObjectParameterfvARB, + InitGetObjectParameterivARB, + InitGetInfoLogARB, + InitGetAttachedObjectsARB, + InitGetUniformLocationARB, + InitGetActiveUniformARB, + InitGetUniformfvARB, + InitGetUniformivARB, + InitGetShaderSourceARB, + InitBindAttribLocationARB, + InitGetActiveAttribARB, + InitGetAttribLocationARB, + InitBlendColorEXT, + InitPolygonOffsetEXT, + InitTexImage3DEXT, + InitTexSubImage3DEXT, + InitGetTexFilterFuncSGIS, + InitTexFilterFuncSGIS, + InitTexSubImage1DEXT, + InitTexSubImage2DEXT, + InitCopyTexImage1DEXT, + InitCopyTexImage2DEXT, + InitCopyTexSubImage1DEXT, + InitCopyTexSubImage2DEXT, + InitCopyTexSubImage3DEXT, + InitGetHistogramEXT, + InitGetHistogramParameterfvEXT, + InitGetHistogramParameterivEXT, + InitGetMinmaxEXT, + InitGetMinmaxParameterfvEXT, + InitGetMinmaxParameterivEXT, + InitHistogramEXT, + InitMinmaxEXT, + InitResetHistogramEXT, + InitResetMinmaxEXT, + InitConvolutionFilter1DEXT, + InitConvolutionFilter2DEXT, + InitConvolutionParameterfEXT, + InitConvolutionParameterfvEXT, + InitConvolutionParameteriEXT, + InitConvolutionParameterivEXT, + InitCopyConvolutionFilter1DEXT, + InitCopyConvolutionFilter2DEXT, + InitGetConvolutionFilterEXT, + InitGetConvolutionParameterfvEXT, + InitGetConvolutionParameterivEXT, + InitGetSeparableFilterEXT, + InitSeparableFilter2DEXT, + InitColorTableSGI, + InitColorTableParameterfvSGI, + InitColorTableParameterivSGI, + InitCopyColorTableSGI, + InitGetColorTableSGI, + InitGetColorTableParameterfvSGI, + InitGetColorTableParameterivSGI, + InitPixelTexGenSGIX, + InitPixelTexGenParameteriSGIS, + InitPixelTexGenParameterivSGIS, + InitPixelTexGenParameterfSGIS, + InitPixelTexGenParameterfvSGIS, + InitGetPixelTexGenParameterivSGIS, + InitGetPixelTexGenParameterfvSGIS, + InitTexImage4DSGIS, + InitTexSubImage4DSGIS, + InitAreTexturesResidentEXT, + InitBindTextureEXT, + InitDeleteTexturesEXT, + InitGenTexturesEXT, + InitIsTextureEXT, + InitPrioritizeTexturesEXT, + InitDetailTexFuncSGIS, + InitGetDetailTexFuncSGIS, + InitSharpenTexFuncSGIS, + InitGetSharpenTexFuncSGIS, + InitSampleMaskSGIS, + InitSamplePatternSGIS, + InitArrayElementEXT, + InitColorPointerEXT, + InitDrawArraysEXT, + InitEdgeFlagPointerEXT, + InitGetPointervEXT, + InitIndexPointerEXT, + InitNormalPointerEXT, + InitTexCoordPointerEXT, + InitVertexPointerEXT, + InitBlendEquationEXT, + InitSpriteParameterfSGIX, + InitSpriteParameterfvSGIX, + InitSpriteParameteriSGIX, + InitSpriteParameterivSGIX, + InitPointParameterfEXT, + InitPointParameterfvEXT, + InitPointParameterfSGIS, + InitPointParameterfvSGIS, + InitGetInstrumentsSGIX, + InitInstrumentsBufferSGIX, + InitPollInstrumentsSGIX, + InitReadInstrumentsSGIX, + InitStartInstrumentsSGIX, + InitStopInstrumentsSGIX, + InitFrameZoomSGIX, + InitTagSampleBufferSGIX, + InitDeformationMap3dSGIX, + InitDeformationMap3fSGIX, + InitDeformSGIX, + InitLoadIdentityDeformationMapSGIX, + InitReferencePlaneSGIX, + InitFlushRasterSGIX, + InitFogFuncSGIS, + InitGetFogFuncSGIS, + InitImageTransformParameteriHP, + InitImageTransformParameterfHP, + InitImageTransformParameterivHP, + InitImageTransformParameterfvHP, + InitGetImageTransformParameterivHP, + InitGetImageTransformParameterfvHP, + InitColorSubTableEXT, + InitCopyColorSubTableEXT, + InitHintPGI, + InitColorTableEXT, + InitGetColorTableEXT, + InitGetColorTableParameterivEXT, + InitGetColorTableParameterfvEXT, + InitGetListParameterfvSGIX, + InitGetListParameterivSGIX, + InitListParameterfSGIX, + InitListParameterfvSGIX, + InitListParameteriSGIX, + InitListParameterivSGIX, + InitIndexMaterialEXT, + InitIndexFuncEXT, + InitLockArraysEXT, + InitUnlockArraysEXT, + InitCullParameterdvEXT, + InitCullParameterfvEXT, + InitFragmentColorMaterialSGIX, + InitFragmentLightfSGIX, + InitFragmentLightfvSGIX, + InitFragmentLightiSGIX, + InitFragmentLightivSGIX, + InitFragmentLightModelfSGIX, + InitFragmentLightModelfvSGIX, + InitFragmentLightModeliSGIX, + InitFragmentLightModelivSGIX, + InitFragmentMaterialfSGIX, + InitFragmentMaterialfvSGIX, + InitFragmentMaterialiSGIX, + InitFragmentMaterialivSGIX, + InitGetFragmentLightfvSGIX, + InitGetFragmentLightivSGIX, + InitGetFragmentMaterialfvSGIX, + InitGetFragmentMaterialivSGIX, + InitLightEnviSGIX, + InitDrawRangeElementsEXT, + InitApplyTextureEXT, + InitTextureLightEXT, + InitTextureMaterialEXT, + InitAsyncMarkerSGIX, + InitFinishAsyncSGIX, + InitPollAsyncSGIX, + InitGenAsyncMarkersSGIX, + InitDeleteAsyncMarkersSGIX, + InitIsAsyncMarkerSGIX, + InitVertexPointervINTEL, + InitNormalPointervINTEL, + InitColorPointervINTEL, + InitTexCoordPointervINTEL, + InitPixelTransformParameteriEXT, + InitPixelTransformParameterfEXT, + InitPixelTransformParameterivEXT, + InitPixelTransformParameterfvEXT, + InitSecondaryColor3bEXT, + InitSecondaryColor3bvEXT, + InitSecondaryColor3dEXT, + InitSecondaryColor3dvEXT, + InitSecondaryColor3fEXT, + InitSecondaryColor3fvEXT, + InitSecondaryColor3iEXT, + InitSecondaryColor3ivEXT, + InitSecondaryColor3sEXT, + InitSecondaryColor3svEXT, + InitSecondaryColor3ubEXT, + InitSecondaryColor3ubvEXT, + InitSecondaryColor3uiEXT, + InitSecondaryColor3uivEXT, + InitSecondaryColor3usEXT, + InitSecondaryColor3usvEXT, + InitSecondaryColorPointerEXT, + InitTextureNormalEXT, + InitMultiDrawArraysEXT, + InitMultiDrawElementsEXT, + InitFogCoordfEXT, + InitFogCoordfvEXT, + InitFogCoorddEXT, + InitFogCoorddvEXT, + InitFogCoordPointerEXT, + InitTangent3bEXT, + InitTangent3bvEXT, + InitTangent3dEXT, + InitTangent3dvEXT, + InitTangent3fEXT, + InitTangent3fvEXT, + InitTangent3iEXT, + InitTangent3ivEXT, + InitTangent3sEXT, + InitTangent3svEXT, + InitBinormal3bEXT, + InitBinormal3bvEXT, + InitBinormal3dEXT, + InitBinormal3dvEXT, + InitBinormal3fEXT, + InitBinormal3fvEXT, + InitBinormal3iEXT, + InitBinormal3ivEXT, + InitBinormal3sEXT, + InitBinormal3svEXT, + InitTangentPointerEXT, + InitBinormalPointerEXT, + InitFinishTextureSUNX, + InitGlobalAlphaFactorbSUN, + InitGlobalAlphaFactorsSUN, + InitGlobalAlphaFactoriSUN, + InitGlobalAlphaFactorfSUN, + InitGlobalAlphaFactordSUN, + InitGlobalAlphaFactorubSUN, + InitGlobalAlphaFactorusSUN, + InitGlobalAlphaFactoruiSUN, + InitReplacementCodeuiSUN, + InitReplacementCodeusSUN, + InitReplacementCodeubSUN, + InitReplacementCodeuivSUN, + InitReplacementCodeusvSUN, + InitReplacementCodeubvSUN, + InitReplacementCodePointerSUN, + InitColor4ubVertex2fSUN, + InitColor4ubVertex2fvSUN, + InitColor4ubVertex3fSUN, + InitColor4ubVertex3fvSUN, + InitColor3fVertex3fSUN, + InitColor3fVertex3fvSUN, + InitNormal3fVertex3fSUN, + InitNormal3fVertex3fvSUN, + InitColor4fNormal3fVertex3fSUN, + InitColor4fNormal3fVertex3fvSUN, + InitTexCoord2fVertex3fSUN, + InitTexCoord2fVertex3fvSUN, + InitTexCoord4fVertex4fSUN, + InitTexCoord4fVertex4fvSUN, + InitTexCoord2fColor4ubVertex3fSUN, + InitTexCoord2fColor4ubVertex3fvSUN, + InitTexCoord2fColor3fVertex3fSUN, + InitTexCoord2fColor3fVertex3fvSUN, + InitTexCoord2fNormal3fVertex3fSUN, + InitTexCoord2fNormal3fVertex3fvSUN, + InitTexCoord2fColor4fNormal3fVertex3fSUN, + InitTexCoord2fColor4fNormal3fVertex3fvSUN, + InitTexCoord4fColor4fNormal3fVertex4fSUN, + InitTexCoord4fColor4fNormal3fVertex4fvSUN, + InitReplacementCodeuiVertex3fSUN, + InitReplacementCodeuiVertex3fvSUN, + InitReplacementCodeuiColor4ubVertex3fSUN, + InitReplacementCodeuiColor4ubVertex3fvSUN, + InitReplacementCodeuiColor3fVertex3fSUN, + InitReplacementCodeuiColor3fVertex3fvSUN, + InitReplacementCodeuiNormal3fVertex3fSUN, + InitReplacementCodeuiNormal3fVertex3fvSUN, + InitReplacementCodeuiColor4fNormal3fVertex3fSUN, + InitReplacementCodeuiColor4fNormal3fVertex3fvSUN, + InitReplacementCodeuiTexCoord2fVertex3fSUN, + InitReplacementCodeuiTexCoord2fVertex3fvSUN, + InitReplacementCodeuiTexCoord2fNormal3fVertex3fSUN, + InitReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN, + InitReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN, + InitReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN, + InitBlendFuncSeparateEXT, + InitBlendFuncSeparateINGR, + InitVertexWeightfEXT, + InitVertexWeightfvEXT, + InitVertexWeightPointerEXT, + InitFlushVertexArrayRangeNV, + InitVertexArrayRangeNV, + InitCombinerParameterfvNV, + InitCombinerParameterfNV, + InitCombinerParameterivNV, + InitCombinerParameteriNV, + InitCombinerInputNV, + InitCombinerOutputNV, + InitFinalCombinerInputNV, + InitGetCombinerInputParameterfvNV, + InitGetCombinerInputParameterivNV, + InitGetCombinerOutputParameterfvNV, + InitGetCombinerOutputParameterivNV, + InitGetFinalCombinerInputParameterfvNV, + InitGetFinalCombinerInputParameterivNV, + InitResizeBuffersMESA, + InitWindowPos2dMESA, + InitWindowPos2dvMESA, + InitWindowPos2fMESA, + InitWindowPos2fvMESA, + InitWindowPos2iMESA, + InitWindowPos2ivMESA, + InitWindowPos2sMESA, + InitWindowPos2svMESA, + InitWindowPos3dMESA, + InitWindowPos3dvMESA, + InitWindowPos3fMESA, + InitWindowPos3fvMESA, + InitWindowPos3iMESA, + InitWindowPos3ivMESA, + InitWindowPos3sMESA, + InitWindowPos3svMESA, + InitWindowPos4dMESA, + InitWindowPos4dvMESA, + InitWindowPos4fMESA, + InitWindowPos4fvMESA, + InitWindowPos4iMESA, + InitWindowPos4ivMESA, + InitWindowPos4sMESA, + InitWindowPos4svMESA, + InitMultiModeDrawArraysIBM, + InitMultiModeDrawElementsIBM, + InitColorPointerListIBM, + InitSecondaryColorPointerListIBM, + InitEdgeFlagPointerListIBM, + InitFogCoordPointerListIBM, + InitIndexPointerListIBM, + InitNormalPointerListIBM, + InitTexCoordPointerListIBM, + InitVertexPointerListIBM, + InitTbufferMask3DFX, + InitSampleMaskEXT, + InitSamplePatternEXT, + InitTextureColorMaskSGIS, + InitIglooInterfaceSGIX, + InitDeleteFencesNV, + InitGenFencesNV, + InitIsFenceNV, + InitTestFenceNV, + InitGetFenceivNV, + InitFinishFenceNV, + InitSetFenceNV, + InitMapControlPointsNV, + InitMapParameterivNV, + InitMapParameterfvNV, + InitGetMapControlPointsNV, + InitGetMapParameterivNV, + InitGetMapParameterfvNV, + InitGetMapAttribParameterivNV, + InitGetMapAttribParameterfvNV, + InitEvalMapsNV, + InitCombinerStageParameterfvNV, + InitGetCombinerStageParameterfvNV, + InitAreProgramsResidentNV, + InitBindProgramNV, + InitDeleteProgramsNV, + InitExecuteProgramNV, + InitGenProgramsNV, + InitGetProgramParameterdvNV, + InitGetProgramParameterfvNV, + InitGetProgramivNV, + InitGetProgramStringNV, + InitGetTrackMatrixivNV, + InitGetVertexAttribdvNV, + InitGetVertexAttribfvNV, + InitGetVertexAttribivNV, + InitGetVertexAttribPointervNV, + InitIsProgramNV, + InitLoadProgramNV, + InitProgramParameter4dNV, + InitProgramParameter4dvNV, + InitProgramParameter4fNV, + InitProgramParameter4fvNV, + InitProgramParameters4dvNV, + InitProgramParameters4fvNV, + InitRequestResidentProgramsNV, + InitTrackMatrixNV, + InitVertexAttribPointerNV, + InitVertexAttrib1dNV, + InitVertexAttrib1dvNV, + InitVertexAttrib1fNV, + InitVertexAttrib1fvNV, + InitVertexAttrib1sNV, + InitVertexAttrib1svNV, + InitVertexAttrib2dNV, + InitVertexAttrib2dvNV, + InitVertexAttrib2fNV, + InitVertexAttrib2fvNV, + InitVertexAttrib2sNV, + InitVertexAttrib2svNV, + InitVertexAttrib3dNV, + InitVertexAttrib3dvNV, + InitVertexAttrib3fNV, + InitVertexAttrib3fvNV, + InitVertexAttrib3sNV, + InitVertexAttrib3svNV, + InitVertexAttrib4dNV, + InitVertexAttrib4dvNV, + InitVertexAttrib4fNV, + InitVertexAttrib4fvNV, + InitVertexAttrib4sNV, + InitVertexAttrib4svNV, + InitVertexAttrib4ubNV, + InitVertexAttrib4ubvNV, + InitVertexAttribs1dvNV, + InitVertexAttribs1fvNV, + InitVertexAttribs1svNV, + InitVertexAttribs2dvNV, + InitVertexAttribs2fvNV, + InitVertexAttribs2svNV, + InitVertexAttribs3dvNV, + InitVertexAttribs3fvNV, + InitVertexAttribs3svNV, + InitVertexAttribs4dvNV, + InitVertexAttribs4fvNV, + InitVertexAttribs4svNV, + InitVertexAttribs4ubvNV, + InitTexBumpParameterivATI, + InitTexBumpParameterfvATI, + InitGetTexBumpParameterivATI, + InitGetTexBumpParameterfvATI, + InitGenFragmentShadersATI, + InitBindFragmentShaderATI, + InitDeleteFragmentShaderATI, + InitBeginFragmentShaderATI, + InitEndFragmentShaderATI, + InitPassTexCoordATI, + InitSampleMapATI, + InitColorFragmentOp1ATI, + InitColorFragmentOp2ATI, + InitColorFragmentOp3ATI, + InitAlphaFragmentOp1ATI, + InitAlphaFragmentOp2ATI, + InitAlphaFragmentOp3ATI, + InitSetFragmentShaderConstantATI, + InitPNTrianglesiATI, + InitPNTrianglesfATI, + InitNewObjectBufferATI, + InitIsObjectBufferATI, + InitUpdateObjectBufferATI, + InitGetObjectBufferfvATI, + InitGetObjectBufferivATI, + InitFreeObjectBufferATI, + InitArrayObjectATI, + InitGetArrayObjectfvATI, + InitGetArrayObjectivATI, + InitVariantArrayObjectATI, + InitGetVariantArrayObjectfvATI, + InitGetVariantArrayObjectivATI, + InitBeginVertexShaderEXT, + InitEndVertexShaderEXT, + InitBindVertexShaderEXT, + InitGenVertexShadersEXT, + InitDeleteVertexShaderEXT, + InitShaderOp1EXT, + InitShaderOp2EXT, + InitShaderOp3EXT, + InitSwizzleEXT, + InitWriteMaskEXT, + InitInsertComponentEXT, + InitExtractComponentEXT, + InitGenSymbolsEXT, + InitSetInvariantEXT, + InitSetLocalConstantEXT, + InitVariantbvEXT, + InitVariantsvEXT, + InitVariantivEXT, + InitVariantfvEXT, + InitVariantdvEXT, + InitVariantubvEXT, + InitVariantusvEXT, + InitVariantuivEXT, + InitVariantPointerEXT, + InitEnableVariantClientStateEXT, + InitDisableVariantClientStateEXT, + InitBindLightParameterEXT, + InitBindMaterialParameterEXT, + InitBindTexGenParameterEXT, + InitBindTextureUnitParameterEXT, + InitBindParameterEXT, + InitIsVariantEnabledEXT, + InitGetVariantBooleanvEXT, + InitGetVariantIntegervEXT, + InitGetVariantFloatvEXT, + InitGetVariantPointervEXT, + InitGetInvariantBooleanvEXT, + InitGetInvariantIntegervEXT, + InitGetInvariantFloatvEXT, + InitGetLocalConstantBooleanvEXT, + InitGetLocalConstantIntegervEXT, + InitGetLocalConstantFloatvEXT, + InitVertexStream1sATI, + InitVertexStream1svATI, + InitVertexStream1iATI, + InitVertexStream1ivATI, + InitVertexStream1fATI, + InitVertexStream1fvATI, + InitVertexStream1dATI, + InitVertexStream1dvATI, + InitVertexStream2sATI, + InitVertexStream2svATI, + InitVertexStream2iATI, + InitVertexStream2ivATI, + InitVertexStream2fATI, + InitVertexStream2fvATI, + InitVertexStream2dATI, + InitVertexStream2dvATI, + InitVertexStream3sATI, + InitVertexStream3svATI, + InitVertexStream3iATI, + InitVertexStream3ivATI, + InitVertexStream3fATI, + InitVertexStream3fvATI, + InitVertexStream3dATI, + InitVertexStream3dvATI, + InitVertexStream4sATI, + InitVertexStream4svATI, + InitVertexStream4iATI, + InitVertexStream4ivATI, + InitVertexStream4fATI, + InitVertexStream4fvATI, + InitVertexStream4dATI, + InitVertexStream4dvATI, + InitNormalStream3bATI, + InitNormalStream3bvATI, + InitNormalStream3sATI, + InitNormalStream3svATI, + InitNormalStream3iATI, + InitNormalStream3ivATI, + InitNormalStream3fATI, + InitNormalStream3fvATI, + InitNormalStream3dATI, + InitNormalStream3dvATI, + InitClientActiveVertexStreamATI, + InitVertexBlendEnviATI, + InitVertexBlendEnvfATI, + InitElementPointerATI, + InitDrawElementArrayATI, + InitDrawRangeElementArrayATI, + InitDrawMeshArraysSUN, + InitGenOcclusionQueriesNV, + InitDeleteOcclusionQueriesNV, + InitIsOcclusionQueryNV, + InitBeginOcclusionQueryNV, + InitEndOcclusionQueryNV, + InitGetOcclusionQueryivNV, + InitGetOcclusionQueryuivNV, + InitPointParameteriNV, + InitPointParameterivNV, + InitActiveStencilFaceEXT, + InitElementPointerAPPLE, + InitDrawElementArrayAPPLE, + InitDrawRangeElementArrayAPPLE, + InitMultiDrawElementArrayAPPLE, + InitMultiDrawRangeElementArrayAPPLE, + InitGenFencesAPPLE, + InitDeleteFencesAPPLE, + InitSetFenceAPPLE, + InitIsFenceAPPLE, + InitTestFenceAPPLE, + InitFinishFenceAPPLE, + InitTestObjectAPPLE, + InitFinishObjectAPPLE, + InitBindVertexArrayAPPLE, + InitDeleteVertexArraysAPPLE, + InitGenVertexArraysAPPLE, + InitIsVertexArrayAPPLE, + InitVertexArrayRangeAPPLE, + InitFlushVertexArrayRangeAPPLE, + InitVertexArrayParameteriAPPLE, + InitDrawBuffersATI, + InitProgramNamedParameter4fNV, + InitProgramNamedParameter4dNV, + InitProgramNamedParameter4fvNV, + InitProgramNamedParameter4dvNV, + InitGetProgramNamedParameterfvNV, + InitGetProgramNamedParameterdvNV, + InitVertex2hNV, + InitVertex2hvNV, + InitVertex3hNV, + InitVertex3hvNV, + InitVertex4hNV, + InitVertex4hvNV, + InitNormal3hNV, + InitNormal3hvNV, + InitColor3hNV, + InitColor3hvNV, + InitColor4hNV, + InitColor4hvNV, + InitTexCoord1hNV, + InitTexCoord1hvNV, + InitTexCoord2hNV, + InitTexCoord2hvNV, + InitTexCoord3hNV, + InitTexCoord3hvNV, + InitTexCoord4hNV, + InitTexCoord4hvNV, + InitMultiTexCoord1hNV, + InitMultiTexCoord1hvNV, + InitMultiTexCoord2hNV, + InitMultiTexCoord2hvNV, + InitMultiTexCoord3hNV, + InitMultiTexCoord3hvNV, + InitMultiTexCoord4hNV, + InitMultiTexCoord4hvNV, + InitFogCoordhNV, + InitFogCoordhvNV, + InitSecondaryColor3hNV, + InitSecondaryColor3hvNV, + InitVertexWeighthNV, + InitVertexWeighthvNV, + InitVertexAttrib1hNV, + InitVertexAttrib1hvNV, + InitVertexAttrib2hNV, + InitVertexAttrib2hvNV, + InitVertexAttrib3hNV, + InitVertexAttrib3hvNV, + InitVertexAttrib4hNV, + InitVertexAttrib4hvNV, + InitVertexAttribs1hvNV, + InitVertexAttribs2hvNV, + InitVertexAttribs3hvNV, + InitVertexAttribs4hvNV, + InitPixelDataRangeNV, + InitFlushPixelDataRangeNV, + InitPrimitiveRestartNV, + InitPrimitiveRestartIndexNV, + InitMapObjectBufferATI, + InitUnmapObjectBufferATI, + InitStencilOpSeparateATI, + InitStencilFuncSeparateATI, + InitVertexAttribArrayObjectATI, + InitGetVertexAttribArrayObjectfvATI, + InitGetVertexAttribArrayObjectivATI, + InitDepthBoundsEXT, + InitBlendEquationSeparateEXT, + InitAddSwapHintRectWIN, +#ifdef _WIN32 + InitCreateBufferRegionARB, + InitDeleteBufferRegionARB, + InitSaveBufferRegionARB, + InitRestoreBufferRegionARB, + InitGetExtensionsStringARB, + InitGetPixelFormatAttribivARB, + InitGetPixelFormatAttribfvARB, + InitChoosePixelFormatARB, + InitMakeContextCurrentARB, + InitGetCurrentReadDCARB, + InitCreatePbufferARB, + InitGetPbufferDCARB, + InitReleasePbufferDCARB, + InitDestroyPbufferARB, + InitQueryPbufferARB, + InitBindTexImageARB, + InitReleaseTexImageARB, + InitSetPbufferAttribARB, + InitCreateDisplayColorTableEXT, + InitLoadDisplayColorTableEXT, + InitBindDisplayColorTableEXT, + InitDestroyDisplayColorTableEXT, + InitGetExtensionsStringEXT, + InitMakeContextCurrentEXT, + InitGetCurrentReadDCEXT, + InitCreatePbufferEXT, + InitGetPbufferDCEXT, + InitReleasePbufferDCEXT, + InitDestroyPbufferEXT, + InitQueryPbufferEXT, + InitGetPixelFormatAttribivEXT, + InitGetPixelFormatAttribfvEXT, + InitChoosePixelFormatEXT, + InitSwapIntervalEXT, + InitGetSwapIntervalEXT, + InitAllocateMemoryNV, + InitFreeMemoryNV, + InitGetSyncValuesOML, + InitGetMscRateOML, + InitSwapBuffersMscOML, + InitSwapLayerBuffersMscOML, + InitWaitForMscOML, + InitWaitForSbcOML, + InitGetDigitalVideoParametersI3D, + InitSetDigitalVideoParametersI3D, + InitGetGammaTableParametersI3D, + InitSetGammaTableParametersI3D, + InitGetGammaTableI3D, + InitSetGammaTableI3D, + InitEnableGenlockI3D, + InitDisableGenlockI3D, + InitIsEnabledGenlockI3D, + InitGenlockSourceI3D, + InitGetGenlockSourceI3D, + InitGenlockSourceEdgeI3D, + InitGetGenlockSourceEdgeI3D, + InitGenlockSampleRateI3D, + InitGetGenlockSampleRateI3D, + InitGenlockSourceDelayI3D, + InitGetGenlockSourceDelayI3D, + InitQueryGenlockMaxSourceDelayI3D, + InitCreateImageBufferI3D, + InitDestroyImageBufferI3D, + InitAssociateImageBufferEventsI3D, + InitReleaseImageBufferEventsI3D, + InitEnableFrameLockI3D, + InitDisableFrameLockI3D, + InitIsEnabledFrameLockI3D, + InitQueryFrameLockMasterI3D, + InitGetFrameUsageI3D, + InitBeginFrameTrackingI3D, + InitEndFrameTrackingI3D, + InitQueryFrameTrackingI3D, +#endif /* _WIN32 */ +}; diff --git a/plugins/zzogl-pg-cg/opengl/glprocs.h b/plugins/zzogl-pg-cg/opengl/glprocs.h new file mode 100644 index 000000000..467f6ea0e --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/glprocs.h @@ -0,0 +1,2217 @@ +#ifndef _GLPROCS_H_ +#define _GLPROCS_H_ + +/* +** GLprocs utility for getting function addresses for OpenGL(R) 1.2, +** OpenGL 1.3, OpenGL 1.4, OpenGL 1.5 and OpenGL extension functions. +** +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and associated documentation files (the "Software"), +** to deal in the Software without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Software, and to permit persons to whom the +** Software is furnished to do so, subject to the following conditions: +** +** The above copyright notice including the dates of first publication and +** either this permission notice or a reference to +** http://oss.sgi.com/projects/FreeB/ +** shall be included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +** WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +** OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +** SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. +** shall not be used in advertising or otherwise to promote the sale, use or +** other dealings in this Software without prior written authorization from +** Silicon Graphics, Inc. +** +** Additional Notice Provisions: This software was created using the +** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has +** not been independently verified as being compliant with the OpenGL(R) +** version 1.2.1 Specification. +** +** Initial version of glprocs.{c,h} contributed by Intel(R) Corporation. +*/ + +#ifdef _WIN32 + #include + #include +#else + #include +#endif + +#ifndef _WIN32 /* non-Windows environment */ + #ifndef APIENTRY + #define APIENTRY + #endif + #ifdef __GNUC__ + #define _inline __inline__ + #else + #define _inline + #endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Structure of all OpenGL {1.2, 1.3, 1.4, 1.5}, GL extension procs.*/ + +typedef struct { + void (APIENTRY *BlendColor) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + void (APIENTRY *BlendEquation) (GLenum mode); + void (APIENTRY *DrawRangeElements) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); + void (APIENTRY *ColorTable) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); + void (APIENTRY *ColorTableParameterfv) (GLenum target, GLenum pname, const GLfloat *params); + void (APIENTRY *ColorTableParameteriv) (GLenum target, GLenum pname, const GLint *params); + void (APIENTRY *CopyColorTable) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); + void (APIENTRY *GetColorTable) (GLenum target, GLenum format, GLenum type, GLvoid *table); + void (APIENTRY *GetColorTableParameterfv) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetColorTableParameteriv) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *ColorSubTable) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); + void (APIENTRY *CopyColorSubTable) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); + void (APIENTRY *ConvolutionFilter1D) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); + void (APIENTRY *ConvolutionFilter2D) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); + void (APIENTRY *ConvolutionParameterf) (GLenum target, GLenum pname, GLfloat params); + void (APIENTRY *ConvolutionParameterfv) (GLenum target, GLenum pname, const GLfloat *params); + void (APIENTRY *ConvolutionParameteri) (GLenum target, GLenum pname, GLint params); + void (APIENTRY *ConvolutionParameteriv) (GLenum target, GLenum pname, const GLint *params); + void (APIENTRY *CopyConvolutionFilter1D) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); + void (APIENTRY *CopyConvolutionFilter2D) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); + void (APIENTRY *GetConvolutionFilter) (GLenum target, GLenum format, GLenum type, GLvoid *image); + void (APIENTRY *GetConvolutionParameterfv) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetConvolutionParameteriv) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetSeparableFilter) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); + void (APIENTRY *SeparableFilter2D) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); + void (APIENTRY *GetHistogram) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); + void (APIENTRY *GetHistogramParameterfv) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetHistogramParameteriv) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetMinmax) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); + void (APIENTRY *GetMinmaxParameterfv) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetMinmaxParameteriv) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *Histogram) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); + void (APIENTRY *Minmax) (GLenum target, GLenum internalformat, GLboolean sink); + void (APIENTRY *ResetHistogram) (GLenum target); + void (APIENTRY *ResetMinmax) (GLenum target); + void (APIENTRY *TexImage3D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); + void (APIENTRY *TexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); + void (APIENTRY *CopyTexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); + void (APIENTRY *ActiveTexture) (GLenum texture); + void (APIENTRY *ClientActiveTexture) (GLenum texture); + void (APIENTRY *MultiTexCoord1d) (GLenum target, GLdouble s); + void (APIENTRY *MultiTexCoord1dv) (GLenum target, const GLdouble *v); + void (APIENTRY *MultiTexCoord1f) (GLenum target, GLfloat s); + void (APIENTRY *MultiTexCoord1fv) (GLenum target, const GLfloat *v); + void (APIENTRY *MultiTexCoord1i) (GLenum target, GLint s); + void (APIENTRY *MultiTexCoord1iv) (GLenum target, const GLint *v); + void (APIENTRY *MultiTexCoord1s) (GLenum target, GLshort s); + void (APIENTRY *MultiTexCoord1sv) (GLenum target, const GLshort *v); + void (APIENTRY *MultiTexCoord2d) (GLenum target, GLdouble s, GLdouble t); + void (APIENTRY *MultiTexCoord2dv) (GLenum target, const GLdouble *v); + void (APIENTRY *MultiTexCoord2f) (GLenum target, GLfloat s, GLfloat t); + void (APIENTRY *MultiTexCoord2fv) (GLenum target, const GLfloat *v); + void (APIENTRY *MultiTexCoord2i) (GLenum target, GLint s, GLint t); + void (APIENTRY *MultiTexCoord2iv) (GLenum target, const GLint *v); + void (APIENTRY *MultiTexCoord2s) (GLenum target, GLshort s, GLshort t); + void (APIENTRY *MultiTexCoord2sv) (GLenum target, const GLshort *v); + void (APIENTRY *MultiTexCoord3d) (GLenum target, GLdouble s, GLdouble t, GLdouble r); + void (APIENTRY *MultiTexCoord3dv) (GLenum target, const GLdouble *v); + void (APIENTRY *MultiTexCoord3f) (GLenum target, GLfloat s, GLfloat t, GLfloat r); + void (APIENTRY *MultiTexCoord3fv) (GLenum target, const GLfloat *v); + void (APIENTRY *MultiTexCoord3i) (GLenum target, GLint s, GLint t, GLint r); + void (APIENTRY *MultiTexCoord3iv) (GLenum target, const GLint *v); + void (APIENTRY *MultiTexCoord3s) (GLenum target, GLshort s, GLshort t, GLshort r); + void (APIENTRY *MultiTexCoord3sv) (GLenum target, const GLshort *v); + void (APIENTRY *MultiTexCoord4d) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); + void (APIENTRY *MultiTexCoord4dv) (GLenum target, const GLdouble *v); + void (APIENTRY *MultiTexCoord4f) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); + void (APIENTRY *MultiTexCoord4fv) (GLenum target, const GLfloat *v); + void (APIENTRY *MultiTexCoord4i) (GLenum target, GLint s, GLint t, GLint r, GLint q); + void (APIENTRY *MultiTexCoord4iv) (GLenum target, const GLint *v); + void (APIENTRY *MultiTexCoord4s) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); + void (APIENTRY *MultiTexCoord4sv) (GLenum target, const GLshort *v); + void (APIENTRY *LoadTransposeMatrixf) (const GLfloat *m); + void (APIENTRY *LoadTransposeMatrixd) (const GLdouble *m); + void (APIENTRY *MultTransposeMatrixf) (const GLfloat *m); + void (APIENTRY *MultTransposeMatrixd) (const GLdouble *m); + void (APIENTRY *SampleCoverage) (GLclampf value, GLboolean invert); + void (APIENTRY *CompressedTexImage3D) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexImage2D) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexImage1D) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexSubImage1D) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *GetCompressedTexImage) (GLenum target, GLint level, GLvoid *img); + void (APIENTRY *BlendFuncSeparate) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); + void (APIENTRY *FogCoordf) (GLfloat coord); + void (APIENTRY *FogCoordfv) (const GLfloat *coord); + void (APIENTRY *FogCoordd) (GLdouble coord); + void (APIENTRY *FogCoorddv) (const GLdouble *coord); + void (APIENTRY *FogCoordPointer) (GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *MultiDrawArrays) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); + void (APIENTRY *MultiDrawElements) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); + void (APIENTRY *PointParameterf) (GLenum pname, GLfloat param); + void (APIENTRY *PointParameterfv) (GLenum pname, const GLfloat *params); + void (APIENTRY *PointParameteri) (GLenum pname, GLint param); + void (APIENTRY *PointParameteriv) (GLenum pname, const GLint *params); + void (APIENTRY *SecondaryColor3b) (GLbyte red, GLbyte green, GLbyte blue); + void (APIENTRY *SecondaryColor3bv) (const GLbyte *v); + void (APIENTRY *SecondaryColor3d) (GLdouble red, GLdouble green, GLdouble blue); + void (APIENTRY *SecondaryColor3dv) (const GLdouble *v); + void (APIENTRY *SecondaryColor3f) (GLfloat red, GLfloat green, GLfloat blue); + void (APIENTRY *SecondaryColor3fv) (const GLfloat *v); + void (APIENTRY *SecondaryColor3i) (GLint red, GLint green, GLint blue); + void (APIENTRY *SecondaryColor3iv) (const GLint *v); + void (APIENTRY *SecondaryColor3s) (GLshort red, GLshort green, GLshort blue); + void (APIENTRY *SecondaryColor3sv) (const GLshort *v); + void (APIENTRY *SecondaryColor3ub) (GLubyte red, GLubyte green, GLubyte blue); + void (APIENTRY *SecondaryColor3ubv) (const GLubyte *v); + void (APIENTRY *SecondaryColor3ui) (GLuint red, GLuint green, GLuint blue); + void (APIENTRY *SecondaryColor3uiv) (const GLuint *v); + void (APIENTRY *SecondaryColor3us) (GLushort red, GLushort green, GLushort blue); + void (APIENTRY *SecondaryColor3usv) (const GLushort *v); + void (APIENTRY *SecondaryColorPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *WindowPos2d) (GLdouble x, GLdouble y); + void (APIENTRY *WindowPos2dv) (const GLdouble *v); + void (APIENTRY *WindowPos2f) (GLfloat x, GLfloat y); + void (APIENTRY *WindowPos2fv) (const GLfloat *v); + void (APIENTRY *WindowPos2i) (GLint x, GLint y); + void (APIENTRY *WindowPos2iv) (const GLint *v); + void (APIENTRY *WindowPos2s) (GLshort x, GLshort y); + void (APIENTRY *WindowPos2sv) (const GLshort *v); + void (APIENTRY *WindowPos3d) (GLdouble x, GLdouble y, GLdouble z); + void (APIENTRY *WindowPos3dv) (const GLdouble *v); + void (APIENTRY *WindowPos3f) (GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *WindowPos3fv) (const GLfloat *v); + void (APIENTRY *WindowPos3i) (GLint x, GLint y, GLint z); + void (APIENTRY *WindowPos3iv) (const GLint *v); + void (APIENTRY *WindowPos3s) (GLshort x, GLshort y, GLshort z); + void (APIENTRY *WindowPos3sv) (const GLshort *v); + void (APIENTRY *GenQueries) (GLsizei n, GLuint *ids); + void (APIENTRY *DeleteQueries) (GLsizei n, const GLuint *ids); + GLboolean (APIENTRY *IsQuery) (GLuint id); + void (APIENTRY *BeginQuery) (GLenum target, GLuint id); + void (APIENTRY *EndQuery) (GLenum target); + void (APIENTRY *GetQueryiv) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetQueryObjectiv) (GLuint id, GLenum pname, GLint *params); + void (APIENTRY *GetQueryObjectuiv) (GLuint id, GLenum pname, GLuint *params); + void (APIENTRY *BindBuffer) (GLenum target, GLuint buffer); + void (APIENTRY *DeleteBuffers) (GLsizei n, const GLuint *buffers); + void (APIENTRY *GenBuffers) (GLsizei n, GLuint *buffers); + GLboolean (APIENTRY *IsBuffer) (GLuint buffer); + void (APIENTRY *BufferData) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage); + void (APIENTRY *BufferSubData) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data); + void (APIENTRY *GetBufferSubData) (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data); + GLvoid* (APIENTRY *MapBuffer) (GLenum target, GLenum access); + GLboolean (APIENTRY *UnmapBuffer) (GLenum target); + void (APIENTRY *GetBufferParameteriv) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetBufferPointerv) (GLenum target, GLenum pname, GLvoid* *params); + void (APIENTRY *ActiveTextureARB) (GLenum texture); + void (APIENTRY *ClientActiveTextureARB) (GLenum texture); + void (APIENTRY *MultiTexCoord1dARB) (GLenum target, GLdouble s); + void (APIENTRY *MultiTexCoord1dvARB) (GLenum target, const GLdouble *v); + void (APIENTRY *MultiTexCoord1fARB) (GLenum target, GLfloat s); + void (APIENTRY *MultiTexCoord1fvARB) (GLenum target, const GLfloat *v); + void (APIENTRY *MultiTexCoord1iARB) (GLenum target, GLint s); + void (APIENTRY *MultiTexCoord1ivARB) (GLenum target, const GLint *v); + void (APIENTRY *MultiTexCoord1sARB) (GLenum target, GLshort s); + void (APIENTRY *MultiTexCoord1svARB) (GLenum target, const GLshort *v); + void (APIENTRY *MultiTexCoord2dARB) (GLenum target, GLdouble s, GLdouble t); + void (APIENTRY *MultiTexCoord2dvARB) (GLenum target, const GLdouble *v); + void (APIENTRY *MultiTexCoord2fARB) (GLenum target, GLfloat s, GLfloat t); + void (APIENTRY *MultiTexCoord2fvARB) (GLenum target, const GLfloat *v); + void (APIENTRY *MultiTexCoord2iARB) (GLenum target, GLint s, GLint t); + void (APIENTRY *MultiTexCoord2ivARB) (GLenum target, const GLint *v); + void (APIENTRY *MultiTexCoord2sARB) (GLenum target, GLshort s, GLshort t); + void (APIENTRY *MultiTexCoord2svARB) (GLenum target, const GLshort *v); + void (APIENTRY *MultiTexCoord3dARB) (GLenum target, GLdouble s, GLdouble t, GLdouble r); + void (APIENTRY *MultiTexCoord3dvARB) (GLenum target, const GLdouble *v); + void (APIENTRY *MultiTexCoord3fARB) (GLenum target, GLfloat s, GLfloat t, GLfloat r); + void (APIENTRY *MultiTexCoord3fvARB) (GLenum target, const GLfloat *v); + void (APIENTRY *MultiTexCoord3iARB) (GLenum target, GLint s, GLint t, GLint r); + void (APIENTRY *MultiTexCoord3ivARB) (GLenum target, const GLint *v); + void (APIENTRY *MultiTexCoord3sARB) (GLenum target, GLshort s, GLshort t, GLshort r); + void (APIENTRY *MultiTexCoord3svARB) (GLenum target, const GLshort *v); + void (APIENTRY *MultiTexCoord4dARB) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); + void (APIENTRY *MultiTexCoord4dvARB) (GLenum target, const GLdouble *v); + void (APIENTRY *MultiTexCoord4fARB) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); + void (APIENTRY *MultiTexCoord4fvARB) (GLenum target, const GLfloat *v); + void (APIENTRY *MultiTexCoord4iARB) (GLenum target, GLint s, GLint t, GLint r, GLint q); + void (APIENTRY *MultiTexCoord4ivARB) (GLenum target, const GLint *v); + void (APIENTRY *MultiTexCoord4sARB) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); + void (APIENTRY *MultiTexCoord4svARB) (GLenum target, const GLshort *v); + void (APIENTRY *LoadTransposeMatrixfARB) (const GLfloat *m); + void (APIENTRY *LoadTransposeMatrixdARB) (const GLdouble *m); + void (APIENTRY *MultTransposeMatrixfARB) (const GLfloat *m); + void (APIENTRY *MultTransposeMatrixdARB) (const GLdouble *m); + void (APIENTRY *SampleCoverageARB) (GLclampf value, GLboolean invert); + void (APIENTRY *CompressedTexImage3DARB) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexImage2DARB) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexImage1DARB) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexSubImage3DARB) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexSubImage2DARB) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexSubImage1DARB) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *GetCompressedTexImageARB) (GLenum target, GLint level, GLvoid *img); + void (APIENTRY *PointParameterfARB) (GLenum pname, GLfloat param); + void (APIENTRY *PointParameterfvARB) (GLenum pname, const GLfloat *params); + void (APIENTRY *WeightbvARB) (GLint size, const GLbyte *weights); + void (APIENTRY *WeightsvARB) (GLint size, const GLshort *weights); + void (APIENTRY *WeightivARB) (GLint size, const GLint *weights); + void (APIENTRY *WeightfvARB) (GLint size, const GLfloat *weights); + void (APIENTRY *WeightdvARB) (GLint size, const GLdouble *weights); + void (APIENTRY *WeightubvARB) (GLint size, const GLubyte *weights); + void (APIENTRY *WeightusvARB) (GLint size, const GLushort *weights); + void (APIENTRY *WeightuivARB) (GLint size, const GLuint *weights); + void (APIENTRY *WeightPointerARB) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *VertexBlendARB) (GLint count); + void (APIENTRY *CurrentPaletteMatrixARB) (GLint index); + void (APIENTRY *MatrixIndexubvARB) (GLint size, const GLubyte *indices); + void (APIENTRY *MatrixIndexusvARB) (GLint size, const GLushort *indices); + void (APIENTRY *MatrixIndexuivARB) (GLint size, const GLuint *indices); + void (APIENTRY *MatrixIndexPointerARB) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *WindowPos2dARB) (GLdouble x, GLdouble y); + void (APIENTRY *WindowPos2dvARB) (const GLdouble *v); + void (APIENTRY *WindowPos2fARB) (GLfloat x, GLfloat y); + void (APIENTRY *WindowPos2fvARB) (const GLfloat *v); + void (APIENTRY *WindowPos2iARB) (GLint x, GLint y); + void (APIENTRY *WindowPos2ivARB) (const GLint *v); + void (APIENTRY *WindowPos2sARB) (GLshort x, GLshort y); + void (APIENTRY *WindowPos2svARB) (const GLshort *v); + void (APIENTRY *WindowPos3dARB) (GLdouble x, GLdouble y, GLdouble z); + void (APIENTRY *WindowPos3dvARB) (const GLdouble *v); + void (APIENTRY *WindowPos3fARB) (GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *WindowPos3fvARB) (const GLfloat *v); + void (APIENTRY *WindowPos3iARB) (GLint x, GLint y, GLint z); + void (APIENTRY *WindowPos3ivARB) (const GLint *v); + void (APIENTRY *WindowPos3sARB) (GLshort x, GLshort y, GLshort z); + void (APIENTRY *WindowPos3svARB) (const GLshort *v); + void (APIENTRY *VertexAttrib1dARB) (GLuint index, GLdouble x); + void (APIENTRY *VertexAttrib1dvARB) (GLuint index, const GLdouble *v); + void (APIENTRY *VertexAttrib1fARB) (GLuint index, GLfloat x); + void (APIENTRY *VertexAttrib1fvARB) (GLuint index, const GLfloat *v); + void (APIENTRY *VertexAttrib1sARB) (GLuint index, GLshort x); + void (APIENTRY *VertexAttrib1svARB) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib2dARB) (GLuint index, GLdouble x, GLdouble y); + void (APIENTRY *VertexAttrib2dvARB) (GLuint index, const GLdouble *v); + void (APIENTRY *VertexAttrib2fARB) (GLuint index, GLfloat x, GLfloat y); + void (APIENTRY *VertexAttrib2fvARB) (GLuint index, const GLfloat *v); + void (APIENTRY *VertexAttrib2sARB) (GLuint index, GLshort x, GLshort y); + void (APIENTRY *VertexAttrib2svARB) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib3dARB) (GLuint index, GLdouble x, GLdouble y, GLdouble z); + void (APIENTRY *VertexAttrib3dvARB) (GLuint index, const GLdouble *v); + void (APIENTRY *VertexAttrib3fARB) (GLuint index, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *VertexAttrib3fvARB) (GLuint index, const GLfloat *v); + void (APIENTRY *VertexAttrib3sARB) (GLuint index, GLshort x, GLshort y, GLshort z); + void (APIENTRY *VertexAttrib3svARB) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib4NbvARB) (GLuint index, const GLbyte *v); + void (APIENTRY *VertexAttrib4NivARB) (GLuint index, const GLint *v); + void (APIENTRY *VertexAttrib4NsvARB) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib4NubARB) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); + void (APIENTRY *VertexAttrib4NubvARB) (GLuint index, const GLubyte *v); + void (APIENTRY *VertexAttrib4NuivARB) (GLuint index, const GLuint *v); + void (APIENTRY *VertexAttrib4NusvARB) (GLuint index, const GLushort *v); + void (APIENTRY *VertexAttrib4bvARB) (GLuint index, const GLbyte *v); + void (APIENTRY *VertexAttrib4dARB) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + void (APIENTRY *VertexAttrib4dvARB) (GLuint index, const GLdouble *v); + void (APIENTRY *VertexAttrib4fARB) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *VertexAttrib4fvARB) (GLuint index, const GLfloat *v); + void (APIENTRY *VertexAttrib4ivARB) (GLuint index, const GLint *v); + void (APIENTRY *VertexAttrib4sARB) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); + void (APIENTRY *VertexAttrib4svARB) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib4ubvARB) (GLuint index, const GLubyte *v); + void (APIENTRY *VertexAttrib4uivARB) (GLuint index, const GLuint *v); + void (APIENTRY *VertexAttrib4usvARB) (GLuint index, const GLushort *v); + void (APIENTRY *VertexAttribPointerARB) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *EnableVertexAttribArrayARB) (GLuint index); + void (APIENTRY *DisableVertexAttribArrayARB) (GLuint index); + void (APIENTRY *ProgramStringARB) (GLenum target, GLenum format, GLsizei len, const GLvoid *string); + void (APIENTRY *BindProgramARB) (GLenum target, GLuint program); + void (APIENTRY *DeleteProgramsARB) (GLsizei n, const GLuint *programs); + void (APIENTRY *GenProgramsARB) (GLsizei n, GLuint *programs); + void (APIENTRY *ProgramEnvParameter4dARB) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + void (APIENTRY *ProgramEnvParameter4dvARB) (GLenum target, GLuint index, const GLdouble *params); + void (APIENTRY *ProgramEnvParameter4fARB) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *ProgramEnvParameter4fvARB) (GLenum target, GLuint index, const GLfloat *params); + void (APIENTRY *ProgramLocalParameter4dARB) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + void (APIENTRY *ProgramLocalParameter4dvARB) (GLenum target, GLuint index, const GLdouble *params); + void (APIENTRY *ProgramLocalParameter4fARB) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *ProgramLocalParameter4fvARB) (GLenum target, GLuint index, const GLfloat *params); + void (APIENTRY *GetProgramEnvParameterdvARB) (GLenum target, GLuint index, GLdouble *params); + void (APIENTRY *GetProgramEnvParameterfvARB) (GLenum target, GLuint index, GLfloat *params); + void (APIENTRY *GetProgramLocalParameterdvARB) (GLenum target, GLuint index, GLdouble *params); + void (APIENTRY *GetProgramLocalParameterfvARB) (GLenum target, GLuint index, GLfloat *params); + void (APIENTRY *GetProgramivARB) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetProgramStringARB) (GLenum target, GLenum pname, GLvoid *string); + void (APIENTRY *GetVertexAttribdvARB) (GLuint index, GLenum pname, GLdouble *params); + void (APIENTRY *GetVertexAttribfvARB) (GLuint index, GLenum pname, GLfloat *params); + void (APIENTRY *GetVertexAttribivARB) (GLuint index, GLenum pname, GLint *params); + void (APIENTRY *GetVertexAttribPointervARB) (GLuint index, GLenum pname, GLvoid* *pointer); + GLboolean (APIENTRY *IsProgramARB) (GLuint program); + void (APIENTRY *BindBufferARB) (GLenum target, GLuint buffer); + void (APIENTRY *DeleteBuffersARB) (GLsizei n, const GLuint *buffers); + void (APIENTRY *GenBuffersARB) (GLsizei n, GLuint *buffers); + GLboolean (APIENTRY *IsBufferARB) (GLuint buffer); + void (APIENTRY *BufferDataARB) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage); + void (APIENTRY *BufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data); + void (APIENTRY *GetBufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data); + GLvoid* (APIENTRY *MapBufferARB) (GLenum target, GLenum access); + GLboolean (APIENTRY *UnmapBufferARB) (GLenum target); + void (APIENTRY *GetBufferParameterivARB) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetBufferPointervARB) (GLenum target, GLenum pname, GLvoid* *params); + void (APIENTRY *GenQueriesARB) (GLsizei n, GLuint *ids); + void (APIENTRY *DeleteQueriesARB) (GLsizei n, const GLuint *ids); + GLboolean (APIENTRY *IsQueryARB) (GLuint id); + void (APIENTRY *BeginQueryARB) (GLenum target, GLuint id); + void (APIENTRY *EndQueryARB) (GLenum target); + void (APIENTRY *GetQueryivARB) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetQueryObjectivARB) (GLuint id, GLenum pname, GLint *params); + void (APIENTRY *GetQueryObjectuivARB) (GLuint id, GLenum pname, GLuint *params); + void (APIENTRY *DeleteObjectARB) (GLhandleARB obj); + GLhandleARB (APIENTRY *GetHandleARB) (GLenum pname); + void (APIENTRY *DetachObjectARB) (GLhandleARB containerObj, GLhandleARB attachedObj); + GLhandleARB (APIENTRY *CreateShaderObjectARB) (GLenum shaderType); + void (APIENTRY *ShaderSourceARB) (GLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length); + void (APIENTRY *CompileShaderARB) (GLhandleARB shaderObj); + GLhandleARB (APIENTRY *CreateProgramObjectARB) (void); + void (APIENTRY *AttachObjectARB) (GLhandleARB containerObj, GLhandleARB obj); + void (APIENTRY *LinkProgramARB) (GLhandleARB programObj); + void (APIENTRY *UseProgramObjectARB) (GLhandleARB programObj); + void (APIENTRY *ValidateProgramARB) (GLhandleARB programObj); + void (APIENTRY *Uniform1fARB) (GLint location, GLfloat v0); + void (APIENTRY *Uniform2fARB) (GLint location, GLfloat v0, GLfloat v1); + void (APIENTRY *Uniform3fARB) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); + void (APIENTRY *Uniform4fARB) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); + void (APIENTRY *Uniform1iARB) (GLint location, GLint v0); + void (APIENTRY *Uniform2iARB) (GLint location, GLint v0, GLint v1); + void (APIENTRY *Uniform3iARB) (GLint location, GLint v0, GLint v1, GLint v2); + void (APIENTRY *Uniform4iARB) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); + void (APIENTRY *Uniform1fvARB) (GLint location, GLsizei count, const GLfloat *value); + void (APIENTRY *Uniform2fvARB) (GLint location, GLsizei count, const GLfloat *value); + void (APIENTRY *Uniform3fvARB) (GLint location, GLsizei count, const GLfloat *value); + void (APIENTRY *Uniform4fvARB) (GLint location, GLsizei count, const GLfloat *value); + void (APIENTRY *Uniform1ivARB) (GLint location, GLsizei count, const GLint *value); + void (APIENTRY *Uniform2ivARB) (GLint location, GLsizei count, const GLint *value); + void (APIENTRY *Uniform3ivARB) (GLint location, GLsizei count, const GLint *value); + void (APIENTRY *Uniform4ivARB) (GLint location, GLsizei count, const GLint *value); + void (APIENTRY *UniformMatrix2fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void (APIENTRY *UniformMatrix3fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void (APIENTRY *UniformMatrix4fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void (APIENTRY *GetObjectParameterfvARB) (GLhandleARB obj, GLenum pname, GLfloat *params); + void (APIENTRY *GetObjectParameterivARB) (GLhandleARB obj, GLenum pname, GLint *params); + void (APIENTRY *GetInfoLogARB) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog); + void (APIENTRY *GetAttachedObjectsARB) (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj); + GLint (APIENTRY *GetUniformLocationARB) (GLhandleARB programObj, const GLcharARB *name); + void (APIENTRY *GetActiveUniformARB) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); + void (APIENTRY *GetUniformfvARB) (GLhandleARB programObj, GLint location, GLfloat *params); + void (APIENTRY *GetUniformivARB) (GLhandleARB programObj, GLint location, GLint *params); + void (APIENTRY *GetShaderSourceARB) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source); + void (APIENTRY *BindAttribLocationARB) (GLhandleARB programObj, GLuint index, const GLcharARB *name); + void (APIENTRY *GetActiveAttribARB) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); + GLint (APIENTRY *GetAttribLocationARB) (GLhandleARB programObj, const GLcharARB *name); + void (APIENTRY *BlendColorEXT) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + void (APIENTRY *PolygonOffsetEXT) (GLfloat factor, GLfloat bias); + void (APIENTRY *TexImage3DEXT) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); + void (APIENTRY *TexSubImage3DEXT) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); + void (APIENTRY *GetTexFilterFuncSGIS) (GLenum target, GLenum filter, GLfloat *weights); + void (APIENTRY *TexFilterFuncSGIS) (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights); + void (APIENTRY *TexSubImage1DEXT) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); + void (APIENTRY *TexSubImage2DEXT) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); + void (APIENTRY *CopyTexImage1DEXT) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); + void (APIENTRY *CopyTexImage2DEXT) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); + void (APIENTRY *CopyTexSubImage1DEXT) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); + void (APIENTRY *CopyTexSubImage2DEXT) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); + void (APIENTRY *CopyTexSubImage3DEXT) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); + void (APIENTRY *GetHistogramEXT) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); + void (APIENTRY *GetHistogramParameterfvEXT) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetHistogramParameterivEXT) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetMinmaxEXT) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); + void (APIENTRY *GetMinmaxParameterfvEXT) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetMinmaxParameterivEXT) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *HistogramEXT) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); + void (APIENTRY *MinmaxEXT) (GLenum target, GLenum internalformat, GLboolean sink); + void (APIENTRY *ResetHistogramEXT) (GLenum target); + void (APIENTRY *ResetMinmaxEXT) (GLenum target); + void (APIENTRY *ConvolutionFilter1DEXT) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); + void (APIENTRY *ConvolutionFilter2DEXT) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); + void (APIENTRY *ConvolutionParameterfEXT) (GLenum target, GLenum pname, GLfloat params); + void (APIENTRY *ConvolutionParameterfvEXT) (GLenum target, GLenum pname, const GLfloat *params); + void (APIENTRY *ConvolutionParameteriEXT) (GLenum target, GLenum pname, GLint params); + void (APIENTRY *ConvolutionParameterivEXT) (GLenum target, GLenum pname, const GLint *params); + void (APIENTRY *CopyConvolutionFilter1DEXT) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); + void (APIENTRY *CopyConvolutionFilter2DEXT) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); + void (APIENTRY *GetConvolutionFilterEXT) (GLenum target, GLenum format, GLenum type, GLvoid *image); + void (APIENTRY *GetConvolutionParameterfvEXT) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetConvolutionParameterivEXT) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetSeparableFilterEXT) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); + void (APIENTRY *SeparableFilter2DEXT) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); + void (APIENTRY *ColorTableSGI) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); + void (APIENTRY *ColorTableParameterfvSGI) (GLenum target, GLenum pname, const GLfloat *params); + void (APIENTRY *ColorTableParameterivSGI) (GLenum target, GLenum pname, const GLint *params); + void (APIENTRY *CopyColorTableSGI) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); + void (APIENTRY *GetColorTableSGI) (GLenum target, GLenum format, GLenum type, GLvoid *table); + void (APIENTRY *GetColorTableParameterfvSGI) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetColorTableParameterivSGI) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *PixelTexGenSGIX) (GLenum mode); + void (APIENTRY *PixelTexGenParameteriSGIS) (GLenum pname, GLint param); + void (APIENTRY *PixelTexGenParameterivSGIS) (GLenum pname, const GLint *params); + void (APIENTRY *PixelTexGenParameterfSGIS) (GLenum pname, GLfloat param); + void (APIENTRY *PixelTexGenParameterfvSGIS) (GLenum pname, const GLfloat *params); + void (APIENTRY *GetPixelTexGenParameterivSGIS) (GLenum pname, GLint *params); + void (APIENTRY *GetPixelTexGenParameterfvSGIS) (GLenum pname, GLfloat *params); + void (APIENTRY *TexImage4DSGIS) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const GLvoid *pixels); + void (APIENTRY *TexSubImage4DSGIS) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const GLvoid *pixels); + GLboolean (APIENTRY *AreTexturesResidentEXT) (GLsizei n, const GLuint *textures, GLboolean *residences); + void (APIENTRY *BindTextureEXT) (GLenum target, GLuint texture); + void (APIENTRY *DeleteTexturesEXT) (GLsizei n, const GLuint *textures); + void (APIENTRY *GenTexturesEXT) (GLsizei n, GLuint *textures); + GLboolean (APIENTRY *IsTextureEXT) (GLuint texture); + void (APIENTRY *PrioritizeTexturesEXT) (GLsizei n, const GLuint *textures, const GLclampf *priorities); + void (APIENTRY *DetailTexFuncSGIS) (GLenum target, GLsizei n, const GLfloat *points); + void (APIENTRY *GetDetailTexFuncSGIS) (GLenum target, GLfloat *points); + void (APIENTRY *SharpenTexFuncSGIS) (GLenum target, GLsizei n, const GLfloat *points); + void (APIENTRY *GetSharpenTexFuncSGIS) (GLenum target, GLfloat *points); + void (APIENTRY *SampleMaskSGIS) (GLclampf value, GLboolean invert); + void (APIENTRY *SamplePatternSGIS) (GLenum pattern); + void (APIENTRY *ArrayElementEXT) (GLint i); + void (APIENTRY *ColorPointerEXT) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); + void (APIENTRY *DrawArraysEXT) (GLenum mode, GLint first, GLsizei count); + void (APIENTRY *EdgeFlagPointerEXT) (GLsizei stride, GLsizei count, const GLboolean *pointer); + void (APIENTRY *GetPointervEXT) (GLenum pname, GLvoid* *params); + void (APIENTRY *IndexPointerEXT) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); + void (APIENTRY *NormalPointerEXT) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); + void (APIENTRY *TexCoordPointerEXT) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); + void (APIENTRY *VertexPointerEXT) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); + void (APIENTRY *BlendEquationEXT) (GLenum mode); + void (APIENTRY *SpriteParameterfSGIX) (GLenum pname, GLfloat param); + void (APIENTRY *SpriteParameterfvSGIX) (GLenum pname, const GLfloat *params); + void (APIENTRY *SpriteParameteriSGIX) (GLenum pname, GLint param); + void (APIENTRY *SpriteParameterivSGIX) (GLenum pname, const GLint *params); + void (APIENTRY *PointParameterfEXT) (GLenum pname, GLfloat param); + void (APIENTRY *PointParameterfvEXT) (GLenum pname, const GLfloat *params); + void (APIENTRY *PointParameterfSGIS) (GLenum pname, GLfloat param); + void (APIENTRY *PointParameterfvSGIS) (GLenum pname, const GLfloat *params); + GLint (APIENTRY *GetInstrumentsSGIX) (void); + void (APIENTRY *InstrumentsBufferSGIX) (GLsizei size, GLint *buffer); + GLint (APIENTRY *PollInstrumentsSGIX) (GLint *marker_p); + void (APIENTRY *ReadInstrumentsSGIX) (GLint marker); + void (APIENTRY *StartInstrumentsSGIX) (void); + void (APIENTRY *StopInstrumentsSGIX) (GLint marker); + void (APIENTRY *FrameZoomSGIX) (GLint factor); + void (APIENTRY *TagSampleBufferSGIX) (void); + void (APIENTRY *DeformationMap3dSGIX) (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble *points); + void (APIENTRY *DeformationMap3fSGIX) (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat *points); + void (APIENTRY *DeformSGIX) (GLbitfield mask); + void (APIENTRY *LoadIdentityDeformationMapSGIX) (GLbitfield mask); + void (APIENTRY *ReferencePlaneSGIX) (const GLdouble *equation); + void (APIENTRY *FlushRasterSGIX) (void); + void (APIENTRY *FogFuncSGIS) (GLsizei n, const GLfloat *points); + void (APIENTRY *GetFogFuncSGIS) (GLfloat *points); + void (APIENTRY *ImageTransformParameteriHP) (GLenum target, GLenum pname, GLint param); + void (APIENTRY *ImageTransformParameterfHP) (GLenum target, GLenum pname, GLfloat param); + void (APIENTRY *ImageTransformParameterivHP) (GLenum target, GLenum pname, const GLint *params); + void (APIENTRY *ImageTransformParameterfvHP) (GLenum target, GLenum pname, const GLfloat *params); + void (APIENTRY *GetImageTransformParameterivHP) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetImageTransformParameterfvHP) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *ColorSubTableEXT) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); + void (APIENTRY *CopyColorSubTableEXT) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); + void (APIENTRY *HintPGI) (GLenum target, GLint mode); + void (APIENTRY *ColorTableEXT) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); + void (APIENTRY *GetColorTableEXT) (GLenum target, GLenum format, GLenum type, GLvoid *data); + void (APIENTRY *GetColorTableParameterivEXT) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetColorTableParameterfvEXT) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetListParameterfvSGIX) (GLuint list, GLenum pname, GLfloat *params); + void (APIENTRY *GetListParameterivSGIX) (GLuint list, GLenum pname, GLint *params); + void (APIENTRY *ListParameterfSGIX) (GLuint list, GLenum pname, GLfloat param); + void (APIENTRY *ListParameterfvSGIX) (GLuint list, GLenum pname, const GLfloat *params); + void (APIENTRY *ListParameteriSGIX) (GLuint list, GLenum pname, GLint param); + void (APIENTRY *ListParameterivSGIX) (GLuint list, GLenum pname, const GLint *params); + void (APIENTRY *IndexMaterialEXT) (GLenum face, GLenum mode); + void (APIENTRY *IndexFuncEXT) (GLenum func, GLclampf ref); + void (APIENTRY *LockArraysEXT) (GLint first, GLsizei count); + void (APIENTRY *UnlockArraysEXT) (void); + void (APIENTRY *CullParameterdvEXT) (GLenum pname, GLdouble *params); + void (APIENTRY *CullParameterfvEXT) (GLenum pname, GLfloat *params); + void (APIENTRY *FragmentColorMaterialSGIX) (GLenum face, GLenum mode); + void (APIENTRY *FragmentLightfSGIX) (GLenum light, GLenum pname, GLfloat param); + void (APIENTRY *FragmentLightfvSGIX) (GLenum light, GLenum pname, const GLfloat *params); + void (APIENTRY *FragmentLightiSGIX) (GLenum light, GLenum pname, GLint param); + void (APIENTRY *FragmentLightivSGIX) (GLenum light, GLenum pname, const GLint *params); + void (APIENTRY *FragmentLightModelfSGIX) (GLenum pname, GLfloat param); + void (APIENTRY *FragmentLightModelfvSGIX) (GLenum pname, const GLfloat *params); + void (APIENTRY *FragmentLightModeliSGIX) (GLenum pname, GLint param); + void (APIENTRY *FragmentLightModelivSGIX) (GLenum pname, const GLint *params); + void (APIENTRY *FragmentMaterialfSGIX) (GLenum face, GLenum pname, GLfloat param); + void (APIENTRY *FragmentMaterialfvSGIX) (GLenum face, GLenum pname, const GLfloat *params); + void (APIENTRY *FragmentMaterialiSGIX) (GLenum face, GLenum pname, GLint param); + void (APIENTRY *FragmentMaterialivSGIX) (GLenum face, GLenum pname, const GLint *params); + void (APIENTRY *GetFragmentLightfvSGIX) (GLenum light, GLenum pname, GLfloat *params); + void (APIENTRY *GetFragmentLightivSGIX) (GLenum light, GLenum pname, GLint *params); + void (APIENTRY *GetFragmentMaterialfvSGIX) (GLenum face, GLenum pname, GLfloat *params); + void (APIENTRY *GetFragmentMaterialivSGIX) (GLenum face, GLenum pname, GLint *params); + void (APIENTRY *LightEnviSGIX) (GLenum pname, GLint param); + void (APIENTRY *DrawRangeElementsEXT) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); + void (APIENTRY *ApplyTextureEXT) (GLenum mode); + void (APIENTRY *TextureLightEXT) (GLenum pname); + void (APIENTRY *TextureMaterialEXT) (GLenum face, GLenum mode); + void (APIENTRY *AsyncMarkerSGIX) (GLuint marker); + GLint (APIENTRY *FinishAsyncSGIX) (GLuint *markerp); + GLint (APIENTRY *PollAsyncSGIX) (GLuint *markerp); + GLuint (APIENTRY *GenAsyncMarkersSGIX) (GLsizei range); + void (APIENTRY *DeleteAsyncMarkersSGIX) (GLuint marker, GLsizei range); + GLboolean (APIENTRY *IsAsyncMarkerSGIX) (GLuint marker); + void (APIENTRY *VertexPointervINTEL) (GLint size, GLenum type, const GLvoid* *pointer); + void (APIENTRY *NormalPointervINTEL) (GLenum type, const GLvoid* *pointer); + void (APIENTRY *ColorPointervINTEL) (GLint size, GLenum type, const GLvoid* *pointer); + void (APIENTRY *TexCoordPointervINTEL) (GLint size, GLenum type, const GLvoid* *pointer); + void (APIENTRY *PixelTransformParameteriEXT) (GLenum target, GLenum pname, GLint param); + void (APIENTRY *PixelTransformParameterfEXT) (GLenum target, GLenum pname, GLfloat param); + void (APIENTRY *PixelTransformParameterivEXT) (GLenum target, GLenum pname, const GLint *params); + void (APIENTRY *PixelTransformParameterfvEXT) (GLenum target, GLenum pname, const GLfloat *params); + void (APIENTRY *SecondaryColor3bEXT) (GLbyte red, GLbyte green, GLbyte blue); + void (APIENTRY *SecondaryColor3bvEXT) (const GLbyte *v); + void (APIENTRY *SecondaryColor3dEXT) (GLdouble red, GLdouble green, GLdouble blue); + void (APIENTRY *SecondaryColor3dvEXT) (const GLdouble *v); + void (APIENTRY *SecondaryColor3fEXT) (GLfloat red, GLfloat green, GLfloat blue); + void (APIENTRY *SecondaryColor3fvEXT) (const GLfloat *v); + void (APIENTRY *SecondaryColor3iEXT) (GLint red, GLint green, GLint blue); + void (APIENTRY *SecondaryColor3ivEXT) (const GLint *v); + void (APIENTRY *SecondaryColor3sEXT) (GLshort red, GLshort green, GLshort blue); + void (APIENTRY *SecondaryColor3svEXT) (const GLshort *v); + void (APIENTRY *SecondaryColor3ubEXT) (GLubyte red, GLubyte green, GLubyte blue); + void (APIENTRY *SecondaryColor3ubvEXT) (const GLubyte *v); + void (APIENTRY *SecondaryColor3uiEXT) (GLuint red, GLuint green, GLuint blue); + void (APIENTRY *SecondaryColor3uivEXT) (const GLuint *v); + void (APIENTRY *SecondaryColor3usEXT) (GLushort red, GLushort green, GLushort blue); + void (APIENTRY *SecondaryColor3usvEXT) (const GLushort *v); + void (APIENTRY *SecondaryColorPointerEXT) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *TextureNormalEXT) (GLenum mode); + void (APIENTRY *MultiDrawArraysEXT) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); + void (APIENTRY *MultiDrawElementsEXT) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); + void (APIENTRY *FogCoordfEXT) (GLfloat coord); + void (APIENTRY *FogCoordfvEXT) (const GLfloat *coord); + void (APIENTRY *FogCoorddEXT) (GLdouble coord); + void (APIENTRY *FogCoorddvEXT) (const GLdouble *coord); + void (APIENTRY *FogCoordPointerEXT) (GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *Tangent3bEXT) (GLbyte tx, GLbyte ty, GLbyte tz); + void (APIENTRY *Tangent3bvEXT) (const GLbyte *v); + void (APIENTRY *Tangent3dEXT) (GLdouble tx, GLdouble ty, GLdouble tz); + void (APIENTRY *Tangent3dvEXT) (const GLdouble *v); + void (APIENTRY *Tangent3fEXT) (GLfloat tx, GLfloat ty, GLfloat tz); + void (APIENTRY *Tangent3fvEXT) (const GLfloat *v); + void (APIENTRY *Tangent3iEXT) (GLint tx, GLint ty, GLint tz); + void (APIENTRY *Tangent3ivEXT) (const GLint *v); + void (APIENTRY *Tangent3sEXT) (GLshort tx, GLshort ty, GLshort tz); + void (APIENTRY *Tangent3svEXT) (const GLshort *v); + void (APIENTRY *Binormal3bEXT) (GLbyte bx, GLbyte by, GLbyte bz); + void (APIENTRY *Binormal3bvEXT) (const GLbyte *v); + void (APIENTRY *Binormal3dEXT) (GLdouble bx, GLdouble by, GLdouble bz); + void (APIENTRY *Binormal3dvEXT) (const GLdouble *v); + void (APIENTRY *Binormal3fEXT) (GLfloat bx, GLfloat by, GLfloat bz); + void (APIENTRY *Binormal3fvEXT) (const GLfloat *v); + void (APIENTRY *Binormal3iEXT) (GLint bx, GLint by, GLint bz); + void (APIENTRY *Binormal3ivEXT) (const GLint *v); + void (APIENTRY *Binormal3sEXT) (GLshort bx, GLshort by, GLshort bz); + void (APIENTRY *Binormal3svEXT) (const GLshort *v); + void (APIENTRY *TangentPointerEXT) (GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *BinormalPointerEXT) (GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *FinishTextureSUNX) (void); + void (APIENTRY *GlobalAlphaFactorbSUN) (GLbyte factor); + void (APIENTRY *GlobalAlphaFactorsSUN) (GLshort factor); + void (APIENTRY *GlobalAlphaFactoriSUN) (GLint factor); + void (APIENTRY *GlobalAlphaFactorfSUN) (GLfloat factor); + void (APIENTRY *GlobalAlphaFactordSUN) (GLdouble factor); + void (APIENTRY *GlobalAlphaFactorubSUN) (GLubyte factor); + void (APIENTRY *GlobalAlphaFactorusSUN) (GLushort factor); + void (APIENTRY *GlobalAlphaFactoruiSUN) (GLuint factor); + void (APIENTRY *ReplacementCodeuiSUN) (GLuint code); + void (APIENTRY *ReplacementCodeusSUN) (GLushort code); + void (APIENTRY *ReplacementCodeubSUN) (GLubyte code); + void (APIENTRY *ReplacementCodeuivSUN) (const GLuint *code); + void (APIENTRY *ReplacementCodeusvSUN) (const GLushort *code); + void (APIENTRY *ReplacementCodeubvSUN) (const GLubyte *code); + void (APIENTRY *ReplacementCodePointerSUN) (GLenum type, GLsizei stride, const GLvoid* *pointer); + void (APIENTRY *Color4ubVertex2fSUN) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y); + void (APIENTRY *Color4ubVertex2fvSUN) (const GLubyte *c, const GLfloat *v); + void (APIENTRY *Color4ubVertex3fSUN) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *Color4ubVertex3fvSUN) (const GLubyte *c, const GLfloat *v); + void (APIENTRY *Color3fVertex3fSUN) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *Color3fVertex3fvSUN) (const GLfloat *c, const GLfloat *v); + void (APIENTRY *Normal3fVertex3fSUN) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *Normal3fVertex3fvSUN) (const GLfloat *n, const GLfloat *v); + void (APIENTRY *Color4fNormal3fVertex3fSUN) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *Color4fNormal3fVertex3fvSUN) (const GLfloat *c, const GLfloat *n, const GLfloat *v); + void (APIENTRY *TexCoord2fVertex3fSUN) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *TexCoord2fVertex3fvSUN) (const GLfloat *tc, const GLfloat *v); + void (APIENTRY *TexCoord4fVertex4fSUN) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *TexCoord4fVertex4fvSUN) (const GLfloat *tc, const GLfloat *v); + void (APIENTRY *TexCoord2fColor4ubVertex3fSUN) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *TexCoord2fColor4ubVertex3fvSUN) (const GLfloat *tc, const GLubyte *c, const GLfloat *v); + void (APIENTRY *TexCoord2fColor3fVertex3fSUN) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *TexCoord2fColor3fVertex3fvSUN) (const GLfloat *tc, const GLfloat *c, const GLfloat *v); + void (APIENTRY *TexCoord2fNormal3fVertex3fSUN) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *TexCoord2fNormal3fVertex3fvSUN) (const GLfloat *tc, const GLfloat *n, const GLfloat *v); + void (APIENTRY *TexCoord2fColor4fNormal3fVertex3fSUN) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *TexCoord2fColor4fNormal3fVertex3fvSUN) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); + void (APIENTRY *TexCoord4fColor4fNormal3fVertex4fSUN) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *TexCoord4fColor4fNormal3fVertex4fvSUN) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); + void (APIENTRY *ReplacementCodeuiVertex3fSUN) (GLuint rc, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *ReplacementCodeuiVertex3fvSUN) (const GLuint *rc, const GLfloat *v); + void (APIENTRY *ReplacementCodeuiColor4ubVertex3fSUN) (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *ReplacementCodeuiColor4ubVertex3fvSUN) (const GLuint *rc, const GLubyte *c, const GLfloat *v); + void (APIENTRY *ReplacementCodeuiColor3fVertex3fSUN) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *ReplacementCodeuiColor3fVertex3fvSUN) (const GLuint *rc, const GLfloat *c, const GLfloat *v); + void (APIENTRY *ReplacementCodeuiNormal3fVertex3fSUN) (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *ReplacementCodeuiNormal3fVertex3fvSUN) (const GLuint *rc, const GLfloat *n, const GLfloat *v); + void (APIENTRY *ReplacementCodeuiColor4fNormal3fVertex3fSUN) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *ReplacementCodeuiColor4fNormal3fVertex3fvSUN) (const GLuint *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v); + void (APIENTRY *ReplacementCodeuiTexCoord2fVertex3fSUN) (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *ReplacementCodeuiTexCoord2fVertex3fvSUN) (const GLuint *rc, const GLfloat *tc, const GLfloat *v); + void (APIENTRY *ReplacementCodeuiTexCoord2fNormal3fVertex3fSUN) (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *ReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN) (const GLuint *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v); + void (APIENTRY *ReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN) (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *ReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN) (const GLuint *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); + void (APIENTRY *BlendFuncSeparateEXT) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); + void (APIENTRY *BlendFuncSeparateINGR) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); + void (APIENTRY *VertexWeightfEXT) (GLfloat weight); + void (APIENTRY *VertexWeightfvEXT) (const GLfloat *weight); + void (APIENTRY *VertexWeightPointerEXT) (GLsizei size, GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *FlushVertexArrayRangeNV) (void); + void (APIENTRY *VertexArrayRangeNV) (GLsizei length, const GLvoid *pointer); + void (APIENTRY *CombinerParameterfvNV) (GLenum pname, const GLfloat *params); + void (APIENTRY *CombinerParameterfNV) (GLenum pname, GLfloat param); + void (APIENTRY *CombinerParameterivNV) (GLenum pname, const GLint *params); + void (APIENTRY *CombinerParameteriNV) (GLenum pname, GLint param); + void (APIENTRY *CombinerInputNV) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); + void (APIENTRY *CombinerOutputNV) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum); + void (APIENTRY *FinalCombinerInputNV) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); + void (APIENTRY *GetCombinerInputParameterfvNV) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params); + void (APIENTRY *GetCombinerInputParameterivNV) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params); + void (APIENTRY *GetCombinerOutputParameterfvNV) (GLenum stage, GLenum portion, GLenum pname, GLfloat *params); + void (APIENTRY *GetCombinerOutputParameterivNV) (GLenum stage, GLenum portion, GLenum pname, GLint *params); + void (APIENTRY *GetFinalCombinerInputParameterfvNV) (GLenum variable, GLenum pname, GLfloat *params); + void (APIENTRY *GetFinalCombinerInputParameterivNV) (GLenum variable, GLenum pname, GLint *params); + void (APIENTRY *ResizeBuffersMESA) (void); + void (APIENTRY *WindowPos2dMESA) (GLdouble x, GLdouble y); + void (APIENTRY *WindowPos2dvMESA) (const GLdouble *v); + void (APIENTRY *WindowPos2fMESA) (GLfloat x, GLfloat y); + void (APIENTRY *WindowPos2fvMESA) (const GLfloat *v); + void (APIENTRY *WindowPos2iMESA) (GLint x, GLint y); + void (APIENTRY *WindowPos2ivMESA) (const GLint *v); + void (APIENTRY *WindowPos2sMESA) (GLshort x, GLshort y); + void (APIENTRY *WindowPos2svMESA) (const GLshort *v); + void (APIENTRY *WindowPos3dMESA) (GLdouble x, GLdouble y, GLdouble z); + void (APIENTRY *WindowPos3dvMESA) (const GLdouble *v); + void (APIENTRY *WindowPos3fMESA) (GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *WindowPos3fvMESA) (const GLfloat *v); + void (APIENTRY *WindowPos3iMESA) (GLint x, GLint y, GLint z); + void (APIENTRY *WindowPos3ivMESA) (const GLint *v); + void (APIENTRY *WindowPos3sMESA) (GLshort x, GLshort y, GLshort z); + void (APIENTRY *WindowPos3svMESA) (const GLshort *v); + void (APIENTRY *WindowPos4dMESA) (GLdouble x, GLdouble y, GLdouble z, GLdouble w); + void (APIENTRY *WindowPos4dvMESA) (const GLdouble *v); + void (APIENTRY *WindowPos4fMESA) (GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *WindowPos4fvMESA) (const GLfloat *v); + void (APIENTRY *WindowPos4iMESA) (GLint x, GLint y, GLint z, GLint w); + void (APIENTRY *WindowPos4ivMESA) (const GLint *v); + void (APIENTRY *WindowPos4sMESA) (GLshort x, GLshort y, GLshort z, GLshort w); + void (APIENTRY *WindowPos4svMESA) (const GLshort *v); + void (APIENTRY *MultiModeDrawArraysIBM) (const GLenum *mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride); + void (APIENTRY *MultiModeDrawElementsIBM) (const GLenum *mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei primcount, GLint modestride); + void (APIENTRY *ColorPointerListIBM) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); + void (APIENTRY *SecondaryColorPointerListIBM) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); + void (APIENTRY *EdgeFlagPointerListIBM) (GLint stride, const GLboolean* *pointer, GLint ptrstride); + void (APIENTRY *FogCoordPointerListIBM) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); + void (APIENTRY *IndexPointerListIBM) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); + void (APIENTRY *NormalPointerListIBM) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); + void (APIENTRY *TexCoordPointerListIBM) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); + void (APIENTRY *VertexPointerListIBM) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); + void (APIENTRY *TbufferMask3DFX) (GLuint mask); + void (APIENTRY *SampleMaskEXT) (GLclampf value, GLboolean invert); + void (APIENTRY *SamplePatternEXT) (GLenum pattern); + void (APIENTRY *TextureColorMaskSGIS) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); + void (APIENTRY *IglooInterfaceSGIX) (GLenum pname, const GLvoid *params); + void (APIENTRY *DeleteFencesNV) (GLsizei n, const GLuint *fences); + void (APIENTRY *GenFencesNV) (GLsizei n, GLuint *fences); + GLboolean (APIENTRY *IsFenceNV) (GLuint fence); + GLboolean (APIENTRY *TestFenceNV) (GLuint fence); + void (APIENTRY *GetFenceivNV) (GLuint fence, GLenum pname, GLint *params); + void (APIENTRY *FinishFenceNV) (GLuint fence); + void (APIENTRY *SetFenceNV) (GLuint fence, GLenum condition); + void (APIENTRY *MapControlPointsNV) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const GLvoid *points); + void (APIENTRY *MapParameterivNV) (GLenum target, GLenum pname, const GLint *params); + void (APIENTRY *MapParameterfvNV) (GLenum target, GLenum pname, const GLfloat *params); + void (APIENTRY *GetMapControlPointsNV) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, GLvoid *points); + void (APIENTRY *GetMapParameterivNV) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetMapParameterfvNV) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetMapAttribParameterivNV) (GLenum target, GLuint index, GLenum pname, GLint *params); + void (APIENTRY *GetMapAttribParameterfvNV) (GLenum target, GLuint index, GLenum pname, GLfloat *params); + void (APIENTRY *EvalMapsNV) (GLenum target, GLenum mode); + void (APIENTRY *CombinerStageParameterfvNV) (GLenum stage, GLenum pname, const GLfloat *params); + void (APIENTRY *GetCombinerStageParameterfvNV) (GLenum stage, GLenum pname, GLfloat *params); + GLboolean (APIENTRY *AreProgramsResidentNV) (GLsizei n, const GLuint *programs, GLboolean *residences); + void (APIENTRY *BindProgramNV) (GLenum target, GLuint id); + void (APIENTRY *DeleteProgramsNV) (GLsizei n, const GLuint *programs); + void (APIENTRY *ExecuteProgramNV) (GLenum target, GLuint id, const GLfloat *params); + void (APIENTRY *GenProgramsNV) (GLsizei n, GLuint *programs); + void (APIENTRY *GetProgramParameterdvNV) (GLenum target, GLuint index, GLenum pname, GLdouble *params); + void (APIENTRY *GetProgramParameterfvNV) (GLenum target, GLuint index, GLenum pname, GLfloat *params); + void (APIENTRY *GetProgramivNV) (GLuint id, GLenum pname, GLint *params); + void (APIENTRY *GetProgramStringNV) (GLuint id, GLenum pname, GLubyte *program); + void (APIENTRY *GetTrackMatrixivNV) (GLenum target, GLuint address, GLenum pname, GLint *params); + void (APIENTRY *GetVertexAttribdvNV) (GLuint index, GLenum pname, GLdouble *params); + void (APIENTRY *GetVertexAttribfvNV) (GLuint index, GLenum pname, GLfloat *params); + void (APIENTRY *GetVertexAttribivNV) (GLuint index, GLenum pname, GLint *params); + void (APIENTRY *GetVertexAttribPointervNV) (GLuint index, GLenum pname, GLvoid* *pointer); + GLboolean (APIENTRY *IsProgramNV) (GLuint id); + void (APIENTRY *LoadProgramNV) (GLenum target, GLuint id, GLsizei len, const GLubyte *program); + void (APIENTRY *ProgramParameter4dNV) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + void (APIENTRY *ProgramParameter4dvNV) (GLenum target, GLuint index, const GLdouble *v); + void (APIENTRY *ProgramParameter4fNV) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *ProgramParameter4fvNV) (GLenum target, GLuint index, const GLfloat *v); + void (APIENTRY *ProgramParameters4dvNV) (GLenum target, GLuint index, GLuint count, const GLdouble *v); + void (APIENTRY *ProgramParameters4fvNV) (GLenum target, GLuint index, GLuint count, const GLfloat *v); + void (APIENTRY *RequestResidentProgramsNV) (GLsizei n, const GLuint *programs); + void (APIENTRY *TrackMatrixNV) (GLenum target, GLuint address, GLenum matrix, GLenum transform); + void (APIENTRY *VertexAttribPointerNV) (GLuint index, GLint fsize, GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *VertexAttrib1dNV) (GLuint index, GLdouble x); + void (APIENTRY *VertexAttrib1dvNV) (GLuint index, const GLdouble *v); + void (APIENTRY *VertexAttrib1fNV) (GLuint index, GLfloat x); + void (APIENTRY *VertexAttrib1fvNV) (GLuint index, const GLfloat *v); + void (APIENTRY *VertexAttrib1sNV) (GLuint index, GLshort x); + void (APIENTRY *VertexAttrib1svNV) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib2dNV) (GLuint index, GLdouble x, GLdouble y); + void (APIENTRY *VertexAttrib2dvNV) (GLuint index, const GLdouble *v); + void (APIENTRY *VertexAttrib2fNV) (GLuint index, GLfloat x, GLfloat y); + void (APIENTRY *VertexAttrib2fvNV) (GLuint index, const GLfloat *v); + void (APIENTRY *VertexAttrib2sNV) (GLuint index, GLshort x, GLshort y); + void (APIENTRY *VertexAttrib2svNV) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib3dNV) (GLuint index, GLdouble x, GLdouble y, GLdouble z); + void (APIENTRY *VertexAttrib3dvNV) (GLuint index, const GLdouble *v); + void (APIENTRY *VertexAttrib3fNV) (GLuint index, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *VertexAttrib3fvNV) (GLuint index, const GLfloat *v); + void (APIENTRY *VertexAttrib3sNV) (GLuint index, GLshort x, GLshort y, GLshort z); + void (APIENTRY *VertexAttrib3svNV) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib4dNV) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + void (APIENTRY *VertexAttrib4dvNV) (GLuint index, const GLdouble *v); + void (APIENTRY *VertexAttrib4fNV) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *VertexAttrib4fvNV) (GLuint index, const GLfloat *v); + void (APIENTRY *VertexAttrib4sNV) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); + void (APIENTRY *VertexAttrib4svNV) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib4ubNV) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); + void (APIENTRY *VertexAttrib4ubvNV) (GLuint index, const GLubyte *v); + void (APIENTRY *VertexAttribs1dvNV) (GLuint index, GLsizei count, const GLdouble *v); + void (APIENTRY *VertexAttribs1fvNV) (GLuint index, GLsizei count, const GLfloat *v); + void (APIENTRY *VertexAttribs1svNV) (GLuint index, GLsizei count, const GLshort *v); + void (APIENTRY *VertexAttribs2dvNV) (GLuint index, GLsizei count, const GLdouble *v); + void (APIENTRY *VertexAttribs2fvNV) (GLuint index, GLsizei count, const GLfloat *v); + void (APIENTRY *VertexAttribs2svNV) (GLuint index, GLsizei count, const GLshort *v); + void (APIENTRY *VertexAttribs3dvNV) (GLuint index, GLsizei count, const GLdouble *v); + void (APIENTRY *VertexAttribs3fvNV) (GLuint index, GLsizei count, const GLfloat *v); + void (APIENTRY *VertexAttribs3svNV) (GLuint index, GLsizei count, const GLshort *v); + void (APIENTRY *VertexAttribs4dvNV) (GLuint index, GLsizei count, const GLdouble *v); + void (APIENTRY *VertexAttribs4fvNV) (GLuint index, GLsizei count, const GLfloat *v); + void (APIENTRY *VertexAttribs4svNV) (GLuint index, GLsizei count, const GLshort *v); + void (APIENTRY *VertexAttribs4ubvNV) (GLuint index, GLsizei count, const GLubyte *v); + void (APIENTRY *TexBumpParameterivATI) (GLenum pname, const GLint *param); + void (APIENTRY *TexBumpParameterfvATI) (GLenum pname, const GLfloat *param); + void (APIENTRY *GetTexBumpParameterivATI) (GLenum pname, GLint *param); + void (APIENTRY *GetTexBumpParameterfvATI) (GLenum pname, GLfloat *param); + GLuint (APIENTRY *GenFragmentShadersATI) (GLuint range); + void (APIENTRY *BindFragmentShaderATI) (GLuint id); + void (APIENTRY *DeleteFragmentShaderATI) (GLuint id); + void (APIENTRY *BeginFragmentShaderATI) (void); + void (APIENTRY *EndFragmentShaderATI) (void); + void (APIENTRY *PassTexCoordATI) (GLuint dst, GLuint coord, GLenum swizzle); + void (APIENTRY *SampleMapATI) (GLuint dst, GLuint interp, GLenum swizzle); + void (APIENTRY *ColorFragmentOp1ATI) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); + void (APIENTRY *ColorFragmentOp2ATI) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); + void (APIENTRY *ColorFragmentOp3ATI) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); + void (APIENTRY *AlphaFragmentOp1ATI) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); + void (APIENTRY *AlphaFragmentOp2ATI) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); + void (APIENTRY *AlphaFragmentOp3ATI) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); + void (APIENTRY *SetFragmentShaderConstantATI) (GLuint dst, const GLfloat *value); + void (APIENTRY *PNTrianglesiATI) (GLenum pname, GLint param); + void (APIENTRY *PNTrianglesfATI) (GLenum pname, GLfloat param); + GLuint (APIENTRY *NewObjectBufferATI) (GLsizei size, const GLvoid *pointer, GLenum usage); + GLboolean (APIENTRY *IsObjectBufferATI) (GLuint buffer); + void (APIENTRY *UpdateObjectBufferATI) (GLuint buffer, GLuint offset, GLsizei size, const GLvoid *pointer, GLenum preserve); + void (APIENTRY *GetObjectBufferfvATI) (GLuint buffer, GLenum pname, GLfloat *params); + void (APIENTRY *GetObjectBufferivATI) (GLuint buffer, GLenum pname, GLint *params); + void (APIENTRY *FreeObjectBufferATI) (GLuint buffer); + void (APIENTRY *ArrayObjectATI) (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); + void (APIENTRY *GetArrayObjectfvATI) (GLenum array, GLenum pname, GLfloat *params); + void (APIENTRY *GetArrayObjectivATI) (GLenum array, GLenum pname, GLint *params); + void (APIENTRY *VariantArrayObjectATI) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); + void (APIENTRY *GetVariantArrayObjectfvATI) (GLuint id, GLenum pname, GLfloat *params); + void (APIENTRY *GetVariantArrayObjectivATI) (GLuint id, GLenum pname, GLint *params); + void (APIENTRY *BeginVertexShaderEXT) (void); + void (APIENTRY *EndVertexShaderEXT) (void); + void (APIENTRY *BindVertexShaderEXT) (GLuint id); + GLuint (APIENTRY *GenVertexShadersEXT) (GLuint range); + void (APIENTRY *DeleteVertexShaderEXT) (GLuint id); + void (APIENTRY *ShaderOp1EXT) (GLenum op, GLuint res, GLuint arg1); + void (APIENTRY *ShaderOp2EXT) (GLenum op, GLuint res, GLuint arg1, GLuint arg2); + void (APIENTRY *ShaderOp3EXT) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3); + void (APIENTRY *SwizzleEXT) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); + void (APIENTRY *WriteMaskEXT) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); + void (APIENTRY *InsertComponentEXT) (GLuint res, GLuint src, GLuint num); + void (APIENTRY *ExtractComponentEXT) (GLuint res, GLuint src, GLuint num); + GLuint (APIENTRY *GenSymbolsEXT) (GLenum datatype, GLenum storagetype, GLenum range, GLuint components); + void (APIENTRY *SetInvariantEXT) (GLuint id, GLenum type, const GLvoid *addr); + void (APIENTRY *SetLocalConstantEXT) (GLuint id, GLenum type, const GLvoid *addr); + void (APIENTRY *VariantbvEXT) (GLuint id, const GLbyte *addr); + void (APIENTRY *VariantsvEXT) (GLuint id, const GLshort *addr); + void (APIENTRY *VariantivEXT) (GLuint id, const GLint *addr); + void (APIENTRY *VariantfvEXT) (GLuint id, const GLfloat *addr); + void (APIENTRY *VariantdvEXT) (GLuint id, const GLdouble *addr); + void (APIENTRY *VariantubvEXT) (GLuint id, const GLubyte *addr); + void (APIENTRY *VariantusvEXT) (GLuint id, const GLushort *addr); + void (APIENTRY *VariantuivEXT) (GLuint id, const GLuint *addr); + void (APIENTRY *VariantPointerEXT) (GLuint id, GLenum type, GLuint stride, const GLvoid *addr); + void (APIENTRY *EnableVariantClientStateEXT) (GLuint id); + void (APIENTRY *DisableVariantClientStateEXT) (GLuint id); + GLuint (APIENTRY *BindLightParameterEXT) (GLenum light, GLenum value); + GLuint (APIENTRY *BindMaterialParameterEXT) (GLenum face, GLenum value); + GLuint (APIENTRY *BindTexGenParameterEXT) (GLenum unit, GLenum coord, GLenum value); + GLuint (APIENTRY *BindTextureUnitParameterEXT) (GLenum unit, GLenum value); + GLuint (APIENTRY *BindParameterEXT) (GLenum value); + GLboolean (APIENTRY *IsVariantEnabledEXT) (GLuint id, GLenum cap); + void (APIENTRY *GetVariantBooleanvEXT) (GLuint id, GLenum value, GLboolean *data); + void (APIENTRY *GetVariantIntegervEXT) (GLuint id, GLenum value, GLint *data); + void (APIENTRY *GetVariantFloatvEXT) (GLuint id, GLenum value, GLfloat *data); + void (APIENTRY *GetVariantPointervEXT) (GLuint id, GLenum value, GLvoid* *data); + void (APIENTRY *GetInvariantBooleanvEXT) (GLuint id, GLenum value, GLboolean *data); + void (APIENTRY *GetInvariantIntegervEXT) (GLuint id, GLenum value, GLint *data); + void (APIENTRY *GetInvariantFloatvEXT) (GLuint id, GLenum value, GLfloat *data); + void (APIENTRY *GetLocalConstantBooleanvEXT) (GLuint id, GLenum value, GLboolean *data); + void (APIENTRY *GetLocalConstantIntegervEXT) (GLuint id, GLenum value, GLint *data); + void (APIENTRY *GetLocalConstantFloatvEXT) (GLuint id, GLenum value, GLfloat *data); + void (APIENTRY *VertexStream1sATI) (GLenum stream, GLshort x); + void (APIENTRY *VertexStream1svATI) (GLenum stream, const GLshort *coords); + void (APIENTRY *VertexStream1iATI) (GLenum stream, GLint x); + void (APIENTRY *VertexStream1ivATI) (GLenum stream, const GLint *coords); + void (APIENTRY *VertexStream1fATI) (GLenum stream, GLfloat x); + void (APIENTRY *VertexStream1fvATI) (GLenum stream, const GLfloat *coords); + void (APIENTRY *VertexStream1dATI) (GLenum stream, GLdouble x); + void (APIENTRY *VertexStream1dvATI) (GLenum stream, const GLdouble *coords); + void (APIENTRY *VertexStream2sATI) (GLenum stream, GLshort x, GLshort y); + void (APIENTRY *VertexStream2svATI) (GLenum stream, const GLshort *coords); + void (APIENTRY *VertexStream2iATI) (GLenum stream, GLint x, GLint y); + void (APIENTRY *VertexStream2ivATI) (GLenum stream, const GLint *coords); + void (APIENTRY *VertexStream2fATI) (GLenum stream, GLfloat x, GLfloat y); + void (APIENTRY *VertexStream2fvATI) (GLenum stream, const GLfloat *coords); + void (APIENTRY *VertexStream2dATI) (GLenum stream, GLdouble x, GLdouble y); + void (APIENTRY *VertexStream2dvATI) (GLenum stream, const GLdouble *coords); + void (APIENTRY *VertexStream3sATI) (GLenum stream, GLshort x, GLshort y, GLshort z); + void (APIENTRY *VertexStream3svATI) (GLenum stream, const GLshort *coords); + void (APIENTRY *VertexStream3iATI) (GLenum stream, GLint x, GLint y, GLint z); + void (APIENTRY *VertexStream3ivATI) (GLenum stream, const GLint *coords); + void (APIENTRY *VertexStream3fATI) (GLenum stream, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *VertexStream3fvATI) (GLenum stream, const GLfloat *coords); + void (APIENTRY *VertexStream3dATI) (GLenum stream, GLdouble x, GLdouble y, GLdouble z); + void (APIENTRY *VertexStream3dvATI) (GLenum stream, const GLdouble *coords); + void (APIENTRY *VertexStream4sATI) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w); + void (APIENTRY *VertexStream4svATI) (GLenum stream, const GLshort *coords); + void (APIENTRY *VertexStream4iATI) (GLenum stream, GLint x, GLint y, GLint z, GLint w); + void (APIENTRY *VertexStream4ivATI) (GLenum stream, const GLint *coords); + void (APIENTRY *VertexStream4fATI) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *VertexStream4fvATI) (GLenum stream, const GLfloat *coords); + void (APIENTRY *VertexStream4dATI) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + void (APIENTRY *VertexStream4dvATI) (GLenum stream, const GLdouble *coords); + void (APIENTRY *NormalStream3bATI) (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz); + void (APIENTRY *NormalStream3bvATI) (GLenum stream, const GLbyte *coords); + void (APIENTRY *NormalStream3sATI) (GLenum stream, GLshort nx, GLshort ny, GLshort nz); + void (APIENTRY *NormalStream3svATI) (GLenum stream, const GLshort *coords); + void (APIENTRY *NormalStream3iATI) (GLenum stream, GLint nx, GLint ny, GLint nz); + void (APIENTRY *NormalStream3ivATI) (GLenum stream, const GLint *coords); + void (APIENTRY *NormalStream3fATI) (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz); + void (APIENTRY *NormalStream3fvATI) (GLenum stream, const GLfloat *coords); + void (APIENTRY *NormalStream3dATI) (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz); + void (APIENTRY *NormalStream3dvATI) (GLenum stream, const GLdouble *coords); + void (APIENTRY *ClientActiveVertexStreamATI) (GLenum stream); + void (APIENTRY *VertexBlendEnviATI) (GLenum pname, GLint param); + void (APIENTRY *VertexBlendEnvfATI) (GLenum pname, GLfloat param); + void (APIENTRY *ElementPointerATI) (GLenum type, const GLvoid *pointer); + void (APIENTRY *DrawElementArrayATI) (GLenum mode, GLsizei count); + void (APIENTRY *DrawRangeElementArrayATI) (GLenum mode, GLuint start, GLuint end, GLsizei count); + void (APIENTRY *DrawMeshArraysSUN) (GLenum mode, GLint first, GLsizei count, GLsizei width); + void (APIENTRY *GenOcclusionQueriesNV) (GLsizei n, GLuint *ids); + void (APIENTRY *DeleteOcclusionQueriesNV) (GLsizei n, const GLuint *ids); + GLboolean (APIENTRY *IsOcclusionQueryNV) (GLuint id); + void (APIENTRY *BeginOcclusionQueryNV) (GLuint id); + void (APIENTRY *EndOcclusionQueryNV) (void); + void (APIENTRY *GetOcclusionQueryivNV) (GLuint id, GLenum pname, GLint *params); + void (APIENTRY *GetOcclusionQueryuivNV) (GLuint id, GLenum pname, GLuint *params); + void (APIENTRY *PointParameteriNV) (GLenum pname, GLint param); + void (APIENTRY *PointParameterivNV) (GLenum pname, const GLint *params); + void (APIENTRY *ActiveStencilFaceEXT) (GLenum face); + void (APIENTRY *ElementPointerAPPLE) (GLenum type, const GLvoid *pointer); + void (APIENTRY *DrawElementArrayAPPLE) (GLenum mode, GLint first, GLsizei count); + void (APIENTRY *DrawRangeElementArrayAPPLE) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count); + void (APIENTRY *MultiDrawElementArrayAPPLE) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); + void (APIENTRY *MultiDrawRangeElementArrayAPPLE) (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount); + void (APIENTRY *GenFencesAPPLE) (GLsizei n, GLuint *fences); + void (APIENTRY *DeleteFencesAPPLE) (GLsizei n, const GLuint *fences); + void (APIENTRY *SetFenceAPPLE) (GLuint fence); + GLboolean (APIENTRY *IsFenceAPPLE) (GLuint fence); + GLboolean (APIENTRY *TestFenceAPPLE) (GLuint fence); + void (APIENTRY *FinishFenceAPPLE) (GLuint fence); + GLboolean (APIENTRY *TestObjectAPPLE) (GLenum object, GLuint name); + void (APIENTRY *FinishObjectAPPLE) (GLenum object, GLint name); + void (APIENTRY *BindVertexArrayAPPLE) (GLuint array); + void (APIENTRY *DeleteVertexArraysAPPLE) (GLsizei n, const GLuint *arrays); + void (APIENTRY *GenVertexArraysAPPLE) (GLsizei n, const GLuint *arrays); + GLboolean (APIENTRY *IsVertexArrayAPPLE) (GLuint array); + void (APIENTRY *VertexArrayRangeAPPLE) (GLsizei length, GLvoid *pointer); + void (APIENTRY *FlushVertexArrayRangeAPPLE) (GLsizei length, GLvoid *pointer); + void (APIENTRY *VertexArrayParameteriAPPLE) (GLenum pname, GLint param); + void (APIENTRY *DrawBuffersATI) (GLsizei n, const GLenum *bufs); + void (APIENTRY *ProgramNamedParameter4fNV) (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *ProgramNamedParameter4dNV) (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + void (APIENTRY *ProgramNamedParameter4fvNV) (GLuint id, GLsizei len, const GLubyte *name, const GLfloat *v); + void (APIENTRY *ProgramNamedParameter4dvNV) (GLuint id, GLsizei len, const GLubyte *name, const GLdouble *v); + void (APIENTRY *GetProgramNamedParameterfvNV) (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params); + void (APIENTRY *GetProgramNamedParameterdvNV) (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params); + void (APIENTRY *Vertex2hNV) (GLhalfNV x, GLhalfNV y); + void (APIENTRY *Vertex2hvNV) (const GLhalfNV *v); + void (APIENTRY *Vertex3hNV) (GLhalfNV x, GLhalfNV y, GLhalfNV z); + void (APIENTRY *Vertex3hvNV) (const GLhalfNV *v); + void (APIENTRY *Vertex4hNV) (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w); + void (APIENTRY *Vertex4hvNV) (const GLhalfNV *v); + void (APIENTRY *Normal3hNV) (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz); + void (APIENTRY *Normal3hvNV) (const GLhalfNV *v); + void (APIENTRY *Color3hNV) (GLhalfNV red, GLhalfNV green, GLhalfNV blue); + void (APIENTRY *Color3hvNV) (const GLhalfNV *v); + void (APIENTRY *Color4hNV) (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha); + void (APIENTRY *Color4hvNV) (const GLhalfNV *v); + void (APIENTRY *TexCoord1hNV) (GLhalfNV s); + void (APIENTRY *TexCoord1hvNV) (const GLhalfNV *v); + void (APIENTRY *TexCoord2hNV) (GLhalfNV s, GLhalfNV t); + void (APIENTRY *TexCoord2hvNV) (const GLhalfNV *v); + void (APIENTRY *TexCoord3hNV) (GLhalfNV s, GLhalfNV t, GLhalfNV r); + void (APIENTRY *TexCoord3hvNV) (const GLhalfNV *v); + void (APIENTRY *TexCoord4hNV) (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q); + void (APIENTRY *TexCoord4hvNV) (const GLhalfNV *v); + void (APIENTRY *MultiTexCoord1hNV) (GLenum target, GLhalfNV s); + void (APIENTRY *MultiTexCoord1hvNV) (GLenum target, const GLhalfNV *v); + void (APIENTRY *MultiTexCoord2hNV) (GLenum target, GLhalfNV s, GLhalfNV t); + void (APIENTRY *MultiTexCoord2hvNV) (GLenum target, const GLhalfNV *v); + void (APIENTRY *MultiTexCoord3hNV) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r); + void (APIENTRY *MultiTexCoord3hvNV) (GLenum target, const GLhalfNV *v); + void (APIENTRY *MultiTexCoord4hNV) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q); + void (APIENTRY *MultiTexCoord4hvNV) (GLenum target, const GLhalfNV *v); + void (APIENTRY *FogCoordhNV) (GLhalfNV fog); + void (APIENTRY *FogCoordhvNV) (const GLhalfNV *fog); + void (APIENTRY *SecondaryColor3hNV) (GLhalfNV red, GLhalfNV green, GLhalfNV blue); + void (APIENTRY *SecondaryColor3hvNV) (const GLhalfNV *v); + void (APIENTRY *VertexWeighthNV) (GLhalfNV weight); + void (APIENTRY *VertexWeighthvNV) (const GLhalfNV *weight); + void (APIENTRY *VertexAttrib1hNV) (GLuint index, GLhalfNV x); + void (APIENTRY *VertexAttrib1hvNV) (GLuint index, const GLhalfNV *v); + void (APIENTRY *VertexAttrib2hNV) (GLuint index, GLhalfNV x, GLhalfNV y); + void (APIENTRY *VertexAttrib2hvNV) (GLuint index, const GLhalfNV *v); + void (APIENTRY *VertexAttrib3hNV) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z); + void (APIENTRY *VertexAttrib3hvNV) (GLuint index, const GLhalfNV *v); + void (APIENTRY *VertexAttrib4hNV) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w); + void (APIENTRY *VertexAttrib4hvNV) (GLuint index, const GLhalfNV *v); + void (APIENTRY *VertexAttribs1hvNV) (GLuint index, GLsizei n, const GLhalfNV *v); + void (APIENTRY *VertexAttribs2hvNV) (GLuint index, GLsizei n, const GLhalfNV *v); + void (APIENTRY *VertexAttribs3hvNV) (GLuint index, GLsizei n, const GLhalfNV *v); + void (APIENTRY *VertexAttribs4hvNV) (GLuint index, GLsizei n, const GLhalfNV *v); + void (APIENTRY *PixelDataRangeNV) (GLenum target, GLsizei length, GLvoid *pointer); + void (APIENTRY *FlushPixelDataRangeNV) (GLenum target); + void (APIENTRY *PrimitiveRestartNV) (void); + void (APIENTRY *PrimitiveRestartIndexNV) (GLuint index); + GLvoid* (APIENTRY *MapObjectBufferATI) (GLuint buffer); + void (APIENTRY *UnmapObjectBufferATI) (GLuint buffer); + void (APIENTRY *StencilOpSeparateATI) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); + void (APIENTRY *StencilFuncSeparateATI) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); + void (APIENTRY *VertexAttribArrayObjectATI) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset); + void (APIENTRY *GetVertexAttribArrayObjectfvATI) (GLuint index, GLenum pname, GLfloat *params); + void (APIENTRY *GetVertexAttribArrayObjectivATI) (GLuint index, GLenum pname, GLint *params); + void (APIENTRY *DepthBoundsEXT) (GLclampd zmin, GLclampd zmax); + void (APIENTRY *BlendEquationSeparateEXT) (GLenum modeRGB, GLenum modeAlpha); + void (APIENTRY *AddSwapHintRectWIN) (GLint x, GLint y, GLsizei width, GLsizei height); +#ifdef _WIN32 + HANDLE (WINAPI *CreateBufferRegionARB) (HDC hDC, int iLayerPlane, UINT uType); + VOID (WINAPI *DeleteBufferRegionARB) (HANDLE hRegion); + BOOL (WINAPI *SaveBufferRegionARB) (HANDLE hRegion, int x, int y, int width, int height); + BOOL (WINAPI *RestoreBufferRegionARB) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc); + const int (WINAPI *GetExtensionsStringARB) (HDC hdc); + BOOL (WINAPI *GetPixelFormatAttribivARB) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); + BOOL (WINAPI *GetPixelFormatAttribfvARB) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues); + BOOL (WINAPI *ChoosePixelFormatARB) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); + BOOL (WINAPI *MakeContextCurrentARB) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); + HDC (WINAPI *GetCurrentReadDCARB) (void); + HPBUFFERARB (WINAPI *CreatePbufferARB) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); + HDC (WINAPI *GetPbufferDCARB) (HPBUFFERARB hPbuffer); + int (WINAPI *ReleasePbufferDCARB) (HPBUFFERARB hPbuffer, HDC hDC); + BOOL (WINAPI *DestroyPbufferARB) (HPBUFFERARB hPbuffer); + BOOL (WINAPI *QueryPbufferARB) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue); + BOOL (WINAPI *BindTexImageARB) (HPBUFFERARB hPbuffer, int iBuffer); + BOOL (WINAPI *ReleaseTexImageARB) (HPBUFFERARB hPbuffer, int iBuffer); + BOOL (WINAPI *SetPbufferAttribARB) (HPBUFFERARB hPbuffer, const int *piAttribList); + GLboolean (WINAPI *CreateDisplayColorTableEXT) (GLushort id); + GLboolean (WINAPI *LoadDisplayColorTableEXT) (const GLushort *table, GLuint length); + GLboolean (WINAPI *BindDisplayColorTableEXT) (GLushort id); + VOID (WINAPI *DestroyDisplayColorTableEXT) (GLushort id); + const int (WINAPI *GetExtensionsStringEXT) (void); + BOOL (WINAPI *MakeContextCurrentEXT) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); + HDC (WINAPI *GetCurrentReadDCEXT) (void); + HPBUFFEREXT (WINAPI *CreatePbufferEXT) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); + HDC (WINAPI *GetPbufferDCEXT) (HPBUFFEREXT hPbuffer); + int (WINAPI *ReleasePbufferDCEXT) (HPBUFFEREXT hPbuffer, HDC hDC); + BOOL (WINAPI *DestroyPbufferEXT) (HPBUFFEREXT hPbuffer); + BOOL (WINAPI *QueryPbufferEXT) (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue); + BOOL (WINAPI *GetPixelFormatAttribivEXT) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues); + BOOL (WINAPI *GetPixelFormatAttribfvEXT) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues); + BOOL (WINAPI *ChoosePixelFormatEXT) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); + BOOL (WINAPI *SwapIntervalEXT) (int interval); + int (WINAPI *GetSwapIntervalEXT) (void); + void* (WINAPI *AllocateMemoryNV) (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority); + void (WINAPI *FreeMemoryNV) (void); + BOOL (WINAPI *GetSyncValuesOML) (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc); + BOOL (WINAPI *GetMscRateOML) (HDC hdc, INT32 *numerator, INT32 *denominator); + INT64 (WINAPI *SwapBuffersMscOML) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder); + INT64 (WINAPI *SwapLayerBuffersMscOML) (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder); + BOOL (WINAPI *WaitForMscOML) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc); + BOOL (WINAPI *WaitForSbcOML) (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc); + BOOL (WINAPI *GetDigitalVideoParametersI3D) (HDC hDC, int iAttribute, int *piValue); + BOOL (WINAPI *SetDigitalVideoParametersI3D) (HDC hDC, int iAttribute, const int *piValue); + BOOL (WINAPI *GetGammaTableParametersI3D) (HDC hDC, int iAttribute, int *piValue); + BOOL (WINAPI *SetGammaTableParametersI3D) (HDC hDC, int iAttribute, const int *piValue); + BOOL (WINAPI *GetGammaTableI3D) (HDC hDC, int iEntries, USHORT *puRed, USHORT *puGreen, USHORT *puBlue); + BOOL (WINAPI *SetGammaTableI3D) (HDC hDC, int iEntries, const USHORT *puRed, const USHORT *puGreen, const USHORT *puBlue); + BOOL (WINAPI *EnableGenlockI3D) (HDC hDC); + BOOL (WINAPI *DisableGenlockI3D) (HDC hDC); + BOOL (WINAPI *IsEnabledGenlockI3D) (HDC hDC, BOOL *pFlag); + BOOL (WINAPI *GenlockSourceI3D) (HDC hDC, UINT uSource); + BOOL (WINAPI *GetGenlockSourceI3D) (HDC hDC, UINT *uSource); + BOOL (WINAPI *GenlockSourceEdgeI3D) (HDC hDC, UINT uEdge); + BOOL (WINAPI *GetGenlockSourceEdgeI3D) (HDC hDC, UINT *uEdge); + BOOL (WINAPI *GenlockSampleRateI3D) (HDC hDC, UINT uRate); + BOOL (WINAPI *GetGenlockSampleRateI3D) (HDC hDC, UINT *uRate); + BOOL (WINAPI *GenlockSourceDelayI3D) (HDC hDC, UINT uDelay); + BOOL (WINAPI *GetGenlockSourceDelayI3D) (HDC hDC, UINT *uDelay); + BOOL (WINAPI *QueryGenlockMaxSourceDelayI3D) (HDC hDC, UINT *uMaxLineDelay, UINT *uMaxPixelDelay); + LPVOID (WINAPI *CreateImageBufferI3D) (HDC hDC, DWORD dwSize, UINT uFlags); + BOOL (WINAPI *DestroyImageBufferI3D) (HDC hDC, LPVOID pAddress); + BOOL (WINAPI *AssociateImageBufferEventsI3D) (HDC hDC, const HANDLE *pEvent, const LPVOID *pAddress, const DWORD *pSize, UINT count); + BOOL (WINAPI *ReleaseImageBufferEventsI3D) (HDC hDC, const LPVOID *pAddress, UINT count); + BOOL (WINAPI *EnableFrameLockI3D) (void); + BOOL (WINAPI *DisableFrameLockI3D) (void); + BOOL (WINAPI *IsEnabledFrameLockI3D) (BOOL *pFlag); + BOOL (WINAPI *QueryFrameLockMasterI3D) (BOOL *pFlag); + BOOL (WINAPI *GetFrameUsageI3D) (float *pUsage); + BOOL (WINAPI *BeginFrameTrackingI3D) (void); + BOOL (WINAPI *EndFrameTrackingI3D) (void); + BOOL (WINAPI *QueryFrameTrackingI3D) (DWORD *pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage); +#endif /* _WIN32 */ +} _GLextensionProcs; + +#define glBlendColor (_GET_TLS_PROCTABLE()->BlendColor) +#define glBlendEquation (_GET_TLS_PROCTABLE()->BlendEquation) +#define glDrawRangeElements (_GET_TLS_PROCTABLE()->DrawRangeElements) +#define glColorTable (_GET_TLS_PROCTABLE()->ColorTable) +#define glColorTableParameterfv (_GET_TLS_PROCTABLE()->ColorTableParameterfv) +#define glColorTableParameteriv (_GET_TLS_PROCTABLE()->ColorTableParameteriv) +#define glCopyColorTable (_GET_TLS_PROCTABLE()->CopyColorTable) +#define glGetColorTable (_GET_TLS_PROCTABLE()->GetColorTable) +#define glGetColorTableParameterfv (_GET_TLS_PROCTABLE()->GetColorTableParameterfv) +#define glGetColorTableParameteriv (_GET_TLS_PROCTABLE()->GetColorTableParameteriv) +#define glColorSubTable (_GET_TLS_PROCTABLE()->ColorSubTable) +#define glCopyColorSubTable (_GET_TLS_PROCTABLE()->CopyColorSubTable) +#define glConvolutionFilter1D (_GET_TLS_PROCTABLE()->ConvolutionFilter1D) +#define glConvolutionFilter2D (_GET_TLS_PROCTABLE()->ConvolutionFilter2D) +#define glConvolutionParameterf (_GET_TLS_PROCTABLE()->ConvolutionParameterf) +#define glConvolutionParameterfv (_GET_TLS_PROCTABLE()->ConvolutionParameterfv) +#define glConvolutionParameteri (_GET_TLS_PROCTABLE()->ConvolutionParameteri) +#define glConvolutionParameteriv (_GET_TLS_PROCTABLE()->ConvolutionParameteriv) +#define glCopyConvolutionFilter1D (_GET_TLS_PROCTABLE()->CopyConvolutionFilter1D) +#define glCopyConvolutionFilter2D (_GET_TLS_PROCTABLE()->CopyConvolutionFilter2D) +#define glGetConvolutionFilter (_GET_TLS_PROCTABLE()->GetConvolutionFilter) +#define glGetConvolutionParameterfv (_GET_TLS_PROCTABLE()->GetConvolutionParameterfv) +#define glGetConvolutionParameteriv (_GET_TLS_PROCTABLE()->GetConvolutionParameteriv) +#define glGetSeparableFilter (_GET_TLS_PROCTABLE()->GetSeparableFilter) +#define glSeparableFilter2D (_GET_TLS_PROCTABLE()->SeparableFilter2D) +#define glGetHistogram (_GET_TLS_PROCTABLE()->GetHistogram) +#define glGetHistogramParameterfv (_GET_TLS_PROCTABLE()->GetHistogramParameterfv) +#define glGetHistogramParameteriv (_GET_TLS_PROCTABLE()->GetHistogramParameteriv) +#define glGetMinmax (_GET_TLS_PROCTABLE()->GetMinmax) +#define glGetMinmaxParameterfv (_GET_TLS_PROCTABLE()->GetMinmaxParameterfv) +#define glGetMinmaxParameteriv (_GET_TLS_PROCTABLE()->GetMinmaxParameteriv) +#define glHistogram (_GET_TLS_PROCTABLE()->Histogram) +#define glMinmax (_GET_TLS_PROCTABLE()->Minmax) +#define glResetHistogram (_GET_TLS_PROCTABLE()->ResetHistogram) +#define glResetMinmax (_GET_TLS_PROCTABLE()->ResetMinmax) +#define glTexImage3D (_GET_TLS_PROCTABLE()->TexImage3D) +#define glTexSubImage3D (_GET_TLS_PROCTABLE()->TexSubImage3D) +#define glCopyTexSubImage3D (_GET_TLS_PROCTABLE()->CopyTexSubImage3D) +#define glActiveTexture (_GET_TLS_PROCTABLE()->ActiveTexture) +#define glClientActiveTexture (_GET_TLS_PROCTABLE()->ClientActiveTexture) +#define glMultiTexCoord1d (_GET_TLS_PROCTABLE()->MultiTexCoord1d) +#define glMultiTexCoord1dv (_GET_TLS_PROCTABLE()->MultiTexCoord1dv) +#define glMultiTexCoord1f (_GET_TLS_PROCTABLE()->MultiTexCoord1f) +#define glMultiTexCoord1fv (_GET_TLS_PROCTABLE()->MultiTexCoord1fv) +#define glMultiTexCoord1i (_GET_TLS_PROCTABLE()->MultiTexCoord1i) +#define glMultiTexCoord1iv (_GET_TLS_PROCTABLE()->MultiTexCoord1iv) +#define glMultiTexCoord1s (_GET_TLS_PROCTABLE()->MultiTexCoord1s) +#define glMultiTexCoord1sv (_GET_TLS_PROCTABLE()->MultiTexCoord1sv) +#define glMultiTexCoord2d (_GET_TLS_PROCTABLE()->MultiTexCoord2d) +#define glMultiTexCoord2dv (_GET_TLS_PROCTABLE()->MultiTexCoord2dv) +#define glMultiTexCoord2f (_GET_TLS_PROCTABLE()->MultiTexCoord2f) +#define glMultiTexCoord2fv (_GET_TLS_PROCTABLE()->MultiTexCoord2fv) +#define glMultiTexCoord2i (_GET_TLS_PROCTABLE()->MultiTexCoord2i) +#define glMultiTexCoord2iv (_GET_TLS_PROCTABLE()->MultiTexCoord2iv) +#define glMultiTexCoord2s (_GET_TLS_PROCTABLE()->MultiTexCoord2s) +#define glMultiTexCoord2sv (_GET_TLS_PROCTABLE()->MultiTexCoord2sv) +#define glMultiTexCoord3d (_GET_TLS_PROCTABLE()->MultiTexCoord3d) +#define glMultiTexCoord3dv (_GET_TLS_PROCTABLE()->MultiTexCoord3dv) +#define glMultiTexCoord3f (_GET_TLS_PROCTABLE()->MultiTexCoord3f) +#define glMultiTexCoord3fv (_GET_TLS_PROCTABLE()->MultiTexCoord3fv) +#define glMultiTexCoord3i (_GET_TLS_PROCTABLE()->MultiTexCoord3i) +#define glMultiTexCoord3iv (_GET_TLS_PROCTABLE()->MultiTexCoord3iv) +#define glMultiTexCoord3s (_GET_TLS_PROCTABLE()->MultiTexCoord3s) +#define glMultiTexCoord3sv (_GET_TLS_PROCTABLE()->MultiTexCoord3sv) +#define glMultiTexCoord4d (_GET_TLS_PROCTABLE()->MultiTexCoord4d) +#define glMultiTexCoord4dv (_GET_TLS_PROCTABLE()->MultiTexCoord4dv) +#define glMultiTexCoord4f (_GET_TLS_PROCTABLE()->MultiTexCoord4f) +#define glMultiTexCoord4fv (_GET_TLS_PROCTABLE()->MultiTexCoord4fv) +#define glMultiTexCoord4i (_GET_TLS_PROCTABLE()->MultiTexCoord4i) +#define glMultiTexCoord4iv (_GET_TLS_PROCTABLE()->MultiTexCoord4iv) +#define glMultiTexCoord4s (_GET_TLS_PROCTABLE()->MultiTexCoord4s) +#define glMultiTexCoord4sv (_GET_TLS_PROCTABLE()->MultiTexCoord4sv) +#define glLoadTransposeMatrixf (_GET_TLS_PROCTABLE()->LoadTransposeMatrixf) +#define glLoadTransposeMatrixd (_GET_TLS_PROCTABLE()->LoadTransposeMatrixd) +#define glMultTransposeMatrixf (_GET_TLS_PROCTABLE()->MultTransposeMatrixf) +#define glMultTransposeMatrixd (_GET_TLS_PROCTABLE()->MultTransposeMatrixd) +#define glSampleCoverage (_GET_TLS_PROCTABLE()->SampleCoverage) +#define glCompressedTexImage3D (_GET_TLS_PROCTABLE()->CompressedTexImage3D) +#define glCompressedTexImage2D (_GET_TLS_PROCTABLE()->CompressedTexImage2D) +#define glCompressedTexImage1D (_GET_TLS_PROCTABLE()->CompressedTexImage1D) +#define glCompressedTexSubImage3D (_GET_TLS_PROCTABLE()->CompressedTexSubImage3D) +#define glCompressedTexSubImage2D (_GET_TLS_PROCTABLE()->CompressedTexSubImage2D) +#define glCompressedTexSubImage1D (_GET_TLS_PROCTABLE()->CompressedTexSubImage1D) +#define glGetCompressedTexImage (_GET_TLS_PROCTABLE()->GetCompressedTexImage) +#define glBlendFuncSeparate (_GET_TLS_PROCTABLE()->BlendFuncSeparate) +#define glFogCoordf (_GET_TLS_PROCTABLE()->FogCoordf) +#define glFogCoordfv (_GET_TLS_PROCTABLE()->FogCoordfv) +#define glFogCoordd (_GET_TLS_PROCTABLE()->FogCoordd) +#define glFogCoorddv (_GET_TLS_PROCTABLE()->FogCoorddv) +#define glFogCoordPointer (_GET_TLS_PROCTABLE()->FogCoordPointer) +#define glMultiDrawArrays (_GET_TLS_PROCTABLE()->MultiDrawArrays) +#define glMultiDrawElements (_GET_TLS_PROCTABLE()->MultiDrawElements) +#define glPointParameterf (_GET_TLS_PROCTABLE()->PointParameterf) +#define glPointParameterfv (_GET_TLS_PROCTABLE()->PointParameterfv) +#define glPointParameteri (_GET_TLS_PROCTABLE()->PointParameteri) +#define glPointParameteriv (_GET_TLS_PROCTABLE()->PointParameteriv) +#define glSecondaryColor3b (_GET_TLS_PROCTABLE()->SecondaryColor3b) +#define glSecondaryColor3bv (_GET_TLS_PROCTABLE()->SecondaryColor3bv) +#define glSecondaryColor3d (_GET_TLS_PROCTABLE()->SecondaryColor3d) +#define glSecondaryColor3dv (_GET_TLS_PROCTABLE()->SecondaryColor3dv) +#define glSecondaryColor3f (_GET_TLS_PROCTABLE()->SecondaryColor3f) +#define glSecondaryColor3fv (_GET_TLS_PROCTABLE()->SecondaryColor3fv) +#define glSecondaryColor3i (_GET_TLS_PROCTABLE()->SecondaryColor3i) +#define glSecondaryColor3iv (_GET_TLS_PROCTABLE()->SecondaryColor3iv) +#define glSecondaryColor3s (_GET_TLS_PROCTABLE()->SecondaryColor3s) +#define glSecondaryColor3sv (_GET_TLS_PROCTABLE()->SecondaryColor3sv) +#define glSecondaryColor3ub (_GET_TLS_PROCTABLE()->SecondaryColor3ub) +#define glSecondaryColor3ubv (_GET_TLS_PROCTABLE()->SecondaryColor3ubv) +#define glSecondaryColor3ui (_GET_TLS_PROCTABLE()->SecondaryColor3ui) +#define glSecondaryColor3uiv (_GET_TLS_PROCTABLE()->SecondaryColor3uiv) +#define glSecondaryColor3us (_GET_TLS_PROCTABLE()->SecondaryColor3us) +#define glSecondaryColor3usv (_GET_TLS_PROCTABLE()->SecondaryColor3usv) +#define glSecondaryColorPointer (_GET_TLS_PROCTABLE()->SecondaryColorPointer) +#define glWindowPos2d (_GET_TLS_PROCTABLE()->WindowPos2d) +#define glWindowPos2dv (_GET_TLS_PROCTABLE()->WindowPos2dv) +#define glWindowPos2f (_GET_TLS_PROCTABLE()->WindowPos2f) +#define glWindowPos2fv (_GET_TLS_PROCTABLE()->WindowPos2fv) +#define glWindowPos2i (_GET_TLS_PROCTABLE()->WindowPos2i) +#define glWindowPos2iv (_GET_TLS_PROCTABLE()->WindowPos2iv) +#define glWindowPos2s (_GET_TLS_PROCTABLE()->WindowPos2s) +#define glWindowPos2sv (_GET_TLS_PROCTABLE()->WindowPos2sv) +#define glWindowPos3d (_GET_TLS_PROCTABLE()->WindowPos3d) +#define glWindowPos3dv (_GET_TLS_PROCTABLE()->WindowPos3dv) +#define glWindowPos3f (_GET_TLS_PROCTABLE()->WindowPos3f) +#define glWindowPos3fv (_GET_TLS_PROCTABLE()->WindowPos3fv) +#define glWindowPos3i (_GET_TLS_PROCTABLE()->WindowPos3i) +#define glWindowPos3iv (_GET_TLS_PROCTABLE()->WindowPos3iv) +#define glWindowPos3s (_GET_TLS_PROCTABLE()->WindowPos3s) +#define glWindowPos3sv (_GET_TLS_PROCTABLE()->WindowPos3sv) +#define glGenQueries (_GET_TLS_PROCTABLE()->GenQueries) +#define glDeleteQueries (_GET_TLS_PROCTABLE()->DeleteQueries) +#define glIsQuery (_GET_TLS_PROCTABLE()->IsQuery) +#define glBeginQuery (_GET_TLS_PROCTABLE()->BeginQuery) +#define glEndQuery (_GET_TLS_PROCTABLE()->EndQuery) +#define glGetQueryiv (_GET_TLS_PROCTABLE()->GetQueryiv) +#define glGetQueryObjectiv (_GET_TLS_PROCTABLE()->GetQueryObjectiv) +#define glGetQueryObjectuiv (_GET_TLS_PROCTABLE()->GetQueryObjectuiv) +#define glBindBuffer (_GET_TLS_PROCTABLE()->BindBuffer) +#define glDeleteBuffers (_GET_TLS_PROCTABLE()->DeleteBuffers) +#define glGenBuffers (_GET_TLS_PROCTABLE()->GenBuffers) +#define glIsBuffer (_GET_TLS_PROCTABLE()->IsBuffer) +#define glBufferData (_GET_TLS_PROCTABLE()->BufferData) +#define glBufferSubData (_GET_TLS_PROCTABLE()->BufferSubData) +#define glGetBufferSubData (_GET_TLS_PROCTABLE()->GetBufferSubData) +#define glMapBuffer (_GET_TLS_PROCTABLE()->MapBuffer) +#define glUnmapBuffer (_GET_TLS_PROCTABLE()->UnmapBuffer) +#define glGetBufferParameteriv (_GET_TLS_PROCTABLE()->GetBufferParameteriv) +#define glGetBufferPointerv (_GET_TLS_PROCTABLE()->GetBufferPointerv) +#define glActiveTextureARB (_GET_TLS_PROCTABLE()->ActiveTextureARB) +#define glClientActiveTextureARB (_GET_TLS_PROCTABLE()->ClientActiveTextureARB) +#define glMultiTexCoord1dARB (_GET_TLS_PROCTABLE()->MultiTexCoord1dARB) +#define glMultiTexCoord1dvARB (_GET_TLS_PROCTABLE()->MultiTexCoord1dvARB) +#define glMultiTexCoord1fARB (_GET_TLS_PROCTABLE()->MultiTexCoord1fARB) +#define glMultiTexCoord1fvARB (_GET_TLS_PROCTABLE()->MultiTexCoord1fvARB) +#define glMultiTexCoord1iARB (_GET_TLS_PROCTABLE()->MultiTexCoord1iARB) +#define glMultiTexCoord1ivARB (_GET_TLS_PROCTABLE()->MultiTexCoord1ivARB) +#define glMultiTexCoord1sARB (_GET_TLS_PROCTABLE()->MultiTexCoord1sARB) +#define glMultiTexCoord1svARB (_GET_TLS_PROCTABLE()->MultiTexCoord1svARB) +#define glMultiTexCoord2dARB (_GET_TLS_PROCTABLE()->MultiTexCoord2dARB) +#define glMultiTexCoord2dvARB (_GET_TLS_PROCTABLE()->MultiTexCoord2dvARB) +#define glMultiTexCoord2fARB (_GET_TLS_PROCTABLE()->MultiTexCoord2fARB) +#define glMultiTexCoord2fvARB (_GET_TLS_PROCTABLE()->MultiTexCoord2fvARB) +#define glMultiTexCoord2iARB (_GET_TLS_PROCTABLE()->MultiTexCoord2iARB) +#define glMultiTexCoord2ivARB (_GET_TLS_PROCTABLE()->MultiTexCoord2ivARB) +#define glMultiTexCoord2sARB (_GET_TLS_PROCTABLE()->MultiTexCoord2sARB) +#define glMultiTexCoord2svARB (_GET_TLS_PROCTABLE()->MultiTexCoord2svARB) +#define glMultiTexCoord3dARB (_GET_TLS_PROCTABLE()->MultiTexCoord3dARB) +#define glMultiTexCoord3dvARB (_GET_TLS_PROCTABLE()->MultiTexCoord3dvARB) +#define glMultiTexCoord3fARB (_GET_TLS_PROCTABLE()->MultiTexCoord3fARB) +#define glMultiTexCoord3fvARB (_GET_TLS_PROCTABLE()->MultiTexCoord3fvARB) +#define glMultiTexCoord3iARB (_GET_TLS_PROCTABLE()->MultiTexCoord3iARB) +#define glMultiTexCoord3ivARB (_GET_TLS_PROCTABLE()->MultiTexCoord3ivARB) +#define glMultiTexCoord3sARB (_GET_TLS_PROCTABLE()->MultiTexCoord3sARB) +#define glMultiTexCoord3svARB (_GET_TLS_PROCTABLE()->MultiTexCoord3svARB) +#define glMultiTexCoord4dARB (_GET_TLS_PROCTABLE()->MultiTexCoord4dARB) +#define glMultiTexCoord4dvARB (_GET_TLS_PROCTABLE()->MultiTexCoord4dvARB) +#define glMultiTexCoord4fARB (_GET_TLS_PROCTABLE()->MultiTexCoord4fARB) +#define glMultiTexCoord4fvARB (_GET_TLS_PROCTABLE()->MultiTexCoord4fvARB) +#define glMultiTexCoord4iARB (_GET_TLS_PROCTABLE()->MultiTexCoord4iARB) +#define glMultiTexCoord4ivARB (_GET_TLS_PROCTABLE()->MultiTexCoord4ivARB) +#define glMultiTexCoord4sARB (_GET_TLS_PROCTABLE()->MultiTexCoord4sARB) +#define glMultiTexCoord4svARB (_GET_TLS_PROCTABLE()->MultiTexCoord4svARB) +#define glLoadTransposeMatrixfARB (_GET_TLS_PROCTABLE()->LoadTransposeMatrixfARB) +#define glLoadTransposeMatrixdARB (_GET_TLS_PROCTABLE()->LoadTransposeMatrixdARB) +#define glMultTransposeMatrixfARB (_GET_TLS_PROCTABLE()->MultTransposeMatrixfARB) +#define glMultTransposeMatrixdARB (_GET_TLS_PROCTABLE()->MultTransposeMatrixdARB) +#define glSampleCoverageARB (_GET_TLS_PROCTABLE()->SampleCoverageARB) +#define glCompressedTexImage3DARB (_GET_TLS_PROCTABLE()->CompressedTexImage3DARB) +#define glCompressedTexImage2DARB (_GET_TLS_PROCTABLE()->CompressedTexImage2DARB) +#define glCompressedTexImage1DARB (_GET_TLS_PROCTABLE()->CompressedTexImage1DARB) +#define glCompressedTexSubImage3DARB (_GET_TLS_PROCTABLE()->CompressedTexSubImage3DARB) +#define glCompressedTexSubImage2DARB (_GET_TLS_PROCTABLE()->CompressedTexSubImage2DARB) +#define glCompressedTexSubImage1DARB (_GET_TLS_PROCTABLE()->CompressedTexSubImage1DARB) +#define glGetCompressedTexImageARB (_GET_TLS_PROCTABLE()->GetCompressedTexImageARB) +#define glPointParameterfARB (_GET_TLS_PROCTABLE()->PointParameterfARB) +#define glPointParameterfvARB (_GET_TLS_PROCTABLE()->PointParameterfvARB) +#define glWeightbvARB (_GET_TLS_PROCTABLE()->WeightbvARB) +#define glWeightsvARB (_GET_TLS_PROCTABLE()->WeightsvARB) +#define glWeightivARB (_GET_TLS_PROCTABLE()->WeightivARB) +#define glWeightfvARB (_GET_TLS_PROCTABLE()->WeightfvARB) +#define glWeightdvARB (_GET_TLS_PROCTABLE()->WeightdvARB) +#define glWeightubvARB (_GET_TLS_PROCTABLE()->WeightubvARB) +#define glWeightusvARB (_GET_TLS_PROCTABLE()->WeightusvARB) +#define glWeightuivARB (_GET_TLS_PROCTABLE()->WeightuivARB) +#define glWeightPointerARB (_GET_TLS_PROCTABLE()->WeightPointerARB) +#define glVertexBlendARB (_GET_TLS_PROCTABLE()->VertexBlendARB) +#define glCurrentPaletteMatrixARB (_GET_TLS_PROCTABLE()->CurrentPaletteMatrixARB) +#define glMatrixIndexubvARB (_GET_TLS_PROCTABLE()->MatrixIndexubvARB) +#define glMatrixIndexusvARB (_GET_TLS_PROCTABLE()->MatrixIndexusvARB) +#define glMatrixIndexuivARB (_GET_TLS_PROCTABLE()->MatrixIndexuivARB) +#define glMatrixIndexPointerARB (_GET_TLS_PROCTABLE()->MatrixIndexPointerARB) +#define glWindowPos2dARB (_GET_TLS_PROCTABLE()->WindowPos2dARB) +#define glWindowPos2dvARB (_GET_TLS_PROCTABLE()->WindowPos2dvARB) +#define glWindowPos2fARB (_GET_TLS_PROCTABLE()->WindowPos2fARB) +#define glWindowPos2fvARB (_GET_TLS_PROCTABLE()->WindowPos2fvARB) +#define glWindowPos2iARB (_GET_TLS_PROCTABLE()->WindowPos2iARB) +#define glWindowPos2ivARB (_GET_TLS_PROCTABLE()->WindowPos2ivARB) +#define glWindowPos2sARB (_GET_TLS_PROCTABLE()->WindowPos2sARB) +#define glWindowPos2svARB (_GET_TLS_PROCTABLE()->WindowPos2svARB) +#define glWindowPos3dARB (_GET_TLS_PROCTABLE()->WindowPos3dARB) +#define glWindowPos3dvARB (_GET_TLS_PROCTABLE()->WindowPos3dvARB) +#define glWindowPos3fARB (_GET_TLS_PROCTABLE()->WindowPos3fARB) +#define glWindowPos3fvARB (_GET_TLS_PROCTABLE()->WindowPos3fvARB) +#define glWindowPos3iARB (_GET_TLS_PROCTABLE()->WindowPos3iARB) +#define glWindowPos3ivARB (_GET_TLS_PROCTABLE()->WindowPos3ivARB) +#define glWindowPos3sARB (_GET_TLS_PROCTABLE()->WindowPos3sARB) +#define glWindowPos3svARB (_GET_TLS_PROCTABLE()->WindowPos3svARB) +#define glVertexAttrib1dARB (_GET_TLS_PROCTABLE()->VertexAttrib1dARB) +#define glVertexAttrib1dvARB (_GET_TLS_PROCTABLE()->VertexAttrib1dvARB) +#define glVertexAttrib1fARB (_GET_TLS_PROCTABLE()->VertexAttrib1fARB) +#define glVertexAttrib1fvARB (_GET_TLS_PROCTABLE()->VertexAttrib1fvARB) +#define glVertexAttrib1sARB (_GET_TLS_PROCTABLE()->VertexAttrib1sARB) +#define glVertexAttrib1svARB (_GET_TLS_PROCTABLE()->VertexAttrib1svARB) +#define glVertexAttrib2dARB (_GET_TLS_PROCTABLE()->VertexAttrib2dARB) +#define glVertexAttrib2dvARB (_GET_TLS_PROCTABLE()->VertexAttrib2dvARB) +#define glVertexAttrib2fARB (_GET_TLS_PROCTABLE()->VertexAttrib2fARB) +#define glVertexAttrib2fvARB (_GET_TLS_PROCTABLE()->VertexAttrib2fvARB) +#define glVertexAttrib2sARB (_GET_TLS_PROCTABLE()->VertexAttrib2sARB) +#define glVertexAttrib2svARB (_GET_TLS_PROCTABLE()->VertexAttrib2svARB) +#define glVertexAttrib3dARB (_GET_TLS_PROCTABLE()->VertexAttrib3dARB) +#define glVertexAttrib3dvARB (_GET_TLS_PROCTABLE()->VertexAttrib3dvARB) +#define glVertexAttrib3fARB (_GET_TLS_PROCTABLE()->VertexAttrib3fARB) +#define glVertexAttrib3fvARB (_GET_TLS_PROCTABLE()->VertexAttrib3fvARB) +#define glVertexAttrib3sARB (_GET_TLS_PROCTABLE()->VertexAttrib3sARB) +#define glVertexAttrib3svARB (_GET_TLS_PROCTABLE()->VertexAttrib3svARB) +#define glVertexAttrib4NbvARB (_GET_TLS_PROCTABLE()->VertexAttrib4NbvARB) +#define glVertexAttrib4NivARB (_GET_TLS_PROCTABLE()->VertexAttrib4NivARB) +#define glVertexAttrib4NsvARB (_GET_TLS_PROCTABLE()->VertexAttrib4NsvARB) +#define glVertexAttrib4NubARB (_GET_TLS_PROCTABLE()->VertexAttrib4NubARB) +#define glVertexAttrib4NubvARB (_GET_TLS_PROCTABLE()->VertexAttrib4NubvARB) +#define glVertexAttrib4NuivARB (_GET_TLS_PROCTABLE()->VertexAttrib4NuivARB) +#define glVertexAttrib4NusvARB (_GET_TLS_PROCTABLE()->VertexAttrib4NusvARB) +#define glVertexAttrib4bvARB (_GET_TLS_PROCTABLE()->VertexAttrib4bvARB) +#define glVertexAttrib4dARB (_GET_TLS_PROCTABLE()->VertexAttrib4dARB) +#define glVertexAttrib4dvARB (_GET_TLS_PROCTABLE()->VertexAttrib4dvARB) +#define glVertexAttrib4fARB (_GET_TLS_PROCTABLE()->VertexAttrib4fARB) +#define glVertexAttrib4fvARB (_GET_TLS_PROCTABLE()->VertexAttrib4fvARB) +#define glVertexAttrib4ivARB (_GET_TLS_PROCTABLE()->VertexAttrib4ivARB) +#define glVertexAttrib4sARB (_GET_TLS_PROCTABLE()->VertexAttrib4sARB) +#define glVertexAttrib4svARB (_GET_TLS_PROCTABLE()->VertexAttrib4svARB) +#define glVertexAttrib4ubvARB (_GET_TLS_PROCTABLE()->VertexAttrib4ubvARB) +#define glVertexAttrib4uivARB (_GET_TLS_PROCTABLE()->VertexAttrib4uivARB) +#define glVertexAttrib4usvARB (_GET_TLS_PROCTABLE()->VertexAttrib4usvARB) +#define glVertexAttribPointerARB (_GET_TLS_PROCTABLE()->VertexAttribPointerARB) +#define glEnableVertexAttribArrayARB (_GET_TLS_PROCTABLE()->EnableVertexAttribArrayARB) +#define glDisableVertexAttribArrayARB (_GET_TLS_PROCTABLE()->DisableVertexAttribArrayARB) +#define glProgramStringARB (_GET_TLS_PROCTABLE()->ProgramStringARB) +#define glBindProgramARB (_GET_TLS_PROCTABLE()->BindProgramARB) +#define glDeleteProgramsARB (_GET_TLS_PROCTABLE()->DeleteProgramsARB) +#define glGenProgramsARB (_GET_TLS_PROCTABLE()->GenProgramsARB) +#define glProgramEnvParameter4dARB (_GET_TLS_PROCTABLE()->ProgramEnvParameter4dARB) +#define glProgramEnvParameter4dvARB (_GET_TLS_PROCTABLE()->ProgramEnvParameter4dvARB) +#define glProgramEnvParameter4fARB (_GET_TLS_PROCTABLE()->ProgramEnvParameter4fARB) +#define glProgramEnvParameter4fvARB (_GET_TLS_PROCTABLE()->ProgramEnvParameter4fvARB) +#define glProgramLocalParameter4dARB (_GET_TLS_PROCTABLE()->ProgramLocalParameter4dARB) +#define glProgramLocalParameter4dvARB (_GET_TLS_PROCTABLE()->ProgramLocalParameter4dvARB) +#define glProgramLocalParameter4fARB (_GET_TLS_PROCTABLE()->ProgramLocalParameter4fARB) +#define glProgramLocalParameter4fvARB (_GET_TLS_PROCTABLE()->ProgramLocalParameter4fvARB) +#define glGetProgramEnvParameterdvARB (_GET_TLS_PROCTABLE()->GetProgramEnvParameterdvARB) +#define glGetProgramEnvParameterfvARB (_GET_TLS_PROCTABLE()->GetProgramEnvParameterfvARB) +#define glGetProgramLocalParameterdvARB (_GET_TLS_PROCTABLE()->GetProgramLocalParameterdvARB) +#define glGetProgramLocalParameterfvARB (_GET_TLS_PROCTABLE()->GetProgramLocalParameterfvARB) +#define glGetProgramivARB (_GET_TLS_PROCTABLE()->GetProgramivARB) +#define glGetProgramStringARB (_GET_TLS_PROCTABLE()->GetProgramStringARB) +#define glGetVertexAttribdvARB (_GET_TLS_PROCTABLE()->GetVertexAttribdvARB) +#define glGetVertexAttribfvARB (_GET_TLS_PROCTABLE()->GetVertexAttribfvARB) +#define glGetVertexAttribivARB (_GET_TLS_PROCTABLE()->GetVertexAttribivARB) +#define glGetVertexAttribPointervARB (_GET_TLS_PROCTABLE()->GetVertexAttribPointervARB) +#define glIsProgramARB (_GET_TLS_PROCTABLE()->IsProgramARB) +#define glBindBufferARB (_GET_TLS_PROCTABLE()->BindBufferARB) +#define glDeleteBuffersARB (_GET_TLS_PROCTABLE()->DeleteBuffersARB) +#define glGenBuffersARB (_GET_TLS_PROCTABLE()->GenBuffersARB) +#define glIsBufferARB (_GET_TLS_PROCTABLE()->IsBufferARB) +#define glBufferDataARB (_GET_TLS_PROCTABLE()->BufferDataARB) +#define glBufferSubDataARB (_GET_TLS_PROCTABLE()->BufferSubDataARB) +#define glGetBufferSubDataARB (_GET_TLS_PROCTABLE()->GetBufferSubDataARB) +#define glMapBufferARB (_GET_TLS_PROCTABLE()->MapBufferARB) +#define glUnmapBufferARB (_GET_TLS_PROCTABLE()->UnmapBufferARB) +#define glGetBufferParameterivARB (_GET_TLS_PROCTABLE()->GetBufferParameterivARB) +#define glGetBufferPointervARB (_GET_TLS_PROCTABLE()->GetBufferPointervARB) +#define glGenQueriesARB (_GET_TLS_PROCTABLE()->GenQueriesARB) +#define glDeleteQueriesARB (_GET_TLS_PROCTABLE()->DeleteQueriesARB) +#define glIsQueryARB (_GET_TLS_PROCTABLE()->IsQueryARB) +#define glBeginQueryARB (_GET_TLS_PROCTABLE()->BeginQueryARB) +#define glEndQueryARB (_GET_TLS_PROCTABLE()->EndQueryARB) +#define glGetQueryivARB (_GET_TLS_PROCTABLE()->GetQueryivARB) +#define glGetQueryObjectivARB (_GET_TLS_PROCTABLE()->GetQueryObjectivARB) +#define glGetQueryObjectuivARB (_GET_TLS_PROCTABLE()->GetQueryObjectuivARB) +#define glDeleteObjectARB (_GET_TLS_PROCTABLE()->DeleteObjectARB) +#define glGetHandleARB (_GET_TLS_PROCTABLE()->GetHandleARB) +#define glDetachObjectARB (_GET_TLS_PROCTABLE()->DetachObjectARB) +#define glCreateShaderObjectARB (_GET_TLS_PROCTABLE()->CreateShaderObjectARB) +#define glShaderSourceARB (_GET_TLS_PROCTABLE()->ShaderSourceARB) +#define glCompileShaderARB (_GET_TLS_PROCTABLE()->CompileShaderARB) +#define glCreateProgramObjectARB (_GET_TLS_PROCTABLE()->CreateProgramObjectARB) +#define glAttachObjectARB (_GET_TLS_PROCTABLE()->AttachObjectARB) +#define glLinkProgramARB (_GET_TLS_PROCTABLE()->LinkProgramARB) +#define glUseProgramObjectARB (_GET_TLS_PROCTABLE()->UseProgramObjectARB) +#define glValidateProgramARB (_GET_TLS_PROCTABLE()->ValidateProgramARB) +#define glUniform1fARB (_GET_TLS_PROCTABLE()->Uniform1fARB) +#define glUniform2fARB (_GET_TLS_PROCTABLE()->Uniform2fARB) +#define glUniform3fARB (_GET_TLS_PROCTABLE()->Uniform3fARB) +#define glUniform4fARB (_GET_TLS_PROCTABLE()->Uniform4fARB) +#define glUniform1iARB (_GET_TLS_PROCTABLE()->Uniform1iARB) +#define glUniform2iARB (_GET_TLS_PROCTABLE()->Uniform2iARB) +#define glUniform3iARB (_GET_TLS_PROCTABLE()->Uniform3iARB) +#define glUniform4iARB (_GET_TLS_PROCTABLE()->Uniform4iARB) +#define glUniform1fvARB (_GET_TLS_PROCTABLE()->Uniform1fvARB) +#define glUniform2fvARB (_GET_TLS_PROCTABLE()->Uniform2fvARB) +#define glUniform3fvARB (_GET_TLS_PROCTABLE()->Uniform3fvARB) +#define glUniform4fvARB (_GET_TLS_PROCTABLE()->Uniform4fvARB) +#define glUniform1ivARB (_GET_TLS_PROCTABLE()->Uniform1ivARB) +#define glUniform2ivARB (_GET_TLS_PROCTABLE()->Uniform2ivARB) +#define glUniform3ivARB (_GET_TLS_PROCTABLE()->Uniform3ivARB) +#define glUniform4ivARB (_GET_TLS_PROCTABLE()->Uniform4ivARB) +#define glUniformMatrix2fvARB (_GET_TLS_PROCTABLE()->UniformMatrix2fvARB) +#define glUniformMatrix3fvARB (_GET_TLS_PROCTABLE()->UniformMatrix3fvARB) +#define glUniformMatrix4fvARB (_GET_TLS_PROCTABLE()->UniformMatrix4fvARB) +#define glGetObjectParameterfvARB (_GET_TLS_PROCTABLE()->GetObjectParameterfvARB) +#define glGetObjectParameterivARB (_GET_TLS_PROCTABLE()->GetObjectParameterivARB) +#define glGetInfoLogARB (_GET_TLS_PROCTABLE()->GetInfoLogARB) +#define glGetAttachedObjectsARB (_GET_TLS_PROCTABLE()->GetAttachedObjectsARB) +#define glGetUniformLocationARB (_GET_TLS_PROCTABLE()->GetUniformLocationARB) +#define glGetActiveUniformARB (_GET_TLS_PROCTABLE()->GetActiveUniformARB) +#define glGetUniformfvARB (_GET_TLS_PROCTABLE()->GetUniformfvARB) +#define glGetUniformivARB (_GET_TLS_PROCTABLE()->GetUniformivARB) +#define glGetShaderSourceARB (_GET_TLS_PROCTABLE()->GetShaderSourceARB) +#define glBindAttribLocationARB (_GET_TLS_PROCTABLE()->BindAttribLocationARB) +#define glGetActiveAttribARB (_GET_TLS_PROCTABLE()->GetActiveAttribARB) +#define glGetAttribLocationARB (_GET_TLS_PROCTABLE()->GetAttribLocationARB) +#define glBlendColorEXT (_GET_TLS_PROCTABLE()->BlendColorEXT) +#define glPolygonOffsetEXT (_GET_TLS_PROCTABLE()->PolygonOffsetEXT) +#define glTexImage3DEXT (_GET_TLS_PROCTABLE()->TexImage3DEXT) +#define glTexSubImage3DEXT (_GET_TLS_PROCTABLE()->TexSubImage3DEXT) +#define glGetTexFilterFuncSGIS (_GET_TLS_PROCTABLE()->GetTexFilterFuncSGIS) +#define glTexFilterFuncSGIS (_GET_TLS_PROCTABLE()->TexFilterFuncSGIS) +#define glTexSubImage1DEXT (_GET_TLS_PROCTABLE()->TexSubImage1DEXT) +#define glTexSubImage2DEXT (_GET_TLS_PROCTABLE()->TexSubImage2DEXT) +#define glCopyTexImage1DEXT (_GET_TLS_PROCTABLE()->CopyTexImage1DEXT) +#define glCopyTexImage2DEXT (_GET_TLS_PROCTABLE()->CopyTexImage2DEXT) +#define glCopyTexSubImage1DEXT (_GET_TLS_PROCTABLE()->CopyTexSubImage1DEXT) +#define glCopyTexSubImage2DEXT (_GET_TLS_PROCTABLE()->CopyTexSubImage2DEXT) +#define glCopyTexSubImage3DEXT (_GET_TLS_PROCTABLE()->CopyTexSubImage3DEXT) +#define glGetHistogramEXT (_GET_TLS_PROCTABLE()->GetHistogramEXT) +#define glGetHistogramParameterfvEXT (_GET_TLS_PROCTABLE()->GetHistogramParameterfvEXT) +#define glGetHistogramParameterivEXT (_GET_TLS_PROCTABLE()->GetHistogramParameterivEXT) +#define glGetMinmaxEXT (_GET_TLS_PROCTABLE()->GetMinmaxEXT) +#define glGetMinmaxParameterfvEXT (_GET_TLS_PROCTABLE()->GetMinmaxParameterfvEXT) +#define glGetMinmaxParameterivEXT (_GET_TLS_PROCTABLE()->GetMinmaxParameterivEXT) +#define glHistogramEXT (_GET_TLS_PROCTABLE()->HistogramEXT) +#define glMinmaxEXT (_GET_TLS_PROCTABLE()->MinmaxEXT) +#define glResetHistogramEXT (_GET_TLS_PROCTABLE()->ResetHistogramEXT) +#define glResetMinmaxEXT (_GET_TLS_PROCTABLE()->ResetMinmaxEXT) +#define glConvolutionFilter1DEXT (_GET_TLS_PROCTABLE()->ConvolutionFilter1DEXT) +#define glConvolutionFilter2DEXT (_GET_TLS_PROCTABLE()->ConvolutionFilter2DEXT) +#define glConvolutionParameterfEXT (_GET_TLS_PROCTABLE()->ConvolutionParameterfEXT) +#define glConvolutionParameterfvEXT (_GET_TLS_PROCTABLE()->ConvolutionParameterfvEXT) +#define glConvolutionParameteriEXT (_GET_TLS_PROCTABLE()->ConvolutionParameteriEXT) +#define glConvolutionParameterivEXT (_GET_TLS_PROCTABLE()->ConvolutionParameterivEXT) +#define glCopyConvolutionFilter1DEXT (_GET_TLS_PROCTABLE()->CopyConvolutionFilter1DEXT) +#define glCopyConvolutionFilter2DEXT (_GET_TLS_PROCTABLE()->CopyConvolutionFilter2DEXT) +#define glGetConvolutionFilterEXT (_GET_TLS_PROCTABLE()->GetConvolutionFilterEXT) +#define glGetConvolutionParameterfvEXT (_GET_TLS_PROCTABLE()->GetConvolutionParameterfvEXT) +#define glGetConvolutionParameterivEXT (_GET_TLS_PROCTABLE()->GetConvolutionParameterivEXT) +#define glGetSeparableFilterEXT (_GET_TLS_PROCTABLE()->GetSeparableFilterEXT) +#define glSeparableFilter2DEXT (_GET_TLS_PROCTABLE()->SeparableFilter2DEXT) +#define glColorTableSGI (_GET_TLS_PROCTABLE()->ColorTableSGI) +#define glColorTableParameterfvSGI (_GET_TLS_PROCTABLE()->ColorTableParameterfvSGI) +#define glColorTableParameterivSGI (_GET_TLS_PROCTABLE()->ColorTableParameterivSGI) +#define glCopyColorTableSGI (_GET_TLS_PROCTABLE()->CopyColorTableSGI) +#define glGetColorTableSGI (_GET_TLS_PROCTABLE()->GetColorTableSGI) +#define glGetColorTableParameterfvSGI (_GET_TLS_PROCTABLE()->GetColorTableParameterfvSGI) +#define glGetColorTableParameterivSGI (_GET_TLS_PROCTABLE()->GetColorTableParameterivSGI) +#define glPixelTexGenSGIX (_GET_TLS_PROCTABLE()->PixelTexGenSGIX) +#define glPixelTexGenParameteriSGIS (_GET_TLS_PROCTABLE()->PixelTexGenParameteriSGIS) +#define glPixelTexGenParameterivSGIS (_GET_TLS_PROCTABLE()->PixelTexGenParameterivSGIS) +#define glPixelTexGenParameterfSGIS (_GET_TLS_PROCTABLE()->PixelTexGenParameterfSGIS) +#define glPixelTexGenParameterfvSGIS (_GET_TLS_PROCTABLE()->PixelTexGenParameterfvSGIS) +#define glGetPixelTexGenParameterivSGIS (_GET_TLS_PROCTABLE()->GetPixelTexGenParameterivSGIS) +#define glGetPixelTexGenParameterfvSGIS (_GET_TLS_PROCTABLE()->GetPixelTexGenParameterfvSGIS) +#define glTexImage4DSGIS (_GET_TLS_PROCTABLE()->TexImage4DSGIS) +#define glTexSubImage4DSGIS (_GET_TLS_PROCTABLE()->TexSubImage4DSGIS) +#define glAreTexturesResidentEXT (_GET_TLS_PROCTABLE()->AreTexturesResidentEXT) +#define glBindTextureEXT (_GET_TLS_PROCTABLE()->BindTextureEXT) +#define glDeleteTexturesEXT (_GET_TLS_PROCTABLE()->DeleteTexturesEXT) +#define glGenTexturesEXT (_GET_TLS_PROCTABLE()->GenTexturesEXT) +#define glIsTextureEXT (_GET_TLS_PROCTABLE()->IsTextureEXT) +#define glPrioritizeTexturesEXT (_GET_TLS_PROCTABLE()->PrioritizeTexturesEXT) +#define glDetailTexFuncSGIS (_GET_TLS_PROCTABLE()->DetailTexFuncSGIS) +#define glGetDetailTexFuncSGIS (_GET_TLS_PROCTABLE()->GetDetailTexFuncSGIS) +#define glSharpenTexFuncSGIS (_GET_TLS_PROCTABLE()->SharpenTexFuncSGIS) +#define glGetSharpenTexFuncSGIS (_GET_TLS_PROCTABLE()->GetSharpenTexFuncSGIS) +#define glSampleMaskSGIS (_GET_TLS_PROCTABLE()->SampleMaskSGIS) +#define glSamplePatternSGIS (_GET_TLS_PROCTABLE()->SamplePatternSGIS) +#define glArrayElementEXT (_GET_TLS_PROCTABLE()->ArrayElementEXT) +#define glColorPointerEXT (_GET_TLS_PROCTABLE()->ColorPointerEXT) +#define glDrawArraysEXT (_GET_TLS_PROCTABLE()->DrawArraysEXT) +#define glEdgeFlagPointerEXT (_GET_TLS_PROCTABLE()->EdgeFlagPointerEXT) +#define glGetPointervEXT (_GET_TLS_PROCTABLE()->GetPointervEXT) +#define glIndexPointerEXT (_GET_TLS_PROCTABLE()->IndexPointerEXT) +#define glNormalPointerEXT (_GET_TLS_PROCTABLE()->NormalPointerEXT) +#define glTexCoordPointerEXT (_GET_TLS_PROCTABLE()->TexCoordPointerEXT) +#define glVertexPointerEXT (_GET_TLS_PROCTABLE()->VertexPointerEXT) +#define glBlendEquationEXT (_GET_TLS_PROCTABLE()->BlendEquationEXT) +#define glSpriteParameterfSGIX (_GET_TLS_PROCTABLE()->SpriteParameterfSGIX) +#define glSpriteParameterfvSGIX (_GET_TLS_PROCTABLE()->SpriteParameterfvSGIX) +#define glSpriteParameteriSGIX (_GET_TLS_PROCTABLE()->SpriteParameteriSGIX) +#define glSpriteParameterivSGIX (_GET_TLS_PROCTABLE()->SpriteParameterivSGIX) +#define glPointParameterfEXT (_GET_TLS_PROCTABLE()->PointParameterfEXT) +#define glPointParameterfvEXT (_GET_TLS_PROCTABLE()->PointParameterfvEXT) +#define glPointParameterfSGIS (_GET_TLS_PROCTABLE()->PointParameterfSGIS) +#define glPointParameterfvSGIS (_GET_TLS_PROCTABLE()->PointParameterfvSGIS) +#define glGetInstrumentsSGIX (_GET_TLS_PROCTABLE()->GetInstrumentsSGIX) +#define glInstrumentsBufferSGIX (_GET_TLS_PROCTABLE()->InstrumentsBufferSGIX) +#define glPollInstrumentsSGIX (_GET_TLS_PROCTABLE()->PollInstrumentsSGIX) +#define glReadInstrumentsSGIX (_GET_TLS_PROCTABLE()->ReadInstrumentsSGIX) +#define glStartInstrumentsSGIX (_GET_TLS_PROCTABLE()->StartInstrumentsSGIX) +#define glStopInstrumentsSGIX (_GET_TLS_PROCTABLE()->StopInstrumentsSGIX) +#define glFrameZoomSGIX (_GET_TLS_PROCTABLE()->FrameZoomSGIX) +#define glTagSampleBufferSGIX (_GET_TLS_PROCTABLE()->TagSampleBufferSGIX) +#define glDeformationMap3dSGIX (_GET_TLS_PROCTABLE()->DeformationMap3dSGIX) +#define glDeformationMap3fSGIX (_GET_TLS_PROCTABLE()->DeformationMap3fSGIX) +#define glDeformSGIX (_GET_TLS_PROCTABLE()->DeformSGIX) +#define glLoadIdentityDeformationMapSGIX (_GET_TLS_PROCTABLE()->LoadIdentityDeformationMapSGIX) +#define glReferencePlaneSGIX (_GET_TLS_PROCTABLE()->ReferencePlaneSGIX) +#define glFlushRasterSGIX (_GET_TLS_PROCTABLE()->FlushRasterSGIX) +#define glFogFuncSGIS (_GET_TLS_PROCTABLE()->FogFuncSGIS) +#define glGetFogFuncSGIS (_GET_TLS_PROCTABLE()->GetFogFuncSGIS) +#define glImageTransformParameteriHP (_GET_TLS_PROCTABLE()->ImageTransformParameteriHP) +#define glImageTransformParameterfHP (_GET_TLS_PROCTABLE()->ImageTransformParameterfHP) +#define glImageTransformParameterivHP (_GET_TLS_PROCTABLE()->ImageTransformParameterivHP) +#define glImageTransformParameterfvHP (_GET_TLS_PROCTABLE()->ImageTransformParameterfvHP) +#define glGetImageTransformParameterivHP (_GET_TLS_PROCTABLE()->GetImageTransformParameterivHP) +#define glGetImageTransformParameterfvHP (_GET_TLS_PROCTABLE()->GetImageTransformParameterfvHP) +#define glColorSubTableEXT (_GET_TLS_PROCTABLE()->ColorSubTableEXT) +#define glCopyColorSubTableEXT (_GET_TLS_PROCTABLE()->CopyColorSubTableEXT) +#define glHintPGI (_GET_TLS_PROCTABLE()->HintPGI) +#define glColorTableEXT (_GET_TLS_PROCTABLE()->ColorTableEXT) +#define glGetColorTableEXT (_GET_TLS_PROCTABLE()->GetColorTableEXT) +#define glGetColorTableParameterivEXT (_GET_TLS_PROCTABLE()->GetColorTableParameterivEXT) +#define glGetColorTableParameterfvEXT (_GET_TLS_PROCTABLE()->GetColorTableParameterfvEXT) +#define glGetListParameterfvSGIX (_GET_TLS_PROCTABLE()->GetListParameterfvSGIX) +#define glGetListParameterivSGIX (_GET_TLS_PROCTABLE()->GetListParameterivSGIX) +#define glListParameterfSGIX (_GET_TLS_PROCTABLE()->ListParameterfSGIX) +#define glListParameterfvSGIX (_GET_TLS_PROCTABLE()->ListParameterfvSGIX) +#define glListParameteriSGIX (_GET_TLS_PROCTABLE()->ListParameteriSGIX) +#define glListParameterivSGIX (_GET_TLS_PROCTABLE()->ListParameterivSGIX) +#define glIndexMaterialEXT (_GET_TLS_PROCTABLE()->IndexMaterialEXT) +#define glIndexFuncEXT (_GET_TLS_PROCTABLE()->IndexFuncEXT) +#define glLockArraysEXT (_GET_TLS_PROCTABLE()->LockArraysEXT) +#define glUnlockArraysEXT (_GET_TLS_PROCTABLE()->UnlockArraysEXT) +#define glCullParameterdvEXT (_GET_TLS_PROCTABLE()->CullParameterdvEXT) +#define glCullParameterfvEXT (_GET_TLS_PROCTABLE()->CullParameterfvEXT) +#define glFragmentColorMaterialSGIX (_GET_TLS_PROCTABLE()->FragmentColorMaterialSGIX) +#define glFragmentLightfSGIX (_GET_TLS_PROCTABLE()->FragmentLightfSGIX) +#define glFragmentLightfvSGIX (_GET_TLS_PROCTABLE()->FragmentLightfvSGIX) +#define glFragmentLightiSGIX (_GET_TLS_PROCTABLE()->FragmentLightiSGIX) +#define glFragmentLightivSGIX (_GET_TLS_PROCTABLE()->FragmentLightivSGIX) +#define glFragmentLightModelfSGIX (_GET_TLS_PROCTABLE()->FragmentLightModelfSGIX) +#define glFragmentLightModelfvSGIX (_GET_TLS_PROCTABLE()->FragmentLightModelfvSGIX) +#define glFragmentLightModeliSGIX (_GET_TLS_PROCTABLE()->FragmentLightModeliSGIX) +#define glFragmentLightModelivSGIX (_GET_TLS_PROCTABLE()->FragmentLightModelivSGIX) +#define glFragmentMaterialfSGIX (_GET_TLS_PROCTABLE()->FragmentMaterialfSGIX) +#define glFragmentMaterialfvSGIX (_GET_TLS_PROCTABLE()->FragmentMaterialfvSGIX) +#define glFragmentMaterialiSGIX (_GET_TLS_PROCTABLE()->FragmentMaterialiSGIX) +#define glFragmentMaterialivSGIX (_GET_TLS_PROCTABLE()->FragmentMaterialivSGIX) +#define glGetFragmentLightfvSGIX (_GET_TLS_PROCTABLE()->GetFragmentLightfvSGIX) +#define glGetFragmentLightivSGIX (_GET_TLS_PROCTABLE()->GetFragmentLightivSGIX) +#define glGetFragmentMaterialfvSGIX (_GET_TLS_PROCTABLE()->GetFragmentMaterialfvSGIX) +#define glGetFragmentMaterialivSGIX (_GET_TLS_PROCTABLE()->GetFragmentMaterialivSGIX) +#define glLightEnviSGIX (_GET_TLS_PROCTABLE()->LightEnviSGIX) +#define glDrawRangeElementsEXT (_GET_TLS_PROCTABLE()->DrawRangeElementsEXT) +#define glApplyTextureEXT (_GET_TLS_PROCTABLE()->ApplyTextureEXT) +#define glTextureLightEXT (_GET_TLS_PROCTABLE()->TextureLightEXT) +#define glTextureMaterialEXT (_GET_TLS_PROCTABLE()->TextureMaterialEXT) +#define glAsyncMarkerSGIX (_GET_TLS_PROCTABLE()->AsyncMarkerSGIX) +#define glFinishAsyncSGIX (_GET_TLS_PROCTABLE()->FinishAsyncSGIX) +#define glPollAsyncSGIX (_GET_TLS_PROCTABLE()->PollAsyncSGIX) +#define glGenAsyncMarkersSGIX (_GET_TLS_PROCTABLE()->GenAsyncMarkersSGIX) +#define glDeleteAsyncMarkersSGIX (_GET_TLS_PROCTABLE()->DeleteAsyncMarkersSGIX) +#define glIsAsyncMarkerSGIX (_GET_TLS_PROCTABLE()->IsAsyncMarkerSGIX) +#define glVertexPointervINTEL (_GET_TLS_PROCTABLE()->VertexPointervINTEL) +#define glNormalPointervINTEL (_GET_TLS_PROCTABLE()->NormalPointervINTEL) +#define glColorPointervINTEL (_GET_TLS_PROCTABLE()->ColorPointervINTEL) +#define glTexCoordPointervINTEL (_GET_TLS_PROCTABLE()->TexCoordPointervINTEL) +#define glPixelTransformParameteriEXT (_GET_TLS_PROCTABLE()->PixelTransformParameteriEXT) +#define glPixelTransformParameterfEXT (_GET_TLS_PROCTABLE()->PixelTransformParameterfEXT) +#define glPixelTransformParameterivEXT (_GET_TLS_PROCTABLE()->PixelTransformParameterivEXT) +#define glPixelTransformParameterfvEXT (_GET_TLS_PROCTABLE()->PixelTransformParameterfvEXT) +#define glSecondaryColor3bEXT (_GET_TLS_PROCTABLE()->SecondaryColor3bEXT) +#define glSecondaryColor3bvEXT (_GET_TLS_PROCTABLE()->SecondaryColor3bvEXT) +#define glSecondaryColor3dEXT (_GET_TLS_PROCTABLE()->SecondaryColor3dEXT) +#define glSecondaryColor3dvEXT (_GET_TLS_PROCTABLE()->SecondaryColor3dvEXT) +#define glSecondaryColor3fEXT (_GET_TLS_PROCTABLE()->SecondaryColor3fEXT) +#define glSecondaryColor3fvEXT (_GET_TLS_PROCTABLE()->SecondaryColor3fvEXT) +#define glSecondaryColor3iEXT (_GET_TLS_PROCTABLE()->SecondaryColor3iEXT) +#define glSecondaryColor3ivEXT (_GET_TLS_PROCTABLE()->SecondaryColor3ivEXT) +#define glSecondaryColor3sEXT (_GET_TLS_PROCTABLE()->SecondaryColor3sEXT) +#define glSecondaryColor3svEXT (_GET_TLS_PROCTABLE()->SecondaryColor3svEXT) +#define glSecondaryColor3ubEXT (_GET_TLS_PROCTABLE()->SecondaryColor3ubEXT) +#define glSecondaryColor3ubvEXT (_GET_TLS_PROCTABLE()->SecondaryColor3ubvEXT) +#define glSecondaryColor3uiEXT (_GET_TLS_PROCTABLE()->SecondaryColor3uiEXT) +#define glSecondaryColor3uivEXT (_GET_TLS_PROCTABLE()->SecondaryColor3uivEXT) +#define glSecondaryColor3usEXT (_GET_TLS_PROCTABLE()->SecondaryColor3usEXT) +#define glSecondaryColor3usvEXT (_GET_TLS_PROCTABLE()->SecondaryColor3usvEXT) +#define glSecondaryColorPointerEXT (_GET_TLS_PROCTABLE()->SecondaryColorPointerEXT) +#define glTextureNormalEXT (_GET_TLS_PROCTABLE()->TextureNormalEXT) +#define glMultiDrawArraysEXT (_GET_TLS_PROCTABLE()->MultiDrawArraysEXT) +#define glMultiDrawElementsEXT (_GET_TLS_PROCTABLE()->MultiDrawElementsEXT) +#define glFogCoordfEXT (_GET_TLS_PROCTABLE()->FogCoordfEXT) +#define glFogCoordfvEXT (_GET_TLS_PROCTABLE()->FogCoordfvEXT) +#define glFogCoorddEXT (_GET_TLS_PROCTABLE()->FogCoorddEXT) +#define glFogCoorddvEXT (_GET_TLS_PROCTABLE()->FogCoorddvEXT) +#define glFogCoordPointerEXT (_GET_TLS_PROCTABLE()->FogCoordPointerEXT) +#define glTangent3bEXT (_GET_TLS_PROCTABLE()->Tangent3bEXT) +#define glTangent3bvEXT (_GET_TLS_PROCTABLE()->Tangent3bvEXT) +#define glTangent3dEXT (_GET_TLS_PROCTABLE()->Tangent3dEXT) +#define glTangent3dvEXT (_GET_TLS_PROCTABLE()->Tangent3dvEXT) +#define glTangent3fEXT (_GET_TLS_PROCTABLE()->Tangent3fEXT) +#define glTangent3fvEXT (_GET_TLS_PROCTABLE()->Tangent3fvEXT) +#define glTangent3iEXT (_GET_TLS_PROCTABLE()->Tangent3iEXT) +#define glTangent3ivEXT (_GET_TLS_PROCTABLE()->Tangent3ivEXT) +#define glTangent3sEXT (_GET_TLS_PROCTABLE()->Tangent3sEXT) +#define glTangent3svEXT (_GET_TLS_PROCTABLE()->Tangent3svEXT) +#define glBinormal3bEXT (_GET_TLS_PROCTABLE()->Binormal3bEXT) +#define glBinormal3bvEXT (_GET_TLS_PROCTABLE()->Binormal3bvEXT) +#define glBinormal3dEXT (_GET_TLS_PROCTABLE()->Binormal3dEXT) +#define glBinormal3dvEXT (_GET_TLS_PROCTABLE()->Binormal3dvEXT) +#define glBinormal3fEXT (_GET_TLS_PROCTABLE()->Binormal3fEXT) +#define glBinormal3fvEXT (_GET_TLS_PROCTABLE()->Binormal3fvEXT) +#define glBinormal3iEXT (_GET_TLS_PROCTABLE()->Binormal3iEXT) +#define glBinormal3ivEXT (_GET_TLS_PROCTABLE()->Binormal3ivEXT) +#define glBinormal3sEXT (_GET_TLS_PROCTABLE()->Binormal3sEXT) +#define glBinormal3svEXT (_GET_TLS_PROCTABLE()->Binormal3svEXT) +#define glTangentPointerEXT (_GET_TLS_PROCTABLE()->TangentPointerEXT) +#define glBinormalPointerEXT (_GET_TLS_PROCTABLE()->BinormalPointerEXT) +#define glFinishTextureSUNX (_GET_TLS_PROCTABLE()->FinishTextureSUNX) +#define glGlobalAlphaFactorbSUN (_GET_TLS_PROCTABLE()->GlobalAlphaFactorbSUN) +#define glGlobalAlphaFactorsSUN (_GET_TLS_PROCTABLE()->GlobalAlphaFactorsSUN) +#define glGlobalAlphaFactoriSUN (_GET_TLS_PROCTABLE()->GlobalAlphaFactoriSUN) +#define glGlobalAlphaFactorfSUN (_GET_TLS_PROCTABLE()->GlobalAlphaFactorfSUN) +#define glGlobalAlphaFactordSUN (_GET_TLS_PROCTABLE()->GlobalAlphaFactordSUN) +#define glGlobalAlphaFactorubSUN (_GET_TLS_PROCTABLE()->GlobalAlphaFactorubSUN) +#define glGlobalAlphaFactorusSUN (_GET_TLS_PROCTABLE()->GlobalAlphaFactorusSUN) +#define glGlobalAlphaFactoruiSUN (_GET_TLS_PROCTABLE()->GlobalAlphaFactoruiSUN) +#define glReplacementCodeuiSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiSUN) +#define glReplacementCodeusSUN (_GET_TLS_PROCTABLE()->ReplacementCodeusSUN) +#define glReplacementCodeubSUN (_GET_TLS_PROCTABLE()->ReplacementCodeubSUN) +#define glReplacementCodeuivSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuivSUN) +#define glReplacementCodeusvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeusvSUN) +#define glReplacementCodeubvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeubvSUN) +#define glReplacementCodePointerSUN (_GET_TLS_PROCTABLE()->ReplacementCodePointerSUN) +#define glColor4ubVertex2fSUN (_GET_TLS_PROCTABLE()->Color4ubVertex2fSUN) +#define glColor4ubVertex2fvSUN (_GET_TLS_PROCTABLE()->Color4ubVertex2fvSUN) +#define glColor4ubVertex3fSUN (_GET_TLS_PROCTABLE()->Color4ubVertex3fSUN) +#define glColor4ubVertex3fvSUN (_GET_TLS_PROCTABLE()->Color4ubVertex3fvSUN) +#define glColor3fVertex3fSUN (_GET_TLS_PROCTABLE()->Color3fVertex3fSUN) +#define glColor3fVertex3fvSUN (_GET_TLS_PROCTABLE()->Color3fVertex3fvSUN) +#define glNormal3fVertex3fSUN (_GET_TLS_PROCTABLE()->Normal3fVertex3fSUN) +#define glNormal3fVertex3fvSUN (_GET_TLS_PROCTABLE()->Normal3fVertex3fvSUN) +#define glColor4fNormal3fVertex3fSUN (_GET_TLS_PROCTABLE()->Color4fNormal3fVertex3fSUN) +#define glColor4fNormal3fVertex3fvSUN (_GET_TLS_PROCTABLE()->Color4fNormal3fVertex3fvSUN) +#define glTexCoord2fVertex3fSUN (_GET_TLS_PROCTABLE()->TexCoord2fVertex3fSUN) +#define glTexCoord2fVertex3fvSUN (_GET_TLS_PROCTABLE()->TexCoord2fVertex3fvSUN) +#define glTexCoord4fVertex4fSUN (_GET_TLS_PROCTABLE()->TexCoord4fVertex4fSUN) +#define glTexCoord4fVertex4fvSUN (_GET_TLS_PROCTABLE()->TexCoord4fVertex4fvSUN) +#define glTexCoord2fColor4ubVertex3fSUN (_GET_TLS_PROCTABLE()->TexCoord2fColor4ubVertex3fSUN) +#define glTexCoord2fColor4ubVertex3fvSUN (_GET_TLS_PROCTABLE()->TexCoord2fColor4ubVertex3fvSUN) +#define glTexCoord2fColor3fVertex3fSUN (_GET_TLS_PROCTABLE()->TexCoord2fColor3fVertex3fSUN) +#define glTexCoord2fColor3fVertex3fvSUN (_GET_TLS_PROCTABLE()->TexCoord2fColor3fVertex3fvSUN) +#define glTexCoord2fNormal3fVertex3fSUN (_GET_TLS_PROCTABLE()->TexCoord2fNormal3fVertex3fSUN) +#define glTexCoord2fNormal3fVertex3fvSUN (_GET_TLS_PROCTABLE()->TexCoord2fNormal3fVertex3fvSUN) +#define glTexCoord2fColor4fNormal3fVertex3fSUN (_GET_TLS_PROCTABLE()->TexCoord2fColor4fNormal3fVertex3fSUN) +#define glTexCoord2fColor4fNormal3fVertex3fvSUN (_GET_TLS_PROCTABLE()->TexCoord2fColor4fNormal3fVertex3fvSUN) +#define glTexCoord4fColor4fNormal3fVertex4fSUN (_GET_TLS_PROCTABLE()->TexCoord4fColor4fNormal3fVertex4fSUN) +#define glTexCoord4fColor4fNormal3fVertex4fvSUN (_GET_TLS_PROCTABLE()->TexCoord4fColor4fNormal3fVertex4fvSUN) +#define glReplacementCodeuiVertex3fSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiVertex3fSUN) +#define glReplacementCodeuiVertex3fvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiVertex3fvSUN) +#define glReplacementCodeuiColor4ubVertex3fSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiColor4ubVertex3fSUN) +#define glReplacementCodeuiColor4ubVertex3fvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiColor4ubVertex3fvSUN) +#define glReplacementCodeuiColor3fVertex3fSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiColor3fVertex3fSUN) +#define glReplacementCodeuiColor3fVertex3fvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiColor3fVertex3fvSUN) +#define glReplacementCodeuiNormal3fVertex3fSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiNormal3fVertex3fSUN) +#define glReplacementCodeuiNormal3fVertex3fvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiNormal3fVertex3fvSUN) +#define glReplacementCodeuiColor4fNormal3fVertex3fSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiColor4fNormal3fVertex3fSUN) +#define glReplacementCodeuiColor4fNormal3fVertex3fvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiColor4fNormal3fVertex3fvSUN) +#define glReplacementCodeuiTexCoord2fVertex3fSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiTexCoord2fVertex3fSUN) +#define glReplacementCodeuiTexCoord2fVertex3fvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiTexCoord2fVertex3fvSUN) +#define glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiTexCoord2fNormal3fVertex3fSUN) +#define glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN) +#define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN) +#define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN) +#define glBlendFuncSeparateEXT (_GET_TLS_PROCTABLE()->BlendFuncSeparateEXT) +#define glBlendFuncSeparateINGR (_GET_TLS_PROCTABLE()->BlendFuncSeparateINGR) +#define glVertexWeightfEXT (_GET_TLS_PROCTABLE()->VertexWeightfEXT) +#define glVertexWeightfvEXT (_GET_TLS_PROCTABLE()->VertexWeightfvEXT) +#define glVertexWeightPointerEXT (_GET_TLS_PROCTABLE()->VertexWeightPointerEXT) +#define glFlushVertexArrayRangeNV (_GET_TLS_PROCTABLE()->FlushVertexArrayRangeNV) +#define glVertexArrayRangeNV (_GET_TLS_PROCTABLE()->VertexArrayRangeNV) +#define glCombinerParameterfvNV (_GET_TLS_PROCTABLE()->CombinerParameterfvNV) +#define glCombinerParameterfNV (_GET_TLS_PROCTABLE()->CombinerParameterfNV) +#define glCombinerParameterivNV (_GET_TLS_PROCTABLE()->CombinerParameterivNV) +#define glCombinerParameteriNV (_GET_TLS_PROCTABLE()->CombinerParameteriNV) +#define glCombinerInputNV (_GET_TLS_PROCTABLE()->CombinerInputNV) +#define glCombinerOutputNV (_GET_TLS_PROCTABLE()->CombinerOutputNV) +#define glFinalCombinerInputNV (_GET_TLS_PROCTABLE()->FinalCombinerInputNV) +#define glGetCombinerInputParameterfvNV (_GET_TLS_PROCTABLE()->GetCombinerInputParameterfvNV) +#define glGetCombinerInputParameterivNV (_GET_TLS_PROCTABLE()->GetCombinerInputParameterivNV) +#define glGetCombinerOutputParameterfvNV (_GET_TLS_PROCTABLE()->GetCombinerOutputParameterfvNV) +#define glGetCombinerOutputParameterivNV (_GET_TLS_PROCTABLE()->GetCombinerOutputParameterivNV) +#define glGetFinalCombinerInputParameterfvNV (_GET_TLS_PROCTABLE()->GetFinalCombinerInputParameterfvNV) +#define glGetFinalCombinerInputParameterivNV (_GET_TLS_PROCTABLE()->GetFinalCombinerInputParameterivNV) +#define glResizeBuffersMESA (_GET_TLS_PROCTABLE()->ResizeBuffersMESA) +#define glWindowPos2dMESA (_GET_TLS_PROCTABLE()->WindowPos2dMESA) +#define glWindowPos2dvMESA (_GET_TLS_PROCTABLE()->WindowPos2dvMESA) +#define glWindowPos2fMESA (_GET_TLS_PROCTABLE()->WindowPos2fMESA) +#define glWindowPos2fvMESA (_GET_TLS_PROCTABLE()->WindowPos2fvMESA) +#define glWindowPos2iMESA (_GET_TLS_PROCTABLE()->WindowPos2iMESA) +#define glWindowPos2ivMESA (_GET_TLS_PROCTABLE()->WindowPos2ivMESA) +#define glWindowPos2sMESA (_GET_TLS_PROCTABLE()->WindowPos2sMESA) +#define glWindowPos2svMESA (_GET_TLS_PROCTABLE()->WindowPos2svMESA) +#define glWindowPos3dMESA (_GET_TLS_PROCTABLE()->WindowPos3dMESA) +#define glWindowPos3dvMESA (_GET_TLS_PROCTABLE()->WindowPos3dvMESA) +#define glWindowPos3fMESA (_GET_TLS_PROCTABLE()->WindowPos3fMESA) +#define glWindowPos3fvMESA (_GET_TLS_PROCTABLE()->WindowPos3fvMESA) +#define glWindowPos3iMESA (_GET_TLS_PROCTABLE()->WindowPos3iMESA) +#define glWindowPos3ivMESA (_GET_TLS_PROCTABLE()->WindowPos3ivMESA) +#define glWindowPos3sMESA (_GET_TLS_PROCTABLE()->WindowPos3sMESA) +#define glWindowPos3svMESA (_GET_TLS_PROCTABLE()->WindowPos3svMESA) +#define glWindowPos4dMESA (_GET_TLS_PROCTABLE()->WindowPos4dMESA) +#define glWindowPos4dvMESA (_GET_TLS_PROCTABLE()->WindowPos4dvMESA) +#define glWindowPos4fMESA (_GET_TLS_PROCTABLE()->WindowPos4fMESA) +#define glWindowPos4fvMESA (_GET_TLS_PROCTABLE()->WindowPos4fvMESA) +#define glWindowPos4iMESA (_GET_TLS_PROCTABLE()->WindowPos4iMESA) +#define glWindowPos4ivMESA (_GET_TLS_PROCTABLE()->WindowPos4ivMESA) +#define glWindowPos4sMESA (_GET_TLS_PROCTABLE()->WindowPos4sMESA) +#define glWindowPos4svMESA (_GET_TLS_PROCTABLE()->WindowPos4svMESA) +#define glMultiModeDrawArraysIBM (_GET_TLS_PROCTABLE()->MultiModeDrawArraysIBM) +#define glMultiModeDrawElementsIBM (_GET_TLS_PROCTABLE()->MultiModeDrawElementsIBM) +#define glColorPointerListIBM (_GET_TLS_PROCTABLE()->ColorPointerListIBM) +#define glSecondaryColorPointerListIBM (_GET_TLS_PROCTABLE()->SecondaryColorPointerListIBM) +#define glEdgeFlagPointerListIBM (_GET_TLS_PROCTABLE()->EdgeFlagPointerListIBM) +#define glFogCoordPointerListIBM (_GET_TLS_PROCTABLE()->FogCoordPointerListIBM) +#define glIndexPointerListIBM (_GET_TLS_PROCTABLE()->IndexPointerListIBM) +#define glNormalPointerListIBM (_GET_TLS_PROCTABLE()->NormalPointerListIBM) +#define glTexCoordPointerListIBM (_GET_TLS_PROCTABLE()->TexCoordPointerListIBM) +#define glVertexPointerListIBM (_GET_TLS_PROCTABLE()->VertexPointerListIBM) +#define glTbufferMask3DFX (_GET_TLS_PROCTABLE()->TbufferMask3DFX) +#define glSampleMaskEXT (_GET_TLS_PROCTABLE()->SampleMaskEXT) +#define glSamplePatternEXT (_GET_TLS_PROCTABLE()->SamplePatternEXT) +#define glTextureColorMaskSGIS (_GET_TLS_PROCTABLE()->TextureColorMaskSGIS) +#define glIglooInterfaceSGIX (_GET_TLS_PROCTABLE()->IglooInterfaceSGIX) +#define glDeleteFencesNV (_GET_TLS_PROCTABLE()->DeleteFencesNV) +#define glGenFencesNV (_GET_TLS_PROCTABLE()->GenFencesNV) +#define glIsFenceNV (_GET_TLS_PROCTABLE()->IsFenceNV) +#define glTestFenceNV (_GET_TLS_PROCTABLE()->TestFenceNV) +#define glGetFenceivNV (_GET_TLS_PROCTABLE()->GetFenceivNV) +#define glFinishFenceNV (_GET_TLS_PROCTABLE()->FinishFenceNV) +#define glSetFenceNV (_GET_TLS_PROCTABLE()->SetFenceNV) +#define glMapControlPointsNV (_GET_TLS_PROCTABLE()->MapControlPointsNV) +#define glMapParameterivNV (_GET_TLS_PROCTABLE()->MapParameterivNV) +#define glMapParameterfvNV (_GET_TLS_PROCTABLE()->MapParameterfvNV) +#define glGetMapControlPointsNV (_GET_TLS_PROCTABLE()->GetMapControlPointsNV) +#define glGetMapParameterivNV (_GET_TLS_PROCTABLE()->GetMapParameterivNV) +#define glGetMapParameterfvNV (_GET_TLS_PROCTABLE()->GetMapParameterfvNV) +#define glGetMapAttribParameterivNV (_GET_TLS_PROCTABLE()->GetMapAttribParameterivNV) +#define glGetMapAttribParameterfvNV (_GET_TLS_PROCTABLE()->GetMapAttribParameterfvNV) +#define glEvalMapsNV (_GET_TLS_PROCTABLE()->EvalMapsNV) +#define glCombinerStageParameterfvNV (_GET_TLS_PROCTABLE()->CombinerStageParameterfvNV) +#define glGetCombinerStageParameterfvNV (_GET_TLS_PROCTABLE()->GetCombinerStageParameterfvNV) +#define glAreProgramsResidentNV (_GET_TLS_PROCTABLE()->AreProgramsResidentNV) +#define glBindProgramNV (_GET_TLS_PROCTABLE()->BindProgramNV) +#define glDeleteProgramsNV (_GET_TLS_PROCTABLE()->DeleteProgramsNV) +#define glExecuteProgramNV (_GET_TLS_PROCTABLE()->ExecuteProgramNV) +#define glGenProgramsNV (_GET_TLS_PROCTABLE()->GenProgramsNV) +#define glGetProgramParameterdvNV (_GET_TLS_PROCTABLE()->GetProgramParameterdvNV) +#define glGetProgramParameterfvNV (_GET_TLS_PROCTABLE()->GetProgramParameterfvNV) +#define glGetProgramivNV (_GET_TLS_PROCTABLE()->GetProgramivNV) +#define glGetProgramStringNV (_GET_TLS_PROCTABLE()->GetProgramStringNV) +#define glGetTrackMatrixivNV (_GET_TLS_PROCTABLE()->GetTrackMatrixivNV) +#define glGetVertexAttribdvNV (_GET_TLS_PROCTABLE()->GetVertexAttribdvNV) +#define glGetVertexAttribfvNV (_GET_TLS_PROCTABLE()->GetVertexAttribfvNV) +#define glGetVertexAttribivNV (_GET_TLS_PROCTABLE()->GetVertexAttribivNV) +#define glGetVertexAttribPointervNV (_GET_TLS_PROCTABLE()->GetVertexAttribPointervNV) +#define glIsProgramNV (_GET_TLS_PROCTABLE()->IsProgramNV) +#define glLoadProgramNV (_GET_TLS_PROCTABLE()->LoadProgramNV) +#define glProgramParameter4dNV (_GET_TLS_PROCTABLE()->ProgramParameter4dNV) +#define glProgramParameter4dvNV (_GET_TLS_PROCTABLE()->ProgramParameter4dvNV) +#define glProgramParameter4fNV (_GET_TLS_PROCTABLE()->ProgramParameter4fNV) +#define glProgramParameter4fvNV (_GET_TLS_PROCTABLE()->ProgramParameter4fvNV) +#define glProgramParameters4dvNV (_GET_TLS_PROCTABLE()->ProgramParameters4dvNV) +#define glProgramParameters4fvNV (_GET_TLS_PROCTABLE()->ProgramParameters4fvNV) +#define glRequestResidentProgramsNV (_GET_TLS_PROCTABLE()->RequestResidentProgramsNV) +#define glTrackMatrixNV (_GET_TLS_PROCTABLE()->TrackMatrixNV) +#define glVertexAttribPointerNV (_GET_TLS_PROCTABLE()->VertexAttribPointerNV) +#define glVertexAttrib1dNV (_GET_TLS_PROCTABLE()->VertexAttrib1dNV) +#define glVertexAttrib1dvNV (_GET_TLS_PROCTABLE()->VertexAttrib1dvNV) +#define glVertexAttrib1fNV (_GET_TLS_PROCTABLE()->VertexAttrib1fNV) +#define glVertexAttrib1fvNV (_GET_TLS_PROCTABLE()->VertexAttrib1fvNV) +#define glVertexAttrib1sNV (_GET_TLS_PROCTABLE()->VertexAttrib1sNV) +#define glVertexAttrib1svNV (_GET_TLS_PROCTABLE()->VertexAttrib1svNV) +#define glVertexAttrib2dNV (_GET_TLS_PROCTABLE()->VertexAttrib2dNV) +#define glVertexAttrib2dvNV (_GET_TLS_PROCTABLE()->VertexAttrib2dvNV) +#define glVertexAttrib2fNV (_GET_TLS_PROCTABLE()->VertexAttrib2fNV) +#define glVertexAttrib2fvNV (_GET_TLS_PROCTABLE()->VertexAttrib2fvNV) +#define glVertexAttrib2sNV (_GET_TLS_PROCTABLE()->VertexAttrib2sNV) +#define glVertexAttrib2svNV (_GET_TLS_PROCTABLE()->VertexAttrib2svNV) +#define glVertexAttrib3dNV (_GET_TLS_PROCTABLE()->VertexAttrib3dNV) +#define glVertexAttrib3dvNV (_GET_TLS_PROCTABLE()->VertexAttrib3dvNV) +#define glVertexAttrib3fNV (_GET_TLS_PROCTABLE()->VertexAttrib3fNV) +#define glVertexAttrib3fvNV (_GET_TLS_PROCTABLE()->VertexAttrib3fvNV) +#define glVertexAttrib3sNV (_GET_TLS_PROCTABLE()->VertexAttrib3sNV) +#define glVertexAttrib3svNV (_GET_TLS_PROCTABLE()->VertexAttrib3svNV) +#define glVertexAttrib4dNV (_GET_TLS_PROCTABLE()->VertexAttrib4dNV) +#define glVertexAttrib4dvNV (_GET_TLS_PROCTABLE()->VertexAttrib4dvNV) +#define glVertexAttrib4fNV (_GET_TLS_PROCTABLE()->VertexAttrib4fNV) +#define glVertexAttrib4fvNV (_GET_TLS_PROCTABLE()->VertexAttrib4fvNV) +#define glVertexAttrib4sNV (_GET_TLS_PROCTABLE()->VertexAttrib4sNV) +#define glVertexAttrib4svNV (_GET_TLS_PROCTABLE()->VertexAttrib4svNV) +#define glVertexAttrib4ubNV (_GET_TLS_PROCTABLE()->VertexAttrib4ubNV) +#define glVertexAttrib4ubvNV (_GET_TLS_PROCTABLE()->VertexAttrib4ubvNV) +#define glVertexAttribs1dvNV (_GET_TLS_PROCTABLE()->VertexAttribs1dvNV) +#define glVertexAttribs1fvNV (_GET_TLS_PROCTABLE()->VertexAttribs1fvNV) +#define glVertexAttribs1svNV (_GET_TLS_PROCTABLE()->VertexAttribs1svNV) +#define glVertexAttribs2dvNV (_GET_TLS_PROCTABLE()->VertexAttribs2dvNV) +#define glVertexAttribs2fvNV (_GET_TLS_PROCTABLE()->VertexAttribs2fvNV) +#define glVertexAttribs2svNV (_GET_TLS_PROCTABLE()->VertexAttribs2svNV) +#define glVertexAttribs3dvNV (_GET_TLS_PROCTABLE()->VertexAttribs3dvNV) +#define glVertexAttribs3fvNV (_GET_TLS_PROCTABLE()->VertexAttribs3fvNV) +#define glVertexAttribs3svNV (_GET_TLS_PROCTABLE()->VertexAttribs3svNV) +#define glVertexAttribs4dvNV (_GET_TLS_PROCTABLE()->VertexAttribs4dvNV) +#define glVertexAttribs4fvNV (_GET_TLS_PROCTABLE()->VertexAttribs4fvNV) +#define glVertexAttribs4svNV (_GET_TLS_PROCTABLE()->VertexAttribs4svNV) +#define glVertexAttribs4ubvNV (_GET_TLS_PROCTABLE()->VertexAttribs4ubvNV) +#define glTexBumpParameterivATI (_GET_TLS_PROCTABLE()->TexBumpParameterivATI) +#define glTexBumpParameterfvATI (_GET_TLS_PROCTABLE()->TexBumpParameterfvATI) +#define glGetTexBumpParameterivATI (_GET_TLS_PROCTABLE()->GetTexBumpParameterivATI) +#define glGetTexBumpParameterfvATI (_GET_TLS_PROCTABLE()->GetTexBumpParameterfvATI) +#define glGenFragmentShadersATI (_GET_TLS_PROCTABLE()->GenFragmentShadersATI) +#define glBindFragmentShaderATI (_GET_TLS_PROCTABLE()->BindFragmentShaderATI) +#define glDeleteFragmentShaderATI (_GET_TLS_PROCTABLE()->DeleteFragmentShaderATI) +#define glBeginFragmentShaderATI (_GET_TLS_PROCTABLE()->BeginFragmentShaderATI) +#define glEndFragmentShaderATI (_GET_TLS_PROCTABLE()->EndFragmentShaderATI) +#define glPassTexCoordATI (_GET_TLS_PROCTABLE()->PassTexCoordATI) +#define glSampleMapATI (_GET_TLS_PROCTABLE()->SampleMapATI) +#define glColorFragmentOp1ATI (_GET_TLS_PROCTABLE()->ColorFragmentOp1ATI) +#define glColorFragmentOp2ATI (_GET_TLS_PROCTABLE()->ColorFragmentOp2ATI) +#define glColorFragmentOp3ATI (_GET_TLS_PROCTABLE()->ColorFragmentOp3ATI) +#define glAlphaFragmentOp1ATI (_GET_TLS_PROCTABLE()->AlphaFragmentOp1ATI) +#define glAlphaFragmentOp2ATI (_GET_TLS_PROCTABLE()->AlphaFragmentOp2ATI) +#define glAlphaFragmentOp3ATI (_GET_TLS_PROCTABLE()->AlphaFragmentOp3ATI) +#define glSetFragmentShaderConstantATI (_GET_TLS_PROCTABLE()->SetFragmentShaderConstantATI) +#define glPNTrianglesiATI (_GET_TLS_PROCTABLE()->PNTrianglesiATI) +#define glPNTrianglesfATI (_GET_TLS_PROCTABLE()->PNTrianglesfATI) +#define glNewObjectBufferATI (_GET_TLS_PROCTABLE()->NewObjectBufferATI) +#define glIsObjectBufferATI (_GET_TLS_PROCTABLE()->IsObjectBufferATI) +#define glUpdateObjectBufferATI (_GET_TLS_PROCTABLE()->UpdateObjectBufferATI) +#define glGetObjectBufferfvATI (_GET_TLS_PROCTABLE()->GetObjectBufferfvATI) +#define glGetObjectBufferivATI (_GET_TLS_PROCTABLE()->GetObjectBufferivATI) +#define glFreeObjectBufferATI (_GET_TLS_PROCTABLE()->FreeObjectBufferATI) +#define glArrayObjectATI (_GET_TLS_PROCTABLE()->ArrayObjectATI) +#define glGetArrayObjectfvATI (_GET_TLS_PROCTABLE()->GetArrayObjectfvATI) +#define glGetArrayObjectivATI (_GET_TLS_PROCTABLE()->GetArrayObjectivATI) +#define glVariantArrayObjectATI (_GET_TLS_PROCTABLE()->VariantArrayObjectATI) +#define glGetVariantArrayObjectfvATI (_GET_TLS_PROCTABLE()->GetVariantArrayObjectfvATI) +#define glGetVariantArrayObjectivATI (_GET_TLS_PROCTABLE()->GetVariantArrayObjectivATI) +#define glBeginVertexShaderEXT (_GET_TLS_PROCTABLE()->BeginVertexShaderEXT) +#define glEndVertexShaderEXT (_GET_TLS_PROCTABLE()->EndVertexShaderEXT) +#define glBindVertexShaderEXT (_GET_TLS_PROCTABLE()->BindVertexShaderEXT) +#define glGenVertexShadersEXT (_GET_TLS_PROCTABLE()->GenVertexShadersEXT) +#define glDeleteVertexShaderEXT (_GET_TLS_PROCTABLE()->DeleteVertexShaderEXT) +#define glShaderOp1EXT (_GET_TLS_PROCTABLE()->ShaderOp1EXT) +#define glShaderOp2EXT (_GET_TLS_PROCTABLE()->ShaderOp2EXT) +#define glShaderOp3EXT (_GET_TLS_PROCTABLE()->ShaderOp3EXT) +#define glSwizzleEXT (_GET_TLS_PROCTABLE()->SwizzleEXT) +#define glWriteMaskEXT (_GET_TLS_PROCTABLE()->WriteMaskEXT) +#define glInsertComponentEXT (_GET_TLS_PROCTABLE()->InsertComponentEXT) +#define glExtractComponentEXT (_GET_TLS_PROCTABLE()->ExtractComponentEXT) +#define glGenSymbolsEXT (_GET_TLS_PROCTABLE()->GenSymbolsEXT) +#define glSetInvariantEXT (_GET_TLS_PROCTABLE()->SetInvariantEXT) +#define glSetLocalConstantEXT (_GET_TLS_PROCTABLE()->SetLocalConstantEXT) +#define glVariantbvEXT (_GET_TLS_PROCTABLE()->VariantbvEXT) +#define glVariantsvEXT (_GET_TLS_PROCTABLE()->VariantsvEXT) +#define glVariantivEXT (_GET_TLS_PROCTABLE()->VariantivEXT) +#define glVariantfvEXT (_GET_TLS_PROCTABLE()->VariantfvEXT) +#define glVariantdvEXT (_GET_TLS_PROCTABLE()->VariantdvEXT) +#define glVariantubvEXT (_GET_TLS_PROCTABLE()->VariantubvEXT) +#define glVariantusvEXT (_GET_TLS_PROCTABLE()->VariantusvEXT) +#define glVariantuivEXT (_GET_TLS_PROCTABLE()->VariantuivEXT) +#define glVariantPointerEXT (_GET_TLS_PROCTABLE()->VariantPointerEXT) +#define glEnableVariantClientStateEXT (_GET_TLS_PROCTABLE()->EnableVariantClientStateEXT) +#define glDisableVariantClientStateEXT (_GET_TLS_PROCTABLE()->DisableVariantClientStateEXT) +#define glBindLightParameterEXT (_GET_TLS_PROCTABLE()->BindLightParameterEXT) +#define glBindMaterialParameterEXT (_GET_TLS_PROCTABLE()->BindMaterialParameterEXT) +#define glBindTexGenParameterEXT (_GET_TLS_PROCTABLE()->BindTexGenParameterEXT) +#define glBindTextureUnitParameterEXT (_GET_TLS_PROCTABLE()->BindTextureUnitParameterEXT) +#define glBindParameterEXT (_GET_TLS_PROCTABLE()->BindParameterEXT) +#define glIsVariantEnabledEXT (_GET_TLS_PROCTABLE()->IsVariantEnabledEXT) +#define glGetVariantBooleanvEXT (_GET_TLS_PROCTABLE()->GetVariantBooleanvEXT) +#define glGetVariantIntegervEXT (_GET_TLS_PROCTABLE()->GetVariantIntegervEXT) +#define glGetVariantFloatvEXT (_GET_TLS_PROCTABLE()->GetVariantFloatvEXT) +#define glGetVariantPointervEXT (_GET_TLS_PROCTABLE()->GetVariantPointervEXT) +#define glGetInvariantBooleanvEXT (_GET_TLS_PROCTABLE()->GetInvariantBooleanvEXT) +#define glGetInvariantIntegervEXT (_GET_TLS_PROCTABLE()->GetInvariantIntegervEXT) +#define glGetInvariantFloatvEXT (_GET_TLS_PROCTABLE()->GetInvariantFloatvEXT) +#define glGetLocalConstantBooleanvEXT (_GET_TLS_PROCTABLE()->GetLocalConstantBooleanvEXT) +#define glGetLocalConstantIntegervEXT (_GET_TLS_PROCTABLE()->GetLocalConstantIntegervEXT) +#define glGetLocalConstantFloatvEXT (_GET_TLS_PROCTABLE()->GetLocalConstantFloatvEXT) +#define glVertexStream1sATI (_GET_TLS_PROCTABLE()->VertexStream1sATI) +#define glVertexStream1svATI (_GET_TLS_PROCTABLE()->VertexStream1svATI) +#define glVertexStream1iATI (_GET_TLS_PROCTABLE()->VertexStream1iATI) +#define glVertexStream1ivATI (_GET_TLS_PROCTABLE()->VertexStream1ivATI) +#define glVertexStream1fATI (_GET_TLS_PROCTABLE()->VertexStream1fATI) +#define glVertexStream1fvATI (_GET_TLS_PROCTABLE()->VertexStream1fvATI) +#define glVertexStream1dATI (_GET_TLS_PROCTABLE()->VertexStream1dATI) +#define glVertexStream1dvATI (_GET_TLS_PROCTABLE()->VertexStream1dvATI) +#define glVertexStream2sATI (_GET_TLS_PROCTABLE()->VertexStream2sATI) +#define glVertexStream2svATI (_GET_TLS_PROCTABLE()->VertexStream2svATI) +#define glVertexStream2iATI (_GET_TLS_PROCTABLE()->VertexStream2iATI) +#define glVertexStream2ivATI (_GET_TLS_PROCTABLE()->VertexStream2ivATI) +#define glVertexStream2fATI (_GET_TLS_PROCTABLE()->VertexStream2fATI) +#define glVertexStream2fvATI (_GET_TLS_PROCTABLE()->VertexStream2fvATI) +#define glVertexStream2dATI (_GET_TLS_PROCTABLE()->VertexStream2dATI) +#define glVertexStream2dvATI (_GET_TLS_PROCTABLE()->VertexStream2dvATI) +#define glVertexStream3sATI (_GET_TLS_PROCTABLE()->VertexStream3sATI) +#define glVertexStream3svATI (_GET_TLS_PROCTABLE()->VertexStream3svATI) +#define glVertexStream3iATI (_GET_TLS_PROCTABLE()->VertexStream3iATI) +#define glVertexStream3ivATI (_GET_TLS_PROCTABLE()->VertexStream3ivATI) +#define glVertexStream3fATI (_GET_TLS_PROCTABLE()->VertexStream3fATI) +#define glVertexStream3fvATI (_GET_TLS_PROCTABLE()->VertexStream3fvATI) +#define glVertexStream3dATI (_GET_TLS_PROCTABLE()->VertexStream3dATI) +#define glVertexStream3dvATI (_GET_TLS_PROCTABLE()->VertexStream3dvATI) +#define glVertexStream4sATI (_GET_TLS_PROCTABLE()->VertexStream4sATI) +#define glVertexStream4svATI (_GET_TLS_PROCTABLE()->VertexStream4svATI) +#define glVertexStream4iATI (_GET_TLS_PROCTABLE()->VertexStream4iATI) +#define glVertexStream4ivATI (_GET_TLS_PROCTABLE()->VertexStream4ivATI) +#define glVertexStream4fATI (_GET_TLS_PROCTABLE()->VertexStream4fATI) +#define glVertexStream4fvATI (_GET_TLS_PROCTABLE()->VertexStream4fvATI) +#define glVertexStream4dATI (_GET_TLS_PROCTABLE()->VertexStream4dATI) +#define glVertexStream4dvATI (_GET_TLS_PROCTABLE()->VertexStream4dvATI) +#define glNormalStream3bATI (_GET_TLS_PROCTABLE()->NormalStream3bATI) +#define glNormalStream3bvATI (_GET_TLS_PROCTABLE()->NormalStream3bvATI) +#define glNormalStream3sATI (_GET_TLS_PROCTABLE()->NormalStream3sATI) +#define glNormalStream3svATI (_GET_TLS_PROCTABLE()->NormalStream3svATI) +#define glNormalStream3iATI (_GET_TLS_PROCTABLE()->NormalStream3iATI) +#define glNormalStream3ivATI (_GET_TLS_PROCTABLE()->NormalStream3ivATI) +#define glNormalStream3fATI (_GET_TLS_PROCTABLE()->NormalStream3fATI) +#define glNormalStream3fvATI (_GET_TLS_PROCTABLE()->NormalStream3fvATI) +#define glNormalStream3dATI (_GET_TLS_PROCTABLE()->NormalStream3dATI) +#define glNormalStream3dvATI (_GET_TLS_PROCTABLE()->NormalStream3dvATI) +#define glClientActiveVertexStreamATI (_GET_TLS_PROCTABLE()->ClientActiveVertexStreamATI) +#define glVertexBlendEnviATI (_GET_TLS_PROCTABLE()->VertexBlendEnviATI) +#define glVertexBlendEnvfATI (_GET_TLS_PROCTABLE()->VertexBlendEnvfATI) +#define glElementPointerATI (_GET_TLS_PROCTABLE()->ElementPointerATI) +#define glDrawElementArrayATI (_GET_TLS_PROCTABLE()->DrawElementArrayATI) +#define glDrawRangeElementArrayATI (_GET_TLS_PROCTABLE()->DrawRangeElementArrayATI) +#define glDrawMeshArraysSUN (_GET_TLS_PROCTABLE()->DrawMeshArraysSUN) +#define glGenOcclusionQueriesNV (_GET_TLS_PROCTABLE()->GenOcclusionQueriesNV) +#define glDeleteOcclusionQueriesNV (_GET_TLS_PROCTABLE()->DeleteOcclusionQueriesNV) +#define glIsOcclusionQueryNV (_GET_TLS_PROCTABLE()->IsOcclusionQueryNV) +#define glBeginOcclusionQueryNV (_GET_TLS_PROCTABLE()->BeginOcclusionQueryNV) +#define glEndOcclusionQueryNV (_GET_TLS_PROCTABLE()->EndOcclusionQueryNV) +#define glGetOcclusionQueryivNV (_GET_TLS_PROCTABLE()->GetOcclusionQueryivNV) +#define glGetOcclusionQueryuivNV (_GET_TLS_PROCTABLE()->GetOcclusionQueryuivNV) +#define glPointParameteriNV (_GET_TLS_PROCTABLE()->PointParameteriNV) +#define glPointParameterivNV (_GET_TLS_PROCTABLE()->PointParameterivNV) +#define glActiveStencilFaceEXT (_GET_TLS_PROCTABLE()->ActiveStencilFaceEXT) +#define glElementPointerAPPLE (_GET_TLS_PROCTABLE()->ElementPointerAPPLE) +#define glDrawElementArrayAPPLE (_GET_TLS_PROCTABLE()->DrawElementArrayAPPLE) +#define glDrawRangeElementArrayAPPLE (_GET_TLS_PROCTABLE()->DrawRangeElementArrayAPPLE) +#define glMultiDrawElementArrayAPPLE (_GET_TLS_PROCTABLE()->MultiDrawElementArrayAPPLE) +#define glMultiDrawRangeElementArrayAPPLE (_GET_TLS_PROCTABLE()->MultiDrawRangeElementArrayAPPLE) +#define glGenFencesAPPLE (_GET_TLS_PROCTABLE()->GenFencesAPPLE) +#define glDeleteFencesAPPLE (_GET_TLS_PROCTABLE()->DeleteFencesAPPLE) +#define glSetFenceAPPLE (_GET_TLS_PROCTABLE()->SetFenceAPPLE) +#define glIsFenceAPPLE (_GET_TLS_PROCTABLE()->IsFenceAPPLE) +#define glTestFenceAPPLE (_GET_TLS_PROCTABLE()->TestFenceAPPLE) +#define glFinishFenceAPPLE (_GET_TLS_PROCTABLE()->FinishFenceAPPLE) +#define glTestObjectAPPLE (_GET_TLS_PROCTABLE()->TestObjectAPPLE) +#define glFinishObjectAPPLE (_GET_TLS_PROCTABLE()->FinishObjectAPPLE) +#define glBindVertexArrayAPPLE (_GET_TLS_PROCTABLE()->BindVertexArrayAPPLE) +#define glDeleteVertexArraysAPPLE (_GET_TLS_PROCTABLE()->DeleteVertexArraysAPPLE) +#define glGenVertexArraysAPPLE (_GET_TLS_PROCTABLE()->GenVertexArraysAPPLE) +#define glIsVertexArrayAPPLE (_GET_TLS_PROCTABLE()->IsVertexArrayAPPLE) +#define glVertexArrayRangeAPPLE (_GET_TLS_PROCTABLE()->VertexArrayRangeAPPLE) +#define glFlushVertexArrayRangeAPPLE (_GET_TLS_PROCTABLE()->FlushVertexArrayRangeAPPLE) +#define glVertexArrayParameteriAPPLE (_GET_TLS_PROCTABLE()->VertexArrayParameteriAPPLE) +#define glDrawBuffersATI (_GET_TLS_PROCTABLE()->DrawBuffersATI) +#define glProgramNamedParameter4fNV (_GET_TLS_PROCTABLE()->ProgramNamedParameter4fNV) +#define glProgramNamedParameter4dNV (_GET_TLS_PROCTABLE()->ProgramNamedParameter4dNV) +#define glProgramNamedParameter4fvNV (_GET_TLS_PROCTABLE()->ProgramNamedParameter4fvNV) +#define glProgramNamedParameter4dvNV (_GET_TLS_PROCTABLE()->ProgramNamedParameter4dvNV) +#define glGetProgramNamedParameterfvNV (_GET_TLS_PROCTABLE()->GetProgramNamedParameterfvNV) +#define glGetProgramNamedParameterdvNV (_GET_TLS_PROCTABLE()->GetProgramNamedParameterdvNV) +#define glVertex2hNV (_GET_TLS_PROCTABLE()->Vertex2hNV) +#define glVertex2hvNV (_GET_TLS_PROCTABLE()->Vertex2hvNV) +#define glVertex3hNV (_GET_TLS_PROCTABLE()->Vertex3hNV) +#define glVertex3hvNV (_GET_TLS_PROCTABLE()->Vertex3hvNV) +#define glVertex4hNV (_GET_TLS_PROCTABLE()->Vertex4hNV) +#define glVertex4hvNV (_GET_TLS_PROCTABLE()->Vertex4hvNV) +#define glNormal3hNV (_GET_TLS_PROCTABLE()->Normal3hNV) +#define glNormal3hvNV (_GET_TLS_PROCTABLE()->Normal3hvNV) +#define glColor3hNV (_GET_TLS_PROCTABLE()->Color3hNV) +#define glColor3hvNV (_GET_TLS_PROCTABLE()->Color3hvNV) +#define glColor4hNV (_GET_TLS_PROCTABLE()->Color4hNV) +#define glColor4hvNV (_GET_TLS_PROCTABLE()->Color4hvNV) +#define glTexCoord1hNV (_GET_TLS_PROCTABLE()->TexCoord1hNV) +#define glTexCoord1hvNV (_GET_TLS_PROCTABLE()->TexCoord1hvNV) +#define glTexCoord2hNV (_GET_TLS_PROCTABLE()->TexCoord2hNV) +#define glTexCoord2hvNV (_GET_TLS_PROCTABLE()->TexCoord2hvNV) +#define glTexCoord3hNV (_GET_TLS_PROCTABLE()->TexCoord3hNV) +#define glTexCoord3hvNV (_GET_TLS_PROCTABLE()->TexCoord3hvNV) +#define glTexCoord4hNV (_GET_TLS_PROCTABLE()->TexCoord4hNV) +#define glTexCoord4hvNV (_GET_TLS_PROCTABLE()->TexCoord4hvNV) +#define glMultiTexCoord1hNV (_GET_TLS_PROCTABLE()->MultiTexCoord1hNV) +#define glMultiTexCoord1hvNV (_GET_TLS_PROCTABLE()->MultiTexCoord1hvNV) +#define glMultiTexCoord2hNV (_GET_TLS_PROCTABLE()->MultiTexCoord2hNV) +#define glMultiTexCoord2hvNV (_GET_TLS_PROCTABLE()->MultiTexCoord2hvNV) +#define glMultiTexCoord3hNV (_GET_TLS_PROCTABLE()->MultiTexCoord3hNV) +#define glMultiTexCoord3hvNV (_GET_TLS_PROCTABLE()->MultiTexCoord3hvNV) +#define glMultiTexCoord4hNV (_GET_TLS_PROCTABLE()->MultiTexCoord4hNV) +#define glMultiTexCoord4hvNV (_GET_TLS_PROCTABLE()->MultiTexCoord4hvNV) +#define glFogCoordhNV (_GET_TLS_PROCTABLE()->FogCoordhNV) +#define glFogCoordhvNV (_GET_TLS_PROCTABLE()->FogCoordhvNV) +#define glSecondaryColor3hNV (_GET_TLS_PROCTABLE()->SecondaryColor3hNV) +#define glSecondaryColor3hvNV (_GET_TLS_PROCTABLE()->SecondaryColor3hvNV) +#define glVertexWeighthNV (_GET_TLS_PROCTABLE()->VertexWeighthNV) +#define glVertexWeighthvNV (_GET_TLS_PROCTABLE()->VertexWeighthvNV) +#define glVertexAttrib1hNV (_GET_TLS_PROCTABLE()->VertexAttrib1hNV) +#define glVertexAttrib1hvNV (_GET_TLS_PROCTABLE()->VertexAttrib1hvNV) +#define glVertexAttrib2hNV (_GET_TLS_PROCTABLE()->VertexAttrib2hNV) +#define glVertexAttrib2hvNV (_GET_TLS_PROCTABLE()->VertexAttrib2hvNV) +#define glVertexAttrib3hNV (_GET_TLS_PROCTABLE()->VertexAttrib3hNV) +#define glVertexAttrib3hvNV (_GET_TLS_PROCTABLE()->VertexAttrib3hvNV) +#define glVertexAttrib4hNV (_GET_TLS_PROCTABLE()->VertexAttrib4hNV) +#define glVertexAttrib4hvNV (_GET_TLS_PROCTABLE()->VertexAttrib4hvNV) +#define glVertexAttribs1hvNV (_GET_TLS_PROCTABLE()->VertexAttribs1hvNV) +#define glVertexAttribs2hvNV (_GET_TLS_PROCTABLE()->VertexAttribs2hvNV) +#define glVertexAttribs3hvNV (_GET_TLS_PROCTABLE()->VertexAttribs3hvNV) +#define glVertexAttribs4hvNV (_GET_TLS_PROCTABLE()->VertexAttribs4hvNV) +#define glPixelDataRangeNV (_GET_TLS_PROCTABLE()->PixelDataRangeNV) +#define glFlushPixelDataRangeNV (_GET_TLS_PROCTABLE()->FlushPixelDataRangeNV) +#define glPrimitiveRestartNV (_GET_TLS_PROCTABLE()->PrimitiveRestartNV) +#define glPrimitiveRestartIndexNV (_GET_TLS_PROCTABLE()->PrimitiveRestartIndexNV) +#define glMapObjectBufferATI (_GET_TLS_PROCTABLE()->MapObjectBufferATI) +#define glUnmapObjectBufferATI (_GET_TLS_PROCTABLE()->UnmapObjectBufferATI) +#define glStencilOpSeparateATI (_GET_TLS_PROCTABLE()->StencilOpSeparateATI) +#define glStencilFuncSeparateATI (_GET_TLS_PROCTABLE()->StencilFuncSeparateATI) +#define glVertexAttribArrayObjectATI (_GET_TLS_PROCTABLE()->VertexAttribArrayObjectATI) +#define glGetVertexAttribArrayObjectfvATI (_GET_TLS_PROCTABLE()->GetVertexAttribArrayObjectfvATI) +#define glGetVertexAttribArrayObjectivATI (_GET_TLS_PROCTABLE()->GetVertexAttribArrayObjectivATI) +#define glDepthBoundsEXT (_GET_TLS_PROCTABLE()->DepthBoundsEXT) +#define glBlendEquationSeparateEXT (_GET_TLS_PROCTABLE()->BlendEquationSeparateEXT) +#define glAddSwapHintRectWIN (_GET_TLS_PROCTABLE()->AddSwapHintRectWIN) +#ifdef _WIN32 +#define wglCreateBufferRegionARB (_GET_TLS_PROCTABLE()->CreateBufferRegionARB) +#define wglDeleteBufferRegionARB (_GET_TLS_PROCTABLE()->DeleteBufferRegionARB) +#define wglSaveBufferRegionARB (_GET_TLS_PROCTABLE()->SaveBufferRegionARB) +#define wglRestoreBufferRegionARB (_GET_TLS_PROCTABLE()->RestoreBufferRegionARB) +#define wglGetExtensionsStringARB (_GET_TLS_PROCTABLE()->GetExtensionsStringARB) +#define wglGetPixelFormatAttribivARB (_GET_TLS_PROCTABLE()->GetPixelFormatAttribivARB) +#define wglGetPixelFormatAttribfvARB (_GET_TLS_PROCTABLE()->GetPixelFormatAttribfvARB) +#define wglChoosePixelFormatARB (_GET_TLS_PROCTABLE()->ChoosePixelFormatARB) +#define wglMakeContextCurrentARB (_GET_TLS_PROCTABLE()->MakeContextCurrentARB) +#define wglGetCurrentReadDCARB (_GET_TLS_PROCTABLE()->GetCurrentReadDCARB) +#define wglCreatePbufferARB (_GET_TLS_PROCTABLE()->CreatePbufferARB) +#define wglGetPbufferDCARB (_GET_TLS_PROCTABLE()->GetPbufferDCARB) +#define wglReleasePbufferDCARB (_GET_TLS_PROCTABLE()->ReleasePbufferDCARB) +#define wglDestroyPbufferARB (_GET_TLS_PROCTABLE()->DestroyPbufferARB) +#define wglQueryPbufferARB (_GET_TLS_PROCTABLE()->QueryPbufferARB) +#define wglBindTexImageARB (_GET_TLS_PROCTABLE()->BindTexImageARB) +#define wglReleaseTexImageARB (_GET_TLS_PROCTABLE()->ReleaseTexImageARB) +#define wglSetPbufferAttribARB (_GET_TLS_PROCTABLE()->SetPbufferAttribARB) +#define wglCreateDisplayColorTableEXT (_GET_TLS_PROCTABLE()->CreateDisplayColorTableEXT) +#define wglLoadDisplayColorTableEXT (_GET_TLS_PROCTABLE()->LoadDisplayColorTableEXT) +#define wglBindDisplayColorTableEXT (_GET_TLS_PROCTABLE()->BindDisplayColorTableEXT) +#define wglDestroyDisplayColorTableEXT (_GET_TLS_PROCTABLE()->DestroyDisplayColorTableEXT) +#define wglGetExtensionsStringEXT (_GET_TLS_PROCTABLE()->GetExtensionsStringEXT) +#define wglMakeContextCurrentEXT (_GET_TLS_PROCTABLE()->MakeContextCurrentEXT) +#define wglGetCurrentReadDCEXT (_GET_TLS_PROCTABLE()->GetCurrentReadDCEXT) +#define wglCreatePbufferEXT (_GET_TLS_PROCTABLE()->CreatePbufferEXT) +#define wglGetPbufferDCEXT (_GET_TLS_PROCTABLE()->GetPbufferDCEXT) +#define wglReleasePbufferDCEXT (_GET_TLS_PROCTABLE()->ReleasePbufferDCEXT) +#define wglDestroyPbufferEXT (_GET_TLS_PROCTABLE()->DestroyPbufferEXT) +#define wglQueryPbufferEXT (_GET_TLS_PROCTABLE()->QueryPbufferEXT) +#define wglGetPixelFormatAttribivEXT (_GET_TLS_PROCTABLE()->GetPixelFormatAttribivEXT) +#define wglGetPixelFormatAttribfvEXT (_GET_TLS_PROCTABLE()->GetPixelFormatAttribfvEXT) +#define wglChoosePixelFormatEXT (_GET_TLS_PROCTABLE()->ChoosePixelFormatEXT) +#define wglSwapIntervalEXT (_GET_TLS_PROCTABLE()->SwapIntervalEXT) +#define wglGetSwapIntervalEXT (_GET_TLS_PROCTABLE()->GetSwapIntervalEXT) +#define wglAllocateMemoryNV (_GET_TLS_PROCTABLE()->AllocateMemoryNV) +#define wglFreeMemoryNV (_GET_TLS_PROCTABLE()->FreeMemoryNV) +#define wglGetSyncValuesOML (_GET_TLS_PROCTABLE()->GetSyncValuesOML) +#define wglGetMscRateOML (_GET_TLS_PROCTABLE()->GetMscRateOML) +#define wglSwapBuffersMscOML (_GET_TLS_PROCTABLE()->SwapBuffersMscOML) +#define wglSwapLayerBuffersMscOML (_GET_TLS_PROCTABLE()->SwapLayerBuffersMscOML) +#define wglWaitForMscOML (_GET_TLS_PROCTABLE()->WaitForMscOML) +#define wglWaitForSbcOML (_GET_TLS_PROCTABLE()->WaitForSbcOML) +#define wglGetDigitalVideoParametersI3D (_GET_TLS_PROCTABLE()->GetDigitalVideoParametersI3D) +#define wglSetDigitalVideoParametersI3D (_GET_TLS_PROCTABLE()->SetDigitalVideoParametersI3D) +#define wglGetGammaTableParametersI3D (_GET_TLS_PROCTABLE()->GetGammaTableParametersI3D) +#define wglSetGammaTableParametersI3D (_GET_TLS_PROCTABLE()->SetGammaTableParametersI3D) +#define wglGetGammaTableI3D (_GET_TLS_PROCTABLE()->GetGammaTableI3D) +#define wglSetGammaTableI3D (_GET_TLS_PROCTABLE()->SetGammaTableI3D) +#define wglEnableGenlockI3D (_GET_TLS_PROCTABLE()->EnableGenlockI3D) +#define wglDisableGenlockI3D (_GET_TLS_PROCTABLE()->DisableGenlockI3D) +#define wglIsEnabledGenlockI3D (_GET_TLS_PROCTABLE()->IsEnabledGenlockI3D) +#define wglGenlockSourceI3D (_GET_TLS_PROCTABLE()->GenlockSourceI3D) +#define wglGetGenlockSourceI3D (_GET_TLS_PROCTABLE()->GetGenlockSourceI3D) +#define wglGenlockSourceEdgeI3D (_GET_TLS_PROCTABLE()->GenlockSourceEdgeI3D) +#define wglGetGenlockSourceEdgeI3D (_GET_TLS_PROCTABLE()->GetGenlockSourceEdgeI3D) +#define wglGenlockSampleRateI3D (_GET_TLS_PROCTABLE()->GenlockSampleRateI3D) +#define wglGetGenlockSampleRateI3D (_GET_TLS_PROCTABLE()->GetGenlockSampleRateI3D) +#define wglGenlockSourceDelayI3D (_GET_TLS_PROCTABLE()->GenlockSourceDelayI3D) +#define wglGetGenlockSourceDelayI3D (_GET_TLS_PROCTABLE()->GetGenlockSourceDelayI3D) +#define wglQueryGenlockMaxSourceDelayI3D (_GET_TLS_PROCTABLE()->QueryGenlockMaxSourceDelayI3D) +#define wglCreateImageBufferI3D (_GET_TLS_PROCTABLE()->CreateImageBufferI3D) +#define wglDestroyImageBufferI3D (_GET_TLS_PROCTABLE()->DestroyImageBufferI3D) +#define wglAssociateImageBufferEventsI3D (_GET_TLS_PROCTABLE()->AssociateImageBufferEventsI3D) +#define wglReleaseImageBufferEventsI3D (_GET_TLS_PROCTABLE()->ReleaseImageBufferEventsI3D) +#define wglEnableFrameLockI3D (_GET_TLS_PROCTABLE()->EnableFrameLockI3D) +#define wglDisableFrameLockI3D (_GET_TLS_PROCTABLE()->DisableFrameLockI3D) +#define wglIsEnabledFrameLockI3D (_GET_TLS_PROCTABLE()->IsEnabledFrameLockI3D) +#define wglQueryFrameLockMasterI3D (_GET_TLS_PROCTABLE()->QueryFrameLockMasterI3D) +#define wglGetFrameUsageI3D (_GET_TLS_PROCTABLE()->GetFrameUsageI3D) +#define wglBeginFrameTrackingI3D (_GET_TLS_PROCTABLE()->BeginFrameTrackingI3D) +#define wglEndFrameTrackingI3D (_GET_TLS_PROCTABLE()->EndFrameTrackingI3D) +#define wglQueryFrameTrackingI3D (_GET_TLS_PROCTABLE()->QueryFrameTrackingI3D) +#endif /* _WIN32 */ + +#ifndef _APP_PROCTABLE + +/* + * Applications can replace the following function with its own function + * for accessing thread local proc/context dependent proc table. + * The following default function works for most applications which + * are using the same device for all their contexts - even if + * the contexts are on different threads. + */ + +static _inline _GLextensionProcs *_GET_TLS_PROCTABLE(void) + +{ + extern _GLextensionProcs _extensionProcs; + + return (&_extensionProcs); +} + +#else + +/* + * Application should replace this compiled function with + * an inlined function for maximum performance. + */ + +extern _GLextensionProcs *_GET_TLS_PROCTABLE(void); + +#endif + +/* + * Provide an initialization function for the application + * to initialize its own proc tables in case the application + * needs to use multiple proc tables. + */ + +static _inline void _InitExtensionProcs(_GLextensionProcs *appProcs) +{ + extern _GLextensionProcs _extensionProcs; + + *appProcs = _extensionProcs; +} + +#ifdef __cplusplus +} +#endif + + +#endif /* _GLPROCS_H_ */ diff --git a/plugins/zzogl-pg-cg/opengl/linux_replay.cpp b/plugins/zzogl-pg-cg/opengl/linux_replay.cpp new file mode 100644 index 000000000..28ca68808 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/linux_replay.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2011-2012 Hainaut gregory + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "GS.h" + +EXPORT_C_(void) GSsetLogDir(const char* dir); +EXPORT_C_(void) GSsetSettingsDir(const char* dir); +EXPORT_C_(void) GSReplay(char* lpszCmdLine); + + +void help() +{ + fprintf(stderr, "Loader gs file\n"); + fprintf(stderr, "ARG1 Ini directory\n"); + fprintf(stderr, "ARG2 .gs file\n"); + exit(1); +} + +int main ( int argc, char *argv[] ) +{ + if ( argc < 2 ) help(); + + GSsetSettingsDir(argv[1]); + GSsetLogDir("/tmp"); + GSReplay(argv[2]); +} + diff --git a/plugins/zzogl-pg-cg/opengl/ps2hw.dat b/plugins/zzogl-pg-cg/opengl/ps2hw.dat new file mode 100644 index 0000000000000000000000000000000000000000..2d3b43cae0cdc3de4925148f558b574b9dd1d7ea GIT binary patch literal 113923 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%0D$dh7L)rEwD_|~-_dBVHX zwTEBL&n~V*TQ0tS{q4T>g46?E`-b6727iz1{f7~D+3c6AX;|QlLj&s}nk`2;4Yd^@ z5RCBVQ=kC;78jJCis-aU3fRsGA7+^}L#B*w8)o>|?v0FwpQN!tl=D~70X-dzk(rM^n963(zQO59pR(1JZHRT;YvitvTEiG5?v{E`& zKo)+d;70bJ;FhA-kBp6NdVm%xF%b+ln`h9Eg#i zVgF~t>aQoChrPU&609emi!Ha3A`xIROMfn*27xx8iq5}8h)p|*vB=@|G+fM2} z9V+ht;-lnqefd^@+o5yylgm-?Zo~VO`B7*Wk&o}O7a;$F1UAtsQE8;L(wFvBdF`LZ zXoGGT+oLqyMzx4u?+yl zkWd)P;TB}b;cpTUhC?w7TzJ?S4u>_#30sxG_xAfW7){(iuI_p{| zRgLw75RQtb@bBjsS&tolnk9wl@reVCSmG$C;^KZ`6b%*lz@W5<{JPEEiq)=JD!T1E-l6mr4NXflIhN8G_CGLu#IJWA{ATAw{T0V9i9&83gOo&0E{<}ICk4l@ zeSO4yAEKa#h6U~mcmae#;sO;o3!T{)z)hux#!xY`r*v>Iv!}F^MYf3xl?TaX4*8?6 z1shEu;h22a1>(v11J~wUDIaxcz2I8~LRh*>dDF?+ZZfKz@I=9kEMVC)(u*ud@9~M~ zMadR3oqlQ5rP05UisnQ$_s;v(X!QN0J4Dvh`@;!%$n}SE=pPkIgq4vgIecEdmh+L{ zTHwExwC-bWI^6ND>V?)mV|WG;0$qGUQ<<299k|E))>Z-n^kjL>_(1-Q zKr8tMM5K{HM|;-33X1x3H=Gi;C5;?evM1Fk5TEf41JvyG$&t?#)a>=K!-F$p)f%<( zBJg-c=!}uoDVH@-ti{Xqn>4jggDq2hx0bHsmu@X#v{(oVFc|>kYvV~BAN(ki5Yqf8 zv_?dQq~R)zN#JQ=DNeF%PP5cDJ0rapx3p@*Wr#@Go!3Vf(`t`rhbMnBf4XYksJE#F2h+gM;sYT1+AFmzna_ zCN&kEutB7j5A!-fR|=$U-_j6GGPX$K8|t>QxBv=6Q9^FGmJbb0swM{fRVQT_&aCxE*^Ea7FhLJBJ{Sr*7^=T?S>Vl2){_GDH(}_YvMklRFF^zS zO_J~yiw!?yD~PH*8&AJ&mH$9doTQp5cl%k=K)dAi>Jqi1^b`Fh=pFVzPUzd0Uq|oy z-l}@|MG*L934J zxb|tY02|M;_3%PT;Z{ls+Y?PD9xK&BRRmF{Sa_gVA?pcNCr6bs zIH-n`j#h7cs(m23tiN2{>r*8=^+oUGPgl*mDLv#*k3NA&%7ggOlih^AMjcx_Mi`+} zy$}OYy|q{l9ar7)K9bH(vIrvFGlZb!vnZ)fr&h;~N$Bk>GU zn~+A_cn`6i${yO}AhG`(08?gk9Oe1|wxX+!LIB;9{7QYKq$S&<1z;{^0 z<7`m>_4bnfW-yc#%6@y?U*5&*aCkca@>uW8sHI_mi|oq>z!MV-Xz(UO#R`@%m<7jD z;Er3lZtl&etur^=3kkcAgR5&E zq+So>{44-GF_o+Yq!a_`XmyIZSRT)tASp$km1^(7oPdcYytp;o3%)uESY((w*GJ1j zZ)~_9OW7Yx<)|$^=UF+P-#g7skAAri5@^+uIX)7HK@|-`Ar*&l!V)c0 zLxUlGI|oB58ipdPr!(T`YzvGGUPO8H7jsjf3-LIK=i9wvm7^l8cC}lvs)PT7qH}GA z7f`Lbr^%D)C4>Jl1oUJ{`D3KIHjOn-uut-WEPQCMfjtfZROq(}0}XtL;QpQ3NZtwH zWY-_&!5Gkwg?(p;qB>ID6-`jA?ZrX>%kSVU{KvvrmDX@*IL8Lx`=Zx`Gtub+P{NrApYe}#CHfF>Y~Kw{_#r?s;R_W9 z>RO|HW7_J{xw}*{urARDuKxz(4WuyG`+vad(Zkg%PTdfqbsL@@)z5E&x3&!ECy|Felg_aWPWhI`#wU1 zZTJ0cZm>5JraFQskt$l~T-U}zS7o~kbA?WgS6iO|y^jA468mO*s=B!{5O)^)@nXF7 zU)&kj@(`}rd&Ic$V9f-4U5yuGnVP?8XJ0yB)6N(#h3a8nfV8vxS|IIA?Km6$#Z_)s z{es-2eYWn}Wqveh_Q;}Oij>LCV_5yW8^g@Tt;9$EA2QsnT^jAZCr~B$nYP!88sJ34 z30F{|&!oO1#J2$ac^v&Zq(G4iKjMpV3wW(XJ?{^Ty~O?*IRL!Y+IvX|;4SWbR0}HCeE}K>mfI9!)ehELXB-V8zjA z5OgD(%7W?BWJ%_T3VzYkG{qU;kUPB!HqFH~hf4Q1b<9tzK(rEJpP3ls*!QgvW*_*3 zCBhyV`IV)T()gVY8;4j6!)E=>J=$hHLSYo8(+}kE7Mh^V`W*ru=qZ1ve=vyYVEf*- zyy}@mE|Z*FZDg3&QDujqt&E8Wn~OqVl`Ak$umo=+Bq?jnMV=e$GO#g@KHhLHX)$kEAAM#5k%1q(3hfcLtzZ5C88dS2|(7LN!#j2eZT>!9!-E40W_Ty_RVJkn%PDu zm2OPnkh2DX@l35GZ6c_0&>|N?rw6MR(i-ePVCzq|Vm5lKL)DW!$Y?}POkq6dq-Pzs zAR_}~ij?tT^TC8Ni2Yp`o~$=iPOsTDE&#Ogy2&xqJM0`jngAbQ5sX%)OYV9Dla-So6?Z)qqN1P89qnYy} z;S;1zBLr-re<7uH0#Q~Gv{OjojaLcwPSeqKj9_gFjwzd!m7%AsN|fgnb@kP-78yRR z<*P)h=s(5kh7@#s&?MBEVXxy;b`JKgI7`b1i1fY6XpF2_3__peUY}PJO`C*91=9^K z4-=(LfhKNQs<&muinpMy3_G&uh=RRR9y$Q14ohDyMg?9++B>BurbNJzm4K5{N}*EW z7LZLm$7VX>?0`I1GYakE)3)e;DA)!)C>Uy|VigBl7-*-e$0Nd|sw)>$x<_Nr_cgLG zqT)ZK?tfe(xH>N8)K9|?P7I(dHaZaz#o5PD&Sy18zzZD8{SQ1W5OfwnWsI5BK^rx4 z0}5khc9*EUx_F#Pk4`OkyGn@v$;ip1Sl)XJNT-971}u^hcp@X`0X?-M{LXs|nIg)h zHOrgu&UT`&cy0re)c0FQ%fxX09G_D~J4)d2${UI9{G z0XpWuCk_USmd+HXoGQ%|LVd0w?x|Si42!FzHF-<+vdKcO`Pg%@)^$a3n?t~ab(iDw z-_*5K2CB$W!+HSdH;e(#_MZA4V=30vW`OW7gFP`Q}}leq$B3)$lX+n6H&U z=o)o6qFCxd#xPn1No5(k?LXRps{=X5hUmFXn=r5upbhqoAW2?n1Ei`Wj>Rv;XMbsf zFU9`)=w=LYo>x@ZcCQw!ckznp$|o>c_`<&d+Tf(EYZgCi?9R|-sf=MOMCLu7oCSl4 zvDbwAQNqlSG7qX^5c;k-0O$8QEwLUpJaNDeXp*u<+gOjk1sJjVDiYLE#no%}!nn4e z>SDqF*NYEkkoEZ!M4w-6@mv2|W702!!8Y$!AcQri2ZNoCPE%cyAq?i7qu&_F`LlR> z!p3B|H9+qQcCFyLhGZF-0f6;{c?bM4fjif_ET9i@1(&p5Vr6wt)ObZp&$U=v?i~Ra zzd;n!5GQO-ueGTp$q&g~SFa30OYu_lj8)l~Vm>rXGuDQDt54ynHQHm@lT%ryovbwy zYF~GO#tgD~)NV6hXEunApX9@`?;0^bL~PVyczj}KVIMDdUY7Yuvl#ePG!o4?WEGc{ z<=XUN3FykuHcsV0q}mi1t9TD<6&I&mh(RkM3jhZcoHVVnHU)K2pmK=KTv}0LJR8G- z+{vDD$d`3CTe-1o>#~w+n44PsrX6Nc_%_u~lioIPeCQ}sNiQ{6P)#qrQF+FA zH>d;v#}I~Q{PI-#7OJGy>Ygz?{lBqnI7L;UST^%b zAeIe|D@I4c8i-}1!xBmnxlF#SqEjC`FAO{a#j=Sl_6wmf@*eNVxkO#wzQ(Bbd~*}#ZJs~oht&aAuI0wcnbP#Lv6Hq^>HSi zyr>KK)NsM;dVyJqR)3#wbQ9B=Q3taT(V4+&#C%GU8u|6cJn}mjFoLv^(Q6$0<+rf} zJ)xlUmP^i)mLa{+#D8L!nWs%*E*F7D#g7fRz8xEQF+d#iV^e?*U>nUx;3ou?HiXl% z`3aAv@L3ZWU`>iGq7~nom~&F8I&Ils2DRYr^YAG8|7{|ex3?mI9!^_!0P1c8q4twx z1ZEDqc)--j5zqaF>&5z_vysiv#oBj1>drWh7WJ0AkmU?nr!mrvS@x%Gi}m0uwB3%U zsLu4TS{v+Mv1>R8WZ;U@8KOh(4wJn@p{~;*mK-33RuRkW9w}$YN;K@gArXMBE-bLx z9+Ed%qrDii_;v032X6Hri7hOG=e3Ay`bl=uo=NU8QyOYDDl=I%6|uk0>#3he(wQy% ziomee`o61dg|p!t65)2}7_m4742R0!IkIW-&J{Od)uJm)T}2O?_J6P|<`% zY1nb*pm4YhCfGBVs1*9t|364p6kOJ`fc`EoELhnX=$V_%_g(rFP9iku?EUcC?1B4n ziH1-F=)Cp!*cGlg1KiIJiXQk@kcbEQW08tS!oOt|p*9v-YYGa(nyY3ke9|5*OzWTj z77CDJV}{o{wvya8K6CNtq&a}a*9w7oZewNg(a5t7FX8UII+hI(ik z6sT+r>N$vt#n2+%hLMRg2pX4-n{|?%rWGuqfCKAy=zU)oLrg0U7bjYXLMyKem#{ue z%+_r@O={66+KurbkG`bG<)AE`{$4sgwtaC&=zpxw*qOwV^4gHgyHq$?hd7(c zzdk>B{}j({rD2MQ+{>`BHhXTt|ymBhT zc`}s+xr}_GkBd+YcLk}K(5HG`aafSNgO!>nSV52mA^@oBgRYI%@P-9?pt=OsfTSP; z41D`QfVpjO4Ap+Y6GOTVDNuPA4FDD3%cLEpk%3z#Dhfb~CrYN+2qUVkn;AwbNLsOU zNKR4yvCK89q_@=71jQk`I0U*(0nwm|{-4(z09b(WTq-sh(pcUr_ap9T9_%en5eh{X zFBVBgwpo+>=lFBcQ<6McK9AxL`a~E?(eU?V0AR@|8v-Xm6~lw`JaO5#Y;4i2wVCjASC88V8}x6)Ci~_63h88e6L#=j@Bc_ zzvRJCC4TyUV`9j@z>xQau>ioV5Cm*ES{sFfq)>O8?JYB4hGV3HPh9U z!>x>CR8hLZvyZr743&L}A}RxN%cp)2zMO(OLUj<|d2@JPm!!KuEC3y$lO>p6S3vQu zJa^d*y6i_)#PUAezSnnUA$bak4HUOs8EgNnW+V7yl#BKQZGS$H^Ee(MS6fwmXd*Q+ zTMz(*mb9AbUKW=o`a%km8#J?%U9U=)SHVl$@e-DBf`!McN|Lf>!&qCW1sJjW&H$T@ zc{v^B^iJu3jwgn04&0EyU40%Lr2mDz9BLdzqW8#~-N@ zpEx~3xANSM2>~b)#QXx>W1nRK{hwQ?`8q*cj7;LgslWoA$Ga>`!rzWYMnCCx)l~qsaoiOW<$zq@ z!+=?B?o)gP}+nq$2U{hoD?(SvnK=^rPei?$P3Z;Fv9x`S(vz`p4W@IdP#8? zM~ytr&>%W0zU}z&k~SF!2rN4at7KXrg$X-WyCl9y_9+t6V+J}lbjEQ#NdHP6U<}JZ z-=pJmhr7q>lCYcAxmOR`TCx>r*^-M9DPM(?7u(HU9RF(4Euw4pp!e!7zo#dY- zim(HynWN$@V2M&^3CJO4S^+tP2?|(h$Fcq16GD_`nja|6}O6edfKbdY` zIJb{}bV+dkJ%3_kZ}ybk>BY#OkpDxw+rIn;>31ZQ+hWO3+?tV{clgsc>NOvW-z8__ zpO@Dx#&b+dp4#dExOu=DnN^$c@S7~2tWSMi&y}QW-QL&n`g3yMcfMWqW&Qd21U7SP zY$r0BMnfY!)4t`mpGPQBbfr*wNs8;m*V+e9@y9-?t%;rZ!K}|yR#yqfLP@8jS6Tc~ zdf;^_1XJ&fzbD$Aw;YztZ!7c`r8Yg*xP9xmB<_4bT3Q}lLe${Kt5#O^g}gjhi*k81 zI(Ki{>F;PPe~v^M)60SZQZ~9|4YnQGdzC-ZwBGj(p6BQZ|HUyl|KeveJ;u#`8|atfYThp>d9Tr9 z0Ia13jdHta-KAr&XjC$@-8!`LhxP`Po|L5>xnlDzj=mOSbBo%N-s~=<@Dc4{%1(>X zHKlodWFXfT@^8lN8f7b06CJ#+k;mKDiTIR@`cBf8Z-`F&YkrgYdT>!(-z6Mpc5B#9 zY)*k-bXDQMsp+pl!;SK2hB;=S1)O5RDd%XzgI*d2O*SFO{6R8~N~KT%YjO+7LRKaD zn}|%w*%k`KB4f+N1Mf2hDwB2)1tXL0z(IEGX27U4TGf1`;&6jOqau42&s&Nu-(+n~ zv}Q%4a7{yhO2cqXvg9xTJT&)mRkcCnvK&Q{`bdkovV|sDStC<2PI8>U>RxOf;>g;M zkVTSpHAC(t+@zNFcjt~s+HpxWnx17oF_%Va%nvi0!}K}N8xKZ6mX5N8XfZ6V<^(<# zW*2xES$-G|Swxs&Tp;v=4)`1 zS>>ZHFL)Z-TJUCcI=1u`8F+|+0aWPxMmy6f13aCocH!(%S8QMIHllU0=%OSlEIW2o zyj<-(;~p*eWJGY^LnVTl2;-8{pyx$+NLq=c6~33eHfIDj&wgwv)hB2EY}k;y!l_nd z6XoJK+j{CPEyGHp=?`rBtU8)&;aCvbx$Q2f^2kt%CX|MLI3!SEVE;kvC>zs&a5IiB z`H(+OAr%zR6{U+HRKf`5!=8~pWZ36@0K$2OA zT!SrhaDLDF{LlqF2wI3jlvec063S91jw3tk;oacMor#W;x_Th_`T?1rHGb+Yr5@l z6`^Y^{;8RB6f<+2d{YQ3CE_v5JoL?G7dHVIaMEDPei$T>{~#Gp1g;?gIFOOVidq)N zibgFbN&Dy5sAB9je932~$bZ$4fQO@yqK;N-NCJWq&u$oQ64bj8{Nu;5F)HP=$I}Z8 z4*yvQET!rhh-4y_O+m_zI9_XTv2wUVxH8f5Sh`oB0Vih)vln-{>uXU5Kh|l_Nj4)ag9p%fY&?qPtT833a6i~W6OOY^ z+T+ZN|Do|LI94z&zIqY5$mi}sV0jC4eD%m4Dp4*@@*Rxt7_@iQ<}`E)91 zV|0w}UBj|A%`ac^Mk^B{5m!_thxOK-59xkK3vxhDia5;>{0E_32Ih)<=}u8U(bE&s z4*@TY)h6E*!2*o^Kdb+Wq zT|ckV5=rgM(nBg#Q8VueBI*OeTps!L%H~y*i53u*i}}fmoE?bDZEvWd7~UC}n#Tj8 za?8b`?OvmDMZfJv0a3Z6wF*3!jX+fHhcdv#7i;{g3%y7to=PU2A_2R1@?$;xQ$Ll= zdlU=^ND-00(2JX3U{jhx2^Wt*FDwH4^h7GW8x>E{FR2*P6x=!#^=0r)m1B?NyFWaX z*+|bHm$oec7A6rM#KK%m(w^S~ER56H;o|wX`l@u-9N%F&CA(lX7d^G45=**UUEV2a zkCF@w3c}O`NV?|zKpFF=7B^$#YdvP_W>yApy;1hr2i}E2+y0YiGD(u9CndGC(=nNlQIde_*>DL z5PYrZNS+DR%lHBno!eNTqSM5bE$934=X~>{-Tp{h_3r*e4N0w{jhKXvE%&dH6Pzrl zU;WqalYNt|f!Qf8AIWuR=}O`O;YYQm*W zn&>;M{a0;$)T#9dwH}$ms(t*h;%)v!$`xaW43uG|Oz$rJRp{U|aw=6_%^ABMKGvl! z9Rb;j%_$35VMq|rv;sxf95Dn3Oe$zfTJCUvwPkO&3ZuB&)D8W(8N8wFdho9gN9Iw= z21anLBx!gAn`Q}EHYVj(-gmF61y6nrh-cmw$BKnC2GbJ$4{*vt806`(0vHOZ;McjO zbg{M+!EnKG>qHl4 zE!!JzIf9dgqow_Fq)9_7uT)WuHHt)qEC&Zh-vd_*Uis!Pu+dRYpjArGVECya-Hq&) z0hY8j-o3Pxx=|DU*Ki$6JtnCB`=87Jj(e?)>XeT zdh^DccwEYS8UBzd<*?Q0Bg=Zz@}}62Rv#`kom-xg`-a=`z6S%{ml|A!qAX&ySM_L@ z7c{0FlPjT_4zhrXxb5_LaGght(5-B~l&EAMM$`E%sgSl#&uOxd_(3IEOkvfi$v@xS1rBgoVY#Lv&aVf*kAZw6E`W|UO_V4u zP=YnMZj`DvZ6YQxk2;;mH&x0&Kk!R|ZhVW*|FGmS{jUB|f=ch1??FgS>9RgN6!7)w z;K<1u3;f*j+YH#?LBIlAyBSp(8gR-Itt?nrN(oWinyH{55>n~oru~5j5>j!3-UYnBB^wpfPH$Ig5=u zu~}iM=OMMqM-&Pj(Vhhd0V=Rp{~u@-`T%{d=w>W)LXZf_{b9B^={Me7uEll4XG|0DdbUPBPN45HDSsL~Z>_kyCIF2&=Dux7 zOMTM)iSldjII@8Ga>d7?4g82rcMY#Bi{IgHW0<)m<4W^CUtaVTZ~B#cVx?$gkWcR< z_=>!nrN*?$TdsNk$;61G?$0lW)P0F>{J*+(i*ph#I#cXDTeh=>TJlYl_IzO>pMYUc zFUFOi_{L%NjVvWdjU~T%~3yr^Nd%^q+m{a3%H9j=EEAjc~ z(@Q?#f`57R|3Dg@1ILu}KG0?>_Xdj;N0^**Mmn$kGDv*= zg}^u+DSqO;9RUP%-g>k?G?L?*{&1^GbZlIj%lbtXMdSADXKba5na|u>6dlUp(_qN! zSN8Sb)cvFOY?%lks7JUJ1?a1Aeq4_{aO!abJRUl(o7;|MS)A|gQ?;eT1w_bLa-oA5 zVud#>0tm?c{nxe29-59~h2&B(p{(MbWJHp-m8n^wE=1XZz&PEtb7TF6QrwxQB%8Dp;Y=s~uh2+@nz>pU)3RUUqI_|z zCkgf@Z6TxOpb^p8=JVO7N=sJT%3H#3Yo8)5*nDmGo9IL5t&}#0mbnq<- zXj#E~s^CgDvRO5FRpHf`$X{)En|RGI5zyoZj)i@Z*HQ0HZu+{hG!l-6=|$f%(D;!A zpDD1ZPHGI1mOIlW`-U&nQLGiII`C|Vuhn)>H^qwjjqWhsr`M@y0r(h2zf2F?pm;G= zCeEbDT^;6?i$X_e`O-UO=X=@iG;*64#3Y#-isT?l0~t-U{~)oIl9k!^7<#>v@q{t| zlcus|a%0zygIs$rVE8D=7%n>VCOu z6m70T8K$kqJpb7~rQK5Cq+>z4#W6OLLsRy>Iwz~i^+o@vu8m4-nXJypr;59MVo&9+ zS=r}X6MSAK#?n|K#i%reV`(i`0BB8vK?C5ERBRS>PC5y>6tc+NC<|%;1*Vp8EH4U0 z76Qg{v5IbmD}A*Zww^;(GUu>7SSt}!<;U)Yt$bt?%pmR`oQsFXi7%rt{bfwk*r%p6 zipml;_SM$tIb)C7Pm1+5o#&I@r)GNJne>yVtrKbfU+uJ-D+0V3(S!z(u!zZcKOpn3;wGl^H%zmhrV3Q1w;ez8fE*<}E@gdIG9JNWQ=^|vbghWBL-|5q=U-LiY6 zG(vS;x|Q`dfy1&pH|uilv$HmaGLs|SyI`>$6dnj9f3XM)2kGibaQl%&-T~mhpjenk z4=MSez!2dXWUPGo`Ta#*kfCA(?>;V31TVFfiH6DE{&l~hBH&vcIKIQyTImP6GVI>Z z%wRmpIO3klCzz1 zJ~%dDJ(O1p8kCO1Y%r>u>UYuy#wti@ioAueXo!hoo=@i&Mg;dgnri!zs^-yv17EDA zP>V+SW9eZ*x}D^r_i|n)lKPzwklge9Tc_^v>d5!`p=I%I`_J$F;dj1I%b^Yoi&zhW zuj`xb%XLcVbd1}yZ+nODGkbSL&0fXN(@t-fCycY}o6x&*kIGx(inU?eKQ#=sD=Cai zfAp2aQ6mQp(d$=;-1-emus&=U^=M6-^c&9Ctt9gODZQp2DA%TY-l9w6CPN7RWHF^Y zQEjcTjpVd}241*r<3t=1L~0<7g9ZR4KLxRv>{u+D-eCl2ZqBNt@4`Tu!AW823mVOz zf^lZ4jg@EhO%n?P(QZ<@=fAd&|Kq0?eF8SDGkpWja|;#S0yFxCpbSh3j?pji*W{r1 z)&-X>Eh)z1=Gkq(ggvS*1a_~4eVp-8#y(jqjEf({JNvkKsCPqz2SJGwl}NF!@78|1 z%6^}@OyNxb*uCu`>7i{)CHvc+eFK5JfASy9xitjdii5sN9k?F(;N0T|Z}?=nZuEpL zU*IfX`Z#bneOa_D<%@A-qhfZAe&Ps)#IPpvIo|)o5i6tKGddWHSbfw4_G_RqEzCq0 zN$jugYtn@uAGW1@w(HKGl(A+_TGzOgXHyV@*FJa0e6r=s)pGgGg~k?kM+@_T@3)cgfj6i(RY-j9 zpYD$q)<@KQyX40S06lPJbkXFei3561Gk7ZFr0M*c2qbg+&CzRMycx4TkR8uNqKU{t zI5Z~kryDwQ`9bA^nZLpF<9ZrhjVpkjNzD{Q6(&zppFo=7L!Jf$#tNbOmxKXpFq<W_1fKXSU|U_|1Sh1gJLLuDdkd;PWNlJfvREq6BPg3_m zo@;NV2ite!KRZ%HjNjIr^~Wcya3KV^KdllqMiNKZ=d%To-({-Rnq1Vp;abQSN8KH( z^0Zk#521Imsf~w|rX!)wN!2yg1`EI1_4-NF9SQ(Cy=c!5P1i4=nXR~^#}7fV4M$P$ zAz}B6hTK`J&M>>PaIXAly&CO^kh8ho3E$alL*(>OU&DHX{|8i&N)w&0Yp=Iwq&@D> zL_8rIW_N-dTj19$l)UqQa){N?u`>$|RGEY;{RQp*gr>x` ze#$$JI5af_g|UmyM6|Z=5`m zK5&EI= ztMh2hX~oZvFjz%P8iy>SdZHdwV4;U$d|3}XN4R>2mu~i zlCdiOB>lR4nIp+^cfvV6vzJQIuQZJ=tMYH`>(*61dRbhH%pE62KD0U=Ix}i59~;3$ zNmos_dxK8)9Oef|5w9Evu{P8sbyf&w7Ct;it4tIXxquB?1$V*43y z!_d6g_qI;HJhn_UTX)Pk1vUp(Wd5od4%ezLy_TvH7Jy%nRFP`en&=ffb)X5pTMDH$ zGsos4)bbc51zBhWs{32HguBxrL=I zQR;o121pM!2S|b zG?kbtl^X2RL%XOC?f0UaM3nDETKj8BV>NF{DwzkDuQ|ODKlT3wxus>KF>1u9%bdcR zI3>DkU2yAlvW&@2{=N9$_cUxJT^zN3IvE!{j>I<)O9Z_DLLC#*MnmRju0!Q zf!UEV%m$}M;PY<}j8*c|6oZSy=@3=TfzQ896#>M6X5P2RX3*y!BOY9=MFS3jmZh-A z-VicmnY5``SHJafx#5Dv`*rmi(793X#I(z5XtCw`d2`0R3&k8@1!4Yuz59z0Q7$2@ z`ER8s2tpt$my0y_f>qVe)ly_w5UTFGE|(t{VXi{i?^w2eQHH~!iR-FcpU>*`yv!M& zjQ0j>_E`>?GThx|UDYlZ!*Px(hNr3bE4FRe$pV7)Ni|`x03c-0L|x{cRQ?D-Pun}@ zUdHtLsD?1OB~-som7BLtHdiGsVgPr3ELtIQG&oRvo9zFb^FgQn&PNIkcS<`wk4Qh1 z&Un08#1znl#%n5?Nox%=gTIZe6~^qy1=nqw$h1Sx`YXDPgSU-ygzX>@N`aV zGvlpJP4?+&-`^=8NoVaVhEtsqkalzpt(26y=HsI^iCw(sUqJc`wgHxI@000Xe7GE% z$mP^>U3umEhmWbY=wxJ!MP!Uqg9<3n3Ntw7XeILsoQ?_jLZ|YaPR?{43ub_W=M*cP z4;i0Sadm3e6zJdyjI*l8Hah4m;t_~N6DSnoIb?`BWE`Q0IuMq5rT#y*-ZChwc>Nld z?rup5>F$(nNoncs?(Rk!q#Nn(?nb&(Lb^pl;Mq4G&wtK4@0Y!PfisS{_gYuOQ)2|G zuS(rtj-Bqe5rzKixu8$ERsFmpB?a_dphMQ$sy>v<0IW+cD<0%@C5pYp@0)+xGtqr6 z7bjDwDhlf3+qcVPXc=|2G~JKzd{A-vp+HS(ar)USl%T?Bseg>Ry<>Vkt0LTNg0Zhb z<>H=^&Z)aPhhM@Zn@2=$9V9I?6)eUq~l9CQKZR@Xh|1@k`PWt6B#+ z@V8KV_@Y54_8AqRi^c8V4}7KCsK=CNt|A16SiMfKlF2%cPhTYB_PC32KgHPQRdOFV zxvK;`Euj64$^J%qN$^axhb>Mpa%*9eKOz2RTX*8w$0oJb*M^D-XA`)GI%QsMoWy4W z)-k*H+h@;bw`j8iPR!b}II~Ec-A<-@t(of>BXmsb`Kf0L1&+f`JFAARsW!+(Z9{(T zSz{rGMTV`0E_OCa?;cR=$Xli>T;LpyGbTjIKNd}C`K}G_adiD+RBgabQoBEKJY^hb z50`GbT$vX?3LduEDO}}3ZeTPo*DkfnDlbIsD2ejalx!Rs#%@_;fpoX&tmQYu>A>uf zHGU&yqEV(dwxa84og)!`HIbxcyH=TuyePV=K;2M0mlcn_PEY^9aJ-`Igr+TuGc5){ zhUXJ>>u`YW>&X|sp}2?W40ijV2W3=dcF`ye{VK+@pfDI&wHuZQw#lMyos^Vi&Pie2 zDV!T9Z=wH!+W8~gLqMllRwkY|!1fuPHaUz3mhumIC$62EF6`m8y8VdEBIBs60Lb`I z(-?%Lc4&?RiEjN-)wl*6O6pc?mjSpd1=7CrdahwP_2MqFZIw`&fmGII`ju<>tiXRd zC9Y&UYrHa@HX(h>2_03@-P{sNfbf6lz0(E}J}n;qA&Bs?9q}r8J_Cdg%Lowuek?%v zH#DC7eU2vcM83eTKGuD2>1Er@19YvJ>1 z9?|U_S)^Z#f~Iv-k`b9XAX&njIg-^I-8J{Ps=Xk} zFVl6I75bx8>DClmb*66Km(V*6^57@T@4PP&N!|GC!H?Z~_27T1Z0k^Jk=x@*I{s8S zWW&D})FFwdQt9}`-xG1oaEl1yH*WI~Qfmer?YACRFpA)mmzf|7xpv5pRuU zC_p$AZjG&MaVC1FJx(kLIyoN3_X_Q_#ZpUY;gAnX z>Np^34L!^C{141dcLdgIhyw7ZI-gf0xdRpu=h zSwM>6acwMaS3K57vr(Wf^WtU^8U9Tbqq0s4txV8%@%5wXP%9;~n^ZI%d#&DvxrNcc zS?+w8jNAhY+m=f=m|^5q8C6?3rXL{ zDM4z=)sruF!+ zwe&nxu9||}oq=J<(*I=Qe?+5^7p(j7y@8r|3??k6aub%hYfZ_EoXw*c z*54@j1Edo{a`7HWbiQ7`#P}0*D;7Y0Hxd;ygwrB9Zzm5kfjgmKjID@JS`{ zdu1~3cbgC4IpIZOkVrxzQ>bizp&o-W78EPMVMCXM3J?c}6B?uS7tMU<9O6EQx8G}C zFzv9zHjrrbPxjG2Q3HnR&~$1%Kbiztxa#=iG+?MsPD|z)$BX8hF)dND`^~*kf=D$) z(!&(>)KeBQIVGw8BoB>COL={oU#LX`lh*SnC$;31!q@TKGhK15iPQv^RSti#ld?K7 z-^ax)7lpCY&&53X6g}(9ry=yZLx^HsFV_QnHeAXqll^ILx_}r$=vd-i*fSt14&V!D zV;f2-58=I1T+~SZ^~?FRYa)jh&OPz)X`Gtcan#M5=JiHH*3HoSXlZ~4-D|DMUO*Yf$m9K+!|FOvJQNM@VCo} zOdNhSIV%mJ9+)~6K6wOq^*B{T?^Us^IA12R`ZuzI7^W=pyqH)D9hgb^E;$z;4|NIH z8X+rG{C?;ftk>tS6F&}N7Fkq$y!R}!Mya>t91rk>G1F?2y6@Z@@!Zo55;>=!>%puA z@u!miP@NA?Ls&;$Wx>|R8Pl4;SZ9Ws!dM$Evy9X#s^Ol@#^u zW|Aj`+EjfaQgWBvdzTc-s6rG{H?LI6=hggpbN|@%^Ywj`Xvbt6khxR>Ae#TKSqF$3 z^z?%>@<*f~L*a+E15pE=h!nYT8BYd$owWFrn9ttLPb7riVH(ty;oa{C`B>B;-$^7O zt^PRzc?r@q_Yy`Mx^(9HVE`||;zF@~uXVc<{t(&?#bG_I*+fDKr++X%5*wlKF7jb%Kl+n-=g!JEim$zR8dSEn22^w5IzD)#F-sM#AL z>`*POjYrwpokIGcbm1jdD(I=_Ejf?PE8s?FqWJ1vX6A0qNxdtCGZRD7+hn|Hgq z^(t~NnzVcs^@hzae@4#>mUlq>N_kK;mC2-cZY+Pt@1(Ovy6h2MJ&8Rb$~rB}hVd6z zqYE}-#pRS(rH-)7-b?YbB@}Gb$9r_Rw*``U)fDKAL$TX7vf~e#qhp8Nw4&<+(ScPo zQXo2Dmt=-?3q%LhU7z)eS6VD|)y8TJv#UAZ$PuTUVW={TH;U|-p~jGNN?8hLP}-sn za@2gZ!dUI+sF~PJXC{^SVm%YZjJ8T%qM?_*y!>8jLN-1v!3JHmjU5h92~z4~8HS~A ztWY3U7i!4(Dx1G8;Gn0d;^k| z-a3RzfNy|0$eTL8O-n#^(YC%t1Z)-L8_3aTAgt#Vz*ytU{st;jO1 zQdjRO{Wlz^_RjA+Z~sl;$?x;h=(AZvRyzXaEMNmi8{o2L`2*@YhIC_mD`xiC8HL>%cGwvdIHn^FRbZxHYwPYdX}A!2Ff)uJ zdN3D6jag>t@Jw^5lZxitD#MCCEqD_STB)7KSD?YBE5&gXR0yubaugt$i>$;p(xofb zC32vDgqji0gELQe%ae+^#=!zRU*~!e(c+EvAyi#I6vxfv4OZR|JgxR+GrRiKd6}v> z>v`i`de-bcyV!CeB+KCf=zwuaPs-EGYAv3VqSV{yrfq9C{0-GDYi|^Rh95 zN*B<^Rf@Kv>k7^t+lAYKYlo-%x~{hN|NS(PV@ZiA#my~CADILacRi!q0IK_4iEr@WXN`GFiq%`0AfC ztP~5v$4VvnvpwKChqWrLPpv(Yo!UCcoZ7*N3MjL_|1(YUU)jCxD z8+t+7NNV@;^~}{3?G@bOnq(HWfaRLG%TMrRrG)=qxrd0mUm@|Whsm8)Hcf^HxHW+Z z$=yL~;m%z7F1odwa=*CD9%Vo z5mQL$H7Q|420`&w}EZ2<9B%ABGw zDN$8PlY4t+^mE~_2Z!dztNvdp#9eDP8}P8Sy`Uy10PqA<18#lFaL~@uzq%+r;iSb1 z)>67RP5trJ+SkiO7rX!w^H2eCf=Vx*fIV?V;Ba64+%VWe8Wzg!&)?xnPJ zJBtopl-oOmj0LFG@M>}s1C;MUt(rMxVB)qCJBz`Wi7Q?>p=iiQs@$hERX)}`{s zYq#l5XUSgE!9hWOLX2Fkm)T|wFOR-JD$0J~y`Dg-Ef2&l5HY=G7W5$m)9~QF;KM;hfu}oNtS|%{{oSiWvFnbh$j9fQH7W#Wl;lv3R1;K zDNBjU$2Fg*F9QALij9K$vkpY+bOCnXk-3DY!0h9CQ7f`odfh7HmCL_@d_!vV)Y1MkBeMqh#`33uC2^%s zrrQ7^|7oV@q5Ip(X291IQCbzz&L8b2|!1K84`T8 z;9eHA-93YchC5(}cpZtPdyN6M%jgU0bzm#_@ORE7Z&xUd!sc-o0Hmi|! z#5SvHs|ibrorH#R;4d=p`L`NOVx0?2$ifX3ku5&4lM3BiGTT&r4Nw&xrzTz%?0y>7 zv7rlcxT^vm3-Z-dQyh4!_TEZ;Y5aqOTYiQ4;CjqBgvbms=C9%aWB!>`h9;xLuBi9x ze4Dx8k@Hu#5*hXFs6vAhb(-V|0GRQ+m1^b?l_Es2d8A}03f1*W3NULvDMidmQ{S2( zp~Nr_Dn&3S%{8wiw-FTcYoRV2N7SvyOj@%>yUkJs8s|~3w)wayZQloGnj9RJYvYZ_ z5Uy-&eJJ}hu_`@)x{8cYz|I@5Nl^k{EeEcSpkf;*-ZCx!W zJwfq-l1vt{E!NnqE;mJLw!wT*NjZ78=Qh(w*L@kkfBt*>kv1}8_VQrd>GhFcrO)z5 zxGNd^-Syg@)||PHHXoFef-#Pw&Y4EhrPsQ{(j5EsyYkL604Lj7@vEt<8AMB~?r{lRf~`k+7K zRv9qkl5xwj_9DsB8vSBG5PS>a4!qNW=xkIlpahAWi`|QmX=FymcG?4Jp6yfJJw>e4 zG5cqTMNB&+;MvX2?->FL?eE`w?)x*GOKf$$pT?%f-N$Y>p=F1JG!FY6F8HUm9MU)y z%BXSn6|~rOh8MROg$Gd; zxt&XsBU_iU-@2%4SKw{YJ7!pwILjNv zCJbu6wG`?K&&xI#0n1MAQSz5@{874- zNQIOu65AYL&eI1I&W)?|m>y$=V!ABTXf zB&_ropXVW4UoHNZr_B#Of3BN+y>Vfjtt}7w)}Pi-clJ?y-S7Um{r*$j_BiwbqC=2z z3gKoF+oMUo2ASBm`8sWg=B1|8`{edz6dcnBFW6h31RNeduoo`Z4&_ZiFKdk7?Pm@J zE(%P!a<@dHY2osgB8fzm3GGa8znqF<EIvHXbd8M+y(yl}MhouX&hr58}1cx7KO zArAGsz;6Se^gb+|2c4v>2|f%@_xT_eWWzqjUDKKj`2a@akk9TPmXZ5urMD*u$cj9o zhp2@jPQ8SA)Uzkf+-n$VQ6nqyQ=owU`5Q^>_+X=V8URF(h_R3#f5;+#PmVAmTnj~> zZi8O;vsS2~Fc%ck&-auLdkyJ}C1NXLGfmzBDj?{l?d($_*Rrwa}{y@Wc@^z4?+h-I6yMvyK7R67vlY%EgaR4`vDM9~2?- z%I3Zj|B{p=H%&Ff2?3PL!MlNgjirF(ufJn|2)UsW1;K0!xhX(bKmuz~Bx)gIJ~MG4 z;)PygmaG#eB2h(ZvBJv?Y_Y=f-}qIfTiQMoX96y^;?iXQ#w|eMi`bHT%&#o$zM~A1O4X^E2rfifnF#Ti z7&AK5bLZQ~Ut!Up#M!)g|Tvv>zgkM`QdgF_)+Wkv#(;RSfS4$mE;Q z=lh$;*V_h^4kMfca8}^f1Vr$&q1rt$HwYu5kuPn$Jl$|Mfao{ypWls>VuP>+)A_OG z1K`fLT8Rjm*m3Wzfh8??@7{Dj?^{zkK;AuylVj<7Sq*2}8ogLKq^uRO>UPKxlYT10 zWSOFzPN^(^i{j%jmsX3U(YVo(>^|yvopdVHhFLu9MuTyZP_sm{RC~J^itnMA+0bnu z=Gttty03hgTNs+`d`LaLTRUDKik&G+IW6Uc4nU|g%i;>UQ@q&W0Xa{&+&*6suvFGc zjFFSmr9{D{KinfJd6N}ati56M87!(q-y-#GQOG}-=$XU4;Q}RX7A5Zo*vKL&_sw0g zv9F})H*=aa|Nh#W;laU?89@G51z zJ^73Vzo-yY!rORYAKPpFZXzkq2^t?Lh#X?BtndR&@?xusfpO`0z$BMm0Zj6bli(vD zlRU-R1A8AZ$+t_kdbNCm&A#~pCOLa0$RuC%R&x3{%`Ub`M@3}6kULs6@}900TDM2- z0?P~PFHE56qKpb5Zy%ChCJ`8cb;bum>W&D>(ZVdJoA7aw;Ef3l;woEOt(rMz#MtZW zRF&bl^71q}^ZodkA5|GHV1NFwY##X&#f3DV_Q?f_iz+ye%%TDs-)sN| z;@%T+{vhnVWl*!4?lABtZ=!6#1X@sfpZ=CmP$U1g*12<(wC9Ba!C2~S?6{DIV0rDM z(sRvGwQ$T7A7d@jZry*U*f_5??U29!E~RKn-~m-z(H7xLdq-oT&~!&5rQENxsV)e+ zl1=tnnCBTu@5h+r;sxIp(kQLBPV=Z9W%!#ijvw+GIp6maEEJ*mY@c%+D8k>ib=0ew zPK2WkT#_ztw7;nu*5ObZ;U%|3Yjd$>vQ^fWv|T_-d=5u~KUCQ@fc{O)Fk#66l)rjW zKTuco%jN%OU3&^l$yVyxb^Kl7ZnAQ==bbe3d}{1D{}e4_Yv`CzcG99U?Kmd%0$;vP zA5r_n+*tTB+9qH6hZlZy-2!&QReHn0E@iEf-k$BHv<)>4L;NPNjB#kwH+#%oMY=p~S?@j#A=|V$ zAmYmWy=DW1<)5aOkWPOXtap4b>PfM(Zaw8BmTa0Ck|XBb!H6gRoQ|6CWb?Qb$5Mbu zeauTCiKnDGu0HB;8X-KI8t0ez&R9}o62jtZ98&`xTyb(OM3KG6JyUCssS$7bd81cb z&n2N3%;q64#T{~|@@o(?@Z9Kxcf6YblvA}S<+#lbL^s=m&!?1;;5wM$v`sgZkq~-> zs}(k>{e$F>6MOb~W~2>Zc29neLfTe#mxFPD1IN1Y^Pgs;;`Jq+2HCvm5Qo+nWQ zk}C~fXMJ~Z3C)EHBCwl;X~|XEPe`x&4Ya?I9@9HqJ}O3zPxZ`Fxa5qgZvuA*{CdKF z4j4IxnC-Zor?DcRUbCyas+UyZcR8O;DY(}i_nG|2*-^VEH!f;DpWZENoxm;{aov8* zJh=jd(5FNlT@P=?UUTYPgK7ajSd`wt3lhFzJ#P;$yz&pmMC6?6<1sM2DBojXMvzS6 z@iUyhRE>N=y14^XP{kzS?sxUFvq%;TKm}DNW2-c&X?`+SEEG$^p5IA5cW&0<+ryrp z=vudq1HS8k)*<`XV|mr8W_fFxzb zBsY%ATkLd=t6w{7970KqzVA%7Xu*^mw(p>1`KFX!}{4O=>`8xs> zm;_24Nf7`P0Nhwuftu*PCzaNl#UzuaLmM|rUDMLX$gFi59mFtk8m&cS;j~=KcOn(D z!GvnCBU^*z?EN>TaCUz%u+|!suINa%+z4(%z6#B`pJbh1l3b*jW--ET@C9x;KMxwr ziB3>r3e5?U&{22@2w6tQ0GV@yB|@pNJn{B)CZREaya|mlB48ciQcA@?N#M~svMQ-7 zoOJ1RZe;b_J}%ovvHvxa7-6{YelP6*>q(kZT>& z0w`MuQU>4d_pk?r9EPxyE}}qX3yusEEp&L^nT(;0-eBhZPWV)M@=~JvgpzhG#k2E zRx2$a_yZS*ROO<-8PJnLMLW`g#oJ)Nrycdb;}an%F?yxM)F5cWrSsyyk<)xlkai*RvPg;|;HQyN>l6JH zpJ>F)n{)y=`jW^gzDh~QUv21RFQ{oxh_v;)DQI^fSs9C-I~c?Jt?N*~DSDF%>TQ@% zyLW6yWF!vNjpCZkA#wG`&ehlT5%zE9GAM!hdT?*@EW90i>q^nior;AwXzcQ|$Jox@ zpn1)4xqC0s&V843tAa*1GH2HVkg|~aM&th3>6CGmqvsQl zvf#XEF=CI;xISpl>=Pb*D(rG?bTsnZBR`=z-3T_Ty1K|BuZ#vIO zqoVy7)Njz~K0#m{s0K8h^eqHNep-W$Dtwv#$w0LtbB5)y?XQ)IVlB(6IxbR_ip-cM z?=(qIAc1wyMQ04EF022ZkxBiEw)$#8HywY)@Q=G8{|C!+!6&Sy#5UzKxfWiTmO97H zJg`w~&L{;;X<%TMa$(hSkp^%wOZevV2tCw;Y z$rtqrh#NevVLxxIcJ;-1>9o@4##FHf_7k#rm#Igy~Eo8z6*8fxyc7{QKn2qa0m?|Fl@{Y{eOYmBT8NhG++A~#FNqHk#D9=F<*x=l*yU^aak zFWXp#z4~gsv?@>)^WivUeJ;NX^LB&Yz2Y%xMYOCLK>;MTT!}e1h-x4HBeo3xiY>WJ zkl2c+$k_mit&Xo-cza?El~#kF4UMfgs%YFcfc%094W(&ozm{mVNHlC|iG&GrjwHrV0)^mMdww1apAs+-jr#(WR@@i&jzU)PiIG7Ks zJs!H~rkwgVxr$hLYKe|-s!TLx0u3iRXqV1!XLK^zDNQ;YhR>9qCJ@XRj4#AczNF*J zkvg1h=xr3G)Bn<{<8CPQHCV5RzU`M_FtPi+Gt<65<4HN1l9zoYeZuC!Ik4X0c2E6F zM!ab-y*B5Hx3|eaW8FzKV?OS_W{b*Nq z?pk!rmUrPsK%4iUT6O8jDemci+FSChv~#?CtD^koV*Wm zaGbo&%RLh@cxxvIg7_uB1JVg4T9%pXpQa{a?ruRpHWX*;;)LS0mQKi@5}i&+y?#RF z+OnJ*lk7qK)-6v(N0#qmn&U2BRqnc}Z$#%K{OxvT9M0|GP0TigMej6h`16CJsT#fCgkuP59n?@f3H z=8BXvRt}LU!I?MTZ8^**m@8H^CPDAsQU=$ zq9d4LdIDK;4@`+O;lKo@P>@=o^gPiIG+(O$M!I8pMpOYl(SuzY@Vn+<#!)I*M8r`h zzc*nCWyVX)y z8E>=)uO44cK*xPqo^fJ{M#yxotvi-WxDW!5LR;%%xHw6uK~u&2&T0qQqaq2#ph!mV z%dN%ysWS8FJc2HYv2TMXx?!!8#;kF)qCsMx_QDo97o6N}Cb}JZ1|+3&_XtQdBmkm; zvcxeJRxbW4AQ}=tq9MWPJ?n_9Tx;8k(NE~svJUUt1u>K#mgQ0pVkzuEUFwXiWA!TS zL=PLxEPfD`XQ_~yZCch8dZZl3P|CBIp8$j5__;X`L{1Px5^g&@2=|RW-g0-Pk)KZA7T~~R2#pXU6?JF&!*=3kBe`8f1giU6Cb+% zl&<2p^pQQN8lK9JYsnR9bGLZ;J>VbH=%_X%t3`9Q6JFu|`Chm#Rye<_v6^;Ktorgu zil{tvxZwr&#rC_iOVezICs~@Kt&YW{c5~q#X@$qa^Q;&QCJsYn8^j}>3(DK%81K=Z zob6i#bVZ$HeE!P|53UwYjyx()8 zb)Em-5S%|RZp2)baxSG(;`%6H+>$ke5lfCe? zSlP(Jd9@-2xu%}*raA^ zFwn$BP*bCEYQyQ{f2H&FK=UN)z$5OqS9H(feD2?R!{CRo z1>PLi^AWpwFs#S=rFD)t$+p)xY?)#w@l(aAT+l>GB-1U9W=46-YGONn~3QN3Od8MaT_WnhB_{4 z*4#!i4rfyZZ{YOn^+i1oPF+lI%|gCZ(2FAeszz^HC~n7BV;kx2wg_xheMCP}In{k3 z`9rY@$v{%_hqlGee5f=g3zIf`)o{AF&_cdA2KQ~=tZq4y@93f+ast77Zdr%ap;7%# zgkxdlQT^VTY9}z6zL{z^y3Ca$D~FV7wz4|?!^3Je)(gEuxbg0M;jJaZ06(%r zhHhp;J6V!-G4;smh1Jl8a^hnIuZ=&A=!^o=n@1y=#*Y_G!(N#oc9=mB+k#xE$N_GdJ;ek^-2 z05WW@aieH|fmLZ%nT@@qYJ zT_;w4KNYid6nehw0u^r?WvHrNq6G8k-S5LQalB0;;L?#v+QEz)e-D!Ryv z=R2uG;ft1dEuUxk)D1w}KLDS5hMd?Vz|J1#l?*(o@>Ei9HKPyPeqb;&ZYq3dHg7 zm-3!@Det2`b~tuA+Az%Rhq1R(2ilxYT73K%XwY(iGqz8jh{GaW=&EuQmcFjyXl9HM z0K6F=;5O@pWdHBYShmJnF{W^-kay=SHCKxB$MkeNkW*2qvUqub>EXP8Z?~*_=vzCP*ljk zGso?_;k5>i{5~e8sWu;#03oL7?K>&~|K-q|gZR)4C!#Bsf~=dXSOt_hWkG)63GwTO zkAwK=-3#n5VE^6eTj(FMxjxu_G;xx_Rqk8uVp$=^ZMI(Xpjii`V*1Tfe7Q%Tmu9HG z3EvMdJ55~`SufA$fY7*K?GlI*`D$R5r!(~g6vjrIYo|?FB^BuLt`&h?2W24D;cv!6|0WahIL!6eyn9sNKCiGYLh5I6 zu4ucrpuaav@a%>Fcrlv%7-N=8f*~IgCU~&mI|bNRm@&^mrGkY22p23_>@Qp}D~>z4 z@F8R(vhKca$q1@M%|p63ItU+*6WxYVx>sd7PEt;uiP!ZX(D6lEwM)}Jp;(T-+b=tXpiR8>t+ z8GlEr&|euQW!JR2;FS$VuS6#Syz)cil$E;aa>lydRxwCCuEDK#AmK^md+XXlprv&u zX?df~j!6TzSqiUKxU&9Qp*uK^<8|X2!OBq8Z<}mWRkl+cRi0H72R$5YWnoK-&yvkd z_jcPV%|F;8?cNcE4sF}J5xhbW;w2X!@|V6HSiH&Zok3VU8-Q4{Pi%YHOP2SLlSG?O zv38+}nU)Ad2$+hQ`jABk z_}@p@BPBGC3)pLfa3qTTK*#S5sm=xd0Fu546bBmwKB;~}r?%MCIDRjI(9nB~3 zj@@oc{48>)64f^NQGiO>Um}n~Dl_eXP2m zNRwc*t(ubjQ*?aw7{I*H$jqbYe! zJCe0#ybB&Bf5)AT@vb-ZDRlHxsf^D9Z%MognL9b-T-S{q5I8koekYVi!#q*94jpjy&g@iaC`{H(;Bh&1p3$wyhA81tQP?1C-;MC<*A%9Y!VeB!goKIhc(rDT%UnkpB!SL$Cvg zYJ$d-vG)L~fqwHbSs9?33Z?7fl=-NSR!#)YHVla?29kzBqqzEQb(&*KB-IQL{teu4 zd%=j`4z-hb1kGIM2{e}<3VGQ^i~|g<$LEPW+Sb4Fr)?Wrx@d*WX@+YbD{mn6rj47w zSEu z^aElLiL-`1)7#!gKS%%gX5d$>Q}*Ka`+Dd4bX|=KOFCF7cWznfC}svuNBnZ;g*-#B zymBmZi^7dtt^LHG=EA|Erj`HVN~NatW!WqB-ut>KlD>|b%dsG5-8W)lXiMy}%k;z3 zHj03CsiKIh(Lqsc?&IuJlDD(z>4)@_0A+N`Zl0^_ve%V;y#8)f5rBL*vxX<*!Ic#5<`LAyU(yVy}4c~|lBB*naFO9$dh8>U<~UFRKx28k%cAp(k++Z`K;&Nd9(A%ii>@Zk@D2bpPA%27U}nUMGxfx*BK#Fo|w7J4gVy zyV3mFw_v%zV~QXoAQ$||z%41Wrx!j%PslXilPw#4FI%LOIf$OZ&*c=hT@KxF!R>eH zrMAiz@O`-*&(lK0=<8=8*ZU_F|wCDXFnHR9UILY|@~%BQ zmwZs(43g2PizKCib6(AawfTgjKgqHyMoqA)#x@*1BN+7^uZR^*!dsFCQ!F}BCy1G2 z^Ly@eON&CO*Hyj(LNs4P<5wYQ?Hg7zNAytyyxf^K8t2N%vr_K*S`~3uGxP??w3VA; z{u`GzR!_FRp@ox1M4|du8z~)yU2)tmn?KH}xU^KQ!S^Y!KGO@MS+w-3YPWYlri{l! ziEiKKi&(sdIZLKE;V&FZveqkhR45HT-%Y~lB^lFp$gQke|}HU+yCW)><{dR-Y*yViBDlu z6h1-3+Y+;vWWp(TiVnGBQ5eZp1h=@1oXf5Q>`z1FKP3C(!qO#3&phIENNuiB^q7(2 zDfSNDw}#u~rJrK|Pam|cDG{!@7pspM$iVa_j2}}(H9;cbvpu=gj%F!~{@(~?{d*o%!D#~BEeKWOjZ+}|6k6$9IkuW%S z3hy}H#qgZMa)QzpQUicps+F`F2DF}cI*8~dauU-!-%a@SV0z#V_rW(di>~6Ag#+9Z z+5_2*#KD)T%}KI5If3Bw*JN6atEhiRuclekT-Cb;$$0;fHZXwQHZ0e_iicdb^Y)s?F(xDj`1 zPDfJb(Nm81BfIn?TJWOew)cZF!6NLkjJDx#^FqG8vj}^O{cSsOK6Z@)Sb|Pk#_&qE zms-Y7byFTNo<26GaHn6B9e8V`-pqgR)n0QWdB+0k2 zY$WF0e`fq_PYTBDpq$AsaqMS+?gr71-awGMC5(w$7Cxc3fXV!)Be856RRW7T>ib|R zeWldIdSY3g<@(L%SNMKK9b2`$L-HtIIqwTX3vmO*4bghwFuZ)NIg{-r?_uxC|wGYo$JoG%Hgz&4l<65JCbBKR0;FfZ{EhRIb^bWtI zAs?ih$v`FRhh-LydWHC-C|g8e(}6D-g=%P3T)gOwC*BC?*?+o2B z`v8z#aLJmBxnt@8G5EoB$5fblFk3U~?f^rYnu+qqTUboAMNR^Bk4(dUtiKH-5nh3` z!VYH*%JpMZTUdRs_K27!>tt1@gMxXxgxTiaZ?^mdPI5pE#J20dsa~YXZ{OZ0o;HZ5 zzJ}`lI}p!M%j#ci4+|?%+rOJX&*$yGl z#`9-b-YPKqsGX^t#qwKyud0P%h!5-xgG%_^5TxQC*237vpDEyLW=nX`wBvrAuJ*a~ zKpW-P?qrwu-85Fk8tq^zZUHq3k|e~8AKNR034xmnuGrwbl|1&H+a-y{C65(HbV$S{ ze6h)rFaAC z6F%~ubsePhk-JM?#d1ro?zMSc$4cVQgw(&Yeg(8p(Z9u6WXR$5XrZ!3G)6CfBp5#& zqWC8|FX;Gl#7UDTiPD6BLN8gv@o>c>{)&4O0T&NSml%I=?Z&x)@&eNZ;8!=06q=U= zwdIL<0eYE`J1Fn_hoYRh@qO8kVs zS~o8Jk7X9{`IW;y5~t_bZv7(K{x63mD+3(1p#kEs-Z2n|sdfPz=9p9{g@|92G}r>- zuo?@4`To*y6^yctXOOgW34uzd{uRCuzs)`XkI* z*bTVNh?ocKzWS+|c^Y=Xho+*msufVsiMZ7Ki&vIlNX@mIB$iSpeaYG;35Q z3=wx9Y)(w9`pvWxvxRir)HbGYs0g{!5pFh0l)cNeZEBLIsZnGABJl}IGanxtR6 zKPn6lt*)Qc#6!cb3;uobZ7rjVI$TFflQyLlh7+SyZteeL?yaKg%APPzJZRA1?gV#& zLvRfQ3+@)&65QS0-CcrPf_s7{xI=J<072&5OVa)CSu?X{-sYii?Q>YGS3h)}s{PgX z+xwDVy=Sd5o~lXEt7Ykq7ZTA|6fFGtc5nXZ##n>`J=^iVk+MUgm1Ayhc&t;((-CW< zMmwCpW02>bhn4 z@9U_DBzPm7aCd78CJp#hO0(>$emtq~8CZbBOax>!<456jaZ!}1fFO$Yi#k1?TAE<( z6aY?w-1dno=yi}7Kvy>GvDBDr9ULyG?&UcZkKth_iF%qu4eF|T3GU8s#pD050QZaG zT)SOcf3^2WY(RT28kux133{)fRbAOI6qfU&HPUisJ4eS)Sn>^4lc5GWC>mh8TkB+dUe0Wh+AV-%HoM>R8fu|M(gw%IDrK10qi-YcWEd26N2}B^HOCVD3oH-A#rF_WNC7u7ZOw%XyPqO zHVJLV2|0_j+{2lJY)%-twA>@(N=Li2+>X#nM+l=R1!PI}>o8Mc$+-&!32MF8b_9z> z#|dC^BR*syMgjcBl-K4pFM5-K$13~=^akgP-%JQaZb>`16RdegH{t_H+`HlfT#wo> z&SBp%ph$Md+EEf(G|gI_Z2ZvcMp0?=4YTsmBVJE_2sUsqyQcC=jnTV8qwtbGLjEi_ zz>GPViB3TwadpMYHZpMwmCgORvNt?hrq#{C>>WRUEyuhChg7bJ`5Rw2;1>;_!x@Eq zEC{q7cj5@)Aix((JCw5Esxvhn8%&GkB9|{$i~6g#v;nN4r|Zk4U=#%aNBgI+ zUAYP#i#G*)2fxaA{uV>ipKc1N^6;};q6R@Nm!UP+cQtB~_x|Clz#)=Me&MTmr4Hz& zT;O$4k9fiSD!H;X#i;pycK>$Y>Rqf=9nJK6YAQTQHo!kQ)J#Xc;exyEa^`CDBt3}g z4q~1K@RKPHvSXed9ApJ(L%I?N@^7pZx5b-zxC4J2_2riy+>*3zQtG6@BrH zSqCI;YQGybwcn#-lQlULye%ISX=_hgg*8zr0+jUV|54Jv^MRCfOtUj1oXclIL}pY; zZ^(0dZ-OwYyE!X%12JNG3!az0-izTau-Q|V zK4Xa{gmZuWq@}lkwDis=E!`T>(hC?w3c1KF|D&bDRX%CyQu4a&!e-yd{?XFoKw5eu zSWCy725ITC&HrfWUij}pTKWc{rSm2^G3;tg*1nY;Sk|V_j_R9bb&2RWPS8KV6@Kq#7w8)lC-jEtZmuv>#S`#{uQldzj*iST*&M9 z!rsmC zn@7Pa#WlR3Uo;SCucFcM(MG^m$bHUsx^h6Q{a7JA)k z*6{z;BW#{j_Q=vSG4q^hV(ou=xgABImtz5|?8;T3UhcccKPo#TCl5$vzfP?7y<@!5 zI&0drbsSw;PI$F#E8_ZwIN{kA5WLE0zm3Yi$x4OExyw+>N=?qWgE7^eB$CH=T7EY^ z5|dgt=+`aBf;kGq-USL5-4i`ek0!%%#zF?v5_(ZAw`|MspN?-TN$TE~O$vQgPz#1(v|!#MBs^kk>uc;;Oh{q+Pk!Lh{5wPbGzY`Qu!s3dtg3 z6LoK;06Ah)+@8PI)Y^9#WzT>M_}vaqsc(BNonL;A+0vh`=buz(ExyA>RixWjKT5om zr8{c6c^2^RB?RTy1289H6{H_wb$!*(`|0caR$sj9qA-D#K8xL?7?O-T&Y@gkmF8>_ z&M}(NNvp#&QcXv=yWVm+|BV7VN%rYL+2V>aruQhbD(<^w zXr9aS9_Kx*nxQfhV%|`mNpCtn(`ZM;;V{Fxfx-3_*GJa?hg0(!sSC`fb?nYhV*~q$ zou5F_k;md*i~D&nnImJl?n2WoW=&l7Ll`y%G?wC+P@@BlrTQ`ChgE>F)ZAOyvSji| z`4*=-@K|b6swZ;T&Im{tiiMmRrrXLV0q-j)VdkF%JmnHT4mw*=7i)+g|JnRlJ_&e{ zJ82wN`kTb*|0K++5|A*o8lcS&Mkjdllkrc&lyh>F0SV&*jHM1(=ZxwGjHAsm1Ug%W zx!p$@A#D)sWPP-t7BN?%$Q+@kwuL5l>P|?Li zLwj`HE3Z(fqPpu0cS?z6PX5lPjImS2O=I5~yO8koiRNSPdDkeAo&Yv*1}vn^^1!QR z9Bkf(FDt~@w`E^e9<2oD?>cW5`reL&?Cj8@e|f}8SL`UeUip;$aPmw~W~Rhmc+&H& z)UW&9hvClFPgmLUE(Lx>6n4uFS~d7OE$Xgw4pZNK zLWC>J;uJEN_hi~6{hnwd`>A-!3|$f#eb0FH(vHo}%2fH^&qV?&`yoM#f2uxpO6jjP zmZ_msx{*PmQKvYx<&jY_Qd`m(N$sd+Li?89bqA#b4+O?Uyf?h{@S0I4DvYXd`lU3D zVP>D@*z>s^nr(g|p2qiWfwoK9BDk3S0jvgcxS!5*QTydSZn0Rr0>3KmNh#RUA6=Yu z_{}^{r6`#d#lJM`+De39te8~XlWRvyh#1_RYgckd7{)^cObyoFOxe?}JMm!Ix5j^K z+RrxrxpjPJ?^4(CV;_k+PLeWOia54?PV&qJ&+tPxg3D8bh-f5*g%K!5rX+Q-NeLVy zHPH@*A%Ga#|5@<^&BXOp3@s%uD+X0sGGu5J;TQqe*sy8YOH5bH?=|p-UfXXkw$&ej z5wdU7FlwMq8{&*a<{z=oSd;Tf?2{+reGU@)p!BMexV3{8EgdTRGz#{=TMJfkJ=3{4 zThGdAR9tm%T~1=MY;4puBe&9p8_ST&6lsf`V6l*zj1h&Ee%&dK?|_G)FJmDEj|LS0 zK_(1@(PRi|@ju7*#)V~|Lq=tWfhSX0D*^j1pO9o;?s@?_Uq}5~wr*ttD=0^&N3`}i zqkc!+ra}|}>I76Fmm;%1UV7vXGN7=7)rrbLu6#|$*_<+_Th*tz@kdaCUOrW{JYa5Y zVce~6&Gp}k*7;P?>jP3$AG0)!>R21X3ql3#BvgdlR6*3VW@# zVN0(==+;-hBzH`%hXSmTzE##gd-H1#YD~1AzSUGYpDx9L)zp~Ku43#Sf!hE%#FEeu z40Hi|v5Pb6wGdiDSjjFWJ1ih<^(cvnuF>)!Mx{NML`MkBj|&el&3N?K${GFmZM1V_ z#G;Y9T2eQ}hRS@?juF8icCzvGO8am=mb&g^CeC90VoBv$^Xl;E#N)F;qz@kb_Z# zvV_<(!`nkIF@IrB0tk21cF(V;q%inAjM}TC)o(FY{?zHo7R&d6&Q&{J*vree19SxH zgYDs@9@y1NlOOZt;&paQrqJ&l#}khQj}R<>!!X6~SnnFTye|)=?gTP^m;Ed26`Wl(mAWD_M`Vn|h%F|GW-ouv(+>-g9}xOf>!Uk%r)9n-8YZrq{D+ zOG&v$YKA{<6F$VZQBx9Vv<{RXsi_$SyxCBIO6NYrj#wN;f=3`^WStR0jy zw3uuRdQ&LG^!4tCFlDL~TdXnpkXT$ansg_Ed(mV#rQA<+^E(6=YUTx17wQlNI|{^`m;_f z5j+gIN!o;58wdOJ&kFh%BCm9271R0NiPwdh8NV2M8I_{iu6vZOdIxy;#K-@yJbW9C zh9zahrl89$BF8}hXCQA2J8m)>RiNuM1!R0_|aFFxAlfMjx~klaUpbRoV{NJY8#$HcO%}f;LZnz-dUptr;}b z%`hbFXp6D_(LFF)bG@1-P=S6D*dig59y=@GLkh_iG;U(s-tP-C#yweL3okjko5A`6 zpQF>P4P(}5@2+;NOEYyx-?1ii(;!pT!i527o|HQXo+lL&1M{R9TWi+|7?_TL>{qe8 zYaa;Wt?G)5_LzQ%cTRpzSUnE9(0D2Dr$TU5pIaCGwRsz4Jcpo&?EqZc`L z>16Bzw!z-xE{bBRS6RL{XYTSA+xj|?BR=?AxfhZ5b5W-dH)~X;dvEU zcQEyrN9O+W;hWJvx`PEBpgTlXfINH?>tNksZow$FbYODRHL^vfMmyuC+IO5i*G%+V zKo)|)@kgXJYK9-fBR*Pii)^b&UC1_gEK7-6a1o`zLx%0sLup_}wBS;r zr5jW;jNLiHs&3~uR-f>!T(ccKw;*uv)w)0yc>RsK(hSCC;?pKn6JGIqy;qx@y1Vtq z6_C8g(y!x!C{d*G&vq#EtJ!2;+dRBrD*D1E2f5JaQmbS2Vb+D4;O_b|+0Gxwp4+eM z)>==31QjkipsSMstq{h)Yc+tSdEkAQeqMsU-7s#3Mnar1aPv`ItQXtla_G42!1*>e z08~$;(*m|}@6(e6sH81j$dTqD0WZPWAv(F|@jaU?ufPG`+|VI~kUDq>eY|%Q-aJb% zN7^Iqn(|b7J^rSTCK{o0sE~!|RyVjoEf&kPOk@<4F}8H0IOlyHta?Dm4838S#CUp2 zCZyixn$KcrX(3aYi)*A~)%5Mx8 z1JS2Oceq0R(We_Ycg>&NMYCbOJg|hKfZ@^6!093I$B%{p(ZdccMEvUF74nxv`F&Mt zIXZn)bQr0~7gkS`*usjt=CuaZ;-sCY<}5BO&F85(gO%YmZw8vPynw18feg6uN%u-u zolUME)@OB~=1gu2+?-)#1I<})b7QkbcdTyf1kjw>v`4<;eWm5l==Wx5PJzO#4Y`9O zKZ6lCb9BA%Bb~11YT?ISf{%2rT7QlyJ!@n?o2)%=1Vrrylf{6MpP#~4UxpR{?b%*~ zYmM%FB4h{9o)s)>g=>A4K#5H=uLjyP%PKfS=2n9ApL<`9p4v0?FM)84nhR^BBFwi4 ztzg07`5w@oDO!RB2gGVV4umkM3hTYO|LmV|b)F0m;_2`X!jD;SZGUZj!zw^~hM@)8 zKN-$|+B57)pgqIPE*xSbI8D@U1r3jUZJ}0RIuSfDuZg)&JTcW;O|Y)FgJ8KCnhm;8 zkZd&Udi)5mOYEmPGFY7;I(D9@-cR{^DVJq%j%Btv$z~e5oy0Tpyubc)Z!kO|5Rx=?%vy^t}uK#FWhe;Rq4l=1n_B!T*th6wUp@NNvLRNJfha{ zQIrLNU%R9v;iG7T{eRV}uiS+T#Bh#4`tBNbr?61p`5_!jH9{kn2h^5aOKz+NtN&K| zAQ^~KyG|8|qPiv?Xf5>X^NOm$0_slLF@@*PpN79rMwVVQdgkuICLwsaHAZ`Pz3CuoDrTAsU-JC_sfavZPc!FH zC&jA-dXHbz5625)#L2;8#4AD#kM0G78)tz}|2PB>Za8EQZn&endORv`D&6#;6_C^A zOAY(3J-^6zK}FZ)y=@^xMz{G)ioRviVL?=gOhgqoOhBN7_3stS1<|z7N?cF)SwaLF z)d(#?2%D%~WjO7#;F%=4z?q~rATkHf9E`Z>BphUhJ9R7w$TTie$uxS<$y_Z99RL29 zVD)N@cCL;Fc%_dmPf)>LM8vaK#vx^ii?tT z{^3~maG4>)WJ)e9?z7kX|ApJSR5qq_y*i0d1EhafppA2P5TJ+TB z3K#rzX#*8zuQQ|vwKKU9E$|tIufHjeVr#sQEFo8Duz^+rDK!xopQ;jlBeoH=(MA>~ zFO{ko4H^b;u~gGAOT%B<8fnVhMP4shtlPHLyJgvV;eydEz}y4yS`bxYKH<28e_$@w z<{_vbxWE7!a9HJ^$u}djwi#!{l{GAd*1TG1{r=v*4$c;6b*-yr*jkt`jpartk1ohc zV^->STti!DFW6}qer}7FTK~*on12shB!JNnj>mL6Rs;UPpo8{*+a}--Ok4&a&5(x(~g>o*XuwEX?RT+0F<7-4152WBz~EYJu79~k!+vY4zKV#R*O`$TSSvP38LczlSrdybhDREVU35BwVJPOF*4w*?fw%S4e?3@%LdeI~1@4@aDt zXACtp3X??ESdf4KqxB^T$_i5J3w8|^rxh7Ad?UbdjX2c=B9qPn*cQ6PS|3ndbQopd z(LpjoX~NX^lO#0BG3PYg{3uFE9KbicLlf#nH9HLcj~x+W;Psb@#|xQOB*6ZP2{k~B z2}20NxORPvpmv$MH3J%!1uIPMHS|``x0@0_o+{ni{2pOg_P)&Dvo;`w-5H5RFcpuJ-Z3^K6YZ;u&x{01Gh?Qlm~| zhr9Za%kW}Dvzvtxy1S-cy2^y}ikQG?Ib zHv8UWn1D+q5eo3fL-;0Uz|n7r5ofd#cz~ULi59qyBLUasxrFp{MzefEvS6-=h;-D4 zChxm@Nqe-JFJAEAXPa z;wdY-xk{Bh+oQ`N27Z0r+=$arFJrs|+<<2@-s#s5=z9h*>+lq48;69ytKJsnBtKzL zEkRRB$5$xDz~zREerwyGvmZ|vR@Ak|m?k8#x`v z?A)w&2vNEEBH@YLqFht}4!;^^UAwaTW#NeXjiCjWQ$+p^<}?f^O-NeiQoIwr@K}D1 zDaf-s9bt5sHK}SlpF&J7HVYFNW5A>4CFMxKn8X4SNvrlHwRt{895)asYMbz zZTR{={lh@!!AFt<`pF^0hq*}nsu62}=I`6|-In`YHlRdm`2-|VzYdT{tbpnLpF|R$ z0ut$yHT5$W16HbfweG+GqT01^X=je@e05ETUlh+FWI+2VB(M$#K4@!kH9u0Yx(!92#{suB*XqG@uj?nj0 z|9XYS3pQhr5EQ!2TFmq zbW5BA)s~xI!hYMYS4G-NPFO_Z$9z<@ykWXIJ9Bir=LAYlNqhM_j%rTZ+<7~gDJxP7 zETJO@n8_yQuisHJ)sk7k6YTL(&7yIs=)Y#KA;U-lmH{a813^+6hOZ;+2@N8Q+T)B@ z3a6%VF#+0I;*N3adf|*W|9W9tufp&v1=28pZeaoh*FT>3uJC2NQ>FVx=KSaZNy#&% z#~!Y^R~}d-@`IA@@R%f2e8JI08~F&vKSR3F1KoeqW^CDb`hH7aQCshmEbP?rsM3pd zy`E?(U8Gk^PT`>gxUH9e=q)rF3|BC{MW#?YB|&a`v@S+|+z`rt=CHX1Vz~HdnUjP4 zk0vWKQvByPmq03`p5kA6ix!!e5zfS%=!xZ`?c&4b*jQb9p!W#fMjuNDP6axL=2iF=R|5KLb z=bFhD!Fb=c5}|7ZA^Hv&dIYtvR2r@?sxHT9HA4TwTL8ng3W+cE1p|P$0ER2ZXUmw= zF2ZLENR~rH?lsHR1GZ!tj8zvJD7G1KTw0VhW!mC-0HGhWvQRpb6~Kewc&7lkZR=&m zvUSzixoRiurvbOEWjRA6`b(n#fE8vm^8eDh^XxmA70xLFSYe1tFC;IVetS6u58~m_9o08GbyMbA+sJc8=4>?-#~85L2QXi^H^Y{0w5jb$Up=ah}r@%7SbbFyUNC4r++q1)kXde(4;xG0qQ5nL(92Z;6I^DprF=3pAMyHRALH$yYFn9@{gPL= zv`_1vm3EUng{g70XmvE!&*hPhi^LzN?=kECB3S6UzElEb zDKvH6wDB=^o1){j>9CAHhTQ{RI z1t47t65{Z-AerDV(BFCR-!3Di?xVFY6qmP8-`nk3Cg&cme;jbm0uKaFxrh$IJDy8IU zt5jQv2fk_LSPM0mLLF4mW?kN`;#d9u9pc(M8;TZX!ayE@&ZaJ0xpK=B>@l?(Pr^Q&Iy{^P2|CX~!7oePBl!D3`4l}r%r2yqj+O%-U z3EvrHpV|TJQvkq4-=*$X{qC8bZFgE~f?qY5-vVP?S!afxepNZI!Y@V6cXM97B^EiK z_N$W2K9iDXB^&i|f;TwgyRc8SgU1B%TTd95@)Zc(LI*G|`GIJ7ops5fKqhttjZTMI zqxMDPl@~uQNa8~%&?U)jh(nwA#oa=i$AoSK~jH__8HoaW0?NsB3Q? zKXKZ(KCUd^Up89TyOIbkcOpW5D`hmNU2x`>?2IQxiD_e1HahP6#1c^-*#_&_`-~AKH7D zXLkOBgvtJcgn9f$!gdlb=il$ZB7Cli$HlOV4PP^^tgSu znHmxo-el&4s$x-2r_YewkI0jeJGp-h&C5CH!t#jphV#VV6Gu{}Cq89V#1`m)^20d_T=X8G@zbb|(jJ45p^~ z7YG}D8)(EysJD#4DTbo-dK!&WJ159d?X^QPm=4Pe+GJ9cLIDn+B4nvcso>!+gTx#JT2^2sVzX+hHd@MdM5`DW#g?zz*q zf)Rd|$m}m9#(BwHW}eqxN)INniJH13rfTOds4g|g@f9DZ8FO|uGTraBRxM<X#Pf=CZD(vJ|(&F_E`AMku3*Di_=pWnSX9YY8Rkr{R zmO56i3Btj6k)nN9ng0S|51;#-+XpAE{XT=w9|9jk^ck0V?(G(4U9k$3vG=gCVxr=p zmzBthzxs`Fs*Pw#z#Bed4tzIL9<%ieSJbN^j z@Y7HY6n^vA3DB0I_+F6HWl~1I^FPD!lQ#BePV<8(pDA*_YOXukWY+!Qz!Jbr^-ZY= z38ua$IjDBV^X`tx{n}}ZSKG3NL{U|Orm2cq8nH{8?Ie#6FGatit!Y4?0fd496c{*s z_iHz3Wd+s^Tt2l${TiDn1`KCG{+lS$&~b1eF3ir&;)|Kf80eO!`qNAy2L^ARfN;#Gn0{tw(Xa$Jo(g} zr-inQA9ArV%@@LG-u^lYPO_K>uC1h)BqwT~x#{e7;YBqW5E5C-`tlReKgnxisq$QS zX~3LQ*PVRKvYngGje1Nv?UO1Iz=cuuho|7u#BK-Rl1YT18-hcuidicwK!`PR`QVcE zPb)|}E2QBDD>wt$7X(qY;W`!%M#5$k0;0-HG7KX*Rs7_f#WHzc4)r_asfrVja_T6v z`ryAsfyyhLPgrjLdKjp@|C`0Uk&RjvS7uLTLA7oEI}MrEuus~Ys;P3gjk@y>w#dBB z_aGvy)v9v8)#k&t+tgB%ThqIPrk2@;S6gEjl_;$en#2%gLaMH{blv+TCU{%nUw(S3 zexy)Y_oCdv>2fGgVKLLMZhy;-ig!(e=ws;md` z^#3x~OrF)r_5L?||4jV!ajo;ZZ*dFxP0+j6Qjh=yrgh;W=C%M;vBPK}e&I6emVTJu z)D!q(h&apgYFy4s{ekw^Ao1RLx%Pm#0}EDdNnCks4L=6!cuS2cO&rI+iB({If9dr9h=dVJs}5e>MvHi{F+kBJe|nBRPOU6m5GO?i zBEvj$KV+Z9QuymCiJZyL#XsBr3=O)}1ay&!k1a%JkMziFcS-M+hEOZ05W9epqU2A1tXEgPIVky7!uWuDlx91EQ(ICG$e$<;_W`}aE#VMkO=!gtGN`%r}SzSzU z3cCow{RPDi8WavKRwW8>Kg`zqut44_OsdiK3PySn~*0}b^B=>)1B;&=$^I1AvxsHHgxv!h9SW@m|&16350 zRJ5*C{1S+$#g^S z9fm<~t?CG<~xTv00`GA?pcvC)u}NCrdGBG{(#)xk;KBmK5SmJ;^`C(+ED1**Vd#&3=j zM9aLI4*Oee>1P`-|H_JzLO4mQ*x=Kl&V5Dww1n5L{j~0jBQXxi=Q;h&)o*lpm(6j& zBp4V7lY_C6a)AWFVeBL|WOJ~yF$efL{O{b!>PQi>)hK{_VBzTJ;+|80iLlv{NdtF= zLbu*lUEAf($0Og}f*c9}`tpm)*{~n4t#wy6L>fOO-AQ@iTOuKvIs`~Dd&C_n8LQzP z9$}dZEfmKlZDX4$^}LMhmogc1UG_I?or_rH?uo%S1@zg9Wjd1JW>GR-Zp~rkdXoF7 zEx}hL{BNc?mUT3;P}BSAY7x!6v?}%l(O`8<%0j-;A+U`1FVnPW3|pfo&eE>L(zZBl zm9J%3qV<!>LtkY)_7aL@cJ^vVn~2GW2uQ)%$Z z)~ieLw)mH>x?TsZH&kRMfq_UQ%eM4xfOQ{(4db*6+A#!*$ zh@|o=RS#QDd5bj$z`$fg69RV3G4g&`_97@H5Nt`b0NvPdq(lB9MQV@&Io6gbKJTyq z$ySjK>9Bx*t8WFGtfqaCMW6ElmyrzpI_UPEDHj=l2!m_F3;l-$69lthxgM(!ThLP@ zDi@g;qm!S+2126HiPCkQ4$j;>CTh?2%SxCBjV*XEq5>$^q<;J!} zgvjxHJV^HsNjczA(%Rr+O<#l7=7InUh62E0E;$?o@7SM!Fi)lL2Qd<_ z`Y-LGGc?_Aj*9NA{6Hia7zi7lu5q7_w?U}vN?@Uqdqq-2Sr7L%in;!~_ti@f4AwiZ zUBO7;S%Cr~!JdGy?O`wk1^{7cs5r5f{^3#$C~xvBJMgv8{E=kqhMYzH6Q!m5VDGrewIHx~0R)1gb4yl1}v38cLtjWA`5x(rr!JLN{?y=MTp_U`Yndkjz+clY zGH)mV94xI2KXz0MbR~qjprsfaCTE`2CWHyaRCxYHX2h7oNbfcXuHu`UU7RViwK@WJ z)l^YipGmxK@9fV{da|RVvjra?3~}*Z6jG0kUV3|c)N(+o?>D>N^453_E+ zPc|xDQVU#o*c_Bc9-M{x(5flAbH9&67*5NH!RV!gte~> z9ecMsX}P%VmMgifbah=MHzc6bnQ(rA8o1a15CZl@f?+zy4^RK$!Z5;nIB5vO_k|pj zR|&gXFp<8N(!u>a0lYXM_zM&?W72y-D~rZXF#ri8=jIj`X}g+q78z%%(4)agKuM~h z0wA!c1ERUMQq$wkEW@j#KbxR`Ik2zGQott2zv+tv5`PBWAyxmJyLB0zC%oVKh6Y`j9UZ`2xjwlE{9ty zw)cYH2xD6HtmO8-Qcov+H8pIdx{^AuU#=Yp|EPIL`G3oSeRQbj7Q3qjIyfmiBE|Mh zZE|JlZ{;rJDwE>jnlF@N3d^EO-cmJS4ttimm%DOVShN-xe&k5PqojK~^SpyGa{;Na zOq~Dy$y@BZi?4`1+L@ZImOmzMDUD_ENZ8wk<=Vd;mK|vpu}*%FpHHq)#SwMZ`EmGF z+qU($+A&x75(iEjS8+Su+lJ6_sZ!|Xi{h8eT;d<^^T)G2(699?5UV$bi?z?mU6nI# z)I3>>seTksiODi5fObP(Ky~>{dCTO*VD& zO#8v7%`3Zo;YIwYCF#qqO1u4#<_2-GH8o{VyZw*N&M>8dqHX~fSwaOrFBY{|&u^z> z2t6tneVVwrm8Z)8oTiug=`El9y#+WqD;Kdl{;UqTYX=#GsUB5G0{~ zE1FPqNSVisuf7%a-`@>_n_&DyegT1;{SOo-Zi)sx@ECh`UCH=~46-oL(5j<7|IR=S zhQP>LdN98c9Vvy_8MDz_qIc4{pM9yY3Bb-3H%He5f{vKz!mPke53Hy=TCV(K<`HxK z?iB!t@xkU&dGna$5|Mh(%2(WkSKB;Xb%e~PdXLcRl2&s{3BT(p zQOp(oCJIs$?iwgj2+4m)M-_X$Ut~ho4~Jh<3kELww#WuyU<~9limN@rA|rM0nIFCO zf4Odd{C;m}gb~b@*~Fk5F!%b|fS6#Y2gc1JG&b`(!Wd?l2UPeM@)~#saQMigL3xYt zw3fPXY^>oCyZ8j8izp+Y%a$zn<6{_2oW35sWS@{|DsO$CTJ&ax z69j?jK>TplY2tJ2*gewfSYS|F&_0;YI5QRdQDi_tfjT>#UDiH}wRRZ|6@4bY`nv07 zdmMfC$yoTNwEepFWnV^;cD4d$c>{-~*EA_6cxd@X(H7O32;xk&;G~M8m<53T6Lz)CBFb39ZQ{AEL`8w3Urh?YZG7Mv}YkWKUY+|Ov zRLsdK27dLCX;`UR^X~kh-1{c^jm%6Ahyiny`qk0eVJG>a=rdPK9AZ_(mzM2DbFS7i z;4<0e@aj(Q^Z6IVB?P#mla9xcr@Rf59B+GVUc68dC|@zS5LB;2+wZR}T$(!l6apOt zFVA*T#)rql!A|$|odA6<(pcCpBNxH+=ydC=Q70$UG~>i!FX zvF`Y@O7c6V)DuP^7D`UeU8(Ab(~0?vG%`0dc%!6KL8|&`gAOmc)&nTrxL@l=~zIerj3d4$9u5E^R|6s=p?^kwoBHje@F9L%Aim75oTl1uvgk zLG#@<>PR`e2#g+9HiYptsp>v!F%Ycfm*?yYEUcqHK@FEP+Qj& zvlyGT5Tfd9w-ITQEJLyeQ|;nZ)Ryi5{X+y@Qh3+XW*i7prE7ry za6*l^M_u&Bbr78BO5}NxQ6W{;l7#4i`Kuu4%P)VmWY-QW_6>Nw4Tix=Cd5T)00hi1 zcl3gn-Lp9PQyr(Pz?s|T<>3CIx`d-ZXS?nVil)k>@xxyPtW11v_4G&f2AmA{n^1rN zOWv{M`9pwFOwM3Kh^r&~&Mi0kJ`)>wKX??oMA3$0`it-|J$b|Reu$n)^{gtO3Rz!j z#8$8le$_rk_75})`ex9P;h>AgAZ10}vPwWDF5c z(kx?H%Sikda9=@z(F<|H!_~H@oVXh45nfC*BDB_Rtv!ou5|lNQ>*Maci2Pl(XP9TF zb!xn~d_T?xsjcN=(5^{|)Wl1mF{|)1_xCjo?IPy2oZz84Q&aO6hTQ8WCnAA3{BhKgbt|0#k%1l@5T4fuMvy5RQWvAoC&QMb{L_z$0vq zGLuteqAV-mRpUc<*~5^nRC`Hb4D65QcO$3Bqa(i)T3=5)N%!$v_Hx1}7g-v*LGm@> z$W$Kp#LN$es2Z?TO*yF_7HNUBgC1)@JCNpY1!)Hyskc?qxtLG~4lVzy9n>B@X$SFb zT$BXw+`g3m)eaK;6PTg0U#Nk!gH>CQb`ZZ?#>^If$Ae{|Ftxh|ZMc zzcS>!{m6g|2V%ZJ7}ywYPe_j+Xw5|eX2Bwvp7X68>|-Jo6sdFX@zrL}EP_xfeu{D_ zHTy3W>oX=R73;qj+7LxXyoK&AZZ@{pf`v#(fWgy!ABzorSXr7O+~f60Bli44n=Kgr z0vNDG>amBq#r_5FS6lPes?C*?3u=!e*v-c_zfjP9(I}6?e@6{^YDJ*_qJjzi9X01E ziS0)@B~=tFXOv<=$P$73SkzfWm*9xh?!A<$MHm@I_m}+wAz)Ik^9)OHU%F_%l)%S$ zL4op03O}xb9E7bIzbH;tCFC)lP1mVj-(3&oUpJqf2}IZHY@^eI1xT;3C*X@$-no#J z;?L7Nv1#YVcfAksEg|#?ZB4Z~(*$eeo^EV*e3>AQRf6 zKfKNDv6FX~e3K;bJ{5tfYXAZM=u6jtjo+A#A!C!Ts0c+lt(e8L`z`R;h{u3f;;1U) zw>jk$cx+@L;Lq|jHX0+uZ2UVmdbNxH83}rkysdd=w+A#f${hrcjf#o=lLQBwoZHQz z{Y1LIWl6=Kv`I^Iy?a|%1jRa(M*Ql%8(#PpWnIx9)GK5Q3LwCSGRTv_FPH{_)xbyw zFffw9tlE%Xj1SL!Ig|jX42`Yks`LQ)r3uW7X5BVE4(%6+%MjQC1Ebnv{5+KP^3v9< ztkFLMBe*8EURB(VeX&(lKBym{fzfpaFfd|E1P_d?D>~oDUBKYAZC3y9z-YAVX<%ek z6S*dFP5iOq@4$$P5f~U1$ASk&ni-&h5pCOExSW6~*SGg$s(xF04E%6U%onB`^+o$n z#(@2g_Lb5BSuG}C{s;Zy@zsJ;`LLA)Y4Wn!#BR6=x#Vb=(Z4n@166k^v2Yh*72`{$ z0>p>=F)Zljf2c12{z7jS|2EEkVfEcjVij9}KxfsZdv~4&+f|-ZX^|M2 z7~cQ&J5m`0IR7q+?p5q+SpQIEzb>Qx)mU*lX^FT9N<2Jjilt2We}_Y26DH&lUv9<* zuxdu#U>ODyY8gHw|3A@R#6thlUsK_V#26lu$=w$_?k||%CrTMaA$#heor6jbRp5V9oFxdTvGRw@bRZH5mCD&g$`-0EWCr2|0`7R#qFsDkf^ z!_g00MQBRH{1F7Yubd~viV5gfKJLed1^IYv$gVUWL&;E^H@{FUI$Afj+HaG55rsUTv zwyQ~mEvr-IC(LUS768Bm|BtfHGA^oj+v5YmfV9Y;l#o_HQo4~+x*KUErH0NSgc(E{ z1PM`ES`>x`hjIXgp@*Tn8-_S@^ql*-pL^fz_3X9Zu4nJ(yVv@y15TLJdv~8hJ+z(p+i5a5RW`pKf2>de7uzhUzZI)H1Ap6ayvY>#*>Zz(#6ws zSi9MxmPbXfVQ6i?C|qyq$kUec!q{m+km8(kUvoaELo9O7<_>z|AjRW8QHamKm0q(o z^Zz6MD#t3lqHrJnaT$g-*$A#ioOM=Qg8rB4i)mqr_$g{%5UcUB`78CZ@uxcb@mB)I z<_1M2O1eoe*dN@7V2Wudx6D@_rW0!!fmpC#_%wEIb)A%gJDE4F({gt&jlc8{N5I1a zMQ-*t*5q!tme#^CR<3)S`_mX>xgE>TE%lrUyebAblr)LxDZxR*B{4DvRs_*2g;O?A zbSal0y@(`R49li=56(ncQ8l@2oru^-k^s$)a&SpyYdezba|Uwe4Bh_4^V9W~;#F1$ zQj}?2P9&~q=B1s3*e+KkvT9Uma^3PpQlWp$?J~wBQ?Jjz@ku1%+}38IKRf87e|wP6 zSC^@_gV<6rv{zc`1iGs}XvHSA$3WjZG48%HqtzKAl}|wH z76bbJ9_?UV|F5p2qrN#P=l33?uRdc$A#Z&B>#6Bbfsg4~rh_iXw+r}I{b&i?r!HtD zobTVAdC<`0PyufId`h-l5Pu}FO0tytz@XtZdO7n{xS=_QTUMf-FI?+vQ0yfC^FixC zx-WcX= z*Z2`ouZl52?ONR$k2SwB4;rdd3jBwl+dw>x*^R_A${M;r*DW0DL^4b(s}-H@c~+q; zNwFGc#ZP-7{9kPf+pT)y73%EvhAkZJ+n(Hhu5+U4KHKb))n{G=EbUB2cHGKpfZb6U ziwDV%ltd{V1k_BzT5w3^?~DLM0Hp75>;ZK0z;~VT$(`(6nosx6C#+ZVb7@At1a~P+ zPHMHpk`;ixes^+n%m36N1QgYJ%H))o<=fTsvpjfM7V+>UAuVof#6t=rd8T&+%QkCe zSQ|Ih2Y!GnEm6JC9%vHx%#&p(8<;-=AR%q^Bd1W_4(lvq8`4!M0QI~i1hmPHQ|!d`ixpHKhovN$wdFu zyYrCXYwKiyD8v{DAr=L9hOM+3uujGlPHfIyY4d7iYRHyE4F@3xU#`5632U2`2xHoA ztO-0?%n-11f)5eHhg2D*oM4<>s{R4_-V;Wjd$|c{)kNFgY}2Y0H@Y*biHhc3%h#>2 z@^J=YpVE6zoZ9bAr;x5z?R=CN+76#EYItqE04~)>)@eyjtq~Rz2{$r2x?$QKGR-)F zs$h$2Fp&zZEC&`8R+YV4L68P&Jy5J{Xd_as0S%J#@63On>#EN3V3Mk64;gF!CHG!= z7eRmUOXzH?j(MuWk>Dpqi$`tQs&qA2qL(IYpf#YV%+=Qd_ntF6#; zq2@OgSK%i+W!5Ktl{l^)^fj^lW=cy*;hf_FRhurMm4&~K?#$wcr#y}Jmd~zbW9gb= zN{0ht?tm3x48FSEK9P!+GFtH=?NZ)`{`x-*7q`0`pXZj7ques$6}=plD(*9!)yR5S z7xDGUjae70JTY!g$obv+e7aZ6_Mqu-Cx|A5q=K1WZnm|BM=VOVfPDSVWfn!KKul<{ zykL|;sNL*)Utn>~9jfSugi0ZgbdHlY;`n+p&rx24%eE1?8wlsy$0|fJvzpz}i~y%j zMn9=?5F0Asvia68vb)xK_rY-6)26_@Bl1j8a43W2?0b*hQ4vG$bb+Ip zb$EMQr0X8d4C6lxKISM8?lBd zG`328+1rYX)B6BG-46u#!FVlhD%<4pH$pei*`Z(Dd&|uaVy-(mfW8nP|0sk<5$5Js zSjGJS-J6ywZAF8m0$JDz|Iy(rXIK+a6z+mLHQxa6B0Dhs1}4?$=v#2}<##4~pT)W6 zCY$+;5@OqMlwZ~hZ}ky>k5=j{{BT`=xz7^6ea`gC$rkIvuE#Q!eV2bL^BByE&;IP; z-7bn-C_M37Rx<921AZ;s#${BD8+qtUh&69N=w+po2`2vAMO{*<`LiZ4br}C6Oog z#^qVnDQFn0O=+`Up+6M_5Et7+U7yFI6h;Mpx6RwwFx!+$x)eXNUn<2vxW%&OKXx6o z0zl|O0KB6oHan%0mP_;jzYZ=PG>0T>a-@yJUO=s&CxqEauiJUz5Yh|sxcWA%x8IFC z$DCtIq-0_p0($q~E--e(veAl;(%)Z7_dWB6gP{a;bw_Y@U)(kzjuK`cF&Dca?txJ>B}bS9zi_)Q$o;_I9|?( zyDxFGI-)f?M6eAVHWzP=@&^mje}CEJe@48kHEc=wT`G}1q=}t<5XgF0txI|k-M@D` zn=c!Lg2}kl!o2;jJq)%UzeG-cn^Hs~$J}zN!RqxOKS8N?D0oHEkC?e1&X!ZQ_F=oe z!KT&D`)=PVK}gGEo~nygm-HX?fWrZOuR+awnYZ-`)~z zFq4&^G3fZjg~`UOkn37NC69cng{wixZ0(Gc;pxrh8CUOLMjyhQ9$pfArPPm??;}&4 zP%-PmK2LVZ^ro$*>T}}3-y3q%N`>1q`2EbCtXkEO+5RVI`5iC)7_Q6T&}qCe7R?H< ztn^Q7V$Orr5&tdT;m4ZyuM_Nz=6{4xVb^8=t6?in=0kesKwX}2-+B|!Ph+o{nMBEf zEg0@;7_lj^oy+shg;0F1c1WWu8Bb##JVBFbe16YFm3yKVm}mfF3=>dK(?Y4eVCYg;R(@yht(b`!JOEO;LEcVbhvL;pKC^R334Vp0ycwn$XTGY?|uEvw)kGjjazAV$AbKT%}kKic6H)>8?xDu<5S2UC``P7%Vdjd zxU1f!DcSt}o7n>6l7)P%w>B&A0;eRaEm+rU*2{)pz14MvY)ZTI-h`o2^r0D5l$r&E zGxrhI^>{vt6&*d=FLwy61OD6wZDr$USBE~I0OMW0I1>ZihuvlThLThC_+f8DHE%Uo88 z`!61qGdVraXlD#?;){i_W{i z$9?w2Rk;ySBBCL4o2-iv=@n(T5=&*^;QMcgk!Qh8qi>^%SI+W16vW|_vfQ`{5v&D- zsrq=M5d+1<+lAMxd^H5yHX-SnwQ;9>+EYxxDmVHh8~`C;(HFp~Oe$63!Jd#M`=UwD zRCDP?LOQ2bKnoM1gNH7Y*$9(1Ttj_0;bYooJ*Oxea(OX)i*1&K{^>^P7l3n7ksnc- zhBF3E^dlj*b@rM%|8RYJ;I|~^F-bwX+@%n;tt!p>CWtcp+S6AhY$ECMerWA2r{D2O ziHpcvU+XEhPI-BXcN;`~KNNM~JD5H6xZ(R-zlUKORBTTP^uM0L6ol7u{a?UJ=1nO&2GLD5U6WBvA*&Dyzp*1~ zRhuCAeGUpMMt(E)~XX)PD6!>eHp~!plp&E*H+O@Rro`)|mbY`Zp z=gU`(R}v_G^jLTX{A=sVbwq?Bx2)uOOWN*0(XZ{a=I0JF)YZj|p#zBh<1_7*^s9}f zwJrnG(woI@L+QoM^ivzTUrIltDC+fRi+CAjm~y+ee!_Y4Zf7 z?E>KY(1j&KWl+!K+2Jkxzq48C{@|2cS#mq(1|7bq6c(fY(iE2p5b;(ULb9BB!L^3( zyOsBvLNx5^1iJ((6#%q}p*d5O6DRhu*MJ2=b$k*Wr49-KJd(&7+`|ZI z7IGv4vS9P3H~EA@)P1~l{>DUUj&sh9dSE6oU`;wqJzUhqp2H==4O zOI@TE!N|gA{3FE2w!olYPUXr)YiuJB90)Iajt9*r4*9r)kKnjSQQtRYI~uo$999V0 z883h-p>Ovj{Ot1^kpgx{XW#GLf}8RYWCeHD0g@49O89&QM5Vap5s$IPmdZddxtyZE z#9fGBiYUuY`scy1oANuCEMiD0JER9<2`ze!FBAo3Ve2ClQhab{sY6_V47y~WSTt;( zB1qrcGhosnBQ}fU56zZZ?V-^w|KufbEN)dxI(z4=L*_O4EH)`*7L`%J;e6N3ThGkf z?6cT(^IQ-0k!)r>96PO82<4_O%9guPb(1Va(J? z##U>SjhYw}+?XCR^a1N4-A-9^tTVpg>R(si6>aDJ(81oe!4ctsI5%MeV`b?bTs#SLj8wD>c{P(^t}JK8c|V_8agW4?Bh`f6-YSaS#Cw3^c+i!H9)7 zE!8EhnOf}lQFrEtN$%laVWE)I$#LsFX;0GASFn-M<9uqP3)b6L9>`TW1Ru8cRZ|)+ z$5vYFo^vZADqV96pdKcqM!xup3wg(7H0W^Bdpf-Ovi$)fkB><%{OY28u+wTweC~V1 zj8+ml9CI}oKJyFXAi+K4b9MxR`56iQ)??* z?H-GmAUCy`04C zjfs?3t3#OSSqFYGbi+=-USZR7G6X_+hc z>kXLx#MYk>OVHK%!RV^n@j#&0WD6f!oVA2wVn6Mw`zN5HpuF$yLH`p}MF&917fV?| ze#+w?Bc$fvrdmNh@>|zX g_fBilinear.z ) // region repeat mode for x (umsk&x)|ufix + final.x = texRECT(g_sBitwiseANDX, abs(coord.x)*TexWrapMode.zx).x * g_fClampExts.x + g_fClampExts.z; + if( TexWrapMode.y > g_fBilinear.z ) // region repeat mode for x (vmsk&x)|vfix + final.y = texRECT(g_sBitwiseANDY, abs(coord.y)*TexWrapMode.wy).x * g_fClampExts.y + g_fClampExts.w; + + return final; +} + +#else + +float2 ps2addr(float2 coord) +{ + return frac(clamp(coord.xy, g_fClampExts.xy, g_fClampExts.zw)); +} + +#endif + +half4 tex2DPS_32(float2 tex0) +{ + return texRECT(g_sMemory, ps2memcoord(tex0).xy); +} + +// use when texture is not tiled -- shader 1 +half4 tex2DPS_tex32(float2 tex0) +{ + return texRECT(g_sMemory, g_fTexDims.xy*tex0+g_fTexDims.zw)*g_fZBias.zzzw+g_fPageOffset.w; +} + +// use when texture is not tiled -- shader 2 +half4 tex2DPS_clut32(float2 tex0) +{ + float index = texRECT(g_sMemory, g_fTexDims.xy*tex0+g_fTexDims.zw).a+g_fPageOffset.w; + return tex2D(g_sCLUT, index*g_fExactColor.xz+g_fExactColor.yz); +} + +// Shader 3 +// use when texture is not tiled and converting from 32bit to 16bit +// don't convert on the block level, only on the column level +// so every other 8 pixels, use the upper bits instead of lower +half4 tex2DPS_tex32to16(float2 tex0) +{ + bool upper = false; + tex0.y += g_fPageOffset.z; + float2 ffrac = fmod(tex0, g_fTexOffset.xy); + tex0.xy = g_fc0.ww * (tex0.xy + ffrac); + if( ffrac.x > g_fTexOffset.z ) { + tex0.x -= g_fTexOffset.z; + upper = true; + } + if( ffrac.y >= g_fTexOffset.w ) { + tex0.y -= g_fTexOffset.w; + tex0.x += g_fc0.w; + } + + half4 color = texRECT(g_sMemory, g_fTexDims.xy*tex0+g_fTexDims.zw)*g_fZBias.zzzw+g_fPageOffset.w; + float2 uv = upper ? color.xw : color.zy; + return tex2D(g_sConv16to32, uv+g_fPageOffset.xy); +} + +// Shader 4 +// used when a 16 bit texture is used an 8h +half4 tex2DPS_tex16to8h(float2 tex0) +{ + float4 final; + float2 ffrac = fmod(tex0+g_fPageOffset.zw, g_fTexOffset.xy); + tex0.xy = g_fPageOffset.xy * tex0.xy - ffrac * g_fc0.yw; + + if( ffrac.x > g_fTexOffset.x*g_fc0.w ) + tex0.x += g_fTexOffset.x*g_fc0.w; + if( tex0.x >= g_fc0.y ) tex0 += g_fTexOffset.zw; + + float4 upper = texRECT(g_sMemory, g_fTexDims.xy*tex0+g_fTexDims.zw); + + // only need alpha + float index = tex3D(g_sConv32to16, upper.zyx-g_fc0.z).y + upper.w*g_fc0.w*g_fc0.w; + return tex2D(g_sCLUT, index+g_fExactColor.yz); +} + +// Shader 5 +// used when a 16 bit texture is used a 32bit one +half4 tex2DPS_tex16to32(float2 tex0) +{ + float4 final; + float2 ffrac = fmod(tex0+g_fPageOffset.zw, g_fTexOffset.xy); + //tex0.xy = g_fPageOffset.xy * tex0.xy - ffrac * g_fc0.yw; + tex0.y += g_fPageOffset.y * ffrac.y; + + if( ffrac.x > g_fTexOffset.z ) { + tex0.x -= g_fTexOffset.z; + tex0.y += g_fTexOffset.w; + } + + float fconst = g_fc0.w*g_fc0.w; + float4 lower = tex2D(g_sSrcFinal, g_fTexDims.xy*tex0); + float4 upper = tex2D(g_sMemory, g_fTexDims.xy*tex0+g_fTexDims.zw); + + final.zy = tex3D(g_sConv32to16, lower.zyx).xy + lower.ww*fconst; + final.xw = tex3D(g_sConv32to16, upper.zyx).xy + upper.ww*fconst; + return final; +} + + +//half4 f; +//f.w = old.y > (127.2f/255.0f) ? 1 : 0; +//old.y -= 0.5f * f.w; +//f.xyz = frac(old.yyx*half3(2.002*255.0f/256.0f, 64.025f*255.0f/256.0f, 8.002*255.0f/256.0f)); +//f.y += old.x * (0.25f*255.0f/256.0f); + +//////////////////////////////// +// calculates the texture color +//////////////////////////////// + +#define decl_ps2shade(num) \ +decl_ps2shade_##num(_32) \ +decl_ps2shade_##num(_tex32) \ +decl_ps2shade_##num(_clut32) \ +decl_ps2shade_##num(_tex32to16) \ +decl_ps2shade_##num(_tex16to8h) \ +decl_ps2shade_##num(_tex16to32h) \ + +// nearest +#define decl_ps2shade_0(bit) \ +float4 ps2shade0##bit( TEX_DECL tex) \ +{ \ + return tex2DPS##bit( ps2addr(TEX_XY)); \ +} \ + +// do fast memcoord4 calcs when textures behave well +#ifdef REPEAT +#define PS2MEMCOORD4 ps2memcoord4 +#else +#define PS2MEMCOORD4 ps2memcoord4 +#endif + +#define decl_BilinearFilter(bit, addrfn) \ +half4 BilinearFilter##bit(float2 tex0) \ +{ \ + float4 off0, off1; \ + float4 ftex; \ + float2 ffrac; \ + ftex.xy = tex0 + g_fBilinear.xy * g_fRealTexDims.zw; \ + ffrac = frac(ftex.xy*g_fRealTexDims.xy); \ + ftex.xy -= ffrac.xy * g_fRealTexDims.zw; \ + \ + ftex.zw = ps2addr(ftex.xy + g_fRealTexDims.zw); \ + ftex.xy = ps2addr(ftex.xy); \ + \ + PS2MEMCOORD4(ftex, off0, off1); \ + half4 c0 = texRECT(g_sMemory, off0.xy); \ + half4 c1 = texRECT(g_sMemory, off0.zw); \ + half4 c2 = texRECT(g_sMemory, off1.xy); \ + half4 c3 = texRECT(g_sMemory, off1.zw); \ + return lerp( lerp(c0, c1, ffrac.x), lerp(c2, c3, ffrac.x), ffrac.y ); \ +} \ + +decl_BilinearFilter(_32, ps2addr) +decl_BilinearFilter(_tex32, ps2addr) +decl_BilinearFilter(_clut32, ps2addr) +decl_BilinearFilter(_tex32to16, ps2addr) +decl_BilinearFilter(_tex16to8h, ps2addr) +decl_BilinearFilter(_tex16to32h, ps2addr) + +//TODO! For mip maps, only apply when LOD >= 0 +// lcm == 0, LOD = log(1/Q)*L + K, lcm == 1, LOD = K + +// bilinear +#define decl_ps2shade_1(bit) \ +half4 ps2shade1##bit(TEX_DECL tex) \ +{ \ + return BilinearFilter##bit(TEX_XY); \ +} \ + +// nearest, mip nearest +#define decl_ps2shade_2(bit) \ +half4 ps2shade2##bit(TEX_DECL tex) \ +{ \ + return tex2DPS##bit( ps2addr(TEX_XY)); \ +} \ + +// nearest, mip linear +#define decl_ps2shade_3(bit) \ +half4 ps2shade3##bit(TEX_DECL tex) \ +{ \ + return tex2DPS##bit(ps2addr(TEX_XY)); \ +} \ + +// linear, mip nearest +#define decl_ps2shade_4(bit) \ +half4 ps2shade4##bit(TEX_DECL tex) \ +{ \ + return BilinearFilter##bit(TEX_XY); \ +} \ + +// linear, mip linear +#define decl_ps2shade_5(bit) \ +half4 ps2shade5##bit(TEX_DECL tex) \ +{ \ + return BilinearFilter##bit(TEX_XY); \ +} \ + +decl_ps2shade(0) +decl_ps2shade(1) +decl_ps2shade(2) +decl_ps2shade(3) +decl_ps2shade(4) +decl_ps2shade(5) + +half4 ps2CalcShade(half4 texcol, half4 color) +{ +#ifdef TEST_AEM + if( dot(texcol.xyzw, g_fTestBlack.xyzw) <= g_fc0.z ) + texcol.w = g_fc0.x; + else +#endif + texcol.w = texcol.w * fTexAlpha.y + fTexAlpha.x; + + texcol = texcol * (fTexAlpha2.zzzw * color + fTexAlpha2.xxxy) + fTexAlpha.zzzw * color.wwww; + + return texcol; +} + +// final ops on the color +#ifdef EXACT_COLOR + +half4 ps2FinalColor(half4 col) +{ + // g_fOneColor has to scale by 255 + half4 temp = col * g_fOneColor.xxxy + g_fOneColor.zzzw; + temp.w = floor(temp.w)*g_fExactColor.w; + return temp; +} + +#else +half4 ps2FinalColor(half4 col) +{ + return col * g_fOneColor.xxxy + g_fOneColor.zzzw; +} +#endif + +//////////////// +// Techniques // +//////////////// + +// technique to copy a rectangle from source to target +struct VSOUT_ +{ + float4 pos : POSITION; + half4 color : COLOR0; + DOZWRITE(float4 z : TEXCOORD0;) +}; + +struct VSOUT_T +{ + float4 pos : POSITION; + half4 color : COLOR0; + TEX_DECL tex : TEXCOORD0; + DOZWRITE(float4 z : TEXCOORD1;) +}; + +struct VSOUT_F +{ + float4 pos : POSITION; + half4 color : COLOR0; + float fog : TEXCOORD0; + DOZWRITE(float4 z : TEXCOORD1;) +}; + +struct VSOUT_TF +{ + float4 pos : POSITION; + half4 color : COLOR0; + TEX_DECL tex : TEXCOORD0; + half fog : TEXCOORD1; + DOZWRITE(float4 z : TEXCOORD2;) +}; + +// just smooth shadering +VSOUT_ RegularVS(float4 pos : POSITION, + half4 color : COLOR0, + float4 z : COLOR1 + ) +{ + VSOUT_ o; + + o.pos.xy = pos.xy*g_fPosXY.xy+g_fPosXY.zw; + o.pos.z = (log(g_fc0.y+dot(g_fZ, z.zyxw))*g_fZNorm.x+g_fZNorm.y) * g_fZMin.y + dot(g_fZ, z.zyxw) * g_fZMin.x ; + o.pos.w = g_fc0.y; // 1 + o.color = color; + + DOZWRITE(o.z = z*g_fZBias.x+g_fZBias.y; o.z.w = g_fc0.y;) + return o; +} + +void RegularPS(VSOUT_ i, out float4 c0 : COLOR0 +#ifdef WRITE_DEPTH + , out float4 c1 : COLOR1 +#endif + ) +{ + // whenever outputting depth, make sure to mult by 255/256 and 1 + c0 = ps2FinalColor(i.color); + DOZWRITE(c1 = i.z;) +} + +// diffuse texture mapping +VSOUT_T TextureVS(float4 pos : POSITION, + half4 color : COLOR0, + float4 z : COLOR1, + float3 tex0 : TEXCOORD0) +{ + VSOUT_T o; + o.pos.xy = pos.xy*g_fPosXY.xy+g_fPosXY.zw; + o.pos.z = (log(g_fc0.y+dot(g_fZ, z.zyxw))*g_fZNorm.x + g_fZNorm.y) * g_fZMin.y + dot(g_fZ, z.zyxw) * g_fZMin.x ; + o.pos.w = g_fc0.y; + o.color = color; + DOZWRITE(o.z = z*g_fZBias.x+g_fZBias.y; o.z.w = g_fc0.y;) +#ifdef PERSPECTIVE_CORRECT_TEX + o.tex = tex0; +#else + o.tex = tex0.xy/tex0.z; +#endif + return o; +} + +#ifdef WRITE_DEPTH + +#define DECL_TEXPS(num, bit) \ +void Texture##num##bit##PS(VSOUT_T i, out half4 c0 : COLOR0, out float4 c1 : COLOR1) \ +{ \ + c0 = ps2FinalColor(ps2CalcShade(ps2shade##num##bit(i.tex), i.color)); \ + c1 = i.z; \ +} \ + +#else + +#define DECL_TEXPS(num, bit) \ +void Texture##num##bit##PS(VSOUT_T i, out half4 c0 : COLOR0) \ +{ \ + c0 = ps2FinalColor(ps2CalcShade(ps2shade##num##bit(i.tex), i.color)); \ +} \ + +#endif + +#define DECL_TEXPS_(num) \ +DECL_TEXPS(num, _32) \ +DECL_TEXPS(num, _tex32) \ +DECL_TEXPS(num, _clut32) \ +DECL_TEXPS(num, _tex32to16) \ +DECL_TEXPS(num, _tex16to8h) \ + +DECL_TEXPS_(0) +DECL_TEXPS_(1) +DECL_TEXPS_(2) +DECL_TEXPS_(3) +DECL_TEXPS_(4) +DECL_TEXPS_(5) + +VSOUT_F RegularFogVS(float4 pos : POSITION, + half4 color : COLOR0, + float4 z : COLOR1) +{ + VSOUT_F o; + + o.pos.xy = pos.xy*g_fPosXY.xy+g_fPosXY.zw; + o.pos.z = (log(g_fc0.y+dot(g_fZ, z.zyxw))*g_fZNorm.x+g_fZNorm.y) * g_fZMin.y + dot(g_fZ, z.zyxw) * g_fZMin.x ; + o.pos.w = g_fc0.y; + DOZWRITE(o.z = z*g_fZBias.x+g_fZBias.y; o.z.w = g_fc0.y;) + o.color = color; + o.fog = pos.z*g_fBilinear.w; + return o; +} + +void RegularFogPS(VSOUT_F i, out half4 c0 : COLOR0 +#ifdef WRITE_DEPTH + , out float4 c1 : COLOR1 +#endif + ) +{ + half4 c; + c.xyz = lerp(g_fFogColor.xyz, i.color.xyz, i.fog); + c.w = i.color.w; + c0 = ps2FinalColor(c); + DOZWRITE(c1 = i.z;) +} + +VSOUT_TF TextureFogVS(float4 pos : POSITION, + half4 color : COLOR0, + float4 z : COLOR1, + float3 tex0 : TEXCOORD0) +{ + VSOUT_TF o; + + o.pos.xy = pos.xy*g_fPosXY.xy+g_fPosXY.zw; + o.pos.z = (log(g_fc0.y+dot(g_fZ, z.zyxw))*g_fZNorm.x+g_fZNorm.y) * g_fZMin.y + dot(g_fZ, z.zyxw) * g_fZMin.x ; + o.pos.w = g_fc0.y; + o.color = color; + o.fog = pos.z*g_fBilinear.w; + DOZWRITE(o.z = z*g_fZBias.x+g_fZBias.y; o.z.w = g_fc0.y;) +#ifdef PERSPECTIVE_CORRECT_TEX + o.tex = tex0; +#else + o.tex = tex0.xy/tex0.z; +#endif + return o; +} + +#ifdef WRITE_DEPTH + +#define DECL_TEXFOGPS(num, bit) \ +void TextureFog##num##bit##PS(VSOUT_TF i, out half4 c0 : COLOR0, out float4 c1 : COLOR1 ) \ +{ \ + half4 c = ps2CalcShade(ps2shade##num##bit(i.tex), i.color); \ + c.xyz = lerp(g_fFogColor.xyz, c.xyz, i.fog); \ + c0 = ps2FinalColor(c); \ + c1 = i.z; \ +} \ + +#else + +#define DECL_TEXFOGPS(num, bit) \ +void TextureFog##num##bit##PS(VSOUT_TF i, out half4 c0 : COLOR0) \ +{ \ + half4 c = ps2CalcShade(ps2shade##num##bit(i.tex), i.color); \ + c.xyz = lerp(g_fFogColor.xyz, c.xyz, i.fog); \ + c0 = ps2FinalColor(c); \ +} \ + +#endif + +#define DECL_TEXFOGPS_(num) \ +DECL_TEXFOGPS(num, _32) \ +DECL_TEXFOGPS(num, _tex32) \ +DECL_TEXFOGPS(num, _clut32) \ +DECL_TEXFOGPS(num, _tex32to16) \ +DECL_TEXFOGPS(num, _tex16to8h) \ + +DECL_TEXFOGPS_(0) +DECL_TEXFOGPS_(1) +DECL_TEXFOGPS_(2) +DECL_TEXFOGPS_(3) +DECL_TEXFOGPS_(4) +DECL_TEXFOGPS_(5) + +//------------------------------------------------------- +// Techniques not related to the main primitive commands +half4 BilinearBitBlt(float2 tex0) +{ + float4 ftex; + float2 ffrac; + + ffrac.xy = frac(tex0*g_fRealTexDims.xy); + ftex.xy = tex0 - ffrac.xy * g_fRealTexDims.zw; + ftex.zw = ftex.xy + g_fRealTexDims.zw; + + float4 off0, off1; + ps2memcoord4_fast(ftex, off0, off1); + half4 c0 = texRECT(g_sMemory, off0.xy); + half4 c1 = texRECT(g_sMemory, off0.zw); + half4 c2 = texRECT(g_sMemory, off1.xy); + half4 c3 = texRECT(g_sMemory, off1.zw); + + return lerp( lerp(c0, c1, ffrac.x), lerp(c2, c3, ffrac.x), ffrac.y ); +} + +void BitBltVS(in float4 pos : POSITION, + in half4 tex0 : COLOR1, + in float3 tex : TEXCOORD0, + out float4 opos : POSITION, + out float2 otex0 : TEXCOORD0, + out float2 ointerpos : TEXCOORD1) +{ + opos.xy = pos.xy * g_fBitBltPos.xy + g_fBitBltPos.zw; + ointerpos = opos.xy * g_fBitBltTrans.xy + g_fBitBltTrans.zw; + opos.zw = g_fc0.xy; + otex0 = tex.xy * g_fBitBltTex.xy + g_fBitBltTex.zw; +} + +half4 BitBltPS(in float2 tex0 : TEXCOORD0) : COLOR +{ + return texRECT(g_sMemory, ps2memcoord(tex0).xy)*g_fOneColor.xxxy; +} + +// used when AA +half4 BitBltAAPS(in float2 tex0 : TEXCOORD0) : COLOR +{ + return BilinearBitBlt(tex0)*g_fOneColor.xxxy; +} + +void BitBltDepthPS(in float2 tex0 : TEXCOORD0, + out float4 c : COLOR0, + out float depth : DEPTH) +{ + c = texRECT(g_sMemory, ps2memcoord(tex0)); + + depth = (log(g_fc0.y+dot(c, g_fBitBltZ))*g_fOneColor.w) * g_fZMin.y + dot(c, g_fBitBltZ) * g_fZMin.x ; + c += g_fZBias.y; +} + +void BitBltDepthMRTPS(in float2 tex0 : TEXCOORD0, + out half4 c0 : COLOR0, + out float4 c1 : COLOR1, + out float depth : DEPTH) +{ + c1 = texRECT(g_sMemory, ps2memcoord(tex0)); + + depth = (log(g_fc0.y+dot(c1, g_fBitBltZ))*g_fOneColor.w) * g_fZMin.y + dot(c1, g_fBitBltZ) * g_fZMin.x ; + c1 += g_fZBias.y; + c0 = g_fc0.x; +} + +/*static const float BlurKernel[9] = { + 0.027601, + 0.066213, + 0.123701, + 0.179952, + 0.205065, + 0.179952, + 0.123701, + 0.066213, + 0.027601 +};*/ + +half4 BilinearFloat16(float2 tex0) +{ + return texRECT(g_sSrcFinal, tex0.xy); +} + +half4 CRTCTargInterPS(in float2 tex0 : TEXCOORD0, in float2 ointerpos : TEXCOORD1) : COLOR +{ + float finter = texRECT(g_sInterlace, ointerpos.yy).x * g_fOneColor.z + g_fOneColor.w + g_fc0.w; + float4 c = BilinearFloat16(tex0); + c.w = ( g_fc0.w*c.w * g_fOneColor.x + g_fOneColor.y ) * finter; + return c; +} + +half4 CRTCTargPS(in float2 tex0 : TEXCOORD0) : COLOR +{ + float4 c = BilinearFloat16(tex0); + c.w = g_fc0.w*c.w * g_fOneColor.x + g_fOneColor.y; + return c; +} + +half4 CRTCInterPS(in float2 tex0 : TEXCOORD0, in float2 ointerpos : TEXCOORD1) : COLOR +{ + float finter = texRECT(g_sInterlace, ointerpos.yy).x * g_fOneColor.z + g_fOneColor.w + g_fc0.w; + float2 filtcoord = (tex0-frac(tex0))*g_fInvTexDims.xy+g_fInvTexDims.zw; + half4 c = BilinearBitBlt(filtcoord); + c.w = (c.w * g_fOneColor.x + g_fOneColor.y)*finter; + + return c; +} + +// simpler +half4 CRTCInterPS_Nearest(in float2 tex0 : TEXCOORD0, in float2 ointerpos : TEXCOORD1) : COLOR +{ + float finter = texRECT(g_sInterlace, ointerpos.yy).x * g_fOneColor.z + g_fOneColor.w + g_fc0.w; + half4 c = texRECT(g_sMemory, ps2memcoord(tex0).xy); + c.w = (c.w * g_fOneColor.x + g_fOneColor.y)*finter; + return c; +} + +half4 CRTCPS(in float2 tex0 : TEXCOORD0) : COLOR +{ + float2 filtcoord = (tex0/*-frac(tex0)*/)*g_fInvTexDims.xy+g_fInvTexDims.zw; + half4 c = BilinearBitBlt(filtcoord); + c.w = c.w * g_fOneColor.x + g_fOneColor.y; + + return c; +} + +// simpler +half4 CRTCPS_Nearest(in float2 tex0 : TEXCOORD0) : COLOR +{ + half4 c = texRECT(g_sMemory, ps2memcoord(tex0).xy); + c.w = c.w * g_fOneColor.x + g_fOneColor.y; + return c; +} + +half4 CRTC24InterPS(in float2 tex0 : TEXCOORD0, in float2 ointerpos : TEXCOORD1) : COLOR +{ + float finter = texRECT(g_sInterlace, ointerpos.yy).x * g_fOneColor.z + g_fOneColor.w + g_fc0.w; + float2 filtcoord = (tex0-frac(tex0))*g_fInvTexDims.xy+g_fInvTexDims.zw; + + half4 c = texRECT(g_sMemory, ps2memcoord(filtcoord).xy).x; + c.w = (c.w * g_fOneColor.x + g_fOneColor.y)*finter; + + return c; +} + +half4 CRTC24PS(in float2 tex0 : TEXCOORD0) : COLOR +{ + float2 filtcoord = (tex0-frac(tex0))*g_fInvTexDims.xy+g_fInvTexDims.zw; + half4 c = texRECT(g_sMemory, ps2memcoord(filtcoord).xy).x; + c.w = c.w * g_fOneColor.x + g_fOneColor.y; + + return c; +} + +half4 ZeroPS() : COLOR +{ + return g_fOneColor.x; +} + +half4 BaseTexturePS(in float2 tex0 : TEXCOORD0) : COLOR +{ + return texRECT(g_sSrcFinal, tex0) * g_fOneColor; +} + +half4 Convert16to32PS(float2 tex0 : TEXCOORD0) : COLOR +{ + float4 final; + float2 ffrac = fmod(tex0+g_fTexDims.zw, g_fTexOffset.xy); + tex0.xy = g_fTexDims.xy * tex0.xy - ffrac * g_fc0.yw; + + if( ffrac.x > g_fTexOffset.x*g_fc0.w ) + tex0.x += g_fTexOffset.x*g_fc0.w; + if( tex0.x >= g_fc0.y ) tex0 += g_fTexOffset.zw; + + float4 lower = texRECT(g_sSrcFinal, tex0); + float4 upper = texRECT(g_sSrcFinal, tex0+g_fPageOffset.xy); + + final.zy = tex3D(g_sConv32to16, lower.zyx).xy + lower.ww*g_fPageOffset.zw; + final.xw = tex3D(g_sConv32to16, upper.zyx).xy + upper.ww*g_fPageOffset.zw; + + return final; +} + +// use when texture is not tiled and converting from 32bit to 16bit +// don't convert on the block level, only on the column level +// so every other 8 pixels, use the upper bits instead of lower +half4 Convert32to16PS(float2 tex0 : TEXCOORD0) : COLOR +{ + bool upper = false; + float2 ffrac = fmod(tex0+g_fTexDims.zw, g_fTexOffset.xy); + tex0.xy = g_fc0.ww * (tex0.xy + ffrac); + if( ffrac.x > g_fTexOffset.z ) { + tex0.x -= g_fTexOffset.z; + upper = true; + } + if( ffrac.y >= g_fTexOffset.w ) { + tex0.y -= g_fTexOffset.w; + tex0.x += g_fc0.w; + } + + half4 color = texRECT(g_sSrcFinal, tex0*g_fTexDims.xy)*g_fc0.yyyw; + float2 uv = upper ? color.xw : color.zy; + return tex2D(g_sConv16to32, uv*g_fPageOffset.xy+g_fPageOffset.zw)*g_fTexDims.xxxy; +} diff --git a/plugins/zzogl-pg-cg/opengl/rasterfont.cpp b/plugins/zzogl-pg-cg/opengl/rasterfont.cpp new file mode 100644 index 000000000..38b04ccf4 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/rasterfont.cpp @@ -0,0 +1,168 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifdef _WIN32 +#include "Utilities/RedtapeWindows.h" +#endif + +#include +#include + +#include "rasterfont.h" +// globals + +GLubyte rasters[][13] = +{ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36}, + {0x00, 0x00, 0x00, 0x66, 0x66, 0xff, 0x66, 0x66, 0xff, 0x66, 0x66, 0x00, 0x00}, + {0x00, 0x00, 0x18, 0x7e, 0xff, 0x1b, 0x1f, 0x7e, 0xf8, 0xd8, 0xff, 0x7e, 0x18}, + {0x00, 0x00, 0x0e, 0x1b, 0xdb, 0x6e, 0x30, 0x18, 0x0c, 0x76, 0xdb, 0xd8, 0x70}, + {0x00, 0x00, 0x7f, 0xc6, 0xcf, 0xd8, 0x70, 0x70, 0xd8, 0xcc, 0xcc, 0x6c, 0x38}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1c, 0x0c, 0x0e}, + {0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c}, + {0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30}, + {0x00, 0x00, 0x00, 0x00, 0x99, 0x5a, 0x3c, 0xff, 0x3c, 0x5a, 0x99, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00}, + {0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03, 0x03}, + {0x00, 0x00, 0x3c, 0x66, 0xc3, 0xe3, 0xf3, 0xdb, 0xcf, 0xc7, 0xc3, 0x66, 0x3c}, + {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x38, 0x18}, + {0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0xe7, 0x7e}, + {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0x07, 0x03, 0x03, 0xe7, 0x7e}, + {0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xcc, 0x6c, 0x3c, 0x1c, 0x0c}, + {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xff}, + {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e}, + {0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x03, 0x03, 0xff}, + {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e}, + {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x03, 0x7f, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e}, + {0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06}, + {0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60}, + {0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x06, 0x03, 0xc3, 0xc3, 0x7e}, + {0x00, 0x00, 0x3f, 0x60, 0xcf, 0xdb, 0xd3, 0xdd, 0xc3, 0x7e, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18}, + {0x00, 0x00, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe}, + {0x00, 0x00, 0x7e, 0xe7, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e}, + {0x00, 0x00, 0xfc, 0xce, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xce, 0xfc}, + {0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xff}, + {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xff}, + {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xcf, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e}, + {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, + {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e}, + {0x00, 0x00, 0x7c, 0xee, 0xc6, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06}, + {0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6, 0xc3}, + {0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0}, + {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xff, 0xff, 0xe7, 0xc3}, + {0x00, 0x00, 0xc7, 0xc7, 0xcf, 0xcf, 0xdf, 0xdb, 0xfb, 0xf3, 0xf3, 0xe3, 0xe3}, + {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e}, + {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe}, + {0x00, 0x00, 0x3f, 0x6e, 0xdf, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c}, + {0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe}, + {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0xe0, 0xc0, 0xc0, 0xe7, 0x7e}, + {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff}, + {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, + {0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, + {0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, + {0x00, 0x00, 0xc3, 0x66, 0x66, 0x3c, 0x3c, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3}, + {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3}, + {0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x7e, 0x0c, 0x06, 0x03, 0x03, 0xff}, + {0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c}, + {0x00, 0x03, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60}, + {0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18}, + {0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x30, 0x70}, + {0x00, 0x00, 0x7f, 0xc3, 0xc3, 0x7f, 0x03, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0}, + {0x00, 0x00, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x03, 0x03, 0x03, 0x03, 0x03}, + {0x00, 0x00, 0x7f, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x33, 0x1e}, + {0x7e, 0xc3, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0}, + {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00}, + {0x38, 0x6c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x0c, 0x00}, + {0x00, 0x00, 0xc6, 0xcc, 0xf8, 0xf0, 0xd8, 0xcc, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0}, + {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78}, + {0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xfe, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, + {0xc0, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0x00, 0x00, 0x00, 0x00}, + {0x03, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, 0xfe, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xfe, 0x03, 0x03, 0x7e, 0xc0, 0xc0, 0x7f, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x00}, + {0x00, 0x00, 0x7e, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xc3, 0xe7, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00}, + {0xc0, 0x60, 0x60, 0x30, 0x18, 0x3c, 0x66, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xff, 0x60, 0x30, 0x18, 0x0c, 0x06, 0xff, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x0f, 0x18, 0x18, 0x18, 0x38, 0xf0, 0x38, 0x18, 0x18, 0x18, 0x0f}, + {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, + {0x00, 0x00, 0xf0, 0x18, 0x18, 0x18, 0x1c, 0x0f, 0x1c, 0x18, 0x18, 0x18, 0xf0}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x8f, 0xf1, 0x60, 0x00, 0x00, 0x00} +}; + +RasterFont::RasterFont() +{ + // set GL modes + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + // create the raster font + fontOffset = glGenLists(128); + + for (int i = 32; i < 127; i++) + { + glNewList(i + fontOffset, GL_COMPILE); + glBitmap(8, 13, 0.0f, 2.0f, 10.0f, 0.0f, rasters[i-32]); + glEndList(); + } +} + +RasterFont::~RasterFont() +{ + glDeleteLists(fontOffset, 128); +} + +void RasterFont::printString(const char *s, double x, double y, double z) +{ + // go to the right spot + glRasterPos3d(x, y, z); + + glPushAttrib(GL_LIST_BIT); + glListBase(fontOffset); + glCallLists(strlen(s), GL_UNSIGNED_BYTE, (GLubyte *) s); + glPopAttrib(); +} + +void RasterFont::printCenteredString(const char *s, double y, int screen_width, double z) +{ + int length = strlen(s); + int x = int(screen_width / 2.0 - (length / 2.0) * char_width); + + printString(s, x, y, z); +} + diff --git a/plugins/zzogl-pg-cg/opengl/rasterfont.h b/plugins/zzogl-pg-cg/opengl/rasterfont.h new file mode 100644 index 000000000..80a341099 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/rasterfont.h @@ -0,0 +1,43 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef RasterFont_Header +#define RasterFont_Header + +class RasterFont +{ + + protected: + int fontOffset; + + public: + RasterFont(); + ~RasterFont(void); + static int debug; + + // some useful constants + enum {char_width = 10}; + enum {char_height = 15}; + + // and the happy helper functions + void printString(const char *s, double x, double y, double z = 0.0); + void printCenteredString(const char *s, double y, int screen_width, double z = 0.0); +}; + +#endif diff --git a/plugins/zzogl-pg-cg/opengl/shaders.sh b/plugins/zzogl-pg-cg/opengl/shaders.sh new file mode 100755 index 000000000..7c5e57b04 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/shaders.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +# PCSX2 - PS2 Emulator for PCs +# Copyright (C) 2002-2011 PCSX2 Dev Team +# +# PCSX2 is free software: you can redistribute it and/or modify it under the terms +# of the GNU Lesser General Public License as published by the Free Software Found- +# ation, either version 3 of the License, or (at your option) any later version. +# +# PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with PCSX2. +# If not, see . + +./zgsbuild ps2hw.fx +cp ps2hw.dat ../../../bin/plugins/ diff --git a/plugins/zzogl-pg-cg/opengl/targets.cpp b/plugins/zzogl-pg-cg/opengl/targets.cpp new file mode 100644 index 000000000..8b134a72e --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/targets.cpp @@ -0,0 +1,3521 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "GS.h" + +#include + +#include "Mem.h" +#include "x86.h" +#include "targets.h" +#include "ZZoglShaders.h" +#include "ZZClut.h" +#include +#include "ZZoglVB.h" + +#ifdef ZEROGS_SSE2 +#include +#endif + +const float g_filog32 = 0.999f / (32.0f * logf(2.0f)); +#define RHA +//#define RW + +extern int g_TransferredToGPU; +extern bool g_bUpdateStencil; + +#if !defined(ZEROGS_DEVBUILD) +# define INC_RESOLVE() +#else +# define INC_RESOLVE() ++g_nResolve +#endif + +extern int s_nResolved; +extern u32 g_nResolve; +extern bool g_bSaveTrans; + +CRenderTargetMngr s_RTs, s_DepthRTs; +CBitwiseTextureMngr s_BitwiseTextures; +CMemoryTargetMngr g_MemTargs; + +//extern u32 s_ptexCurSet[2]; +bool g_bSaveZUpdate = 0; + +int VALIDATE_THRESH = 8; +u32 TEXDESTROY_THRESH = 16; +#define FORCE_TEXDESTROY_THRESH (3) // destroy texture after FORCE_TEXDESTROY_THRESH frames + +void _Resolve(const void* psrc, int fbp, int fbw, int fbh, int psm, u32 fbm, bool mode); +void SetWriteDepth(); +bool IsWriteDepth(); +bool IsWriteDestAlphaTest(); + +// ------------------------- Useful inlines ------------------------------------ + +// memory size for one row of texture. It depends on width of texture and number of bytes +// per pixel +inline u32 Pitch(int fbw) { return (RW(fbw) * 4) ; } + +// memory size of whole texture. It is number of rows multiplied by memory size of row +inline u32 Tex_Memory_Size(int fbw, int fbh) { return (RH(fbh) * Pitch(fbw)); } + +// Often called for several reasons +// Call flush if renderer or depth target is equal to ptr +inline void FlushIfNecesary(void* ptr) +{ + if (vb[0].prndr == ptr || vb[0].pdepth == ptr) Flush(0); + if (vb[1].prndr == ptr || vb[1].pdepth == ptr) Flush(1); +} + +// This block was repeated several times, so I inlined it. +inline void DestroyAllTargetsHelper(void* ptr) +{ + for (int i = 0; i < 2; ++i) + { + if (ptr == vb[i].prndr) { vb[i].prndr = NULL; vb[i].bNeedFrameCheck = 1; } + if (ptr == vb[i].pdepth) { vb[i].pdepth = NULL; vb[i].bNeedZCheck = 1; } + } +} + +// Made an empty texture and bind it to $ptr_p +// returns false if creating texture was unsuccessful +// fbh and fdb should be properly shifted before calling this! +// We should ignore framebuffer trouble here, as we put textures of different sizes to it. +inline bool CRenderTarget::InitialiseDefaultTexture(u32 *ptr_p, int fbw, int fbh) +{ + glGenTextures(1, ptr_p); + glBindTexture(GL_TEXTURE_RECTANGLE_NV, *ptr_p); + + // initialize to default + TextureRect(GL_RGBA, fbw, fbh, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + setRectWrap(GL_CLAMP); + setRectFilters(GL_LINEAR); + + GLenum Error = glGetError(); + return ((Error == GL_NO_ERROR) || (Error == GL_INVALID_FRAMEBUFFER_OPERATION_EXT)); +} + +// Draw 4 triangles from binded array using only stencil buffer +inline void FillOnlyStencilBuffer() +{ + if (IsWriteDestAlphaTest() && !(conf.settings().no_stencil)) + { + glColorMask(0, 0, 0, 0); + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GEQUAL, 1.0f); + + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + glStencilFunc(GL_ALWAYS, 1, 0xff); + + DrawTriangleArray(); + glColorMask(1, 1, 1, 1); + } +} + +// used for transformation from vertex position in GS window.coords (I hope) +// to view coordinates (in range 0, 1). +inline float4 CRenderTarget::DefaultBitBltPos() +{ + float4 v = float4(1, -1, 0.5f / (float)RW(fbw), 0.5f / (float)RH(fbh)); + v *= 1.0f / 32767.0f; + ZZshSetParameter4fv(pvsBitBlt.prog, pvsBitBlt.sBitBltPos, v, "g_sBitBltPos"); + return v; +} + +// Used to transform texture coordinates from GS (when 0,0 is upper left) to +// OpenGL (0,0 - lower left). +inline float4 CRenderTarget::DefaultBitBltTex() +{ + // I really sure that -0.5 is correct, because OpenGL have no half-offset + // issue, DirectX known for. + float4 v = float4(1, -1, 0.5f / (float)RW(fbw), -0.5f / (float)RH(fbh)); + ZZshSetParameter4fv(pvsBitBlt.prog, pvsBitBlt.sBitBltTex, v, "g_sBitBltTex"); + return v; +} + +inline void BindToSample(u32 *p_ptr) +{ + glBindTexture(GL_TEXTURE_RECTANGLE_NV, *p_ptr); + setRectFilters(GL_NEAREST); +} + +//////////////////// +// Render Targets // +//////////////////// +CRenderTarget::CRenderTarget() : ptex(0), ptexFeedback(0), psys(NULL) +{ + FUNCLOG + nUpdateTarg = 0; +} + +CRenderTarget::~CRenderTarget() +{ + FUNCLOG + Destroy(); +} + +bool CRenderTarget::Create(const frameInfo& frame) +{ + FUNCLOG + Resolve(); + Destroy(); + created = 123; + + lastused = timeGetTime(); + fbp = frame.fbp; + fbw = frame.fbw; + fbh = frame.fbh; + psm = (u8)frame.psm; + fbm = frame.fbm; + + vposxy.x = 2.0f * (1.0f / 8.0f) / (float)fbw; + vposxy.y = 2.0f * (1.0f / 8.0f) / (float)fbh; + vposxy.z = -1 - 0.5f / (float)fbw; + vposxy.w = -1 + 0.5f / (float)fbh; + status = 0; + + if (fbw > 0 && fbh > 0) + { + GetRectMemAddress(start, end, psm, 0, 0, fbw, fbh, fbp, fbw); + psys = _aligned_malloc(Tex_Memory_Size(fbw, fbh), 16); + + GL_REPORT_ERRORD(); + + if (!InitialiseDefaultTexture(&ptex, RW(fbw), RH(fbh))) + { + Destroy(); + return false; + } + + status = TS_NeedUpdate; + } + else + { + start = end = 0; + } + + return true; +} + +void CRenderTarget::Destroy() +{ + FUNCLOG + created = 1; + _aligned_free(psys); + psys = NULL; + SAFE_RELEASE_TEX(ptex); + SAFE_RELEASE_TEX(ptexFeedback); +} + +void CRenderTarget::SetTarget(int fbplocal, const Rect2& scissor, int context) +{ + FUNCLOG + int dy = 0; + + if (fbplocal != fbp) + { + float4 v; + + // will be rendering to a subregion + u32 bpp = PSMT_ISHALF(psm) ? 2 : 4; + assert(((256 / bpp)*(fbplocal - fbp)) % fbw == 0); + assert(fbplocal >= fbp); + + dy = ((256 / bpp) * (fbplocal - fbp)) / fbw; + + v.x = vposxy.x; + v.y = vposxy.y; + v.z = vposxy.z; + v.w = vposxy.w - dy * 2.0f / (float)fbh; + ZZshSetParameter4fv(g_vparamPosXY[context], v, "g_fPosXY"); + } + else + { + ZZshSetParameter4fv(g_vparamPosXY[context], vposxy, "g_fPosXY"); + } + + // set render states + // Bleh. I *really* need to fix this. << 3 when setting the scissors, then >> 3 when using them... --Arcum42 + scissorrect.x = scissor.x0 >> 3; + scissorrect.y = (scissor.y0 >> 3) + dy; + scissorrect.w = (scissor.x1 >> 3) + 1; + scissorrect.h = (scissor.y1 >> 3) + 1 + dy; + + scissorrect.w = min(scissorrect.w, fbw) - scissorrect.x; + scissorrect.h = min(scissorrect.h, fbh) - scissorrect.y; + + scissorrect.x = RW(scissorrect.x); + scissorrect.y = RH(scissorrect.y); + scissorrect.w = RW(scissorrect.w); + scissorrect.h = RH(scissorrect.h); +} + +void CRenderTarget::SetViewport() +{ + FUNCLOG + glViewport(0, 0, RW(fbw), RH(fbh)); +} + +inline bool NotResolveHelper() +{ + return ((s_nResolved > 8 && (2 * s_nResolved > fFPS - 10)) || (conf.settings().no_target_resolve)); +} + +void CRenderTarget::Resolve() +{ + FUNCLOG + + if (ptex != 0 && !(status&TS_Resolved) && !(status&TS_NeedUpdate)) + { + // flush if necessary + FlushIfNecesary(this) ; + + if ((IsDepth() && !IsWriteDepth()) || NotResolveHelper()) + { + // don't resolve if depths aren't used + status = TS_Resolved; + return; + } + + glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptex); + + GL_REPORT_ERRORD(); + // This code extremely slow on DC1. +// _aligned_free(psys); +// psys = _aligned_malloc( Tex_Memory_Size ( fbw, fbh ), 16 ); + + glGetTexImage(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA, GL_UNSIGNED_BYTE, psys); + + GL_REPORT_ERRORD(); + +#if defined(ZEROGS_DEVBUILD) + + if (g_bSaveResolved) + { + SaveTexture("resolved.tga", GL_TEXTURE_RECTANGLE_NV, ptex, RW(fbw), RH(fbh)); + g_bSaveResolved = 0; + } + +#endif + _Resolve(psys, fbp, fbw, fbh, psm, fbm, true); + + status = TS_Resolved; + } +} + +void CRenderTarget::Resolve(int startrange, int endrange) +{ + FUNCLOG + + assert(startrange < end && endrange > start); // make sure it at least intersects + + if (ptex != 0 && !(status&TS_Resolved) && !(status&TS_NeedUpdate)) + { + // flush if necessary + FlushIfNecesary(this) ; + +#if defined(ZEROGS_DEVBUILD) + if (g_bSaveResolved) + { + SaveTexture("resolved.tga", GL_TEXTURE_RECTANGLE_NV, ptex, RW(fbw), RH(fbh)); + g_bSaveResolved = 0; + } +#endif + if (conf.settings().no_target_resolve) + { + status = TS_Resolved; + return; + } + + int blockheight = PSMT_ISHALF(psm) ? 64 : 32; + int resolvefbp = fbp, resolveheight = fbh; + int scanlinewidth = 0x2000 * (fbw >> 6); + + // in no way should data be overwritten!, instead resolve less + + if (endrange < end) + { + // round down to nearest block and scanline + resolveheight = ((endrange - start) / (0x2000 * (fbw >> 6))) * blockheight; + + if (resolveheight <= 32) + { + status = TS_Resolved; + return; + } + } + else if (startrange > start) + { + // round up to nearest block and scanline + resolvefbp = startrange + scanlinewidth - 1; + resolvefbp -= resolvefbp % scanlinewidth; + + resolveheight = fbh - ((resolvefbp - fbp) * blockheight / scanlinewidth); + + if (resolveheight <= 64) // this is a total hack, but kh doesn't resolve now + { + status = TS_Resolved; + return; + } + + resolvefbp >>= 8; + } + + glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptex); + + glGetTexImage(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA, GL_UNSIGNED_BYTE, psys); + GL_REPORT_ERRORD(); + + u8* pbits = (u8*)psys; + + if (fbp != resolvefbp) pbits += ((resolvefbp - fbp) * 256 / scanlinewidth) * blockheight * Pitch(fbw); + + _Resolve(pbits, resolvefbp, fbw, resolveheight, psm, fbm, true); + + status = TS_Resolved; + } +} + +void CRenderTarget::Update(int context, CRenderTarget* pdepth) +{ + FUNCLOG + + DisableAllgl(); + + glBindBuffer(GL_ARRAY_BUFFER, vboRect); + SET_STREAM(); + + // assume depth already set + //pd3dDevice->SetDepthStencilSurface(psurfDepth); + ResetRenderTarget(1); + SetRenderTarget(0); + assert(pdepth != NULL); + ((CDepthTarget*)pdepth)->SetDepthStencilSurface(); + + SetShaderCaller("CRenderTarget::Update"); + float4 v = DefaultBitBltPos(); + + CRenderTargetMngr::MAPTARGETS::iterator ittarg; + + if (nUpdateTarg) + { + ittarg = s_RTs.mapTargets.find(nUpdateTarg); + + if (ittarg == s_RTs.mapTargets.end()) + { + ittarg = s_DepthRTs.mapTargets.find(nUpdateTarg); + + if (ittarg == s_DepthRTs.mapTargets.end()) + nUpdateTarg = 0; + else if (ittarg->second == this) + { + ZZLog::Debug_Log("Updating self."); + nUpdateTarg = 0; + } + } + else if (ittarg->second == this) + { + ZZLog::Debug_Log("Updating self."); + nUpdateTarg = 0; + } + } + + SetViewport(); + + if (nUpdateTarg) + { + ZZshGLSetTextureParameter(ppsBaseTexture.prog, ppsBaseTexture.sFinal, ittarg->second->ptex, "BaseTexture.final"); + + //assert( ittarg->second->fbw == fbw ); + int offset = (fbp - ittarg->second->fbp) * 64 / fbw; + + if (PSMT_ISHALF(psm)) // 16 bit + offset *= 2; + + v.x = (float)RW(fbw); + v.y = (float)RH(fbh); + v.z = 0.25f; + v.w = (float)RH(offset) + 0.25f; + + ZZshSetParameter4fv(pvsBitBlt.prog, pvsBitBlt.sBitBltTex, v, "g_fBitBltTex"); + +// v = DefaultBitBltTex(); Maybe? + ZZshDefaultOneColor ( ppsBaseTexture ); + + ZZshSetPixelShader(ppsBaseTexture.prog); + + nUpdateTarg = 0; + } + else + { + u32 bit_idx = (AA.x == 0) ? 0 : 1; + + // align the rect to the nearest page + // note that fbp is always aligned on page boundaries + tex0Info texframe; + texframe.tbp0 = fbp; + texframe.tbw = fbw; + texframe.tw = fbw; + texframe.th = fbh; + texframe.psm = psm; + // FIXME some field are not initialized... + // in particular the clut related one + assert(!PSMT_ISCLUT(psm)); + + // write color and zero out stencil buf, always 0 context! + // force bilinear if using AA + // Fix in r133 -- FFX movies and Gust backgrounds! + //SetTexVariablesInt(0, 0*(AA.x || AA.y) ? 2 : 0, texframe, false, &ppsBitBlt[!!s_AAx], 1); + SetTexVariablesInt(0, 0, texframe, false, &ppsBitBlt[bit_idx], 1); + ZZshGLSetTextureParameter(ppsBitBlt[bit_idx].prog, ppsBitBlt[bit_idx].sMemory, vb[0].pmemtarg->ptex->tex, "BitBlt.memory"); + + v = float4(1, 1, 0.0f, 0.0f); + ZZshSetParameter4fv(pvsBitBlt.prog, pvsBitBlt.sBitBltTex, v, "g_fBitBltTex"); + + v.x = 1; + v.y = 2; + ZZshSetParameter4fv(ppsBitBlt[bit_idx].prog, ppsBitBlt[bit_idx].sOneColor, v, "g_fOneColor"); + + assert(ptex != 0); + + if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + if (IsWriteDestAlphaTest()) + { + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_ALWAYS, 0, 0xff); + glStencilMask(0xff); + glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO); + } + + // render with an AA shader if possible (bilinearly interpolates data) + //cgGLLoadProgram(ppsBitBlt[bit_idx].prog); + ZZshSetPixelShader(ppsBitBlt[bit_idx].prog); + } + + ZZshSetVertexShader(pvsBitBlt.prog); + + DrawTriangleArray(); + + // fill stencil buf only + FillOnlyStencilBuffer(); + glEnable(GL_SCISSOR_TEST); + + if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + if (conf.mrtdepth && pdepth != NULL && IsWriteDepth()) pdepth->SetRenderTarget(1); + + status = TS_Resolved; + + // reset since settings changed + vb[0].bVarsTexSync = 0; + +// ResetAlphaVariables(); +} + +void CRenderTarget::ConvertTo32() +{ + FUNCLOG + + u32 ptexConv; +// ZZLog::Error_Log("Convert to 32, report if something missing."); + // create new target + + if (! InitialiseDefaultTexture(&ptexConv, RW(fbw), RH(fbh) / 2)) + { + ZZLog::Error_Log("Failed to create target for ConvertTo32 %dx%d.", RW(fbw), RH(fbh) / 2); + return; + } + + DisableAllgl(); + + SetShaderCaller("CRenderTarget::ConvertTo32"); + + // tex coords, test ffx bikanel island when changing these + float4 v = DefaultBitBltPos(); + v = DefaultBitBltTex(); + + v.x = (float)RW(16); + v.y = (float)RH(16); + v.z = -(float)RW(fbw); + v.w = (float)RH(8); + ZZshSetParameter4fv(ppsConvert16to32.prog, ppsConvert16to32.fTexOffset, v, "g_fTexOffset"); + + v.x = (float)RW(8); + v.y = 0; + v.z = 0; + v.w = 0.25f; + ZZshSetParameter4fv(ppsConvert16to32.prog, ppsConvert16to32.fPageOffset, v, "g_fPageOffset"); + + v.x = (float)RW(2 * fbw); + v.y = (float)RH(fbh); + v.z = 0; + v.w = 0.0001f * (float)RH(fbh); + ZZshSetParameter4fv(ppsConvert16to32.prog, ppsConvert16to32.fTexDims, v, "g_fTexDims"); + +// v.x = 0; +// ZZshSetParameter4fv(ppsConvert16to32.fTexBlock, v, "g_fTexBlock"); + + glBindBuffer(GL_ARRAY_BUFFER, vboRect); + SET_STREAM(); + + // assume depth already set !? + FBTexture(0, ptexConv); + ResetRenderTarget(1); + + BindToSample(&ptex); + ZZshGLSetTextureParameter(ppsConvert16to32.prog, ppsConvert16to32.sFinal, ptex, "Convert 16 to 32.Final"); + + fbh /= 2; // have 16 bit surfaces are usually 2x higher + SetViewport(); + + if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + // render with an AA shader if possible (bilinearly interpolates data) + ZZshSetVertexShader(pvsBitBlt.prog); + ZZshSetPixelShader(ppsConvert16to32.prog); + DrawTriangleArray(); + +#ifdef _DEBUG + if (g_bSaveZUpdate) + { + // buggy + SaveTexture("tex1.tga", GL_TEXTURE_RECTANGLE_NV, ptex, RW(fbw), RH(fbh)*2); + SaveTexture("tex3.tga", GL_TEXTURE_RECTANGLE_NV, ptexConv, RW(fbw), RH(fbh)); + } + +#endif + + vposxy.y = -2.0f * (32767.0f / 8.0f) / (float)fbh; + vposxy.w = 1 + 0.5f / fbh; + + // restore + SAFE_RELEASE_TEX(ptex); + SAFE_RELEASE_TEX(ptexFeedback); + + ptex = ptexConv; + + // no need to free psys since the render target is getting shrunk + if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + // reset textures + BindToSample(&ptex); + + glEnable(GL_SCISSOR_TEST); + + status = TS_Resolved; + + // TODO, reset depth? + if (icurctx >= 0) + { + // reset since settings changed + vb[icurctx].bVarsTexSync = 0; + vb[icurctx].bVarsSetTarg = 0; + } + + vb[0].bVarsTexSync = 0; +} + +void CRenderTarget::ConvertTo16() +{ + FUNCLOG + + u32 ptexConv; + +// ZZLog::Error_Log("Convert to 16, report if something missing."); + // create new target + + if (! InitialiseDefaultTexture(&ptexConv, RW(fbw), RH(fbh)*2)) + { + ZZLog::Error_Log("Failed to create target for ConvertTo16 %dx%d.", RW(fbw), RH(fbh)*2); + return; + } + + DisableAllgl(); + + SetShaderCaller("CRenderTarget::ConvertTo16"); + + // tex coords, test ffx bikanel island when changing these + float4 v = DefaultBitBltPos(); + v = DefaultBitBltTex(); + + v.x = 16.0f / (float)fbw; + v.y = 8.0f / (float)fbh; + v.z = 0.5f * v.x; + v.w = 0.5f * v.y; + ZZshSetParameter4fv(ppsConvert32to16.prog, ppsConvert32to16.fTexOffset, v, "g_fTexOffset"); + + v.x = 256.0f / 255.0f; + v.y = 256.0f / 255.0f; + v.z = 0.05f / 256.0f; + v.w = -0.001f / 256.0f; + ZZshSetParameter4fv(ppsConvert32to16.prog, ppsConvert32to16.fPageOffset, v, "g_fPageOffset"); + + v.x = (float)RW(fbw); + v.y = (float)RH(2 * fbh); + v.z = 0; + v.w = -0.1f / RH(fbh); + ZZshSetParameter4fv(ppsConvert32to16.prog, ppsConvert32to16.fTexDims, v, "g_fTexDims"); + + glBindBuffer(GL_ARRAY_BUFFER, vboRect); + SET_STREAM(); + + // assume depth already set !? + FBTexture(0, ptexConv); + ResetRenderTarget(1); + GL_REPORT_ERRORD(); + + BindToSample(&ptex); + + ZZshGLSetTextureParameter(ppsConvert32to16.prog, ppsConvert32to16.sFinal, ptex, "Convert 32 to 16"); + +// fbh *= 2; // have 16 bit surfaces are usually 2x higher + + SetViewport(); + + if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + // render with an AA shader if possible (bilinearly interpolates data) + ZZshSetVertexShader(pvsBitBlt.prog); + ZZshSetPixelShader(ppsConvert32to16.prog); + DrawTriangleArray(); + +#ifdef _DEBUG + //g_bSaveZUpdate = 1; + if (g_bSaveZUpdate) + { + SaveTexture("tex1.tga", GL_TEXTURE_RECTANGLE_NV, ptexConv, RW(fbw), RH(fbh)); + } + +#endif + + vposxy.y = -2.0f * (32767.0f / 8.0f) / (float)fbh; + vposxy.w = 1 + 0.5f / fbh; + + // restore + SAFE_RELEASE_TEX(ptex); + SAFE_RELEASE_TEX(ptexFeedback); + + ptex = ptexConv; + + _aligned_free(psys); + + psys = _aligned_malloc(Tex_Memory_Size(fbw, fbh), 16); + + if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + // reset textures + BindToSample(&ptex) ; + + glEnable(GL_SCISSOR_TEST); + + status = TS_Resolved; + + // TODO, reset depth? + if (icurctx >= 0) + { + // reset since settings changed + vb[icurctx].bVarsTexSync = 0; + vb[icurctx].bVarsSetTarg = 0; + } + + vb[0].bVarsTexSync = 0; +} + +void CRenderTarget::_CreateFeedback() +{ + FUNCLOG + + if (ptexFeedback == 0) + { + // create + if (! InitialiseDefaultTexture(&ptexFeedback, RW(fbw), RH(fbh))) + { + ZZLog::Error_Log("Failed to create feedback %dx%d.", RW(fbw), RH(fbh)); + return; + } + } + + DisableAllgl(); + + SetShaderCaller("CRenderTarget::_CreateFeedback"); + + // assume depth already set + ResetRenderTarget(1); + + // tex coords, test ffx bikanel island when changing these + /* float4 v = DefaultBitBltPos(); + v = float4 ((float)(RW(fbw+4)), (float)(RH(fbh+4)), +0.25f, -0.25f); + ZZshSetParameter4fv(pvsBitBlt.prog, pvsBitBlt.sBitBltTex, v, "BitBltTex");*/ + + // tex coords, test ffx bikanel island when changing these + +// float4 v = float4(1, -1, 0.5f / (fbw << AA.x), 0.5f / (fbh << AA.y)); +// v *= 1/32767.0f; +// cgGLSetParameter4fv(pvsBitBlt.sBitBltPos, v); + float4 v = DefaultBitBltPos(); + + v.x = (float)(RW(fbw)); + v.y = (float)(RH(fbh)); + v.z = 0.0f; + v.w = 0.0f; + ZZshSetParameter4fv(pvsBitBlt.prog, pvsBitBlt.sBitBltTex, v, "BitBlt.Feedback"); + ZZshDefaultOneColor(ppsBaseTexture); + + glBindBuffer(GL_ARRAY_BUFFER, vboRect); + SET_STREAM(); + + FBTexture(0, ptexFeedback); + glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptex); + GL_REPORT_ERRORD(); + + ZZshGLSetTextureParameter(ppsBaseTexture.prog, ppsBaseTexture.sFinal, ptex, "BaseTexture.Feedback"); + + SetViewport(); + + if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + // render with an AA shader if possible (bilinearly interpolates data) + ZZshSetVertexShader(pvsBitBlt.prog); + ZZshSetPixelShader(ppsBaseTexture.prog); + DrawTriangleArray(); + + // restore + swap(ptex, ptexFeedback); + + if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + glEnable(GL_SCISSOR_TEST); + + status |= TS_FeedbackReady; + + // TODO, reset depth? + if (icurctx >= 0) + { + // reset since settings changed + vb[icurctx].bVarsTexSync = 0; + } + + GL_REPORT_ERRORD(); +} + +void CRenderTarget::SetRenderTarget(int targ) +{ + FUNCLOG + + FBTexture(targ, ptex); + + //GL_REPORT_ERRORD(); + //if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) + //ERROR_LOG_SPAM("The Framebuffer is not complete. Glitches could appear onscreen.\n"); +} + +CDepthTarget::CDepthTarget() : CRenderTarget(), pdepth(0), pstencil(0), icount(0) {} + +CDepthTarget::~CDepthTarget() +{ + FUNCLOG + + Destroy(); +} + +bool CDepthTarget::Create(const frameInfo& frame) +{ + FUNCLOG + + if (!CRenderTarget::Create(frame)) return false; + + GL_REPORT_ERROR(); + + glGenRenderbuffersEXT(1, &pdepth); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, pdepth); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, RW(fbw), RH(fbh)); + + if (glGetError() != GL_NO_ERROR) + { + // try a separate depth and stencil buffer + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, pdepth); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, RW(fbw), RH(fbh)); + + if (g_bUpdateStencil) + { + glGenRenderbuffersEXT(1, &pstencil); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, pstencil); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX8_EXT, RW(fbw), RH(fbh)); + + if (glGetError() != GL_NO_ERROR) + { + ZZLog::Error_Log("Failed to create depth buffer %dx%d.", RW(fbw), RH(fbh)); + return false; + } + } + else + { + pstencil = 0; + } + } + else + { + pstencil = pdepth; + } + + status = TS_NeedUpdate; + + return true; +} + +void CDepthTarget::Destroy() +{ + FUNCLOG + + if (status) // In this case Framebuffer extension is off-use and lead to segfault + { + ResetRenderTarget(1); + TextureRect(GL_DEPTH_ATTACHMENT_EXT); + TextureRect(GL_STENCIL_ATTACHMENT_EXT); + GL_REPORT_ERRORD(); + + if (pstencil != 0) + { + if (pstencil != pdepth) glDeleteRenderbuffersEXT(1, &pstencil); + pstencil = 0; + } + + if (pdepth != 0) + { + glDeleteRenderbuffersEXT(1, &pdepth); + pdepth = 0; + } + + GL_REPORT_ERRORD(); + } + + CRenderTarget::Destroy(); +} + + +extern int g_nDepthUsed; // > 0 if depth is used + +void CDepthTarget::Resolve() +{ + FUNCLOG + + if (g_nDepthUsed > 0 && conf.mrtdepth && !(status&TS_Virtual) && IsWriteDepth() && !(conf.settings().no_depth_resolve)) + CRenderTarget::Resolve(); + else + { + // flush if necessary + FlushIfNecesary(this) ; + + if (!(status & TS_Virtual)) status |= TS_Resolved; + } + + if (!(status&TS_Virtual)) + { + SetWriteDepth(); + } +} + +void CDepthTarget::Resolve(int startrange, int endrange) +{ + FUNCLOG + + if (g_nDepthUsed > 0 && conf.mrtdepth && !(status&TS_Virtual) && IsWriteDepth()) + { + CRenderTarget::Resolve(startrange, endrange); + } + else + { + // flush if necessary + FlushIfNecesary(this) ; + + if (!(status & TS_Virtual)) + status |= TS_Resolved; + } + + if (!(status&TS_Virtual)) + { + SetWriteDepth(); + } +} + +void CDepthTarget::Update(int context, CRenderTarget* prndr) +{ + FUNCLOG + + assert(!(status & TS_Virtual)); + + // align the rect to the nearest page + // note that fbp is always aligned on page boundaries + tex0Info texframe; + texframe.tbp0 = fbp; + texframe.tbw = fbw; + texframe.tw = fbw; + texframe.th = fbh; + texframe.psm = psm; + // FIXME some field are not initialized... + // in particular the clut related one + assert(!PSMT_ISCLUT(psm)); + + DisableAllgl(); + + VB& curvb = vb[context]; + + if (curvb.test.zte == 0) return; + + SetShaderCaller("CDepthTarget::Update"); + + glEnable(GL_DEPTH_TEST); + + glDepthMask(!curvb.zbuf.zmsk); + + static const u32 g_dwZCmp[] = { GL_NEVER, GL_ALWAYS, GL_GEQUAL, GL_GREATER }; + + glDepthFunc(g_dwZCmp[curvb.test.ztst]); + + // write color and zero out stencil buf, always 0 context! + SetTexVariablesInt(0, 0, texframe, false, &ppsBitBltDepth, 1); + ZZshGLSetTextureParameter(ppsBitBltDepth.prog, ppsBitBltDepth.sMemory, vb[0].pmemtarg->ptex->tex, "BitBltDepth"); + + float4 v = DefaultBitBltPos(); + + v = DefaultBitBltTex(); + + v.x = 1; + v.y = 2; + v.z = PSMT_IS16Z(psm) ? 1.0f : 0.0f; + v.w = g_filog32; + ZZshSetParameter4fv(ppsBitBltDepth.prog, ppsBitBltDepth.sOneColor, v, "g_fOneColor"); + + float4 vdepth = g_vdepth; + + if (psm == PSMT24Z) + { + vdepth.w = 0; + } + else if (psm != PSMT32Z) + { + vdepth.z = vdepth.w = 0; + } + + assert(ppsBitBltDepth.sBitBltZ != 0); + + ZZshSetParameter4fv(ppsBitBltDepth.prog, ppsBitBltDepth.sBitBltZ, (vdepth*(255.0f / 256.0f)), "g_fBitBltZ"); + + assert(pdepth != 0); + //GLint w1 = 0; + //GLint h1 = 0; + + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_NV, ptex, 0); + //glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_WIDTH_EXT, &w1); + //glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_HEIGHT_EXT, &h1); + SetDepthStencilSurface(); + + FBTexture(1); + + GLenum buffer = GL_COLOR_ATTACHMENT0_EXT; + + //ZZLog::Error_Log("CDepthTarget::Update: w1 = 0x%x; h1 = 0x%x", w1, h1); + DrawBuffers(&buffer); + + SetViewport(); + + if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + glBindBuffer(GL_ARRAY_BUFFER, vboRect); + + SET_STREAM(); + ZZshSetVertexShader(pvsBitBlt.prog); + ZZshSetPixelShader(ppsBitBltDepth.prog); + + DrawTriangleArray(); + + status = TS_Resolved; + + if (!IsWriteDepth()) + { + ResetRenderTarget(1); + } + + if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + glEnable(GL_SCISSOR_TEST); + +#ifdef _DEBUG + if (g_bSaveZUpdate) + { + SaveTex(&texframe, 1); + SaveTexture("frame1.tga", GL_TEXTURE_RECTANGLE_NV, ptex, RW(fbw), RH(fbh)); + } +#endif +} + +void CDepthTarget::SetDepthStencilSurface() +{ + FUNCLOG + TextureRect(GL_DEPTH_ATTACHMENT_EXT, pdepth); + + if (pstencil) + { + // there's a bug with attaching stencil and depth buffers + TextureRect(GL_STENCIL_ATTACHMENT_EXT, pstencil); + + if (icount++ < 8) // not going to fail if succeeded 4 times + { + GL_REPORT_ERRORD(); + + if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) + { + TextureRect(GL_STENCIL_ATTACHMENT_EXT); + + if (pstencil != pdepth) glDeleteRenderbuffersEXT(1, &pstencil); + + pstencil = 0; + g_bUpdateStencil = 0; + } + } + } + else + { + TextureRect(GL_STENCIL_ATTACHMENT_EXT); + } +} + +void CRenderTargetMngr::Destroy() +{ + FUNCLOG + + for (MAPTARGETS::iterator it = mapTargets.begin(); it != mapTargets.end(); ++it) + { + delete it->second; + } + + mapTargets.clear(); + + for (MAPTARGETS::iterator it = mapDummyTargs.begin(); it != mapDummyTargs.end(); ++it) + { + delete it->second; + } + + mapDummyTargs.clear(); +} + +void CRenderTargetMngr::DestroyAllTargs(int start, int end, int fbw) +{ + FUNCLOG + + for (MAPTARGETS::iterator it = mapTargets.begin(); it != mapTargets.end();) + { + if (it->second->start < end && start < it->second->end) + { + // if is depth, only resolve if fbw is the same + if (!it->second->IsDepth()) + { + // only resolve if the widths are the same or it->second has bit outside the range + // shadow of colossus swaps between fbw=256,fbh=256 and fbw=512,fbh=448. This kills the game if doing || it->second->end > end + + // kh hack, sometimes kh movies do this to clear the target, so have a static count that periodically checks end + static int count = 0; + + if (it->second->fbw == fbw || (it->second->fbw != fbw && (it->second->start < start || ((count++&0xf) ? 0 : it->second->end > end)))) + { + it->second->Resolve(); + } + else + { + FlushIfNecesary(it->second) ; + it->second->status |= CRenderTarget::TS_Resolved; + } + } + else + { + if (it->second->fbw == fbw) + { + it->second->Resolve(); + } + else + { + FlushIfNecesary(it->second) ; + it->second->status |= CRenderTarget::TS_Resolved; + } + } + + DestroyAllTargetsHelper(it->second) ; + + u32 dummykey = GetFrameKeyDummy(it->second); + + if (mapDummyTargs.find(dummykey) == mapDummyTargs.end()) + { + mapDummyTargs[dummykey] = it->second; + } + else + { + delete it->second; + } + + mapTargets.erase(it++); + } + else + { + ++it; + } + } +} + +void CRenderTargetMngr::DestroyTarg(CRenderTarget* ptarg) +{ + FUNCLOG + DestroyAllTargetsHelper(ptarg) ; + delete ptarg; +} + +void CRenderTargetMngr::DestroyIntersecting(CRenderTarget* prndr) +{ + FUNCLOG + assert(prndr != NULL); + + int start, end; + GetRectMemAddress(start, end, prndr->psm, 0, 0, prndr->fbw, prndr->fbh, prndr->fbp, prndr->fbw); + + for (MAPTARGETS::iterator it = mapTargets.begin(); it != mapTargets.end();) + { + if ((it->second != prndr) && (it->second->start < end) && (start < it->second->end)) + { + it->second->Resolve(); + DestroyAllTargetsHelper(it->second) ; + u32 dummykey = GetFrameKeyDummy(it->second); + + if (mapDummyTargs.find(dummykey) == mapDummyTargs.end()) + { + mapDummyTargs[dummykey] = it->second; + } + else + { + delete it->second; + } + + mapTargets.erase(it++); + } + else + { + ++it; + } + } +} + +//-------------------------------------------------- + + +inline bool CheckWidthIsSame(const frameInfo& frame, CRenderTarget* ptarg) +{ + if (PSMT_ISHALF(frame.psm) == PSMT_ISHALF(ptarg->psm)) + return (frame.fbw == ptarg->fbw); + + if (PSMT_ISHALF(frame.psm)) + return (frame.fbw == 2 * ptarg->fbw); + else + return (2 * frame.fbw == ptarg->fbw); +} + +void CRenderTargetMngr::PrintTargets() +{ +#ifdef _DEBUG + for (MAPTARGETS::iterator it1 = mapDummyTargs.begin(); it1 != mapDummyTargs.end(); ++it1) + ZZLog::Debug_Log("\t Dummy Targets(0x%x) fbw:0x%x fbh:0x%x psm:0x%x fbp:0x%x", GetFrameKey(it1->second), it1->second->fbw, it1->second->fbh, it1->second->psm, it1->second->fbp); + + for (MAPTARGETS::iterator it1 = mapTargets.begin(); it1 != mapTargets.end(); ++it1) + ZZLog::Debug_Log("\t Targets(0x%x) fbw:0x%x fbh:0x%x psm:0x%x fbp:0x%x", GetFrameKey(it1->second), it1->second->fbw, it1->second->fbh, it1->second->psm, it1->second->fbp); +#endif +} + +bool CRenderTargetMngr::isFound(const frameInfo& frame, MAPTARGETS::iterator& it, u32 opts, u32 key, int maxposheight) +{ + // only enforce height if frame.fbh <= 0x1c0 + bool bfound = it != mapTargets.end(); + + if (bfound) + { + if (opts&TO_StrictHeight) + { + bfound = it->second->fbh == frame.fbh; + + if ((conf.settings().partial_depth) && !bfound) + { + MAPTARGETS::iterator itnew = mapTargets.find(key + 1); + + if (itnew != mapTargets.end() && itnew->second->fbh == frame.fbh) + { + // found! delete the previous and restore + delete it->second; + mapTargets.erase(it); + + it = mapTargets.insert(MAPTARGETS::value_type(key, itnew->second)).first; // readd + mapTargets.erase(itnew); // delete old + + bfound = true; + } + } + } + else + { + if (PSMT_ISHALF(frame.psm) == PSMT_ISHALF(it->second->psm) && !(conf.settings().full_16_bit_res)) + bfound = ((frame.fbh > 0x1c0) || (it->second->fbh >= frame.fbh)) && (it->second->fbh <= maxposheight); + } + } + + if (!bfound) + { + // might be a virtual target + it = mapTargets.find(key | TARGET_VIRTUAL_KEY); + bfound = it != mapTargets.end() && ((opts & TO_StrictHeight) ? it->second->fbh == frame.fbh : it->second->fbh >= frame.fbh) && it->second->fbh <= maxposheight; + } + + if (bfound && PSMT_ISHALF(frame.psm) && PSMT_ISHALF(it->second->psm) && (conf.settings().full_16_bit_res)) + { + // mgs3 + if (frame.fbh > it->second->fbh) + { + bfound = false; + } + } + + return bfound; +} + +CRenderTarget* CRenderTargetMngr::GetTarg(const frameInfo& frame, u32 opts, int maxposheight) +{ + FUNCLOG + + if (frame.fbw <= 0 || frame.fbh <= 0) + { + //ZZLog::Dev_Log("frame fbw == %d; fbh == %d", frame.fbw, frame.fbh); + return NULL; + } + + GL_REPORT_ERRORD(); + + u32 key = GetFrameKey(frame); + + MAPTARGETS::iterator it = mapTargets.find(key); + + if (isFound(frame, it, opts, key, maxposheight)) + { + // can be both 16bit and 32bit + if (PSMT_ISHALF(frame.psm) != PSMT_ISHALF(it->second->psm)) + { + // a lot of games do this, actually... + ZZLog::Debug_Log("Really bad formats! %d %d", frame.psm, it->second->psm); + +// This code SHOULD be commented, until I redo the _Resolve function + + if (!(opts & TO_StrictHeight)) + { + if ((conf.settings().vss_hack_off)) + { + if (PSMT_ISHALF(it->second->psm)) + { + it->second->status |= CRenderTarget::TS_NeedConvert32; + it->second->fbh /= 2; + } + else + { + it->second->status |= CRenderTarget::TS_NeedConvert16; + it->second->fbh *= 2; + } + } + } + + // recalc extents + GetRectMemAddress(it->second->start, it->second->end, frame.psm, 0, 0, frame.fbw, it->second->fbh, it->second->fbp, frame.fbw); + } + else + { + // certain variables have to be reset every time + if ((it->second->psm & ~1) != (frame.psm & ~1)) + { + ZZLog::Dev_Log("Bad formats 2: %d %d", frame.psm, it->second->psm); + + it->second->psm = frame.psm; + + // recalc extents + GetRectMemAddress(it->second->start, it->second->end, frame.psm, 0, 0, frame.fbw, it->second->fbh, it->second->fbp, frame.fbw); + } + } + + if (it->second->fbm != frame.fbm) + { + //ZZLog::Dev_Log("Bad fbm: 0x%8.8x 0x%8.8x, psm: %d", frame.fbm, it->second->fbm, frame.psm); + } + + it->second->fbm &= frame.fbm; + it->second->psm = frame.psm; // have to convert (ffx2) + + if ((it->first & TARGET_VIRTUAL_KEY) && !(opts&TO_Virtual)) + { + // switch + it->second->lastused = timeGetTime(); + return Promote(it->first&~TARGET_VIRTUAL_KEY); + } + + // check if there exists a more recent target that this target could update from + // only update if target isn't mirrored + bool bCheckHalfCovering = (conf.settings().full_16_bit_res) && PSMT_ISHALF(it->second->psm) && it->second->fbh + 32 < frame.fbh; + + for (MAPTARGETS::iterator itnew = mapTargets.begin(); itnew != mapTargets.end(); ++itnew) + { + if (itnew->second != it->second && itnew->second->ptex != it->second->ptex && itnew->second->ptexFeedback != it->second->ptex && + itnew->second->lastused > it->second->lastused && !(itnew->second->status & CRenderTarget::TS_NeedUpdate)) + { + + // if new target totally encompasses the current one + if (itnew->second->start <= it->second->start && itnew->second->end >= it->second->end) + { + it->second->status |= CRenderTarget::TS_NeedUpdate; + it->second->nUpdateTarg = itnew->first; + break; + } + + // if 16bit, then check for half encompassing targets + if (bCheckHalfCovering && itnew->second->start > it->second->start && itnew->second->start < it->second->end && itnew->second->end <= it->second->end + 0x2000) + { + it->second->status |= CRenderTarget::TS_NeedUpdate; + it->second->nUpdateTarg = itnew->first; + break; + } + } + } + + it->second->lastused = timeGetTime(); + + return it->second; + } + + // NOTE: instead of resolving, if current render targ is completely outside of old, can transfer + // the data like that. + + // first search for the target + CRenderTarget* ptarg = NULL; + + // have to change, so recreate (find all intersecting targets and Resolve) + u32 besttarg = 0; + + if (!(opts & CRenderTargetMngr::TO_Virtual)) + { + + int start, end; + GetRectMemAddress(start, end, frame.psm, 0, 0, frame.fbw, frame.fbh, frame.fbp, frame.fbw); + CRenderTarget* pbesttarg = NULL; + + if (besttarg == 0) + { + // if there is only one intersecting target and it encompasses the current one, update the new render target with + // its data instead of resolving then updating (ffx2). Do not change the original target. + for (MAPTARGETS::iterator it = mapTargets.begin(); it != mapTargets.end(); ++it) + { + if (it->second->start < end && start < it->second->end) + { + if ((conf.settings().fast_update) || + ((frame.fbw == it->second->fbw) && + // check depth targets only if partialdepth option + ((it->second->fbp != frame.fbp) || ((conf.settings().partial_depth) && (opts & CRenderTargetMngr::TO_DepthBuffer))))) + { + if (besttarg != 0) + { + besttarg = 0; + break; + } + + if (start >= it->second->start && end <= it->second->end) + { + besttarg = it->first; + pbesttarg = it->second; + } + } + } + } + } + + if (besttarg != 0 && pbesttarg->fbw != frame.fbw) + { + //ZZLog::Debug_Log("A %d %d %d %d\n", frame.psm, frame.fbw, pbesttarg->psm, pbesttarg->fbw); + + vb[0].frame.fbw = pbesttarg->fbw; + // Something should be here, but what? + } + + if (besttarg == 0) + { + // if none found, resolve all + DestroyAllTargs(start, end, frame.fbw); + } + else if (key == besttarg && pbesttarg != NULL) + { + // add one and store in a different location until best targ is processed + mapTargets.erase(besttarg); + besttarg++; + mapTargets[besttarg] = pbesttarg; + } + } + + if (mapTargets.size() > 8) + { + // release some resources + it = GetOldestTarg(mapTargets); + + // if more than 5s passed since target used, destroy + + if ((it->second != vb[0].prndr) && (it->second != vb[1].prndr) && + (it->second != vb[0].pdepth) && (it->second != vb[1].pdepth) && + ((timeGetTime() - it->second->lastused) > 5000)) + { + delete it->second; + mapTargets.erase(it); + } + } + + if (ptarg == NULL) + { + // not found yet, so create + + if (mapDummyTargs.size() > 8) + { + it = GetOldestTarg(mapDummyTargs); + + delete it->second; + mapDummyTargs.erase(it); + } + + it = mapDummyTargs.find(GetFrameKeyDummy(frame)); + + if (it != mapDummyTargs.end()) + { + ZZLog::Debug_Log("Dummy Frame fbw:0x%x fbh:0x%x psm:0x%x fbp:0x%x", frame.fbw, frame.fbh, frame.psm, frame.fbp); + PrintTargets(); + ZZLog::Debug_Log("Dummy it->second fbw:0x%x fbh:0x%x psm:0x%x fbp:0x%x", it->second->fbw, it->second->fbh, it->second->psm, it->second->fbp); + ptarg = it->second; + + mapDummyTargs.erase(it); + + // restore all setttings + ptarg->psm = frame.psm; + ptarg->fbm = frame.fbm; + ptarg->fbp = frame.fbp; + + GetRectMemAddress(ptarg->start, ptarg->end, frame.psm, 0, 0, frame.fbw, frame.fbh, frame.fbp, frame.fbw); + + ptarg->status = CRenderTarget::TS_NeedUpdate; + } + else + { + ZZLog::Debug_Log("Frame fbw:0x%x fbh:0x%x psm:0x%x fbp:0x%x", frame.fbw, frame.fbh, frame.psm, frame.fbp); + PrintTargets(); + // create anew + ptarg = (opts & TO_DepthBuffer) ? new CDepthTarget : new CRenderTarget; + CRenderTargetMngr* pmngrs[2] = { &s_DepthRTs, this == &s_RTs ? &s_RTs : NULL }; + int cur = 0; + + while (!ptarg->Create(frame)) + { + // destroy unused targets + if (mapDummyTargs.size() > 0) + { + it = mapDummyTargs.begin(); + delete it->second; + mapDummyTargs.erase(it); + continue; + } + + if (g_MemTargs.listClearedTargets.size() > 0) + { + g_MemTargs.DestroyCleared(); + continue; + } + else if (g_MemTargs.listTargets.size() > 32) + { + g_MemTargs.DestroyOldest(); + continue; + } + + if (pmngrs[cur] == NULL) + { + cur = !cur; + + if (pmngrs[cur] == NULL) + { + ZZLog::Warn_Log("Out of memory!"); + delete ptarg; + return NULL; + } + } + + if (pmngrs[cur]->mapTargets.size() == 0) + { + pmngrs[cur] = NULL; + cur = !cur; + continue; + } + + it = GetOldestTarg(pmngrs[cur]->mapTargets); + + DestroyTarg(it->second); + pmngrs[cur]->mapTargets.erase(it); + cur = !cur; + } + } + } + + if ((opts & CRenderTargetMngr::TO_Virtual)) + { + ptarg->status = CRenderTarget::TS_Virtual; + key |= TARGET_VIRTUAL_KEY; + + if ((it = mapTargets.find(key)) != mapTargets.end()) + { + + DestroyTarg(it->second); + it->second = ptarg; + ptarg->nUpdateTarg = besttarg; + return ptarg; + } + } + else + { + assert(mapTargets.find(key) == mapTargets.end()); + } + + ptarg->nUpdateTarg = besttarg; + + mapTargets[key] = ptarg; + + return ptarg; +} + +CRenderTargetMngr::MAPTARGETS::iterator CRenderTargetMngr::GetOldestTarg(MAPTARGETS& m) +{ + FUNCLOG + + if (m.size() == 0) + { + return m.end(); + } + + // release some resources + MAPTARGETS::iterator itmaxtarg = m.begin(); + + for (MAPTARGETS::iterator it = ++m.begin(); it != m.end(); ++it) + { + if (itmaxtarg->second->lastused < it->second->lastused) itmaxtarg = it; + } + + return itmaxtarg; +} + +void CRenderTargetMngr::GetTargs(int start, int end, list& listTargets) const +{ + FUNCLOG + + for (MAPTARGETS::const_iterator it = mapTargets.begin(); it != mapTargets.end(); ++it) + { + if ((it->second->start < end) && (start < it->second->end)) listTargets.push_back(it->second); + } +} + +void CRenderTargetMngr::Resolve(int start, int end) +{ + FUNCLOG + + for (MAPTARGETS::const_iterator it = mapTargets.begin(); it != mapTargets.end(); ++it) + { + if ((it->second->start < end) && (start < it->second->end)) + it->second->Resolve(); + } +} + +void CMemoryTargetMngr::Destroy() +{ + FUNCLOG + listTargets.clear(); + listClearedTargets.clear(); +} + +bool CMemoryTarget::ValidateTex(const tex0Info& tex0, int starttex, int endtex, bool bDeleteBadTex) +{ + FUNCLOG + + if (clearmaxy == 0) return true; + + int checkstarty = max(starttex, clearminy); + int checkendy = min(endtex, clearmaxy); + + if (checkstarty >= checkendy) return true; + + if (validatecount++ > VALIDATE_THRESH) + { + height = 0; + return false; + } + + // lock and compare + assert(ptex != NULL && ptex->memptr != NULL); + + int result = memcmp_mmx(ptex->memptr + MemorySize(checkstarty-realy), MemoryAddress(checkstarty), MemorySize(checkendy-checkstarty)); + + if (result == 0) + { + clearmaxy = 0; + return true; + } + + if (!bDeleteBadTex) return false; + + // delete clearminy, clearmaxy range (not the checkstarty, checkendy range) + //int newstarty = 0; + if (clearminy <= starty) + { + if (clearmaxy < starty + height) + { + // preserve end + height = starty + height - clearmaxy; + starty = clearmaxy; + assert(height > 0); + } + else + { + // destroy + height = 0; + } + } + else + { + // beginning can be preserved + height = clearminy - starty; + } + + clearmaxy = 0; + + assert((starty >= realy) && ((starty + height) <= (realy + realheight))); + + return false; +} + +#define TARGET_THRESH 0x500 + +extern int g_MaxTexWidth, g_MaxTexHeight; // Maximum height & width of supported texture. + +//#define SORT_TARGETS +inline list::iterator CMemoryTargetMngr::DestroyTargetIter(list::iterator& it) +{ + // find the target and destroy + list::iterator itprev = it; + ++it; + listClearedTargets.splice(listClearedTargets.end(), listTargets, itprev); + + if (listClearedTargets.size() > TEXDESTROY_THRESH) + { + listClearedTargets.pop_front(); + } + + return it; +} + +// Compare target to current texture info +// Not same format -> 1 +// Same format, not same data (clut only) -> 2 +// identical -> 0 +int CMemoryTargetMngr::CompareTarget(list::iterator& it, const tex0Info& tex0, int clutsize) +{ + if (PSMT_ISCLUT(it->psm) != PSMT_ISCLUT(tex0.psm)) + return 1; + + if (PSMT_ISCLUT(tex0.psm)) { + if (it->psm != tex0.psm || it->cpsm != tex0.cpsm || it->clutsize != clutsize) + return 1; + + if (PSMT_IS32BIT(tex0.cpsm)) { + if (Cmp_ClutBuffer_SavedClut((u32*)&it->clut[0], tex0.csa, clutsize)) + return 2; + } else { + if (Cmp_ClutBuffer_SavedClut((u16*)&it->clut[0], tex0.csa, clutsize)) + return 2; + } + + } else { + if (PSMT_IS16BIT(tex0.psm) != PSMT_IS16BIT(it->psm)) + return 1; + } + + return 0; +} + +void CMemoryTargetMngr::GetClutVariables(int& clutsize, const tex0Info& tex0) +{ + clutsize = 0; + + if (PSMT_ISCLUT(tex0.psm)) + { + int entries = PSMT_IS8CLUT(tex0.psm) ? 256 : 16; + + if (PSMT_IS32BIT(tex0.cpsm)) + clutsize = min(entries, 256 - tex0.csa * 16) * 4; + else + clutsize = min(entries, 512 - tex0.csa * 16) * 2; + } +} + +void CMemoryTargetMngr::GetMemAddress(int& start, int& end, const tex0Info& tex0) +{ + int nbStart, nbEnd; + GetRectMemAddress(nbStart, nbEnd, tex0.psm, 0, 0, tex0.tw, tex0.th, tex0.tbp0, tex0.tbw); + assert(nbStart < nbEnd); + nbEnd = min(nbEnd, MEMORY_END); + + start = nbStart / (4 * GPU_TEXWIDTH); + end = (nbEnd + GPU_TEXWIDTH * 4 - 1) / (4 * GPU_TEXWIDTH); + assert(start < end); + +} + +CMemoryTarget* CMemoryTargetMngr::SearchExistTarget(int start, int end, int clutsize, const tex0Info& tex0, int forcevalidate) +{ + for (list::iterator it = listTargets.begin(); it != listTargets.end();) + { + + if (it->starty <= start && it->starty + it->height >= end) + { + + int res = CompareTarget(it, tex0, clutsize); + + if (res == 1) + { + if (it->validatecount++ > VALIDATE_THRESH) + { + it = DestroyTargetIter(it); + + if (listTargets.size() == 0) break; + } + else + ++it; + + continue; + } + else if (res == 2) + { + ++it; + continue; + } + + if (forcevalidate) //&& listTargets.size() < TARGET_THRESH ) { + { + // do more validation checking. delete if not been used for a while + + if (!it->ValidateTex(tex0, start, end, curstamp > it->usedstamp + FORCE_TEXDESTROY_THRESH)) + { + + if (it->height <= 0) + { + it = DestroyTargetIter(it); + + if (listTargets.size() == 0) break; + } + else + ++it; + + continue; + } + } + + it->usedstamp = curstamp; + + it->validatecount = 0; + + return &(*it); + } + +#ifdef SORT_TARGETS + else if (it->starty >= end) break; + +#endif + + ++it; + } + + return NULL; +} + +CMemoryTarget* CMemoryTargetMngr::ClearedTargetsSearch(int fmt, int widthmult, int channels, int height) +{ + CMemoryTarget* targ = NULL; + + if (listClearedTargets.size() > 0) + { + list::iterator itbest = listClearedTargets.begin(); + + while (itbest != listClearedTargets.end()) + { + if ((height == itbest->realheight) && (itbest->fmt == fmt) && (itbest->widthmult == widthmult) && (itbest->channels == channels)) + { + // check channels + if (PIXELS_PER_WORD(itbest->psm) == channels) break; + } + + ++itbest; + } + + if (itbest != listClearedTargets.end()) + { + listTargets.splice(listTargets.end(), listClearedTargets, itbest); + targ = &listTargets.back(); + targ->validatecount = 0; + } + else + { + // create a new + listTargets.push_back(CMemoryTarget()); + targ = &listTargets.back(); + } + } + else + { + listTargets.push_back(CMemoryTarget()); + targ = &listTargets.back(); + } + + return targ; +} + +CMemoryTarget* CMemoryTargetMngr::GetMemoryTarget(const tex0Info& tex0, int forcevalidate) +{ + FUNCLOG + int start, end, clutsize; + + GetClutVariables(clutsize, tex0); + GetMemAddress(start, end, tex0); + + CMemoryTarget* it = SearchExistTarget(start, end, clutsize, tex0, forcevalidate); + + if (it != NULL) return it; + + // couldn't find so create + CMemoryTarget* targ; + + u32 fmt; + u32 internal_fmt; + if (PSMT_ISHALF_STORAGE(tex0)) { + // RGBA_5551 storage format + fmt = GL_UNSIGNED_SHORT_1_5_5_5_REV; + internal_fmt = GL_RGB5_A1; + } else { + // RGBA_8888 storage format + fmt = GL_UNSIGNED_BYTE; + internal_fmt = GL_RGBA; + } + + int widthmult = 1, channels = 1; + + // If our texture is too big and could not be placed in 1 GPU texture. Pretty rare in modern cards. + if ((g_MaxTexHeight < 4096) && (end - start > g_MaxTexHeight)) + { + // In this rare case we made a texture of half height and place it on the screen. + ZZLog::Debug_Log("Making a half height texture (start - end == 0x%x)", (end-start)); + widthmult = 2; + } + + channels = PIXELS_PER_WORD(tex0.psm); + + targ = ClearedTargetsSearch(fmt, widthmult, channels, end - start); + + if (targ->ptex != NULL) + { + assert(end - start <= targ->realheight && targ->fmt == fmt && targ->widthmult == widthmult); + + // good enough, so init + targ->realy = targ->starty = start; + targ->usedstamp = curstamp; + targ->psm = tex0.psm; + targ->cpsm = tex0.cpsm; + targ->height = end - start; + } else { + // not initialized yet + targ->fmt = fmt; + targ->realy = targ->starty = start; + targ->realheight = targ->height = end - start; + targ->usedstamp = curstamp; + targ->psm = tex0.psm; + targ->cpsm = tex0.cpsm; + targ->widthmult = widthmult; + targ->channels = channels; + targ->texH = (targ->realheight + widthmult - 1)/widthmult; + targ->texW = GPU_TEXWIDTH * widthmult * channels; + + // alloc the mem + targ->ptex = new CMemoryTarget::TEXTURE(); + targ->ptex->ref = 1; + } + +#if defined(ZEROGS_DEVBUILD) + g_TransferredToGPU += MemorySize(channels * targ->height); +#endif + + // fill with data + if (targ->ptex->memptr == NULL) + { + targ->ptex->memptr = (u8*)_aligned_malloc(MemorySize(targ->realheight), 16); + assert(targ->ptex->ref > 0); + } + + memcpy_amd(targ->ptex->memptr, MemoryAddress(targ->realy), MemorySize(targ->height)); + + __aligned16 u8* ptexdata = NULL; + bool has_data = false; + + if (PSMT_ISCLUT(tex0.psm)) + { + assert(clutsize > 0); + + // Local clut parameter + targ->cpsm = tex0.cpsm; + + // Allocate a local clut array + targ->clutsize = clutsize; + if(targ->clut == NULL) + targ->clut = (u8*)_aligned_malloc(clutsize, 16); + else { + // In case it could occured + // realloc would be better but you need to get it from libutilies first + // _aligned_realloc is brought in from ScopedAlloc.h now. --arcum42 + _aligned_free(targ->clut); + targ->clut = (u8*)_aligned_malloc(clutsize, 16); + } + + // texture parameter + ptexdata = (u8*)_aligned_malloc(CLUT_PIXEL_SIZE(tex0.cpsm) * targ->texH * targ->texW, 16); + has_data = true; + + u8* psrc = (u8*)(MemoryAddress(targ->realy)); + + // Fill a local clut then build the real texture + if (PSMT_IS32BIT(tex0.cpsm)) + { + ClutBuffer_to_Array((u32*)targ->clut, tex0.csa, clutsize); + Build_Clut_Texture(tex0.psm, targ->height, (u32*)targ->clut, psrc, (u32*)ptexdata); + } + else + { + ClutBuffer_to_Array((u16*)targ->clut, tex0.csa, clutsize); + Build_Clut_Texture(tex0.psm, targ->height, (u16*)targ->clut, psrc, (u16*)ptexdata); + } + + assert(targ->clutsize > 0); + } + else if (tex0.psm == PSMT16Z || tex0.psm == PSMT16SZ) + { + ptexdata = (u8*)_aligned_malloc(4 * targ->texH * targ->texW, 16); + has_data = true; + + // needs to be 8 bit, use xmm for unpacking + u16* dst = (u16*)ptexdata; + u16* src = (u16*)(MemoryAddress(targ->realy)); + +#ifdef ZEROGS_SSE2 + assert(((u32)(uptr)dst) % 16 == 0); + // FIXME Uncomment to test intrinsic versions (instead of asm) + // perf improvement vs asm: + // 1/ gcc updates both pointer with 1 addition + // 2/ Bypass the cache for the store +#define NEW_INTRINSIC_VERSION +#ifdef NEW_INTRINSIC_VERSION + + __m128i zero_128 = _mm_setzero_si128(); + // NOTE: future performance improvement + // SSE4.1 support uncacheable load 128bits. Maybe it can + // avoid some cache pollution + // NOTE2: I create multiple _n variable to mimic the previous ASM behavior + // but I'm not sure there are real gains. + for (int i = targ->height * GPU_TEXWIDTH/16 ; i > 0 ; --i) + { + // Convert 16 bits pixels to 32bits (zero extended) + // Batch 64 bytes (32 pixels) at once. + __m128i pixels_1 = _mm_load_si128((__m128i*)src); + __m128i pixels_2 = _mm_load_si128((__m128i*)(src+8)); + __m128i pixels_3 = _mm_load_si128((__m128i*)(src+16)); + __m128i pixels_4 = _mm_load_si128((__m128i*)(src+24)); + + __m128i pix_low_1 = _mm_unpacklo_epi16(pixels_1, zero_128); + __m128i pix_high_1 = _mm_unpackhi_epi16(pixels_1, zero_128); + __m128i pix_low_2 = _mm_unpacklo_epi16(pixels_2, zero_128); + __m128i pix_high_2 = _mm_unpackhi_epi16(pixels_2, zero_128); + + // Note: bypass cache + _mm_stream_si128((__m128i*)dst, pix_low_1); + _mm_stream_si128((__m128i*)(dst+8), pix_high_1); + _mm_stream_si128((__m128i*)(dst+16), pix_low_2); + _mm_stream_si128((__m128i*)(dst+24), pix_high_2); + + __m128i pix_low_3 = _mm_unpacklo_epi16(pixels_3, zero_128); + __m128i pix_high_3 = _mm_unpackhi_epi16(pixels_3, zero_128); + __m128i pix_low_4 = _mm_unpacklo_epi16(pixels_4, zero_128); + __m128i pix_high_4 = _mm_unpackhi_epi16(pixels_4, zero_128); + + // Note: bypass cache + _mm_stream_si128((__m128i*)(dst+32), pix_low_3); + _mm_stream_si128((__m128i*)(dst+40), pix_high_3); + _mm_stream_si128((__m128i*)(dst+48), pix_low_4); + _mm_stream_si128((__m128i*)(dst+56), pix_high_4); + + src += 32; + dst += 64; + } + // It is advise to use a fence instruction after non temporal move (mm_stream) instruction... + // store fence insures that previous store are finish before execute new one. + _mm_sfence(); +#else + SSE2_UnswizzleZ16Target(dst, src, targ->height * GPU_TEXWIDTH / 16); +#endif +#else // ZEROGS_SSE2 + + for (int i = 0; i < targ->height; ++i) + { + for (int j = 0; j < GPU_TEXWIDTH; ++j) + { + dst[0] = src[0]; + dst[1] = 0; + dst[2] = src[1]; + dst[3] = 0; + dst += 4; + src += 2; + } + } + +#endif // ZEROGS_SSE2 + } + else + { + ptexdata = targ->ptex->memptr; + // We really don't want to deallocate memptr. As a reminder... + has_data = false; + } + + // create the texture + GL_REPORT_ERRORD(); + + assert(ptexdata != NULL); + + if (targ->ptex->tex == 0) glGenTextures(1, &targ->ptex->tex); + + glBindTexture(GL_TEXTURE_RECTANGLE_NV, targ->ptex->tex); + + TextureRect(internal_fmt, targ->texW, targ->texH, GL_RGBA, fmt, ptexdata); + + while (glGetError() != GL_NO_ERROR) + { + // release resources until can create + if (listClearedTargets.size() > 0) + { + listClearedTargets.pop_front(); + } + else + { + if (listTargets.size() == 0) + { + ZZLog::Error_Log("Failed to create %dx%x texture.", targ->texW, targ->texH); + channels = 1; + if (has_data) _aligned_free(ptexdata); + return NULL; + } + + DestroyOldest(); + } + + TextureRect(internal_fmt, targ->texW, targ->texH, GL_RGBA, fmt, ptexdata); + } + + setRectWrap(GL_CLAMP); + if (has_data) _aligned_free(ptexdata); + + assert(tex0.psm != 0xd); + + return targ; +} + +void CMemoryTargetMngr::ClearRange(int nbStartY, int nbEndY) +{ + FUNCLOG + int starty = nbStartY / (4 * GPU_TEXWIDTH); + int endy = (nbEndY + 4 * GPU_TEXWIDTH - 1) / (4 * GPU_TEXWIDTH); + //int endy = (nbEndY+4096-1) / 4096; + + //if( listTargets.size() < TARGET_THRESH ) { + + for (list::iterator it = listTargets.begin(); it != listTargets.end();) + { + + if (it->starty < endy && (it->starty + it->height) > starty) + { + + // intersects, reduce valid texture mem (or totally delete texture) + // there are 4 cases + int miny = max(it->starty, starty); + int maxy = min(it->starty + it->height, endy); + assert(miny < maxy); + + if (it->clearmaxy == 0) + { + it->clearminy = miny; + it->clearmaxy = maxy; + } + else + { + if (it->clearminy > miny) it->clearminy = miny; + if (it->clearmaxy < maxy) it->clearmaxy = maxy; + } + } + + ++it; + } + +// } +// else { +// for(list::iterator it = listTargets.begin(); it != listTargets.end(); ) { +// +// if( it->starty < endy && (it->starty+it->height) > starty ) { +// int newstarty = 0; +// if( starty <= it->starty ) { +// if( endy < it->starty + it->height) { +// // preserve end +// it->height = it->starty+it->height-endy; +// it->starty = endy; +// assert(it->height > 0); +// } +// else { +// // destroy +// it->height = 0; +// } +// } +// else { +// // beginning can be preserved +// it->height = starty-it->starty; +// } +// +// assert( it->starty >= it->realy && it->starty+it->height<=it->realy+it->realheight ); +// if( it->height <= 0 ) { +// list::iterator itprev = it; ++it; +// listClearedTargets.splice(listClearedTargets.end(), listTargets, itprev); +// continue; +// } +// } +// +// ++it; +// } +// } +} + +void CMemoryTargetMngr::DestroyCleared() +{ + FUNCLOG + + for (list::iterator it = listClearedTargets.begin(); it != listClearedTargets.end();) + { + if (it->usedstamp < curstamp - (FORCE_TEXDESTROY_THRESH -1)) + { + it = listClearedTargets.erase(it); + continue; + } + + ++it; + } + + if ((curstamp % FORCE_TEXDESTROY_THRESH) == 0) + { + // purge old targets every FORCE_TEXDESTROY_THRESH frames + for (list::iterator it = listTargets.begin(); it != listTargets.end();) + { + if (it->usedstamp < curstamp - FORCE_TEXDESTROY_THRESH) + { + it = listTargets.erase(it); + continue; + } + + ++it; + } + } + + ++curstamp; +} + +void CMemoryTargetMngr::DestroyOldest() +{ + FUNCLOG + + if (listTargets.size() == 0) + return; + + list::iterator it, itbest; + + it = itbest = listTargets.begin(); + + while (it != listTargets.end()) + { + if (it->usedstamp < itbest->usedstamp) itbest = it; + ++it; + } + + listTargets.erase(itbest); +} + +////////////////////////////////////// +// Texture Mngr For Bitwise AND Ops // +////////////////////////////////////// +void CBitwiseTextureMngr::Destroy() +{ + FUNCLOG + + for (map::iterator it = mapTextures.begin(); it != mapTextures.end(); ++it) + { + glDeleteTextures(1, &it->second); + } + + mapTextures.clear(); +} + +u32 CBitwiseTextureMngr::GetTexInt(u32 bitvalue, u32 ptexDoNotDelete) +{ + FUNCLOG + + if (mapTextures.size() > 32) + { + // randomly delete 8 + for (map::iterator it = mapTextures.begin(); it != mapTextures.end();) + { + if (!(rand()&3) && it->second != ptexDoNotDelete) + { + glDeleteTextures(1, &it->second); + mapTextures.erase(it++); + } + else + { + ++it; + } + } + } + + if (glGetError() != GL_NO_ERROR) ZZLog::Error_Log("Error before creation of bitmask texture."); + + // create a new tex + u32 ptex; + + glGenTextures(1, &ptex); + + if (glGetError() != GL_NO_ERROR) ZZLog::Error_Log("Error on generation of bitmask texture."); + + vector data(GPU_TEXMASKWIDTH); + + for (u32 i = 0; i < GPU_TEXMASKWIDTH; ++i) + { + data[i] = (((i << MASKDIVISOR) & bitvalue) << 6); // add the 1/2 offset so that + } + + // data[GPU_TEXMASKWIDTH] = 0; // I remove GPU_TEXMASKWIDTH+1 element of this texture, because it was a reason of FFC crush + // Probably, some sort of PoT incompability in drivers. + + glBindTexture(GL_TEXTURE_RECTANGLE, ptex); + if (glGetError() != GL_NO_ERROR) ZZLog::Error_Log("Error on binding bitmask texture."); + + TextureRect2(GL_LUMINANCE16, GPU_TEXMASKWIDTH, 1, GL_LUMINANCE, GL_UNSIGNED_SHORT, &data[0]); + if (glGetError() != GL_NO_ERROR) ZZLog::Error_Log("Error on applying bitmask texture."); + +// Removing clamping, as it seems lead to numerous troubles at some drivers +// Need to observe, may be clamping is not really needed. + /* setRectWrap2(GL_REPEAT); + + GLint Error = glGetError(); + if( Error != GL_NO_ERROR ) { + ERROR_LOG_SPAM_TEST("Failed to create bitmask texture; \t"); + if (SPAM_PASS) { + ZZLog::Log("bitmask cache %d; \t", mapTextures.size()); + switch (Error) { + case GL_INVALID_ENUM: ZZLog::Error_Log("Invalid enumerator.") ; break; + case GL_INVALID_VALUE: ZZLog::Error_Log("Invalid value."); break; + case GL_INVALID_OPERATION: ZZLog::Error_Log("Invalid operation."); break; + default: ZZLog::Error_Log("Error number: %d.", Error); + } + } + return 0; + }*/ + + mapTextures[bitvalue] = ptex; + + return ptex; +} + +void CRangeManager::RangeSanityCheck() +{ +#ifdef _DEBUG + // sanity check + + for (int i = 0; i < (int)ranges.size() - 1; ++i) + { + assert(ranges[i].end < ranges[i+1].start); + } + +#endif +} + +void CRangeManager::Insert(int start, int end) +{ + FUNCLOG + int imin = 0, imax = (int)ranges.size(), imid; + + RangeSanityCheck(); + + switch (ranges.size()) + { + + case 0: + ranges.push_back(RANGE(start, end)); + return; + + case 1: + if (end < ranges.front().start) + { + ranges.insert(ranges.begin(), RANGE(start, end)); + } + else if (start > ranges.front().end) + { + ranges.push_back(RANGE(start, end)); + } + else + { + if (start < ranges.front().start) ranges.front().start = start; + if (end > ranges.front().end) ranges.front().end = end; + } + + return; + } + + // find where start is + while (imin < imax) + { + imid = (imin + imax) >> 1; + + assert(imid < (int)ranges.size()); + + if ((ranges[imid].end >= start) && ((imid == 0) || (ranges[imid-1].end < start))) + { + imin = imid; + break; + } + else if (ranges[imid].start > start) + { + imax = imid; + } + else + { + imin = imid + 1; + } + } + + int startindex = imin; + + if (startindex >= (int)ranges.size()) + { + // non intersecting + assert(start > ranges.back().end); + ranges.push_back(RANGE(start, end)); + return; + } + + if (startindex == 0 && end < ranges.front().start) + { + ranges.insert(ranges.begin(), RANGE(start, end)); + RangeSanityCheck(); + return; + } + + imin = 0; + imax = (int)ranges.size(); + + // find where end is + + while (imin < imax) + { + imid = (imin + imax) >> 1; + + assert(imid < (int)ranges.size()); + + if ((ranges[imid].end <= end) && ((imid == ranges.size() - 1) || (ranges[imid+1].start > end))) + { + imin = imid; + break; + } + else if (ranges[imid].start >= end) + { + imax = imid; + } + else + { + imin = imid + 1; + } + } + + int endindex = imin; + + if (startindex > endindex) + { + // create a new range + ranges.insert(ranges.begin() + startindex, RANGE(start, end)); + RangeSanityCheck(); + return; + } + + if (endindex >= (int)ranges.size() - 1) + { + // pop until startindex is reached + int lastend = ranges.back().end; + int numpop = (int)ranges.size() - startindex - 1; + + while (numpop-- > 0) + { + ranges.pop_back(); + } + + assert(start <= ranges.back().end); + + if (start < ranges.back().start) ranges.back().start = start; + if (lastend > ranges.back().end) ranges.back().end = lastend; + if (end > ranges.back().end) ranges.back().end = end; + + RangeSanityCheck(); + + return; + } + + if (endindex == 0) + { + assert(end >= ranges.front().start); + + if (start < ranges.front().start) ranges.front().start = start; + if (end > ranges.front().end) ranges.front().end = end; + + RangeSanityCheck(); + } + + // somewhere in the middle + if (ranges[startindex].start < start) start = ranges[startindex].start; + + if (startindex < endindex) + { + ranges.erase(ranges.begin() + startindex, ranges.begin() + endindex); + } + + if (start < ranges[startindex].start) ranges[startindex].start = start; + if (end > ranges[startindex].end) ranges[startindex].end = end; + + RangeSanityCheck(); +} + +CRangeManager s_RangeMngr; // manages overwritten memory + +void ResolveInRange(int start, int end) +{ + FUNCLOG + list listTargs = CreateTargetsList(start, end); + /* s_DepthRTs.GetTargs(start, end, listTargs); + s_RTs.GetTargs(start, end, listTargs);*/ + + if (listTargs.size() > 0) + { + FlushBoth(); + + // We need another list, because old one could be brocken by Flush(). + listTargs.clear(); + listTargs = CreateTargetsList(start, end); + /* s_DepthRTs.GetTargs(start, end, listTargs_1); + s_RTs.GetTargs(start, end, listTargs_1);*/ + + for (list::iterator it = listTargs.begin(); it != listTargs.end(); ++it) + { + // only resolve if not completely covered + if ((*it)->created == 123) + (*it)->Resolve(); + else + ZZLog::Debug_Log("Resolving non-existing object! Destroy code %d.", (*it)->created); + } + } +} + +////////////////// +// Transferring // +////////////////// +void FlushTransferRanges(const tex0Info* ptex) +{ + FUNCLOG + assert(s_RangeMngr.ranges.size() > 0); + //bool bHasFlushed = false; + list listTransmissionUpdateTargs; + + int texstart = -1, texend = -1; + + if (ptex != NULL) + { + GetRectMemAddress(texstart, texend, ptex->psm, 0, 0, ptex->tw, ptex->th, ptex->tbp0, ptex->tbw); + } + + for (vector::iterator itrange = s_RangeMngr.ranges.begin(); itrange != s_RangeMngr.ranges.end(); ++itrange) + { + + int start = itrange->start; + int end = itrange->end; + + listTransmissionUpdateTargs.clear(); + listTransmissionUpdateTargs = CreateTargetsList(start, end); + + /* s_DepthRTs.GetTargs(start, end, listTransmissionUpdateTargs); + s_RTs.GetTargs(start, end, listTransmissionUpdateTargs);*/ + +// if( !bHasFlushed && listTransmissionUpdateTargs.size() > 0 ) { +// FlushBoth(); +// +//#ifdef _DEBUG +// // make sure targets are still the same +// list::iterator it; +// FORIT(it, listTransmissionUpdateTargs) { +// CRenderTargetMngr::MAPTARGETS::iterator itmap; +// for(itmap = s_RTs.mapTargets.begin(); itmap != s_RTs.mapTargets.end(); ++itmap) { +// if( itmap->second == *it ) +// break; +// } +// +// if( itmap == s_RTs.mapTargets.end() ) { +// +// for(itmap = s_DepthRTs.mapTargets.begin(); itmap != s_DepthRTs.mapTargets.end(); ++itmap) { +// if( itmap->second == *it ) +// break; +// } +// +// assert( itmap != s_DepthRTs.mapTargets.end() ); +// } +// } +//#endif +// } + + for (list::iterator it = listTransmissionUpdateTargs.begin(); it != listTransmissionUpdateTargs.end(); ++it) + { + + CRenderTarget* ptarg = *it; + + if ((ptarg->status & CRenderTarget::TS_Virtual)) continue; + + if (!(ptarg->start < texend && ptarg->end > texstart)) + { + // check if target is currently being used + + if (!(conf.settings().no_quick_resolve)) + { + if (ptarg->fbp != vb[0].gsfb.fbp) //&& (vb[0].prndr == NULL || ptarg->fbp != vb[0].prndr->fbp) ) { + { + if (ptarg->fbp != vb[1].gsfb.fbp) //&& (vb[1].prndr == NULL || ptarg->fbp != vb[1].prndr->fbp) ) { + { + // this render target currently isn't used and is not in the texture's way, so can safely ignore + // resolving it. Also the range has to be big enough compared to the target to really call it resolved + // (ffx changing screens, shadowhearts) + // start == ptarg->start, used for kh to transfer text + + if (ptarg->IsDepth() || end - start > 0x50000 || ((conf.settings().quick_resolve_1) && start == ptarg->start)) + ptarg->status |= CRenderTarget::TS_NeedUpdate | CRenderTarget::TS_Resolved; + + continue; + } + } + } + } + else + { +// if( start <= texstart && end >= texend ) { +// // texture taken care of so can skip!? +// continue; +// } + } + + // the first range check was very rough; some games (dragonball z) have the zbuf in the same page as textures (but not overlapping) + // so detect that condition + if (ptarg->fbh % m_Blocks[ptarg->psm].height) + { + + // get start of left-most boundry page + int targstart, targend; + GetRectMemAddress(targstart, targend, ptarg->psm, 0, 0, ptarg->fbw, ptarg->fbh & ~(m_Blocks[ptarg->psm].height - 1), ptarg->fbp, ptarg->fbw); + + if (start >= targend) + { + // don't bother + if ((ptarg->fbh % m_Blocks[ptarg->psm].height) <= 2) continue; + + // calc how many bytes of the block that the page spans + } + } + + if (!(ptarg->status & CRenderTarget::TS_Virtual)) + { + + if (start < ptarg->end && end > ptarg->start) + { + + // suikoden5 is faster with check, but too big of a value and kh screens mess up + /* Zeydlitz remove this check, it does not do anything good + if ((end - start > 0x8000) && (!(conf.settings() & GAME_GUSTHACK) || (end-start > 0x40000))) { + // intersects, do only one sided resolves + if( end-start > 4*ptarg->fbw ) { // at least it be greater than one scanline (spiro is faster) + if( start > ptarg->start ) { + ptarg->Resolve(ptarg->start, start); + + } + else if( end < ptarg->end ) { + ptarg->Resolve(end, ptarg->end); + } + } + }*/ + + ptarg->status |= CRenderTarget::TS_Resolved; + + if ((!ptarg->IsDepth() || (!(conf.settings().no_depth_update) || end - start > 0x1000)) && ((end - start > 0x40000) || !(conf.settings().gust))) + ptarg->status |= CRenderTarget::TS_NeedUpdate; + } + } + } + + g_MemTargs.ClearRange(start, end); + } + + s_RangeMngr.Clear(); +} + + +#if 0 +// I removed some code here that wasn't getting called. The old versions #if'ed out below this. +#define RESOLVE_32_BIT(PSM, T, Tsrc, convfn) \ + { \ + u32 mask, imask; \ + \ + if (PSMT_ISHALF(psm)) /* 16 bit */ \ + {\ + /* mask is shifted*/ \ + imask = RGBA32to16(fbm);\ + mask = (~imask)&0xffff;\ + }\ + else \ + {\ + mask = ~fbm;\ + imask = fbm;\ + }\ + \ + Tsrc* src = (Tsrc*)(psrc); \ + T* pPageOffset = (T*)g_pbyGSMemory + fbp*(256/sizeof(T)), *dst; \ + int maxfbh = (MEMORY_END-fbp*256) / (sizeof(T) * fbw); \ + if( maxfbh > fbh ) maxfbh = fbh; \ + \ + for(int i = 0; i < maxfbh; ++i) { \ + for(int j = 0; j < fbw; ++j) { \ + T dsrc = convfn(src[RW(j)]); \ + dst = pPageOffset + getPixelAddress##PSM##_0(j, i, fbw); \ + *dst = (dsrc & mask) | (*dst & imask); \ + } \ + src += RH(Pitch(fbw))/sizeof(Tsrc); \ + } \ + } \ + +#endif + +#ifdef __LINUX__ +//#define LOG_RESOLVE_PROFILE +#endif + +template +inline void Resolve_32_Bit(const void* psrc, int fbp, int fbw, int fbh, const int psm, u32 fbm) +{ + u32 mask, imask; +#ifdef LOG_RESOLVE_PROFILE + u32 startime = timeGetPreciseTime(); +#endif + + if (PSMT_ISHALF(psm)) /* 16 bit */ + { + /* mask is shifted*/ + imask = RGBA32to16(fbm); + mask = (~imask)&0xffff; + } + else + { + mask = ~fbm; + imask = fbm; + } + + Tdst* pPageOffset = (Tdst*)g_pbyGSMemory + fbp*(256/sizeof(Tdst)); + Tdst* dst; + Tdst dsrc; + + int maxfbh = (MEMORY_END-fbp*256) / (sizeof(Tdst) * fbw); + if( maxfbh > fbh ) maxfbh = fbh; + +#ifdef LOG_RESOLVE_PROFILE + ZZLog::Dev_Log("*** Resolve 32 bits: %dx%d in %x", maxfbh, fbw, psm); +#endif + + // Start the src array at the end to reduce testing in loop + u32 raw_size = RH(Pitch(fbw))/sizeof(u32); + u32* src = (u32*)(psrc) + (maxfbh-1)*raw_size; + + for(int i = maxfbh-1; i >= 0; --i) { + for(int j = fbw-1; j >= 0; --j) { + if (do_conversion) { + dsrc = RGBA32to16(src[RW(j)]); + } else { + dsrc = (Tdst)src[RW(j)]; + } + // They are 3 methods to call the functions + // macro (compact, inline) but need a nice psm ; swich (inline) ; function pointer (compact) + // Use a switch to allow inlining of the getPixel function. + // Note: psm is const so the switch is completely optimized + // Function method example: + // dst = pPageOffset + getPixelFun_0[psm](j, i, fbw); + switch (psm) + { + case PSMCT32: + case PSMCT24: + dst = pPageOffset + getPixelAddress32_0(j, i, fbw); + break; + + case PSMCT16: + dst = pPageOffset + getPixelAddress16_0(j, i, fbw); + break; + + case PSMCT16S: + dst = pPageOffset + getPixelAddress16S_0(j, i, fbw); + break; + + case PSMT32Z: + case PSMT24Z: + dst = pPageOffset + getPixelAddress32Z_0(j, i, fbw); + break; + + case PSMT16Z: + dst = pPageOffset + getPixelAddress16Z_0(j, i, fbw); + break; + + case PSMT16SZ: + dst = pPageOffset + getPixelAddress16SZ_0(j, i, fbw); + break; + } + *dst = (dsrc & mask) | (*dst & imask); + } + src -= raw_size; + } +#ifdef LOG_RESOLVE_PROFILE + ZZLog::Dev_Log("*** 32 bits: execution time %d", timeGetPreciseTime()-startime); +#endif +} + +static const __aligned16 unsigned int pixel_5b_mask[4] = {0x0000001F, 0x0000001F, 0x0000001F, 0x0000001F}; + +#ifdef ZEROGS_SSE2 +// The function process 2*2 pixels in 32bits. And 2*4 pixels in 16bits +template +__forceinline void update_8pixels_sse2(u32* src, u32* basepage, u32 i_msk, u32 j, u32 pix_mask, u32 src_pitch) +{ + u32* base_ptr; + __m128i pixels_0; + __m128i pixel_0_low; + __m128i pixel_0_high; + + __m128i pixels_1; + __m128i pixel_1_low; + __m128i pixel_1_high; + + assert((i_msk&0x1) == 0); // Failure => wrong line selected + + // Note: pixels have a special arrangement in column. Here a short description when AA.x = 0 + // + // 32 bits format: 8x2 pixels: the idea is to read pixels 0-3 + // It is easier to process 4 bits (we can not cross column bondary) + // 0 1 4 5 8 9 12 13 + // 2 3 6 7 10 11 14 15 + // + // 16 bits format: 16x2 pixels, each pixels have a lower and higher part. + // Here the idea to read 0L-3L & 0H-3H to combine lower and higher part this avoid + // data interleaving and useless read/write + // 0L 1L 4L 5L 8L 9L 12L 13L 0H 1H 4H 5H 8H 9H 12H 13H + // 2L 3L 6L 7L 10L 11L 14L 15L 2H 3H 6H 7H 10H 11H 14H 15H + // + if (AA.x == 2) { + // Note: pixels (32bits) are stored like that: + // p0 p0 p0 p0 p1 p1 p1 p1 p4 p4 p4 p4 p5 p5 p5 p5 + // ... + // p2 p2 p2 p2 p3 p3 p3 p3 p6 p6 p6 p6 p7 p7 p7 p7 + base_ptr = &src[((j+INDEX)<<2)]; + pixel_0_low = _mm_loadl_epi64((__m128i*)(base_ptr + 3)); + if (!null_second_line) pixel_0_high = _mm_loadl_epi64((__m128i*)(base_ptr + 3 + src_pitch)); + + if (PSMT_ISHALF(psm)) { + pixel_1_low = _mm_loadl_epi64((__m128i*)(base_ptr + 3 + 32)); + if (!null_second_line) pixel_1_high = _mm_loadl_epi64((__m128i*)(base_ptr + 3 + 32 + src_pitch)); + } + } else if(AA.x ==1) { + // Note: pixels (32bits) are stored like that: + // p0 p0 p1 p1 p4 p4 p5 p5 + // ... + // p2 p2 p3 p3 p6 p6 p7 p7 + base_ptr = &src[((j+INDEX)<<1)]; + pixel_0_low = _mm_loadl_epi64((__m128i*)(base_ptr + 1)); + if (!null_second_line) pixel_0_high = _mm_loadl_epi64((__m128i*)(base_ptr + 1 + src_pitch)); + + if (PSMT_ISHALF(psm)) { + pixel_1_low = _mm_loadl_epi64((__m128i*)(base_ptr + 1 + 16)); + if (!null_second_line) pixel_1_high = _mm_loadl_epi64((__m128i*)(base_ptr + 1 + 16 + src_pitch)); + } + } else { + // Note: pixels (32bits) are stored like that: + // p0 p1 p4 p5 + // p2 p3 p6 p7 + base_ptr = &src[(j+INDEX)]; + pixel_0_low = _mm_loadl_epi64((__m128i*)base_ptr); + if (!null_second_line) pixel_0_high = _mm_loadl_epi64((__m128i*)(base_ptr + src_pitch)); + + if (PSMT_ISHALF(psm)) { + pixel_1_low = _mm_loadl_epi64((__m128i*)(base_ptr + 8)); + if (!null_second_line) pixel_1_high = _mm_loadl_epi64((__m128i*)(base_ptr + 8 + src_pitch)); + } + } + + // 2nd line does not exist... Just duplicate the pixel value + if(null_second_line) { + pixel_0_high = pixel_0_low; + if (PSMT_ISHALF(psm)) pixel_1_high = pixel_1_low; + } + + // Merge the 2 dword + pixels_0 = _mm_unpacklo_epi64(pixel_0_low, pixel_0_high); + if (PSMT_ISHALF(psm)) pixels_1 = _mm_unpacklo_epi64(pixel_1_low, pixel_1_high); + + // transform pixel from ARGB:8888 to ARGB:1555 + if (psm == PSMCT16 || psm == PSMCT16S) { + // shift pixel instead of the mask. It allow to keep 1 mask into a register + // instead of 4 (not enough room on x86...). + __m128i pixel_mask = _mm_load_si128((__m128i*)pixel_5b_mask); + + __m128i pixel_0_B = _mm_srli_epi32(pixels_0, 3); + pixel_0_B = _mm_and_si128(pixel_0_B, pixel_mask); + + __m128i pixel_0_G = _mm_srli_epi32(pixels_0, 11); + pixel_0_G = _mm_and_si128(pixel_0_G, pixel_mask); + + __m128i pixel_0_R = _mm_srli_epi32(pixels_0, 19); + pixel_0_R = _mm_and_si128(pixel_0_R, pixel_mask); + + // Note: because of the logical shift we do not need to mask the value + __m128i pixel_0_A = _mm_srli_epi32(pixels_0, 31); + + // Realignment of pixels + pixel_0_A = _mm_slli_epi32(pixel_0_A, 15); + pixel_0_R = _mm_slli_epi32(pixel_0_R, 10); + pixel_0_G = _mm_slli_epi32(pixel_0_G, 5); + + // rebuild a complete pixel + pixels_0 = _mm_or_si128(pixel_0_A, pixel_0_B); + pixels_0 = _mm_or_si128(pixels_0, pixel_0_G); + pixels_0 = _mm_or_si128(pixels_0, pixel_0_R); + + // do the same for pixel_1 + __m128i pixel_1_B = _mm_srli_epi32(pixels_1, 3); + pixel_1_B = _mm_and_si128(pixel_1_B, pixel_mask); + + __m128i pixel_1_G = _mm_srli_epi32(pixels_1, 11); + pixel_1_G = _mm_and_si128(pixel_1_G, pixel_mask); + + __m128i pixel_1_R = _mm_srli_epi32(pixels_1, 19); + pixel_1_R = _mm_and_si128(pixel_1_R, pixel_mask); + + __m128i pixel_1_A = _mm_srli_epi32(pixels_1, 31); + + // Realignment of pixels + pixel_1_A = _mm_slli_epi32(pixel_1_A, 15); + pixel_1_R = _mm_slli_epi32(pixel_1_R, 10); + pixel_1_G = _mm_slli_epi32(pixel_1_G, 5); + + // rebuild a complete pixel + pixels_1 = _mm_or_si128(pixel_1_A, pixel_1_B); + pixels_1 = _mm_or_si128(pixels_1, pixel_1_G); + pixels_1 = _mm_or_si128(pixels_1, pixel_1_R); + } + + // Move the pixels to higher parts and merge it with pixels_0 + if (PSMT_ISHALF(psm)) { + pixels_1 = _mm_slli_epi32(pixels_1, 16); + pixels_0 = _mm_or_si128(pixels_0, pixels_1); + } + + // Status 16 bits + // pixels_0 = p3H p3L p2H p2L p1H p1L p0H p0L + // Status 32 bits + // pixels_0 = p3 p2 p1 p0 + + // load the destination add + u32* dst_add; + if (PSMT_ISHALF(psm)) + dst_add = basepage + (pageTable[i_msk][(INDEX)] >> 1); + else + dst_add = basepage + pageTable[i_msk][(INDEX)]; + + // Save some memory access when pix_mask is 0. + if (pix_mask) { + // Build fbm mask (tranform a u32 to a 4 packets u32) + // In 16 bits texture one packet is "0000 DATA" + __m128i imask = _mm_cvtsi32_si128(pix_mask); + imask = _mm_shuffle_epi32(imask, 0); + + // apply the mask on new values + pixels_0 = _mm_andnot_si128(imask, pixels_0); + + __m128i old_pixels_0; + __m128i final_pixels_0; + + old_pixels_0 = _mm_and_si128(imask, _mm_load_si128((__m128i*)dst_add)); + final_pixels_0 = _mm_or_si128(old_pixels_0, pixels_0); + + _mm_store_si128((__m128i*)dst_add, final_pixels_0); + } else { + // Note: because we did not read the previous value of add. We could bypass the cache. + // We gains a few percents + _mm_stream_si128((__m128i*)dst_add, pixels_0); + } + +} + +// Update 2 lines of a page (2*64 pixels) +template +__forceinline void update_pixels_row_sse2(u32* src, u32* basepage, u32 i_msk, u32 j, u32 pix_mask, u32 raw_size) +{ + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + + if(!PSMT_ISHALF(psm)) { + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + } + + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + + if(!PSMT_ISHALF(psm)) { + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + } + + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + + if(!PSMT_ISHALF(psm)) { + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + } + + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + + if(!PSMT_ISHALF(psm)) { + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + update_8pixels_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + } +} + +template +void Resolve_32_Bit_sse2(const void* psrc, int fbp, int fbw, int fbh, u32 fbm) +{ + // Note a basic implementation was done in Resolve_32_Bit function +#ifdef LOG_RESOLVE_PROFILE + u32 startime = timeGetPreciseTime(); +#endif + u32 pix_mask; + if (PSMT_ISHALF(psm)) /* 16 bit format */ + { + /* Use 2 16bits mask */ + u32 pix16_mask = RGBA32to16(fbm); + pix_mask = (pix16_mask<<16) | pix16_mask; + } + else + pix_mask = fbm; + + // Note GS register: frame_register__fbp is specified in units of the 32 bits address divided by 2048 + // fbp is stored as 32*frame_register__fbp + u32* pPageOffset = (u32*)g_pbyGSMemory + (fbp/32)*2048; + + int maxfbh; + int memory_space = MEMORY_END-(fbp/32)*2048*4; + if (PSMT_ISHALF(psm)) + maxfbh = memory_space / (2*fbw); + else + maxfbh = memory_space / (4*fbw); + + if( maxfbh > fbh ) maxfbh = fbh; + +#ifdef LOG_RESOLVE_PROFILE + ZZLog::Dev_Log("*** Resolve 32 to 32 bits: %dx%d. Frame Mask %x. Format %x", maxfbh, fbw, pix_mask, psm); +#endif + + // Start the src array at the end to reduce testing in loop + // If maxfbh is odd, proces maxfbh -1 alone and then go back to maxfbh -3 + u32 raw_size = RH(Pitch(fbw))/sizeof(u32); + u32* src; + if (maxfbh&0x1) { + ZZLog::Dev_Log("*** Warning resolve 32bits have an odd number of lines"); + + // decrease maxfbh to process the bottom line (maxfbh-1) + maxfbh--; + + src = (u32*)(psrc) + maxfbh*raw_size; + u32 i_msk = maxfbh & (size-1); + // Note fbw is a multiple of 64. So you can unroll the loop 64 times + for(int j = (fbw - 64); j >= 0; j -= 64) { + u32* basepage = pPageOffset + ((maxfbh/size) * (fbw/64) + (j/64)) * 2048; + update_pixels_row_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + } + // realign the src pointer to process others lines + src -= 2*raw_size; + } else { + // Because we process 2 lines at once go back to maxfbh-2. + src = (u32*)(psrc) + (maxfbh-2)*raw_size; + } + + // Note i must be even for the update_8pixels functions + assert((maxfbh&0x1) == 0); + for(int i = (maxfbh-2); i >= 0; i -= 2) { + u32 i_msk = i & (size-1); + // Note fbw is a multiple of 64. So you can unroll the loop 64 times + for(int j = (fbw - 64); j >= 0; j -= 64) { + u32* basepage = pPageOffset + ((i/size) * (fbw/64) + (j/64)) * 2048; + update_pixels_row_sse2(src, basepage, i_msk, j, pix_mask, raw_size); + } + + // Note update_8pixels process 2 lines at onces hence the factor 2 + src -= 2*raw_size; + } + + if(!pix_mask) { + // Ensure that previous (out of order) write are done. It must be done after non temporal instruction + // (or *_stream_* intrinsic) + _mm_sfence(); + } + +#ifdef LOG_RESOLVE_PROFILE + ZZLog::Dev_Log("*** 32 bits: execution time %d", timeGetPreciseTime()-startime); +#endif +} +#endif + +void _Resolve(const void* psrc, int fbp, int fbw, int fbh, int psm, u32 fbm, bool mode = true) +{ + FUNCLOG + + int start, end; + + s_nResolved += 2; + + // align the rect to the nearest page + // note that fbp is always aligned on page boundaries + GetRectMemAddress(start, end, psm, 0, 0, fbw, fbh, fbp, fbw); + + // Comment this to restore the previous resolve_32 version +#define OPTI_RESOLVE_32 + // start the conversion process A8R8G8B8 -> psm + switch (psm) + { + + // NOTE pass psm as a constant value otherwise gcc does not do its job. It keep + // the psm switch in Resolve_32_Bit + case PSMCT32: + case PSMCT24: +#if defined(ZEROGS_SSE2) && defined(OPTI_RESOLVE_32) + Resolve_32_Bit_sse2(psrc, fbp, fbw, fbh, fbm); +#else + Resolve_32_Bit(psrc, fbp, fbw, fbh, PSMCT32, fbm); +#endif + break; + + case PSMCT16: +#if defined(ZEROGS_SSE2) && defined(OPTI_RESOLVE_32) + Resolve_32_Bit_sse2(psrc, fbp, fbw, fbh, fbm); +#else + Resolve_32_Bit(psrc, fbp, fbw, fbh, PSMCT16, fbm); +#endif + break; + + case PSMCT16S: +#if defined(ZEROGS_SSE2) && defined(OPTI_RESOLVE_32) + Resolve_32_Bit_sse2(psrc, fbp, fbw, fbh, fbm); +#else + Resolve_32_Bit(psrc, fbp, fbw, fbh, PSMCT16S, fbm); +#endif + break; + + case PSMT32Z: + case PSMT24Z: +#if defined(ZEROGS_SSE2) && defined(OPTI_RESOLVE_32) + Resolve_32_Bit_sse2(psrc, fbp, fbw, fbh, fbm); +#else + Resolve_32_Bit(psrc, fbp, fbw, fbh, PSMT32Z, fbm); +#endif + break; + + case PSMT16Z: +#if defined(ZEROGS_SSE2) && defined(OPTI_RESOLVE_32) + Resolve_32_Bit_sse2(psrc, fbp, fbw, fbh, fbm); +#else + Resolve_32_Bit(psrc, fbp, fbw, fbh, PSMT16Z, fbm); +#endif + break; + + case PSMT16SZ: +#if defined(ZEROGS_SSE2) && defined(OPTI_RESOLVE_32) + Resolve_32_Bit_sse2(psrc, fbp, fbw, fbh, fbm); +#else + Resolve_32_Bit(psrc, fbp, fbw, fbh, PSMT16SZ, fbm); +#endif + break; + } + + g_MemTargs.ClearRange(start, end); + + INC_RESOLVE(); +} + +// Leaving this code in for reference for the moment. +#if 0 +void _Resolve(const void* psrc, int fbp, int fbw, int fbh, int psm, u32 fbm, bool mode) +{ + FUNCLOG + //GL_REPORT_ERRORD(); + s_nResolved += 2; + + // align the rect to the nearest page + // note that fbp is always aligned on page boundaries + int start, end; + GetRectMemAddress(start, end, psm, 0, 0, fbw, fbh, fbp, fbw); + + int i, j; + //short smask1 = gs.smask&1; + //short smask2 = gs.smask&2; + u32 mask, imask; + + if (PSMT_ISHALF(psm)) // 16 bit + { + // mask is shifted + imask = RGBA32to16(fbm); + mask = (~imask) & 0xffff; + } + else + { + mask = ~fbm; + imask = fbm; + + if ((psm&0xf) > 0 && 0) + { + // preserve the alpha? + mask &= 0x00ffffff; + imask |= 0xff000000; + } + } + + // Targets over 2000 should be shuffle. FFX and KH2 (0x2100) + int X = (psm == 0) ? 0 : 0; + +//if (X == 1) +//ZZLog::Error_Log("resolve: %x %x %x %x (%x-%x).", psm, fbp, fbw, fbh, start, end); + + +#define RESOLVE_32BIT(psm, T, Tsrc, blockbits, blockwidth, blockheight, convfn, frame, aax, aay) \ + { \ + Tsrc* src = (Tsrc*)(psrc); \ + T* pPageOffset = (T*)g_pbyGSMemory + fbp*(256/sizeof(T)), *dst; \ + int srcpitch = Pitch(fbw) * blockheight/sizeof(Tsrc); \ + int maxfbh = (MEMORY_END-fbp*256) / (sizeof(T) * fbw); \ + if( maxfbh > fbh ) maxfbh = fbh; \ + for(i = 0; i < (maxfbh&~(blockheight-1))*X; i += blockheight) { \ + /*if( smask2 && (i&1) == smask1 ) continue; */ \ + for(j = 0; j < fbw; j += blockwidth) { \ + /* have to write in the tiled format*/ \ + frame##SwizzleBlock##blockbits(pPageOffset + getPixelAddress##psm##_0(j, i, fbw), \ + src+RW(j), Pitch(fbw)/sizeof(Tsrc), mask); \ + } \ + src += RH(srcpitch); \ + } \ + for(; i < maxfbh; ++i) { \ + for(j = 0; j < fbw; ++j) { \ + T dsrc = convfn(src[RW(j)]); \ + dst = pPageOffset + getPixelAddress##psm##_0(j, i, fbw); \ + *dst = (dsrc & mask) | (*dst & imask); \ + } \ + src += RH(Pitch(fbw))/sizeof(Tsrc); \ + } \ + } \ + + if( GetRenderFormat() == RFT_byte8 ) { + // start the conversion process A8R8G8B8 -> psm + switch (psm) + { + + case PSMCT32: + + case PSMCT24: + + if (AA.y) + { + RESOLVE_32BIT(32, u32, u32, 32A4, 8, 8, (u32), Frame, AA.x, AA.y); + } + else if (AA.x) + { + RESOLVE_32BIT(32, u32, u32, 32A2, 8, 8, (u32), Frame, 1, 0); + } + else + { + RESOLVE_32BIT(32, u32, u32, 32, 8, 8, (u32), Frame, 0, 0); + } + + break; + + case PSMCT16: + + if (AA.y) + { + RESOLVE_32BIT(16, u16, u32, 16A4, 16, 8, RGBA32to16, Frame, AA.x, AA.y); + } + else if (AA.x) + { + RESOLVE_32BIT(16, u16, u32, 16A2, 16, 8, RGBA32to16, Frame, 1, 0); + } + else + { + RESOLVE_32BIT(16, u16, u32, 16, 16, 8, RGBA32to16, Frame, 0, 0); + } + + break; + + case PSMCT16S: + + if (AA.y) + { + RESOLVE_32BIT(16S, u16, u32, 16A4, 16, 8, RGBA32to16, Frame, AA.x, AA.y); + } + else if (AA.x) + { + RESOLVE_32BIT(16S, u16, u32, 16A2, 16, 8, RGBA32to16, Frame, 1, 0); + } + else + { + RESOLVE_32BIT(16S, u16, u32, 16, 16, 8, RGBA32to16, Frame, 0, 0); + } + + break; + + case PSMT32Z: + + case PSMT24Z: + + if (AA.y) + { + RESOLVE_32BIT(32Z, u32, u32, 32A4, 8, 8, (u32), Frame, AA.x, AA.y); + } + else if (AA.x) + { + RESOLVE_32BIT(32Z, u32, u32, 32A2, 8, 8, (u32), Frame, 1, 0); + } + else + { + RESOLVE_32BIT(32Z, u32, u32, 32, 8, 8, (u32), Frame, 0, 0); + } + + break; + + case PSMT16Z: + + if (AA.y) + { + RESOLVE_32BIT(16Z, u16, u32, 16A4, 16, 8, (u16), Frame, AA.x, AA.y); + } + else if (AA.x) + { + RESOLVE_32BIT(16Z, u16, u32, 16A2, 16, 8, (u16), Frame, 1, 0); + } + else + { + RESOLVE_32BIT(16Z, u16, u32, 16, 16, 8, (u16), Frame, 0, 0); + } + + break; + + case PSMT16SZ: + + if (AA.y) + { + RESOLVE_32BIT(16SZ, u16, u32, 16A4, 16, 8, (u16), Frame, AA.x, AA.y); + } + else if (AA.x) + { + RESOLVE_32BIT(16SZ, u16, u32, 16A2, 16, 8, (u16), Frame, 1, 0); + } + else + { + RESOLVE_32BIT(16SZ, u16, u32, 16, 16, 8, (u16), Frame, 0, 0); + } + + break; + } + } + else // float16 + { + switch (psm) + { + + case PSMCT32: + + case PSMCT24: + + if (AA.y) + { + RESOLVE_32BIT(32, u32, Vector_16F, 32A4, 8, 8, Float16ToARGB, Frame16, 1, 1); + } + else if (AA.x) + { + RESOLVE_32BIT(32, u32, Vector_16F, 32A2, 8, 8, Float16ToARGB, Frame16, 1, 0); + } + else + { + RESOLVE_32BIT(32, u32, Vector_16F, 32, 8, 8, Float16ToARGB, Frame16, 0, 0); + } + + break; + + case PSMCT16: + + if (AA.y) + { + RESOLVE_32BIT(16, u16, Vector_16F, 16A4, 16, 8, Float16ToARGB16, Frame16, 1, 1); + } + else if (AA.x) + { + RESOLVE_32BIT(16, u16, Vector_16F, 16A2, 16, 8, Float16ToARGB16, Frame16, 1, 0); + } + else + { + RESOLVE_32BIT(16, u16, Vector_16F, 16, 16, 8, Float16ToARGB16, Frame16, 0, 0); + } + + break; + + case PSMCT16S: + + if (AA.y) + { + RESOLVE_32BIT(16S, u16, Vector_16F, 16A4, 16, 8, Float16ToARGB16, Frame16, 1, 1); + } + else if (AA.x) + { + RESOLVE_32BIT(16S, u16, Vector_16F, 16A2, 16, 8, Float16ToARGB16, Frame16, 1, 0); + } + else + { + RESOLVE_32BIT(16S, u16, Vector_16F, 16, 16, 8, Float16ToARGB16, Frame16, 0, 0); + } + + break; + + case PSMT32Z: + + case PSMT24Z: + + if (AA.y) + { + RESOLVE_32BIT(32Z, u32, Vector_16F, 32ZA4, 8, 8, Float16ToARGB_Z, Frame16, 1, 1); + } + else if (AA.x) + { + RESOLVE_32BIT(32Z, u32, Vector_16F, 32ZA2, 8, 8, Float16ToARGB_Z, Frame16, 1, 0); + } + else + { + RESOLVE_32BIT(32Z, u32, Vector_16F, 32Z, 8, 8, Float16ToARGB_Z, Frame16, 0, 0); + } + + break; + + case PSMT16Z: + + if (AA.y) + { + RESOLVE_32BIT(16Z, u16, Vector_16F, 16ZA4, 16, 8, Float16ToARGB16_Z, Frame16, 1, 1); + } + else if (AA.x) + { + RESOLVE_32BIT(16Z, u16, Vector_16F, 16ZA2, 16, 8, Float16ToARGB16_Z, Frame16, 1, 0); + } + else + { + RESOLVE_32BIT(16Z, u16, Vector_16F, 16Z, 16, 8, Float16ToARGB16_Z, Frame16, 0, 0); + } + + break; + + case PSMT16SZ: + + if (AA.y) + { + RESOLVE_32BIT(16SZ, u16, Vector_16F, 16ZA4, 16, 8, Float16ToARGB16_Z, Frame16, 1, 1); + } + else if (AA.x) + { + RESOLVE_32BIT(16SZ, u16, Vector_16F, 16ZA2, 16, 8, Float16ToARGB16_Z, Frame16, 1, 0); + } + else + { + RESOLVE_32BIT(16SZ, u16, Vector_16F, 16Z, 16, 8, Float16ToARGB16_Z, Frame16, 0, 0); + } + + break; + } + } + + g_MemTargs.ClearRange(start, end); + + INC_RESOLVE(); +} + +#endif diff --git a/plugins/zzogl-pg-cg/opengl/targets.h b/plugins/zzogl-pg-cg/opengl/targets.h new file mode 100644 index 000000000..d48fc5977 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/targets.h @@ -0,0 +1,607 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __ZEROGS_TARGETS_H__ +#define __ZEROGS_TARGETS_H__ + +#define TARGET_VIRTUAL_KEY 0x80000000 +#include "PS2Edefs.h" +#include +#include +#include "GS.h" +#include "ZZGl.h" +//#include "ZZoglVB.h" + +#ifndef GL_TEXTURE_RECTANGLE +#define GL_TEXTURE_RECTANGLE GL_TEXTURE_RECTANGLE_NV +#endif + +#define VB_BUFFERSIZE 0x4000 + +// all textures have this width +extern int GPU_TEXWIDTH; +extern float g_fiGPU_TEXWIDTH; +#define MASKDIVISOR 0 // Used for decrement bitwise mask texture size if 1024 is too big +#define GPU_TEXMASKWIDTH (1024 >> MASKDIVISOR) // bitwise mask width for region repeat mode + +// managers render-to-texture targets +class CRenderTarget +{ + + public: + CRenderTarget(); + virtual ~CRenderTarget(); + + virtual bool Create(const frameInfo& frame); + virtual void Destroy(); + + // set the GPU_POSXY variable, scissor rect, and current render target + void SetTarget(int fbplocal, const Rect2& scissor, int context); + void SetViewport(); + + // copies/creates the feedback contents + inline void CreateFeedback() + { + if (ptexFeedback == 0 || !(status&TS_FeedbackReady)) + _CreateFeedback(); + } + + virtual void Resolve(); + virtual void Resolve(int startrange, int endrange); // resolves only in the allowed range + virtual void Update(int context, CRenderTarget* pdepth); + virtual void ConvertTo32(); // converts a psm==2 target, to a psm==0 + virtual void ConvertTo16(); // converts a psm==0 target, to a psm==2 + + virtual bool IsDepth() { return false; } + + void SetRenderTarget(int targ); + + void* psys; // system data used for comparison + u32 ptex; + + int fbp, fbw, fbh, fbhCalc; // if fbp is negative, virtual target (not mapped to any real addr) + int start, end; // in bytes + u32 lastused; // time stamp since last used + float4 vposxy; + + u32 fbm; + u16 status; + u8 psm; + u8 resv0; + Rect scissorrect; + + u8 created; // Check for object destruction/creating for r201. + + //int startresolve, endresolve; + u32 nUpdateTarg; // use this target to update the texture if non 0 (one time only) + + // this is optionally used when feedback effects are used (render target is used as a texture when rendering to itself) + u32 ptexFeedback; + + enum TargetStatus + { + TS_Resolved = 1, + TS_NeedUpdate = 2, + TS_Virtual = 4, // currently not mapped to memory + TS_FeedbackReady = 8, // feedback effect is ready and doesn't need to be updated + TS_NeedConvert32 = 16, + TS_NeedConvert16 = 32, + }; + inline float4 DefaultBitBltPos(); + inline float4 DefaultBitBltTex(); + + private: + void _CreateFeedback(); + inline bool InitialiseDefaultTexture(u32 *p_ptr, int fbw, int fbh) ; +}; + +// manages zbuffers + +class CDepthTarget : public CRenderTarget +{ + + public: + CDepthTarget(); + virtual ~CDepthTarget(); + + virtual bool Create(const frameInfo& frame); + virtual void Destroy(); + + virtual void Resolve(); + virtual void Resolve(int startrange, int endrange); // resolves only in the allowed range + virtual void Update(int context, CRenderTarget* prndr); + + virtual bool IsDepth() { return true; } + + void SetDepthStencilSurface(); + + u32 pdepth; // 24 bit, will contain the stencil buffer if possible + u32 pstencil; // if not 0, contains the stencil buffer + int icount; // internal counter +}; + +// manages contiguous chunks of memory (width is always 1024) + +class CMemoryTarget +{ + public: + struct TEXTURE + { + inline TEXTURE() : tex(0), memptr(NULL), ref(0) {} + inline ~TEXTURE() { glDeleteTextures(1, &tex); _aligned_free(memptr); } + + u32 tex; + u8* memptr; // GPU memory used for comparison + int ref; + }; + + inline CMemoryTarget() : ptex(NULL), starty(0), height(0), realy(0), realheight(0), usedstamp(0), psm(0), cpsm(0), channels(0), clearminy(0), clearmaxy(0), validatecount(0), clut(NULL), clutsize(0) {} + + inline CMemoryTarget(const CMemoryTarget& r) + { + ptex = r.ptex; + + if (ptex != NULL) ptex->ref++; + + starty = r.starty; + height = r.height; + realy = r.realy; + realheight = r.realheight; + usedstamp = r.usedstamp; + psm = r.psm; + cpsm = r.cpsm; + clut = r.clut; + clearminy = r.clearminy; + clearmaxy = r.clearmaxy; + widthmult = r.widthmult; + texH = r.texH; + texW = r.texW; + channels = r.channels; + validatecount = r.validatecount; + fmt = r.fmt; + } + + ~CMemoryTarget() { Destroy(); } + + inline void Destroy() + { + if (ptex != NULL && ptex->ref > 0) + { + if (--ptex->ref <= 0) delete ptex; + } + + ptex = NULL; + + _aligned_free(clut); + clut = NULL; + clutsize = 0; + } + + // returns true if clut data is synced + bool ValidateClut(const tex0Info& tex0); + // returns true if tex data is synced + bool ValidateTex(const tex0Info& tex0, int starttex, int endtex, bool bDeleteBadTex); + + // realy is offset in pixels from start of valid region + // so texture in memory is [realy,starty+height] + // valid texture is [starty,starty+height] + // offset in mem [starty-realy, height] + TEXTURE* ptex; // can be 16bit + + int starty, height; // assert(starty >= realy) + int realy, realheight; // this is never touched once allocated + // realy is start pointer of data in 4M data block (start) and size (end-start). + + u32 usedstamp; + u8 psm, cpsm; // texture and clut format. For psm, only 16bit/32bit differentiation matters + + u32 fmt; + + int widthmult; // Either 1 or 2. + int channels; // The number of pixels per PSM format word. channels == PIXELS_PER_WORD(psm) + // This is the real drawing size in pixels of the texture in renderbuffer. + int texW; // (realheight + widthmult - 1)/widthmult == realheight or [(realheight+1)/2] + int texH; // GPU_TEXWIDTH *widthmult * channels; + + int clearminy, clearmaxy; // when maxy > 0, need to check for clearing + + int validatecount; // count how many times has been validated, if too many, destroy + + u8* clut; // Clut texture data. Null otherwise + int clutsize; // size of the clut array. 0 otherwise +}; + +inline u32 GetFrameKey(int fbp, int fbw); + +// manages render targets +class CRenderTargetMngr +{ + public: + typedef map MAPTARGETS; + + enum TargetOptions + { + TO_DepthBuffer = 1, + TO_StrictHeight = 2, // height returned has to be the same as requested + TO_Virtual = 4 + }; + + ~CRenderTargetMngr() { Destroy(); } + + void Destroy(); + static MAPTARGETS::iterator GetOldestTarg(MAPTARGETS& m); + + bool isFound(const frameInfo& frame, MAPTARGETS::iterator& it, u32 opts, u32 key, int maxposheight); + + CRenderTarget* GetTarg(const frameInfo& frame, u32 Options, int maxposheight); + inline CRenderTarget* GetTarg(int fbp, int fbw) + { + MAPTARGETS::iterator it = mapTargets.find(GetFrameKey(fbp, fbw)); + + /* if (fbp == 0x3600 && fbw == 0x100 && it == mapTargets.end()) + { + ZZLog::Debug_Log("%x", GetFrameKey(fbp, fbw)) ; + ZZLog::Debug_Log("%x %x", fbp, fbw); + for(MAPTARGETS::iterator it1 = mapTargets.begin(); it1 != mapTargets.end(); ++it1) + ZZLog::Debug_Log("\t %x %x %x %x", it1->second->fbw, it1->second->fbh, it1->second->psm, it1->second->fbp); + }*/ + return it != mapTargets.end() ? it->second : NULL; + } + + // gets all targets with a range + void GetTargs(int start, int end, list& listTargets) const; + + // resolves all targets within a range + __forceinline void Resolve(int start, int end); + __forceinline void ResolveAll() + { + for (MAPTARGETS::iterator it = mapTargets.begin(); it != mapTargets.end(); ++it) + it->second->Resolve(); + } + + void DestroyAllTargs(int start, int end, int fbw); + void DestroyIntersecting(CRenderTarget* prndr); + + // promotes a target from virtual to real + inline CRenderTarget* Promote(u32 key) + { + assert(!(key & TARGET_VIRTUAL_KEY)); + + // promote to regular targ + CRenderTargetMngr::MAPTARGETS::iterator it = mapTargets.find(key | TARGET_VIRTUAL_KEY); + assert(it != mapTargets.end()); + + CRenderTarget* ptarg = it->second; + mapTargets.erase(it); + + DestroyIntersecting(ptarg); + + it = mapTargets.find(key); + + if (it != mapTargets.end()) + { + DestroyTarg(it->second); + it->second = ptarg; + } + else + mapTargets[key] = ptarg; + + if (conf.settings().resolve_promoted) + ptarg->status = CRenderTarget::TS_Resolved; + else + ptarg->status = CRenderTarget::TS_NeedUpdate; + + return ptarg; + } + + static void DestroyTarg(CRenderTarget* ptarg); + void PrintTargets(); + MAPTARGETS mapTargets, mapDummyTargs; +}; + +class CMemoryTargetMngr +{ + public: + CMemoryTargetMngr() : curstamp(0) {} + + CMemoryTarget* GetMemoryTarget(const tex0Info& tex0, int forcevalidate); // pcbp is pointer to start of clut + CMemoryTarget* SearchExistTarget(int start, int end, int clutsize, const tex0Info& tex0, int forcevalidate); + CMemoryTarget* ClearedTargetsSearch(int fmt, int widthmult, int channels, int height); + int CompareTarget(list::iterator& it, const tex0Info& tex0, int clutsize); + + void Destroy(); // destroy all targs + + void ClearRange(int starty, int endy); // set all targets to cleared + void DestroyCleared(); // flush all cleared targes + void DestroyOldest(); + + list listTargets, listClearedTargets; + u32 curstamp; + + private: + list::iterator DestroyTargetIter(list::iterator& it); + void GetClutVariables(int& clutsize, const tex0Info& tex0); + void GetMemAddress(int& start, int& end, const tex0Info& tex0); +}; + +class CBitwiseTextureMngr +{ + public: + ~CBitwiseTextureMngr() { Destroy(); } + + void Destroy(); + + // since GetTex can delete textures to free up mem, it is dangerous if using that texture, so specify at least one other tex to save + __forceinline u32 GetTex(u32 bitvalue, u32 ptexDoNotDelete) + { + map::iterator it = mapTextures.find(bitvalue); + + if (it != mapTextures.end()) return it->second; + + return GetTexInt(bitvalue, ptexDoNotDelete); + } + + private: + u32 GetTexInt(u32 bitvalue, u32 ptexDoNotDelete); + + map mapTextures; +}; + +// manages + +class CRangeManager +{ + public: + CRangeManager() + { + ranges.reserve(16); + } + + // [start, end) + + struct RANGE + { + RANGE() {} + + inline RANGE(int start, int end) : start(start), end(end) {} + + int start, end; + }; + + // works in semi logN + void Insert(int start, int end); + void RangeSanityCheck(); + inline void Clear() + { + ranges.resize(0); + } + + vector ranges; // organized in ascending order, non-intersecting +}; + +extern CRenderTargetMngr s_RTs, s_DepthRTs; +extern CBitwiseTextureMngr s_BitwiseTextures; +extern CMemoryTargetMngr g_MemTargs; +extern CRangeManager s_RangeMngr; // manages overwritten memory + +//extern u8 s_AAx, s_AAy; +extern Point AA; + +// Real rendered width, depends on AA. +inline int RW(int tbw) +{ + return (tbw << AA.x); +} + +// Real rendered height, depends on AA. +inline int RH(int tbh) +{ + return (tbh << AA.y); +} + +/* inline void CreateTargetsList(int start, int end, list& listTargs) { + s_DepthRTs.GetTargs(start, end, listTargs); + s_RTs.GetTargs(start, end, listTargs); + }*/ + +// This pattern of functions is called 3 times, so I add creating Targets list into one. +inline list CreateTargetsList(int start, int end) +{ + list listTargs; + s_DepthRTs.GetTargs(start, end, listTargs); + s_RTs.GetTargs(start, end, listTargs); + return listTargs; +} + +extern int icurctx; +extern GLuint vboRect; + +// Unworking +#define PSMPOSITION 28 + +// Code width and height of frame into key, that used in targetmanager +// This is 3 variants of one function, Key dependant on fbp and fbw. +inline u32 GetFrameKey(const frameInfo& frame) +{ + return (((frame.fbw) << 16) | (frame.fbp)); +} + +inline u32 GetFrameKey(CRenderTarget* frame) +{ + return (((frame->fbw) << 16) | (frame->fbp)); +} + +inline u32 GetFrameKey(int fbp, int fbw) +{ + return (((fbw) << 16) | (fbp)); +} + +inline u16 ShiftHeight(int fbh, int fbp, int fbhCalc) +{ + return fbh; +} + +//#define FRAME_KEY_BY_FBH + +//FIXME: this code is for P4 and KH1. It should not be so strange! +//Dummy targets was deleted from mapTargets, but not erased. +inline u32 GetFrameKeyDummy(int fbp, int fbw, int fbh, int psm) +{ +// if (fbp > 0x2000 && ZZOgl_fbh_Calc(fbp, fbw, psm) < 0x400 && ZZOgl_fbh_Calc(fbp, fbw, psm) != fbh) +// ZZLog::Debug_Log("Z %x %x %x %x\n", fbh, fbhCalc, fbp, ZZOgl_fbh_Calc(fbp, fbw, psm)); + // height over 1024 would shrink to 1024, so dummy targets with calculated size more than 0x400 should be + // distinct by real height. But in FFX there is 3e0 height target, so I put 0x300 as limit. + +#ifndef FRAME_KEY_BY_FBH + int calc = ZZOgl_fbh_Calc(fbp, fbw, psm); + if (/*fbp > 0x2000 && */calc < /*0x300*/0x2E0) + return ((fbw << 16) | calc); + else +#endif + return ((fbw << 16) | fbh); +} + +inline u32 GetFrameKeyDummy(const frameInfo& frame) +{ + return GetFrameKeyDummy(frame.fbp, frame.fbw, frame.fbh, frame.psm); +} + +inline u32 GetFrameKeyDummy(CRenderTarget* frame) +{ + return GetFrameKeyDummy(frame->fbp, frame->fbw, frame->fbh, frame->psm); +} + +#include "Mem.h" + +static __forceinline void DrawTriangleArray() +{ + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + GL_REPORT_ERRORD(); +} + +static __forceinline void DrawBuffers(GLenum *buffer) +{ + if (glDrawBuffers != NULL) + { + glDrawBuffers(1, buffer); + } + + GL_REPORT_ERRORD(); +} + +static __forceinline void FBTexture(int attach, int id = 0) +{ + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + attach, GL_TEXTURE_RECTANGLE_NV, id, 0); + GL_REPORT_ERRORD(); +} + +static __forceinline void ResetRenderTarget(int index) +{ + FBTexture(index); +} + +static __forceinline void Texture2D(GLint iFormat, GLint width, GLint height, GLenum format, GLenum type, const GLvoid* pixels) +{ + glTexImage2D(GL_TEXTURE_2D, 0, iFormat, width, height, 0, format, type, pixels); +} + +static __forceinline void Texture2D(GLint iFormat, GLenum format, GLenum type, const GLvoid* pixels) +{ + glTexImage2D(GL_TEXTURE_2D, 0, iFormat, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, format, type, pixels); +} + +static __forceinline void Texture3D(GLint iFormat, GLint width, GLint height, GLint depth, GLenum format, GLenum type, const GLvoid* pixels) +{ + glTexImage3D(GL_TEXTURE_3D, 0, iFormat, width, height, depth, 0, format, type, pixels); +} + +static __forceinline void TextureRect(GLint iFormat, GLint width, GLint height, GLenum format, GLenum type, const GLvoid* pixels) +{ + glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, iFormat, width, height, 0, format, type, pixels); +} + +static __forceinline void TextureRect2(GLint iFormat, GLint width, GLint height, GLenum format, GLenum type, const GLvoid* pixels) +{ + glTexImage2D(GL_TEXTURE_RECTANGLE, 0, iFormat, width, height, 0, format, type, pixels); +} + +static __forceinline void TextureRect(GLenum attach, GLuint id = 0) +{ + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attach, GL_RENDERBUFFER_EXT, id); +} + +static __forceinline void setTex2DFilters(GLint type) +{ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, type); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, type); +} + +static __forceinline void setTex2DWrap(GLint type) +{ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, type); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, type); +} + +static __forceinline void setTex3DFilters(GLint type) +{ + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, type); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, type); +} + +static __forceinline void setTex3DWrap(GLint type) +{ + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, type); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, type); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, type); +} + +static __forceinline void setRectFilters(GLint type) +{ + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, type); + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, type); +} + +static __forceinline void setRectWrap(GLint type) +{ + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, type); + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, type); +} + +static __forceinline void setRectWrap2(GLint type) +{ + glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, type); + glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, type); +} + +//------------------------ Inlines ------------------------- + +// Calculate maximum height for target +inline int get_maxheight(int fbp, int fbw, int psm) +{ + int ret; + + if (fbw == 0) return 0; + + ret = (((0x00100000 - 64 * fbp) / fbw) & ~0x1f); + if (PSMT_ISHALF(psm)) ret *= 2; + + return ret; +} + +#endif diff --git a/plugins/zzogl-pg-cg/opengl/x86-32.S b/plugins/zzogl-pg-cg/opengl/x86-32.S new file mode 100644 index 000000000..728d20378 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/x86-32.S @@ -0,0 +1,716 @@ +# Copyright (C) 2005-2006 zerofrog(@gmail.com) +# +# This Program is free software you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation either ve%rsion 2, or (at your option) +# any later ve%rsion. +# +# This Program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Make see the file COPYING. If not, write to +# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +# http://www.gnu.org/copyleft/gpl.html +# +# +.intel_syntax + +#ifdef ZEROGS_SSE2 +// SSE2 extensions + +// Note: pshufd 0xea <=> movdqa !!! +// What the function does is +// Interleave s1 and sd0 -> d1 (high) & sd0 (low) +// Interleave s3 and sd2 -> d3 (high) & sd2 (low) +#define punpck(op, sd0, sd2, s1, s3, d1, d3) \ + movdqa %xmm##d1, %xmm##sd0; \ + pshufd %xmm##d3, %xmm##sd2, 0xe4; \ + punpckl##op %xmm##sd0, %xmm##s1; \ + punpckh##op %xmm##d1, %xmm##s1; \ + punpckl##op %xmm##sd2, %xmm##s3; \ + punpckh##op %xmm##d3, %xmm##s3; \ + + +// Input xmm7 == 0x0F0F0F0F 0x0F0F0F0F 0x0F0F0F0F 0x0F0F0F0F +// DATA xmm[0-3] +// This function does a 4-bits interleaving of 4 xmm registers +// +// ARG Can not put comment in the middle of the define... +// After the first por +// low 32bits (4bits packed) == 1.6 0.6 1.4 0.4 1.2 0.2 1.0 0.0 +// After the second one +// low 32bits (4bits packed) == 1.7 0.7 1.5 0.5 1.3 0.3 1.1 0.1 +#define punpcknb \ + movdqa %xmm4, %xmm0; \ + pshufd %xmm5, %xmm1, 0xe4; \ + \ + psllq %xmm1, 4; \ + psrlq %xmm4, 4; \ + \ + movdqa %xmm6, %xmm7; \ + pand %xmm0, %xmm7; \ + pandn %xmm6, %xmm1; \ + por %xmm0, %xmm6; \ + \ + movdqa %xmm6, %xmm7; \ + pand %xmm4, %xmm7; \ + pandn %xmm6, %xmm5; \ + por %xmm4, %xmm6; \ + \ + movdqa %xmm1, %xmm4; \ + \ + \ + movdqa %xmm4, %xmm2; \ + pshufd %xmm5, %xmm3, 0xe4; \ + \ + psllq %xmm3, 4; \ + psrlq %xmm4, 4; \ + \ + movdqa %xmm6, %xmm7; \ + pand %xmm2, %xmm7; \ + pandn %xmm6, %xmm3; \ + por %xmm2, %xmm6; \ + \ + movdqa %xmm6, %xmm7; \ + pand %xmm4, %xmm7; \ + pandn %xmm6, %xmm5; \ + por %xmm4, %xmm6; \ + \ + movdqa %xmm3, %xmm4; \ + \ + punpck(bw, 0, 2, 1, 3, 4, 6);\ + +// output +// low 32 bits 0 (4 bits packed) == 1.3 0.3 1.2 0.2 1.1 0.1 1.0 0.0 +// low 32 bits 4 (4 bits packed) == 1.19 0.19 1.18 0.18 1.17 0.17 1.16 0.16 +// low 32 bits 2 (4 bits packed) == 3.3 2.3 3.2 2.2 3.1 2.1 3.0 2.0 +// low 32 bits 6 (4 bits packed) == 3.19 2.19 3.18 2.18 3.17 2.17 3.16 2.16 + + +// +// swizzling +// + +// +// SwizzleBlock32 +// + +.globl SwizzleBlock32_sse2 + .type SwizzleBlock32_sse2, @function +SwizzleBlock32_sse2: + + push %esi + push %edi + + // save dst + mov %edi, %ecx + // save src + mov %esi, %edx + // get pitch + mov %edx, [%esp+4+8] + mov %ecx, 4 + + // get WriteMask + mov %eax, [%esp+8+8] + cmp %eax, 0xffffffff + jne SwizzleBlock32_sse2_2 + + .align 16 +SwizzleBlock32_sse2_1: + movdqa %xmm0, [%esi] + movdqa %xmm4, [%esi+16] + movdqa %xmm1, [%esi+%edx] + movdqa %xmm5, [%esi+%edx+16] + + // 64bits interleave 1&0 -> 2&0 + // 64bits interleave 5&4 -> 6&4 + punpck(qdq, 0, 4, 1, 5, 2, 6) + + movntps [%edi+16*0], %xmm0 + movntps [%edi+16*1], %xmm2 + movntps [%edi+16*2], %xmm4 + movntps [%edi+16*3], %xmm6 + + // update ptr + lea %esi, [%esi+%edx*2] + add %edi, 64 + + dec %ecx + jnz SwizzleBlock32_sse2_1 + + pop %edi + pop %esi + + ret 8 + +SwizzleBlock32_sse2_2: + + // WriteMask: 32bits to 4*32bits + movd %xmm7, %eax + pshufd %xmm7, %xmm7, 0 + + .align 16 +SwizzleBlock32_sse2_3: + movdqa %xmm0, [%esi] + movdqa %xmm4, [%esi+16] + movdqa %xmm1, [%esi+%edx] + movdqa %xmm5, [%esi+%edx+16] + + // 64bits interleave 1&0 -> 2&0 + // 64bits interleave 5&4 -> 6&4 + punpck(qdq, 0, 4, 1, 5, 2, 6) + + // save a mask copy + movdqa %xmm3, %xmm7 + pshufd %xmm5, %xmm7, 0xe4 + + // *dst & ~WriteMask + pandn %xmm3, [%edi+16*0] + // *src & WriteMask + pand %xmm0, %xmm7 + // Final value to save + por %xmm0, %xmm3 + movntps [%edi+16*0], %xmm0 + + pandn %xmm5, [%edi+16*1] + pand %xmm2, %xmm7 + por %xmm2, %xmm5 + movntps [%edi+16*1], %xmm2 + + movdqa %xmm3, %xmm7 + pshufd %xmm5, %xmm7, 0xe4 + + pandn %xmm3, [%edi+16*2] + pand %xmm4, %xmm7 + por %xmm4, %xmm3 + movntps [%edi+16*2], %xmm4 + + pandn %xmm5, [%edi+16*3] + pand %xmm6, %xmm7 + por %xmm6, %xmm5 + movntps [%edi+16*3], %xmm6 + + // update ptr + lea %esi, [%esi+%edx*2] + add %edi, 64 + + dec %ecx + jnz SwizzleBlock32_sse2_3 + + pop %edi + pop %esi + + ret 8 + +// +// SwizzleBlock16 +// + +.globl SwizzleBlock16_sse2 + .type SwizzleBlock16_sse2, @function +SwizzleBlock16_sse2: + + push %ebx + + // srcpitch + mov %ebx, [%esp+4+4] + mov %eax, 4 + + .align 16 +SwizzleBlock16_sse2_1: + movdqa %xmm0, [%edx] + movdqa %xmm1, [%edx+16] + movdqa %xmm2, [%edx+%ebx] + movdqa %xmm3, [%edx+%ebx+16] + + // 16bits interleave 1&0 -> 4&0 + // 16bits interleave 3&2 -> 6&2 + punpck(wd, 0, 2, 1, 3, 4, 6) + // 64bits interleave 2&0 -> 1&0 + // 64bits interleave 6&4 -> 5&4 + punpck(qdq, 0, 4, 2, 6, 1, 5) + + movntps [%ecx+16*0], %xmm0 + movntps [%ecx+16*1], %xmm1 + movntps [%ecx+16*2], %xmm4 + movntps [%ecx+16*3], %xmm5 + + // update ptr + lea %edx, [%edx+%ebx*2] + add %ecx, 64 + + dec %eax + jnz SwizzleBlock16_sse2_1 + + pop %ebx + + ret 4 + +// +// SwizzleBlock8 +// + +.globl SwizzleBlock8_sse2 + .type SwizzleBlock8_sse2, @function +SwizzleBlock8_sse2: + + push %ebx + + // load srcpitch + mov %ebx, [%esp+4+4] + // basic counter + mov %eax, 2 + + .align 16 +SwizzleBlock8_sse2_1: + // col 0, 2 + + movdqa %xmm0, [%edx] + movdqa %xmm2, [%edx+%ebx] + // update src pointer + lea %edx, [%edx+%ebx*2] + + // 2 3 0 1 + pshufd %xmm1, [%edx], 0xb1 + pshufd %xmm3, [%edx+%ebx], 0xb1 + // update src pointer + lea %edx, [%edx+%ebx*2] + + // 8bits interleave 1&0 -> 4&0 + // 8bits interleave 3&2 -> 6&2 + punpck(bw, 0, 2, 1, 3, 4, 6) + // 16bits interleave 4&0 -> 1&0 + // 16bits interleave 6&2 -> 3&2 + punpck(wd, 0, 2, 4, 6, 1, 3) + // 64bits interleave 2&0 -> 4&0 + // 64bits interleave 3&1 -> 5&1 + punpck(qdq, 0, 1, 2, 3, 4, 5) + + movntps [%ecx+16*0], %xmm0 + movntps [%ecx+16*1], %xmm4 + movntps [%ecx+16*2], %xmm1 + movntps [%ecx+16*3], %xmm5 + + // col 1, 3 (same as previous column) + + // 2 3 0 1 + pshufd %xmm0, [%edx], 0xb1 + pshufd %xmm2, [%edx+%ebx], 0xb1 + // update src pointer + lea %edx, [%edx+%ebx*2] + + movdqa %xmm1, [%edx] + movdqa %xmm3, [%edx+%ebx] + // update src pointer + lea %edx, [%edx+%ebx*2] + + // 8bits interleave 1&0 -> 4&0 + // 8bits interleave 3&2 -> 6&2 + punpck(bw, 0, 2, 1, 3, 4, 6) + // 16bits interleave 4&0 -> 1&0 + // 16bits interleave 6&2 -> 3&2 + punpck(wd, 0, 2, 4, 6, 1, 3) + // 64bits interleave 2&0 -> 4&0 + // 64bits interleave 3&1 -> 5&1 + punpck(qdq, 0, 1, 2, 3, 4, 5) + + movntps [%ecx+16*4], %xmm0 + movntps [%ecx+16*5], %xmm4 + movntps [%ecx+16*6], %xmm1 + movntps [%ecx+16*7], %xmm5 + + // update dst pointer + add %ecx, 128 + + dec %eax + jnz SwizzleBlock8_sse2_1 + + pop %ebx + + ret 4 + +// +// SwizzleBlock4 +// + +.globl SwizzleBlock4_sse2 + .type SwizzleBlock4_sse2, @function +SwizzleBlock4_sse2: + + push %ebx + + // load 4 0x0F0F0F0F + mov %eax, 0xf0f0f0f + movd %xmm7, %eax + pshufd %xmm7, %xmm7, 0 + + // load srcpitch + mov %ebx, [%esp+4+4] + mov %eax, 2 + + .align 16 +SwizzleBlock4_sse2_1: + // col 0, 2 + + movdqa %xmm0, [%edx] + movdqa %xmm2, [%edx+%ebx] + //update src pointer + lea %edx, [%edx+%ebx*2] + + movdqa %xmm1, [%edx] + movdqa %xmm3, [%edx+%ebx] + // update src pointer + lea %edx, [%edx+%ebx*2] + + // - - - - 2 3 0 1 + pshuflw %xmm1, %xmm1, 0xb1 + pshuflw %xmm3, %xmm3, 0xb1 + // 6 7 4 5 - - - - + pshufhw %xmm1, %xmm1, 0xb1 + pshufhw %xmm3, %xmm3, 0xb1 + + // 4bits interleave 1&0 -> 4&0 + // 4bits interleave 3&2 -> 6&2 + punpcknb + // 8bits interleave 4&0 -> 1&0 + // 8bits interleave 6&2 -> 3&2 + punpck(bw, 0, 2, 4, 6, 1, 3) + // 8bits interleave 1&0 -> 4&0 + // 8bits interleave 3&2 -> 6&2 + punpck(bw, 0, 2, 1, 3, 4, 6) + // 64bits interleave 2&0 -> 1&0 + // 64bits interleave 6&4 -> 3&4 + punpck(qdq, 0, 4, 2, 6, 1, 3) + + movntps [%ecx+16*0], %xmm0 + movntps [%ecx+16*1], %xmm1 + movntps [%ecx+16*2], %xmm4 + movntps [%ecx+16*3], %xmm3 + + // col 1, 3 (same as previous column) + + movdqa %xmm0, [%edx] + movdqa %xmm2, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + movdqa %xmm1, [%edx] + movdqa %xmm3, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + pshuflw %xmm0, %xmm0, 0xb1 + pshuflw %xmm2, %xmm2, 0xb1 + pshufhw %xmm0, %xmm0, 0xb1 + pshufhw %xmm2, %xmm2, 0xb1 + + punpcknb + punpck(bw, 0, 2, 4, 6, 1, 3) + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 3) + + movntps [%ecx+16*4], %xmm0 + movntps [%ecx+16*5], %xmm1 + movntps [%ecx+16*6], %xmm4 + movntps [%ecx+16*7], %xmm3 + + add %ecx, 128 + + dec %eax + jnz SwizzleBlock4_sse2_1 + + pop %ebx + + ret 4 + +// +// swizzling with unaligned reads +// Same functions as a above with movdqu instead of movdqa for the reads +// Movdqu is as fast as movdqa with aligned address... So do not bother, directly +// use movdqu +// + +// +// SwizzleBlock32u +// + +.globl SwizzleBlock32u_sse2 + .type SwizzleBlock32u_sse2, @function +SwizzleBlock32u_sse2: + + push %esi + push %edi + + mov %edi, %ecx + mov %esi, %edx + mov %edx, [%esp+4+8] + mov %ecx, 4 + + mov %eax, [%esp+8+8] + cmp %eax, 0xffffffff + jne SwizzleBlock32u_sse2_2 + + .align 16 +SwizzleBlock32u_sse2_1: + movdqu %xmm0, [%esi] + movdqu %xmm4, [%esi+16] + movdqu %xmm1, [%esi+%edx] + movdqu %xmm5, [%esi+%edx+16] + + punpck(qdq, 0, 4, 1, 5, 2, 6) + + movntps [%edi+16*0], %xmm0 + movntps [%edi+16*1], %xmm2 + movntps [%edi+16*2], %xmm4 + movntps [%edi+16*3], %xmm6 + + lea %esi, [%esi+%edx*2] + add %edi, 64 + + dec %ecx + jnz SwizzleBlock32u_sse2_1 + + pop %edi + pop %esi + + ret 8 + +SwizzleBlock32u_sse2_2: + + movd %xmm7, %eax + pshufd %xmm7, %xmm7, 0 + + .align 16 +SwizzleBlock32u_sse2_3: + movdqu %xmm0, [%esi] + movdqu %xmm4, [%esi+16] + movdqu %xmm1, [%esi+%edx] + movdqu %xmm5, [%esi+%edx+16] + + punpck(qdq, 0, 4, 1, 5, 2, 6) + + movdqa %xmm3, %xmm7 + pshufd %xmm5, %xmm7, 0xe4 + + pandn %xmm3, [%edi+16*0] + pand %xmm0, %xmm7 + por %xmm0, %xmm3 + movdqa [%edi+16*0], %xmm0 + + pandn %xmm5, [%edi+16*1] + pand %xmm2, %xmm7 + por %xmm2, %xmm5 + movdqa [%edi+16*1], %xmm2 + + movdqa %xmm3, %xmm7 + pshufd %xmm5, %xmm7, 0xe4 + + pandn %xmm3, [%edi+16*2] + pand %xmm4, %xmm7 + por %xmm4, %xmm3 + movdqa [%edi+16*2], %xmm4 + + pandn %xmm5, [%edi+16*3] + pand %xmm6, %xmm7 + por %xmm6, %xmm5 + movdqa [%edi+16*3], %xmm6 + + lea %esi, [%esi+%edx*2] + add %edi, 64 + + dec %ecx + jnz SwizzleBlock32u_sse2_3 + + pop %edi + pop %esi + + ret 8 + +// +// SwizzleBlock16u +// + +.globl SwizzleBlock16u_sse2 + .type SwizzleBlock16u_sse2, @function +SwizzleBlock16u_sse2: + + push %ebx + + mov %ebx, [%esp+4+4] + mov %eax, 4 + + .align 16 +SwizzleBlock16u_sse2_1: + movdqu %xmm0, [%edx] + movdqu %xmm1, [%edx+16] + movdqu %xmm2, [%edx+%ebx] + movdqu %xmm3, [%edx+%ebx+16] + + punpck(wd, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 5) + + movntps [%ecx+16*0], %xmm0 + movntps [%ecx+16*1], %xmm1 + movntps [%ecx+16*2], %xmm4 + movntps [%ecx+16*3], %xmm5 + + lea %edx, [%edx+%ebx*2] + add %ecx, 64 + + dec %eax + jnz SwizzleBlock16u_sse2_1 + + pop %ebx + + ret 4 + +// +// SwizzleBlock8u +// + +.globl SwizzleBlock8u_sse2 + .type SwizzleBlock8u_sse2, @function +SwizzleBlock8u_sse2: + + push %ebx + + mov %ebx, [%esp+4+4] + mov %eax, 2 + + .align 16 +SwizzleBlock8u_sse2_1: + // col 0, 2 + + movdqu %xmm0, [%edx] + movdqu %xmm2, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + movdqu %xmm1, [%edx] + movdqu %xmm3, [%edx+%ebx] + pshufd %xmm1, %xmm1, 0xb1 + pshufd %xmm3, %xmm3, 0xb1 + lea %edx, [%edx+%ebx*2] + + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(wd, 0, 2, 4, 6, 1, 3) + punpck(qdq, 0, 1, 2, 3, 4, 5) + + movntps [%ecx+16*0], %xmm0 + movntps [%ecx+16*1], %xmm4 + movntps [%ecx+16*2], %xmm1 + movntps [%ecx+16*3], %xmm5 + + // col 1, 3 + + movdqu %xmm0, [%edx] + movdqu %xmm2, [%edx+%ebx] + pshufd %xmm0, %xmm0, 0xb1 + pshufd %xmm2, %xmm2, 0xb1 + lea %edx, [%edx+%ebx*2] + + movdqu %xmm1, [%edx] + movdqu %xmm3, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(wd, 0, 2, 4, 6, 1, 3) + punpck(qdq, 0, 1, 2, 3, 4, 5) + + movntps [%ecx+16*4], %xmm0 + movntps [%ecx+16*5], %xmm4 + movntps [%ecx+16*6], %xmm1 + movntps [%ecx+16*7], %xmm5 + + add %ecx, 128 + + dec %eax + jnz SwizzleBlock8u_sse2_1 + + pop %ebx + + ret 4 + +// +// SwizzleBlock4u +// + +.globl SwizzleBlock4u_sse2 + .type SwizzleBlock4u_sse2, @function +SwizzleBlock4u_sse2: + + push %ebx + + mov %eax, 0xf0f0f0f + movd %xmm7, %eax + pshufd %xmm7, %xmm7, 0 + + mov %ebx, [%esp+4+4] + mov %eax, 2 + + .align 16 +SwizzleBlock4u_sse2_1: + // col 0, 2 + + movdqu %xmm0, [%edx] + movdqu %xmm2, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + movdqu %xmm1, [%edx] + movdqu %xmm3, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + pshuflw %xmm1, %xmm1, 0xb1 + pshuflw %xmm3, %xmm3, 0xb1 + pshufhw %xmm1, %xmm1, 0xb1 + pshufhw %xmm3, %xmm3, 0xb1 + + punpcknb + punpck(bw, 0, 2, 4, 6, 1, 3) + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 3) + + movntps [%ecx+16*0], %xmm0 + movntps [%ecx+16*1], %xmm1 + movntps [%ecx+16*2], %xmm4 + movntps [%ecx+16*3], %xmm3 + + // col 1, 3 + + movdqu %xmm0, [%edx] + movdqu %xmm2, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + movdqu %xmm1, [%edx] + movdqu %xmm3, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + pshuflw %xmm0, %xmm0, 0xb1 + pshuflw %xmm2, %xmm2, 0xb1 + pshufhw %xmm0, %xmm0, 0xb1 + pshufhw %xmm2, %xmm2, 0xb1 + + punpcknb + punpck(bw, 0, 2, 4, 6, 1, 3) + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 3) + + movntps [%ecx+16*4], %xmm0 + movntps [%ecx+16*5], %xmm1 + movntps [%ecx+16*6], %xmm4 + movntps [%ecx+16*7], %xmm3 + + add %ecx, 128 + + dec %eax + jnz SwizzleBlock4u_sse2_1 + + pop %ebx + + ret 4 + +#endif + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/plugins/zzogl-pg-cg/opengl/x86-32.asm b/plugins/zzogl-pg-cg/opengl/x86-32.asm new file mode 100644 index 000000000..0531e9542 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/x86-32.asm @@ -0,0 +1,652 @@ +; Copyright (C) 2003-2005 Gabest +; http://www.gabest.org +; +; This Program is free software; you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 2, or (at your option) +; any later version. +; +; This Program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with GNU Make; see the file COPYING. If not, write to +; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +; http://www.gnu.org/copyleft/gpl.html +; +; + .686 + .model flat + .mmx + .xmm + + .const + + __uvmin DD 0d01502f9r ; -1e+010 + __uvmax DD 0501502f9r ; +1e+010 + + .code + +; +; swizzling +; + +punpck macro op, sd0, sd2, s1, s3, d1, d3 + + movdqa @CatStr(xmm, %d1), @CatStr(xmm, %sd0) + pshufd @CatStr(xmm, %d3), @CatStr(xmm, %sd2), 0e4h + + @CatStr(punpckl, op) @CatStr(xmm, %sd0), @CatStr(xmm, %s1) + @CatStr(punpckh, op) @CatStr(xmm, %d1), @CatStr(xmm, %s1) + @CatStr(punpckl, op) @CatStr(xmm, %sd2), @CatStr(xmm, %s3) + @CatStr(punpckh, op) @CatStr(xmm, %d3), @CatStr(xmm, %s3) + + endm + +punpcknb macro + + movdqa xmm4, xmm0 + pshufd xmm5, xmm1, 0e4h + + psllq xmm1, 4 + psrlq xmm4, 4 + + movdqa xmm6, xmm7 + pand xmm0, xmm7 + pandn xmm6, xmm1 + por xmm0, xmm6 + + movdqa xmm6, xmm7 + pand xmm4, xmm7 + pandn xmm6, xmm5 + por xmm4, xmm6 + + movdqa xmm1, xmm4 + + movdqa xmm4, xmm2 + pshufd xmm5, xmm3, 0e4h + + psllq xmm3, 4 + psrlq xmm4, 4 + + movdqa xmm6, xmm7 + pand xmm2, xmm7 + pandn xmm6, xmm3 + por xmm2, xmm6 + + movdqa xmm6, xmm7 + pand xmm4, xmm7 + pandn xmm6, xmm5 + por xmm4, xmm6 + + movdqa xmm3, xmm4 + + punpck bw, 0, 2, 1, 3, 4, 6 + + endm + + +; +; swizzling +; + +; +; SwizzleBlock32 +; + +@SwizzleBlock32_sse2@16 proc public + + + push esi + push edi + + mov edi, ecx + mov esi, edx + mov edx, [esp+4+8] + mov ecx, 4 + + mov eax, [esp+8+8] + cmp eax, 0ffffffffh + jne SwizzleBlock32_sse2@WM + + align 16 +@@: + movdqa xmm0, [esi] + movdqa xmm4, [esi+16] + movdqa xmm1, [esi+edx] + movdqa xmm5, [esi+edx+16] + + punpck qdq, 0, 4, 1, 5, 2, 6 + + movntps [edi+16*0], xmm0 + movntps [edi+16*1], xmm2 + movntps [edi+16*2], xmm4 + movntps [edi+16*3], xmm6 + + lea esi, [esi+edx*2] + add edi, 64 + + dec ecx + jnz @B + + pop edi + pop esi + + ret 8 + +SwizzleBlock32_sse2@WM: + + movd xmm7, eax + pshufd xmm7, xmm7, 0 + + align 16 +@@: + movdqa xmm0, [esi] + movdqa xmm4, [esi+16] + movdqa xmm1, [esi+edx] + movdqa xmm5, [esi+edx+16] + + punpck qdq, 0, 4, 1, 5, 2, 6 + + movdqa xmm3, xmm7 + pshufd xmm5, xmm7, 0e4h + + pandn xmm3, [edi+16*0] + pand xmm0, xmm7 + por xmm0, xmm3 + movntps [edi+16*0], xmm0 + + pandn xmm5, [edi+16*1] + pand xmm2, xmm7 + por xmm2, xmm5 + movntps [edi+16*1], xmm2 + + movdqa xmm3, xmm7 + pshufd xmm5, xmm7, 0e4h + + pandn xmm3, [edi+16*2] + pand xmm4, xmm7 + por xmm4, xmm3 + movntps [edi+16*2], xmm4 + + pandn xmm5, [edi+16*3] + pand xmm6, xmm7 + por xmm6, xmm5 + movntps [edi+16*3], xmm6 + + lea esi, [esi+edx*2] + add edi, 64 + + dec ecx + jnz @B + + pop edi + pop esi + + ret 8 + +@SwizzleBlock32_sse2@16 endp + +; +; SwizzleBlock16 +; + +@SwizzleBlock16_sse2@12 proc public + + push ebx + + mov ebx, [esp+4+4] + mov eax, 4 + + align 16 +@@: + movdqa xmm0, [edx] + movdqa xmm1, [edx+16] + movdqa xmm2, [edx+ebx] + movdqa xmm3, [edx+ebx+16] + + punpck wd, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 5 + + movntps [ecx+16*0], xmm0 + movntps [ecx+16*1], xmm1 + movntps [ecx+16*2], xmm4 + movntps [ecx+16*3], xmm5 + + lea edx, [edx+ebx*2] + add ecx, 64 + + dec eax + jnz @B + + pop ebx + + ret 4 + +@SwizzleBlock16_sse2@12 endp + +; +; SwizzleBlock8 +; + +@SwizzleBlock8_sse2@12 proc public + + push ebx + + mov ebx, [esp+4+4] + mov eax, 2 + + align 16 +@@: + ; col 0, 2 + + movdqa xmm0, [edx] + movdqa xmm2, [edx+ebx] + lea edx, [edx+ebx*2] + + pshufd xmm1, [edx], 0b1h + pshufd xmm3, [edx+ebx], 0b1h + lea edx, [edx+ebx*2] + + punpck bw, 0, 2, 1, 3, 4, 6 + punpck wd, 0, 2, 4, 6, 1, 3 + punpck qdq, 0, 1, 2, 3, 4, 5 + + movntps [ecx+16*0], xmm0 + movntps [ecx+16*1], xmm4 + movntps [ecx+16*2], xmm1 + movntps [ecx+16*3], xmm5 + + ; col 1, 3 + + pshufd xmm0, [edx], 0b1h + pshufd xmm2, [edx+ebx], 0b1h + lea edx, [edx+ebx*2] + + movdqa xmm1, [edx] + movdqa xmm3, [edx+ebx] + lea edx, [edx+ebx*2] + + punpck bw, 0, 2, 1, 3, 4, 6 + punpck wd, 0, 2, 4, 6, 1, 3 + punpck qdq, 0, 1, 2, 3, 4, 5 + + movntps [ecx+16*4], xmm0 + movntps [ecx+16*5], xmm4 + movntps [ecx+16*6], xmm1 + movntps [ecx+16*7], xmm5 + + add ecx, 128 + + dec eax + jnz @B + + pop ebx + + ret 4 + +@SwizzleBlock8_sse2@12 endp + +; +; SwizzleBlock4 +; + +@SwizzleBlock4_sse2@12 proc public + + push ebx + + mov eax, 0f0f0f0fh + movd xmm7, eax + pshufd xmm7, xmm7, 0 + + mov ebx, [esp+4+4] + mov eax, 2 + + align 16 +@@: + ; col 0, 2 + + movdqa xmm0, [edx] + movdqa xmm2, [edx+ebx] + lea edx, [edx+ebx*2] + + movdqa xmm1, [edx] + movdqa xmm3, [edx+ebx] + lea edx, [edx+ebx*2] + + pshuflw xmm1, xmm1, 0b1h + pshuflw xmm3, xmm3, 0b1h + pshufhw xmm1, xmm1, 0b1h + pshufhw xmm3, xmm3, 0b1h + + punpcknb + punpck bw, 0, 2, 4, 6, 1, 3 + punpck bw, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 3 + + movntps [ecx+16*0], xmm0 + movntps [ecx+16*1], xmm1 + movntps [ecx+16*2], xmm4 + movntps [ecx+16*3], xmm3 + + ; col 1, 3 + + movdqa xmm0, [edx] + movdqa xmm2, [edx+ebx] + lea edx, [edx+ebx*2] + + movdqa xmm1, [edx] + movdqa xmm3, [edx+ebx] + lea edx, [edx+ebx*2] + + pshuflw xmm0, xmm0, 0b1h + pshuflw xmm2, xmm2, 0b1h + pshufhw xmm0, xmm0, 0b1h + pshufhw xmm2, xmm2, 0b1h + + punpcknb + punpck bw, 0, 2, 4, 6, 1, 3 + punpck bw, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 3 + + movntps [ecx+16*4], xmm0 + movntps [ecx+16*5], xmm1 + movntps [ecx+16*6], xmm4 + movntps [ecx+16*7], xmm3 + + add ecx, 128 + + dec eax + jnz @B + + pop ebx + + ret 4 + +@SwizzleBlock4_sse2@12 endp + +; +; swizzling with unaligned reads +; + +; +; SwizzleBlock32u +; + +@SwizzleBlock32u_sse2@16 proc public + + push esi + push edi + + mov edi, ecx + mov esi, edx + mov edx, [esp+4+8] + mov ecx, 4 + + mov eax, [esp+8+8] + cmp eax, 0ffffffffh + jne SwizzleBlock32u_sse2@WM + + align 16 +@@: + movdqu xmm0, [esi] + movdqu xmm4, [esi+16] + movdqu xmm1, [esi+edx] + movdqu xmm5, [esi+edx+16] + + punpck qdq, 0, 4, 1, 5, 2, 6 + + movntps [edi+16*0], xmm0 + movntps [edi+16*1], xmm2 + movntps [edi+16*2], xmm4 + movntps [edi+16*3], xmm6 + + lea esi, [esi+edx*2] + add edi, 64 + + dec ecx + jnz @B + + pop edi + pop esi + + ret 8 + +SwizzleBlock32u_sse2@WM: + + movd xmm7, eax + pshufd xmm7, xmm7, 0 + + align 16 +@@: + movdqu xmm0, [esi] + movdqu xmm4, [esi+16] + movdqu xmm1, [esi+edx] + movdqu xmm5, [esi+edx+16] + + punpck qdq, 0, 4, 1, 5, 2, 6 + + movdqa xmm3, xmm7 + pshufd xmm5, xmm7, 0e4h + + pandn xmm3, [edi+16*0] + pand xmm0, xmm7 + por xmm0, xmm3 + movdqa [edi+16*0], xmm0 + + pandn xmm5, [edi+16*1] + pand xmm2, xmm7 + por xmm2, xmm5 + movdqa [edi+16*1], xmm2 + + movdqa xmm3, xmm7 + pshufd xmm5, xmm7, 0e4h + + pandn xmm3, [edi+16*2] + pand xmm4, xmm7 + por xmm4, xmm3 + movdqa [edi+16*2], xmm4 + + pandn xmm5, [edi+16*3] + pand xmm6, xmm7 + por xmm6, xmm5 + movdqa [edi+16*3], xmm6 + + lea esi, [esi+edx*2] + add edi, 64 + + dec ecx + jnz @B + + pop edi + pop esi + + ret 8 + +@SwizzleBlock32u_sse2@16 endp + +; +; SwizzleBlock16u +; + +@SwizzleBlock16u_sse2@12 proc public + + push ebx + + mov ebx, [esp+4+4] + mov eax, 4 + + align 16 +@@: + movdqu xmm0, [edx] + movdqu xmm1, [edx+16] + movdqu xmm2, [edx+ebx] + movdqu xmm3, [edx+ebx+16] + + punpck wd, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 5 + + movntps [ecx+16*0], xmm0 + movntps [ecx+16*1], xmm1 + movntps [ecx+16*2], xmm4 + movntps [ecx+16*3], xmm5 + + lea edx, [edx+ebx*2] + add ecx, 64 + + dec eax + jnz @B + + pop ebx + + ret 4 + +@SwizzleBlock16u_sse2@12 endp + +; +; SwizzleBlock8u +; + +@SwizzleBlock8u_sse2@12 proc public + + push ebx + + mov ebx, [esp+4+4] + mov eax, 2 + + align 16 +@@: + ; col 0, 2 + + movdqu xmm0, [edx] + movdqu xmm2, [edx+ebx] + lea edx, [edx+ebx*2] + + movdqu xmm1, [edx] + movdqu xmm3, [edx+ebx] + pshufd xmm1, xmm1, 0b1h + pshufd xmm3, xmm3, 0b1h + lea edx, [edx+ebx*2] + + punpck bw, 0, 2, 1, 3, 4, 6 + punpck wd, 0, 2, 4, 6, 1, 3 + punpck qdq, 0, 1, 2, 3, 4, 5 + + movntps [ecx+16*0], xmm0 + movntps [ecx+16*1], xmm4 + movntps [ecx+16*2], xmm1 + movntps [ecx+16*3], xmm5 + + ; col 1, 3 + + movdqu xmm0, [edx] + movdqu xmm2, [edx+ebx] + pshufd xmm0, xmm0, 0b1h + pshufd xmm2, xmm2, 0b1h + lea edx, [edx+ebx*2] + + movdqu xmm1, [edx] + movdqu xmm3, [edx+ebx] + lea edx, [edx+ebx*2] + + punpck bw, 0, 2, 1, 3, 4, 6 + punpck wd, 0, 2, 4, 6, 1, 3 + punpck qdq, 0, 1, 2, 3, 4, 5 + + movntps [ecx+16*4], xmm0 + movntps [ecx+16*5], xmm4 + movntps [ecx+16*6], xmm1 + movntps [ecx+16*7], xmm5 + + add ecx, 128 + + dec eax + jnz @B + + pop ebx + + ret 4 + +@SwizzleBlock8u_sse2@12 endp + +; +; SwizzleBlock4u +; + +@SwizzleBlock4u_sse2@12 proc public + + push ebx + + mov eax, 0f0f0f0fh + movd xmm7, eax + pshufd xmm7, xmm7, 0 + + mov ebx, [esp+4+4] + mov eax, 2 + + align 16 +@@: + ; col 0, 2 + + movdqu xmm0, [edx] + movdqu xmm2, [edx+ebx] + lea edx, [edx+ebx*2] + + movdqu xmm1, [edx] + movdqu xmm3, [edx+ebx] + lea edx, [edx+ebx*2] + + pshuflw xmm1, xmm1, 0b1h + pshuflw xmm3, xmm3, 0b1h + pshufhw xmm1, xmm1, 0b1h + pshufhw xmm3, xmm3, 0b1h + + punpcknb + punpck bw, 0, 2, 4, 6, 1, 3 + punpck bw, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 3 + + movntps [ecx+16*0], xmm0 + movntps [ecx+16*1], xmm1 + movntps [ecx+16*2], xmm4 + movntps [ecx+16*3], xmm3 + + ; col 1, 3 + + movdqu xmm0, [edx] + movdqu xmm2, [edx+ebx] + lea edx, [edx+ebx*2] + + movdqu xmm1, [edx] + movdqu xmm3, [edx+ebx] + lea edx, [edx+ebx*2] + + pshuflw xmm0, xmm0, 0b1h + pshuflw xmm2, xmm2, 0b1h + pshufhw xmm0, xmm0, 0b1h + pshufhw xmm2, xmm2, 0b1h + + punpcknb + punpck bw, 0, 2, 4, 6, 1, 3 + punpck bw, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 3 + + movntps [ecx+16*4], xmm0 + movntps [ecx+16*5], xmm1 + movntps [ecx+16*6], xmm4 + movntps [ecx+16*7], xmm3 + + add ecx, 128 + + dec eax + jnz @B + + pop ebx + + ret 4 + +@SwizzleBlock4u_sse2@12 endp + + end \ No newline at end of file diff --git a/plugins/zzogl-pg-cg/opengl/x86.cpp b/plugins/zzogl-pg-cg/opengl/x86.cpp new file mode 100644 index 000000000..c798151b8 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/x86.cpp @@ -0,0 +1,1366 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "GS.h" +#include "Mem.h" +#include "x86.h" + +#if defined(ZEROGS_SSE2) +#include +#endif + +// swizzling + +//These were only used in the old version of RESOLVE_32_BITS. Keeping for reference. +#if 0 + +/* FrameSwizzleBlock32 */ +void __fastcall FrameSwizzleBlock32_c(u32* dst, u32* src, int srcpitch, u32 WriteMask) +{ + u32* d = &g_columnTable32[0][0]; + + if (WriteMask == 0xffffffff) + { + for(int i = 0; i < 8; ++i, d += 8) + { + for(int j = 0; j < 8; ++j) + { + dst[d[j]] = (src[j]); + } + src += srcpitch; + } + } + else + { + for(int i = 0; i < 8; ++i, d += 8) + { + for(int j = 0; j < 8; ++j) + { + dst[d[j]] = ((src[j])&WriteMask)|(dst[d[j]]&~WriteMask); + } + src += srcpitch; + } + } +} + +void __fastcall FrameSwizzleBlock32A2_c(u32* dst, u32* src, int srcpitch, u32 WriteMask) +{ + u32* d = &g_columnTable32[0][0]; + + if( WriteMask == 0xffffffff ) { + for(int i = 0; i < 8; ++i, d += 8) { + for(int j = 0; j < 8; ++j) { + dst[d[j]] = ((src[2*j] + src[2*j+1]) >> 1); + } + src += srcpitch; + } + } + else { + for(int i = 0; i < 8; ++i, d += 8) { + for(int j = 0; j < 8; ++j) { + dst[d[j]] = (((src[2*j] + src[2*j+1]) >> 1)&WriteMask)|(dst[d[j]]&~WriteMask); + } + src += srcpitch; + } + } +} + +void __fastcall FrameSwizzleBlock32A4_c(u32* dst, u32* src, int srcpitch, u32 WriteMask) +{ + u32* d = &g_columnTable32[0][0]; + + if( WriteMask == 0xffffffff ) { + for(int i = 0; i < 8; ++i, d += 8) { + for(int j = 0; j < 8; ++j) { + dst[d[j]] = ((src[2*j] + src[2*j+1] + src[2*j+srcpitch] + src[2*j+srcpitch+1]) >> 2); + } + src += srcpitch << 1; + } + } + else { + for(int i = 0; i < 8; ++i, d += 8) { + for(int j = 0; j < 8; ++j) { + dst[d[j]] = (((src[2*j] + src[2*j+1] + src[2*j+srcpitch] + src[2*j+srcpitch+1]) >> 2)&WriteMask)|(dst[d[j]]&~WriteMask); + } + src += srcpitch << 1; + } + } +} + +#define FrameSwizzleBlock24_c FrameSwizzleBlock32_c +#define FrameSwizzleBlock24A2_c FrameSwizzleBlock32A2_c +#define FrameSwizzleBlock24A4_c FrameSwizzleBlock32A4_c + +/* FrameSwizzleBlock16 */ +void __fastcall FrameSwizzleBlock16_c(u16* dst, u32* src, int srcpitch, u32 WriteMask) +{ + u32* d = &g_columnTable16[0][0]; + + if (WriteMask == 0xffff) + { + for(int i = 0; i < 8; ++i, d += 16) + { + for(int j = 0; j < 16; ++j) + { + u32 temp = (src[j]); + dst[d[j]] = RGBA32to16(temp); + } + src += srcpitch; + } + } + else + { + for(int i = 0; i < 8; ++i, d += 16) + { + for(int j = 0; j < 16; ++j) + { + u32 temp = (src[j]); + u32 dsrc = RGBA32to16(temp); + dst[d[j]] = (dsrc&WriteMask)|(dst[d[j]]&~WriteMask); + } + src += srcpitch; + } + } +} + +void __fastcall FrameSwizzleBlock16A2_c(u16* dst, u32* src, int srcpitch, u32 WriteMask) +{ + u32* d = &g_columnTable16[0][0]; + + if (WriteMask == 0xffff) + { + for(int i = 0; i < 8; ++i, d += 16) + { + for(int j = 0; j < 16; ++j) + { + u32 temp = ((src[2*j] + src[2*j+1]) >> 1); + dst[d[j]] = RGBA32to16(temp); + } + src += srcpitch; + } + } + else + { + for(int i = 0; i < 8; ++i, d += 16) + { + for(int j = 0; j < 16; ++j) + { + u32 temp = ((src[2*j] + src[2*j+1]) >> 1); + u32 dsrc = RGBA32to16(temp); + dst[d[j]] = (dsrc&WriteMask)|(dst[d[j]]&~WriteMask); + } + src += srcpitch; + } + } +} + +void __fastcall FrameSwizzleBlock16A4_c(u16* dst, u32* src, int srcpitch, u32 WriteMask) +{ + u32* d = &g_columnTable16[0][0]; + + if (WriteMask == 0xffff) + { + for(int i = 0; i < 8; ++i, d += 16) + { + for(int j = 0; j < 16; ++j) + { + u32 temp = ((src[2*j] + src[2*j+1] + src[2*j+srcpitch] + src[2*j+srcpitch+1]) >> 2); + dst[d[j]] = RGBA32to16(temp); + } + src += srcpitch << 1; + } + } + else + { + for(int i = 0; i < 8; ++i, d += 16) + { + for(int j = 0; j < 16; ++j) + { + u32 temp = ((src[2*j] + src[2*j+1] + src[2*j+srcpitch] + src[2*j+srcpitch+1]) >> 2); + u32 dsrc = RGBA32to16(temp); + dst[d[j]] = (dsrc&WriteMask)|(dst[d[j]]&~WriteMask); + } + src += srcpitch << 1; + } + } +} + + +/* Frame16SwizzleBlock32 */ +void __fastcall Frame16SwizzleBlock32_c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask) +{ + u32* d = &g_columnTable32[0][0]; + + if( WriteMask == 0xffffffff ) + { + for(int i = 0; i < 8; ++i, d += 8) + { + for(int j = 0; j < 8; ++j) + { + Vector_16F dsrc16 = (src[j]); + dst[d[j]] = Float16ToARGB(dsrc16); + } + src += srcpitch; + } + } + else + { + for(int i = 0; i < 8; ++i, d += 8) + { + for(int j = 0; j < 8; ++j) + { + Vector_16F dsrc16 = (src[j]); + u32 dsrc = Float16ToARGB(dsrc16); + dst[d[j]] = (dsrc&WriteMask)|(dst[d[j]]&~WriteMask); + } + src += srcpitch; + } + } + } + +void __fastcall Frame16SwizzleBlock32A2_c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask) +{ + u32* d = &g_columnTable32[0][0]; + + if( WriteMask == 0xffffffff ) + { + for(int i = 0; i < 8; ++i, d += 8) + { + for(int j = 0; j < 8; ++j) + { + Vector_16F dsrc16 = (src[2*j]); + dst[d[j]] = Float16ToARGB(dsrc16); + } + src += srcpitch; + } + } + else + { + for(int i = 0; i < 8; ++i, d += 8) + { + for(int j = 0; j < 8; ++j) + { + Vector_16F dsrc16 = (src[2*j]); + u32 dsrc = Float16ToARGB(dsrc16); + dst[d[j]] = (dsrc&WriteMask)|(dst[d[j]]&~WriteMask); + } + src += srcpitch; + } + } + } + +void __fastcall Frame16SwizzleBlock32A4_c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask) +{ + u32* d = &g_columnTable32[0][0]; + + if( WriteMask == 0xffffffff ) + { + for(int i = 0; i < 8; ++i, d += 8) + { + for(int j = 0; j < 8; ++j) + { + Vector_16F dsrc16 = (src[2*j]); + dst[d[j]] = Float16ToARGB(dsrc16); + } + src += srcpitch << 1; + } + } + else + { + for(int i = 0; i < 8; ++i, d += 8) + { + for(int j = 0; j < 8; ++j) + { + Vector_16F dsrc16 = (src[2*j]); + u32 dsrc = Float16ToARGB(dsrc16); + dst[d[j]] = (dsrc&WriteMask)|(dst[d[j]]&~WriteMask); + } + src += srcpitch << 1; + } + } + } + +/* Frame16SwizzleBlock32Z */ +void __fastcall Frame16SwizzleBlock32Z_c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask) +{ + u32* d = &g_columnTable32[0][0]; + if( WriteMask == 0xffffffff ) /* breaks KH text if not checked */ + { + for(int i = 0; i < 8; ++i, d += 8) + { + for(int j = 0; j < 8; ++j) + { + Vector_16F dsrc16 = (src[j]); + dst[d[j]] = Float16ToARGB_Z(dsrc16); + } + src += srcpitch; + } + } + else + { + for(int i = 0; i < 8; ++i, d += 8) + { + for(int j = 0; j < 8; ++j) + { + Vector_16F dsrc16 = (src[j]); + u32 dsrc = Float16ToARGB_Z(dsrc16); + dst[d[j]] = (dsrc&WriteMask)|(dst[d[j]]&~WriteMask); + } + src += srcpitch; + } + } + } + +void __fastcall Frame16SwizzleBlock32ZA2_c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask) +{ + u32* d = &g_columnTable32[0][0]; + if( WriteMask == 0xffffffff ) /* breaks KH text if not checked */ + { + for(int i = 0; i < 8; ++i, d += 8) + { + for(int j = 0; j < 8; ++j) + { + Vector_16F dsrc16 = (src[2*j]); + dst[d[j]] = Float16ToARGB_Z(dsrc16); + } + src += srcpitch; + } + } + else + { + for(int i = 0; i < 8; ++i, d += 8) + { + for(int j = 0; j < 8; ++j) + { + Vector_16F dsrc16 = (src[2*j]); + u32 dsrc = Float16ToARGB_Z(dsrc16); + dst[d[j]] = (dsrc&WriteMask)|(dst[d[j]]&~WriteMask); + } + src += srcpitch; + } + } + } + +void __fastcall Frame16SwizzleBlock32ZA4_c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask) +{ + u32* d = &g_columnTable32[0][0]; + if( WriteMask == 0xffffffff ) /* breaks KH text if not checked */ + { + for(int i = 0; i < 8; ++i, d += 8) + { + for(int j = 0; j < 8; ++j) + { + Vector_16F dsrc16 = (src[2*j]); + dst[d[j]] = Float16ToARGB_Z(dsrc16); + } + src += srcpitch << 1; + } + } + else + { + for(int i = 0; i < 8; ++i, d += 8) + { + for(int j = 0; j < 8; ++j) + { + Vector_16F dsrc16 = (src[2*j]); + u32 dsrc = Float16ToARGB_Z(dsrc16); + dst[d[j]] = (dsrc&WriteMask)|(dst[d[j]]&~WriteMask); + } + src += srcpitch << 1; + } + } + } + + + /* Frame16SwizzleBlock16 */ +void __fastcall Frame16SwizzleBlock16_c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask) +{ + u32* d = &g_columnTable16[0][0]; + + if ((WriteMask&0xfff8f8f8) == 0xfff8f8f8) + { + for(int i = 0; i < 8; ++i, d += 16) + { + for(int j = 0; j < 16; ++j) + { + Vector_16F dsrc16 = (src[j]); + dst[d[j]] = Float16ToARGB16(dsrc16); + } + src += srcpitch; + } + } + else + { + for(int i = 0; i < 8; ++i, d += 16) + { + for(int j = 0; j < 16; ++j) + { + Vector_16F dsrc16 = (src[j]); + u32 dsrc = Float16ToARGB16(dsrc16); + dst[d[j]] = (dsrc&WriteMask)|(dst[d[j]]&~WriteMask); + } + src += srcpitch; + } + } + } + +void __fastcall Frame16SwizzleBlock16A2_c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask) +{ + u32* d = &g_columnTable16[0][0]; + + if ((WriteMask&0xfff8f8f8) == 0xfff8f8f8) + { + for(int i = 0; i < 8; ++i, d += 16) + { + for(int j = 0; j < 16; ++j) + { + Vector_16F dsrc16 = (src[2*j]); + dst[d[j]] = Float16ToARGB16(dsrc16); + } + src += srcpitch; + } + } + else + { + for(int i = 0; i < 8; ++i, d += 16) + { + for(int j = 0; j < 16; ++j) + { + Vector_16F dsrc16 = (src[2*j]); + u32 dsrc = Float16ToARGB16(dsrc16); + dst[d[j]] = (dsrc&WriteMask)|(dst[d[j]]&~WriteMask); + } + src += srcpitch; + } + } + } + +void __fastcall Frame16SwizzleBlock16A4_c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask) +{ + u32* d = &g_columnTable16[0][0]; + + if ((WriteMask&0xfff8f8f8) == 0xfff8f8f8) + { + for(int i = 0; i < 8; ++i, d += 16) + { + for(int j = 0; j < 16; ++j) + { + Vector_16F dsrc16 = (src[2*j]); + dst[d[j]] = Float16ToARGB16(dsrc16); + } + src += srcpitch << 1; + } + } + else + { + for(int i = 0; i < 8; ++i, d += 16) + { + for(int j = 0; j < 16; ++j) + { + Vector_16F dsrc16 = (src[2*j]); + u32 dsrc = Float16ToARGB16(dsrc16); + dst[d[j]] = (dsrc&WriteMask)|(dst[d[j]]&~WriteMask); + } + src += srcpitch << 1; + } + } + } + + /* Frame16SwizzleBlock16Z */ +void __fastcall Frame16SwizzleBlock16Z_c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask) +{ + u32* d = &g_columnTable16[0][0]; + + for(int i = 0; i < 8; ++i, d += 16) + { + for(int j = 0; j < 16; ++j) + { + Vector_16F dsrc16 = (src[j]); + dst[d[j]] = Float16ToARGB16_Z(dsrc16); + } + src += srcpitch; + } +} + +void __fastcall Frame16SwizzleBlock16ZA2_c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask) +{ + u32* d = &g_columnTable16[0][0]; + + for(int i = 0; i < 8; ++i, d += 16) + { + for(int j = 0; j < 16; ++j) + { + Vector_16F dsrc16 = (src[2*j]); + dst[d[j]] = Float16ToARGB16_Z(dsrc16); + } + src += srcpitch; + } +} + +void __fastcall Frame16SwizzleBlock16ZA4_c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask) +{ + u32* d = &g_columnTable16[0][0]; + + for(int i = 0; i < 8; ++i, d += 16) + { + for(int j = 0; j < 16; ++j) + { + Vector_16F dsrc16 = (src[2*j]); + dst[d[j]] = Float16ToARGB16_Z(dsrc16); + } + src += srcpitch << 1; + } +} +#endif + +#ifdef ZEROGS_SSE2 + +//void __fastcall WriteCLUT_T16_I8_CSM1_sse2(u32* vm, u32* clut) +//{ +// __asm { +// mov eax, vm +// mov ecx, clut +// mov edx, 8 +// } +// +//Extract32x2: +// __asm { +// movdqa xmm0, qword ptr [eax] +// movdqa xmm1, qword ptr [eax+16] +// movdqa xmm2, qword ptr [eax+32] +// movdqa xmm3, qword ptr [eax+48] +// +// // rearrange +// pshuflw xmm0, xmm0, 0xd8 +// pshufhw xmm0, xmm0, 0xd8 +// pshuflw xmm1, xmm1, 0xd8 +// pshufhw xmm1, xmm1, 0xd8 +// pshuflw xmm2, xmm2, 0xd8 +// pshufhw xmm2, xmm2, 0xd8 +// pshuflw xmm3, xmm3, 0xd8 +// pshufhw xmm3, xmm3, 0xd8 +// +// movdqa xmm4, xmm0 +// movdqa xmm6, xmm2 +// +// shufps xmm0, xmm1, 0x88 +// shufps xmm2, xmm3, 0x88 +// +// shufps xmm4, xmm1, 0xdd +// shufps xmm6, xmm3, 0xdd +// +// pshufd xmm0, xmm0, 0xd8 +// pshufd xmm2, xmm2, 0xd8 +// pshufd xmm4, xmm4, 0xd8 +// pshufd xmm6, xmm6, 0xd8 +// +// // left column +// movhlps xmm1, xmm0 +// movlhps xmm0, xmm2 +// //movdqa xmm7, [ecx] +// +// movdqa [ecx], xmm0 +// shufps xmm1, xmm2, 0xe4 +// movdqa [ecx+16], xmm1 +// +// // right column +// movhlps xmm3, xmm4 +// movlhps xmm4, xmm6 +// movdqa [ecx+32], xmm4 +// shufps xmm3, xmm6, 0xe4 +// movdqa [ecx+48], xmm3 +// +// add eax, 16*4 +// add ecx, 16*8 +// sub edx, 1 +// cmp edx, 0 +// jne Extract32x2 +// } +//} + +#if 0 +extern "C" void __fastcall WriteCLUT_T32_I8_CSM1_sse2(u32* vm, u32* clut) +{ + __m128i* src = (__m128i*)vm; + __m128i* dst = (__m128i*)clut; + + for (int j = 0; j < 64; j += 32, src += 32, dst += 32) + { + for (int i = 0; i < 16; i += 4) + { + __m128i r0 = _mm_load_si128(&src[i+0]); + __m128i r1 = _mm_load_si128(&src[i+1]); + __m128i r2 = _mm_load_si128(&src[i+2]); + __m128i r3 = _mm_load_si128(&src[i+3]); + + _mm_store_si128(&dst[i*2+0], _mm_unpacklo_epi64(r0, r1)); + _mm_store_si128(&dst[i*2+1], _mm_unpacklo_epi64(r2, r3)); + _mm_store_si128(&dst[i*2+2], _mm_unpackhi_epi64(r0, r1)); + _mm_store_si128(&dst[i*2+3], _mm_unpackhi_epi64(r2, r3)); + + __m128i r4 = _mm_load_si128(&src[i+0+16]); + __m128i r5 = _mm_load_si128(&src[i+1+16]); + __m128i r6 = _mm_load_si128(&src[i+2+16]); + __m128i r7 = _mm_load_si128(&src[i+3+16]); + + _mm_store_si128(&dst[i*2+4], _mm_unpacklo_epi64(r4, r5)); + _mm_store_si128(&dst[i*2+5], _mm_unpacklo_epi64(r6, r7)); + _mm_store_si128(&dst[i*2+6], _mm_unpackhi_epi64(r4, r5)); + _mm_store_si128(&dst[i*2+7], _mm_unpackhi_epi64(r6, r7)); + } + } +} + + +extern "C" void __fastcall WriteCLUT_T32_I4_CSM1_sse2(u32* vm, u32* clut) +{ + __m128i* src = (__m128i*)vm; + __m128i* dst = (__m128i*)clut; + + __m128i r0 = _mm_load_si128(&src[0]); + __m128i r1 = _mm_load_si128(&src[1]); + __m128i r2 = _mm_load_si128(&src[2]); + __m128i r3 = _mm_load_si128(&src[3]); + + _mm_store_si128(&dst[0], _mm_unpacklo_epi64(r0, r1)); + _mm_store_si128(&dst[1], _mm_unpacklo_epi64(r2, r3)); + _mm_store_si128(&dst[2], _mm_unpackhi_epi64(r0, r1)); + _mm_store_si128(&dst[3], _mm_unpackhi_epi64(r2, r3)); +} + +static const __aligned16 int s_clut_16bits_mask[4] = { 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff }; +static const __aligned16 int s_clut16mask2[4] = { 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff }; +static const __aligned16 int s_clut16mask[8] = { 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, + 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff + }; + +template +void __fastcall WriteCLUT_T16_I4_CSM1_core_sse2(u32* vm, u32* clut) +{ + __m128i vm_0; + __m128i vm_1; + __m128i vm_2; + __m128i vm_3; + __m128i clut_0; + __m128i clut_1; + __m128i clut_2; + __m128i clut_3; + + __m128i clut_mask = _mm_load_si128((__m128i*)s_clut_16bits_mask); + + // !HIGH_16BITS_VM + // CSA in 0-15 + // Replace lower 16 bits of clut0 with lower 16 bits of vm + // CSA in 16-31 + // Replace higher 16 bits of clut0 with lower 16 bits of vm + + // HIGH_16BITS_VM + // CSA in 0-15 + // Replace lower 16 bits of clut0 with higher 16 bits of vm + // CSA in 16-31 + // Replace higher 16 bits of clut0 with higher 16 bits of vm + if(HIGH_16BITS_VM && CSA_0_15) { + // move up to low + vm_0 = _mm_load_si128((__m128i*)vm); // 9 8 1 0 + vm_1 = _mm_load_si128((__m128i*)vm+1); // 11 10 3 2 + vm_2 = _mm_load_si128((__m128i*)vm+2); // 13 12 5 4 + vm_3 = _mm_load_si128((__m128i*)vm+3); // 15 14 7 6 + vm_0 = _mm_srli_epi32(vm_0, 16); + vm_1 = _mm_srli_epi32(vm_1, 16); + vm_2 = _mm_srli_epi32(vm_2, 16); + vm_3 = _mm_srli_epi32(vm_3, 16); + } else if(HIGH_16BITS_VM && !CSA_0_15) { + // Remove lower 16 bits + vm_0 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)vm)); // 9 8 1 0 + vm_1 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)vm+1)); // 11 10 3 2 + vm_2 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)vm+2)); // 13 12 5 4 + vm_3 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)vm+3)); // 15 14 7 6 + } else if(!HIGH_16BITS_VM && CSA_0_15) { + // Remove higher 16 bits + vm_0 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)vm)); // 9 8 1 0 + vm_1 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)vm+1)); // 11 10 3 2 + vm_2 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)vm+2)); // 13 12 5 4 + vm_3 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)vm+3)); // 15 14 7 6 + } else if(!HIGH_16BITS_VM && !CSA_0_15) { + // move low to high + vm_0 = _mm_load_si128((__m128i*)vm); // 9 8 1 0 + vm_1 = _mm_load_si128((__m128i*)vm+1); // 11 10 3 2 + vm_2 = _mm_load_si128((__m128i*)vm+2); // 13 12 5 4 + vm_3 = _mm_load_si128((__m128i*)vm+3); // 15 14 7 6 + vm_0 = _mm_slli_epi32(vm_0, 16); + vm_1 = _mm_slli_epi32(vm_1, 16); + vm_2 = _mm_slli_epi32(vm_2, 16); + vm_3 = _mm_slli_epi32(vm_3, 16); + } + + // Unsizzle the data + __m128i row_0 = _mm_unpacklo_epi32(vm_0, vm_1); // 3 2 1 0 + __m128i row_1 = _mm_unpacklo_epi32(vm_2, vm_3); // 7 6 5 4 + __m128i row_2 = _mm_unpackhi_epi32(vm_0, vm_1); // 11 10 9 8 + __m128i row_3 = _mm_unpackhi_epi32(vm_2, vm_3); // 15 14 13 12 + + // load old data & remove useless part + if(CSA_0_15) { + // Remove lower 16 bits + clut_0 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)clut)); + clut_1 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)clut+1)); + clut_2 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)clut+2)); + clut_3 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)clut+3)); + } else { + // Remove higher 16 bits + clut_0 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)clut)); + clut_1 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)clut+1)); + clut_2 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)clut+2)); + clut_3 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)clut+3)); + } + + // Merge old & new data + clut_0 = _mm_or_si128(clut_0, row_0); + clut_1 = _mm_or_si128(clut_1, row_1); + clut_2 = _mm_or_si128(clut_2, row_2); + clut_3 = _mm_or_si128(clut_3, row_3); + + _mm_store_si128((__m128i*)clut, clut_0); + _mm_store_si128((__m128i*)clut+1, clut_1); + _mm_store_si128((__m128i*)clut+2, clut_2); + _mm_store_si128((__m128i*)clut+3, clut_3); +} + +extern "C" void __fastcall WriteCLUT_T16_I4_CSM1_sse2(u32* vm, u32 csa) +{ + u32* clut = (u32*)(g_pbyGSClut + 64*(csa & 15)); + + if (csa > 15) { + WriteCLUT_T16_I4_CSM1_core_sse2(vm, clut); + } else { + WriteCLUT_T16_I4_CSM1_core_sse2(vm, clut); + } +} + +extern "C" void __fastcall WriteCLUT_T16_I4_CSM1_sse2_old(u32* vm, u32* clut) +{ +#define YET_ANOTHER_INTRINSIC +#ifdef YET_ANOTHER_INTRINSIC + __m128i vm0 = _mm_load_si128((__m128i*)vm); + __m128i vm1 = _mm_load_si128((__m128i*)vm+1); + __m128i vm2 = _mm_load_si128((__m128i*)vm+2); + __m128i vm3 = _mm_load_si128((__m128i*)vm+3); + + // rearrange 16bits words + vm0 = _mm_shufflehi_epi16(vm0, 0x88); + vm0 = _mm_shufflelo_epi16(vm0, 0x88); // 6 4 6 4 2 0 2 0 + vm1 = _mm_shufflehi_epi16(vm1, 0x88); + vm1 = _mm_shufflelo_epi16(vm1, 0x88); // 14 12 14 12 10 8 10 8 + + // Note: MSVC complains about direct c-cast... + // vm0 = (__m128i)_mm_shuffle_ps((__m128)vm0, (__m128)vm1, 0x88); // 14 12 10 8 6 4 2 0 + __m128 vm0_f = (_mm_shuffle_ps((__m128&)vm0, (__m128&)vm1, 0x88)); // 14 12 10 8 6 4 2 0 + vm0 = (__m128i&)vm0_f; + vm0 = _mm_shuffle_epi32(vm0, 0xD8); // 14 12 6 4 10 8 2 0 + + // *** Same jobs for vm2 and vm3 + vm2 = _mm_shufflehi_epi16(vm2, 0x88); + vm2 = _mm_shufflelo_epi16(vm2, 0x88); + vm3 = _mm_shufflehi_epi16(vm3, 0x88); + vm3 = _mm_shufflelo_epi16(vm3, 0x88); + + // Note: MSVC complains about direct c-cast... + // vm2 = (__m128i)_mm_shuffle_ps((__m128)vm2, (__m128)vm3, 0x88); + __m128 vm2_f = (_mm_shuffle_ps((__m128&)vm2, (__m128&)vm3, 0x88)); + vm2 = (__m128i&)vm2_f; + vm2 = _mm_shuffle_epi32(vm2, 0xD8); + + // Create a zero register. + __m128i zero_128 = _mm_setzero_si128(); + + if ((u32)clut & 0x0F) { + // Unaligned write. + + u16* clut_word_ptr = (u16*)clut; + __m128i clut_mask = _mm_load_si128((__m128i*)s_clut16mask2); + + // Load previous data and clear high 16 bits of double words + __m128i clut_0 = _mm_load_si128((__m128i*)(clut_word_ptr-1)); // 6 5 4 3 2 1 0 x + __m128i clut_2 = _mm_load_si128((__m128i*)(clut_word_ptr-1)+2); // 22 21 20 19 18 17 16 15 + clut_0 = _mm_and_si128(clut_0, clut_mask); // - 5 - 3 - 1 - x + clut_2 = _mm_and_si128(clut_2, clut_mask); // - 21 - 19 - 17 - 15 + + // Convert 16bits to 32 bits vm0 (zero entended) + __m128i vm0_low = _mm_unpacklo_epi16(vm0, zero_128); // - 10 - 8 - 2 - 0 + __m128i vm0_high = _mm_unpackhi_epi16(vm0, zero_128); // - 14 - 12 - 6 - 4 + + // shift the value to aligned it with clut + vm0_low = _mm_slli_epi32(vm0_low, 16); // 10 - 8 - 2 - 0 - + vm0_high = _mm_slli_epi32(vm0_high, 16); // 14 - 12 - 6 - 4 - + + // Interlace old and new data + clut_0 = _mm_or_si128(clut_0, vm0_low); // 10 5 8 3 2 1 0 x + clut_2 = _mm_or_si128(clut_2, vm0_high); // 14 21 12 19 6 17 4 15 + + // Save the result + _mm_store_si128((__m128i*)(clut_word_ptr-1), clut_0); + _mm_store_si128((__m128i*)(clut_word_ptr-1)+2, clut_2); + + // *** Same jobs for clut_1 and clut_3 + __m128i clut_1 = _mm_load_si128((__m128i*)(clut_word_ptr-1)+1); + __m128i clut_3 = _mm_load_si128((__m128i*)(clut_word_ptr-1)+3); + clut_1 = _mm_and_si128(clut_1, clut_mask); + clut_3 = _mm_and_si128(clut_3, clut_mask); + + __m128i vm2_low = _mm_unpacklo_epi16(vm2, zero_128); + __m128i vm2_high = _mm_unpackhi_epi16(vm2, zero_128); + vm2_low = _mm_slli_epi32(vm2_low, 16); + vm2_high = _mm_slli_epi32(vm2_high, 16); + + clut_1 = _mm_or_si128(clut_1, vm2_low); + clut_3 = _mm_or_si128(clut_3, vm2_high); + + _mm_store_si128((__m128i*)(clut_word_ptr-1)+1, clut_1); + _mm_store_si128((__m128i*)(clut_word_ptr-1)+3, clut_3); + } else { + // Standard write + + __m128i clut_mask = _mm_load_si128((__m128i*)s_clut16mask); + + // Load previous data and clear low 16 bits of double words + __m128i clut_0 = _mm_and_si128(_mm_load_si128((__m128i*)clut), clut_mask); // 7 - 5 - 3 - 1 - + __m128i clut_2 = _mm_and_si128(_mm_load_si128((__m128i*)clut+2), clut_mask); // 23 - 21 - 19 - 17 - + + // Convert 16bits to 32 bits vm0 (zero entended) + __m128i vm0_low = _mm_unpacklo_epi16(vm0, zero_128); // - 10 - 8 - 2 - 0 + __m128i vm0_high = _mm_unpackhi_epi16(vm0, zero_128); // - 14 - 12 - 6 - 4 + + // Interlace old and new data + clut_0 = _mm_or_si128(clut_0, vm0_low); // 7 10 5 8 3 2 1 0 + clut_2 = _mm_or_si128(clut_2, vm0_high); // 23 14 21 12 19 6 17 4 + + // Save the result + _mm_store_si128((__m128i*)clut, clut_0); + _mm_store_si128((__m128i*)clut+2, clut_2); + + // *** Same jobs for clut_1 and clut_3 + __m128i clut_1 = _mm_and_si128(_mm_load_si128((__m128i*)clut+1), clut_mask); + __m128i clut_3 = _mm_and_si128(_mm_load_si128((__m128i*)clut+3), clut_mask); + + __m128i vm2_low = _mm_unpacklo_epi16(vm2, zero_128); + __m128i vm2_high = _mm_unpackhi_epi16(vm2, zero_128); + + clut_1 = _mm_or_si128(clut_1, vm2_low); + clut_3 = _mm_or_si128(clut_3, vm2_high); + + _mm_store_si128((__m128i*)clut+1, clut_1); + _mm_store_si128((__m128i*)clut+3, clut_3); + } + +#else +#if defined(_MSC_VER) + __asm + { + mov eax, vm + mov ecx, clut + movdqa xmm0, qword ptr [eax] + movdqa xmm1, qword ptr [eax+16] + movdqa xmm2, qword ptr [eax+32] + movdqa xmm3, qword ptr [eax+48] + + // rearrange + pshuflw xmm0, xmm0, 0x88 + pshufhw xmm0, xmm0, 0x88 + pshuflw xmm1, xmm1, 0x88 + pshufhw xmm1, xmm1, 0x88 + pshuflw xmm2, xmm2, 0x88 + pshufhw xmm2, xmm2, 0x88 + pshuflw xmm3, xmm3, 0x88 + pshufhw xmm3, xmm3, 0x88 + + shufps xmm0, xmm1, 0x88 + shufps xmm2, xmm3, 0x88 + + pshufd xmm0, xmm0, 0xd8 + pshufd xmm2, xmm2, 0xd8 + + pxor xmm6, xmm6 + + test ecx, 15 + jnz WriteUnaligned + + movdqa xmm7, s_clut16mask // saves upper 16 bytes + + // have to save interlaced with the old data + movdqa xmm4, [ecx] + movdqa xmm5, [ecx+32] + movhlps xmm1, xmm0 + movlhps xmm0, xmm2 // lower 8 colors + + pand xmm4, xmm7 + pand xmm5, xmm7 + + shufps xmm1, xmm2, 0xe4 // upper 8 colors + movdqa xmm2, xmm0 + movdqa xmm3, xmm1 + + punpcklwd xmm0, xmm6 + punpcklwd xmm1, xmm6 + por xmm0, xmm4 + por xmm1, xmm5 + + punpckhwd xmm2, xmm6 + punpckhwd xmm3, xmm6 + + movdqa [ecx], xmm0 + movdqa [ecx+32], xmm1 + + movdqa xmm5, xmm7 + pand xmm7, [ecx+16] + pand xmm5, [ecx+48] + + por xmm2, xmm7 + por xmm3, xmm5 + + movdqa [ecx+16], xmm2 + movdqa [ecx+48], xmm3 + jmp End + +WriteUnaligned: + // ecx is offset by 2 + sub ecx, 2 + + movdqa xmm7, s_clut16mask2 // saves lower 16 bytes + + // have to save interlaced with the old data + movdqa xmm4, [ecx] + movdqa xmm5, [ecx+32] + movhlps xmm1, xmm0 + movlhps xmm0, xmm2 // lower 8 colors + + pand xmm4, xmm7 + pand xmm5, xmm7 + + shufps xmm1, xmm2, 0xe4 // upper 8 colors + movdqa xmm2, xmm0 + movdqa xmm3, xmm1 + + punpcklwd xmm0, xmm6 + punpcklwd xmm1, xmm6 + pslld xmm0, 16 + pslld xmm1, 16 + por xmm0, xmm4 + por xmm1, xmm5 + + punpckhwd xmm2, xmm6 + punpckhwd xmm3, xmm6 + pslld xmm2, 16 + pslld xmm3, 16 + + movdqa [ecx], xmm0 + movdqa [ecx+32], xmm1 + + movdqa xmm5, xmm7 + pand xmm7, [ecx+16] + pand xmm5, [ecx+48] + + por xmm2, xmm7 + por xmm3, xmm5 + + movdqa [ecx+16], xmm2 + movdqa [ecx+48], xmm3 + +End: + } +#else + __asm__ __volatile__(".intel_syntax noprefix\n" + "movdqa xmm0, xmmword ptr [%[vm]]\n" + "movdqa xmm1, xmmword ptr [%[vm]+16]\n" + "movdqa xmm2, xmmword ptr [%[vm]+32]\n" + "movdqa xmm3, xmmword ptr [%[vm]+48]\n" + + // rearrange + "pshuflw xmm0, xmm0, 0x88\n" + "pshufhw xmm0, xmm0, 0x88\n" + "pshuflw xmm1, xmm1, 0x88\n" + "pshufhw xmm1, xmm1, 0x88\n" + "pshuflw xmm2, xmm2, 0x88\n" + "pshufhw xmm2, xmm2, 0x88\n" + "pshuflw xmm3, xmm3, 0x88\n" + "pshufhw xmm3, xmm3, 0x88\n" + + "shufps xmm0, xmm1, 0x88\n" + "shufps xmm2, xmm3, 0x88\n" + + "pshufd xmm0, xmm0, 0xd8\n" + "pshufd xmm2, xmm2, 0xd8\n" + + "pxor xmm6, xmm6\n" + + "test %[clut], 15\n" + "jnz WriteUnaligned\n" + + "movdqa xmm7, %[s_clut16mask]\n" // saves upper 16 bits + + // have to save interlaced with the old data + "movdqa xmm4, [%[clut]]\n" + "movdqa xmm5, [%[clut]+32]\n" + "movhlps xmm1, xmm0\n" + "movlhps xmm0, xmm2\n"// lower 8 colors + + "pand xmm4, xmm7\n" + "pand xmm5, xmm7\n" + + "shufps xmm1, xmm2, 0xe4\n" // upper 8 colors + "movdqa xmm2, xmm0\n" + "movdqa xmm3, xmm1\n" + + "punpcklwd xmm0, xmm6\n" + "punpcklwd xmm1, xmm6\n" + "por xmm0, xmm4\n" + "por xmm1, xmm5\n" + + "punpckhwd xmm2, xmm6\n" + "punpckhwd xmm3, xmm6\n" + + "movdqa [%[clut]], xmm0\n" + "movdqa [%[clut]+32], xmm1\n" + + "movdqa xmm5, xmm7\n" + "pand xmm7, [%[clut]+16]\n" + "pand xmm5, [%[clut]+48]\n" + + "por xmm2, xmm7\n" + "por xmm3, xmm5\n" + + "movdqa [%[clut]+16], xmm2\n" + "movdqa [%[clut]+48], xmm3\n" + "jmp WriteCLUT_T16_I4_CSM1_End\n" + + "WriteUnaligned:\n" + // %[clut] is offset by 2 + "sub %[clut], 2\n" + + "movdqa xmm7, %[s_clut16mask2]\n" // saves lower 16 bits + + // have to save interlaced with the old data + "movdqa xmm4, [%[clut]]\n" + "movdqa xmm5, [%[clut]+32]\n" + "movhlps xmm1, xmm0\n" + "movlhps xmm0, xmm2\n" // lower 8 colors + + "pand xmm4, xmm7\n" + "pand xmm5, xmm7\n" + + "shufps xmm1, xmm2, 0xe4\n" // upper 8 colors + "movdqa xmm2, xmm0\n" + "movdqa xmm3, xmm1\n" + + "punpcklwd xmm0, xmm6\n" + "punpcklwd xmm1, xmm6\n" + "pslld xmm0, 16\n" + "pslld xmm1, 16\n" + "por xmm0, xmm4\n" + "por xmm1, xmm5\n" + + "punpckhwd xmm2, xmm6\n" + "punpckhwd xmm3, xmm6\n" + "pslld xmm2, 16\n" + "pslld xmm3, 16\n" + + "movdqa [%[clut]], xmm0\n" + "movdqa [%[clut]+32], xmm1\n" + + "movdqa xmm5, xmm7\n" + "pand xmm7, [%[clut]+16]\n" + "pand xmm5, [%[clut]+48]\n" + + "por xmm2, xmm7\n" + "por xmm3, xmm5\n" + + "movdqa [%[clut]+16], xmm2\n" + "movdqa [%[clut]+48], xmm3\n" + "WriteCLUT_T16_I4_CSM1_End:\n" + "\n" + ".att_syntax\n" + : + : [vm] "r" (vm), [clut] "r" (clut), [s_clut16mask] "m" (*s_clut16mask), [s_clut16mask2] "m" (*s_clut16mask2) + : "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "memory" + ); +#endif // _MSC_VER +#endif +} + +__forceinline void WriteCLUT_T16_I8_CSM1_sse2(u32* vm, u32 csa) +{ + // update the right clut column (csa < 16) + u32* clut = (u32*)(g_pbyGSClut + 64*(csa & 15)); + u32 csa_right = (csa < 16) ? 16 - csa : 0; + + for(int i = (csa_right/2); i > 0 ; --i) { + WriteCLUT_T16_I4_CSM1_core_sse2(vm, clut); + clut += 16; + WriteCLUT_T16_I4_CSM1_core_sse2(vm, clut); + clut += 16; + vm += 16; // go down one column + } + + // update the left clut column + u32 csa_left = (csa >= 16) ? 16 : csa; + + // In case csa_right is odd (so csa_left is also odd), we cross the clut column + if(csa_right & 0x1) { + WriteCLUT_T16_I4_CSM1_core_sse2(vm, clut); + // go back to the base before processing left clut column + clut = (u32*)(g_pbyGSClut); + WriteCLUT_T16_I4_CSM1_core_sse2(vm, clut); + } else if(csa_right != 0) { + // go back to the base before processing left clut column + clut = (u32*)(g_pbyGSClut); + } + + for(int i = (csa_left/2); i > 0 ; --i) { + WriteCLUT_T16_I4_CSM1_core_sse2(vm, clut); + clut += 16; + WriteCLUT_T16_I4_CSM1_core_sse2(vm, clut); + clut += 16; + vm += 16; // go down one column + } +} +#endif + +#endif // ZEROGS_SSE2 + +#if 0 +void __fastcall WriteCLUT_T16_I8_CSM1_c(u32* _vm, u32* _clut) +{ + const static u32 map[] = + { + 0, 2, 8, 10, 16, 18, 24, 26, + 4, 6, 12, 14, 20, 22, 28, 30, + 1, 3, 9, 11, 17, 19, 25, 27, + 5, 7, 13, 15, 21, 23, 29, 31 + }; + + u16* vm = (u16*)_vm; + u16* clut = (u16*)_clut; + + int left = ((u32)(uptr)clut & 2) ? 512 : 512 - (((u32)(uptr)clut) & 0x3ff) / 2; + + for (int j = 0; j < 8; j++, vm += 32, clut += 64, left -= 32) + { + if (left == 32) + { + assert(left == 32); + + for (int i = 0; i < 16; i++) + clut[2*i] = vm[map[i]]; + + clut = (u16*)((uptr)clut & ~0x3ff) + 1; + + for (int i = 16; i < 32; i++) + clut[2*i] = vm[map[i]]; + } + else + { + if (left == 0) + { + clut = (u16*)((uptr)clut & ~0x3ff) + 1; + left = -1; + } + + for (int i = 0; i < 32; i++) + clut[2*i] = vm[map[i]]; + } + } +} + +void __fastcall WriteCLUT_T32_I8_CSM1_c(u32* vm, u32* clut) +{ + u64* src = (u64*)vm; + u64* dst = (u64*)clut; + + for (int j = 0; j < 2; j++, src += 32) + { + for (int i = 0; i < 4; i++, dst += 16, src += 8) + { + dst[0] = src[0]; + dst[1] = src[2]; + dst[2] = src[4]; + dst[3] = src[6]; + dst[4] = src[1]; + dst[5] = src[3]; + dst[6] = src[5]; + dst[7] = src[7]; + + dst[8] = src[32]; + dst[9] = src[32+2]; + dst[10] = src[32+4]; + dst[11] = src[32+6]; + dst[12] = src[32+1]; + dst[13] = src[32+3]; + dst[14] = src[32+5]; + dst[15] = src[32+7]; + } + } +} + +void __fastcall WriteCLUT_T16_I4_CSM1_c(u32* _vm, u32* _clut) +{ + u16* dst = (u16*)_clut; + u16* src = (u16*)_vm; + + dst[0] = src[0]; + dst[2] = src[2]; + dst[4] = src[8]; + dst[6] = src[10]; + dst[8] = src[16]; + dst[10] = src[18]; + dst[12] = src[24]; + dst[14] = src[26]; + dst[16] = src[4]; + dst[18] = src[6]; + dst[20] = src[12]; + dst[22] = src[14]; + dst[24] = src[20]; + dst[26] = src[22]; + dst[28] = src[28]; + dst[30] = src[30]; +} + +void __fastcall WriteCLUT_T32_I4_CSM1_c(u32* vm, u32* clut) +{ + u64* src = (u64*)vm; + u64* dst = (u64*)clut; + + dst[0] = src[0]; + dst[1] = src[2]; + dst[2] = src[4]; + dst[3] = src[6]; + dst[4] = src[1]; + dst[5] = src[3]; + dst[6] = src[5]; + dst[7] = src[7]; +} + +#endif + +void SSE2_UnswizzleZ16Target(u16* dst, u16* src, int iters) +{ + +#if defined(_MSC_VER) + __asm + { + mov edx, iters + pxor xmm7, xmm7 + mov eax, dst + mov ecx, src + +Z16Loop: + // unpack 64 bytes at a time + movdqa xmm0, [ecx] + movdqa xmm2, [ecx+16] + movdqa xmm4, [ecx+32] + movdqa xmm6, [ecx+48] + + movdqa xmm1, xmm0 + movdqa xmm3, xmm2 + movdqa xmm5, xmm4 + + punpcklwd xmm0, xmm7 + punpckhwd xmm1, xmm7 + punpcklwd xmm2, xmm7 + punpckhwd xmm3, xmm7 + + // start saving + movdqa [eax], xmm0 + movdqa [eax+16], xmm1 + + punpcklwd xmm4, xmm7 + punpckhwd xmm5, xmm7 + + movdqa [eax+32], xmm2 + movdqa [eax+48], xmm3 + + movdqa xmm0, xmm6 + punpcklwd xmm6, xmm7 + + movdqa [eax+64], xmm4 + movdqa [eax+80], xmm5 + + punpckhwd xmm0, xmm7 + + movdqa [eax+96], xmm6 + movdqa [eax+112], xmm0 + + add ecx, 64 + add eax, 128 + sub edx, 1 + jne Z16Loop + } +#else // _MSC_VER + + __asm__ __volatile__(".intel_syntax\n" + "pxor %%xmm7, %%xmm7\n" + + "Z16Loop:\n" + // unpack 64 bytes at a time + "movdqa %%xmm0, [%[src]]\n" + "movdqa %%xmm2, [%[src]+16]\n" + "movdqa %%xmm4, [%[src]+32]\n" + "movdqa %%xmm6, [%[src]+48]\n" + + "movdqa %%xmm1, %%xmm0\n" + "movdqa %%xmm3, %%xmm2\n" + "movdqa %%xmm5, %%xmm4\n" + + "punpcklwd %%xmm0, %%xmm7\n" + "punpckhwd %%xmm1, %%xmm7\n" + "punpcklwd %%xmm2, %%xmm7\n" + "punpckhwd %%xmm3, %%xmm7\n" + + // start saving + "movdqa [%[dst]], %%xmm0\n" + "movdqa [%[dst]+16], %%xmm1\n" + + "punpcklwd %%xmm4, %%xmm7\n" + "punpckhwd %%xmm5, %%xmm7\n" + + "movdqa [%[dst]+32], %%xmm2\n" + "movdqa [%[dst]+48], %%xmm3\n" + + "movdqa %%xmm0, %%xmm6\n" + "punpcklwd %%xmm6, %%xmm7\n" + + "movdqa [%[dst]+64], %%xmm4\n" + "movdqa [%[dst]+80], %%xmm5\n" + + "punpckhwd %%xmm0, %%xmm7\n" + + "movdqa [%[dst]+96], %%xmm6\n" + "movdqa [%[dst]+112], %%xmm0\n" + + "add %[src], 64\n" + "add %[dst], 128\n" + "sub %[iters], 1\n" + "jne Z16Loop\n" + +".att_syntax\n" + : "=&r"(src), "=&r"(dst), "=&r"(iters) + : [src] "0"(src), [dst] "1"(dst), [iters] "2"(iters) + : "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "memory" + ); +#endif // _MSC_VER +} + diff --git a/plugins/zzogl-pg-cg/opengl/x86.h b/plugins/zzogl-pg-cg/opengl/x86.h new file mode 100644 index 000000000..547b8484c --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/x86.h @@ -0,0 +1,174 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef ZEROGS_X86 +#define ZEROGS_X86 + +#include "GS.h" + +extern "C" void __fastcall SwizzleBlock32_sse2(u8* dst, u8* src, int srcpitch, u32 WriteMask = 0xffffffff); +extern "C" void __fastcall SwizzleBlock16_sse2(u8* dst, u8* src, int srcpitch); +extern "C" void __fastcall SwizzleBlock8_sse2(u8* dst, u8* src, int srcpitch); +extern "C" void __fastcall SwizzleBlock4_sse2(u8* dst, u8* src, int srcpitch); +extern "C" void __fastcall SwizzleBlock32u_sse2(u8* dst, u8* src, int srcpitch, u32 WriteMask = 0xffffffff); +extern "C" void __fastcall SwizzleBlock16u_sse2(u8* dst, u8* src, int srcpitch); +extern "C" void __fastcall SwizzleBlock8u_sse2(u8* dst, u8* src, int srcpitch); +extern "C" void __fastcall SwizzleBlock4u_sse2(u8* dst, u8* src, int srcpitch); + +// frame swizzling + +#if 0 +// no AA +extern "C" void __fastcall FrameSwizzleBlock32_sse2(u32* dst, u32* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall FrameSwizzleBlock16_sse2(u16* dst, u32* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall Frame16SwizzleBlock32_sse2(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall Frame16SwizzleBlock32Z_sse2(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall Frame16SwizzleBlock16_sse2(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall Frame16SwizzleBlock16Z_sse2(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask); + +// AA 2x +extern "C" void __fastcall FrameSwizzleBlock32A2_sse2(u32* dst, u32* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall FrameSwizzleBlock16A2_sse2(u16* dst, u32* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall Frame16SwizzleBlock32A2_sse2(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall Frame16SwizzleBlock32ZA2_sse2(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall Frame16SwizzleBlock16A2_sse2(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall Frame16SwizzleBlock16ZA2_sse2(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask); + +// AA 4x +extern "C" void __fastcall FrameSwizzleBlock32A4_sse2(u32* dst, u32* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall FrameSwizzleBlock16A4_sse2(u16* dst, u32* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall Frame16SwizzleBlock32A4_sse2(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall Frame16SwizzleBlock32ZA4_sse2(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall Frame16SwizzleBlock16A4_sse2(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern "C" void __fastcall Frame16SwizzleBlock16ZA4_sse2(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask); + +/*extern void __fastcall SwizzleBlock32_c(u8* dst, u8* src, int srcpitch, u32 WriteMask = 0xffffffff); +extern void __fastcall SwizzleBlock16_c(u8* dst, u8* src, int srcpitch); +extern void __fastcall SwizzleBlock8_c(u8* dst, u8* src, int srcpitch); +extern void __fastcall SwizzleBlock4_c(u8* dst, u8* src, int srcpitch);*/ + +// no AA +extern void __fastcall FrameSwizzleBlock32_c(u32* dst, u32* src, int srcpitch, u32 WriteMask); +extern void __fastcall FrameSwizzleBlock24_c(u32* dst, u32* src, int srcpitch, u32 WriteMask); +extern void __fastcall FrameSwizzleBlock16_c(u16* dst, u32* src, int srcpitch, u32 WriteMask); +extern void __fastcall Frame16SwizzleBlock32_c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern void __fastcall Frame16SwizzleBlock32Z_c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern void __fastcall Frame16SwizzleBlock16_c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern void __fastcall Frame16SwizzleBlock16Z_c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask); + +// AA 2x +extern void __fastcall FrameSwizzleBlock32A2_c(u32* dst, u32* src, int srcpitch, u32 WriteMask); +extern void __fastcall FrameSwizzleBlock24A2_c(u32* dst, u32* src, int srcpitch, u32 WriteMask); +extern void __fastcall FrameSwizzleBlock16A2_c(u16* dst, u32* src, int srcpitch, u32 WriteMask); +extern void __fastcall Frame16SwizzleBlock32A2_c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern void __fastcall Frame16SwizzleBlock32ZA2_c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern void __fastcall Frame16SwizzleBlock16A2_c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern void __fastcall Frame16SwizzleBlock16ZA2_c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask); + +// AA 4x +extern void __fastcall FrameSwizzleBlock32A4_c(u32* dst, u32* src, int srcpitch, u32 WriteMask); +extern void __fastcall FrameSwizzleBlock24A4_c(u32* dst, u32* src, int srcpitch, u32 WriteMask); +extern void __fastcall FrameSwizzleBlock16A4_c(u16* dst, u32* src, int srcpitch, u32 WriteMask); +extern void __fastcall Frame16SwizzleBlock32A4_c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern void __fastcall Frame16SwizzleBlock32ZA4_c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern void __fastcall Frame16SwizzleBlock16A4_c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +extern void __fastcall Frame16SwizzleBlock16ZA4_c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask); +#endif + +extern void __fastcall SwizzleColumn32_c(int y, u8* dst, u8* src, int srcpitch, u32 WriteMask = 0xffffffff); +extern void __fastcall SwizzleColumn16_c(int y, u8* dst, u8* src, int srcpitch); +extern void __fastcall SwizzleColumn8_c(int y, u8* dst, u8* src, int srcpitch); +extern void __fastcall SwizzleColumn4_c(int y, u8* dst, u8* src, int srcpitch); + +// extern "C" void __fastcall WriteCLUT_T16_I8_CSM1_sse2(u32* vm, u32* clut); +extern "C" void __fastcall WriteCLUT_T16_I8_CSM1_sse2(u32* vm, u32 csa); +extern "C" void __fastcall WriteCLUT_T32_I8_CSM1_sse2(u32* vm, u32* clut); +// extern "C" void __fastcall WriteCLUT_T16_I4_CSM1_sse2(u32* vm, u32* clut); +extern "C" void __fastcall WriteCLUT_T16_I4_CSM1_sse2(u32* vm, u32 csa); +extern "C" void __fastcall WriteCLUT_T32_I4_CSM1_sse2(u32* vm, u32* clut); +extern void __fastcall WriteCLUT_T16_I8_CSM1_c(u32* vm, u32* clut); +extern void __fastcall WriteCLUT_T32_I8_CSM1_c(u32* vm, u32* clut); + +extern void __fastcall WriteCLUT_T16_I4_CSM1_c(u32* vm, u32* clut); +extern void __fastcall WriteCLUT_T32_I4_CSM1_c(u32* vm, u32* clut); + +extern void SSE2_UnswizzleZ16Target(u16* dst, u16* src, int iters); + +#ifdef ZEROGS_SSE2 + +#define FrameSwizzleBlock32 FrameSwizzleBlock32_c +#define FrameSwizzleBlock24 FrameSwizzleBlock24_c +#define FrameSwizzleBlock16 FrameSwizzleBlock16_c +#define Frame16SwizzleBlock32 Frame16SwizzleBlock32_c +#define Frame16SwizzleBlock32Z Frame16SwizzleBlock32Z_c +#define Frame16SwizzleBlock16 Frame16SwizzleBlock16_c +#define Frame16SwizzleBlock16Z Frame16SwizzleBlock16Z_c + +#define FrameSwizzleBlock32A2 FrameSwizzleBlock32A2_c +#define FrameSwizzleBlock24A2 FrameSwizzleBlock24A2_c +#define FrameSwizzleBlock16A2 FrameSwizzleBlock16A2_c +#define Frame16SwizzleBlock32A2 Frame16SwizzleBlock32A2_c +#define Frame16SwizzleBlock32ZA2 Frame16SwizzleBlock32ZA2_c +#define Frame16SwizzleBlock16A2 Frame16SwizzleBlock16A2_c +#define Frame16SwizzleBlock16ZA2 Frame16SwizzleBlock16ZA2_c + +#define FrameSwizzleBlock32A4 FrameSwizzleBlock32A4_c +#define FrameSwizzleBlock24A4 FrameSwizzleBlock24A4_c +#define FrameSwizzleBlock16A4 FrameSwizzleBlock16A4_c +#define Frame16SwizzleBlock32A4 Frame16SwizzleBlock32A4_c +#define Frame16SwizzleBlock32ZA4 Frame16SwizzleBlock32ZA4_c +#define Frame16SwizzleBlock16A4 Frame16SwizzleBlock16A4_c +#define Frame16SwizzleBlock16ZA4 Frame16SwizzleBlock16ZA4_c + +#define WriteCLUT_T16_I8_CSM1 WriteCLUT_T16_I8_CSM1_sse2 +#define WriteCLUT_T32_I8_CSM1 WriteCLUT_T32_I8_CSM1_sse2 +#define WriteCLUT_T16_I4_CSM1 WriteCLUT_T16_I4_CSM1_sse2 +#define WriteCLUT_T32_I4_CSM1 WriteCLUT_T32_I4_CSM1_sse2 + +#else + +#define FrameSwizzleBlock32 FrameSwizzleBlock32_c +#define FrameSwizzleBlock16 FrameSwizzleBlock16_c +#define Frame16SwizzleBlock32 Frame16SwizzleBlock32_c +#define Frame16SwizzleBlock32Z Frame16SwizzleBlock32Z_c +#define Frame16SwizzleBlock16 Frame16SwizzleBlock16_c +#define Frame16SwizzleBlock16Z Frame16SwizzleBlock16Z_c + +#define FrameSwizzleBlock32A2 FrameSwizzleBlock32A2_c +#define FrameSwizzleBlock16A2 FrameSwizzleBlock16A2_c +#define Frame16SwizzleBlock32A2 Frame16SwizzleBlock32A2_c +#define Frame16SwizzleBlock32ZA2 Frame16SwizzleBlock32ZA2_c +#define Frame16SwizzleBlock16A2 Frame16SwizzleBlock16A2_c +#define Frame16SwizzleBlock16ZA2 Frame16SwizzleBlock16ZA2_c + +#define FrameSwizzleBlock32A4 FrameSwizzleBlock32A4_c +#define FrameSwizzleBlock16A4 FrameSwizzleBlock16A4_c +#define Frame16SwizzleBlock32A4 Frame16SwizzleBlock32A4_c +#define Frame16SwizzleBlock32ZA4 Frame16SwizzleBlock32ZA4_c +#define Frame16SwizzleBlock16A4 Frame16SwizzleBlock16A4_c +#define Frame16SwizzleBlock16ZA4 Frame16SwizzleBlock16ZA4_c + +#define WriteCLUT_T16_I8_CSM1 WriteCLUT_T16_I8_CSM1_c +#define WriteCLUT_T32_I8_CSM1 WriteCLUT_T32_I8_CSM1_c +#define WriteCLUT_T16_I4_CSM1 WriteCLUT_T16_I4_CSM1_c +#define WriteCLUT_T32_I4_CSM1 WriteCLUT_T32_I4_CSM1_c + +#endif + +#endif diff --git a/plugins/zzogl-pg-cg/opengl/zerogs.cpp b/plugins/zzogl-pg-cg/opengl/zerogs.cpp new file mode 100644 index 000000000..432d4ee84 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/zerogs.cpp @@ -0,0 +1,442 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +//-------------------------- Includes +#include "Util.h" +#include "zerogs.h" +#include "ZZoglVB.h" + +///////////////////// +// graphics resources + +bool s_bTexFlush = false; +int s_nLastResolveReset = 0; +int s_nResolveCounts[30] = {0}; // resolve counts for last 30 frames +int s_nNewWidth = -1, s_nNewHeight = -1; + +primInfo *prim; +//////////////////// +// State parameters +int g_nDepthUpdateCount = 0; + +static ZeroGSInit s_ZeroGSInit; + +// does one time only initializing/destruction + +void HandleGLError() +{ + FUNCLOG + // check the error status of this framebuffer */ + GLenum error = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + + // if error != GL_FRAMEBUFFER_COMPLETE_EXT, there's an error of some sort + + if (error != 0) + { + int w = 0; + int h = 0; + GLint fmt; + glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_INTERNAL_FORMAT_EXT, &fmt); + glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_WIDTH_EXT, &w); + glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_HEIGHT_EXT, &h); + + switch (error) + { + case GL_FRAMEBUFFER_COMPLETE_EXT: + break; + + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: + ZZLog::Error_Log("Error! missing a required image/buffer attachment!"); + break; + + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: + ZZLog::Error_Log("Error! has no images/buffers attached!"); + break; + +// case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT: +// ZZLog::Error_Log("Error! has an image/buffer attached in multiple locations!"); +// break; + + case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: + ZZLog::Error_Log("Error! has mismatched image/buffer dimensions!"); + break; + + case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: + ZZLog::Error_Log("Error! colorbuffer attachments have different types!"); + break; + + case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: + ZZLog::Error_Log("Error! trying to draw to non-attached color buffer!"); + break; + + case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: + ZZLog::Error_Log("Error! trying to read from a non-attached color buffer!"); + break; + + case GL_FRAMEBUFFER_UNSUPPORTED_EXT: + ZZLog::Error_Log("Error! format is not supported by current graphics card/driver!"); + break; + + default: + ZZLog::Error_Log("*UNKNOWN ERROR* reported from glCheckFramebufferStatusEXT(0x%x)!", error); + break; + } + } +} + +void ZZGSStateReset() +{ + FUNCLOG + icurctx = -1; + + for (int i = 0; i < 2; ++i) + { + vb[i].Destroy(); + memset(&vb[i], 0, sizeof(VB)); + + vb[i].tex0.tw = 1; + vb[i].tex0.th = 1; + vb[i].scissor.x1 = 639; + vb[i].scissor.y1 = 479; + vb[i].tex0.tbw = 64; + vb[i].Init(VB_BUFFERSIZE); + } + + s_RangeMngr.Clear(); + + g_MemTargs.Destroy(); + s_RTs.Destroy(); + s_DepthRTs.Destroy(); + s_BitwiseTextures.Destroy(); + + vb[0].ictx = 0; + vb[1].ictx = 1; +} + +void SetDeviceSize(int nNewWidth, int nNewHeight) +{ + FUNCLOG + s_nNewWidth = nNewWidth; + s_nNewHeight = nNewHeight; + + if (!(conf.fullscreen())) + { + conf.width = nNewWidth; + conf.height = nNewHeight; + } +} + +void ChangeDeviceSize(int nNewWidth, int nNewHeight) +{ + FUNCLOG + + Size oldSize = GLWin.backbuffer; + + if (!ZZCreate(nNewWidth&~7, nNewHeight&~7)) + { + ZZLog::Error_Log("Failed to recreate, changing to old device."); + + if (!ZZCreate(oldSize.w, oldSize.h)) + { + SysMessage("Failed to create device, exiting..."); + exit(0); + } + } + + for (int i = 0; i < 2; ++i) + { + vb[i].bNeedFrameCheck = vb[i].bNeedZCheck = 1; + vb[i].CheckFrame(0); + } + + assert(vb[0].pBufferData != NULL && vb[1].pBufferData != NULL); +} + +void SetAA(int mode) +{ + FUNCLOG + float f = 1.0f; + + // need to flush all targets + s_RTs.ResolveAll(); + s_RTs.Destroy(); + s_DepthRTs.ResolveAll(); + s_DepthRTs.Destroy(); + + AA.x = AA.y = 0; // This is code for x0, x2, x4, x8 and x16 anti-aliasing. + + if (mode > 0) + { + // ( 1, 0 ) ; ( 1, 1 ) ; ( 2, 1 ) ; ( 2, 2 ) + // it's used as a binary shift, so x >> AA.x, y >> AA.y + AA.x = (mode + 1) / 2; + AA.y = mode / 2; + f = 2.0f; + } + + memset(s_nResolveCounts, 0, sizeof(s_nResolveCounts)); + s_nLastResolveReset = 0; + + vb[0].prndr = NULL; + vb[0].pdepth = NULL; + vb[1].prndr = NULL; + vb[1].pdepth = NULL; + + vb[0].bNeedFrameCheck = vb[0].bNeedZCheck = 1; + vb[1].bNeedFrameCheck = vb[1].bNeedZCheck = 1; + + glPointSize(f); +} + +//void RenderCustom(float fAlpha) +//{ +// FUNCLOG +// GL_REPORT_ERROR(); +// +// fAlpha = 1; +// glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the backbuffer +// +// DisableAllgl() ; +// SetShaderCaller("RenderCustom"); +// +// glViewport(0, 0, GLWin.backbuffer.w, GLWin.backbuffer.h); +// +// // play custom animation +// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); +// +// // tex coords +// float4 v = float4(1 / 32767.0f, 1 / 32767.0f, 0, 0); +// ZZshSetParameter4fv(pvsBitBlt.prog, pvsBitBlt.sBitBltPos, v, "g_fBitBltPos"); +// v.x = (float)nLogoWidth; +// v.y = (float)nLogoHeight; +// ZZshSetParameter4fv(pvsBitBlt.prog, pvsBitBlt.sBitBltTex, v, "g_fBitBltTex"); +// +// v.x = v.y = v.z = v.w = fAlpha; +// ZZshSetParameter4fv(ppsBaseTexture.prog, ppsBaseTexture.sOneColor, v, "g_fOneColor"); +// +// if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +// +// // inside vhDCb[0]'s target area, so render that region only +// ZZshGLSetTextureParameter(ppsBaseTexture.prog, ppsBaseTexture.sFinal, ptexLogo, "Logo"); +// glBindBuffer(GL_ARRAY_BUFFER, vboRect); +// +// SET_STREAM(); +// +// ZZshSetVertexShader(pvsBitBlt.prog); +// ZZshSetPixelShader(ppsBaseTexture.prog); +// DrawTriangleArray(); +// +// // restore +// if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +// +// ProcessMessages(); +// +// GLWin.SwapGLBuffers(); +// +// glEnable(GL_SCISSOR_TEST); +// glEnable(GL_STENCIL_TEST); +// +// vb[0].bSyncVars = 0; +// vb[1].bSyncVars = 0; +// +// GL_REPORT_ERROR(); +//} + +////////////////////////// +// Internal Definitions // +////////////////////////// + +__forceinline void SetFogColor(float4 v) +{ + FUNCLOG + + SetShaderCaller("SetFogColor"); + ZZshSetParameter4fv(g_fparamFogColor, v, "g_fParamFogColor"); +} + +__forceinline void SetFogColor(u32 fog) +{ + FUNCLOG + + gs.fogcol = fog; + + FlushBoth(); + + float4 v; + + // set it immediately + v.SetColor(gs.fogcol); + SetFogColor(v); +} + +__forceinline void SetFogColor(GIFRegFOGCOL* fog) +{ + FUNCLOG + + float4 v; + + v.x = fog->FCR / 255.0f; + v.y = fog->FCG / 255.0f; + v.z = fog->FCB / 255.0f; + SetFogColor(v); +} + +void ExtWrite() +{ + FUNCLOG + ZZLog::Warn_Log("A hollow voice says 'EXTWRITE'! Nothing happens."); + + // use local DISPFB, EXTDATA, EXTBUF, and PMODE +// int bpp, start, end; +// tex0Info texframe; + +// bpp = 4; +// if( texframe.psm == PSMT16S ) bpp = 3; +// else if (PSMT_ISHALF(texframe.psm)) bpp = 2; +// +// // get the start and end addresses of the buffer +// GetRectMemAddress(start, end, texframe.psm, 0, 0, texframe.tw, texframe.th, texframe.tbp0, texframe.tbw); +} + +//////////// +// Caches // +//////////// + + +// case 0: return false; +// case 1: break; +// case 2: m_CBP[0] = TEX0.CBP; break; +// case 3: m_CBP[1] = TEX0.CBP; break; +// case 4: if(m_CBP[0] == TEX0.CBP) return false; m_CBP[0] = TEX0.CBP; break; +// case 5: if(m_CBP[1] == TEX0.CBP) return false; m_CBP[1] = TEX0.CBP; break; +// case 6: ASSERT(0); return false; // ffx2 menu +// case 7: ASSERT(0); return false; +// default: __assume(0); + +// cld state: +// 000 - clut data is not loaded; data in the temp buffer is stored +// 001 - clut data is always loaded. +// 010 - clut data is always loaded; cbp0 = cbp. +// 011 - clut data is always loadedl cbp1 = cbp. +// 100 - cbp0 is compared with cbp. if different, clut data is loaded. +// 101 - cbp1 is compared with cbp. if different, clut data is loaded. + +// GSdx sets cbp0 & cbp1 when checking for clut changes. ZeroGS sets them in texClutWrite. +bool CheckChangeInClut(u32 highdword, u32 psm) +{ + FUNCLOG + int cld = ZZOglGet_cld_TexBits(highdword); + int cbp = ZZOglGet_cbp_TexBits(highdword); + + // processing the CLUT after tex0/2 are written + //ZZLog::Error_Log("high == 0x%x; cld == %d", highdword, cld); + + switch (cld) + { + case 0: + return false; + + case 1: + break; + + case 2: + break; + + case 3: + break; + + case 4: + if (gs.cbp[0] == cbp) return false; + break; + + case 5: + if (gs.cbp[1] == cbp) return false; + break; + + default: + break; + } + + // Compare the cache with current memory + + // CSM2 is not supported + if (ZZOglGet_csm_TexBits(highdword)) + return true; + + int cpsm = ZZOglGet_cpsm_TexBits(highdword); + int csa = ZZOglGet_csa_TexBits(highdword); + int entries = PSMT_IS8CLUT(psm) ? 256 : 16; + + u8* GSMem = g_pbyGSMemory + cbp * 256; + + if (PSMT_IS32BIT(cpsm)) + return Cmp_ClutBuffer_GSMem((u32*)GSMem, csa, entries*4); + else { + // Mana Khemia triggers this. + //ZZLog::Error_Log("16 bit clut not supported."); + return Cmp_ClutBuffer_GSMem((u16*)GSMem, csa, entries*2); + } +} + +void texClutWrite(int ctx) +{ + FUNCLOG + s_bTexFlush = false; + + tex0Info& tex0 = vb[ctx].tex0; + + assert(PSMT_ISCLUT(tex0.psm)); + + // processing the CLUT after tex0/2 are written + switch (tex0.cld) + { + case 0: + return; + + case 1: + break; // tex0.cld is usually 1. + + case 2: + gs.cbp[0] = tex0.cbp; + break; + + case 3: + gs.cbp[1] = tex0.cbp; + break; + + case 4: + if (gs.cbp[0] == tex0.cbp) return; + gs.cbp[0] = tex0.cbp; + break; + + case 5: + if (gs.cbp[1] == tex0.cbp) return; + gs.cbp[1] = tex0.cbp; + break; + + default: //ZZLog::Debug_Log("cld isn't 0-5!"); + break; + } + + Flush(!ctx); + + // Write the memory to clut buffer + GSMem_to_ClutBuffer(tex0); +} + diff --git a/plugins/zzogl-pg-cg/opengl/zerogs.h b/plugins/zzogl-pg-cg/opengl/zerogs.h new file mode 100644 index 000000000..b898d4682 --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/zerogs.h @@ -0,0 +1,86 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __ZEROGS__H +#define __ZEROGS__H + +#ifdef _MSC_VER +#pragma warning(disable:4200) // nonstandard extension used : zero-sized array in struct/union +#endif + +// ----------------------------- Includes +#include "PS2Edefs.h" +// ------------------------ Variables ------------------------- + +////////////////////////// +// State parameters + +#if defined(_WIN32) +# include "Utilities/RedtapeWindows.h" +# include "resource.h" +#endif + +#include + +#include "GS.h" +#include "targets.h" +#include "GLWin.h" +#include "ZZoglShaders.h" +#include "ZZClut.h" +#include "HostMemory.h" + +typedef void (APIENTRYP _PFNSWAPINTERVAL)(int); + +PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT = NULL; +PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT = NULL; +PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT = NULL; +PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT = NULL; +PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT = NULL; +PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT = NULL; +PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT = NULL; +PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT = NULL; +PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT = NULL; +PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT = NULL; +PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT = NULL; +PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT = NULL; +PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT = NULL; +PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT = NULL; +PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = NULL; +PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT = NULL; +PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT = NULL; +PFNGLDRAWBUFFERSPROC glDrawBuffers = NULL; + +#ifndef GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT +#define GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT 0x8CD8 +#endif + +bool ZZCreate(int width, int height); +void ZZGSStateReset(); + +// flush current vertices, call before setting new registers (the main render method) +void Flush(int context); +void FlushBoth(); + +//extern u32 ptexLogo; +//extern int nLogoWidth, nLogoHeight; +//extern GLuint vboRect; +//void ProcessMessages(); +//void RenderCustom(float fAlpha); // intro anim + +#endif diff --git a/plugins/zzogl-pg-cg/opengl/zpipe.cpp b/plugins/zzogl-pg-cg/opengl/zpipe.cpp new file mode 100644 index 000000000..45f80824d --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/zpipe.cpp @@ -0,0 +1,131 @@ +/* The file is based of zpipe.c + minor rename and minor adaptation + * + * zpipe.c: example of proper use of zlib's inflate() and deflate() + * Not copyrighted -- provided to the public domain + * Version 1.4 11 December 2005 Mark Adler + */ + +#include + +#include +#include +#include + +//#define ZLIB_WINAPI +#include "zlib.h" + +int def(char *src, char *dst, int bytes_to_compress, int *bytes_after_compressed) +{ + z_stream strm; + + int ret; + unsigned have; + + /* allocate deflate state */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + ret = deflateInit(&strm, Z_DEFAULT_COMPRESSION) ; + + if (ret != Z_OK) + return ret; + + /* compress */ + strm.avail_in = bytes_to_compress ; + strm.avail_out = bytes_to_compress ; + + strm.next_in = (Bytef *)src ; + strm.next_out = (Bytef *)dst ; + + ret = deflate(&strm, Z_FINISH) ; + + have = bytes_to_compress - strm.avail_out ; + + *bytes_after_compressed = have ; + + assert(ret == Z_STREAM_END); /* stream will be complete */ + + /* clean up and return */ + (void)deflateEnd(&strm); + + return Z_OK; +} + +int inf(char *src, char *dst, int bytes_to_decompress, int maximum_after_decompress, int* outbytes) +{ + z_stream strm; + + int ret; + + /* allocate inflate state */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit(&strm); + + if (ret != Z_OK) return ret; + + /* decompress */ + strm.avail_in = bytes_to_decompress ; + strm.next_in = (Bytef *)src ; + strm.next_out = (Bytef *)dst ; + strm.avail_out = maximum_after_decompress ; + + ret = inflate(&strm, Z_NO_FLUSH) ; + + assert(ret != Z_STREAM_ERROR); /* state not clobbered */ + + switch (ret) + { + + case Z_NEED_DICT: + ret = Z_DATA_ERROR; /* and fall through */ + + case Z_DATA_ERROR: + + case Z_MEM_ERROR: + (void)inflateEnd(&strm); + return ret; + } + + assert(strm.avail_in == 0); /* all input will be used */ + + if (outbytes != NULL) *outbytes = strm.total_out; + + /* clean up and return */ + (void)inflateEnd(&strm); + + return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR; +} + +/* report a zlib or i/o error */ +void zerr(int ret) +{ + fputs("zpipe: ", stderr); + + switch (ret) + { + + case Z_ERRNO: + if (ferror(stdin)) fputs("error reading stdin\n", stderr); + if (ferror(stdout)) fputs("error writing stdout\n", stderr); + break; + + case Z_STREAM_ERROR: + fputs("invalid compression level\n", stderr); + break; + + case Z_DATA_ERROR: + fputs("invalid or incomplete deflate data\n", stderr); + break; + + case Z_MEM_ERROR: + fputs("out of memory\n", stderr); + break; + + case Z_VERSION_ERROR: + fputs("zlib version mismatch!\n", stderr); + } +} diff --git a/plugins/zzogl-pg-cg/opengl/zpipe.h b/plugins/zzogl-pg-cg/opengl/zpipe.h new file mode 100644 index 000000000..6562c7b5d --- /dev/null +++ b/plugins/zzogl-pg-cg/opengl/zpipe.h @@ -0,0 +1,26 @@ +/* ZZ Open GL graphics plugin + * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com + * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef zpipe_h +#define zpipe_h + +int def(char *src, char *dst, int bytes_to_compress, int *bytes_after_compressed) ; +int inf(char *src, char *dst, int bytes_to_decompress, int maximum_after_decompress, int* outbytes); + +#endif From e3c741bb2a1724e2de91325b32f61e0f743a9cd6 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Thu, 19 Apr 2012 21:22:08 +0000 Subject: [PATCH 70/83] zzogl: painfully merge the zzogl-dev branch * new memory management * asm was replaced by intrinsic * new GLSL backend (AMD only) Cmake is probably broken anyway with the 2 plugins... * and lots of others stuff that I forgot about it ;) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5166 96395faa-99c1-11dd-bbfe-3dabce05a288 --- cmake/BuildParameters.cmake | 8 + cmake/SearchForStuff.cmake | 4 +- cmake/SelectPcsx2Plugins.cmake | 14 +- pcsx2-codeblocks.workspace | 2 +- plugins/zzogl-pg/opengl/CMakeLists.txt | 43 +- plugins/zzogl-pg/opengl/GLWinX11.cpp | 11 + plugins/zzogl-pg/opengl/GS.h | 92 +- plugins/zzogl-pg/opengl/GSmain.cpp | 69 +- plugins/zzogl-pg/opengl/GifTransfer.cpp | 56 +- plugins/zzogl-pg/opengl/HostMemory.cpp | 238 +- plugins/zzogl-pg/opengl/HostMemory.h | 8 +- plugins/zzogl-pg/opengl/Linux/Linux.cpp | 8 +- .../opengl/Linux/zzogl-pg/zzogl-pg.cbp | 76 +- plugins/zzogl-pg/opengl/Mem.cpp | 68 +- plugins/zzogl-pg/opengl/Mem.h | 14 +- plugins/zzogl-pg/opengl/Mem_Swizzle.cpp | 30 +- plugins/zzogl-pg/opengl/Mem_Tables.cpp | 86 + plugins/zzogl-pg/opengl/Mem_Transmit.h | 47 +- plugins/zzogl-pg/opengl/NewRegs.cpp | 1144 -------- plugins/zzogl-pg/opengl/NewRegs.h | 973 ------- plugins/zzogl-pg/opengl/Regs.cpp | 228 +- plugins/zzogl-pg/opengl/Regs.h | 99 +- plugins/zzogl-pg/opengl/Util.h | 2 + plugins/zzogl-pg/opengl/ZZClut.cpp | 2 +- plugins/zzogl-pg/opengl/ZZDepthTargets.cpp | 314 +++ plugins/zzogl-pg/opengl/ZZGl.h | 241 +- plugins/zzogl-pg/opengl/ZZLog.cpp | 26 +- plugins/zzogl-pg/opengl/ZZMemoryTargets.cpp | 620 +++++ plugins/zzogl-pg/opengl/ZZRenderTargets.cpp | 1325 +++++++++ plugins/zzogl-pg/opengl/ZZoglCRTC.cpp | 236 +- plugins/zzogl-pg/opengl/ZZoglCRTC.h | 3 - plugins/zzogl-pg/opengl/ZZoglCreate.cpp | 100 +- plugins/zzogl-pg/opengl/ZZoglFlush.cpp | 670 ++--- plugins/zzogl-pg/opengl/ZZoglFlush.h | 123 + plugins/zzogl-pg/opengl/ZZoglMath.h | 2 +- plugins/zzogl-pg/opengl/ZZoglMem.cpp | 564 ++++ plugins/zzogl-pg/opengl/ZZoglMem.h | 790 ++++++ plugins/zzogl-pg/opengl/ZZoglSave.cpp | 5 +- plugins/zzogl-pg/opengl/ZZoglShaders.cpp | 124 +- plugins/zzogl-pg/opengl/ZZoglShaders.h | 101 +- plugins/zzogl-pg/opengl/ZZoglShadersGLSL.cpp | 979 +++++++ plugins/zzogl-pg/opengl/ps2hw.glsl | 812 ++++++ plugins/zzogl-pg/opengl/targets.cpp | 2403 +---------------- plugins/zzogl-pg/opengl/targets.h | 124 +- plugins/zzogl-pg/opengl/x86.cpp | 6 +- plugins/zzogl-pg/opengl/x86.h | 226 +- plugins/zzogl-pg/opengl/zerogs.cpp | 6 +- 47 files changed, 7412 insertions(+), 5710 deletions(-) delete mode 100644 plugins/zzogl-pg/opengl/NewRegs.cpp delete mode 100644 plugins/zzogl-pg/opengl/NewRegs.h create mode 100644 plugins/zzogl-pg/opengl/ZZDepthTargets.cpp create mode 100644 plugins/zzogl-pg/opengl/ZZMemoryTargets.cpp create mode 100644 plugins/zzogl-pg/opengl/ZZRenderTargets.cpp create mode 100644 plugins/zzogl-pg/opengl/ZZoglFlush.h create mode 100644 plugins/zzogl-pg/opengl/ZZoglMem.cpp create mode 100644 plugins/zzogl-pg/opengl/ZZoglMem.h create mode 100644 plugins/zzogl-pg/opengl/ZZoglShadersGLSL.cpp create mode 100644 plugins/zzogl-pg/opengl/ps2hw.glsl diff --git a/cmake/BuildParameters.cmake b/cmake/BuildParameters.cmake index 542af6712..52e33e63a 100644 --- a/cmake/BuildParameters.cmake +++ b/cmake/BuildParameters.cmake @@ -8,6 +8,7 @@ # Use soundtouch internal lib: -DFORCE_INTERNAL_SOUNDTOUCH=TRUE # Use zlib internal lib: -DFORCE_INTERNAL_ZLIB=TRUE # Use sdl1.3 internal lib: -DFORCE_INTERNAL_SDL=TRUE # Not supported yet +# Use GLSL API(else NVIDIA_CG): -DGLSL_API=TRUE ### GCC optimization options # control C flags : -DUSER_CMAKE_C_FLAGS="cflags" @@ -183,3 +184,10 @@ if(PACKAGE_MODE) # Compile all source codes with these 2 defines add_definitions(-DPLUGIN_DIR_COMPILATION=${PLUGIN_DIR} -DGAMEINDEX_DIR_COMPILATION=${GAMEINDEX_DIR}) endif(PACKAGE_MODE) + +#------------------------------------------------------------------------------- +# Select nvidia cg shader api by default +#------------------------------------------------------------------------------- +if(NOT DEFINED FORCE_INTERNAL_SOUNDTOUCH) + set(GLSL_API FALSE) +endif(NOT DEFINED FORCE_INTERNAL_SOUNDTOUCH) diff --git a/cmake/SearchForStuff.cmake b/cmake/SearchForStuff.cmake index 6c776f100..da39519c8 100644 --- a/cmake/SearchForStuff.cmake +++ b/cmake/SearchForStuff.cmake @@ -53,7 +53,9 @@ if(NOT FORCE_INTERNAL_ZLIB) endif(NOT FORCE_INTERNAL_ZLIB) ## Use pcsx2 package to find module -include(FindCg) +if(NOT GLSL_API) + include(FindCg) +endif(NOT GLSL_API) include(FindGlew) include(FindLibc) include(FindPortAudio) diff --git a/cmake/SelectPcsx2Plugins.cmake b/cmake/SelectPcsx2Plugins.cmake index 88bb76597..4796a5344 100644 --- a/cmake/SelectPcsx2Plugins.cmake +++ b/cmake/SelectPcsx2Plugins.cmake @@ -6,11 +6,15 @@ set(msg_dep_pcsx2 "check these libraries -> wxWidgets (>=2.8.10), gtk2 (>= set(msg_dep_cdvdiso "check these libraries -> bzip2 (>=1.0.5), gtk2 (>=2.16)") set(msg_dep_zerogs "check these libraries -> glew (>=1.5), opengl, X11, nvidia-cg-toolkit (>=2.1)") set(msg_dep_gsdx "check these libraries -> opengl, X11, pcsx2 SDL") -set(msg_dep_zzogl "check these libraries -> glew (>=1.5), jpeg (>=6.2), opengl, X11, nvidia-cg-toolkit (>=2.1), pcsx2 common libs") set(msg_dep_onepad "check these libraries -> sdl (>=1.2)") set(msg_dep_zeropad "check these libraries -> sdl (>=1.2)") set(msg_dep_spu2x "check these libraries -> soundtouch (>=1.5), alsa, portaudio (>=1.9), pcsx2 common libs") set(msg_dep_zerospu2 "check these libraries -> soundtouch (>=1.5), alsa") +if(GLSP_API) + set(msg_dep_zzogl "check these libraries -> glew (>=1.5), jpeg (>=6.2), opengl, X11, pcsx2 common libs") +else(GLSP_API) + set(msg_dep_zzogl "check these libraries -> glew (>=1.5), jpeg (>=6.2), opengl, X11, nvidia-cg-toolkit (>=2.1), pcsx2 common libs") +endif(GLSP_API) #------------------------------------------------------------------------------- # Pcsx2 core & common libs @@ -153,17 +157,17 @@ endif(GLEW_FOUND AND OPENGL_FOUND AND X11_FOUND AND CG_FOUND) # requires: -GLEW # -OpenGL # -X11 -# -CG +# -CG (only with cg build # -JPEG # -common_libs #--------------------------------------- -if(GLEW_FOUND AND OPENGL_FOUND AND X11_FOUND AND CG_FOUND AND JPEG_FOUND AND common_libs) +if((GLEW_FOUND AND OPENGL_FOUND AND X11_FOUND AND JPEG_FOUND AND common_libs) AND (CG_FOUND OR GLSL_API)) set(zzogl TRUE) -else(GLEW_FOUND AND OPENGL_FOUND AND X11_FOUND AND CG_FOUND AND JPEG_FOUND AND common_libs) +else((GLEW_FOUND AND OPENGL_FOUND AND X11_FOUND AND JPEG_FOUND AND common_libs) AND (CG_FOUND OR GLSL_API)) set(zzogl FALSE) message(STATUS "Skip build of zzogl: miss some dependencies") message(STATUS "${msg_dep_zzogl}") -endif(GLEW_FOUND AND OPENGL_FOUND AND X11_FOUND AND CG_FOUND AND JPEG_FOUND AND common_libs) +endif((GLEW_FOUND AND OPENGL_FOUND AND X11_FOUND AND JPEG_FOUND AND common_libs) AND (CG_FOUND OR GLSL_API)) #--------------------------------------- #--------------------------------------- diff --git a/pcsx2-codeblocks.workspace b/pcsx2-codeblocks.workspace index c5d3652b6..939001417 100644 --- a/pcsx2-codeblocks.workspace +++ b/pcsx2-codeblocks.workspace @@ -27,7 +27,7 @@ - + diff --git a/plugins/zzogl-pg/opengl/CMakeLists.txt b/plugins/zzogl-pg/opengl/CMakeLists.txt index c8bed7a17..5c40f84e6 100644 --- a/plugins/zzogl-pg/opengl/CMakeLists.txt +++ b/plugins/zzogl-pg/opengl/CMakeLists.txt @@ -45,6 +45,14 @@ if(CMAKE_BUILD_TYPE STREQUAL Release) add_definitions(${CommonFlags} ${OptimizationFlags} -W) endif(CMAKE_BUILD_TYPE STREQUAL Release) +# Select the shader API +if(GLSL_API) + add_definitions(-DGLSL_API) +else(GLSL_API) + add_definitions(-DNVIDIA_CG_API) +endif(GLSL_API) + + # zzogl sources set(zzoglSources GifTransfer.cpp @@ -54,17 +62,17 @@ set(zzoglSources GSmain.cpp HostMemory.cpp Mem.cpp - # memcpy_amd.cpp Mem_Swizzle.cpp Mem_Tables.cpp Profile.cpp rasterfont.cpp - NewRegs.cpp Regs.cpp targets.cpp - x86.cpp zerogs.cpp zpipe.cpp + ZZDepthTargets.cpp + ZZMemoryTargets.cpp + ZZRenderTargets.cpp ZZClut.cpp ZZHacks.cpp ZZKeyboard.cpp @@ -74,8 +82,10 @@ set(zzoglSources ZZoglCRTC.cpp ZZoglFlush.cpp ZZoglFlushHack.cpp + ZZoglMem.cpp ZZoglSave.cpp ZZoglShaders.cpp + ZZoglShadersGLSL.cpp ZZoglShoots.cpp ZZoglVB.cpp ) @@ -94,7 +104,6 @@ set(zzoglHeaders Mem_Transmit.h Profile.h rasterfont.h - NewRegs.h Regs.h targets.h Util.h @@ -102,21 +111,19 @@ set(zzoglHeaders zerogs.h zpipe.h ZZClut.h + ZZoglFlush.h ZZGl.h ZZHacks.h ZZoglDrawing.h ZZLog.h ZZoglCRTC.h ZZoglMath.h + ZZoglMem.h ZZoglShaders.h ZZoglShoots.h ZZoglVB.h ) -# zzogl S sources -set(zzoglSSources - x86-32.S) - # zzogl shader sources set(zzoglShaderSources ctx0/ps2hw_ctx.fx @@ -131,9 +138,6 @@ set(zzoglLinuxSources set(zzoglLinuxHeaders Linux/Linux.h) -# change language of .S-files to c++ -set_source_files_properties(${zzoglSSources} PROPERTIES LANGUAGE CXX) - # add additional include directories include_directories(. Linux) @@ -142,7 +146,6 @@ include_directories(. add_library(${Output} SHARED ${zzoglSources} ${zzoglHeaders} - ${zzoglSSources} ${zzoglShaderSources} ${zzoglLinuxSources} ${zzoglLinuxHeaders}) @@ -154,7 +157,9 @@ set_target_properties(${Output} PROPERTIES COMPILE_DEFINITIONS USE_GSOPEN2) target_link_libraries(${Output} Utilities) # link target with Cg -target_link_libraries(${Output} ${CG_LIBRARIES}) +if(NOT GLSP_API) + target_link_libraries(${Output} ${CG_LIBRARIES}) +endif(NOT GLSP_API) # link target with glew target_link_libraries(${Output} ${GLEW_LIBRARY}) @@ -183,10 +188,18 @@ endif(NOT USER_CMAKE_LD_FLAGS STREQUAL "") if(PACKAGE_MODE) install(TARGETS ${Output} DESTINATION ${PLUGIN_DIR}) - install(FILES ${PROJECT_SOURCE_DIR}/plugins/zzogl-pg/opengl/ps2hw.dat DESTINATION ${PLUGIN_DIR}) + if(GLSL_API) + install(FILES ${PROJECT_SOURCE_DIR}/plugins/zzogl-pg/opengl/ps2hw.glsl DESTINATION ${PLUGIN_DIR}) + else(GLSL_API) + install(FILES ${PROJECT_SOURCE_DIR}/plugins/zzogl-pg/opengl/ps2hw.dat DESTINATION ${PLUGIN_DIR}) + endif(GLSL_API) else(PACKAGE_MODE) install(TARGETS ${Output} DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins) - install(FILES ${PROJECT_SOURCE_DIR}/plugins/zzogl-pg/opengl/ps2hw.dat DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins) + if(GLSL_API) + install(FILES ${PROJECT_SOURCE_DIR}/plugins/zzogl-pg/opengl/ps2hw.glsl DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins) + else(GLSL_API) + install(FILES ${PROJECT_SOURCE_DIR}/plugins/zzogl-pg/opengl/ps2hw.dat DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins) + endif(GLSL_API) endif(PACKAGE_MODE) ################################### Replay Loader diff --git a/plugins/zzogl-pg/opengl/GLWinX11.cpp b/plugins/zzogl-pg/opengl/GLWinX11.cpp index 0730acc21..764cb9dfc 100644 --- a/plugins/zzogl-pg/opengl/GLWinX11.cpp +++ b/plugins/zzogl-pg/opengl/GLWinX11.cpp @@ -198,13 +198,24 @@ void GLWindow::CreateContextGL() GLXFBConfig *framebuffer_config = glXChooseFBConfig(glDisplay, DefaultScreen(glDisplay), NULL, &fbcount); if (!framebuffer_config or !fbcount) return; +#if 1 // At least create a 3.0 context with compatibility profile int attribs[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, 0, + // GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0 }; +#else + // Create a 3.2 core context without compatibility profile + int attribs[] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 2, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + 0 + }; +#endif GLXContext context_temp = glXCreateContextAttribsARB(glDisplay, framebuffer_config[0], NULL, true, attribs); if (context_temp) { ZZLog::Error_Log("Create a 3.0 opengl context"); diff --git a/plugins/zzogl-pg/opengl/GS.h b/plugins/zzogl-pg/opengl/GS.h index 8bded3f4c..04052bda1 100644 --- a/plugins/zzogl-pg/opengl/GS.h +++ b/plugins/zzogl-pg/opengl/GS.h @@ -21,7 +21,7 @@ #define __GS_H__ -#define USE_OLD_REGS +#define ZZNORMAL_MEMORY #include "Util.h" #include "GifTransfer.h" @@ -39,6 +39,8 @@ extern float fFPS; extern int g_LastCRC; +#define VB_NUMBUFFERS 512 // number of vbo buffer allocated + struct Vector_16F { u16 x, y, z, w; @@ -132,21 +134,22 @@ extern GSconf conf; // PSM values // PSM types == Texture Storage Format -enum PSM_value -{ - PSMCT32 = 0, // 00 0000 - PSMCT24 = 1, // 00 0001 - PSMCT16 = 2, // 00 0010 - PSMCT16S = 10, // 00 1010 - PSMT8 = 19, // 01 0011 - PSMT4 = 20, // 01 0100 - PSMT8H = 27, // 01 1011 - PSMT4HL = 36, // 10 0100 - PSMT4HH = 44, // 10 1100 - PSMT32Z = 48, // 11 0000 - PSMT24Z = 49, // 11 0001 - PSMT16Z = 50, // 11 0010 - PSMT16SZ = 58, // 11 1010 +enum PSM_value{ + PSMCT32 = 0, // 000000 + PSMCT24 = 1, // 000001 + PSMCT16 = 2, // 000010 + PSMCT16S = 10, // 001010 + PSMT8 = 19, // 010011 + PSMT4 = 20, // 010100 + PSMT8H = 27, // 011011 + PSMT4HL = 36, // 100100 + PSMT4HH = 44, // 101100 + PSMT32Z = 48, // 110000 + PSMT24Z = 49, // 110001 + PSMT16Z = 50, // 110010 + PSMT16SZ = 58, // 111010 + + PSMT_BAD_PSM = 63 // for every unknown psm. }; // Check target bit mode. PSMCT32 and 32Z return 0, 24 and 24Z - 1 @@ -461,7 +464,6 @@ typedef struct { u16 aem; u8 ta[2]; - float fta[2]; } texaInfo; typedef struct @@ -503,6 +505,14 @@ typedef struct int fba; } fbaInfo; +enum transfer_types +{ + XFER_HOST_TO_LOCAL = 0, + XFER_LOCAL_TO_HOST = 1, + XFER_LOCAL_TO_LOCAL = 2, + XFER_DEACTIVATED = 3 +}; + typedef struct { Vertex gsvertex[4]; // circular buffer that contains the vertex @@ -537,15 +547,20 @@ typedef struct texaInfo texa; trxposInfo trxpos, trxposnew; - int imageWtemp, imageHtemp; - int imageTransfer; - int imageWnew, imageHnew, imageX, imageY, imageEndX, imageEndY; + bool transferring; + + Point image, imageEnd; + Size imageNew, imageTemp; pathInfo path[4]; GIFRegDIMX dimx; GSMemory mem; GSClut clut_buffer; + + // Subject to change. + int vsync, interlace; + int primNext(int inc = 1) { // Note: ArraySize(gsvertex) == 2^n => modulo is replaced by an and instruction @@ -615,7 +630,7 @@ static __forceinline u32 RGBA16to32(u16 c) (((c) & 0x8000) ? 0xff000000 : 0); } -#if 0 +#ifndef ZZNORMAL_MEMORY // converts float16 [0,1] to BYTE [0,255] (assumes value is in range, otherwise will take lower 8bits) // f is a u16 static __forceinline u16 Float16ToBYTE(u16 f) @@ -984,4 +999,39 @@ inline void CluttingForFlushedTex(tex0Info* tex0, u32 Data, int ictx) #define CPSM_CSA_BITMASK 0x1f780000 #define CPSM_CSA_NOTMASK 0xe0870000 +// I'll find a good place for these later. + +extern PSM_value PSM_value_Table[64]; +extern bool allowed_psm[256]; // in ZZoglMem.cpp.cpp +inline void FillAlowedPsnTable() { + + allowed_psm[PSMCT32] = true; + allowed_psm[PSMCT24] = true; + allowed_psm[PSMCT16] = true; + allowed_psm[PSMCT16S] = true; + allowed_psm[PSMT8] = true; + allowed_psm[PSMT4] = true; + allowed_psm[PSMT8H] = true; + allowed_psm[PSMT4HH] = true; + allowed_psm[PSMT4HL] = true; + allowed_psm[PSMT32Z] = true; + allowed_psm[PSMT24Z] = true; + allowed_psm[PSMT16Z] = true; + allowed_psm[PSMT16SZ] = true; + + PSM_value_Table[PSMCT32] = PSMCT32; + PSM_value_Table[PSMCT24] = PSMCT24; + PSM_value_Table[PSMCT16] = PSMCT16; + PSM_value_Table[PSMCT16S] = PSMCT16S; + PSM_value_Table[PSMT8] = PSMT8; + PSM_value_Table[PSMT4] = PSMT4; + PSM_value_Table[PSMT8H] = PSMT8H; + PSM_value_Table[PSMT4HH] = PSMT4HH; + PSM_value_Table[PSMT4HL] = PSMT4HL; + PSM_value_Table[PSMT32Z] = PSMT32Z; + PSM_value_Table[PSMT24Z] = PSMT24Z; + PSM_value_Table[PSMT16Z] = PSMT16Z; + PSM_value_Table[PSMT16SZ] = PSMT16SZ; +}; + #endif diff --git a/plugins/zzogl-pg/opengl/GSmain.cpp b/plugins/zzogl-pg/opengl/GSmain.cpp index af8a59173..f92417eda 100644 --- a/plugins/zzogl-pg/opengl/GSmain.cpp +++ b/plugins/zzogl-pg/opengl/GSmain.cpp @@ -22,6 +22,7 @@ #include "Profile.h" #include "GLWin.h" #include "ZZoglFlushHack.h" +#include "ZZoglShaders.h" using namespace std; @@ -82,7 +83,7 @@ extern int ZZSave(s8* pbydata); extern bool ZZLoad(s8* pbydata); // switches the render target to the real target, flushes the current render targets and renders the real image -extern void RenderCRTC(int interlace); +extern void RenderCRTC(); #if defined(_WIN32) && defined(_DEBUG) HANDLE g_hCurrentThread = NULL; @@ -91,37 +92,37 @@ HANDLE g_hCurrentThread = NULL; extern int VALIDATE_THRESH; extern u32 TEXDESTROY_THRESH; -u32 CALLBACK PS2EgetLibType() +EXPORT_C_(u32) PS2EgetLibType() { return PS2E_LT_GS; } -char* CALLBACK PS2EgetLibName() +EXPORT_C_(char*) PS2EgetLibName() { return libraryName; } -u32 CALLBACK PS2EgetLibVersion2(u32 type) +EXPORT_C_(u32) PS2EgetLibVersion2(u32 type) { return (zgsversion << 16) | (zgsrevision << 8) | zgsbuild | (zgsminor << 24); } -void CALLBACK GSsetBaseMem(void* pmem) +EXPORT_C_(void) GSsetBaseMem(void* pmem) { g_pBasePS2Mem = (u8*)pmem; } -void CALLBACK GSsetSettingsDir(const char* dir) +EXPORT_C_(void) GSsetSettingsDir(const char* dir) { s_strIniPath = (dir == NULL) ? wxString(L"inis") : wxString(dir, wxConvFile); } -void CALLBACK GSsetLogDir(const char* dir) +EXPORT_C_(void) GSsetLogDir(const char* dir) { ZZLog::SetDir(dir); } -void CALLBACK GSsetGameCRC(int crc, int options) +EXPORT_C_(void) GSsetGameCRC(int crc, int options) { // build a list of function pointer for GetSkipCount (SkipDraw) static GetSkipCount GSC_list[NUMBER_OF_TITLES]; @@ -217,7 +218,7 @@ void CALLBACK GSsetGameCRC(int crc, int options) ListHacks(); } -void CALLBACK GSsetFrameSkip(int frameskip) +EXPORT_C_(void) GSsetFrameSkip(int frameskip) { FUNCLOG s_frameskipping |= frameskip; @@ -232,7 +233,7 @@ void CALLBACK GSsetFrameSkip(int frameskip) } } -void CALLBACK GSreset() +EXPORT_C_(void) GSreset() { FUNCLOG @@ -242,11 +243,11 @@ void CALLBACK GSreset() gs.prac = 1; prim = &gs._prim[0]; - gs.imageTransfer = -1; + gs.transferring = false; gs.q = 1; } -void CALLBACK GSgifSoftReset(u32 mask) +EXPORT_C_(void) GSgifSoftReset(u32 mask) { FUNCLOG @@ -254,11 +255,11 @@ void CALLBACK GSgifSoftReset(u32 mask) if (mask & 2) memset(&gs.path[1], 0, sizeof(gs.path[1])); if (mask & 4) memset(&gs.path[2], 0, sizeof(gs.path[2])); - gs.imageTransfer = -1; + gs.transferring = false; gs.q = 1; } -s32 CALLBACK GSinit() +EXPORT_C_(s32) GSinit() { FUNCLOG @@ -281,7 +282,7 @@ __forceinline void InitMisc() ResetRegs(); } -s32 CALLBACK GSopen(void *pDsp, char *Title, int multithread) +EXPORT_C_(s32) GSopen(void *pDsp, char *Title, int multithread) { FUNCLOG @@ -337,32 +338,34 @@ EXPORT_C_(s32) GSopen2( void* pDsp, u32 flags ) } #endif -void CALLBACK GSshutdown() +EXPORT_C_(void) GSshutdown() { FUNCLOG ZZLog::Close(); } -void CALLBACK GSclose() +EXPORT_C_(void) GSclose() { FUNCLOG ZZDestroy(); GLWin.CloseWindow(); + // Free alocated memory. We could close plugin without closing pcsx2, so we SHOULD free all allocated resources + ZZshExitCleaning(); SaveStateFile = NULL; SaveStateExists = true; // default value g_LastCRC = 0; } -void CALLBACK GSirqCallback(void (*callback)()) +EXPORT_C_(void) GSirqCallback(void (*callback)()) { FUNCLOG GSirq = callback; } -void CALLBACK GSwriteCSR(u32 write) +EXPORT_C_(void) GSwriteCSR(u32 write) { FUNCLOG @@ -373,7 +376,7 @@ void CALLBACK GSwriteCSR(u32 write) #define access _access #endif -void CALLBACK GSchangeSaveState(int newstate, const char* filename) +EXPORT_C_(void) GSchangeSaveState(int newstate, const char* filename) { FUNCLOG @@ -428,7 +431,7 @@ static bool get_snapshot_filename(char *filename, char* path, const char* extens return true; } -void CALLBACK GSmakeSnapshot(char *path) +EXPORT_C_(void) GSmakeSnapshot(char *path) { FUNCLOG @@ -474,7 +477,16 @@ static __forceinline void SetGSTitle() GLWin.SetTitle(strtitle); } -void CALLBACK GSvsync(int interlace) +// This isn't implemented for some reason? Adding a field for it for the moment, till I get a chance to look closer. +EXPORT_C_(void) GSsetVsync(int enabled) +{ + FUNCLOG + + ZZLog::Debug_Log("Setting VSync to 0x%x.", enabled); + gs.vsync = enabled; +} + +EXPORT_C_(void) GSvsync(int current_interlace) { FUNCLOG @@ -506,8 +518,9 @@ void CALLBACK GSvsync(int interlace) g_nRealFrame++; - // !interlace? Hmmm... Fixme. - RenderCRTC(!interlace); + // The value passed seems to either be 0 or 0x2000, and we want 0 or 1. Perhaps !! would be better... + gs.interlace = !current_interlace; + RenderCRTC(); GLWin.ProcessEvents(); @@ -559,7 +572,7 @@ void CALLBACK GSvsync(int interlace) } -void CALLBACK GSreadFIFO(u64 *pMem) +EXPORT_C_(void) GSreadFIFO(u64 *pMem) { FUNCLOG @@ -571,7 +584,7 @@ void CALLBACK GSreadFIFO(u64 *pMem) TransferLocalHost((u32*)pMem, 1); } -void CALLBACK GSreadFIFO2(u64 *pMem, int qwc) +EXPORT_C_(void) GSreadFIFO2(u64 *pMem, int qwc) { FUNCLOG @@ -583,7 +596,7 @@ void CALLBACK GSreadFIFO2(u64 *pMem, int qwc) TransferLocalHost((u32*)pMem, qwc); } -int CALLBACK GSsetupRecording(int start, void* pData) +EXPORT_C_(int) GSsetupRecording(int start, void* pData) { FUNCLOG @@ -595,7 +608,7 @@ int CALLBACK GSsetupRecording(int start, void* pData) return 1; } -s32 CALLBACK GSfreeze(int mode, freezeData *data) +EXPORT_C_(s32) GSfreeze(int mode, freezeData *data) { FUNCLOG diff --git a/plugins/zzogl-pg/opengl/GifTransfer.cpp b/plugins/zzogl-pg/opengl/GifTransfer.cpp index f8be40629..7c42c9a48 100644 --- a/plugins/zzogl-pg/opengl/GifTransfer.cpp +++ b/plugins/zzogl-pg/opengl/GifTransfer.cpp @@ -27,7 +27,7 @@ static int path1_count = 0; static int nPath3Hack = 0; -void CALLBACK GSgetLastTag(u64* ptag) +EXPORT_C_(void) GSgetLastTag(u64* ptag) { FUNCLOG @@ -165,32 +165,36 @@ template void _GSgifTransfer(const u32 *pMem, u32 size) { int len = min(size, path->nloop); //ZZLog::Error_Log("GIF_FLG_IMAGE(%d)=%d", gs.imageTransfer, len); - - switch (gs.imageTransfer) + + if (gs.transferring) { - case 0: - TransferHostLocal(pMem, len * 4); - break; + switch (gs.imageTransfer) + { + case XFER_HOST_TO_LOCAL: + TransferHostLocal(pMem, len * 4); + break; - case 1: - // This can't happen; downloads can not be started or performed as part of - // a GIFtag operation. They're an entirely separate process that can only be - // done through the ReverseFIFO transfer (aka ReadFIFO). --air - assert(0); - //TransferLocalHost(pMem, len); - break; + case XFER_LOCAL_TO_HOST: + // This can't happen; downloads can not be started or performed as part of + // a GIFtag operation. They're an entirely separate process that can only be + // done through the ReverseFIFO transfer (aka ReadFIFO). --air + assert(0); + //TransferLocalHost(pMem, len); + break; - case 2: - //TransferLocalLocal(); - break; + case XFER_LOCAL_TO_LOCAL: + //TransferLocalLocal(); + break; - case 3: - //assert(0); - break; + case XFER_DEACTIVATED: + //assert(0); + break; - default: - //assert(0); - break; + default: + //assert(0); + break; + } + } pMem += len * 4; @@ -236,7 +240,7 @@ template void _GSgifTransfer(const u32 *pMem, u32 size) } } -void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr) +EXPORT_C_(void) GSgifTransfer1(u32 *pMem, u32 addr) { FUNCLOG @@ -250,7 +254,7 @@ void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr) _GSgifTransfer<0>((u32*)((u8*)pMem + addr), (0x4000 - addr) / 16); } -void CALLBACK GSgifTransfer2(u32 *pMem, u32 size) +EXPORT_C_(void) GSgifTransfer2(u32 *pMem, u32 size) { FUNCLOG @@ -259,7 +263,7 @@ void CALLBACK GSgifTransfer2(u32 *pMem, u32 size) _GSgifTransfer<1>(const_cast(pMem), size); } -void CALLBACK GSgifTransfer3(u32 *pMem, u32 size) +EXPORT_C_(void) GSgifTransfer3(u32 *pMem, u32 size) { FUNCLOG @@ -268,7 +272,7 @@ void CALLBACK GSgifTransfer3(u32 *pMem, u32 size) _GSgifTransfer<2>(const_cast(pMem), size); } -void CALLBACK GSgifTransfer(const u32 *pMem, u32 size) +EXPORT_C_(void) GSgifTransfer(const u32 *pMem, u32 size) { FUNCLOG diff --git a/plugins/zzogl-pg/opengl/HostMemory.cpp b/plugins/zzogl-pg/opengl/HostMemory.cpp index 9b762e943..78d610073 100644 --- a/plugins/zzogl-pg/opengl/HostMemory.cpp +++ b/plugins/zzogl-pg/opengl/HostMemory.cpp @@ -18,8 +18,6 @@ */ #include "GS.h" -#include -#include #include #include "Mem.h" @@ -117,14 +115,14 @@ void GetRectMemAddress(int& start, int& end, int psm, int x, int y, int w, int h if (PSMT_ISZTEX(psm)) { - // Somehow, I doubt this code is right. I'll have to look into it. For the moment, I'm keeping it the - // way it was. --arcum42 - + // This still needs an eye kept on it. const BLOCK& b = m_Blocks[psm]; - - bw = (bw + b.width - 1) / b.width; - start = bp * 256 + ((y / b.height) * bw + (x / b.width)) * 0x2000; - end = bp * 256 + (((y + h - 1) / b.height) * bw + (x + w + b.width - 1) / b.width) * 0x2000; + const int x2 = x + w + b.width - 1; + const int y2 = y + h - 1; + bw = bw / b.width; + + start = (bp + ((y / b.height) * bw + (x / b.width)) * 0x20) * 0x100; + end = (bp + ((y2 / b.height) * bw + (x2 / b.width)) * 0x20) * 0x100; return; } @@ -139,46 +137,101 @@ void GetRectMemAddress(int& start, int& end, int psm, int x, int y, int w, int h } else { - // This is what it used to do, which doesn't seem right. - // Keeping it for reference, in case removing it breaks anything. + start /= 2; + end /= 2; + } +} + +// Same as GetRectMemAddress, except that we know x & y are zero, so it's simplified a bit. +void GetRectMemAddressZero(int& start, int& end, int psm, int w, int h, int bp, int bw) +{ + FUNCLOG + u32 bits = 0; + + if (m_Blocks[psm].bpp == 0) + { + ZZLog::Error_Log("ZeroGS: Bad psm 0x%x.", psm); + start = 0; + end = MEMORY_END; + return; + } + + if (PSMT_ISZTEX(psm)) + { + // This still needs an eye kept on it. + const BLOCK& b = m_Blocks[psm]; + const int x2 = w + b.width - 1; + const int y2 = h - 1; + bw = bw / b.width; + + start = bp * 0x100; + end = (bp + ((y2 / b.height) * bw + (x2 / b.width)) * 0x20) * 0x100; + return; + } - //int newx = ((x + w - 1 + 31) & ~31) - 1; - //int newy = ((y + h - 1 + 15) & ~15) - 1; - //start = getPixelAddress4(x, y, bp, bw) / 2; - //end = (getPixelAddress4(max(newx, x), max(newy, y), bp, bw) + 2) / 2; + bits = PSMT_BITS_NUM(psm); + start = getPixelFun[psm](0, 0, bp, bw); + end = getPixelFun[psm](w - 1, h - 1, bp, bw) + 1; + if (bits > 0) + { + start *= bits; + end *= bits; + } + else + { start /= 2; end /= 2; } } + +void GetRectMemAddress(int& start, int& end, int psm, Point p, Size s, int bp, int bw) +{ + GetRectMemAddress(start, end, psm, p.x, p.y, s.w, s.h, bp, bw); +} + +void GetRectMemAddress(int& start, int& end, int psm, int x, int y, Size s, int bp, int bw) +{ + GetRectMemAddress(start, end, psm, x, y, s.w, s.h, bp, bw); +} + +void GetRectMemAddressZero(int& start, int& end, int psm, Size s, int bp, int bw) +{ + GetRectMemAddressZero(start, end, psm, s.w, s.h, bp, bw); +} + void InitTransferHostLocal() { FUNCLOG #if defined(_DEBUG) // Xenosaga 1. - if (gs.trxpos.dx + gs.imageWnew > gs.dstbuf.bw) - ZZLog::Debug_Log("Transfer error, width exceeded. (0x%x > 0X%x)", gs.trxpos.dx + gs.imageWnew, gs.dstbuf.bw); + if (gs.trxpos.dx + gs.imageNew.w > gs.dstbuf.bw) + ZZLog::Debug_Log("Transfer error, width exceeded. (0x%x > 0X%x)", gs.trxpos.dx + gs.imageNew.w, gs.dstbuf.bw); #endif //bool bHasFlushed = false; - gs.imageX = gs.trxpos.dx; - gs.imageY = gs.trxpos.dy; + gs.image.x = gs.trxpos.dx; + gs.image.y = gs.trxpos.dy; - gs.imageEndX = gs.imageX + gs.imageWnew; - gs.imageEndY = gs.imageY + gs.imageHnew; + gs.imageEnd.x = gs.image.x + gs.imageNew.w; + gs.imageEnd.y = gs.image.y + gs.imageNew.h; - assert(gs.imageEndX < 2048 && gs.imageEndY < 2048); + assert(gs.imageEnd.x < 2048 && gs.imageEnd.y < 2048); // This needs to be looked in to, since psm should *not* be 63. // hack! viewful joe - if (gs.dstbuf.psm == 63) gs.dstbuf.psm = 0; + if (gs.dstbuf.psm == 63) + { + ZZLog::WriteLn("gs.dstbuf.psm set to 0!"); + gs.dstbuf.psm = 0; + } int start, end; - GetRectMemAddress(start, end, gs.dstbuf.psm, gs.trxpos.dx, gs.trxpos.dy, gs.imageWnew, gs.imageHnew, gs.dstbuf.bp, gs.dstbuf.bw); + GetRectMemAddress(start, end, gs.dstbuf.psm, gs.trxpos.dx, gs.trxpos.dy, gs.imageNew, gs.dstbuf.bp, gs.dstbuf.bw); if (end > MEMORY_END) { @@ -189,7 +242,7 @@ void InitTransferHostLocal() // MEMORY_END is 0x400000... ZZLog::Warn_Log("Init host local out of bounds! (end == 0x%x)", end); - //gs.imageTransfer = -1; + //gs.transferring = false; end = MEMORY_END; } @@ -198,17 +251,18 @@ void InitTransferHostLocal() if (vb[0].nCount > 0) Flush(0); if (vb[1].nCount > 0) Flush(1); - //ZZLog::Prim_Log("trans: bp:%x x:%x y:%x w:%x h:%x\n", gs.dstbuf.bp, gs.trxpos.dx, gs.trxpos.dy, gs.imageWnew, gs.imageHnew); + //ZZLog::Prim_Log("trans: bp:%x x:%x y:%x w:%x h:%x\n", gs.dstbuf.bp, gs.trxpos.dx, gs.trxpos.dy, gs.imageNew.w, gs.imageNew.h); } void TransferHostLocal(const void* pbyMem, u32 nQWordSize) { FUNCLOG - int start, end; - - GetRectMemAddress(start, end, gs.dstbuf.psm, gs.imageX, gs.imageY, gs.imageWnew, gs.imageHnew, gs.dstbuf.bp, gs.dstbuf.bw); + int start = -1, end = -1; + GetRectMemAddress(start, end, gs.dstbuf.psm, gs.image, gs.imageNew, gs.dstbuf.bp, gs.dstbuf.bw); + + if ((start == -1) || (end == -1)) ZZLog::WriteLn("start == %d, end == %d", start, end); assert(start < gs_imageEnd); end = gs_imageEnd; @@ -272,8 +326,8 @@ void TransferHostLocal(const void* pbyMem, u32 nQWordSize) { tex0Info t; t.tbp0 = gs.dstbuf.bp; - t.tw = gs.imageWnew; - t.th = gs.imageHnew; + t.tw = gs.imageNew.w; + t.th = gs.imageNew.h; t.tbw = gs.dstbuf.bw; t.psm = gs.dstbuf.psm; SaveTex(&t, 0); @@ -285,24 +339,24 @@ void TransferHostLocal(const void* pbyMem, u32 nQWordSize) void InitTransferLocalHost() { FUNCLOG - assert(gs.trxpos.sx + gs.imageWnew <= 2048 && gs.trxpos.sy + gs.imageHnew <= 2048); + assert(gs.trxpos.sx + gs.imageNew.w <= 2048 && gs.trxpos.sy + gs.imageNew.h <= 2048); #if defined(_DEBUG) - if (gs.trxpos.sx + gs.imageWnew > gs.srcbuf.bw) - ZZLog::Debug_Log("Transfer error, width exceeded. (0x%x > 0x%x)", gs.trxpos.sx + gs.imageWnew, gs.srcbuf.bw); + if (gs.trxpos.sx + gs.imageNew.w > gs.srcbuf.bw) + ZZLog::Debug_Log("Transfer error, width exceeded. (0x%x > 0x%x)", gs.trxpos.sx + gs.imageNew.w, gs.srcbuf.bw); #endif - gs.imageX = gs.trxpos.sx; - gs.imageY = gs.trxpos.sy; + gs.image.x = gs.trxpos.sx; + gs.image.y = gs.trxpos.sy; - gs.imageEndX = gs.imageX + gs.imageWnew; - gs.imageEndY = gs.imageY + gs.imageHnew; + gs.imageEnd.x = gs.image.x + gs.imageNew.w; + gs.imageEnd.y = gs.image.y + gs.imageNew.h; s_vTransferCache.resize(0); int start, end; - GetRectMemAddress(start, end, gs.srcbuf.psm, gs.trxpos.sx, gs.trxpos.sy, gs.imageWnew, gs.imageHnew, gs.srcbuf.bp, gs.srcbuf.bw); + GetRectMemAddress(start, end, gs.srcbuf.psm, gs.trxpos.sx, gs.trxpos.sy, gs.imageNew, gs.srcbuf.bp, gs.srcbuf.bw); ResolveInRange(start, end); } @@ -316,16 +370,16 @@ void TransferLocalHost(void* pbyMem, u32 nQWordSize, int& x, int& y, u8 *pstart) T* pbuf = (T*)pbyMem; u32 nSize = nQWordSize * 16 / sizeof(T); - for (; i < gs.imageEndY; ++i) + for (; i < gs.imageEnd.y; ++i) { - for (; j < gs.imageEndX && nSize > 0; ++j, --nSize) + for (; j < gs.imageEnd.x && nSize > 0; ++j, --nSize) { *pbuf++ = rp(pstart, j % 2048, i % 2048, gs.srcbuf.bw); } - if (j >= gs.imageEndX) + if (j >= gs.imageEnd.x) { - assert(j == gs.imageEndX); + assert(j == gs.imageEnd.x); j = gs.trxpos.sx; } else @@ -344,9 +398,9 @@ void TransferLocalHost_24(void* pbyMem, u32 nQWordSize, int& x, int& y, u8 *psta u8* pbuf = (u8*)pbyMem; u32 nSize = nQWordSize * 16 / 3; - for (; i < gs.imageEndY; ++i) + for (; i < gs.imageEnd.y; ++i) { - for (; j < gs.imageEndX && nSize > 0; ++j, --nSize) + for (; j < gs.imageEnd.x && nSize > 0; ++j, --nSize) { u32 p = rp(pstart, j % 2048, i % 2048, gs.srcbuf.bw); pbuf[0] = (u8)p; @@ -355,9 +409,9 @@ void TransferLocalHost_24(void* pbyMem, u32 nQWordSize, int& x, int& y, u8 *psta pbuf += 3; } - if (j >= gs.imageEndX) + if (j >= gs.imageEnd.x) { - assert(j == gs.imageEndX); + assert(j == gs.imageEnd.x); j = gs.trxpos.sx; } else @@ -372,34 +426,34 @@ void TransferLocalHost_24(void* pbyMem, u32 nQWordSize, int& x, int& y, u8 *psta void TransferLocalHost(void* pbyMem, u32 nQWordSize) { FUNCLOG - assert(gs.imageTransfer == 1); + assert(gs.imageTransfer == XFER_LOCAL_TO_HOST); u8* pstart = g_pbyGSMemory + 256 * gs.srcbuf.bp; switch(PSMT_BITMODE(gs.srcbuf.psm)) { - case 0: - TransferLocalHost(pbyMem, nQWordSize, gs.imageY, gs.imageX, pstart); - break; - case 1: - TransferLocalHost_24(pbyMem, nQWordSize, gs.imageY, gs.imageX, pstart); - break; - case 2: - TransferLocalHost(pbyMem, nQWordSize, gs.imageY, gs.imageX, pstart); - break; - case 3: - TransferLocalHost(pbyMem, nQWordSize, gs.imageY, gs.imageX, pstart); - break; - default: - assert(0); - break; + case 0: + TransferLocalHost(pbyMem, nQWordSize, gs.image.y, gs.image.x, pstart); + break; + case 1: + TransferLocalHost_24(pbyMem, nQWordSize, gs.image.y, gs.image.x, pstart); + break; + case 2: + TransferLocalHost(pbyMem, nQWordSize, gs.image.y, gs.image.x, pstart); + break; + case 3: + TransferLocalHost(pbyMem, nQWordSize, gs.image.y, gs.image.x, pstart); + break; + default: + assert(0); + break; } - if (gs.imageY >= gs.imageEndY) + if (gs.image.y >= gs.imageEnd.y) { - ZZLog::Error_Log("gs.imageY >= gs.imageEndY!"); - assert(gs.imageY == gs.imageEndY); - gs.imageTransfer = -1; + ZZLog::Error_Log("gs.image.y >= gs.imageEnd.y!"); + assert(gs.image.y == gs.imageEnd.y); + gs.transferring = false; } } @@ -411,11 +465,11 @@ __forceinline void _TransferLocalLocal() u8* pSrcBuf = g_pbyGSMemory + gs.srcbuf.bp * 256; u8* pDstBuf = g_pbyGSMemory + gs.dstbuf.bp * 256; u32 widthlimit = 4; - u32 maxX = gs.trxpos.sx + gs.imageWnew; - u32 maxY = gs.trxpos.sy + gs.imageHnew; + u32 maxX = gs.trxpos.sx + gs.imageNew.w; + u32 maxY = gs.trxpos.sy + gs.imageNew.h; if (PSMT_BITMODE(gs.srcbuf.psm) == 0) widthlimit = 2; - if ((gs.imageWnew & widthlimit) != 0) return; + if ((gs.imageNew.w & widthlimit) != 0) return; for(u32 i = gs.trxpos.sy, i2 = gs.trxpos.dy; i < maxY; i++, i2++) { @@ -447,10 +501,10 @@ __forceinline void _TransferLocalLocal_4() _getPixelAddress_0 gdp = getPixelFun_0[gs.dstbuf.psm]; u8* pSrcBuf = g_pbyGSMemory + gs.srcbuf.bp * 256; u8* pDstBuf = g_pbyGSMemory + gs.dstbuf.bp * 256; - u32 maxX = gs.trxpos.sx + gs.imageWnew; - u32 maxY = gs.trxpos.sy + gs.imageHnew; + u32 maxX = gs.trxpos.sx + gs.imageNew.w; + u32 maxY = gs.trxpos.sy + gs.imageNew.h; - assert((gs.imageWnew % 8) == 0); + assert((gs.imageNew.w % 8) == 0); for(u32 i = gs.trxpos.sy, i2 = gs.trxpos.dy; i < maxY; ++i, ++i2) { @@ -498,21 +552,21 @@ void TransferLocalLocal() FUNCLOG //ZZLog::Error_Log("I'z in your code, transferring your memory..."); - assert(gs.imageTransfer == 2); - assert(gs.trxpos.sx + gs.imageWnew < 2048 && gs.trxpos.sy + gs.imageHnew < 2048); - assert(gs.trxpos.dx + gs.imageWnew < 2048 && gs.trxpos.dy + gs.imageHnew < 2048); + assert(gs.imageTransfer == XFER_LOCAL_TO_LOCAL); + assert(gs.trxpos.sx + gs.imageNew.w < 2048 && gs.trxpos.sy + gs.imageNew.h < 2048); + assert(gs.trxpos.dx + gs.imageNew.w < 2048 && gs.trxpos.dy + gs.imageNew.h < 2048); assert((gs.srcbuf.psm&0x7) == (gs.dstbuf.psm&0x7)); - if (gs.trxpos.sx + gs.imageWnew > gs.srcbuf.bw) - ZZLog::Debug_Log("Transfer error, src width exceeded.(0x%x > 0x%x)", gs.trxpos.sx + gs.imageWnew, gs.srcbuf.bw); + if (gs.trxpos.sx + gs.imageNew.w > gs.srcbuf.bw) + ZZLog::Debug_Log("Transfer error, src width exceeded.(0x%x > 0x%x)", gs.trxpos.sx + gs.imageNew.w, gs.srcbuf.bw); - if (gs.trxpos.dx + gs.imageWnew > gs.dstbuf.bw) - ZZLog::Debug_Log("Transfer error, dst width exceeded.(0x%x > 0x%x)", gs.trxpos.dx + gs.imageWnew, gs.dstbuf.bw); + if (gs.trxpos.dx + gs.imageNew.w > gs.dstbuf.bw) + ZZLog::Debug_Log("Transfer error, dst width exceeded.(0x%x > 0x%x)", gs.trxpos.dx + gs.imageNew.w, gs.dstbuf.bw); int srcstart, srcend, dststart, dstend; - GetRectMemAddress(srcstart, srcend, gs.srcbuf.psm, gs.trxpos.sx, gs.trxpos.sy, gs.imageWnew, gs.imageHnew, gs.srcbuf.bp, gs.srcbuf.bw); - GetRectMemAddress(dststart, dstend, gs.dstbuf.psm, gs.trxpos.dx, gs.trxpos.dy, gs.imageWnew, gs.imageHnew, gs.dstbuf.bp, gs.dstbuf.bw); + GetRectMemAddress(srcstart, srcend, gs.srcbuf.psm, gs.trxpos.sx, gs.trxpos.sy, gs.imageNew, gs.srcbuf.bp, gs.srcbuf.bw); + GetRectMemAddress(dststart, dstend, gs.dstbuf.psm, gs.trxpos.dx, gs.trxpos.dy, gs.imageNew, gs.dstbuf.bp, gs.dstbuf.bw); // resolve the targs ResolveInRange(srcstart, srcend); @@ -547,15 +601,15 @@ void TransferLocalLocal() { tex0Info t; t.tbp0 = gs.dstbuf.bp; - t.tw = gs.imageWnew; - t.th = gs.imageHnew; + t.tw = gs.imageNew.w; + t.th = gs.imageNew.h; t.tbw = gs.dstbuf.bw; t.psm = gs.dstbuf.psm; SaveTex(&t, 0); t.tbp0 = gs.srcbuf.bp; - t.tw = gs.imageWnew; - t.th = gs.imageHnew; + t.tw = gs.imageNew.w; + t.th = gs.imageNew.h; t.tbw = gs.srcbuf.bw; t.psm = gs.srcbuf.psm; SaveTex(&t, 0); @@ -563,16 +617,4 @@ void TransferLocalLocal() #endif } - -__forceinline void TerminateLocalHost() -{ - FUNCLOG - //ZZLog::Error_Log("Terminate Local Host!"); -} - -__forceinline void TerminateHostLocal() -{ - FUNCLOG - gs.imageTransfer = -1; -} diff --git a/plugins/zzogl-pg/opengl/HostMemory.h b/plugins/zzogl-pg/opengl/HostMemory.h index e9217685d..a49fe1eb8 100644 --- a/plugins/zzogl-pg/opengl/HostMemory.h +++ b/plugins/zzogl-pg/opengl/HostMemory.h @@ -96,7 +96,10 @@ inline u8* _MemoryAddress(int x) } extern void GetRectMemAddress(int& start, int& end, int psm, int x, int y, int w, int h, int bp, int bw); - +extern void GetRectMemAddress(int& start, int& end, int psm, Point p, Size s, int bp, int bw); +extern void GetRectMemAddress(int& start, int& end, int psm, int x, int y, Size s, int bp, int bw); +extern void GetRectMemAddressZero(int& start, int& end, int psm, int w, int h, int bp, int bw); +extern void GetRectMemAddressZero(int& start, int& end, int psm, Size s, int bp, int bw); // called when trxdir is accessed. If host is involved, transfers memory to temp buffer byTransferBuf. // Otherwise performs the transfer. TODO: Perhaps divide the transfers into chunks? @@ -108,7 +111,4 @@ extern void TransferLocalHost(void* pbyMem, u32 nQWordSize); extern void TransferLocalLocal(); -extern void TerminateLocalHost(); -extern void TerminateHostLocal(); - #endif // HOSTMEMORY_H_INCLUDED diff --git a/plugins/zzogl-pg/opengl/Linux/Linux.cpp b/plugins/zzogl-pg/opengl/Linux/Linux.cpp index 3d5609f95..4cf6ee957 100644 --- a/plugins/zzogl-pg/opengl/Linux/Linux.cpp +++ b/plugins/zzogl-pg/opengl/Linux/Linux.cpp @@ -35,7 +35,7 @@ extern bool THR_bCtrl; static map mapConfOpts; static gameHacks tempHacks; -void CALLBACK GSkeyEvent(keyEvent *ev) +EXPORT_C_(void) GSkeyEvent(keyEvent *ev) { static bool bAlt = false; @@ -450,7 +450,7 @@ void DisplayDialog() gtk_widget_destroy(dialog); } -void CALLBACK GSconfigure() +EXPORT_C_(void) GSconfigure() { char strcurdir[256]; getcwd(strcurdir, 256); @@ -484,12 +484,12 @@ void SysMessage(const char *fmt, ...) gtk_widget_destroy(dialog); } -void CALLBACK GSabout() +EXPORT_C_(void) GSabout() { SysMessage("ZZOgl PG: by Zeydlitz (PG version worked on by arcum42, gregory, and the pcsx2 development team). Based off of ZeroGS, by zerofrog."); } -s32 CALLBACK GStest() +EXPORT_C_(s32) GStest() { return 0; } diff --git a/plugins/zzogl-pg/opengl/Linux/zzogl-pg/zzogl-pg.cbp b/plugins/zzogl-pg/opengl/Linux/zzogl-pg/zzogl-pg.cbp index b9bf0a2d4..33f009d05 100644 --- a/plugins/zzogl-pg/opengl/Linux/zzogl-pg/zzogl-pg.cbp +++ b/plugins/zzogl-pg/opengl/Linux/zzogl-pg/zzogl-pg.cbp @@ -16,11 +16,14 @@ + + + @@ -33,12 +36,15 @@ + + + @@ -50,10 +56,69 @@ + + + + + + + \ No newline at end of file diff --git a/plugins/zzogl-pg/opengl/Win32/zerogsogl.vcxproj.filters b/plugins/zzogl-pg/opengl/Win32/zerogsogl.vcxproj.filters index 0a0899e27..c170e2d84 100644 --- a/plugins/zzogl-pg/opengl/Win32/zerogsogl.vcxproj.filters +++ b/plugins/zzogl-pg/opengl/Win32/zerogsogl.vcxproj.filters @@ -114,6 +114,21 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + @@ -203,6 +218,12 @@ Header Files + + Header Files + + + Header Files + @@ -214,4 +235,4 @@ Source Files - + \ No newline at end of file diff --git a/plugins/zzogl-pg/opengl/Win32/zerogsogl_2008.vcproj b/plugins/zzogl-pg/opengl/Win32/zerogsogl_2008.vcproj index 4266a05ab..067f07a25 100644 --- a/plugins/zzogl-pg/opengl/Win32/zerogsogl_2008.vcproj +++ b/plugins/zzogl-pg/opengl/Win32/zerogsogl_2008.vcproj @@ -1,7 +1,7 @@ - - @@ -360,6 +356,10 @@ RelativePath="..\ZZClut.cpp" > + + @@ -372,6 +372,10 @@ RelativePath="..\ZZLog.cpp" > + + @@ -392,6 +396,10 @@ RelativePath="..\ZZoglFlushHack.cpp" > + + @@ -400,6 +408,10 @@ RelativePath="..\ZZoglShaders.cpp" > + + @@ -408,6 +420,10 @@ RelativePath="..\ZZoglVB.cpp" > + + + + @@ -541,6 +561,10 @@ RelativePath="..\ZZoglMath.h" > + + @@ -584,11 +608,11 @@ diff --git a/plugins/zzogl-pg/opengl/ZZClut.cpp b/plugins/zzogl-pg/opengl/ZZClut.cpp index dae5b846c..fba1afc65 100644 --- a/plugins/zzogl-pg/opengl/ZZClut.cpp +++ b/plugins/zzogl-pg/opengl/ZZClut.cpp @@ -21,10 +21,6 @@ #include "Mem.h" #include "Util.h" -#if defined(ZEROGS_SSE2) -#include -#endif - // Local Clut buffer: // It supports both 32 bits and 16 bits colors formats. The size of the buffer is 1KBytes. // The 16 bits entries are arranged in 2 columns. One row is a 32 bits colors. diff --git a/plugins/zzogl-pg/opengl/ZZDepthTargets.cpp b/plugins/zzogl-pg/opengl/ZZDepthTargets.cpp index a46a6a104..6c33f2d46 100644 --- a/plugins/zzogl-pg/opengl/ZZDepthTargets.cpp +++ b/plugins/zzogl-pg/opengl/ZZDepthTargets.cpp @@ -27,10 +27,7 @@ #include "ZZoglShaders.h" #include "ZZClut.h" #include "ZZoglVB.h" - -#ifdef ZEROGS_SSE2 -#include -#endif +#include "Util.h" extern bool g_bUpdateStencil; diff --git a/plugins/zzogl-pg/opengl/ZZGl.h b/plugins/zzogl-pg/opengl/ZZGl.h index 5db66e56f..7513e6fde 100644 --- a/plugins/zzogl-pg/opengl/ZZGl.h +++ b/plugins/zzogl-pg/opengl/ZZGl.h @@ -129,6 +129,26 @@ extern void (APIENTRY *zgsBlendEquationSeparateEXT)(GLenum, GLenum); extern void (APIENTRY *zgsBlendFuncSeparateEXT)(GLenum, GLenum, GLenum, GLenum); #endif +// GL prototypes +extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT; +extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; +extern PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT; +extern PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT; +extern PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT; +extern PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT; +extern PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT; +extern PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT; +extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT; +extern PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT; +extern PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT; +extern PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT; +extern PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT; +extern PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT; +extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT; +extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT; +extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; +extern PFNGLDRAWBUFFERSPROC glDrawBuffers; + static __forceinline void DrawTriangleArray() { glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); @@ -316,24 +336,4 @@ static __forceinline void GL_BLENDEQ_ALPHA(GLenum eq) zgsBlendEquationSeparateEXT(s_rgbeq, s_alphaeq); } -// GL prototypes -extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT; -extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; -extern PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT; -extern PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT; -extern PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT; -extern PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT; -extern PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT; -extern PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT; -extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT; -extern PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT; -extern PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT; -extern PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT; -extern PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT; -extern PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT; -extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT; -extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT; -extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; -extern PFNGLDRAWBUFFERSPROC glDrawBuffers; - #endif // ZZGL_H_INCLUDED diff --git a/plugins/zzogl-pg/opengl/ZZMemoryTargets.cpp b/plugins/zzogl-pg/opengl/ZZMemoryTargets.cpp index 9125d0ee3..f30893eb2 100644 --- a/plugins/zzogl-pg/opengl/ZZMemoryTargets.cpp +++ b/plugins/zzogl-pg/opengl/ZZMemoryTargets.cpp @@ -24,10 +24,7 @@ #include "Mem.h" #include "targets.h" #include "ZZClut.h" - -#ifdef ZEROGS_SSE2 -#include -#endif +#include "Util.h" extern int g_TransferredToGPU; diff --git a/plugins/zzogl-pg/opengl/ZZRenderTargets.cpp b/plugins/zzogl-pg/opengl/ZZRenderTargets.cpp index 7b8ee82ee..04aba8b96 100644 --- a/plugins/zzogl-pg/opengl/ZZRenderTargets.cpp +++ b/plugins/zzogl-pg/opengl/ZZRenderTargets.cpp @@ -27,10 +27,8 @@ #include "ZZoglShaders.h" #include "ZZClut.h" #include "ZZoglVB.h" +#include "Util.h" -#ifdef ZEROGS_SSE2 -#include -#endif extern int g_TransferredToGPU; extern int s_nResolved; diff --git a/plugins/zzogl-pg/opengl/ZZoglMath.h b/plugins/zzogl-pg/opengl/ZZoglMath.h index 048ad9735..205ade684 100644 --- a/plugins/zzogl-pg/opengl/ZZoglMath.h +++ b/plugins/zzogl-pg/opengl/ZZoglMath.h @@ -212,7 +212,7 @@ typedef Vector4 float4; // Reimplement, swiping a bunch of code from GSdx and adapting it. (specifically GSVector.h) // This doesn't include more then half of the functions in there, as well as some of the structs... -#include +#include "Util.h" #include "Pcsx2Types.h" diff --git a/plugins/zzogl-pg/opengl/targets.cpp b/plugins/zzogl-pg/opengl/targets.cpp index bbbb8ea86..1d4e78f7f 100644 --- a/plugins/zzogl-pg/opengl/targets.cpp +++ b/plugins/zzogl-pg/opengl/targets.cpp @@ -27,10 +27,7 @@ #include "ZZoglShaders.h" #include "ZZClut.h" #include "ZZoglVB.h" - -#ifdef ZEROGS_SSE2 -#include -#endif +#include "Util.h" #define RHA //#define RW diff --git a/plugins/zzogl-pg/opengl/x86.cpp b/plugins/zzogl-pg/opengl/x86.cpp index 6b5b1fa28..80dfa5cf3 100644 --- a/plugins/zzogl-pg/opengl/x86.cpp +++ b/plugins/zzogl-pg/opengl/x86.cpp @@ -20,10 +20,7 @@ #include "GS.h" #include "Mem.h" #include "x86.h" - -#if defined(ZEROGS_SSE2) -#include -#endif +#include "Util.h" // Note: all codes of this files is deprecated. Keeping for reference. From 22d9f16c029e495b35afde16e27c51b6225dfb3b Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Sat, 21 Apr 2012 17:39:48 +0000 Subject: [PATCH 74/83] zzogl: remvove old empty files git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5170 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/zzogl-pg-cg/opengl/Win32/zerogsogl.vcxproj | 0 plugins/zzogl-pg-cg/opengl/Win32/zerogsogl.vcxproj.filters | 0 plugins/zzogl-pg-cg/opengl/Win32/zerogsogl_2008.sln | 0 plugins/zzogl-pg-cg/opengl/Win32/zerogsogl_2008.vcproj | 0 4 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 plugins/zzogl-pg-cg/opengl/Win32/zerogsogl.vcxproj delete mode 100644 plugins/zzogl-pg-cg/opengl/Win32/zerogsogl.vcxproj.filters delete mode 100644 plugins/zzogl-pg-cg/opengl/Win32/zerogsogl_2008.sln delete mode 100644 plugins/zzogl-pg-cg/opengl/Win32/zerogsogl_2008.vcproj diff --git a/plugins/zzogl-pg-cg/opengl/Win32/zerogsogl.vcxproj b/plugins/zzogl-pg-cg/opengl/Win32/zerogsogl.vcxproj deleted file mode 100644 index e69de29bb..000000000 diff --git a/plugins/zzogl-pg-cg/opengl/Win32/zerogsogl.vcxproj.filters b/plugins/zzogl-pg-cg/opengl/Win32/zerogsogl.vcxproj.filters deleted file mode 100644 index e69de29bb..000000000 diff --git a/plugins/zzogl-pg-cg/opengl/Win32/zerogsogl_2008.sln b/plugins/zzogl-pg-cg/opengl/Win32/zerogsogl_2008.sln deleted file mode 100644 index e69de29bb..000000000 diff --git a/plugins/zzogl-pg-cg/opengl/Win32/zerogsogl_2008.vcproj b/plugins/zzogl-pg-cg/opengl/Win32/zerogsogl_2008.vcproj deleted file mode 100644 index e69de29bb..000000000 From 595de0a5eb577d07e3d20dbee56590cc1601c07a Mon Sep 17 00:00:00 2001 From: "sudonim1@gmail.com" Date: Mon, 23 Apr 2012 18:46:09 +0000 Subject: [PATCH 75/83] GSDx: dehacked hover description code for hacks git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5171 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSSettingsDlg.cpp | 101 +++++++++++++++++---------------- plugins/GSdx/GSSettingsDlg.h | 18 +----- plugins/GSdx/GSdx.rc | 6 +- plugins/GSdx/resource.h | 4 +- 4 files changed, 59 insertions(+), 70 deletions(-) diff --git a/plugins/GSdx/GSSettingsDlg.cpp b/plugins/GSdx/GSSettingsDlg.cpp index b6bccc52a..6de373635 100644 --- a/plugins/GSdx/GSSettingsDlg.cpp +++ b/plugins/GSdx/GSSettingsDlg.cpp @@ -427,67 +427,70 @@ void GSHacksDlg::OnInit() SendMessage(GetDlgItem(m_hWnd, IDC_SKIPDRAWHACK), UDM_SETPOS, 0, MAKELPARAM(theApp.GetConfig("UserHacks_SkipDraw", 0), 0)); - // Hacks descriptions - SetWindowText(GetDlgItem(m_hWnd, IDC_HACK_DESCRIPTION), ""); // Blank it - - sprintf(Hack[HK_MSAA].description, "Multisample Anti-Aliasing\n\nEnables hardware Anti-Aliasing. Needs lots of memory." - " The Z-24 modes might need to have LogarithmicZ to compensate for the bits lost (DX9 mode)."); - sprintf(Hack[HK_SKIPDRAW].description, "Skipdraw\n\nSkips drawing n surfaces completely. " - "Use it, for example, to try and get rid of messed up post processing effects." - " Try values between 1 and 100."); - sprintf(Hack[HK_ALPHA].description, "Alpha Hack\n\nDifferent alpha handling. Works around some shadow problems."); - sprintf(Hack[HK_OFFSET].description, "Halfpixel\n\nMight fix some misaligned fog, bloom, or blend effect."); - sprintf(Hack[HK_SPRITE].description, "Sprite Hack\n\nHelps getting rid of black inner lines in some filtered sprites." - " Half option should be the preferred one, for Mana Khemia and ArTonelico for example." - " Full should be used for Tales of Destiny."); - sprintf(Hack[HK_WILD].description, "WildArms\n\nLowers the GS precission to avoid gaps between pixels when" - " upscaling. Full option fixes the text on WildArms games, while Half option might improve portraits" - " in ArTonelico for example."); - - SetNotHover(-1); + // Hacks descriptions + SetWindowText(GetDlgItem(m_hWnd, IDC_HACK_DESCRIPTION), ""); // Blank it } void GSHacksDlg::UpdateControls() {} -void GSHacksDlg::SetNotHover(int skip) -{ - for(int i=0; i= 20 && pos.x <= 120) - { - int isHovering = -1; - - if(pos.y >= 28 && pos.y <= 52) isHovering = HK_MSAA; - else if(pos.y >= 54 && pos.y <= 82) isHovering = HK_SKIPDRAW; - else if(pos.y >= 84 && pos.y <= 106) isHovering = HK_ALPHA; - else if(pos.y >= 112 && pos.y <= 134) isHovering = HK_OFFSET; - else if(pos.y >= 140 && pos.y <= 164) isHovering = HK_SPRITE; - else if (pos.y >= 168 && pos.y <= 190) isHovering = HK_WILD; + POINT pos; + GetCursorPos(&pos); + ScreenToClient(m_hWnd, &pos); - if(isHovering > -1 && !Hack[isHovering].isHovered) - { - Hack[isHovering].isHovered = true; - SetWindowText(GetDlgItem(m_hWnd, IDC_HACK_DESCRIPTION), Hack[isHovering].description); - SetNotHover(isHovering); - } - } + HWND hoveredwnd = ChildWindowFromPointEx(m_hWnd, pos, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT); + if (hoveredwnd != hovered_window) + hovered_window = hoveredwnd; + else + break; - } break; + switch (GetDlgCtrlID(hoveredwnd)) + { + case IDC_SKIPDRAWHACK: + case IDC_SKIPDRAWHACKEDIT: + case IDC_STATIC_SKIPDRAW: + helpstr = "Skipdraw\n\nSkips drawing n surfaces completely. " + "Use it, for example, to try and get rid of messed up post processing effects." + " Try values between 1 and 100."; + break; + case IDC_ALPHAHACK: + helpstr = "Alpha Hack\n\nDifferent alpha handling. Works around some shadow problems."; + break; + case IDC_OFFSETHACK: + helpstr = "Halfpixel\n\nMight fix some misaligned fog, bloom, or blend effect."; + break; + case IDC_SPRITEHACK: + helpstr = "Sprite Hack\n\nHelps getting rid of black inner lines in some filtered sprites." + " Half option should be the preferred one, for Mana Khemia and ArTonelico for example." + " Full should be used for Tales of Destiny."; + break; + case IDC_WILDHACK: + helpstr = "WildArms\n\nLowers the GS precission to avoid gaps between pixels when" + " upscaling. Full option fixes the text on WildArms games, while Half option might improve portraits" + " in ArTonelico for example."; + break; + case IDC_MSAACB: + case IDC_STATIC_MSAA: + helpstr = "Multisample Anti-Aliasing\n\nEnables hardware Anti-Aliasing. Needs lots of memory." + " The Z-24 modes might need to have LogarithmicZ to compensate for the bits lost (DX9 mode)."; + break; + default: + helpstr = ""; + break; + } + + SetWindowText(GetDlgItem(m_hWnd, IDC_HACK_DESCRIPTION), helpstr); + + } break; case WM_COMMAND: { diff --git a/plugins/GSdx/GSSettingsDlg.h b/plugins/GSdx/GSSettingsDlg.h index 76eb3729e..b287c077e 100644 --- a/plugins/GSdx/GSSettingsDlg.h +++ b/plugins/GSdx/GSSettingsDlg.h @@ -47,25 +47,9 @@ class GSHacksDlg : public GSDialog bool isdx9; - enum - { - HK_MSAA, - HK_SKIPDRAW, - HK_ALPHA, - HK_OFFSET, - HK_SPRITE, - HK_WILD, - HK_SIZE - }; - - struct - { - bool isHovered; - char description[1024]; - } Hack[HK_SIZE]; + HWND hovered_window; void UpdateControls(); - void SetNotHover(int i); protected: void OnInit(); diff --git a/plugins/GSdx/GSdx.rc b/plugins/GSdx/GSdx.rc index c54234815..3bbfaad9d 100644 --- a/plugins/GSdx/GSdx.rc +++ b/plugins/GSdx/GSdx.rc @@ -81,9 +81,9 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "OK",IDOK,258,182,50,14 GROUPBOX "Hack",IDC_STATIC,7,7,76,165 - GROUPBOX "Description",IDC_STATIC,85,7,223,165 - LTEXT "MSAA",IDC_STATIC,14,20,20,8 - LTEXT "Skipdraw",IDC_STATIC,14,37,30,8 + GROUPBOX "Description",IDC_STATIC,85,7,223,165,0,WS_EX_TRANSPARENT + LTEXT "MSAA",IDC_STATIC_MSAA,14,20,20,8 + LTEXT "Skipdraw",IDC_STATIC_SKIPDRAW,14,37,30,8 EDITTEXT IDC_SKIPDRAWHACKEDIT,45,35,24,14,ES_RIGHT | ES_AUTOHSCROLL CONTROL "",IDC_SKIPDRAWHACK,"msctls_updown32",UDS_SETBUDDYINT | UDS_AUTOBUDDY | UDS_ARROWKEYS,68,35,10,14 CONTROL "Alpha",IDC_ALPHAHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,54,34,10 diff --git a/plugins/GSdx/resource.h b/plugins/GSdx/resource.h index eea77d33f..3cf1d4c3e 100644 --- a/plugins/GSdx/resource.h +++ b/plugins/GSdx/resource.h @@ -90,6 +90,8 @@ #define IDC_HACKSBUTTON 2071 #define IDC_WILDHACK 2072 #define IDC_HACK_DESCRIPTION 2073 +#define IDC_STATIC_MSAA 2074 +#define IDC_STATIC_SKIPDRAW 2075 #define IDC_COLORSPACE 3000 #define IDR_CONVERT_FX 10000 #define IDR_TFX_FX 10001 @@ -108,7 +110,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 10012 #define _APS_NEXT_COMMAND_VALUE 32771 -#define _APS_NEXT_CONTROL_VALUE 2074 +#define _APS_NEXT_CONTROL_VALUE 2076 #define _APS_NEXT_SYMED_VALUE 5000 #endif #endif From 3d700b9264dd2ad5e7c5bf326f22047d4d392623 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Mon, 23 Apr 2012 18:55:24 +0000 Subject: [PATCH 76/83] spu2x: revert commit 5157. Soundtouch author change in mind and go for LGPL2+ so we come back to LGPL3+ to avoid license proliferation. various: * rename the man page as requested by arch users. * Delete pcsx2/* symlink. Was only useful for autotool removed few years ago. * commit the top metadata of my previous branch merge. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5172 96395faa-99c1-11dd-bbfe-3dabce05a288 --- bin/docs/{pcsx2.man => pcsx2.1} | 0 pcsx2/3rdparty | 1 - pcsx2/bin | 1 - plugins/spu2-x/src/WavFile.cpp | 13 ++++++------- plugins/spu2-x/src/WavFile.h | 13 ++++++------- 5 files changed, 12 insertions(+), 16 deletions(-) rename bin/docs/{pcsx2.man => pcsx2.1} (100%) delete mode 120000 pcsx2/3rdparty delete mode 120000 pcsx2/bin diff --git a/bin/docs/pcsx2.man b/bin/docs/pcsx2.1 similarity index 100% rename from bin/docs/pcsx2.man rename to bin/docs/pcsx2.1 diff --git a/pcsx2/3rdparty b/pcsx2/3rdparty deleted file mode 120000 index 2781723b7..000000000 --- a/pcsx2/3rdparty +++ /dev/null @@ -1 +0,0 @@ -../3rdparty/ \ No newline at end of file diff --git a/pcsx2/bin b/pcsx2/bin deleted file mode 120000 index 19f285ac7..000000000 --- a/pcsx2/bin +++ /dev/null @@ -1 +0,0 @@ -../bin \ No newline at end of file diff --git a/plugins/spu2-x/src/WavFile.cpp b/plugins/spu2-x/src/WavFile.cpp index f25abccc1..dc0953ace 100644 --- a/plugins/spu2-x/src/WavFile.cpp +++ b/plugins/spu2-x/src/WavFile.cpp @@ -4,14 +4,13 @@ * The file is based on WavFile.h from SoundTouch library. * Original portions are (c) 2009 by Olli Parviainen (oparviai 'at' iki.fi) * - * This file is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License, version 2.1 - * as published by the Free Software Foundation. + * SPU2-X is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * SPU2-X is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with SPU2-X. If not, see . diff --git a/plugins/spu2-x/src/WavFile.h b/plugins/spu2-x/src/WavFile.h index d65ddb604..2e07f97ed 100644 --- a/plugins/spu2-x/src/WavFile.h +++ b/plugins/spu2-x/src/WavFile.h @@ -4,14 +4,13 @@ * The file is based on WavFile.h from SoundTouch library. * Original portions are (c) 2009 by Olli Parviainen (oparviai 'at' iki.fi) * - * This file is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License, version 2.1 - * as published by the Free Software Foundation. + * SPU2-X is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * SPU2-X is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with SPU2-X. If not, see . From a27142f1a6415b50d2709bbab35b163f519f26e0 Mon Sep 17 00:00:00 2001 From: "sudonim1@gmail.com" Date: Mon, 23 Apr 2012 18:56:22 +0000 Subject: [PATCH 77/83] Set some svn:eol-style properties. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5173 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSRendererCS.cpp | 1730 +++++++------- plugins/GSdx/GSRendererCS.h | 290 +-- plugins/GSdx/config.h | 88 +- plugins/GSdx/res/cs.fx | 766 +++--- plugins/GSdx/res/fxaa.fx | 3992 ++++++++++++++++---------------- plugins/GSdx/res/shadeboost.fx | 150 +- 6 files changed, 3508 insertions(+), 3508 deletions(-) diff --git a/plugins/GSdx/GSRendererCS.cpp b/plugins/GSdx/GSRendererCS.cpp index d9945a907..50fd594cd 100644 --- a/plugins/GSdx/GSRendererCS.cpp +++ b/plugins/GSdx/GSRendererCS.cpp @@ -1,865 +1,865 @@ -/* - * Copyright (C) 2007-2009 Gabest - * http://www.gabest.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Make; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * http://www.gnu.org/copyleft/gpl.html - * - */ - -#include "stdafx.h" -#include "GSRendererCS.h" - -#define PS_BATCH_SIZE 512 - -GSRendererCS::GSRendererCS() - : GSRenderer() -{ - m_nativeres = true; - - memset(m_vm_valid, 0, sizeof(m_vm_valid)); - - memset(m_texture, 0, sizeof(m_texture)); - - m_output = (uint8*)_aligned_malloc(1024 * 1024 * sizeof(uint32), 32); -} - -GSRendererCS::~GSRendererCS() -{ - for(int i = 0; i < countof(m_texture); i++) - { - delete m_texture[i]; - } - - _aligned_free(m_output); -} - -bool GSRendererCS::CreateDevice(GSDevice* dev_unk) -{ - if(!__super::CreateDevice(dev_unk)) - return false; - - HRESULT hr; - - D3D11_DEPTH_STENCIL_DESC dsd; - D3D11_BLEND_DESC bsd; - D3D11_SAMPLER_DESC sd; - D3D11_BUFFER_DESC bd; - D3D11_TEXTURE2D_DESC td; - D3D11_UNORDERED_ACCESS_VIEW_DESC uavd; - D3D11_SHADER_RESOURCE_VIEW_DESC srvd; - - D3D_FEATURE_LEVEL level; - - ((GSDeviceDX*)dev_unk)->GetFeatureLevel(level); - - if(level < D3D_FEATURE_LEVEL_11_0) - return false; - - GSDevice11* dev = (GSDevice11*)dev_unk; - - ID3D11DeviceContext* ctx = *dev; - - // empty depth stencil state - - memset(&dsd, 0, sizeof(dsd)); - - dsd.StencilEnable = false; - dsd.DepthEnable = false; - - hr = (*dev)->CreateDepthStencilState(&dsd, &m_dss); - - if(FAILED(hr)) return false; - - // empty blend state - - memset(&bsd, 0, sizeof(bsd)); - - bsd.RenderTarget[0].BlendEnable = false; - - hr = (*dev)->CreateBlendState(&bsd, &m_bs); - - if(FAILED(hr)) return false; - - // point sampler - - memset(&sd, 0, sizeof(sd)); - - sd.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; - - sd.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; - sd.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; - sd.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; - - sd.MaxLOD = FLT_MAX; - sd.MaxAnisotropy = 16; - sd.ComparisonFunc = D3D11_COMPARISON_NEVER; - - hr = (*dev)->CreateSamplerState(&sd, &m_ss); - - if(FAILED(hr)) return false; - - // link buffer - - memset(&bd, 0, sizeof(bd)); - - bd.ByteWidth = 256 << 20; // 256 MB w00t - bd.StructureByteStride = sizeof(uint32) * 4; // c, z, id, next - bd.Usage = D3D11_USAGE_DEFAULT; - bd.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE; - bd.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; - - hr = (*dev)->CreateBuffer(&bd, NULL, &m_lb); - - { - uint32 data[] = {0, 0, 0xffffffff, 0}; - - D3D11_BOX box; - memset(&box, 0, sizeof(box)); - box.right = sizeof(data); - box.bottom = 1; - box.back = 1; - - ctx->UpdateSubresource(m_lb, 0, &box, data, 0, 0); - } - - if(FAILED(hr)) return false; - - memset(&uavd, 0, sizeof(uavd)); - - uavd.Format = DXGI_FORMAT_UNKNOWN; - uavd.Buffer.NumElements = bd.ByteWidth / bd.StructureByteStride; - uavd.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_COUNTER; - uavd.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; - - hr = (*dev)->CreateUnorderedAccessView(m_lb, &uavd, &m_lb_uav); - - if(FAILED(hr)) return false; - - memset(&srvd, 0, sizeof(srvd)); - - srvd.Format = DXGI_FORMAT_UNKNOWN; - srvd.Buffer.NumElements = bd.ByteWidth / bd.StructureByteStride; - srvd.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; - - hr = (*dev)->CreateShaderResourceView(m_lb, &srvd, &m_lb_srv); - - if(FAILED(hr)) return false; - - // start offset buffer - - memset(&bd, 0, sizeof(bd)); - - bd.ByteWidth = sizeof(uint32) * 2048 * 2048; // index - bd.Usage = D3D11_USAGE_DEFAULT; - bd.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE; - bd.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; - - hr = (*dev)->CreateBuffer(&bd, NULL, &m_sob); - - if(FAILED(hr)) return false; - - memset(&uavd, 0, sizeof(uavd)); - - uavd.Format = DXGI_FORMAT_R32_TYPELESS; - uavd.Buffer.NumElements = bd.ByteWidth / sizeof(uint32); - uavd.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW; - uavd.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; - - hr = (*dev)->CreateUnorderedAccessView(m_sob, &uavd, &m_sob_uav); - - if(FAILED(hr)) return false; - - memset(&srvd, 0, sizeof(srvd)); - - srvd.Format = DXGI_FORMAT_R32_TYPELESS; - srvd.BufferEx.NumElements = bd.ByteWidth / sizeof(uint32); - srvd.BufferEx.Flags = D3D11_BUFFEREX_SRV_FLAG_RAW; - srvd.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX; - - hr = (*dev)->CreateShaderResourceView(m_sob, &srvd, &m_sob_srv); - - if(FAILED(hr)) return false; - - const uint32 tmp = 0; - - ctx->ClearUnorderedAccessViewUint(m_sob_uav, &tmp); // initial clear, next time Draw should restore it in Step 2 - - // video memory (4MB) - - memset(&bd, 0, sizeof(bd)); - - bd.ByteWidth = 4 * 1024 * 1024; - bd.Usage = D3D11_USAGE_DEFAULT; - bd.BindFlags = D3D11_BIND_UNORDERED_ACCESS; - bd.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; - - hr = (*dev)->CreateBuffer(&bd, NULL, &m_vm); - - if(FAILED(hr)) return false; - - memset(&uavd, 0, sizeof(uavd)); - - uavd.Format = DXGI_FORMAT_R32_TYPELESS; - uavd.Buffer.FirstElement = 0; - uavd.Buffer.NumElements = 1024 * 1024; - uavd.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW; - uavd.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; - - hr = (*dev)->CreateUnorderedAccessView(m_vm, &uavd, &m_vm_uav); - - if(FAILED(hr)) return false; -/* - memset(&td, 0, sizeof(td)); - - td.Width = PAGE_SIZE; - td.Height = MAX_PAGES; - td.Format = DXGI_FORMAT_R8_UINT; - td.MipLevels = 1; - td.ArraySize = 1; - td.SampleDesc.Count = 1; - td.SampleDesc.Quality = 0; - td.Usage = D3D11_USAGE_DEFAULT; - td.BindFlags = D3D11_BIND_UNORDERED_ACCESS; - - hr = (*dev)->CreateTexture2D(&td, NULL, &m_vm); - - if(FAILED(hr)) return false; - - memset(&uavd, 0, sizeof(uavd)); - - uavd.Format = DXGI_FORMAT_R8_UINT; - uavd.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; - - hr = (*dev)->CreateUnorderedAccessView(m_vm, &uavd, &m_vm_uav); - - if(FAILED(hr)) return false; -*/ - // one page, for copying between cpu<->gpu - - memset(&bd, 0, sizeof(bd)); - - bd.ByteWidth = PAGE_SIZE; - bd.Usage = D3D11_USAGE_STAGING; - bd.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; - - hr = (*dev)->CreateBuffer(&bd, NULL, &m_pb); - - if(FAILED(hr)) return false; -/* - memset(&td, 0, sizeof(td)); - - td.Width = PAGE_SIZE; - td.Height = 1; - td.Format = DXGI_FORMAT_R8_UINT; - td.MipLevels = 1; - td.ArraySize = 1; - td.SampleDesc.Count = 1; - td.SampleDesc.Quality = 0; - td.Usage = D3D11_USAGE_STAGING; - td.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; - - hr = (*dev)->CreateTexture2D(&td, NULL, &m_pb); - - if(FAILED(hr)) return false; -*/ - // VSConstantBuffer - - memset(&bd, 0, sizeof(bd)); - - bd.ByteWidth = sizeof(VSConstantBuffer); - bd.Usage = D3D11_USAGE_DEFAULT; - bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - - hr = (*dev)->CreateBuffer(&bd, NULL, &m_vs_cb); - - if(FAILED(hr)) return false; - - // PS - - D3D11_SHADER_MACRO macro[] = - { - {NULL, NULL}, - }; - - hr = dev->CompileShader(IDR_CS_FX, "ps_main0", macro, &m_ps0); - - if(FAILED(hr)) return false; - - // PSConstantBuffer - - memset(&bd, 0, sizeof(bd)); - - bd.ByteWidth = sizeof(PSConstantBuffer); - bd.Usage = D3D11_USAGE_DEFAULT; - bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - - hr = (*dev)->CreateBuffer(&bd, NULL, &m_ps_cb); - - if(FAILED(hr)) return false; - - // - - return true; -} - -void GSRendererCS::ResetDevice() -{ - for(int i = 0; i < countof(m_texture); i++) - { - delete m_texture[i]; - - m_texture[i] = NULL; - } -} - -void GSRendererCS::VSync(int field) -{ - __super::VSync(field); - - //printf("%lld\n", m_perfmon.GetFrame()); -} - -GSTexture* GSRendererCS::GetOutput(int i) -{ - // TODO: create a compute shader which unswizzles the frame from m_vm to the output texture - - const GSRegDISPFB& DISPFB = m_regs->DISP[i].DISPFB; - - int w = DISPFB.FBW * 64; - int h = GetFrameRect(i).bottom; - - // TODO: round up bottom - - if(m_dev->ResizeTexture(&m_texture[i], w, h)) - { - const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[DISPFB.PSM]; - - GSVector4i r(0, 0, w, h); - GSVector4i r2 = r.ralign(psm.bs); - - GSOffset* o = m_mem.GetOffset(DISPFB.Block(), DISPFB.FBW, DISPFB.PSM); - - Read(o, r2, false); - - (m_mem.*psm.rtx)(o, r2, m_output, 1024 * 4, m_env.TEXA); - - m_texture[i]->Update(r, m_output, 1024 * 4); - - if(s_dump) - { - if(s_save && s_n >= s_saven) - { - m_texture[i]->Save(format("c:\\temp1\\_%05d_f%lld_fr%d_%05x_%d.bmp", s_n, m_perfmon.GetFrame(), i, (int)DISPFB.Block(), (int)DISPFB.PSM)); - } - - s_n++; - } - } - - return m_texture[i]; -} - -void GSRendererCS::Draw() -{ - GSDrawingEnvironment& env = m_env; - GSDrawingContext* context = m_context; - - GSVector2i rtsize(2048, 2048); - GSVector4i scissor = GSVector4i(context->scissor.in).rintersect(GSVector4i(rtsize).zwxy()); - GSVector4i bbox = GSVector4i(m_vt.m_min.p.floor().xyxy(m_vt.m_max.p.ceil())); - GSVector4i r = bbox.rintersect(scissor); - - uint32 fm = context->FRAME.FBMSK; - uint32 zm = context->ZBUF.ZMSK || context->TEST.ZTE == 0 ? 0xffffffff : 0; - - if(fm != 0xffffffff) - { - Write(context->offset.fb, r); - - // TODO: m_tc->InvalidateVideoMem(context->offset.fb, r, false); - } - - if(zm != 0xffffffff) - { - Write(context->offset.zb, r); - - // TODO: m_tc->InvalidateVideoMem(context->offset.zb, r, false); - } - - // TODO: if(24-bit) fm/zm |= 0xff000000; - - if(PRIM->TME) - { - m_mem.m_clut.Read32(context->TEX0, env.TEXA); - - GSVector4i r; - - GetTextureMinMax(r, context->TEX0, context->CLAMP, m_vt.IsLinear()); - - // TODO: unswizzle pages of r to a texture, check m_vm_valid, bit not set cpu->gpu, set gpu->gpu - - // TODO: Write transfer should directly write to m_vm, then Read/Write syncing won't be necessary, clut must be updated with the gpu also - - // TODO: tex = m_tc->LookupSource(context->TEX0, env.TEXA, r); - - // if(!tex) return; - } - - // - - GSDevice11* dev = (GSDevice11*)m_dev; - - ID3D11DeviceContext* ctx = *dev; - - // - - dev->BeginScene(); - - // SetupOM - - dev->OMSetDepthStencilState(m_dss, 0); - dev->OMSetBlendState(m_bs, 0); - - ID3D11UnorderedAccessView* uavs[] = {m_vm_uav, m_lb_uav, m_sob_uav}; - uint32 counters[] = {1, 0, 0}; - - dev->OMSetRenderTargets(rtsize, countof(uavs), uavs, counters, &scissor); - - // SetupIA - - D3D11_PRIMITIVE_TOPOLOGY topology; - - switch(m_vt.m_primclass) - { - case GS_POINT_CLASS: - topology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; - break; - case GS_LINE_CLASS: - case GS_SPRITE_CLASS: - topology = D3D11_PRIMITIVE_TOPOLOGY_LINELIST; - break; - case GS_TRIANGLE_CLASS: - topology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; - break; - default: - __assume(0); - } - - GSVector4i r2 = bbox.add32(GSVector4i(-1, -1, 1, 1)).rintersect(scissor); - - m_vertex.buff[m_vertex.next + 0].XYZ.X = context->XYOFFSET.OFX + (r2.left << 4); - m_vertex.buff[m_vertex.next + 0].XYZ.Y = context->XYOFFSET.OFY + (r2.top << 4); - m_vertex.buff[m_vertex.next + 1].XYZ.X = context->XYOFFSET.OFX + (r2.right << 4); - m_vertex.buff[m_vertex.next + 1].XYZ.Y = context->XYOFFSET.OFY + (r2.bottom << 4); - - m_index.buff[m_index.tail + 0] = m_vertex.next + 0; - m_index.buff[m_index.tail + 1] = m_vertex.next + 1; - - dev->IASetVertexBuffer(m_vertex.buff, sizeof(GSVertex), m_vertex.next + 2); - dev->IASetIndexBuffer(m_index.buff, m_index.tail + 2); - - // SetupVS - - VSSelector vs_sel; - - vs_sel.tme = PRIM->TME; - vs_sel.fst = PRIM->FST; - - VSConstantBuffer vs_cb; - - float sx = 2.0f / (rtsize.x << 4); - float sy = 2.0f / (rtsize.y << 4); - //float sx = 1.0f / 16; - //float sy = 1.0f / 16; - float ox = (float)(int)context->XYOFFSET.OFX; - float oy = (float)(int)context->XYOFFSET.OFY; - - vs_cb.VertexScale = GSVector4(sx, -sy, 0.0f, 0.0f); - vs_cb.VertexOffset = GSVector4(ox * sx + 1, -(oy * sy + 1), 0.0f, -1.0f); - //vs_cb.VertexScale = GSVector4(sx, sy, 0.0f, 0.0f); - //vs_cb.VertexOffset = GSVector4(ox * sx, oy * sy, 0.0f, -1.0f); - - { - GSVertexShader11 vs; - - hash_map::const_iterator i = m_vs.find(vs_sel); - - if(i != m_vs.end()) - { - vs = i->second; - } - else - { - string str[2]; - - str[0] = format("%d", vs_sel.tme); - str[1] = format("%d", vs_sel.fst); - - D3D11_SHADER_MACRO macro[] = - { - {"VS_TME", str[0].c_str()}, - {"VS_FST", str[1].c_str()}, - {NULL, NULL}, - }; - - D3D11_INPUT_ELEMENT_DESC layout[] = - { - {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, - {"COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0}, - {"TEXCOORD", 1, DXGI_FORMAT_R32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}, - {"POSITION", 0, DXGI_FORMAT_R16G16_UINT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0}, - {"POSITION", 1, DXGI_FORMAT_R32_UINT, 0, 20, D3D11_INPUT_PER_VERTEX_DATA, 0}, - {"TEXCOORD", 2, DXGI_FORMAT_R16G16_UINT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0}, - {"COLOR", 1, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 28, D3D11_INPUT_PER_VERTEX_DATA, 0}, - }; - - dev->CompileShader(IDR_CS_FX, "vs_main", macro, &vs.vs, layout, countof(layout), &vs.il); - - m_vs[vs_sel] = vs; - } - - ctx->UpdateSubresource(m_vs_cb, 0, NULL, &vs_cb, 0, 0); // TODO: only update if changed - - dev->VSSetShader(vs.vs, m_vs_cb); - - dev->IASetInputLayout(vs.il); - } - - // SetupGS - - GSSelector gs_sel; - - gs_sel.iip = PRIM->IIP; - - CComPtr gs[2]; - - for(int j = 0; j < 2; j++) - { - gs_sel.prim = j == 0 ? m_vt.m_primclass : GS_SPRITE_CLASS; - - hash_map >::const_iterator i = m_gs.find(gs_sel); - - if(i != m_gs.end()) - { - gs[j] = i->second; - } - else - { - string str[2]; - - str[0] = format("%d", gs_sel.iip); - str[1] = format("%d", j == 0 ? gs_sel.prim : GS_SPRITE_CLASS); - - D3D11_SHADER_MACRO macro[] = - { - {"GS_IIP", str[0].c_str()}, - {"GS_PRIM", str[1].c_str()}, - {NULL, NULL}, - }; - - dev->CompileShader(IDR_CS_FX, "gs_main", macro, &gs[j]); - - m_gs[gs_sel] = gs[j]; - } - } - - // SetupPS - - dev->PSSetSamplerState(m_ss, NULL, NULL); - - PSSelector ps_sel; - - ps_sel.fpsm = context->FRAME.PSM; - ps_sel.zpsm = context->ZBUF.PSM; - - CComPtr ps[2] = {m_ps0, NULL}; - - hash_map >::const_iterator i = m_ps1.find(ps_sel); - - if(i != m_ps1.end()) - { - ps[1] = i->second; - } - else - { - string str[15]; - - str[0] = format("%d", PS_BATCH_SIZE); - str[1] = format("%d", context->FRAME.PSM); - str[2] = format("%d", context->ZBUF.PSM); - - D3D11_SHADER_MACRO macro[] = - { - {"PS_BATCH_SIZE", str[0].c_str()}, - {"PS_FPSM", str[1].c_str()}, - {"PS_ZPSM", str[2].c_str()}, - {NULL, NULL}, - }; - - dev->CompileShader(IDR_CS_FX, "ps_main1", macro, &ps[1]); - - m_ps1[ps_sel] = ps[1]; - } - - PSConstantBuffer ps_cb; - - ps_cb.fm = fm; - ps_cb.zm = zm; - - ctx->UpdateSubresource(m_ps_cb, 0, NULL, &ps_cb, 0, 0); // TODO: only update if changed - - OffsetBuffer* fzbo = NULL; - - GetOffsetBuffer(&fzbo); - - dev->PSSetShaderResourceView(0, fzbo->row_srv); - dev->PSSetShaderResourceView(1, fzbo->col_srv); - // TODO: palette, texture - - int step = PS_BATCH_SIZE * GSUtil::GetVertexCount(PRIM->PRIM); - - for(int i = 0; i < m_index.tail; i += step) - { - dev->IASetPrimitiveTopology(topology); - dev->GSSetShader(gs[0]); - dev->PSSetShader(ps[0], m_ps_cb); - dev->DrawIndexedPrimitive(i, std::min(m_index.tail - i, step)); - - dev->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST); - dev->GSSetShader(gs[1]); - dev->PSSetShader(ps[1], m_ps_cb); - dev->DrawIndexedPrimitive(m_index.tail, 2); - - //printf("%d/%d, %d %d %d %d\n", i, m_index.tail, r2.x, r2.y, r2.z, r2.w); - } - - dev->EndScene(); - - if(0) - { - std::string s; - /* - s = format("c:\\temp1\\_%05d_f%lld_fb0_%05x_%d.bmp", s_n, m_perfmon.GetFrame(), 0, 0); - m_mem.SaveBMP(s, 0, 16, PSM_PSMCT32, 1024, 1024); - Read(m_mem.GetOffset(0, 16, PSM_PSMCT32), GSVector4i(0, 0, 1024, 1024), false); - */ - // - if(fm != 0xffffffff) Read(context->offset.fb, r, false); - // - if(zm != 0xffffffff) Read(context->offset.zb, r, false); - - s = format("c:\\temp1\\_%05d_f%lld_rt1_%05x_%d.bmp", s_n, m_perfmon.GetFrame(), m_context->FRAME.Block(), m_context->FRAME.PSM); - m_mem.SaveBMP(s, m_context->FRAME.Block(), m_context->FRAME.FBW, m_context->FRAME.PSM, GetFrameRect().width(), 512); - - s = format("c:\\temp1\\_%05d_f%lld_zt1_%05x_%d.bmp", s_n, m_perfmon.GetFrame(), m_context->ZBUF.Block(), m_context->ZBUF.PSM); - m_mem.SaveBMP(s, m_context->ZBUF.Block(), m_context->FRAME.FBW, m_context->ZBUF.PSM, GetFrameRect().width(), 512); - - /* - s = format("c:\\temp1\\_%05d_f%lld_fb1_%05x_%d.bmp", s_n, m_perfmon.GetFrame(), 0, 0); - m_mem.SaveBMP(s, 0, 16, PSM_PSMCT32, 1024, 1024); - */ - - s_n++; - } -} - -void GSRendererCS::InvalidateVideoMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r) -{ - GSOffset* o = m_mem.GetOffset(BITBLTBUF.DBP, BITBLTBUF.DBW, BITBLTBUF.DPSM); - - Read(o, r, true); // TODO: fully overwritten pages are not needed to be read, only invalidated (important) - - // TODO: false deps, 8H/4HL/4HH texture sharing pages with 24-bit target - // TODO: invalidate texture cache -} - -void GSRendererCS::InvalidateLocalMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r, bool clut) -{ - GSOffset* o = m_mem.GetOffset(BITBLTBUF.SBP, BITBLTBUF.SBW, BITBLTBUF.SPSM); - - Read(o, r, false); -} - -void GSRendererCS::Write(GSOffset* o, const GSVector4i& r) -{ - GSDevice11* dev = (GSDevice11*)m_dev; - - ID3D11DeviceContext* ctx = *dev; - - D3D11_BOX box; - - memset(&box, 0, sizeof(box)); - - box.right = 1; - box.bottom = 1; - box.back = 1; - - uint32* pages = o->GetPages(r); - - for(size_t i = 0; pages[i] != GSOffset::EOP; i++) - { - uint32 page = pages[i]; - - uint32 row = page >> 5; - uint32 col = 1 << (page & 31); - - if((m_vm_valid[row] & col) == 0) - { - m_vm_valid[row] |= col; - - box.left = page * PAGE_SIZE; - box.right = (page + 1) * PAGE_SIZE; - - ctx->UpdateSubresource(m_vm, 0, &box, m_mem.m_vm8 + page * PAGE_SIZE, 0, 0); -/* - // m_vm texture row is 2k in bytes, one page is 8k => starting row: addr / 4k, number of rows: 8k / 2k = 4 - - box.left = 0; - box.right = PAGE_SIZE; - box.top = page; - box.bottom = box.top + 1; - - ctx->UpdateSubresource(m_vm, 0, &box, m_mem.m_vm8 + page * PAGE_SIZE, 0, 0); -*/ - if(0) - printf("[%lld] write %05x %d %d (%d)\n", __rdtsc(), o->bp, o->bw, o->psm, page); - } - } - - delete [] pages; -} - -void GSRendererCS::Read(GSOffset* o, const GSVector4i& r, bool invalidate) -{ - GSDevice11* dev = (GSDevice11*)m_dev; - - ID3D11DeviceContext* ctx = *dev; - - D3D11_BOX box; - - memset(&box, 0, sizeof(box)); - - box.right = 1; - box.bottom = 1; - box.back = 1; - - uint32* pages = o->GetPages(r); - - for(size_t i = 0; pages[i] != GSOffset::EOP; i++) - { - uint32 page = pages[i]; - - uint32 row = page >> 5; - uint32 col = 1 << (page & 31); - - if(m_vm_valid[row] & col) - { - if(invalidate) - { - m_vm_valid[row] ^= col; - } - - box.left = page * PAGE_SIZE; - box.right = (page + 1) * PAGE_SIZE; - - ctx->CopySubresourceRegion(m_pb, 0, 0, 0, 0, m_vm, 0, &box); -/* - // m_vm texture row is 2k in bytes, one page is 8k => starting row: addr / 4k, number of rows: 8k / 2k = 4 - - box.left = 0; - box.right = PAGE_SIZE; - box.top = page; - box.bottom = box.top + 1; - - ctx->CopySubresourceRegion(m_pb, 0, 0, 0, 0, m_vm, 0, &box); -*/ - D3D11_MAPPED_SUBRESOURCE map; - - if(SUCCEEDED(ctx->Map(m_pb, 0, D3D11_MAP_READ, 0, &map))) - { - memcpy(m_mem.m_vm8 + page * PAGE_SIZE, map.pData, PAGE_SIZE); - - ctx->Unmap(m_pb, 0); - - if(0) - printf("[%lld] read %05x %d %d (%d)\n", __rdtsc(), o->bp, o->bw, o->psm, page); - } - } - } - - delete [] pages; -} - -bool GSRendererCS::GetOffsetBuffer(OffsetBuffer** fzbo) -{ - HRESULT hr; - - GSDevice11* dev = (GSDevice11*)m_dev; - - D3D11_BUFFER_DESC bd; - D3D11_SHADER_RESOURCE_VIEW_DESC srvd; - D3D11_SUBRESOURCE_DATA data; - - hash_map::iterator i = m_offset.find(m_context->offset.fzb->hash); - - if(i == m_offset.end()) - { - OffsetBuffer ob; - - memset(&bd, 0, sizeof(bd)); - - bd.ByteWidth = sizeof(GSVector2i) * 2048; - bd.Usage = D3D11_USAGE_IMMUTABLE; - bd.BindFlags = D3D11_BIND_SHADER_RESOURCE; - - memset(&data, 0, sizeof(data)); - - data.pSysMem = m_context->offset.fzb->row; - - hr = (*dev)->CreateBuffer(&bd, &data, &ob.row); - - if(FAILED(hr)) return false; - - data.pSysMem = m_context->offset.fzb->col; - - hr = (*dev)->CreateBuffer(&bd, &data, &ob.col); - - if(FAILED(hr)) return false; - - memset(&srvd, 0, sizeof(srvd)); - - srvd.Format = DXGI_FORMAT_R32G32_SINT; - srvd.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; - srvd.Buffer.FirstElement = 0; - srvd.Buffer.NumElements = 2048; - - hr = (*dev)->CreateShaderResourceView(ob.row, &srvd, &ob.row_srv); - - if(FAILED(hr)) return false; - - hr = (*dev)->CreateShaderResourceView(ob.col, &srvd, &ob.col_srv); - - if(FAILED(hr)) return false; - - m_offset[m_context->offset.fzb->hash] = ob; - - i = m_offset.find(m_context->offset.fzb->hash); - } - - *fzbo = &i->second; - - return true; -} +/* + * Copyright (C) 2007-2009 Gabest + * http://www.gabest.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "stdafx.h" +#include "GSRendererCS.h" + +#define PS_BATCH_SIZE 512 + +GSRendererCS::GSRendererCS() + : GSRenderer() +{ + m_nativeres = true; + + memset(m_vm_valid, 0, sizeof(m_vm_valid)); + + memset(m_texture, 0, sizeof(m_texture)); + + m_output = (uint8*)_aligned_malloc(1024 * 1024 * sizeof(uint32), 32); +} + +GSRendererCS::~GSRendererCS() +{ + for(int i = 0; i < countof(m_texture); i++) + { + delete m_texture[i]; + } + + _aligned_free(m_output); +} + +bool GSRendererCS::CreateDevice(GSDevice* dev_unk) +{ + if(!__super::CreateDevice(dev_unk)) + return false; + + HRESULT hr; + + D3D11_DEPTH_STENCIL_DESC dsd; + D3D11_BLEND_DESC bsd; + D3D11_SAMPLER_DESC sd; + D3D11_BUFFER_DESC bd; + D3D11_TEXTURE2D_DESC td; + D3D11_UNORDERED_ACCESS_VIEW_DESC uavd; + D3D11_SHADER_RESOURCE_VIEW_DESC srvd; + + D3D_FEATURE_LEVEL level; + + ((GSDeviceDX*)dev_unk)->GetFeatureLevel(level); + + if(level < D3D_FEATURE_LEVEL_11_0) + return false; + + GSDevice11* dev = (GSDevice11*)dev_unk; + + ID3D11DeviceContext* ctx = *dev; + + // empty depth stencil state + + memset(&dsd, 0, sizeof(dsd)); + + dsd.StencilEnable = false; + dsd.DepthEnable = false; + + hr = (*dev)->CreateDepthStencilState(&dsd, &m_dss); + + if(FAILED(hr)) return false; + + // empty blend state + + memset(&bsd, 0, sizeof(bsd)); + + bsd.RenderTarget[0].BlendEnable = false; + + hr = (*dev)->CreateBlendState(&bsd, &m_bs); + + if(FAILED(hr)) return false; + + // point sampler + + memset(&sd, 0, sizeof(sd)); + + sd.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; + + sd.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + sd.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + sd.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + + sd.MaxLOD = FLT_MAX; + sd.MaxAnisotropy = 16; + sd.ComparisonFunc = D3D11_COMPARISON_NEVER; + + hr = (*dev)->CreateSamplerState(&sd, &m_ss); + + if(FAILED(hr)) return false; + + // link buffer + + memset(&bd, 0, sizeof(bd)); + + bd.ByteWidth = 256 << 20; // 256 MB w00t + bd.StructureByteStride = sizeof(uint32) * 4; // c, z, id, next + bd.Usage = D3D11_USAGE_DEFAULT; + bd.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE; + bd.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; + + hr = (*dev)->CreateBuffer(&bd, NULL, &m_lb); + + { + uint32 data[] = {0, 0, 0xffffffff, 0}; + + D3D11_BOX box; + memset(&box, 0, sizeof(box)); + box.right = sizeof(data); + box.bottom = 1; + box.back = 1; + + ctx->UpdateSubresource(m_lb, 0, &box, data, 0, 0); + } + + if(FAILED(hr)) return false; + + memset(&uavd, 0, sizeof(uavd)); + + uavd.Format = DXGI_FORMAT_UNKNOWN; + uavd.Buffer.NumElements = bd.ByteWidth / bd.StructureByteStride; + uavd.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_COUNTER; + uavd.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; + + hr = (*dev)->CreateUnorderedAccessView(m_lb, &uavd, &m_lb_uav); + + if(FAILED(hr)) return false; + + memset(&srvd, 0, sizeof(srvd)); + + srvd.Format = DXGI_FORMAT_UNKNOWN; + srvd.Buffer.NumElements = bd.ByteWidth / bd.StructureByteStride; + srvd.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; + + hr = (*dev)->CreateShaderResourceView(m_lb, &srvd, &m_lb_srv); + + if(FAILED(hr)) return false; + + // start offset buffer + + memset(&bd, 0, sizeof(bd)); + + bd.ByteWidth = sizeof(uint32) * 2048 * 2048; // index + bd.Usage = D3D11_USAGE_DEFAULT; + bd.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE; + bd.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; + + hr = (*dev)->CreateBuffer(&bd, NULL, &m_sob); + + if(FAILED(hr)) return false; + + memset(&uavd, 0, sizeof(uavd)); + + uavd.Format = DXGI_FORMAT_R32_TYPELESS; + uavd.Buffer.NumElements = bd.ByteWidth / sizeof(uint32); + uavd.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW; + uavd.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; + + hr = (*dev)->CreateUnorderedAccessView(m_sob, &uavd, &m_sob_uav); + + if(FAILED(hr)) return false; + + memset(&srvd, 0, sizeof(srvd)); + + srvd.Format = DXGI_FORMAT_R32_TYPELESS; + srvd.BufferEx.NumElements = bd.ByteWidth / sizeof(uint32); + srvd.BufferEx.Flags = D3D11_BUFFEREX_SRV_FLAG_RAW; + srvd.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX; + + hr = (*dev)->CreateShaderResourceView(m_sob, &srvd, &m_sob_srv); + + if(FAILED(hr)) return false; + + const uint32 tmp = 0; + + ctx->ClearUnorderedAccessViewUint(m_sob_uav, &tmp); // initial clear, next time Draw should restore it in Step 2 + + // video memory (4MB) + + memset(&bd, 0, sizeof(bd)); + + bd.ByteWidth = 4 * 1024 * 1024; + bd.Usage = D3D11_USAGE_DEFAULT; + bd.BindFlags = D3D11_BIND_UNORDERED_ACCESS; + bd.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; + + hr = (*dev)->CreateBuffer(&bd, NULL, &m_vm); + + if(FAILED(hr)) return false; + + memset(&uavd, 0, sizeof(uavd)); + + uavd.Format = DXGI_FORMAT_R32_TYPELESS; + uavd.Buffer.FirstElement = 0; + uavd.Buffer.NumElements = 1024 * 1024; + uavd.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW; + uavd.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; + + hr = (*dev)->CreateUnorderedAccessView(m_vm, &uavd, &m_vm_uav); + + if(FAILED(hr)) return false; +/* + memset(&td, 0, sizeof(td)); + + td.Width = PAGE_SIZE; + td.Height = MAX_PAGES; + td.Format = DXGI_FORMAT_R8_UINT; + td.MipLevels = 1; + td.ArraySize = 1; + td.SampleDesc.Count = 1; + td.SampleDesc.Quality = 0; + td.Usage = D3D11_USAGE_DEFAULT; + td.BindFlags = D3D11_BIND_UNORDERED_ACCESS; + + hr = (*dev)->CreateTexture2D(&td, NULL, &m_vm); + + if(FAILED(hr)) return false; + + memset(&uavd, 0, sizeof(uavd)); + + uavd.Format = DXGI_FORMAT_R8_UINT; + uavd.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; + + hr = (*dev)->CreateUnorderedAccessView(m_vm, &uavd, &m_vm_uav); + + if(FAILED(hr)) return false; +*/ + // one page, for copying between cpu<->gpu + + memset(&bd, 0, sizeof(bd)); + + bd.ByteWidth = PAGE_SIZE; + bd.Usage = D3D11_USAGE_STAGING; + bd.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + + hr = (*dev)->CreateBuffer(&bd, NULL, &m_pb); + + if(FAILED(hr)) return false; +/* + memset(&td, 0, sizeof(td)); + + td.Width = PAGE_SIZE; + td.Height = 1; + td.Format = DXGI_FORMAT_R8_UINT; + td.MipLevels = 1; + td.ArraySize = 1; + td.SampleDesc.Count = 1; + td.SampleDesc.Quality = 0; + td.Usage = D3D11_USAGE_STAGING; + td.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + + hr = (*dev)->CreateTexture2D(&td, NULL, &m_pb); + + if(FAILED(hr)) return false; +*/ + // VSConstantBuffer + + memset(&bd, 0, sizeof(bd)); + + bd.ByteWidth = sizeof(VSConstantBuffer); + bd.Usage = D3D11_USAGE_DEFAULT; + bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + + hr = (*dev)->CreateBuffer(&bd, NULL, &m_vs_cb); + + if(FAILED(hr)) return false; + + // PS + + D3D11_SHADER_MACRO macro[] = + { + {NULL, NULL}, + }; + + hr = dev->CompileShader(IDR_CS_FX, "ps_main0", macro, &m_ps0); + + if(FAILED(hr)) return false; + + // PSConstantBuffer + + memset(&bd, 0, sizeof(bd)); + + bd.ByteWidth = sizeof(PSConstantBuffer); + bd.Usage = D3D11_USAGE_DEFAULT; + bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + + hr = (*dev)->CreateBuffer(&bd, NULL, &m_ps_cb); + + if(FAILED(hr)) return false; + + // + + return true; +} + +void GSRendererCS::ResetDevice() +{ + for(int i = 0; i < countof(m_texture); i++) + { + delete m_texture[i]; + + m_texture[i] = NULL; + } +} + +void GSRendererCS::VSync(int field) +{ + __super::VSync(field); + + //printf("%lld\n", m_perfmon.GetFrame()); +} + +GSTexture* GSRendererCS::GetOutput(int i) +{ + // TODO: create a compute shader which unswizzles the frame from m_vm to the output texture + + const GSRegDISPFB& DISPFB = m_regs->DISP[i].DISPFB; + + int w = DISPFB.FBW * 64; + int h = GetFrameRect(i).bottom; + + // TODO: round up bottom + + if(m_dev->ResizeTexture(&m_texture[i], w, h)) + { + const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[DISPFB.PSM]; + + GSVector4i r(0, 0, w, h); + GSVector4i r2 = r.ralign(psm.bs); + + GSOffset* o = m_mem.GetOffset(DISPFB.Block(), DISPFB.FBW, DISPFB.PSM); + + Read(o, r2, false); + + (m_mem.*psm.rtx)(o, r2, m_output, 1024 * 4, m_env.TEXA); + + m_texture[i]->Update(r, m_output, 1024 * 4); + + if(s_dump) + { + if(s_save && s_n >= s_saven) + { + m_texture[i]->Save(format("c:\\temp1\\_%05d_f%lld_fr%d_%05x_%d.bmp", s_n, m_perfmon.GetFrame(), i, (int)DISPFB.Block(), (int)DISPFB.PSM)); + } + + s_n++; + } + } + + return m_texture[i]; +} + +void GSRendererCS::Draw() +{ + GSDrawingEnvironment& env = m_env; + GSDrawingContext* context = m_context; + + GSVector2i rtsize(2048, 2048); + GSVector4i scissor = GSVector4i(context->scissor.in).rintersect(GSVector4i(rtsize).zwxy()); + GSVector4i bbox = GSVector4i(m_vt.m_min.p.floor().xyxy(m_vt.m_max.p.ceil())); + GSVector4i r = bbox.rintersect(scissor); + + uint32 fm = context->FRAME.FBMSK; + uint32 zm = context->ZBUF.ZMSK || context->TEST.ZTE == 0 ? 0xffffffff : 0; + + if(fm != 0xffffffff) + { + Write(context->offset.fb, r); + + // TODO: m_tc->InvalidateVideoMem(context->offset.fb, r, false); + } + + if(zm != 0xffffffff) + { + Write(context->offset.zb, r); + + // TODO: m_tc->InvalidateVideoMem(context->offset.zb, r, false); + } + + // TODO: if(24-bit) fm/zm |= 0xff000000; + + if(PRIM->TME) + { + m_mem.m_clut.Read32(context->TEX0, env.TEXA); + + GSVector4i r; + + GetTextureMinMax(r, context->TEX0, context->CLAMP, m_vt.IsLinear()); + + // TODO: unswizzle pages of r to a texture, check m_vm_valid, bit not set cpu->gpu, set gpu->gpu + + // TODO: Write transfer should directly write to m_vm, then Read/Write syncing won't be necessary, clut must be updated with the gpu also + + // TODO: tex = m_tc->LookupSource(context->TEX0, env.TEXA, r); + + // if(!tex) return; + } + + // + + GSDevice11* dev = (GSDevice11*)m_dev; + + ID3D11DeviceContext* ctx = *dev; + + // + + dev->BeginScene(); + + // SetupOM + + dev->OMSetDepthStencilState(m_dss, 0); + dev->OMSetBlendState(m_bs, 0); + + ID3D11UnorderedAccessView* uavs[] = {m_vm_uav, m_lb_uav, m_sob_uav}; + uint32 counters[] = {1, 0, 0}; + + dev->OMSetRenderTargets(rtsize, countof(uavs), uavs, counters, &scissor); + + // SetupIA + + D3D11_PRIMITIVE_TOPOLOGY topology; + + switch(m_vt.m_primclass) + { + case GS_POINT_CLASS: + topology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; + break; + case GS_LINE_CLASS: + case GS_SPRITE_CLASS: + topology = D3D11_PRIMITIVE_TOPOLOGY_LINELIST; + break; + case GS_TRIANGLE_CLASS: + topology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + break; + default: + __assume(0); + } + + GSVector4i r2 = bbox.add32(GSVector4i(-1, -1, 1, 1)).rintersect(scissor); + + m_vertex.buff[m_vertex.next + 0].XYZ.X = context->XYOFFSET.OFX + (r2.left << 4); + m_vertex.buff[m_vertex.next + 0].XYZ.Y = context->XYOFFSET.OFY + (r2.top << 4); + m_vertex.buff[m_vertex.next + 1].XYZ.X = context->XYOFFSET.OFX + (r2.right << 4); + m_vertex.buff[m_vertex.next + 1].XYZ.Y = context->XYOFFSET.OFY + (r2.bottom << 4); + + m_index.buff[m_index.tail + 0] = m_vertex.next + 0; + m_index.buff[m_index.tail + 1] = m_vertex.next + 1; + + dev->IASetVertexBuffer(m_vertex.buff, sizeof(GSVertex), m_vertex.next + 2); + dev->IASetIndexBuffer(m_index.buff, m_index.tail + 2); + + // SetupVS + + VSSelector vs_sel; + + vs_sel.tme = PRIM->TME; + vs_sel.fst = PRIM->FST; + + VSConstantBuffer vs_cb; + + float sx = 2.0f / (rtsize.x << 4); + float sy = 2.0f / (rtsize.y << 4); + //float sx = 1.0f / 16; + //float sy = 1.0f / 16; + float ox = (float)(int)context->XYOFFSET.OFX; + float oy = (float)(int)context->XYOFFSET.OFY; + + vs_cb.VertexScale = GSVector4(sx, -sy, 0.0f, 0.0f); + vs_cb.VertexOffset = GSVector4(ox * sx + 1, -(oy * sy + 1), 0.0f, -1.0f); + //vs_cb.VertexScale = GSVector4(sx, sy, 0.0f, 0.0f); + //vs_cb.VertexOffset = GSVector4(ox * sx, oy * sy, 0.0f, -1.0f); + + { + GSVertexShader11 vs; + + hash_map::const_iterator i = m_vs.find(vs_sel); + + if(i != m_vs.end()) + { + vs = i->second; + } + else + { + string str[2]; + + str[0] = format("%d", vs_sel.tme); + str[1] = format("%d", vs_sel.fst); + + D3D11_SHADER_MACRO macro[] = + { + {"VS_TME", str[0].c_str()}, + {"VS_FST", str[1].c_str()}, + {NULL, NULL}, + }; + + D3D11_INPUT_ELEMENT_DESC layout[] = + { + {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, + {"COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0}, + {"TEXCOORD", 1, DXGI_FORMAT_R32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}, + {"POSITION", 0, DXGI_FORMAT_R16G16_UINT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0}, + {"POSITION", 1, DXGI_FORMAT_R32_UINT, 0, 20, D3D11_INPUT_PER_VERTEX_DATA, 0}, + {"TEXCOORD", 2, DXGI_FORMAT_R16G16_UINT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0}, + {"COLOR", 1, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 28, D3D11_INPUT_PER_VERTEX_DATA, 0}, + }; + + dev->CompileShader(IDR_CS_FX, "vs_main", macro, &vs.vs, layout, countof(layout), &vs.il); + + m_vs[vs_sel] = vs; + } + + ctx->UpdateSubresource(m_vs_cb, 0, NULL, &vs_cb, 0, 0); // TODO: only update if changed + + dev->VSSetShader(vs.vs, m_vs_cb); + + dev->IASetInputLayout(vs.il); + } + + // SetupGS + + GSSelector gs_sel; + + gs_sel.iip = PRIM->IIP; + + CComPtr gs[2]; + + for(int j = 0; j < 2; j++) + { + gs_sel.prim = j == 0 ? m_vt.m_primclass : GS_SPRITE_CLASS; + + hash_map >::const_iterator i = m_gs.find(gs_sel); + + if(i != m_gs.end()) + { + gs[j] = i->second; + } + else + { + string str[2]; + + str[0] = format("%d", gs_sel.iip); + str[1] = format("%d", j == 0 ? gs_sel.prim : GS_SPRITE_CLASS); + + D3D11_SHADER_MACRO macro[] = + { + {"GS_IIP", str[0].c_str()}, + {"GS_PRIM", str[1].c_str()}, + {NULL, NULL}, + }; + + dev->CompileShader(IDR_CS_FX, "gs_main", macro, &gs[j]); + + m_gs[gs_sel] = gs[j]; + } + } + + // SetupPS + + dev->PSSetSamplerState(m_ss, NULL, NULL); + + PSSelector ps_sel; + + ps_sel.fpsm = context->FRAME.PSM; + ps_sel.zpsm = context->ZBUF.PSM; + + CComPtr ps[2] = {m_ps0, NULL}; + + hash_map >::const_iterator i = m_ps1.find(ps_sel); + + if(i != m_ps1.end()) + { + ps[1] = i->second; + } + else + { + string str[15]; + + str[0] = format("%d", PS_BATCH_SIZE); + str[1] = format("%d", context->FRAME.PSM); + str[2] = format("%d", context->ZBUF.PSM); + + D3D11_SHADER_MACRO macro[] = + { + {"PS_BATCH_SIZE", str[0].c_str()}, + {"PS_FPSM", str[1].c_str()}, + {"PS_ZPSM", str[2].c_str()}, + {NULL, NULL}, + }; + + dev->CompileShader(IDR_CS_FX, "ps_main1", macro, &ps[1]); + + m_ps1[ps_sel] = ps[1]; + } + + PSConstantBuffer ps_cb; + + ps_cb.fm = fm; + ps_cb.zm = zm; + + ctx->UpdateSubresource(m_ps_cb, 0, NULL, &ps_cb, 0, 0); // TODO: only update if changed + + OffsetBuffer* fzbo = NULL; + + GetOffsetBuffer(&fzbo); + + dev->PSSetShaderResourceView(0, fzbo->row_srv); + dev->PSSetShaderResourceView(1, fzbo->col_srv); + // TODO: palette, texture + + int step = PS_BATCH_SIZE * GSUtil::GetVertexCount(PRIM->PRIM); + + for(int i = 0; i < m_index.tail; i += step) + { + dev->IASetPrimitiveTopology(topology); + dev->GSSetShader(gs[0]); + dev->PSSetShader(ps[0], m_ps_cb); + dev->DrawIndexedPrimitive(i, std::min(m_index.tail - i, step)); + + dev->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST); + dev->GSSetShader(gs[1]); + dev->PSSetShader(ps[1], m_ps_cb); + dev->DrawIndexedPrimitive(m_index.tail, 2); + + //printf("%d/%d, %d %d %d %d\n", i, m_index.tail, r2.x, r2.y, r2.z, r2.w); + } + + dev->EndScene(); + + if(0) + { + std::string s; + /* + s = format("c:\\temp1\\_%05d_f%lld_fb0_%05x_%d.bmp", s_n, m_perfmon.GetFrame(), 0, 0); + m_mem.SaveBMP(s, 0, 16, PSM_PSMCT32, 1024, 1024); + Read(m_mem.GetOffset(0, 16, PSM_PSMCT32), GSVector4i(0, 0, 1024, 1024), false); + */ + // + if(fm != 0xffffffff) Read(context->offset.fb, r, false); + // + if(zm != 0xffffffff) Read(context->offset.zb, r, false); + + s = format("c:\\temp1\\_%05d_f%lld_rt1_%05x_%d.bmp", s_n, m_perfmon.GetFrame(), m_context->FRAME.Block(), m_context->FRAME.PSM); + m_mem.SaveBMP(s, m_context->FRAME.Block(), m_context->FRAME.FBW, m_context->FRAME.PSM, GetFrameRect().width(), 512); + + s = format("c:\\temp1\\_%05d_f%lld_zt1_%05x_%d.bmp", s_n, m_perfmon.GetFrame(), m_context->ZBUF.Block(), m_context->ZBUF.PSM); + m_mem.SaveBMP(s, m_context->ZBUF.Block(), m_context->FRAME.FBW, m_context->ZBUF.PSM, GetFrameRect().width(), 512); + + /* + s = format("c:\\temp1\\_%05d_f%lld_fb1_%05x_%d.bmp", s_n, m_perfmon.GetFrame(), 0, 0); + m_mem.SaveBMP(s, 0, 16, PSM_PSMCT32, 1024, 1024); + */ + + s_n++; + } +} + +void GSRendererCS::InvalidateVideoMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r) +{ + GSOffset* o = m_mem.GetOffset(BITBLTBUF.DBP, BITBLTBUF.DBW, BITBLTBUF.DPSM); + + Read(o, r, true); // TODO: fully overwritten pages are not needed to be read, only invalidated (important) + + // TODO: false deps, 8H/4HL/4HH texture sharing pages with 24-bit target + // TODO: invalidate texture cache +} + +void GSRendererCS::InvalidateLocalMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r, bool clut) +{ + GSOffset* o = m_mem.GetOffset(BITBLTBUF.SBP, BITBLTBUF.SBW, BITBLTBUF.SPSM); + + Read(o, r, false); +} + +void GSRendererCS::Write(GSOffset* o, const GSVector4i& r) +{ + GSDevice11* dev = (GSDevice11*)m_dev; + + ID3D11DeviceContext* ctx = *dev; + + D3D11_BOX box; + + memset(&box, 0, sizeof(box)); + + box.right = 1; + box.bottom = 1; + box.back = 1; + + uint32* pages = o->GetPages(r); + + for(size_t i = 0; pages[i] != GSOffset::EOP; i++) + { + uint32 page = pages[i]; + + uint32 row = page >> 5; + uint32 col = 1 << (page & 31); + + if((m_vm_valid[row] & col) == 0) + { + m_vm_valid[row] |= col; + + box.left = page * PAGE_SIZE; + box.right = (page + 1) * PAGE_SIZE; + + ctx->UpdateSubresource(m_vm, 0, &box, m_mem.m_vm8 + page * PAGE_SIZE, 0, 0); +/* + // m_vm texture row is 2k in bytes, one page is 8k => starting row: addr / 4k, number of rows: 8k / 2k = 4 + + box.left = 0; + box.right = PAGE_SIZE; + box.top = page; + box.bottom = box.top + 1; + + ctx->UpdateSubresource(m_vm, 0, &box, m_mem.m_vm8 + page * PAGE_SIZE, 0, 0); +*/ + if(0) + printf("[%lld] write %05x %d %d (%d)\n", __rdtsc(), o->bp, o->bw, o->psm, page); + } + } + + delete [] pages; +} + +void GSRendererCS::Read(GSOffset* o, const GSVector4i& r, bool invalidate) +{ + GSDevice11* dev = (GSDevice11*)m_dev; + + ID3D11DeviceContext* ctx = *dev; + + D3D11_BOX box; + + memset(&box, 0, sizeof(box)); + + box.right = 1; + box.bottom = 1; + box.back = 1; + + uint32* pages = o->GetPages(r); + + for(size_t i = 0; pages[i] != GSOffset::EOP; i++) + { + uint32 page = pages[i]; + + uint32 row = page >> 5; + uint32 col = 1 << (page & 31); + + if(m_vm_valid[row] & col) + { + if(invalidate) + { + m_vm_valid[row] ^= col; + } + + box.left = page * PAGE_SIZE; + box.right = (page + 1) * PAGE_SIZE; + + ctx->CopySubresourceRegion(m_pb, 0, 0, 0, 0, m_vm, 0, &box); +/* + // m_vm texture row is 2k in bytes, one page is 8k => starting row: addr / 4k, number of rows: 8k / 2k = 4 + + box.left = 0; + box.right = PAGE_SIZE; + box.top = page; + box.bottom = box.top + 1; + + ctx->CopySubresourceRegion(m_pb, 0, 0, 0, 0, m_vm, 0, &box); +*/ + D3D11_MAPPED_SUBRESOURCE map; + + if(SUCCEEDED(ctx->Map(m_pb, 0, D3D11_MAP_READ, 0, &map))) + { + memcpy(m_mem.m_vm8 + page * PAGE_SIZE, map.pData, PAGE_SIZE); + + ctx->Unmap(m_pb, 0); + + if(0) + printf("[%lld] read %05x %d %d (%d)\n", __rdtsc(), o->bp, o->bw, o->psm, page); + } + } + } + + delete [] pages; +} + +bool GSRendererCS::GetOffsetBuffer(OffsetBuffer** fzbo) +{ + HRESULT hr; + + GSDevice11* dev = (GSDevice11*)m_dev; + + D3D11_BUFFER_DESC bd; + D3D11_SHADER_RESOURCE_VIEW_DESC srvd; + D3D11_SUBRESOURCE_DATA data; + + hash_map::iterator i = m_offset.find(m_context->offset.fzb->hash); + + if(i == m_offset.end()) + { + OffsetBuffer ob; + + memset(&bd, 0, sizeof(bd)); + + bd.ByteWidth = sizeof(GSVector2i) * 2048; + bd.Usage = D3D11_USAGE_IMMUTABLE; + bd.BindFlags = D3D11_BIND_SHADER_RESOURCE; + + memset(&data, 0, sizeof(data)); + + data.pSysMem = m_context->offset.fzb->row; + + hr = (*dev)->CreateBuffer(&bd, &data, &ob.row); + + if(FAILED(hr)) return false; + + data.pSysMem = m_context->offset.fzb->col; + + hr = (*dev)->CreateBuffer(&bd, &data, &ob.col); + + if(FAILED(hr)) return false; + + memset(&srvd, 0, sizeof(srvd)); + + srvd.Format = DXGI_FORMAT_R32G32_SINT; + srvd.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; + srvd.Buffer.FirstElement = 0; + srvd.Buffer.NumElements = 2048; + + hr = (*dev)->CreateShaderResourceView(ob.row, &srvd, &ob.row_srv); + + if(FAILED(hr)) return false; + + hr = (*dev)->CreateShaderResourceView(ob.col, &srvd, &ob.col_srv); + + if(FAILED(hr)) return false; + + m_offset[m_context->offset.fzb->hash] = ob; + + i = m_offset.find(m_context->offset.fzb->hash); + } + + *fzbo = &i->second; + + return true; +} diff --git a/plugins/GSdx/GSRendererCS.h b/plugins/GSdx/GSRendererCS.h index 8a08e0442..69b25d795 100644 --- a/plugins/GSdx/GSRendererCS.h +++ b/plugins/GSdx/GSRendererCS.h @@ -1,145 +1,145 @@ -/* - * Copyright (C) 2007-2009 Gabest - * http://www.gabest.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Make; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * http://www.gnu.org/copyleft/gpl.html - * - */ - -#pragma once - -#include "GSRenderer.h" -#include "GSDevice11.h" - -class GSRendererCS : public GSRenderer -{ - struct VSSelector - { - union - { - struct - { - uint32 tme:1; - uint32 fst:1; - }; - - uint32 key; - }; - - operator uint32() {return key & 0x3;} - - VSSelector() : key(0) {} - }; - - __aligned(struct, 32) VSConstantBuffer - { - GSVector4 VertexScale; - GSVector4 VertexOffset; - }; - - struct GSSelector - { - union - { - struct - { - uint32 iip:1; - uint32 prim:2; - }; - - uint32 key; - }; - - operator uint32() {return key & 0x7;} - - GSSelector() : key(0) {} - }; - - struct PSSelector - { - union - { - struct - { - uint32 fpsm:6; - uint32 zpsm:6; - }; - - uint32 key; - }; - - operator uint32() {return key & 0x3ff;} - - PSSelector() : key(0) {} - }; - - __aligned(struct, 32) PSConstantBuffer - { - uint32 fm; - uint32 zm; - }; - - CComPtr m_dss; - CComPtr m_bs; - CComPtr m_ss; - CComPtr m_lb; - CComPtr m_lb_uav; - CComPtr m_lb_srv; - CComPtr m_sob; - CComPtr m_sob_uav; - CComPtr m_sob_srv; - CComPtr m_vm; - //CComPtr m_vm; - CComPtr m_vm_uav; - uint32 m_vm_valid[16]; - CComPtr m_pb; - //CComPtr m_pb; - hash_map m_vs; - CComPtr m_vs_cb; - hash_map > m_gs; - CComPtr m_ps0; - hash_map > m_ps1; - CComPtr m_ps_cb; - - void Write(GSOffset* o, const GSVector4i& r); - void Read(GSOffset* o, const GSVector4i& r, bool invalidate); - - struct OffsetBuffer - { - CComPtr row, col; - CComPtr row_srv, col_srv; - }; - - hash_map m_offset; - - bool GetOffsetBuffer(OffsetBuffer** fzbo); - -protected: - GSTexture* m_texture[2]; - uint8* m_output; - - bool CreateDevice(GSDevice* dev); - void ResetDevice(); - void VSync(int field); - GSTexture* GetOutput(int i); - void Draw(); - void InvalidateVideoMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r); - void InvalidateLocalMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r, bool clut); - -public: - GSRendererCS(); - virtual ~GSRendererCS(); -}; +/* + * Copyright (C) 2007-2009 Gabest + * http://www.gabest.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#pragma once + +#include "GSRenderer.h" +#include "GSDevice11.h" + +class GSRendererCS : public GSRenderer +{ + struct VSSelector + { + union + { + struct + { + uint32 tme:1; + uint32 fst:1; + }; + + uint32 key; + }; + + operator uint32() {return key & 0x3;} + + VSSelector() : key(0) {} + }; + + __aligned(struct, 32) VSConstantBuffer + { + GSVector4 VertexScale; + GSVector4 VertexOffset; + }; + + struct GSSelector + { + union + { + struct + { + uint32 iip:1; + uint32 prim:2; + }; + + uint32 key; + }; + + operator uint32() {return key & 0x7;} + + GSSelector() : key(0) {} + }; + + struct PSSelector + { + union + { + struct + { + uint32 fpsm:6; + uint32 zpsm:6; + }; + + uint32 key; + }; + + operator uint32() {return key & 0x3ff;} + + PSSelector() : key(0) {} + }; + + __aligned(struct, 32) PSConstantBuffer + { + uint32 fm; + uint32 zm; + }; + + CComPtr m_dss; + CComPtr m_bs; + CComPtr m_ss; + CComPtr m_lb; + CComPtr m_lb_uav; + CComPtr m_lb_srv; + CComPtr m_sob; + CComPtr m_sob_uav; + CComPtr m_sob_srv; + CComPtr m_vm; + //CComPtr m_vm; + CComPtr m_vm_uav; + uint32 m_vm_valid[16]; + CComPtr m_pb; + //CComPtr m_pb; + hash_map m_vs; + CComPtr m_vs_cb; + hash_map > m_gs; + CComPtr m_ps0; + hash_map > m_ps1; + CComPtr m_ps_cb; + + void Write(GSOffset* o, const GSVector4i& r); + void Read(GSOffset* o, const GSVector4i& r, bool invalidate); + + struct OffsetBuffer + { + CComPtr row, col; + CComPtr row_srv, col_srv; + }; + + hash_map m_offset; + + bool GetOffsetBuffer(OffsetBuffer** fzbo); + +protected: + GSTexture* m_texture[2]; + uint8* m_output; + + bool CreateDevice(GSDevice* dev); + void ResetDevice(); + void VSync(int field); + GSTexture* GetOutput(int i); + void Draw(); + void InvalidateVideoMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r); + void InvalidateLocalMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r, bool clut); + +public: + GSRendererCS(); + virtual ~GSRendererCS(); +}; diff --git a/plugins/GSdx/config.h b/plugins/GSdx/config.h index 745bc3582..b082c9bce 100644 --- a/plugins/GSdx/config.h +++ b/plugins/GSdx/config.h @@ -1,44 +1,44 @@ -/* - * Copyright (C) 2007-2009 Gabest - * http://www.gabest.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Make; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * http://www.gnu.org/copyleft/gpl.html - * - */ - -#pragma once - -//#define ENABLE_VTUNE - -#define ENABLE_JIT_RASTERIZER - -//#define ENABLE_DYNAMIC_CRC_HACK - -#define ENABLE_UPSCALE_HACKS // Hacks intended to fix upscaling / rendering glitches in HW renderers - -//#define DISABLE_HW_TEXTURE_CACHE // Slow but fixes a lot of bugs - -//#define DISABLE_CRC_HACKS // Disable all game specific hacks - -#if defined(DISABLE_HW_TEXTURE_CACHE) && !defined(DISABLE_CRC_HACKS) - #define DISABLE_CRC_HACKS -#endif - -//#define DISABLE_BITMASKING - -//#define DISABLE_COLCLAMP - -//#define DISABLE_DATE +/* + * Copyright (C) 2007-2009 Gabest + * http://www.gabest.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#pragma once + +//#define ENABLE_VTUNE + +#define ENABLE_JIT_RASTERIZER + +//#define ENABLE_DYNAMIC_CRC_HACK + +#define ENABLE_UPSCALE_HACKS // Hacks intended to fix upscaling / rendering glitches in HW renderers + +//#define DISABLE_HW_TEXTURE_CACHE // Slow but fixes a lot of bugs + +//#define DISABLE_CRC_HACKS // Disable all game specific hacks + +#if defined(DISABLE_HW_TEXTURE_CACHE) && !defined(DISABLE_CRC_HACKS) + #define DISABLE_CRC_HACKS +#endif + +//#define DISABLE_BITMASKING + +//#define DISABLE_COLCLAMP + +//#define DISABLE_DATE diff --git a/plugins/GSdx/res/cs.fx b/plugins/GSdx/res/cs.fx index 594e99e85..fb63c0b01 100644 --- a/plugins/GSdx/res/cs.fx +++ b/plugins/GSdx/res/cs.fx @@ -1,383 +1,383 @@ -#ifndef VS_TME -#define VS_TME 1 -#define VS_FST 1 -#endif - -#ifndef GS_IIP -#define GS_IIP 0 -#define GS_PRIM 2 -#endif - -#ifndef PS_BATCH_SIZE -#define PS_BATCH_SIZE 2048 -#define PS_FPSM PSM_PSMCT32 -#define PS_ZPSM PSM_PSMZ16 -#endif - -#define PSM_PSMCT32 0 -#define PSM_PSMCT24 1 -#define PSM_PSMCT16 2 -#define PSM_PSMCT16S 10 -#define PSM_PSMT8 19 -#define PSM_PSMT4 20 -#define PSM_PSMT8H 27 -#define PSM_PSMT4HL 36 -#define PSM_PSMT4HH 44 -#define PSM_PSMZ32 48 -#define PSM_PSMZ24 49 -#define PSM_PSMZ16 50 -#define PSM_PSMZ16S 58 - -struct VS_INPUT -{ - float2 st : TEXCOORD0; - float4 c : COLOR0; - float q : TEXCOORD1; - uint2 p : POSITION0; - uint z : POSITION1; - uint2 uv : TEXCOORD2; - float4 f : COLOR1; -}; - -struct VS_OUTPUT -{ - float4 p : SV_Position; - float2 z : TEXCOORD0; - float4 t : TEXCOORD1; - float4 c : COLOR0; -}; - -struct GS_OUTPUT -{ - float4 p : SV_Position; - float2 z : TEXCOORD0; - float4 t : TEXCOORD1; - float4 c : COLOR0; - uint id : SV_PrimitiveID; -}; - -cbuffer VSConstantBuffer : register(c0) -{ - float4 VertexScale; - float4 VertexOffset; -}; - -cbuffer PSConstantBuffer : register(c0) -{ - uint2 WriteMask; -}; - -struct FragmentLinkItem -{ - uint c, z, id, next; -}; - -RWByteAddressBuffer VideoMemory : register(u0); -RWStructuredBuffer FragmentLinkBuffer : register(u1); -RWByteAddressBuffer StartOffsetBuffer : register(u2); -//RWTexture2D VideoMemory : register(u2); // 8192 * 512 R8_UINT - -Buffer FZRowOffset : register(t0); -Buffer FZColOffset : register(t1); -Texture2D Palette : register(t2); -Texture2D Texture : register(t3); - -VS_OUTPUT vs_main(VS_INPUT input) -{ - VS_OUTPUT output; - - output.p = float4(input.p, 0.0f, 0.0f) * VertexScale - VertexOffset; - output.z = float2(input.z & 0xffff, input.z >> 16); // TODO: min(input.z, 0xffffff00) ? - - if(VS_TME) - { - if(VS_FST) - { - output.t.xy = input.uv; - output.t.w = 1.0f; - } - else - { - output.t.xy = input.st; - output.t.w = input.q; - } - } - else - { - output.t.xy = 0; - output.t.w = 1.0f; - } - - output.c = input.c; - output.t.z = input.f.r; - - return output; -} - -#if GS_PRIM == 0 - -[maxvertexcount(1)] -void gs_main(point VS_OUTPUT input[1], inout PointStream stream, uint id : SV_PrimitiveID) -{ - GS_OUTPUT output; - - output.p = input[0].p; - output.z = input[0].z; - output.t = input[0].t; - output.c = input[0].c; - output.id = id; - - stream.Append(output); -} - -#elif GS_PRIM == 1 - -[maxvertexcount(2)] -void gs_main(line VS_OUTPUT input[2], inout LineStream stream, uint id : SV_PrimitiveID) -{ - [unroll] - for(int i = 0; i < 2; i++) - { - GS_OUTPUT output; - - output.p = input[i].p; - output.z = input[i].z; - output.t = input[i].t; - output.c = input[i].c; - output.id = id; - -#if GS_IIP == 0 - if(i != 1) output.c = input[1].c; -#endif - - stream.Append(output); - } -} - -#elif GS_PRIM == 2 - -[maxvertexcount(3)] -void gs_main(triangle VS_OUTPUT input[3], inout TriangleStream stream, uint id : SV_PrimitiveID) -{ - [unroll] - for(int i = 0; i < 3; i++) - { - GS_OUTPUT output; - - output.p = input[i].p; - output.z = input[i].z; - output.t = input[i].t; - output.c = input[i].c; - output.id = id; - -#if GS_IIP == 0 - if(i != 2) output.c = input[2].c; -#endif - - stream.Append(output); - } -} - -#elif GS_PRIM == 3 - -[maxvertexcount(4)] -void gs_main(line VS_OUTPUT input[2], inout TriangleStream stream, uint id : SV_PrimitiveID) -{ - GS_OUTPUT lt, rb, lb, rt; - - lt.p = input[0].p; - lt.z = input[1].z; - lt.t.xy = input[0].t.xy; - lt.t.zw = input[1].t.zw; - lt.c = input[0].c; - lt.id = id; - -#if GS_IIP == 0 - lt.c = input[1].c; -#endif - - rb.p = input[1].p; - rb.z = input[1].z; - rb.t = input[1].t; - rb.c = input[1].c; - rb.id = id; - - lb = lt; - lb.p.y = rb.p.y; - lb.t.y = rb.t.y; - - rt = rb; - rt.p.y = lt.p.y; - rt.t.y = lt.t.y; - - stream.Append(lt); - stream.Append(lb); - stream.Append(rt); - stream.Append(rb); -} - -#endif - -uint CompressColor32(float4 f) -{ - uint4 c = (uint4)(f * 0xff) << uint4(0, 8, 16, 24); - - return c.r | c.g | c.b | c.a; -} - -uint DecompressColor16(uint c) -{ - uint r = (c & 0x001f) << 3; - uint g = (c & 0x03e0) << 6; - uint b = (c & 0x7c00) << 9; - uint a = (c & 0x8000) << 15; - - return r | g | b | a; -} - -uint ReadPixel(uint addr) -{ - return VideoMemory.Load(addr) >> ((addr & 2) << 3); -} - -void WritePixel(uint addr, uint value, uint psm) -{ - uint tmp; - - switch(psm) - { - case PSM_PSMCT32: - case PSM_PSMZ32: - case PSM_PSMCT24: - case PSM_PSMZ24: - VideoMemory.Store(addr, value); - break; - case PSM_PSMCT16: - case PSM_PSMCT16S: - case PSM_PSMZ16: - case PSM_PSMZ16S: - tmp = (addr & 2) << 3; - value = ((value << tmp) ^ VideoMemory.Load(addr)) & (0x0000ffff << tmp); - VideoMemory.InterlockedXor(addr, value, tmp); - break; - } -} - -void ps_main0(GS_OUTPUT input) -{ - uint x = (uint)input.p.x; - uint y = (uint)input.p.y; - - uint tail = FragmentLinkBuffer.IncrementCounter(); - - uint index = (y << 11) + x; - uint next = 0; - - StartOffsetBuffer.InterlockedExchange(index * 4, tail, next); - - FragmentLinkItem item; - - // TODO: preprocess color (tfx, alpha test), z-test - - item.c = CompressColor32(input.c); - item.z = (uint)(input.z.y * 0x10000 + input.z.x); - item.id = input.id; - item.next = next; - - FragmentLinkBuffer[tail] = item; -} - -void ps_main1(GS_OUTPUT input) -{ - uint2 pos = (uint2)input.p.xy; - - // sort fragments - - uint StartOffsetIndex = (pos.y << 11) + pos.x; - - int index[PS_BATCH_SIZE]; - int count = 0; - - uint next = StartOffsetBuffer.Load(StartOffsetIndex * 4); - - StartOffsetBuffer.Store(StartOffsetIndex * 4, 0); - - [allow_uav_condition] - while(next != 0) - { - index[count++] = next; - - next = FragmentLinkBuffer[next].next; - } - - int N2 = 1 << (int)(ceil(log2(count))); - - [allow_uav_condition] - for(int i = count; i < N2; i++) - { - index[i] = 0; - } - - [allow_uav_condition] - for(int k = 2; k <= N2; k = 2 * k) - { - [allow_uav_condition] - for(int j = k >> 1; j > 0 ; j = j >> 1) - { - [allow_uav_condition] - for(int i = 0; i < N2; i++) - { - uint i_id = FragmentLinkBuffer[index[i]].id; - - int ixj = i ^ j; - - if(ixj > i) - { - uint ixj_id = FragmentLinkBuffer[index[ixj]].id; - - if((i & k) == 0 && i_id > ixj_id) - { - int temp = index[i]; - index[i] = index[ixj]; - index[ixj] = temp; - } - - if((i & k) != 0 && i_id < ixj_id) - { - int temp = index[i]; - index[i] = index[ixj]; - index[ixj] = temp; - } - } - } - } - } - - uint2 addr = (uint2)(FZRowOffset[pos.y] + FZColOffset[pos.x]) << 1; - - uint dc = ReadPixel(addr.x); - uint dz = ReadPixel(addr.y); - - uint sc = dc; - uint sz = dz; - - [allow_uav_condition] - while(--count >= 0) - { - FragmentLinkItem f = FragmentLinkBuffer[index[count]]; - - // TODO - - if(sz < f.z) - { - sc = f.c; - sz = f.z; - } - } - - uint c = sc; // (dc & ~WriteMask.x) | (sc & WriteMask.x); - uint z = 0;//sz; //(dz & ~WriteMask.y) | (sz & WriteMask.y); - - WritePixel(addr.x, c, PS_FPSM); - WritePixel(addr.y, z, PS_ZPSM); -} +#ifndef VS_TME +#define VS_TME 1 +#define VS_FST 1 +#endif + +#ifndef GS_IIP +#define GS_IIP 0 +#define GS_PRIM 2 +#endif + +#ifndef PS_BATCH_SIZE +#define PS_BATCH_SIZE 2048 +#define PS_FPSM PSM_PSMCT32 +#define PS_ZPSM PSM_PSMZ16 +#endif + +#define PSM_PSMCT32 0 +#define PSM_PSMCT24 1 +#define PSM_PSMCT16 2 +#define PSM_PSMCT16S 10 +#define PSM_PSMT8 19 +#define PSM_PSMT4 20 +#define PSM_PSMT8H 27 +#define PSM_PSMT4HL 36 +#define PSM_PSMT4HH 44 +#define PSM_PSMZ32 48 +#define PSM_PSMZ24 49 +#define PSM_PSMZ16 50 +#define PSM_PSMZ16S 58 + +struct VS_INPUT +{ + float2 st : TEXCOORD0; + float4 c : COLOR0; + float q : TEXCOORD1; + uint2 p : POSITION0; + uint z : POSITION1; + uint2 uv : TEXCOORD2; + float4 f : COLOR1; +}; + +struct VS_OUTPUT +{ + float4 p : SV_Position; + float2 z : TEXCOORD0; + float4 t : TEXCOORD1; + float4 c : COLOR0; +}; + +struct GS_OUTPUT +{ + float4 p : SV_Position; + float2 z : TEXCOORD0; + float4 t : TEXCOORD1; + float4 c : COLOR0; + uint id : SV_PrimitiveID; +}; + +cbuffer VSConstantBuffer : register(c0) +{ + float4 VertexScale; + float4 VertexOffset; +}; + +cbuffer PSConstantBuffer : register(c0) +{ + uint2 WriteMask; +}; + +struct FragmentLinkItem +{ + uint c, z, id, next; +}; + +RWByteAddressBuffer VideoMemory : register(u0); +RWStructuredBuffer FragmentLinkBuffer : register(u1); +RWByteAddressBuffer StartOffsetBuffer : register(u2); +//RWTexture2D VideoMemory : register(u2); // 8192 * 512 R8_UINT + +Buffer FZRowOffset : register(t0); +Buffer FZColOffset : register(t1); +Texture2D Palette : register(t2); +Texture2D Texture : register(t3); + +VS_OUTPUT vs_main(VS_INPUT input) +{ + VS_OUTPUT output; + + output.p = float4(input.p, 0.0f, 0.0f) * VertexScale - VertexOffset; + output.z = float2(input.z & 0xffff, input.z >> 16); // TODO: min(input.z, 0xffffff00) ? + + if(VS_TME) + { + if(VS_FST) + { + output.t.xy = input.uv; + output.t.w = 1.0f; + } + else + { + output.t.xy = input.st; + output.t.w = input.q; + } + } + else + { + output.t.xy = 0; + output.t.w = 1.0f; + } + + output.c = input.c; + output.t.z = input.f.r; + + return output; +} + +#if GS_PRIM == 0 + +[maxvertexcount(1)] +void gs_main(point VS_OUTPUT input[1], inout PointStream stream, uint id : SV_PrimitiveID) +{ + GS_OUTPUT output; + + output.p = input[0].p; + output.z = input[0].z; + output.t = input[0].t; + output.c = input[0].c; + output.id = id; + + stream.Append(output); +} + +#elif GS_PRIM == 1 + +[maxvertexcount(2)] +void gs_main(line VS_OUTPUT input[2], inout LineStream stream, uint id : SV_PrimitiveID) +{ + [unroll] + for(int i = 0; i < 2; i++) + { + GS_OUTPUT output; + + output.p = input[i].p; + output.z = input[i].z; + output.t = input[i].t; + output.c = input[i].c; + output.id = id; + +#if GS_IIP == 0 + if(i != 1) output.c = input[1].c; +#endif + + stream.Append(output); + } +} + +#elif GS_PRIM == 2 + +[maxvertexcount(3)] +void gs_main(triangle VS_OUTPUT input[3], inout TriangleStream stream, uint id : SV_PrimitiveID) +{ + [unroll] + for(int i = 0; i < 3; i++) + { + GS_OUTPUT output; + + output.p = input[i].p; + output.z = input[i].z; + output.t = input[i].t; + output.c = input[i].c; + output.id = id; + +#if GS_IIP == 0 + if(i != 2) output.c = input[2].c; +#endif + + stream.Append(output); + } +} + +#elif GS_PRIM == 3 + +[maxvertexcount(4)] +void gs_main(line VS_OUTPUT input[2], inout TriangleStream stream, uint id : SV_PrimitiveID) +{ + GS_OUTPUT lt, rb, lb, rt; + + lt.p = input[0].p; + lt.z = input[1].z; + lt.t.xy = input[0].t.xy; + lt.t.zw = input[1].t.zw; + lt.c = input[0].c; + lt.id = id; + +#if GS_IIP == 0 + lt.c = input[1].c; +#endif + + rb.p = input[1].p; + rb.z = input[1].z; + rb.t = input[1].t; + rb.c = input[1].c; + rb.id = id; + + lb = lt; + lb.p.y = rb.p.y; + lb.t.y = rb.t.y; + + rt = rb; + rt.p.y = lt.p.y; + rt.t.y = lt.t.y; + + stream.Append(lt); + stream.Append(lb); + stream.Append(rt); + stream.Append(rb); +} + +#endif + +uint CompressColor32(float4 f) +{ + uint4 c = (uint4)(f * 0xff) << uint4(0, 8, 16, 24); + + return c.r | c.g | c.b | c.a; +} + +uint DecompressColor16(uint c) +{ + uint r = (c & 0x001f) << 3; + uint g = (c & 0x03e0) << 6; + uint b = (c & 0x7c00) << 9; + uint a = (c & 0x8000) << 15; + + return r | g | b | a; +} + +uint ReadPixel(uint addr) +{ + return VideoMemory.Load(addr) >> ((addr & 2) << 3); +} + +void WritePixel(uint addr, uint value, uint psm) +{ + uint tmp; + + switch(psm) + { + case PSM_PSMCT32: + case PSM_PSMZ32: + case PSM_PSMCT24: + case PSM_PSMZ24: + VideoMemory.Store(addr, value); + break; + case PSM_PSMCT16: + case PSM_PSMCT16S: + case PSM_PSMZ16: + case PSM_PSMZ16S: + tmp = (addr & 2) << 3; + value = ((value << tmp) ^ VideoMemory.Load(addr)) & (0x0000ffff << tmp); + VideoMemory.InterlockedXor(addr, value, tmp); + break; + } +} + +void ps_main0(GS_OUTPUT input) +{ + uint x = (uint)input.p.x; + uint y = (uint)input.p.y; + + uint tail = FragmentLinkBuffer.IncrementCounter(); + + uint index = (y << 11) + x; + uint next = 0; + + StartOffsetBuffer.InterlockedExchange(index * 4, tail, next); + + FragmentLinkItem item; + + // TODO: preprocess color (tfx, alpha test), z-test + + item.c = CompressColor32(input.c); + item.z = (uint)(input.z.y * 0x10000 + input.z.x); + item.id = input.id; + item.next = next; + + FragmentLinkBuffer[tail] = item; +} + +void ps_main1(GS_OUTPUT input) +{ + uint2 pos = (uint2)input.p.xy; + + // sort fragments + + uint StartOffsetIndex = (pos.y << 11) + pos.x; + + int index[PS_BATCH_SIZE]; + int count = 0; + + uint next = StartOffsetBuffer.Load(StartOffsetIndex * 4); + + StartOffsetBuffer.Store(StartOffsetIndex * 4, 0); + + [allow_uav_condition] + while(next != 0) + { + index[count++] = next; + + next = FragmentLinkBuffer[next].next; + } + + int N2 = 1 << (int)(ceil(log2(count))); + + [allow_uav_condition] + for(int i = count; i < N2; i++) + { + index[i] = 0; + } + + [allow_uav_condition] + for(int k = 2; k <= N2; k = 2 * k) + { + [allow_uav_condition] + for(int j = k >> 1; j > 0 ; j = j >> 1) + { + [allow_uav_condition] + for(int i = 0; i < N2; i++) + { + uint i_id = FragmentLinkBuffer[index[i]].id; + + int ixj = i ^ j; + + if(ixj > i) + { + uint ixj_id = FragmentLinkBuffer[index[ixj]].id; + + if((i & k) == 0 && i_id > ixj_id) + { + int temp = index[i]; + index[i] = index[ixj]; + index[ixj] = temp; + } + + if((i & k) != 0 && i_id < ixj_id) + { + int temp = index[i]; + index[i] = index[ixj]; + index[ixj] = temp; + } + } + } + } + } + + uint2 addr = (uint2)(FZRowOffset[pos.y] + FZColOffset[pos.x]) << 1; + + uint dc = ReadPixel(addr.x); + uint dz = ReadPixel(addr.y); + + uint sc = dc; + uint sz = dz; + + [allow_uav_condition] + while(--count >= 0) + { + FragmentLinkItem f = FragmentLinkBuffer[index[count]]; + + // TODO + + if(sz < f.z) + { + sc = f.c; + sz = f.z; + } + } + + uint c = sc; // (dc & ~WriteMask.x) | (sc & WriteMask.x); + uint z = 0;//sz; //(dz & ~WriteMask.y) | (sz & WriteMask.y); + + WritePixel(addr.x, c, PS_FPSM); + WritePixel(addr.y, z, PS_ZPSM); +} diff --git a/plugins/GSdx/res/fxaa.fx b/plugins/GSdx/res/fxaa.fx index 095d28919..450aea1d8 100644 --- a/plugins/GSdx/res/fxaa.fx +++ b/plugins/GSdx/res/fxaa.fx @@ -1,1996 +1,1996 @@ -#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency - -#define FXAA_PC 1 -#define FXAA_QUALITY__SUBPIX 0.0 - -#if SHADER_MODEL >= 0x400 - -#if SHADER_MODEL >= 0x500 - #define FXAA_HLSL_5 1 -#else - #define FXAA_HLSL_4 1 -#endif - -Texture2D Texture; -SamplerState TextureSampler; - -cbuffer cb0 -{ - float4 _rcpFrame; - float4 _rcpFrameOpt; -}; - -struct PS_INPUT -{ - float4 p : SV_Position; - float2 t : TEXCOORD0; -}; - -struct PS_OUTPUT -{ - float4 c : SV_Target0; -}; - -#elif SHADER_MODEL <= 0x300 - -#define FXAA_HLSL_3 1 - -sampler Texture : register(s0); - -float4 _rcpFrame : register(c0); -float4 _rcpFrameOpt : register(c1); - -struct PS_INPUT -{ -#if SHADER_MODEL < 0x300 - float4 p : TEXCOORD1; -#else - float4 p : VPOS; -#endif - float2 t : TEXCOORD0; -}; - -struct PS_OUTPUT -{ - float4 c : COLOR; -}; - -#endif - -/*============================================================================ - - - NVIDIA FXAA 3.10 by TIMOTHY LOTTES - - ------------------------------------------------------------------------------- -COPYRIGHT (C) 2010, 2011 NVIDIA CORPORATION. ALL RIGHTS RESERVED. ------------------------------------------------------------------------------- -TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED -*AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA -OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR -CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR -LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, -OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE -THIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - ------------------------------------------------------------------------------- - INTEGRATION CHECKLIST ------------------------------------------------------------------------------- -(1.) -In the shader source, -setup defines for the desired configuration. -Example, - - #define FXAA_PC 1 - #define FXAA_HLSL_3 1 - #define FXAA_QUALITY__PRESET 12 - #define FXAA_QUALITY__EDGE_THRESHOLD (1.0/6.0) - #define FXAA_QUALITY__EDGE_THRESHOLD_MIN (1.0/12.0) - -(2.) -Then include this file, - - #include "Fxaa3.h" - -(3.) -Then call the FXAA pixel shader from within your desired shader, - - return FxaaPixelShader(pos, posPos, tex, rcpFrame, rcpFrameOpt); - -(4.) -Insure pass prior to FXAA outputs RGBL. -See next section. - -(5.) -Setup engine to provide "rcpFrame" and "rcpFrameOpt" constants. -Not using constants will result in a performance loss. - - // {x_} = 1.0/screenWidthInPixels - // {_y} = 1.0/screenHeightInPixels - float2 rcpFrame - - // This must be from a constant/uniform. - // {x___} = 2.0/screenWidthInPixels - // {_y__} = 2.0/screenHeightInPixels - // {__z_} = 0.5/screenWidthInPixels - // {___w} = 0.5/screenHeightInPixels - float4 rcpFrameOpt - -(5.a.) -Optionally change to this for sharper FXAA Console, - - // This must be from a constant/uniform. - // {x___} = 2.0/screenWidthInPixels - // {_y__} = 2.0/screenHeightInPixels - // {__z_} = 0.333/screenWidthInPixels - // {___w} = 0.333/screenHeightInPixels - float4 rcpFrameOpt - -(6.) -Have FXAA vertex shader run as a full screen triangle, -and output "pos" and "posPos" such that inputs in the pixel shader provide, - - // {xy} = center of pixel - float2 pos, - - // {xy__} = upper left of pixel - // {__zw} = lower right of pixel - float4 posPos, - -(7.) -Insure the texture sampler used by FXAA is set to bilinear filtering. - - ------------------------------------------------------------------------------- - INTEGRATION - RGBL AND COLORSPACE ------------------------------------------------------------------------------- -FXAA3 requires RGBL as input. - -RGB should be LDR (low dynamic range). -Specifically do FXAA after tonemapping. - -RGB data as returned by a texture fetch can be linear or non-linear. -Note an "sRGB format" texture counts as linear, -because the result of a texture fetch is linear data. -Regular "RGBA8" textures in the sRGB colorspace are non-linear. - -Luma must be stored in the alpha channel prior to running FXAA. -This luma should be in a perceptual space (could be gamma 2.0). -Example pass before FXAA where output is gamma 2.0 encoded, - - color.rgb = ToneMap(color.rgb); // linear color output - color.rgb = sqrt(color.rgb); // gamma 2.0 color output - return color; - -To use FXAA, - - color.rgb = ToneMap(color.rgb); // linear color output - color.rgb = sqrt(color.rgb); // gamma 2.0 color output - color.a = dot(color.rgb, float3(0.299, 0.587, 0.114)); // compute luma - return color; - -Another example where output is linear encoded, -say for instance writing to an sRGB formated render target, -where the render target does the conversion back to sRGB after blending, - - color.rgb = ToneMap(color.rgb); // linear color output - return color; - -To use FXAA, - - color.rgb = ToneMap(color.rgb); // linear color output - color.a = sqrt(dot(color.rgb, float3(0.299, 0.587, 0.114))); // compute luma - return color; - -Getting luma correct is required for the algorithm to work correctly. - - ------------------------------------------------------------------------------- - BEING LINEARLY CORRECT? ------------------------------------------------------------------------------- -Applying FXAA to a framebuffer with linear RGB color will look worse. -This is very counter intuitive, but happends to be true in this case. -The reason is because dithering artifacts will be more visiable -in a linear colorspace. - - ------------------------------------------------------------------------------- - COMPLEX INTEGRATION ------------------------------------------------------------------------------- -Q. What if the engine is blending into RGB before wanting to run FXAA? - -A. In the last opaque pass prior to FXAA, - have the pass write out luma into alpha. - Then blend into RGB only. - FXAA should be able to run ok - assuming the blending pass did not any add aliasing. - This should be the common case for particles and common blending passes. - -============================================================================*/ - -/*============================================================================ - - INTEGRATION KNOBS - -============================================================================*/ -// -// FXAA_PS3 and FXAA_360 choose the console algorithm (FXAA3 CONSOLE). -// FXAA_360_OPT is a prototype for the new optimized 360 version. -// -// 1 = Use API. -// 0 = Don't use API. -// -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_PS3 - #define FXAA_PS3 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_360 - #define FXAA_360 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_360_OPT - #define FXAA_360_OPT 0 -#endif -/*==========================================================================*/ -#ifndef FXAA_PC - // - // FXAA Quality - // The high quality PC algorithm. - // - #define FXAA_PC 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_PC_CONSOLE - // - // The console algorithm for PC is included - // for developers targeting really low spec machines. - // - #define FXAA_PC_CONSOLE 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_GLSL_120 - #define FXAA_GLSL_120 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_GLSL_130 - #define FXAA_GLSL_130 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_HLSL_3 - #define FXAA_HLSL_3 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_HLSL_4 - #define FXAA_HLSL_4 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_HLSL_5 - #define FXAA_HLSL_5 0 -#endif -/*==========================================================================*/ -#ifndef FXAA_EARLY_EXIT - // - // Controls algorithm's early exit path. - // On PS3 turning this on adds 2 cycles to the shader. - // On 360 turning this off adds 10ths of a millisecond to the shader. - // Turning this off on console will result in a more blurry image. - // So this defaults to on. - // - // 1 = On. - // 0 = Off. - // - #define FXAA_EARLY_EXIT 1 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_DISCARD - // - // Only valid for PC OpenGL currently. - // - // 1 = Use discard on pixels which don't need AA. - // For APIs which enable concurrent TEX+ROP from same surface. - // 0 = Return unchanged color on pixels which don't need AA. - // - #define FXAA_DISCARD 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_FAST_PIXEL_OFFSET - // - // Used for GLSL 120 only. - // - // 1 = GL API supports fast pixel offsets - // 0 = do not use fast pixel offsets - // - #ifdef GL_EXT_gpu_shader4 - #define FXAA_FAST_PIXEL_OFFSET 1 - #endif - #ifdef GL_NV_gpu_shader5 - #define FXAA_FAST_PIXEL_OFFSET 1 - #endif - #ifdef GL_ARB_gpu_shader5 - #define FXAA_FAST_PIXEL_OFFSET 1 - #endif - #ifndef FXAA_FAST_PIXEL_OFFSET - #define FXAA_FAST_PIXEL_OFFSET 0 - #endif -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_GATHER4_ALPHA - // - // 1 = API supports gather4 on alpha channel. - // 0 = API does not support gather4 on alpha channel. - // - #if (FXAA_HLSL_5 == 1) - #define FXAA_GATHER4_ALPHA 1 - #endif - #ifdef GL_ARB_gpu_shader5 - #define FXAA_GATHER4_ALPHA 1 - #endif - #ifdef GL_NV_gpu_shader5 - #define FXAA_GATHER4_ALPHA 1 - #endif - #ifndef FXAA_GATHER4_ALPHA - #define FXAA_GATHER4_ALPHA 0 - #endif -#endif - -/*============================================================================ - FXAA CONSOLE - TUNING KNOBS -============================================================================*/ -#ifndef FXAA_CONSOLE__EDGE_SHARPNESS - // - // Consoles the sharpness of edges. - // - // Due to the PS3 being ALU bound, - // there are only two safe values here: 4 and 8. - // These options use the shaders ability to a free *|/ by 4|8. - // - // 8.0 is sharper - // 4.0 is softer - // 2.0 is really soft (good for vector graphics inputs) - // - #if 1 - #define FXAA_CONSOLE__EDGE_SHARPNESS 8.0 - #endif - #if 0 - #define FXAA_CONSOLE__EDGE_SHARPNESS 4.0 - #endif - #if 0 - #define FXAA_CONSOLE__EDGE_SHARPNESS 2.0 - #endif -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_CONSOLE__EDGE_THRESHOLD - // - // The minimum amount of local contrast required to apply algorithm. - // The console setting has a different mapping than the quality setting. - // - // This only applies when FXAA_EARLY_EXIT is 1. - // - // Due to the PS3 being ALU bound, - // there are only two safe values here: 0.25 and 0.125. - // These options use the shaders ability to a free *|/ by 4|8. - // - // 0.125 leaves less aliasing, but is softer - // 0.25 leaves more aliasing, and is sharper - // - #if 1 - #define FXAA_CONSOLE__EDGE_THRESHOLD 0.125 - #else - #define FXAA_CONSOLE__EDGE_THRESHOLD 0.25 - #endif -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_CONSOLE__EDGE_THRESHOLD_MIN - // - // Trims the algorithm from processing darks. - // The console setting has a different mapping than the quality setting. - // - // This only applies when FXAA_EARLY_EXIT is 1. - // - // This does not apply to PS3. - // PS3 was simplified to avoid more shader instructions. - // - #define FXAA_CONSOLE__EDGE_THRESHOLD_MIN 0.05 -#endif - -/*============================================================================ - FXAA QUALITY - TUNING KNOBS -============================================================================*/ -#ifndef FXAA_QUALITY__EDGE_THRESHOLD - // - // The minimum amount of local contrast required to apply algorithm. - // - // 1/3 - too little - // 1/4 - low quality - // 1/6 - default - // 1/8 - high quality (default) - // 1/16 - overkill - // - #define FXAA_QUALITY__EDGE_THRESHOLD (1.0/6.0) -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_QUALITY__EDGE_THRESHOLD_MIN - // - // Trims the algorithm from processing darks. - // - // 1/32 - visible limit - // 1/16 - high quality - // 1/12 - upper limit (default, the start of visible unfiltered edges) - // - #define FXAA_QUALITY__EDGE_THRESHOLD_MIN (1.0/12.0) -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_QUALITY__SUBPIX - // - // Choose the amount of sub-pixel aliasing removal. - // - // 1 - upper limit (softer) - // 3/4 - default amount of filtering - // 1/2 - lower limit (sharper, less sub-pixel aliasing removal) - // - #define FXAA_QUALITY__SUBPIX (3.0/4.0) -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_QUALITY__PRESET - // - // Choose the quality preset. - // - // OPTIONS - // ----------------------------------------------------------------------- - // 10 to 15 - default medium dither (10=fastest, 15=highest quality) - // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality) - // 39 - no dither, very expensive - // - // NOTES - // ----------------------------------------------------------------------- - // 12 = slightly faster then FXAA 3.9 and higher edge quality (default) - // 13 = about same speed as FXAA 3.9 and better than 12 - // 23 = closest to FXAA 3.9 visually and performance wise - // _ = the lowest digit is directly related to performance - // _ = the highest digit is directly related to style - // - #define FXAA_QUALITY__PRESET 12 -#endif - - -/*============================================================================ - - FXAA QUALITY - PRESETS - -============================================================================*/ - -/*============================================================================ - FXAA QUALITY - MEDIUM DITHER PRESETS -============================================================================*/ -#if (FXAA_QUALITY__PRESET == 10) - #define FXAA_QUALITY__PS 3 - #define FXAA_QUALITY__P0 1.5 - #define FXAA_QUALITY__P1 3.0 - #define FXAA_QUALITY__P2 12.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 11) - #define FXAA_QUALITY__PS 4 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 3.0 - #define FXAA_QUALITY__P3 12.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 12) - #define FXAA_QUALITY__PS 5 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 4.0 - #define FXAA_QUALITY__P4 12.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 13) - #define FXAA_QUALITY__PS 6 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 4.0 - #define FXAA_QUALITY__P5 12.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 14) - #define FXAA_QUALITY__PS 7 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 4.0 - #define FXAA_QUALITY__P6 12.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 15) - #define FXAA_QUALITY__PS 8 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 2.0 - #define FXAA_QUALITY__P6 4.0 - #define FXAA_QUALITY__P7 12.0 -#endif - -/*============================================================================ - FXAA QUALITY - LOW DITHER PRESETS -============================================================================*/ -#if (FXAA_QUALITY__PRESET == 20) - #define FXAA_QUALITY__PS 3 - #define FXAA_QUALITY__P0 1.5 - #define FXAA_QUALITY__P1 2.0 - #define FXAA_QUALITY__P2 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 21) - #define FXAA_QUALITY__PS 4 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 22) - #define FXAA_QUALITY__PS 5 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 23) - #define FXAA_QUALITY__PS 6 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 24) - #define FXAA_QUALITY__PS 7 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 3.0 - #define FXAA_QUALITY__P6 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 25) - #define FXAA_QUALITY__PS 8 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 2.0 - #define FXAA_QUALITY__P6 4.0 - #define FXAA_QUALITY__P7 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 26) - #define FXAA_QUALITY__PS 9 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 2.0 - #define FXAA_QUALITY__P6 2.0 - #define FXAA_QUALITY__P7 4.0 - #define FXAA_QUALITY__P8 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 27) - #define FXAA_QUALITY__PS 10 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 2.0 - #define FXAA_QUALITY__P6 2.0 - #define FXAA_QUALITY__P7 2.0 - #define FXAA_QUALITY__P8 4.0 - #define FXAA_QUALITY__P9 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 28) - #define FXAA_QUALITY__PS 11 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 2.0 - #define FXAA_QUALITY__P6 2.0 - #define FXAA_QUALITY__P7 2.0 - #define FXAA_QUALITY__P8 2.0 - #define FXAA_QUALITY__P9 4.0 - #define FXAA_QUALITY__P10 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 29) - #define FXAA_QUALITY__PS 12 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 2.0 - #define FXAA_QUALITY__P6 2.0 - #define FXAA_QUALITY__P7 2.0 - #define FXAA_QUALITY__P8 2.0 - #define FXAA_QUALITY__P9 2.0 - #define FXAA_QUALITY__P10 4.0 - #define FXAA_QUALITY__P11 8.0 -#endif - -/*============================================================================ - FXAA QUALITY - EXTREME QUALITY -============================================================================*/ -#if (FXAA_QUALITY__PRESET == 39) - #define FXAA_QUALITY__PS 12 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.0 - #define FXAA_QUALITY__P2 1.0 - #define FXAA_QUALITY__P3 1.0 - #define FXAA_QUALITY__P4 1.0 - #define FXAA_QUALITY__P5 1.5 - #define FXAA_QUALITY__P6 2.0 - #define FXAA_QUALITY__P7 2.0 - #define FXAA_QUALITY__P8 2.0 - #define FXAA_QUALITY__P9 2.0 - #define FXAA_QUALITY__P10 4.0 - #define FXAA_QUALITY__P11 8.0 -#endif - - - -/*============================================================================ - - API PORTING - -============================================================================*/ -#if FXAA_GLSL_120 - // Requires, - // #version 120 - // And at least, - // #extension GL_EXT_gpu_shader4 : enable - // (or set FXAA_FAST_PIXEL_OFFSET 1 to work like DX9) - #define half float - #define half2 vec2 - #define half3 vec3 - #define half4 vec4 - #define int2 ivec2 - #define float2 vec2 - #define float3 vec3 - #define float4 vec4 - #define FxaaInt2 ivec2 - #define FxaaFloat2 vec2 - #define FxaaFloat3 vec3 - #define FxaaFloat4 vec4 - #define FxaaDiscard discard - #define FxaaDot3(a, b) dot(a, b) - #define FxaaSat(x) clamp(x, 0.0, 1.0) - #define FxaaLerp(x,y,s) mix(x,y,s) - #define FxaaTex sampler2D - #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0) - #if (FXAA_FAST_PIXEL_OFFSET == 1) - #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o) - #else - #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0) - #endif - #if (FXAA_GATHER4_ALPHA == 1) - // use #extension GL_ARB_gpu_shader5 : enable - #define FxaaTexAlpha4(t, p, r) textureGather(t, p, 3) - #define FxaaTexOffAlpha4(t, p, o, r) textureGatherOffset(t, p, o, 3) - #endif -#endif -/*--------------------------------------------------------------------------*/ -#if FXAA_GLSL_130 - // Requires "#version 130" or better - #define half float - #define half2 vec2 - #define half3 vec3 - #define half4 vec4 - #define int2 ivec2 - #define float2 vec2 - #define float3 vec3 - #define float4 vec4 - #define FxaaInt2 ivec2 - #define FxaaFloat2 vec2 - #define FxaaFloat3 vec3 - #define FxaaFloat4 vec4 - #define FxaaDiscard discard - #define FxaaDot3(a, b) dot(a, b) - #define FxaaSat(x) clamp(x, 0.0, 1.0) - #define FxaaLerp(x,y,s) mix(x,y,s) - #define FxaaTex sampler2D - #define FxaaTexTop(t, p) textureLod(t, p, 0.0) - #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o) - #if (FXAA_GATHER4_ALPHA == 1) - // use #extension GL_ARB_gpu_shader5 : enable - #define FxaaTexAlpha4(t, p, r) textureGather(t, p, 3) - #define FxaaTexOffAlpha4(t, p, o, r) textureGatherOffset(t, p, o, 3) - #endif -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_HLSL_3 == 1) || (FXAA_360 == 1) - #define int2 float2 - #define FxaaInt2 float2 - #define FxaaFloat2 float2 - #define FxaaFloat3 float3 - #define FxaaFloat4 float4 - #define FxaaDiscard clip(-1) - #define FxaaDot3(a, b) dot(a, b) - #define FxaaSat(x) saturate(x) - #define FxaaLerp(x,y,s) lerp(x,y,s) - #define FxaaTex sampler2D - #define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0)) - #define FxaaTexOff(t, p, o, r) tex2Dlod(t, float4(p + (o * r), 0, 0)) -#endif -/*--------------------------------------------------------------------------*/ -#if FXAA_HLSL_4 - #define FxaaInt2 int2 - #define FxaaFloat2 float2 - #define FxaaFloat3 float3 - #define FxaaFloat4 float4 - #define FxaaDiscard clip(-1) - #define FxaaDot3(a, b) dot(a, b) - #define FxaaSat(x) saturate(x) - #define FxaaLerp(x,y,s) lerp(x,y,s) - struct FxaaTex { SamplerState smpl; Texture2D tex; }; - #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) - #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) -#endif -/*--------------------------------------------------------------------------*/ -#if FXAA_HLSL_5 - #define FxaaInt2 int2 - #define FxaaFloat2 float2 - #define FxaaFloat3 float3 - #define FxaaFloat4 float4 - #define FxaaDiscard clip(-1) - #define FxaaDot3(a, b) dot(a, b) - #define FxaaSat(x) saturate(x) - #define FxaaLerp(x,y,s) lerp(x,y,s) - struct FxaaTex { SamplerState smpl; Texture2D tex; }; - #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) - #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) - #define FxaaTexAlpha4(t, p, r) t.tex.GatherAlpha(t.smpl, p) - #define FxaaTexOffAlpha4(t, p, o, r) t.tex.GatherAlpha(t.smpl, p, o) -#endif - - - -/*============================================================================ - - FXAA3 CONSOLE - 360 PIXEL SHADER - ------------------------------------------------------------------------------- -Might be some optimizations left here, -as of this latest change didn't have a PIX dump to verify if TEX bound. -============================================================================*/ -#if (FXAA_360 == 1) -/*--------------------------------------------------------------------------*/ -half4 FxaaPixelShader( - // {xy} = center of pixel - float2 pos, - // {xy__} = upper left of pixel - // {__zw} = lower right of pixel - float4 posPos, - // {rgb_} = color in linear or perceptual color space - // {___a} = alpha output is junk value - FxaaTex tex, - // This must be from a constant/uniform. - // {xy} = rcpFrame not used on PC version of FXAA Console - float2 rcpFrame, - // This must be from a constant/uniform. - // {x___} = 2.0/screenWidthInPixels - // {_y__} = 2.0/screenHeightInPixels - // {__z_} = 0.5/screenWidthInPixels - // {___w} = 0.5/screenHeightInPixels - float4 rcpFrameOpt -) { -/*--------------------------------------------------------------------------*/ - half4 lumaNwNeSwSe; - lumaNwNeSwSe.x = FxaaTexTop(tex, posPos.xy).w; - lumaNwNeSwSe.y = FxaaTexTop(tex, posPos.zy).w; - lumaNwNeSwSe.z = FxaaTexTop(tex, posPos.xw).w; - lumaNwNeSwSe.w = FxaaTexTop(tex, posPos.zw).w; -/*--------------------------------------------------------------------------*/ - half4 rgbyM = FxaaTexTop(tex, pos.xy); -/*--------------------------------------------------------------------------*/ - lumaNwNeSwSe.y += 1.0/384.0; -/*--------------------------------------------------------------------------*/ - half2 lumaMinTemp = min(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); - half2 lumaMaxTemp = max(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); -/*--------------------------------------------------------------------------*/ - half lumaMin = min(lumaMinTemp.x, lumaMinTemp.y); - half lumaMax = max(lumaMaxTemp.x, lumaMaxTemp.y); -/*--------------------------------------------------------------------------*/ - half lumaMinM = min(lumaMin, rgbyM.w); - half lumaMaxM = max(lumaMax, rgbyM.w); - if((lumaMaxM - lumaMinM) < max(FXAA_CONSOLE__EDGE_THRESHOLD_MIN, lumaMax * FXAA_CONSOLE__EDGE_THRESHOLD)) return rgbyM; -/*--------------------------------------------------------------------------*/ - half2 dir; - dir.x = dot(lumaNwNeSwSe, float4(-1.0, -1.0, 1.0, 1.0)); - dir.y = dot(lumaNwNeSwSe, float4( 1.0, -1.0, 1.0,-1.0)); -/*--------------------------------------------------------------------------*/ - half2 dir1; - dir1 = normalize(dir.xy); -/*--------------------------------------------------------------------------*/ - half dirAbsMinTimesC = min(abs(dir1.x), abs(dir1.y)) * FXAA_CONSOLE__EDGE_SHARPNESS; - half2 dir2; - dir2 = clamp(dir1.xy / dirAbsMinTimesC, -2.0, 2.0); -/*--------------------------------------------------------------------------*/ - half4 rgbyN1 = FxaaTexTop(tex, pos.xy - dir1 * rcpFrameOpt.zw); - half4 rgbyP1 = FxaaTexTop(tex, pos.xy + dir1 * rcpFrameOpt.zw); - half4 rgbyN2 = FxaaTexTop(tex, pos.xy - dir2 * rcpFrameOpt.xy); - half4 rgbyP2 = FxaaTexTop(tex, pos.xy + dir2 * rcpFrameOpt.xy); -/*--------------------------------------------------------------------------*/ - half4 rgbyA = rgbyN1 * 0.5 + rgbyP1 * 0.5; - half4 rgbyB = rgbyN2 * 0.25 + rgbyP2 * 0.25 + rgbyA * 0.5; -/*--------------------------------------------------------------------------*/ - bool twoTap = (rgbyB.w < lumaMin) || (rgbyB.w > lumaMax); - if(twoTap) rgbyB.xyz = rgbyA.xyz; - return rgbyB; } -/*==========================================================================*/ -#endif - - - -/*============================================================================ - - FXAA3 CONSOLE - 360 PIXEL SHADER OPTIMIZED PROTOTYPE - ------------------------------------------------------------------------------- -This prototype optimized version thanks to suggestions from Andy Luedke. -Should be fully tex bound in all cases. -As of the FXAA 3.10 release I have not tested this code, -but at least the missing ";" was fixed. -If it does not work, please let me know so I can fix it. ------------------------------------------------------------------------------- -Extra requirements, -(1.) Different inputs: no posPos. -(2.) Different inputs: alias three samplers with different exp bias settings! -(3.) New constants: setup fxaaConst as described below. -============================================================================*/ -#if (FXAA_360_OPT == 1) -/*--------------------------------------------------------------------------*/ -[reduceTempRegUsage(4)] -float4 FxaaPixelShader( - // {xy} = center of pixel - float2 pos, - // Three samplers, - // texExpBias0 = exponent bias 0 - // texExpBiasNeg1 = exponent bias -1 - // texExpBiasNeg2 = exponent bias -2 - // {rgb_} = color in linear or perceptual color space - // {___a} = alpha output is junk value - uniform sampler2D texExpBias0, - uniform sampler2D texExpBiasNeg1, - uniform sampler2D texExpBiasNeg2, - // These must be in physical constant registers and NOT immedates - // Immedates will result in compiler un-optimizing - // width = screen width in pixels - // height = screen height in pixels - fxaaConstDir, // float4(1.0, -1.0, 0.25, -0.25); - fxaaConstInner, // float4(0.5/width, 0.5/height, -0.5/width, -0.5/height); - fxaaConstOuter // float4(8.0/width, 8.0/height, -4.0/width, -4.0/height); -) { -/*--------------------------------------------------------------------------*/ - float4 lumaNwNeSwSe; - asm { - tfetch2D lumaNwNeSwSe.w___, texExpBias0, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false - tfetch2D lumaNwNeSwSe._w__, texExpBias0, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false - tfetch2D lumaNwNeSwSe.__w_, texExpBias0, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false - tfetch2D lumaNwNeSwSe.___w, texExpBias0, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false - }; -/*--------------------------------------------------------------------------*/ - lumaNwNeSwSe.y += 1.0/384.0; - float2 lumaMinTemp = min(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); - float2 lumaMaxTemp = max(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); - float lumaMin = min(lumaMinTemp.x, lumaMinTemp.y); - float lumaMax = max(lumaMaxTemp.x, lumaMaxTemp.y); -/*--------------------------------------------------------------------------*/ - float4 rgbyM = tex2Dlod(texExpBias0, float4(pos.xy, 0.0, 0.0)); - float4 lumaMinM = min(lumaMin, rgbyM.w); - float4 lumaMaxM = max(lumaMax, rgbyM.w); - if((lumaMaxM - lumaMinM) < max(FXAA_CONSOLE__EDGE_THRESHOLD_MIN, lumaMax * FXAA_CONSOLE__EDGE_THRESHOLD)) return rgbyM; -/*--------------------------------------------------------------------------*/ - float2 dir; - dir.x = dot(lumaNwNeSwSe, fxaaConstDir.yyxx); - dir.y = dot(lumaNwNeSwSe, fxaaConstDir.xyxy); - dir = normalize(dir); -/*--------------------------------------------------------------------------*/ - float4 dir1 = dir.xyxy * fxaaConstInner.xyzw; -/*--------------------------------------------------------------------------*/ - float4 dir2; - float dirAbsMinTimesC = min(abs(dir.x), abs(dir.y)); - dir2 = saturate(fxaaConstOuter.zzww * dir.xyxy / FXAA_CONSOLE__EDGE_SHARPNESS / dirAbsMinTimesC + 0.5); - dir2 = dir2 * fxaaConstOuter.xyxy + fxaaConstOuter.zwzw; -/*--------------------------------------------------------------------------*/ - float4 rgbyN1 = tex2Dlod(texExpBiasNeg1, float4(pos.xy + dir1.xy, 0.0, 0.0)); - float4 rgbyP1 = tex2Dlod(texExpBiasNeg1, float4(pos.xy + dir1.zw, 0.0, 0.0)); - float4 rgbyN2 = tex2Dlod(texExpBiasNeg2, float4(pos.xy + dir2.xy, 0.0, 0.0)); - float4 rgbyP2 = tex2Dlod(texExpBiasNeg2, float4(pos.xy + dir2.zw, 0.0, 0.0)); -/*--------------------------------------------------------------------------*/ - half4 rgbyA = rgbyN1 + rgbyP1; - half4 rgbyB = rgbyN2 + rgbyP2 * 0.5 + rgbyA; -/*--------------------------------------------------------------------------*/ - float4 rgbyR = ((rgbyB.w - lumaMax) > 0.0) ? rgbyA : rgbyB; - rgbyR = ((rgbyB.w - lumaMin) > 0.0) ? rgbyR : rgbyA; - return rgbyR; } -/*==========================================================================*/ -#endif - - - - -/*============================================================================ - - FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (NO EARLY EXIT) - -============================================================================== -The code below does not exactly match the assembly. -I have a feeling that 12 cycles is possible, but was not able to get there. -Might have to increase register count to get full performance. -Note this shader does not use perspective interpolation. - -Use the following cgc options, - - --fenable-bx2 --fastmath --fastprecision --nofloatbindings - ------------------------------------------------------------------------------- - NVSHADERPERF OUTPUT ------------------------------------------------------------------------------- -For reference and to aid in debug, output of NVShaderPerf should match this, - -Shader to schedule: - 0: texpkb h0.w(TRUE), v5.zyxx, #0 - 2: addh h2.z(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x - 4: texpkb h0.w(TRUE), v5.xwxx, #0 - 6: addh h0.z(TRUE), -h2, h0.w - 7: texpkb h1.w(TRUE), v5, #0 - 9: addh h0.x(TRUE), h0.z, -h1.w - 10: addh h3.w(TRUE), h0.z, h1 - 11: texpkb h2.w(TRUE), v5.zwzz, #0 - 13: addh h0.z(TRUE), h3.w, -h2.w - 14: addh h0.x(TRUE), h2.w, h0 - 15: nrmh h1.xz(TRUE), h0_n - 16: minh_m8 h0.x(TRUE), |h1|, |h1.z| - 17: maxh h4.w(TRUE), h0, h1 - 18: divx h2.xy(TRUE), h1_n.xzzw, h0_n - 19: movr r1.zw(TRUE), v4.xxxy - 20: madr r2.xz(TRUE), -h1, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zzww, r1.zzww - 22: minh h5.w(TRUE), h0, h1 - 23: texpkb h0(TRUE), r2.xzxx, #0 - 25: madr r0.zw(TRUE), h1.xzxz, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w), r1 - 27: maxh h4.x(TRUE), h2.z, h2.w - 28: texpkb h1(TRUE), r0.zwzz, #0 - 30: addh_d2 h1(TRUE), h0, h1 - 31: madr r0.xy(TRUE), -h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz - 33: texpkb h0(TRUE), r0, #0 - 35: minh h4.z(TRUE), h2, h2.w - 36: fenct TRUE - 37: madr r1.xy(TRUE), h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz - 39: texpkb h2(TRUE), r1, #0 - 41: addh_d2 h0(TRUE), h0, h2 - 42: maxh h2.w(TRUE), h4, h4.x - 43: minh h2.x(TRUE), h5.w, h4.z - 44: addh_d2 h0(TRUE), h0, h1 - 45: slth h2.x(TRUE), h0.w, h2 - 46: sgth h2.w(TRUE), h0, h2 - 47: movh h0(TRUE), h0 - 48: addx.c0 rc(TRUE), h2, h2.w - 49: movh h0(c0.NE.x), h1 - -IPU0 ------ Simplified schedule: -------- -Pass | Unit | uOp | PC: Op ------+--------+------+------------------------- - 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; - | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; - | SCB1 | add | 2: ADDh h2.z, h0.--w-, const.--x-; - | | | - 2 | SCT0/1 | mov | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; - | TEX | txl | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; - | SCB1 | add | 6: ADDh h0.z,-h2, h0.--w-; - | | | - 3 | SCT0/1 | mov | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; - | TEX | txl | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; - | SCB0 | add | 9: ADDh h0.x, h0.z---,-h1.w---; - | SCB1 | add | 10: ADDh h3.w, h0.---z, h1; - | | | - 4 | SCT0/1 | mov | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; - | TEX | txl | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; - | SCB0 | add | 14: ADDh h0.x, h2.w---, h0; - | SCB1 | add | 13: ADDh h0.z, h3.--w-,-h2.--w-; - | | | - 5 | SCT1 | mov | 15: NRMh h1.xz, h0; - | SRB | nrm | 15: NRMh h1.xz, h0; - | SCB0 | min | 16: MINh*8 h0.x, |h1|, |h1.z---|; - | SCB1 | max | 17: MAXh h4.w, h0, h1; - | | | - 6 | SCT0 | div | 18: DIVx h2.xy, h1.xz--, h0; - | SCT1 | mov | 19: MOVr r1.zw, g[TEX0].--xy; - | SCB0 | mad | 20: MADr r2.xz,-h1, const.z-w-, r1.z-w-; - | SCB1 | min | 22: MINh h5.w, h0, h1; - | | | - 7 | SCT0/1 | mov | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; - | TEX | txl | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; - | SCB0 | max | 27: MAXh h4.x, h2.z---, h2.w---; - | SCB1 | mad | 25: MADr r0.zw, h1.--xz, const, r1; - | | | - 8 | SCT0/1 | mov | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; - | TEX | txl | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; - | SCB0/1 | add | 30: ADDh/2 h1, h0, h1; - | | | - 9 | SCT0 | mad | 31: MADr r0.xy,-h2, const.xy--, r1.zw--; - | SCT1 | mov | 33: TXLr h0, r0, const.zzzz, TEX0; - | TEX | txl | 33: TXLr h0, r0, const.zzzz, TEX0; - | SCB1 | min | 35: MINh h4.z, h2, h2.--w-; - | | | - 10 | SCT0 | mad | 37: MADr r1.xy, h2, const.xy--, r1.zw--; - | SCT1 | mov | 39: TXLr h2, r1, const.zzzz, TEX0; - | TEX | txl | 39: TXLr h2, r1, const.zzzz, TEX0; - | SCB0/1 | add | 41: ADDh/2 h0, h0, h2; - | | | - 11 | SCT0 | min | 43: MINh h2.x, h5.w---, h4.z---; - | SCT1 | max | 42: MAXh h2.w, h4, h4.---x; - | SCB0/1 | add | 44: ADDh/2 h0, h0, h1; - | | | - 12 | SCT0 | set | 45: SLTh h2.x, h0.w---, h2; - | SCT1 | set | 46: SGTh h2.w, h0, h2; - | SCB0/1 | mul | 47: MOVh h0, h0; - | | | - 13 | SCT0 | mad | 48: ADDxc0_s rc, h2, h2.w---; - | SCB0/1 | mul | 49: MOVh h0(NE0.xxxx), h1; - -Pass SCT TEX SCB - 1: 0% 100% 25% - 2: 0% 100% 25% - 3: 0% 100% 50% - 4: 0% 100% 50% - 5: 0% 0% 50% - 6: 100% 0% 75% - 7: 0% 100% 75% - 8: 0% 100% 100% - 9: 0% 100% 25% - 10: 0% 100% 100% - 11: 50% 0% 100% - 12: 50% 0% 100% - 13: 25% 0% 100% - -MEAN: 17% 61% 67% - -Pass SCT0 SCT1 TEX SCB0 SCB1 - 1: 0% 0% 100% 0% 100% - 2: 0% 0% 100% 0% 100% - 3: 0% 0% 100% 100% 100% - 4: 0% 0% 100% 100% 100% - 5: 0% 0% 0% 100% 100% - 6: 100% 100% 0% 100% 100% - 7: 0% 0% 100% 100% 100% - 8: 0% 0% 100% 100% 100% - 9: 0% 0% 100% 0% 100% - 10: 0% 0% 100% 100% 100% - 11: 100% 100% 0% 100% 100% - 12: 100% 100% 0% 100% 100% - 13: 100% 0% 0% 100% 100% - -MEAN: 30% 23% 61% 76% 100% -Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 -Results 13 cycles, 3 r regs, 923,076,923 pixels/s -============================================================================*/ -#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 0) -/*--------------------------------------------------------------------------*/ -#pragma disablepc all -#pragma option O3 -#pragma option OutColorPrec=fp16 -#pragma texformat default RGBA8 -/*==========================================================================*/ -half4 FxaaPixelShader( - // {xy} = center of pixel - float2 pos, - // {xy__} = upper left of pixel - // {__zw} = lower right of pixel - float4 posPos, - // {rgb_} = color in linear or perceptual color space - // {___a} = luma in perceptual color space (not linear) - sampler2D tex, - // This must be from a constant/uniform. - // {xy} = rcpFrame not used on PS3 - float2 rcpFrame, - // This must be from a constant/uniform. - // {x___} = 2.0/screenWidthInPixels - // {_y__} = 2.0/screenHeightInPixels - // {__z_} = 0.5/screenWidthInPixels - // {___w} = 0.5/screenHeightInPixels - float4 rcpFrameOpt -) { -/*--------------------------------------------------------------------------*/ -// (1) - half4 dir; - half4 lumaNe = h4tex2Dlod(tex, half4(posPos.zy, 0, 0)); - lumaNe.w += half(1.0/512.0); - dir.x = -lumaNe.w; - dir.z = -lumaNe.w; -/*--------------------------------------------------------------------------*/ -// (2) - half4 lumaSw = h4tex2Dlod(tex, half4(posPos.xw, 0, 0)); - dir.x += lumaSw.w; - dir.z += lumaSw.w; -/*--------------------------------------------------------------------------*/ -// (3) - half4 lumaNw = h4tex2Dlod(tex, half4(posPos.xy, 0, 0)); - dir.x -= lumaNw.w; - dir.z += lumaNw.w; -/*--------------------------------------------------------------------------*/ -// (4) - half4 lumaSe = h4tex2Dlod(tex, half4(posPos.zw, 0, 0)); - dir.x += lumaSe.w; - dir.z -= lumaSe.w; -/*--------------------------------------------------------------------------*/ -// (5) - half4 dir1_pos; - dir1_pos.xy = normalize(dir.xyz).xz; - half dirAbsMinTimesC = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__EDGE_SHARPNESS); -/*--------------------------------------------------------------------------*/ -// (6) - half4 dir2_pos; - dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimesC, half(-2.0), half(2.0)); - dir1_pos.zw = pos.xy; - dir2_pos.zw = pos.xy; - half4 temp1N; - temp1N.xy = dir1_pos.zw - dir1_pos.xy * rcpFrameOpt.zw; -/*--------------------------------------------------------------------------*/ -// (7) - temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); - half4 rgby1; - rgby1.xy = dir1_pos.zw + dir1_pos.xy * rcpFrameOpt.zw; -/*--------------------------------------------------------------------------*/ -// (8) - rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); - rgby1 = (temp1N + rgby1) * 0.5; -/*--------------------------------------------------------------------------*/ -// (9) - half4 temp2N; - temp2N.xy = dir2_pos.zw - dir2_pos.xy * rcpFrameOpt.xy; - temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); -/*--------------------------------------------------------------------------*/ -// (10) - half4 rgby2; - rgby2.xy = dir2_pos.zw + dir2_pos.xy * rcpFrameOpt.xy; - rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); - rgby2 = (temp2N + rgby2) * 0.5; -/*--------------------------------------------------------------------------*/ -// (11) - // compilier moves these scalar ops up to other cycles - half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w)); - half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w)); - rgby2 = (rgby2 + rgby1) * 0.5; -/*--------------------------------------------------------------------------*/ -// (12) - bool twoTapLt = rgby2.w < lumaMin; - bool twoTapGt = rgby2.w > lumaMax; -/*--------------------------------------------------------------------------*/ -// (13) - if(twoTapLt || twoTapGt) rgby2 = rgby1; -/*--------------------------------------------------------------------------*/ - return rgby2; } -/*==========================================================================*/ -#endif - - - -/*============================================================================ - - FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (WITH EARLY EXIT) - -============================================================================== -The code mostly matches the assembly. -I have a feeling that 14 cycles is possible, but was not able to get there. -Might have to increase register count to get full performance. -Note this shader does not use perspective interpolation. - -Use the following cgc options, - - --fenable-bx2 --fastmath --fastprecision --nofloatbindings - ------------------------------------------------------------------------------- - NVSHADERPERF OUTPUT ------------------------------------------------------------------------------- -For reference and to aid in debug, output of NVShaderPerf should match this, - -Shader to schedule: - 0: texpkb h0.w(TRUE), v5.zyxx, #0 - 2: addh h2.y(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x - 4: texpkb h1.w(TRUE), v5.xwxx, #0 - 6: addh h0.x(TRUE), h1.w, -h2.y - 7: texpkb h2.w(TRUE), v5.zwzz, #0 - 9: minh h4.w(TRUE), h2.y, h2 - 10: maxh h5.x(TRUE), h2.y, h2.w - 11: texpkb h0.w(TRUE), v5, #0 - 13: addh h3.w(TRUE), -h0, h0.x - 14: addh h0.x(TRUE), h0.w, h0 - 15: addh h0.z(TRUE), -h2.w, h0.x - 16: addh h0.x(TRUE), h2.w, h3.w - 17: minh h5.y(TRUE), h0.w, h1.w - 18: nrmh h2.xz(TRUE), h0_n - 19: minh_m8 h2.w(TRUE), |h2.x|, |h2.z| - 20: divx h4.xy(TRUE), h2_n.xzzw, h2_n.w - 21: movr r1.zw(TRUE), v4.xxxy - 22: maxh h2.w(TRUE), h0, h1 - 23: fenct TRUE - 24: madr r0.xy(TRUE), -h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz - 26: texpkb h0(TRUE), r0, #0 - 28: maxh h5.x(TRUE), h2.w, h5 - 29: minh h5.w(TRUE), h5.y, h4 - 30: madr r1.xy(TRUE), h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz - 32: texpkb h2(TRUE), r1, #0 - 34: addh_d2 h2(TRUE), h0, h2 - 35: texpkb h1(TRUE), v4, #0 - 37: maxh h5.y(TRUE), h5.x, h1.w - 38: minh h4.w(TRUE), h1, h5 - 39: madr r0.xy(TRUE), -h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz - 41: texpkb h0(TRUE), r0, #0 - 43: addh_m8 h5.z(TRUE), h5.y, -h4.w - 44: madr r2.xy(TRUE), h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz - 46: texpkb h3(TRUE), r2, #0 - 48: addh_d2 h0(TRUE), h0, h3 - 49: addh_d2 h3(TRUE), h0, h2 - 50: movh h0(TRUE), h3 - 51: slth h3.x(TRUE), h3.w, h5.w - 52: sgth h3.w(TRUE), h3, h5.x - 53: addx.c0 rc(TRUE), h3.x, h3 - 54: slth.c0 rc(TRUE), h5.z, h5 - 55: movh h0(c0.NE.w), h2 - 56: movh h0(c0.NE.x), h1 - -IPU0 ------ Simplified schedule: -------- -Pass | Unit | uOp | PC: Op ------+--------+------+------------------------- - 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; - | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; - | SCB0 | add | 2: ADDh h2.y, h0.-w--, const.-x--; - | | | - 2 | SCT0/1 | mov | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; - | TEX | txl | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; - | SCB0 | add | 6: ADDh h0.x, h1.w---,-h2.y---; - | | | - 3 | SCT0/1 | mov | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; - | TEX | txl | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; - | SCB0 | max | 10: MAXh h5.x, h2.y---, h2.w---; - | SCB1 | min | 9: MINh h4.w, h2.---y, h2; - | | | - 4 | SCT0/1 | mov | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; - | TEX | txl | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; - | SCB0 | add | 14: ADDh h0.x, h0.w---, h0; - | SCB1 | add | 13: ADDh h3.w,-h0, h0.---x; - | | | - 5 | SCT0 | mad | 16: ADDh h0.x, h2.w---, h3.w---; - | SCT1 | mad | 15: ADDh h0.z,-h2.--w-, h0.--x-; - | SCB0 | min | 17: MINh h5.y, h0.-w--, h1.-w--; - | | | - 6 | SCT1 | mov | 18: NRMh h2.xz, h0; - | SRB | nrm | 18: NRMh h2.xz, h0; - | SCB1 | min | 19: MINh*8 h2.w, |h2.---x|, |h2.---z|; - | | | - 7 | SCT0 | div | 20: DIVx h4.xy, h2.xz--, h2.ww--; - | SCT1 | mov | 21: MOVr r1.zw, g[TEX0].--xy; - | SCB1 | max | 22: MAXh h2.w, h0, h1; - | | | - 8 | SCT0 | mad | 24: MADr r0.xy,-h2.xz--, const.zw--, r1.zw--; - | SCT1 | mov | 26: TXLr h0, r0, const.xxxx, TEX0; - | TEX | txl | 26: TXLr h0, r0, const.xxxx, TEX0; - | SCB0 | max | 28: MAXh h5.x, h2.w---, h5; - | SCB1 | min | 29: MINh h5.w, h5.---y, h4; - | | | - 9 | SCT0 | mad | 30: MADr r1.xy, h2.xz--, const.zw--, r1.zw--; - | SCT1 | mov | 32: TXLr h2, r1, const.xxxx, TEX0; - | TEX | txl | 32: TXLr h2, r1, const.xxxx, TEX0; - | SCB0/1 | add | 34: ADDh/2 h2, h0, h2; - | | | - 10 | SCT0/1 | mov | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; - | TEX | txl | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; - | SCB0 | max | 37: MAXh h5.y, h5.-x--, h1.-w--; - | SCB1 | min | 38: MINh h4.w, h1, h5; - | | | - 11 | SCT0 | mad | 39: MADr r0.xy,-h4, const.xy--, r1.zw--; - | SCT1 | mov | 41: TXLr h0, r0, const.zzzz, TEX0; - | TEX | txl | 41: TXLr h0, r0, const.zzzz, TEX0; - | SCB0 | mad | 44: MADr r2.xy, h4, const.xy--, r1.zw--; - | SCB1 | add | 43: ADDh*8 h5.z, h5.--y-,-h4.--w-; - | | | - 12 | SCT0/1 | mov | 46: TXLr h3, r2, const.xxxx, TEX0; - | TEX | txl | 46: TXLr h3, r2, const.xxxx, TEX0; - | SCB0/1 | add | 48: ADDh/2 h0, h0, h3; - | | | - 13 | SCT0/1 | mad | 49: ADDh/2 h3, h0, h2; - | SCB0/1 | mul | 50: MOVh h0, h3; - | | | - 14 | SCT0 | set | 51: SLTh h3.x, h3.w---, h5.w---; - | SCT1 | set | 52: SGTh h3.w, h3, h5.---x; - | SCB0 | set | 54: SLThc0 rc, h5.z---, h5; - | SCB1 | add | 53: ADDxc0_s rc, h3.---x, h3; - | | | - 15 | SCT0/1 | mul | 55: MOVh h0(NE0.wwww), h2; - | SCB0/1 | mul | 56: MOVh h0(NE0.xxxx), h1; - -Pass SCT TEX SCB - 1: 0% 100% 25% - 2: 0% 100% 25% - 3: 0% 100% 50% - 4: 0% 100% 50% - 5: 50% 0% 25% - 6: 0% 0% 25% - 7: 100% 0% 25% - 8: 0% 100% 50% - 9: 0% 100% 100% - 10: 0% 100% 50% - 11: 0% 100% 75% - 12: 0% 100% 100% - 13: 100% 0% 100% - 14: 50% 0% 50% - 15: 100% 0% 100% - -MEAN: 26% 60% 56% - -Pass SCT0 SCT1 TEX SCB0 SCB1 - 1: 0% 0% 100% 100% 0% - 2: 0% 0% 100% 100% 0% - 3: 0% 0% 100% 100% 100% - 4: 0% 0% 100% 100% 100% - 5: 100% 100% 0% 100% 0% - 6: 0% 0% 0% 0% 100% - 7: 100% 100% 0% 0% 100% - 8: 0% 0% 100% 100% 100% - 9: 0% 0% 100% 100% 100% - 10: 0% 0% 100% 100% 100% - 11: 0% 0% 100% 100% 100% - 12: 0% 0% 100% 100% 100% - 13: 100% 100% 0% 100% 100% - 14: 100% 100% 0% 100% 100% - 15: 100% 100% 0% 100% 100% - -MEAN: 33% 33% 60% 86% 80% -Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 -Results 15 cycles, 3 r regs, 800,000,000 pixels/s -============================================================================*/ -#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 1) -/*--------------------------------------------------------------------------*/ -#pragma disablepc all -#pragma option O2 -#pragma option OutColorPrec=fp16 -#pragma texformat default RGBA8 -/*==========================================================================*/ -half4 FxaaPixelShader( - // {xy} = center of pixel - float2 pos, - // {xy__} = upper left of pixel - // {__zw} = lower right of pixel - float4 posPos, - // {rgb_} = color in linear or perceptual color space - // {___a} = luma in perceptual color space (not linear) - sampler2D tex, - // This must be from a constant/uniform. - // {xy} = rcpFrame not used on PS3 - float2 rcpFrame, - // This must be from a constant/uniform. - // {x___} = 2.0/screenWidthInPixels - // {_y__} = 2.0/screenHeightInPixels - // {__z_} = 0.5/screenWidthInPixels - // {___w} = 0.5/screenHeightInPixels - float4 rcpFrameOpt -) { -/*--------------------------------------------------------------------------*/ -// (1) - half4 rgbyNe = h4tex2Dlod(tex, half4(posPos.zy, 0, 0)); - half lumaNe = rgbyNe.w + half(1.0/512.0); -/*--------------------------------------------------------------------------*/ -// (2) - half4 lumaSw = h4tex2Dlod(tex, half4(posPos.xw, 0, 0)); - half lumaSwNegNe = lumaSw.w - lumaNe; -/*--------------------------------------------------------------------------*/ -// (3) - half4 lumaNw = h4tex2Dlod(tex, half4(posPos.xy, 0, 0)); - half lumaMaxNwSw = max(lumaNw.w, lumaSw.w); - half lumaMinNwSw = min(lumaNw.w, lumaSw.w); -/*--------------------------------------------------------------------------*/ -// (4) - half4 lumaSe = h4tex2Dlod(tex, half4(posPos.zw, 0, 0)); - half dirZ = lumaNw.w + lumaSwNegNe; - half dirX = -lumaNw.w + lumaSwNegNe; -/*--------------------------------------------------------------------------*/ -// (5) - half3 dir; - dir.y = 0.0; - dir.x = lumaSe.w + dirX; - dir.z = -lumaSe.w + dirZ; - half lumaMinNeSe = min(lumaNe, lumaSe.w); -/*--------------------------------------------------------------------------*/ -// (6) - half4 dir1_pos; - dir1_pos.xy = normalize(dir).xz; - half dirAbsMinTimes8 = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__EDGE_SHARPNESS); -/*--------------------------------------------------------------------------*/ -// (7) - half4 dir2_pos; - dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimes8, half(-2.0), half(2.0)); - dir1_pos.zw = pos.xy; - dir2_pos.zw = pos.xy; - half lumaMaxNeSe = max(lumaNe, lumaSe.w); -/*--------------------------------------------------------------------------*/ -// (8) - half4 temp1N; - temp1N.xy = dir1_pos.zw - dir1_pos.xy * rcpFrameOpt.zw; - temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); - half lumaMax = max(lumaMaxNwSw, lumaMaxNeSe); - half lumaMin = min(lumaMinNwSw, lumaMinNeSe); -/*--------------------------------------------------------------------------*/ -// (9) - half4 rgby1; - rgby1.xy = dir1_pos.zw + dir1_pos.xy * rcpFrameOpt.zw; - rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); - rgby1 = (temp1N + rgby1) * 0.5; -/*--------------------------------------------------------------------------*/ -// (10) - half4 rgbyM = h4tex2Dlod(tex, half4(pos.xy, 0.0, 0.0)); - half lumaMaxM = max(lumaMax, rgbyM.w); - half lumaMinM = min(lumaMin, rgbyM.w); -/*--------------------------------------------------------------------------*/ -// (11) - half4 temp2N; - temp2N.xy = dir2_pos.zw - dir2_pos.xy * rcpFrameOpt.xy; - temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); - half4 rgby2; - rgby2.xy = dir2_pos.zw + dir2_pos.xy * rcpFrameOpt.xy; - half lumaRangeM = (lumaMaxM - lumaMinM) / FXAA_CONSOLE__EDGE_THRESHOLD; -/*--------------------------------------------------------------------------*/ -// (12) - rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); - rgby2 = (temp2N + rgby2) * 0.5; -/*--------------------------------------------------------------------------*/ -// (13) - rgby2 = (rgby2 + rgby1) * 0.5; -/*--------------------------------------------------------------------------*/ -// (14) - bool twoTapLt = rgby2.w < lumaMin; - bool twoTapGt = rgby2.w > lumaMax; - bool earlyExit = lumaRangeM < lumaMax; - bool twoTap = twoTapLt || twoTapGt; -/*--------------------------------------------------------------------------*/ -// (15) - if(twoTap) rgby2 = rgby1; - if(earlyExit) rgby2 = rgbyM; -/*--------------------------------------------------------------------------*/ - return rgby2; } -/*==========================================================================*/ -#endif - - - -/*============================================================================ - - FXAA3 CONSOLE - PC PIXEL SHADER - ------------------------------------------------------------------------------- -Using a modified version of the PS3 version here to best target old hardware. -============================================================================*/ -#if (FXAA_PC_CONSOLE == 1) -/*--------------------------------------------------------------------------*/ -half4 FxaaPixelShader( - // {xy} = center of pixel - float2 pos, - // {xy__} = upper left of pixel - // {__zw} = lower right of pixel - float4 posPos, - // {rgb_} = color in linear or perceptual color space - // {___a} = alpha output is junk value - FxaaTex tex, - // This must be from a constant/uniform. - // {xy} = rcpFrame not used on PC version of FXAA Console - float2 rcpFrame, - // This must be from a constant/uniform. - // {x___} = 2.0/screenWidthInPixels - // {_y__} = 2.0/screenHeightInPixels - // {__z_} = 0.5/screenWidthInPixels - // {___w} = 0.5/screenHeightInPixels - float4 rcpFrameOpt -) { -/*--------------------------------------------------------------------------*/ - half4 dir; - dir.y = 0.0; - half4 lumaNe = FxaaTexTop(tex, posPos.zy); - lumaNe.w += half(1.0/384.0); - dir.x = -lumaNe.w; - dir.z = -lumaNe.w; -/*--------------------------------------------------------------------------*/ - half4 lumaSw = FxaaTexTop(tex, posPos.xw); - dir.x += lumaSw.w; - dir.z += lumaSw.w; -/*--------------------------------------------------------------------------*/ - half4 lumaNw = FxaaTexTop(tex, posPos.xy); - dir.x -= lumaNw.w; - dir.z += lumaNw.w; -/*--------------------------------------------------------------------------*/ - half4 lumaSe = FxaaTexTop(tex, posPos.zw); - dir.x += lumaSe.w; - dir.z -= lumaSe.w; -/*==========================================================================*/ - #if (FXAA_EARLY_EXIT == 1) - half4 rgbyM = FxaaTexTop(tex, pos.xy); -/*--------------------------------------------------------------------------*/ - half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w)); - half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w)); -/*--------------------------------------------------------------------------*/ - half lumaMinM = min(lumaMin, rgbyM.w); - half lumaMaxM = max(lumaMax, rgbyM.w); -/*--------------------------------------------------------------------------*/ - if((lumaMaxM - lumaMinM) < max(FXAA_CONSOLE__EDGE_THRESHOLD_MIN, lumaMax * FXAA_CONSOLE__EDGE_THRESHOLD)) - #if (FXAA_DISCARD == 1) - FxaaDiscard; - #else - return rgbyM; - #endif - #endif -/*==========================================================================*/ - half4 dir1_pos; - dir1_pos.xy = normalize(dir.xyz).xz; - half dirAbsMinTimesC = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__EDGE_SHARPNESS); -/*--------------------------------------------------------------------------*/ - half4 dir2_pos; - dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimesC, half(-2.0), half(2.0)); - dir1_pos.zw = pos.xy; - dir2_pos.zw = pos.xy; - half4 temp1N; - temp1N.xy = dir1_pos.zw - dir1_pos.xy * rcpFrameOpt.zw; -/*--------------------------------------------------------------------------*/ - temp1N = FxaaTexTop(tex, temp1N.xy); - half4 rgby1; - rgby1.xy = dir1_pos.zw + dir1_pos.xy * rcpFrameOpt.zw; -/*--------------------------------------------------------------------------*/ - rgby1 = FxaaTexTop(tex, rgby1.xy); - rgby1 = (temp1N + rgby1) * 0.5; -/*--------------------------------------------------------------------------*/ - half4 temp2N; - temp2N.xy = dir2_pos.zw - dir2_pos.xy * rcpFrameOpt.xy; - temp2N = FxaaTexTop(tex, temp2N.xy); -/*--------------------------------------------------------------------------*/ - half4 rgby2; - rgby2.xy = dir2_pos.zw + dir2_pos.xy * rcpFrameOpt.xy; - rgby2 = FxaaTexTop(tex, rgby2.xy); - rgby2 = (temp2N + rgby2) * 0.5; -/*--------------------------------------------------------------------------*/ - #if (FXAA_EARLY_EXIT == 0) - half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w)); - half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w)); - #endif - rgby2 = (rgby2 + rgby1) * 0.5; -/*--------------------------------------------------------------------------*/ - bool twoTapLt = rgby2.w < lumaMin; - bool twoTapGt = rgby2.w > lumaMax; -/*--------------------------------------------------------------------------*/ - if(twoTapLt || twoTapGt) rgby2 = rgby1; -/*--------------------------------------------------------------------------*/ - return rgby2; } -/*==========================================================================*/ -#endif - - - -/*============================================================================ - - FXAA3 QUALITY - PC - -============================================================================*/ -#if (FXAA_PC == 1) -/*--------------------------------------------------------------------------*/ -float4 FxaaPixelShader( - // {xy} = center of pixel - float2 pos, - // {xyzw} = not used on FXAA3 Quality - float4 posPos, - // {rgb_} = color in linear or perceptual color space - // {___a} = luma in perceptual color space (not linear) - FxaaTex tex, - // This must be from a constant/uniform. - // {x_} = 1.0/screenWidthInPixels - // {_y} = 1.0/screenHeightInPixels - float2 rcpFrame, - // {xyzw} = not used on FXAA3 Quality - float4 rcpFrameOpt -) { -/*--------------------------------------------------------------------------*/ - float2 posM; - posM.x = pos.x; - posM.y = pos.y; - #if (FXAA_GATHER4_ALPHA == 1) - #if (FXAA_DISCARD == 0) - float4 rgbyM = FxaaTexTop(tex, posM); - #define lumaM rgbyM.w - #endif - float4 luma4A = FxaaTexAlpha4(tex, posM, rcpFrame.xy); - float4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1), rcpFrame.xy); - #if (FXAA_DISCARD == 1) - #define lumaM luma4A.w - #endif - #define lumaE luma4A.z - #define lumaS luma4A.x - #define lumaSE luma4A.y - #define lumaNW luma4B.w - #define lumaN luma4B.z - #define lumaW luma4B.x - #else - float4 rgbyM = FxaaTexTop(tex, posM); - #define lumaM rgbyM.w - float lumaS = FxaaTexOff(tex, posM, FxaaInt2( 0, 1), rcpFrame.xy).w; - float lumaE = FxaaTexOff(tex, posM, FxaaInt2( 1, 0), rcpFrame.xy).w; - float lumaN = FxaaTexOff(tex, posM, FxaaInt2( 0,-1), rcpFrame.xy).w; - float lumaW = FxaaTexOff(tex, posM, FxaaInt2(-1, 0), rcpFrame.xy).w; - #endif -/*--------------------------------------------------------------------------*/ - float maxSM = max(lumaS, lumaM); - float minSM = min(lumaS, lumaM); - float maxESM = max(lumaE, maxSM); - float minESM = min(lumaE, minSM); - float maxWN = max(lumaN, lumaW); - float minWN = min(lumaN, lumaW); - float rangeMax = max(maxWN, maxESM); - float rangeMin = min(minWN, minESM); - float rangeMaxScaled = rangeMax * FXAA_QUALITY__EDGE_THRESHOLD; - float range = rangeMax - rangeMin; - float rangeMaxClamped = max(FXAA_QUALITY__EDGE_THRESHOLD_MIN, rangeMaxScaled); - bool earlyExit = range < rangeMaxClamped; -/*--------------------------------------------------------------------------*/ - if(earlyExit) - #if (FXAA_DISCARD == 1) - FxaaDiscard; - #else - return rgbyM; - #endif -/*--------------------------------------------------------------------------*/ - #if (FXAA_GATHER4_ALPHA == 0) - float lumaNW = FxaaTexOff(tex, posM, FxaaInt2(-1,-1), rcpFrame.xy).w; - float lumaSE = FxaaTexOff(tex, posM, FxaaInt2( 1, 1), rcpFrame.xy).w; - float lumaNE = FxaaTexOff(tex, posM, FxaaInt2( 1,-1), rcpFrame.xy).w; - float lumaSW = FxaaTexOff(tex, posM, FxaaInt2(-1, 1), rcpFrame.xy).w; - #else - float lumaNE = FxaaTexOff(tex, posM, FxaaInt2(1, -1), rcpFrame.xy).w; - float lumaSW = FxaaTexOff(tex, posM, FxaaInt2(-1, 1), rcpFrame.xy).w; - #endif -/*--------------------------------------------------------------------------*/ - float lumaNS = lumaN + lumaS; - float lumaWE = lumaW + lumaE; - float subpixRcpRange = 1.0/range; - float subpixNSWE = lumaNS + lumaWE; - float edgeHorz1 = (-2.0 * lumaM) + lumaNS; - float edgeVert1 = (-2.0 * lumaM) + lumaWE; -/*--------------------------------------------------------------------------*/ - float lumaNESE = lumaNE + lumaSE; - float lumaNWNE = lumaNW + lumaNE; - float edgeHorz2 = (-2.0 * lumaE) + lumaNESE; - float edgeVert2 = (-2.0 * lumaN) + lumaNWNE; -/*--------------------------------------------------------------------------*/ - float lumaNWSW = lumaNW + lumaSW; - float lumaSWSE = lumaSW + lumaSE; - float edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2); - float edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2); - float edgeHorz3 = (-2.0 * lumaW) + lumaNWSW; - float edgeVert3 = (-2.0 * lumaS) + lumaSWSE; - float edgeHorz = abs(edgeHorz3) + edgeHorz4; - float edgeVert = abs(edgeVert3) + edgeVert4; -/*--------------------------------------------------------------------------*/ - float subpixNWSWNESE = lumaNWSW + lumaNESE; - float lengthSign = rcpFrame.x; - bool horzSpan = edgeHorz >= edgeVert; - float subpixA = subpixNSWE * 2.0 + subpixNWSWNESE; -/*--------------------------------------------------------------------------*/ - if(!horzSpan) lumaN = lumaW; - if(!horzSpan) lumaS = lumaE; - if(horzSpan) lengthSign = rcpFrame.y; - float subpixB = (subpixA * (1.0/12.0)) - lumaM; -/*--------------------------------------------------------------------------*/ - float gradientN = lumaN - lumaM; - float gradientS = lumaS - lumaM; - float lumaNN = lumaN + lumaM; - float lumaSS = lumaS + lumaM; - bool pairN = abs(gradientN) >= abs(gradientS); - float gradient = max(abs(gradientN), abs(gradientS)); - if(pairN) lengthSign = -lengthSign; - float subpixC = FxaaSat(abs(subpixB) * subpixRcpRange); -/*--------------------------------------------------------------------------*/ - float2 posB; - posB.x = posM.x; - posB.y = posM.y; - float2 offNP; - offNP.x = (!horzSpan) ? 0.0 : rcpFrame.x; - offNP.y = ( horzSpan) ? 0.0 : rcpFrame.y; - if(!horzSpan) posB.x += lengthSign * 0.5; - if( horzSpan) posB.y += lengthSign * 0.5; -/*--------------------------------------------------------------------------*/ - float2 posN; - posN.x = posB.x - offNP.x * FXAA_QUALITY__P0; - posN.y = posB.y - offNP.y * FXAA_QUALITY__P0; - float2 posP; - posP.x = posB.x + offNP.x * FXAA_QUALITY__P0; - posP.y = posB.y + offNP.y * FXAA_QUALITY__P0; - float subpixD = ((-2.0)*subpixC) + 3.0; - float lumaEndN = FxaaTexTop(tex, posN).w; - float subpixE = subpixC * subpixC; - float lumaEndP = FxaaTexTop(tex, posP).w; -/*--------------------------------------------------------------------------*/ - if(!pairN) lumaNN = lumaSS; - float gradientScaled = gradient * 1.0/4.0; - float lumaMM = lumaM - lumaNN * 0.5; - float subpixF = subpixD * subpixE; - bool lumaMLTZero = lumaMM < 0.0; -/*--------------------------------------------------------------------------*/ - lumaEndN -= lumaNN * 0.5; - lumaEndP -= lumaNN * 0.5; - bool doneN = abs(lumaEndN) >= gradientScaled; - bool doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1; - bool doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P1; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P1; -/*--------------------------------------------------------------------------*/ - if(doneNP) { - if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; - if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P2; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P2; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 3) - if(doneNP) { - if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; - if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P3; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P3; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 4) - if(doneNP) { - if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; - if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P4; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P4; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 5) - if(doneNP) { - if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; - if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P5; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P5; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 6) - if(doneNP) { - if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; - if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P6; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P6; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 7) - if(doneNP) { - if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; - if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P7; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P7; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 8) - if(doneNP) { - if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; - if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P8; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P8; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 9) - if(doneNP) { - if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; - if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P9; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P9; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P9; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P9; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 10) - if(doneNP) { - if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; - if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P10; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P10; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P10; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P10; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 11) - if(doneNP) { - if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; - if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P11; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P11; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P11; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P11; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 12) - if(doneNP) { - if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; - if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P12; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P12; -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } -/*--------------------------------------------------------------------------*/ - float dstN = posM.x - posN.x; - float dstP = posP.x - posM.x; - if(!horzSpan) dstN = posM.y - posN.y; - if(!horzSpan) dstP = posP.y - posM.y; -/*--------------------------------------------------------------------------*/ - bool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero; - float spanLength = (dstP + dstN); - bool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero; - float spanLengthRcp = 1.0/spanLength; -/*--------------------------------------------------------------------------*/ - bool directionN = dstN < dstP; - float dst = min(dstN, dstP); - bool goodSpan = directionN ? goodSpanN : goodSpanP; - float subpixG = subpixF * subpixF; - float pixelOffset = (dst * (-spanLengthRcp)) + 0.5; - float subpixH = subpixG * FXAA_QUALITY__SUBPIX; -/*--------------------------------------------------------------------------*/ - float pixelOffsetGood = goodSpan ? pixelOffset : 0.0; - float pixelOffsetSubpix = max(pixelOffsetGood, subpixH); - if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign; - if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign; - #if (FXAA_DISCARD == 1) - return FxaaTexTop(tex, posM); - #else - return float4(FxaaTexTop(tex, posM).xyz, lumaM); - #endif -} -/*==========================================================================*/ -#endif - -PS_OUTPUT ps_main(PS_INPUT input) -{ - PS_OUTPUT output; - - float2 pos = input.t; - float4 posPos = (float4)0; - - FxaaTex tex; - - #if SHADER_MODEL >= 0x400 - - tex.tex = Texture; - tex.smpl = TextureSampler; - - #else - - tex = Texture; - - #endif - - output.c = FxaaPixelShader(pos, posPos, tex, _rcpFrame.xy, _rcpFrameOpt); - - return output; -} - -#endif +#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency + +#define FXAA_PC 1 +#define FXAA_QUALITY__SUBPIX 0.0 + +#if SHADER_MODEL >= 0x400 + +#if SHADER_MODEL >= 0x500 + #define FXAA_HLSL_5 1 +#else + #define FXAA_HLSL_4 1 +#endif + +Texture2D Texture; +SamplerState TextureSampler; + +cbuffer cb0 +{ + float4 _rcpFrame; + float4 _rcpFrameOpt; +}; + +struct PS_INPUT +{ + float4 p : SV_Position; + float2 t : TEXCOORD0; +}; + +struct PS_OUTPUT +{ + float4 c : SV_Target0; +}; + +#elif SHADER_MODEL <= 0x300 + +#define FXAA_HLSL_3 1 + +sampler Texture : register(s0); + +float4 _rcpFrame : register(c0); +float4 _rcpFrameOpt : register(c1); + +struct PS_INPUT +{ +#if SHADER_MODEL < 0x300 + float4 p : TEXCOORD1; +#else + float4 p : VPOS; +#endif + float2 t : TEXCOORD0; +}; + +struct PS_OUTPUT +{ + float4 c : COLOR; +}; + +#endif + +/*============================================================================ + + + NVIDIA FXAA 3.10 by TIMOTHY LOTTES + + +------------------------------------------------------------------------------ +COPYRIGHT (C) 2010, 2011 NVIDIA CORPORATION. ALL RIGHTS RESERVED. +------------------------------------------------------------------------------ +TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED +*AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA +OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR +CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR +LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, +OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE +THIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + +------------------------------------------------------------------------------ + INTEGRATION CHECKLIST +------------------------------------------------------------------------------ +(1.) +In the shader source, +setup defines for the desired configuration. +Example, + + #define FXAA_PC 1 + #define FXAA_HLSL_3 1 + #define FXAA_QUALITY__PRESET 12 + #define FXAA_QUALITY__EDGE_THRESHOLD (1.0/6.0) + #define FXAA_QUALITY__EDGE_THRESHOLD_MIN (1.0/12.0) + +(2.) +Then include this file, + + #include "Fxaa3.h" + +(3.) +Then call the FXAA pixel shader from within your desired shader, + + return FxaaPixelShader(pos, posPos, tex, rcpFrame, rcpFrameOpt); + +(4.) +Insure pass prior to FXAA outputs RGBL. +See next section. + +(5.) +Setup engine to provide "rcpFrame" and "rcpFrameOpt" constants. +Not using constants will result in a performance loss. + + // {x_} = 1.0/screenWidthInPixels + // {_y} = 1.0/screenHeightInPixels + float2 rcpFrame + + // This must be from a constant/uniform. + // {x___} = 2.0/screenWidthInPixels + // {_y__} = 2.0/screenHeightInPixels + // {__z_} = 0.5/screenWidthInPixels + // {___w} = 0.5/screenHeightInPixels + float4 rcpFrameOpt + +(5.a.) +Optionally change to this for sharper FXAA Console, + + // This must be from a constant/uniform. + // {x___} = 2.0/screenWidthInPixels + // {_y__} = 2.0/screenHeightInPixels + // {__z_} = 0.333/screenWidthInPixels + // {___w} = 0.333/screenHeightInPixels + float4 rcpFrameOpt + +(6.) +Have FXAA vertex shader run as a full screen triangle, +and output "pos" and "posPos" such that inputs in the pixel shader provide, + + // {xy} = center of pixel + float2 pos, + + // {xy__} = upper left of pixel + // {__zw} = lower right of pixel + float4 posPos, + +(7.) +Insure the texture sampler used by FXAA is set to bilinear filtering. + + +------------------------------------------------------------------------------ + INTEGRATION - RGBL AND COLORSPACE +------------------------------------------------------------------------------ +FXAA3 requires RGBL as input. + +RGB should be LDR (low dynamic range). +Specifically do FXAA after tonemapping. + +RGB data as returned by a texture fetch can be linear or non-linear. +Note an "sRGB format" texture counts as linear, +because the result of a texture fetch is linear data. +Regular "RGBA8" textures in the sRGB colorspace are non-linear. + +Luma must be stored in the alpha channel prior to running FXAA. +This luma should be in a perceptual space (could be gamma 2.0). +Example pass before FXAA where output is gamma 2.0 encoded, + + color.rgb = ToneMap(color.rgb); // linear color output + color.rgb = sqrt(color.rgb); // gamma 2.0 color output + return color; + +To use FXAA, + + color.rgb = ToneMap(color.rgb); // linear color output + color.rgb = sqrt(color.rgb); // gamma 2.0 color output + color.a = dot(color.rgb, float3(0.299, 0.587, 0.114)); // compute luma + return color; + +Another example where output is linear encoded, +say for instance writing to an sRGB formated render target, +where the render target does the conversion back to sRGB after blending, + + color.rgb = ToneMap(color.rgb); // linear color output + return color; + +To use FXAA, + + color.rgb = ToneMap(color.rgb); // linear color output + color.a = sqrt(dot(color.rgb, float3(0.299, 0.587, 0.114))); // compute luma + return color; + +Getting luma correct is required for the algorithm to work correctly. + + +------------------------------------------------------------------------------ + BEING LINEARLY CORRECT? +------------------------------------------------------------------------------ +Applying FXAA to a framebuffer with linear RGB color will look worse. +This is very counter intuitive, but happends to be true in this case. +The reason is because dithering artifacts will be more visiable +in a linear colorspace. + + +------------------------------------------------------------------------------ + COMPLEX INTEGRATION +------------------------------------------------------------------------------ +Q. What if the engine is blending into RGB before wanting to run FXAA? + +A. In the last opaque pass prior to FXAA, + have the pass write out luma into alpha. + Then blend into RGB only. + FXAA should be able to run ok + assuming the blending pass did not any add aliasing. + This should be the common case for particles and common blending passes. + +============================================================================*/ + +/*============================================================================ + + INTEGRATION KNOBS + +============================================================================*/ +// +// FXAA_PS3 and FXAA_360 choose the console algorithm (FXAA3 CONSOLE). +// FXAA_360_OPT is a prototype for the new optimized 360 version. +// +// 1 = Use API. +// 0 = Don't use API. +// +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_PS3 + #define FXAA_PS3 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_360 + #define FXAA_360 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_360_OPT + #define FXAA_360_OPT 0 +#endif +/*==========================================================================*/ +#ifndef FXAA_PC + // + // FXAA Quality + // The high quality PC algorithm. + // + #define FXAA_PC 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_PC_CONSOLE + // + // The console algorithm for PC is included + // for developers targeting really low spec machines. + // + #define FXAA_PC_CONSOLE 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GLSL_120 + #define FXAA_GLSL_120 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GLSL_130 + #define FXAA_GLSL_130 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_3 + #define FXAA_HLSL_3 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_4 + #define FXAA_HLSL_4 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_5 + #define FXAA_HLSL_5 0 +#endif +/*==========================================================================*/ +#ifndef FXAA_EARLY_EXIT + // + // Controls algorithm's early exit path. + // On PS3 turning this on adds 2 cycles to the shader. + // On 360 turning this off adds 10ths of a millisecond to the shader. + // Turning this off on console will result in a more blurry image. + // So this defaults to on. + // + // 1 = On. + // 0 = Off. + // + #define FXAA_EARLY_EXIT 1 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_DISCARD + // + // Only valid for PC OpenGL currently. + // + // 1 = Use discard on pixels which don't need AA. + // For APIs which enable concurrent TEX+ROP from same surface. + // 0 = Return unchanged color on pixels which don't need AA. + // + #define FXAA_DISCARD 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_FAST_PIXEL_OFFSET + // + // Used for GLSL 120 only. + // + // 1 = GL API supports fast pixel offsets + // 0 = do not use fast pixel offsets + // + #ifdef GL_EXT_gpu_shader4 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifdef GL_NV_gpu_shader5 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifdef GL_ARB_gpu_shader5 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifndef FXAA_FAST_PIXEL_OFFSET + #define FXAA_FAST_PIXEL_OFFSET 0 + #endif +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GATHER4_ALPHA + // + // 1 = API supports gather4 on alpha channel. + // 0 = API does not support gather4 on alpha channel. + // + #if (FXAA_HLSL_5 == 1) + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifdef GL_ARB_gpu_shader5 + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifdef GL_NV_gpu_shader5 + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifndef FXAA_GATHER4_ALPHA + #define FXAA_GATHER4_ALPHA 0 + #endif +#endif + +/*============================================================================ + FXAA CONSOLE - TUNING KNOBS +============================================================================*/ +#ifndef FXAA_CONSOLE__EDGE_SHARPNESS + // + // Consoles the sharpness of edges. + // + // Due to the PS3 being ALU bound, + // there are only two safe values here: 4 and 8. + // These options use the shaders ability to a free *|/ by 4|8. + // + // 8.0 is sharper + // 4.0 is softer + // 2.0 is really soft (good for vector graphics inputs) + // + #if 1 + #define FXAA_CONSOLE__EDGE_SHARPNESS 8.0 + #endif + #if 0 + #define FXAA_CONSOLE__EDGE_SHARPNESS 4.0 + #endif + #if 0 + #define FXAA_CONSOLE__EDGE_SHARPNESS 2.0 + #endif +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_CONSOLE__EDGE_THRESHOLD + // + // The minimum amount of local contrast required to apply algorithm. + // The console setting has a different mapping than the quality setting. + // + // This only applies when FXAA_EARLY_EXIT is 1. + // + // Due to the PS3 being ALU bound, + // there are only two safe values here: 0.25 and 0.125. + // These options use the shaders ability to a free *|/ by 4|8. + // + // 0.125 leaves less aliasing, but is softer + // 0.25 leaves more aliasing, and is sharper + // + #if 1 + #define FXAA_CONSOLE__EDGE_THRESHOLD 0.125 + #else + #define FXAA_CONSOLE__EDGE_THRESHOLD 0.25 + #endif +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_CONSOLE__EDGE_THRESHOLD_MIN + // + // Trims the algorithm from processing darks. + // The console setting has a different mapping than the quality setting. + // + // This only applies when FXAA_EARLY_EXIT is 1. + // + // This does not apply to PS3. + // PS3 was simplified to avoid more shader instructions. + // + #define FXAA_CONSOLE__EDGE_THRESHOLD_MIN 0.05 +#endif + +/*============================================================================ + FXAA QUALITY - TUNING KNOBS +============================================================================*/ +#ifndef FXAA_QUALITY__EDGE_THRESHOLD + // + // The minimum amount of local contrast required to apply algorithm. + // + // 1/3 - too little + // 1/4 - low quality + // 1/6 - default + // 1/8 - high quality (default) + // 1/16 - overkill + // + #define FXAA_QUALITY__EDGE_THRESHOLD (1.0/6.0) +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_QUALITY__EDGE_THRESHOLD_MIN + // + // Trims the algorithm from processing darks. + // + // 1/32 - visible limit + // 1/16 - high quality + // 1/12 - upper limit (default, the start of visible unfiltered edges) + // + #define FXAA_QUALITY__EDGE_THRESHOLD_MIN (1.0/12.0) +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_QUALITY__SUBPIX + // + // Choose the amount of sub-pixel aliasing removal. + // + // 1 - upper limit (softer) + // 3/4 - default amount of filtering + // 1/2 - lower limit (sharper, less sub-pixel aliasing removal) + // + #define FXAA_QUALITY__SUBPIX (3.0/4.0) +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_QUALITY__PRESET + // + // Choose the quality preset. + // + // OPTIONS + // ----------------------------------------------------------------------- + // 10 to 15 - default medium dither (10=fastest, 15=highest quality) + // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality) + // 39 - no dither, very expensive + // + // NOTES + // ----------------------------------------------------------------------- + // 12 = slightly faster then FXAA 3.9 and higher edge quality (default) + // 13 = about same speed as FXAA 3.9 and better than 12 + // 23 = closest to FXAA 3.9 visually and performance wise + // _ = the lowest digit is directly related to performance + // _ = the highest digit is directly related to style + // + #define FXAA_QUALITY__PRESET 12 +#endif + + +/*============================================================================ + + FXAA QUALITY - PRESETS + +============================================================================*/ + +/*============================================================================ + FXAA QUALITY - MEDIUM DITHER PRESETS +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 10) + #define FXAA_QUALITY__PS 3 + #define FXAA_QUALITY__P0 1.5 + #define FXAA_QUALITY__P1 3.0 + #define FXAA_QUALITY__P2 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 11) + #define FXAA_QUALITY__PS 4 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 3.0 + #define FXAA_QUALITY__P3 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 12) + #define FXAA_QUALITY__PS 5 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 4.0 + #define FXAA_QUALITY__P4 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 13) + #define FXAA_QUALITY__PS 6 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 4.0 + #define FXAA_QUALITY__P5 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 14) + #define FXAA_QUALITY__PS 7 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 4.0 + #define FXAA_QUALITY__P6 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 15) + #define FXAA_QUALITY__PS 8 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 4.0 + #define FXAA_QUALITY__P7 12.0 +#endif + +/*============================================================================ + FXAA QUALITY - LOW DITHER PRESETS +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 20) + #define FXAA_QUALITY__PS 3 + #define FXAA_QUALITY__P0 1.5 + #define FXAA_QUALITY__P1 2.0 + #define FXAA_QUALITY__P2 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 21) + #define FXAA_QUALITY__PS 4 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 22) + #define FXAA_QUALITY__PS 5 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 23) + #define FXAA_QUALITY__PS 6 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 24) + #define FXAA_QUALITY__PS 7 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 3.0 + #define FXAA_QUALITY__P6 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 25) + #define FXAA_QUALITY__PS 8 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 4.0 + #define FXAA_QUALITY__P7 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 26) + #define FXAA_QUALITY__PS 9 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 4.0 + #define FXAA_QUALITY__P8 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 27) + #define FXAA_QUALITY__PS 10 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 4.0 + #define FXAA_QUALITY__P9 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 28) + #define FXAA_QUALITY__PS 11 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 2.0 + #define FXAA_QUALITY__P9 4.0 + #define FXAA_QUALITY__P10 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 29) + #define FXAA_QUALITY__PS 12 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 2.0 + #define FXAA_QUALITY__P9 2.0 + #define FXAA_QUALITY__P10 4.0 + #define FXAA_QUALITY__P11 8.0 +#endif + +/*============================================================================ + FXAA QUALITY - EXTREME QUALITY +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 39) + #define FXAA_QUALITY__PS 12 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.0 + #define FXAA_QUALITY__P2 1.0 + #define FXAA_QUALITY__P3 1.0 + #define FXAA_QUALITY__P4 1.0 + #define FXAA_QUALITY__P5 1.5 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 2.0 + #define FXAA_QUALITY__P9 2.0 + #define FXAA_QUALITY__P10 4.0 + #define FXAA_QUALITY__P11 8.0 +#endif + + + +/*============================================================================ + + API PORTING + +============================================================================*/ +#if FXAA_GLSL_120 + // Requires, + // #version 120 + // And at least, + // #extension GL_EXT_gpu_shader4 : enable + // (or set FXAA_FAST_PIXEL_OFFSET 1 to work like DX9) + #define half float + #define half2 vec2 + #define half3 vec3 + #define half4 vec4 + #define int2 ivec2 + #define float2 vec2 + #define float3 vec3 + #define float4 vec4 + #define FxaaInt2 ivec2 + #define FxaaFloat2 vec2 + #define FxaaFloat3 vec3 + #define FxaaFloat4 vec4 + #define FxaaDiscard discard + #define FxaaDot3(a, b) dot(a, b) + #define FxaaSat(x) clamp(x, 0.0, 1.0) + #define FxaaLerp(x,y,s) mix(x,y,s) + #define FxaaTex sampler2D + #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0) + #if (FXAA_FAST_PIXEL_OFFSET == 1) + #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o) + #else + #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0) + #endif + #if (FXAA_GATHER4_ALPHA == 1) + // use #extension GL_ARB_gpu_shader5 : enable + #define FxaaTexAlpha4(t, p, r) textureGather(t, p, 3) + #define FxaaTexOffAlpha4(t, p, o, r) textureGatherOffset(t, p, o, 3) + #endif +#endif +/*--------------------------------------------------------------------------*/ +#if FXAA_GLSL_130 + // Requires "#version 130" or better + #define half float + #define half2 vec2 + #define half3 vec3 + #define half4 vec4 + #define int2 ivec2 + #define float2 vec2 + #define float3 vec3 + #define float4 vec4 + #define FxaaInt2 ivec2 + #define FxaaFloat2 vec2 + #define FxaaFloat3 vec3 + #define FxaaFloat4 vec4 + #define FxaaDiscard discard + #define FxaaDot3(a, b) dot(a, b) + #define FxaaSat(x) clamp(x, 0.0, 1.0) + #define FxaaLerp(x,y,s) mix(x,y,s) + #define FxaaTex sampler2D + #define FxaaTexTop(t, p) textureLod(t, p, 0.0) + #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o) + #if (FXAA_GATHER4_ALPHA == 1) + // use #extension GL_ARB_gpu_shader5 : enable + #define FxaaTexAlpha4(t, p, r) textureGather(t, p, 3) + #define FxaaTexOffAlpha4(t, p, o, r) textureGatherOffset(t, p, o, 3) + #endif +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_3 == 1) || (FXAA_360 == 1) + #define int2 float2 + #define FxaaInt2 float2 + #define FxaaFloat2 float2 + #define FxaaFloat3 float3 + #define FxaaFloat4 float4 + #define FxaaDiscard clip(-1) + #define FxaaDot3(a, b) dot(a, b) + #define FxaaSat(x) saturate(x) + #define FxaaLerp(x,y,s) lerp(x,y,s) + #define FxaaTex sampler2D + #define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0)) + #define FxaaTexOff(t, p, o, r) tex2Dlod(t, float4(p + (o * r), 0, 0)) +#endif +/*--------------------------------------------------------------------------*/ +#if FXAA_HLSL_4 + #define FxaaInt2 int2 + #define FxaaFloat2 float2 + #define FxaaFloat3 float3 + #define FxaaFloat4 float4 + #define FxaaDiscard clip(-1) + #define FxaaDot3(a, b) dot(a, b) + #define FxaaSat(x) saturate(x) + #define FxaaLerp(x,y,s) lerp(x,y,s) + struct FxaaTex { SamplerState smpl; Texture2D tex; }; + #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) + #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) +#endif +/*--------------------------------------------------------------------------*/ +#if FXAA_HLSL_5 + #define FxaaInt2 int2 + #define FxaaFloat2 float2 + #define FxaaFloat3 float3 + #define FxaaFloat4 float4 + #define FxaaDiscard clip(-1) + #define FxaaDot3(a, b) dot(a, b) + #define FxaaSat(x) saturate(x) + #define FxaaLerp(x,y,s) lerp(x,y,s) + struct FxaaTex { SamplerState smpl; Texture2D tex; }; + #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) + #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) + #define FxaaTexAlpha4(t, p, r) t.tex.GatherAlpha(t.smpl, p) + #define FxaaTexOffAlpha4(t, p, o, r) t.tex.GatherAlpha(t.smpl, p, o) +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - 360 PIXEL SHADER + +------------------------------------------------------------------------------ +Might be some optimizations left here, +as of this latest change didn't have a PIX dump to verify if TEX bound. +============================================================================*/ +#if (FXAA_360 == 1) +/*--------------------------------------------------------------------------*/ +half4 FxaaPixelShader( + // {xy} = center of pixel + float2 pos, + // {xy__} = upper left of pixel + // {__zw} = lower right of pixel + float4 posPos, + // {rgb_} = color in linear or perceptual color space + // {___a} = alpha output is junk value + FxaaTex tex, + // This must be from a constant/uniform. + // {xy} = rcpFrame not used on PC version of FXAA Console + float2 rcpFrame, + // This must be from a constant/uniform. + // {x___} = 2.0/screenWidthInPixels + // {_y__} = 2.0/screenHeightInPixels + // {__z_} = 0.5/screenWidthInPixels + // {___w} = 0.5/screenHeightInPixels + float4 rcpFrameOpt +) { +/*--------------------------------------------------------------------------*/ + half4 lumaNwNeSwSe; + lumaNwNeSwSe.x = FxaaTexTop(tex, posPos.xy).w; + lumaNwNeSwSe.y = FxaaTexTop(tex, posPos.zy).w; + lumaNwNeSwSe.z = FxaaTexTop(tex, posPos.xw).w; + lumaNwNeSwSe.w = FxaaTexTop(tex, posPos.zw).w; +/*--------------------------------------------------------------------------*/ + half4 rgbyM = FxaaTexTop(tex, pos.xy); +/*--------------------------------------------------------------------------*/ + lumaNwNeSwSe.y += 1.0/384.0; +/*--------------------------------------------------------------------------*/ + half2 lumaMinTemp = min(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); + half2 lumaMaxTemp = max(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); +/*--------------------------------------------------------------------------*/ + half lumaMin = min(lumaMinTemp.x, lumaMinTemp.y); + half lumaMax = max(lumaMaxTemp.x, lumaMaxTemp.y); +/*--------------------------------------------------------------------------*/ + half lumaMinM = min(lumaMin, rgbyM.w); + half lumaMaxM = max(lumaMax, rgbyM.w); + if((lumaMaxM - lumaMinM) < max(FXAA_CONSOLE__EDGE_THRESHOLD_MIN, lumaMax * FXAA_CONSOLE__EDGE_THRESHOLD)) return rgbyM; +/*--------------------------------------------------------------------------*/ + half2 dir; + dir.x = dot(lumaNwNeSwSe, float4(-1.0, -1.0, 1.0, 1.0)); + dir.y = dot(lumaNwNeSwSe, float4( 1.0, -1.0, 1.0,-1.0)); +/*--------------------------------------------------------------------------*/ + half2 dir1; + dir1 = normalize(dir.xy); +/*--------------------------------------------------------------------------*/ + half dirAbsMinTimesC = min(abs(dir1.x), abs(dir1.y)) * FXAA_CONSOLE__EDGE_SHARPNESS; + half2 dir2; + dir2 = clamp(dir1.xy / dirAbsMinTimesC, -2.0, 2.0); +/*--------------------------------------------------------------------------*/ + half4 rgbyN1 = FxaaTexTop(tex, pos.xy - dir1 * rcpFrameOpt.zw); + half4 rgbyP1 = FxaaTexTop(tex, pos.xy + dir1 * rcpFrameOpt.zw); + half4 rgbyN2 = FxaaTexTop(tex, pos.xy - dir2 * rcpFrameOpt.xy); + half4 rgbyP2 = FxaaTexTop(tex, pos.xy + dir2 * rcpFrameOpt.xy); +/*--------------------------------------------------------------------------*/ + half4 rgbyA = rgbyN1 * 0.5 + rgbyP1 * 0.5; + half4 rgbyB = rgbyN2 * 0.25 + rgbyP2 * 0.25 + rgbyA * 0.5; +/*--------------------------------------------------------------------------*/ + bool twoTap = (rgbyB.w < lumaMin) || (rgbyB.w > lumaMax); + if(twoTap) rgbyB.xyz = rgbyA.xyz; + return rgbyB; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - 360 PIXEL SHADER OPTIMIZED PROTOTYPE + +------------------------------------------------------------------------------ +This prototype optimized version thanks to suggestions from Andy Luedke. +Should be fully tex bound in all cases. +As of the FXAA 3.10 release I have not tested this code, +but at least the missing ";" was fixed. +If it does not work, please let me know so I can fix it. +------------------------------------------------------------------------------ +Extra requirements, +(1.) Different inputs: no posPos. +(2.) Different inputs: alias three samplers with different exp bias settings! +(3.) New constants: setup fxaaConst as described below. +============================================================================*/ +#if (FXAA_360_OPT == 1) +/*--------------------------------------------------------------------------*/ +[reduceTempRegUsage(4)] +float4 FxaaPixelShader( + // {xy} = center of pixel + float2 pos, + // Three samplers, + // texExpBias0 = exponent bias 0 + // texExpBiasNeg1 = exponent bias -1 + // texExpBiasNeg2 = exponent bias -2 + // {rgb_} = color in linear or perceptual color space + // {___a} = alpha output is junk value + uniform sampler2D texExpBias0, + uniform sampler2D texExpBiasNeg1, + uniform sampler2D texExpBiasNeg2, + // These must be in physical constant registers and NOT immedates + // Immedates will result in compiler un-optimizing + // width = screen width in pixels + // height = screen height in pixels + fxaaConstDir, // float4(1.0, -1.0, 0.25, -0.25); + fxaaConstInner, // float4(0.5/width, 0.5/height, -0.5/width, -0.5/height); + fxaaConstOuter // float4(8.0/width, 8.0/height, -4.0/width, -4.0/height); +) { +/*--------------------------------------------------------------------------*/ + float4 lumaNwNeSwSe; + asm { + tfetch2D lumaNwNeSwSe.w___, texExpBias0, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe._w__, texExpBias0, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.__w_, texExpBias0, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.___w, texExpBias0, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false + }; +/*--------------------------------------------------------------------------*/ + lumaNwNeSwSe.y += 1.0/384.0; + float2 lumaMinTemp = min(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); + float2 lumaMaxTemp = max(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); + float lumaMin = min(lumaMinTemp.x, lumaMinTemp.y); + float lumaMax = max(lumaMaxTemp.x, lumaMaxTemp.y); +/*--------------------------------------------------------------------------*/ + float4 rgbyM = tex2Dlod(texExpBias0, float4(pos.xy, 0.0, 0.0)); + float4 lumaMinM = min(lumaMin, rgbyM.w); + float4 lumaMaxM = max(lumaMax, rgbyM.w); + if((lumaMaxM - lumaMinM) < max(FXAA_CONSOLE__EDGE_THRESHOLD_MIN, lumaMax * FXAA_CONSOLE__EDGE_THRESHOLD)) return rgbyM; +/*--------------------------------------------------------------------------*/ + float2 dir; + dir.x = dot(lumaNwNeSwSe, fxaaConstDir.yyxx); + dir.y = dot(lumaNwNeSwSe, fxaaConstDir.xyxy); + dir = normalize(dir); +/*--------------------------------------------------------------------------*/ + float4 dir1 = dir.xyxy * fxaaConstInner.xyzw; +/*--------------------------------------------------------------------------*/ + float4 dir2; + float dirAbsMinTimesC = min(abs(dir.x), abs(dir.y)); + dir2 = saturate(fxaaConstOuter.zzww * dir.xyxy / FXAA_CONSOLE__EDGE_SHARPNESS / dirAbsMinTimesC + 0.5); + dir2 = dir2 * fxaaConstOuter.xyxy + fxaaConstOuter.zwzw; +/*--------------------------------------------------------------------------*/ + float4 rgbyN1 = tex2Dlod(texExpBiasNeg1, float4(pos.xy + dir1.xy, 0.0, 0.0)); + float4 rgbyP1 = tex2Dlod(texExpBiasNeg1, float4(pos.xy + dir1.zw, 0.0, 0.0)); + float4 rgbyN2 = tex2Dlod(texExpBiasNeg2, float4(pos.xy + dir2.xy, 0.0, 0.0)); + float4 rgbyP2 = tex2Dlod(texExpBiasNeg2, float4(pos.xy + dir2.zw, 0.0, 0.0)); +/*--------------------------------------------------------------------------*/ + half4 rgbyA = rgbyN1 + rgbyP1; + half4 rgbyB = rgbyN2 + rgbyP2 * 0.5 + rgbyA; +/*--------------------------------------------------------------------------*/ + float4 rgbyR = ((rgbyB.w - lumaMax) > 0.0) ? rgbyA : rgbyB; + rgbyR = ((rgbyB.w - lumaMin) > 0.0) ? rgbyR : rgbyA; + return rgbyR; } +/*==========================================================================*/ +#endif + + + + +/*============================================================================ + + FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (NO EARLY EXIT) + +============================================================================== +The code below does not exactly match the assembly. +I have a feeling that 12 cycles is possible, but was not able to get there. +Might have to increase register count to get full performance. +Note this shader does not use perspective interpolation. + +Use the following cgc options, + + --fenable-bx2 --fastmath --fastprecision --nofloatbindings + +------------------------------------------------------------------------------ + NVSHADERPERF OUTPUT +------------------------------------------------------------------------------ +For reference and to aid in debug, output of NVShaderPerf should match this, + +Shader to schedule: + 0: texpkb h0.w(TRUE), v5.zyxx, #0 + 2: addh h2.z(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x + 4: texpkb h0.w(TRUE), v5.xwxx, #0 + 6: addh h0.z(TRUE), -h2, h0.w + 7: texpkb h1.w(TRUE), v5, #0 + 9: addh h0.x(TRUE), h0.z, -h1.w + 10: addh h3.w(TRUE), h0.z, h1 + 11: texpkb h2.w(TRUE), v5.zwzz, #0 + 13: addh h0.z(TRUE), h3.w, -h2.w + 14: addh h0.x(TRUE), h2.w, h0 + 15: nrmh h1.xz(TRUE), h0_n + 16: minh_m8 h0.x(TRUE), |h1|, |h1.z| + 17: maxh h4.w(TRUE), h0, h1 + 18: divx h2.xy(TRUE), h1_n.xzzw, h0_n + 19: movr r1.zw(TRUE), v4.xxxy + 20: madr r2.xz(TRUE), -h1, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zzww, r1.zzww + 22: minh h5.w(TRUE), h0, h1 + 23: texpkb h0(TRUE), r2.xzxx, #0 + 25: madr r0.zw(TRUE), h1.xzxz, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w), r1 + 27: maxh h4.x(TRUE), h2.z, h2.w + 28: texpkb h1(TRUE), r0.zwzz, #0 + 30: addh_d2 h1(TRUE), h0, h1 + 31: madr r0.xy(TRUE), -h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 33: texpkb h0(TRUE), r0, #0 + 35: minh h4.z(TRUE), h2, h2.w + 36: fenct TRUE + 37: madr r1.xy(TRUE), h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 39: texpkb h2(TRUE), r1, #0 + 41: addh_d2 h0(TRUE), h0, h2 + 42: maxh h2.w(TRUE), h4, h4.x + 43: minh h2.x(TRUE), h5.w, h4.z + 44: addh_d2 h0(TRUE), h0, h1 + 45: slth h2.x(TRUE), h0.w, h2 + 46: sgth h2.w(TRUE), h0, h2 + 47: movh h0(TRUE), h0 + 48: addx.c0 rc(TRUE), h2, h2.w + 49: movh h0(c0.NE.x), h1 + +IPU0 ------ Simplified schedule: -------- +Pass | Unit | uOp | PC: Op +-----+--------+------+------------------------- + 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | SCB1 | add | 2: ADDh h2.z, h0.--w-, const.--x-; + | | | + 2 | SCT0/1 | mov | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; + | TEX | txl | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; + | SCB1 | add | 6: ADDh h0.z,-h2, h0.--w-; + | | | + 3 | SCT0/1 | mov | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; + | TEX | txl | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; + | SCB0 | add | 9: ADDh h0.x, h0.z---,-h1.w---; + | SCB1 | add | 10: ADDh h3.w, h0.---z, h1; + | | | + 4 | SCT0/1 | mov | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | TEX | txl | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | SCB0 | add | 14: ADDh h0.x, h2.w---, h0; + | SCB1 | add | 13: ADDh h0.z, h3.--w-,-h2.--w-; + | | | + 5 | SCT1 | mov | 15: NRMh h1.xz, h0; + | SRB | nrm | 15: NRMh h1.xz, h0; + | SCB0 | min | 16: MINh*8 h0.x, |h1|, |h1.z---|; + | SCB1 | max | 17: MAXh h4.w, h0, h1; + | | | + 6 | SCT0 | div | 18: DIVx h2.xy, h1.xz--, h0; + | SCT1 | mov | 19: MOVr r1.zw, g[TEX0].--xy; + | SCB0 | mad | 20: MADr r2.xz,-h1, const.z-w-, r1.z-w-; + | SCB1 | min | 22: MINh h5.w, h0, h1; + | | | + 7 | SCT0/1 | mov | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; + | TEX | txl | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; + | SCB0 | max | 27: MAXh h4.x, h2.z---, h2.w---; + | SCB1 | mad | 25: MADr r0.zw, h1.--xz, const, r1; + | | | + 8 | SCT0/1 | mov | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; + | TEX | txl | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; + | SCB0/1 | add | 30: ADDh/2 h1, h0, h1; + | | | + 9 | SCT0 | mad | 31: MADr r0.xy,-h2, const.xy--, r1.zw--; + | SCT1 | mov | 33: TXLr h0, r0, const.zzzz, TEX0; + | TEX | txl | 33: TXLr h0, r0, const.zzzz, TEX0; + | SCB1 | min | 35: MINh h4.z, h2, h2.--w-; + | | | + 10 | SCT0 | mad | 37: MADr r1.xy, h2, const.xy--, r1.zw--; + | SCT1 | mov | 39: TXLr h2, r1, const.zzzz, TEX0; + | TEX | txl | 39: TXLr h2, r1, const.zzzz, TEX0; + | SCB0/1 | add | 41: ADDh/2 h0, h0, h2; + | | | + 11 | SCT0 | min | 43: MINh h2.x, h5.w---, h4.z---; + | SCT1 | max | 42: MAXh h2.w, h4, h4.---x; + | SCB0/1 | add | 44: ADDh/2 h0, h0, h1; + | | | + 12 | SCT0 | set | 45: SLTh h2.x, h0.w---, h2; + | SCT1 | set | 46: SGTh h2.w, h0, h2; + | SCB0/1 | mul | 47: MOVh h0, h0; + | | | + 13 | SCT0 | mad | 48: ADDxc0_s rc, h2, h2.w---; + | SCB0/1 | mul | 49: MOVh h0(NE0.xxxx), h1; + +Pass SCT TEX SCB + 1: 0% 100% 25% + 2: 0% 100% 25% + 3: 0% 100% 50% + 4: 0% 100% 50% + 5: 0% 0% 50% + 6: 100% 0% 75% + 7: 0% 100% 75% + 8: 0% 100% 100% + 9: 0% 100% 25% + 10: 0% 100% 100% + 11: 50% 0% 100% + 12: 50% 0% 100% + 13: 25% 0% 100% + +MEAN: 17% 61% 67% + +Pass SCT0 SCT1 TEX SCB0 SCB1 + 1: 0% 0% 100% 0% 100% + 2: 0% 0% 100% 0% 100% + 3: 0% 0% 100% 100% 100% + 4: 0% 0% 100% 100% 100% + 5: 0% 0% 0% 100% 100% + 6: 100% 100% 0% 100% 100% + 7: 0% 0% 100% 100% 100% + 8: 0% 0% 100% 100% 100% + 9: 0% 0% 100% 0% 100% + 10: 0% 0% 100% 100% 100% + 11: 100% 100% 0% 100% 100% + 12: 100% 100% 0% 100% 100% + 13: 100% 0% 0% 100% 100% + +MEAN: 30% 23% 61% 76% 100% +Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 +Results 13 cycles, 3 r regs, 923,076,923 pixels/s +============================================================================*/ +#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 0) +/*--------------------------------------------------------------------------*/ +#pragma disablepc all +#pragma option O3 +#pragma option OutColorPrec=fp16 +#pragma texformat default RGBA8 +/*==========================================================================*/ +half4 FxaaPixelShader( + // {xy} = center of pixel + float2 pos, + // {xy__} = upper left of pixel + // {__zw} = lower right of pixel + float4 posPos, + // {rgb_} = color in linear or perceptual color space + // {___a} = luma in perceptual color space (not linear) + sampler2D tex, + // This must be from a constant/uniform. + // {xy} = rcpFrame not used on PS3 + float2 rcpFrame, + // This must be from a constant/uniform. + // {x___} = 2.0/screenWidthInPixels + // {_y__} = 2.0/screenHeightInPixels + // {__z_} = 0.5/screenWidthInPixels + // {___w} = 0.5/screenHeightInPixels + float4 rcpFrameOpt +) { +/*--------------------------------------------------------------------------*/ +// (1) + half4 dir; + half4 lumaNe = h4tex2Dlod(tex, half4(posPos.zy, 0, 0)); + lumaNe.w += half(1.0/512.0); + dir.x = -lumaNe.w; + dir.z = -lumaNe.w; +/*--------------------------------------------------------------------------*/ +// (2) + half4 lumaSw = h4tex2Dlod(tex, half4(posPos.xw, 0, 0)); + dir.x += lumaSw.w; + dir.z += lumaSw.w; +/*--------------------------------------------------------------------------*/ +// (3) + half4 lumaNw = h4tex2Dlod(tex, half4(posPos.xy, 0, 0)); + dir.x -= lumaNw.w; + dir.z += lumaNw.w; +/*--------------------------------------------------------------------------*/ +// (4) + half4 lumaSe = h4tex2Dlod(tex, half4(posPos.zw, 0, 0)); + dir.x += lumaSe.w; + dir.z -= lumaSe.w; +/*--------------------------------------------------------------------------*/ +// (5) + half4 dir1_pos; + dir1_pos.xy = normalize(dir.xyz).xz; + half dirAbsMinTimesC = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__EDGE_SHARPNESS); +/*--------------------------------------------------------------------------*/ +// (6) + half4 dir2_pos; + dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimesC, half(-2.0), half(2.0)); + dir1_pos.zw = pos.xy; + dir2_pos.zw = pos.xy; + half4 temp1N; + temp1N.xy = dir1_pos.zw - dir1_pos.xy * rcpFrameOpt.zw; +/*--------------------------------------------------------------------------*/ +// (7) + temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); + half4 rgby1; + rgby1.xy = dir1_pos.zw + dir1_pos.xy * rcpFrameOpt.zw; +/*--------------------------------------------------------------------------*/ +// (8) + rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); + rgby1 = (temp1N + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (9) + half4 temp2N; + temp2N.xy = dir2_pos.zw - dir2_pos.xy * rcpFrameOpt.xy; + temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); +/*--------------------------------------------------------------------------*/ +// (10) + half4 rgby2; + rgby2.xy = dir2_pos.zw + dir2_pos.xy * rcpFrameOpt.xy; + rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); + rgby2 = (temp2N + rgby2) * 0.5; +/*--------------------------------------------------------------------------*/ +// (11) + // compilier moves these scalar ops up to other cycles + half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w)); + half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w)); + rgby2 = (rgby2 + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (12) + bool twoTapLt = rgby2.w < lumaMin; + bool twoTapGt = rgby2.w > lumaMax; +/*--------------------------------------------------------------------------*/ +// (13) + if(twoTapLt || twoTapGt) rgby2 = rgby1; +/*--------------------------------------------------------------------------*/ + return rgby2; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (WITH EARLY EXIT) + +============================================================================== +The code mostly matches the assembly. +I have a feeling that 14 cycles is possible, but was not able to get there. +Might have to increase register count to get full performance. +Note this shader does not use perspective interpolation. + +Use the following cgc options, + + --fenable-bx2 --fastmath --fastprecision --nofloatbindings + +------------------------------------------------------------------------------ + NVSHADERPERF OUTPUT +------------------------------------------------------------------------------ +For reference and to aid in debug, output of NVShaderPerf should match this, + +Shader to schedule: + 0: texpkb h0.w(TRUE), v5.zyxx, #0 + 2: addh h2.y(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x + 4: texpkb h1.w(TRUE), v5.xwxx, #0 + 6: addh h0.x(TRUE), h1.w, -h2.y + 7: texpkb h2.w(TRUE), v5.zwzz, #0 + 9: minh h4.w(TRUE), h2.y, h2 + 10: maxh h5.x(TRUE), h2.y, h2.w + 11: texpkb h0.w(TRUE), v5, #0 + 13: addh h3.w(TRUE), -h0, h0.x + 14: addh h0.x(TRUE), h0.w, h0 + 15: addh h0.z(TRUE), -h2.w, h0.x + 16: addh h0.x(TRUE), h2.w, h3.w + 17: minh h5.y(TRUE), h0.w, h1.w + 18: nrmh h2.xz(TRUE), h0_n + 19: minh_m8 h2.w(TRUE), |h2.x|, |h2.z| + 20: divx h4.xy(TRUE), h2_n.xzzw, h2_n.w + 21: movr r1.zw(TRUE), v4.xxxy + 22: maxh h2.w(TRUE), h0, h1 + 23: fenct TRUE + 24: madr r0.xy(TRUE), -h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz + 26: texpkb h0(TRUE), r0, #0 + 28: maxh h5.x(TRUE), h2.w, h5 + 29: minh h5.w(TRUE), h5.y, h4 + 30: madr r1.xy(TRUE), h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz + 32: texpkb h2(TRUE), r1, #0 + 34: addh_d2 h2(TRUE), h0, h2 + 35: texpkb h1(TRUE), v4, #0 + 37: maxh h5.y(TRUE), h5.x, h1.w + 38: minh h4.w(TRUE), h1, h5 + 39: madr r0.xy(TRUE), -h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 41: texpkb h0(TRUE), r0, #0 + 43: addh_m8 h5.z(TRUE), h5.y, -h4.w + 44: madr r2.xy(TRUE), h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 46: texpkb h3(TRUE), r2, #0 + 48: addh_d2 h0(TRUE), h0, h3 + 49: addh_d2 h3(TRUE), h0, h2 + 50: movh h0(TRUE), h3 + 51: slth h3.x(TRUE), h3.w, h5.w + 52: sgth h3.w(TRUE), h3, h5.x + 53: addx.c0 rc(TRUE), h3.x, h3 + 54: slth.c0 rc(TRUE), h5.z, h5 + 55: movh h0(c0.NE.w), h2 + 56: movh h0(c0.NE.x), h1 + +IPU0 ------ Simplified schedule: -------- +Pass | Unit | uOp | PC: Op +-----+--------+------+------------------------- + 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | SCB0 | add | 2: ADDh h2.y, h0.-w--, const.-x--; + | | | + 2 | SCT0/1 | mov | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; + | TEX | txl | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; + | SCB0 | add | 6: ADDh h0.x, h1.w---,-h2.y---; + | | | + 3 | SCT0/1 | mov | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | TEX | txl | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | SCB0 | max | 10: MAXh h5.x, h2.y---, h2.w---; + | SCB1 | min | 9: MINh h4.w, h2.---y, h2; + | | | + 4 | SCT0/1 | mov | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; + | TEX | txl | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; + | SCB0 | add | 14: ADDh h0.x, h0.w---, h0; + | SCB1 | add | 13: ADDh h3.w,-h0, h0.---x; + | | | + 5 | SCT0 | mad | 16: ADDh h0.x, h2.w---, h3.w---; + | SCT1 | mad | 15: ADDh h0.z,-h2.--w-, h0.--x-; + | SCB0 | min | 17: MINh h5.y, h0.-w--, h1.-w--; + | | | + 6 | SCT1 | mov | 18: NRMh h2.xz, h0; + | SRB | nrm | 18: NRMh h2.xz, h0; + | SCB1 | min | 19: MINh*8 h2.w, |h2.---x|, |h2.---z|; + | | | + 7 | SCT0 | div | 20: DIVx h4.xy, h2.xz--, h2.ww--; + | SCT1 | mov | 21: MOVr r1.zw, g[TEX0].--xy; + | SCB1 | max | 22: MAXh h2.w, h0, h1; + | | | + 8 | SCT0 | mad | 24: MADr r0.xy,-h2.xz--, const.zw--, r1.zw--; + | SCT1 | mov | 26: TXLr h0, r0, const.xxxx, TEX0; + | TEX | txl | 26: TXLr h0, r0, const.xxxx, TEX0; + | SCB0 | max | 28: MAXh h5.x, h2.w---, h5; + | SCB1 | min | 29: MINh h5.w, h5.---y, h4; + | | | + 9 | SCT0 | mad | 30: MADr r1.xy, h2.xz--, const.zw--, r1.zw--; + | SCT1 | mov | 32: TXLr h2, r1, const.xxxx, TEX0; + | TEX | txl | 32: TXLr h2, r1, const.xxxx, TEX0; + | SCB0/1 | add | 34: ADDh/2 h2, h0, h2; + | | | + 10 | SCT0/1 | mov | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; + | TEX | txl | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; + | SCB0 | max | 37: MAXh h5.y, h5.-x--, h1.-w--; + | SCB1 | min | 38: MINh h4.w, h1, h5; + | | | + 11 | SCT0 | mad | 39: MADr r0.xy,-h4, const.xy--, r1.zw--; + | SCT1 | mov | 41: TXLr h0, r0, const.zzzz, TEX0; + | TEX | txl | 41: TXLr h0, r0, const.zzzz, TEX0; + | SCB0 | mad | 44: MADr r2.xy, h4, const.xy--, r1.zw--; + | SCB1 | add | 43: ADDh*8 h5.z, h5.--y-,-h4.--w-; + | | | + 12 | SCT0/1 | mov | 46: TXLr h3, r2, const.xxxx, TEX0; + | TEX | txl | 46: TXLr h3, r2, const.xxxx, TEX0; + | SCB0/1 | add | 48: ADDh/2 h0, h0, h3; + | | | + 13 | SCT0/1 | mad | 49: ADDh/2 h3, h0, h2; + | SCB0/1 | mul | 50: MOVh h0, h3; + | | | + 14 | SCT0 | set | 51: SLTh h3.x, h3.w---, h5.w---; + | SCT1 | set | 52: SGTh h3.w, h3, h5.---x; + | SCB0 | set | 54: SLThc0 rc, h5.z---, h5; + | SCB1 | add | 53: ADDxc0_s rc, h3.---x, h3; + | | | + 15 | SCT0/1 | mul | 55: MOVh h0(NE0.wwww), h2; + | SCB0/1 | mul | 56: MOVh h0(NE0.xxxx), h1; + +Pass SCT TEX SCB + 1: 0% 100% 25% + 2: 0% 100% 25% + 3: 0% 100% 50% + 4: 0% 100% 50% + 5: 50% 0% 25% + 6: 0% 0% 25% + 7: 100% 0% 25% + 8: 0% 100% 50% + 9: 0% 100% 100% + 10: 0% 100% 50% + 11: 0% 100% 75% + 12: 0% 100% 100% + 13: 100% 0% 100% + 14: 50% 0% 50% + 15: 100% 0% 100% + +MEAN: 26% 60% 56% + +Pass SCT0 SCT1 TEX SCB0 SCB1 + 1: 0% 0% 100% 100% 0% + 2: 0% 0% 100% 100% 0% + 3: 0% 0% 100% 100% 100% + 4: 0% 0% 100% 100% 100% + 5: 100% 100% 0% 100% 0% + 6: 0% 0% 0% 0% 100% + 7: 100% 100% 0% 0% 100% + 8: 0% 0% 100% 100% 100% + 9: 0% 0% 100% 100% 100% + 10: 0% 0% 100% 100% 100% + 11: 0% 0% 100% 100% 100% + 12: 0% 0% 100% 100% 100% + 13: 100% 100% 0% 100% 100% + 14: 100% 100% 0% 100% 100% + 15: 100% 100% 0% 100% 100% + +MEAN: 33% 33% 60% 86% 80% +Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 +Results 15 cycles, 3 r regs, 800,000,000 pixels/s +============================================================================*/ +#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 1) +/*--------------------------------------------------------------------------*/ +#pragma disablepc all +#pragma option O2 +#pragma option OutColorPrec=fp16 +#pragma texformat default RGBA8 +/*==========================================================================*/ +half4 FxaaPixelShader( + // {xy} = center of pixel + float2 pos, + // {xy__} = upper left of pixel + // {__zw} = lower right of pixel + float4 posPos, + // {rgb_} = color in linear or perceptual color space + // {___a} = luma in perceptual color space (not linear) + sampler2D tex, + // This must be from a constant/uniform. + // {xy} = rcpFrame not used on PS3 + float2 rcpFrame, + // This must be from a constant/uniform. + // {x___} = 2.0/screenWidthInPixels + // {_y__} = 2.0/screenHeightInPixels + // {__z_} = 0.5/screenWidthInPixels + // {___w} = 0.5/screenHeightInPixels + float4 rcpFrameOpt +) { +/*--------------------------------------------------------------------------*/ +// (1) + half4 rgbyNe = h4tex2Dlod(tex, half4(posPos.zy, 0, 0)); + half lumaNe = rgbyNe.w + half(1.0/512.0); +/*--------------------------------------------------------------------------*/ +// (2) + half4 lumaSw = h4tex2Dlod(tex, half4(posPos.xw, 0, 0)); + half lumaSwNegNe = lumaSw.w - lumaNe; +/*--------------------------------------------------------------------------*/ +// (3) + half4 lumaNw = h4tex2Dlod(tex, half4(posPos.xy, 0, 0)); + half lumaMaxNwSw = max(lumaNw.w, lumaSw.w); + half lumaMinNwSw = min(lumaNw.w, lumaSw.w); +/*--------------------------------------------------------------------------*/ +// (4) + half4 lumaSe = h4tex2Dlod(tex, half4(posPos.zw, 0, 0)); + half dirZ = lumaNw.w + lumaSwNegNe; + half dirX = -lumaNw.w + lumaSwNegNe; +/*--------------------------------------------------------------------------*/ +// (5) + half3 dir; + dir.y = 0.0; + dir.x = lumaSe.w + dirX; + dir.z = -lumaSe.w + dirZ; + half lumaMinNeSe = min(lumaNe, lumaSe.w); +/*--------------------------------------------------------------------------*/ +// (6) + half4 dir1_pos; + dir1_pos.xy = normalize(dir).xz; + half dirAbsMinTimes8 = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__EDGE_SHARPNESS); +/*--------------------------------------------------------------------------*/ +// (7) + half4 dir2_pos; + dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimes8, half(-2.0), half(2.0)); + dir1_pos.zw = pos.xy; + dir2_pos.zw = pos.xy; + half lumaMaxNeSe = max(lumaNe, lumaSe.w); +/*--------------------------------------------------------------------------*/ +// (8) + half4 temp1N; + temp1N.xy = dir1_pos.zw - dir1_pos.xy * rcpFrameOpt.zw; + temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); + half lumaMax = max(lumaMaxNwSw, lumaMaxNeSe); + half lumaMin = min(lumaMinNwSw, lumaMinNeSe); +/*--------------------------------------------------------------------------*/ +// (9) + half4 rgby1; + rgby1.xy = dir1_pos.zw + dir1_pos.xy * rcpFrameOpt.zw; + rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); + rgby1 = (temp1N + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (10) + half4 rgbyM = h4tex2Dlod(tex, half4(pos.xy, 0.0, 0.0)); + half lumaMaxM = max(lumaMax, rgbyM.w); + half lumaMinM = min(lumaMin, rgbyM.w); +/*--------------------------------------------------------------------------*/ +// (11) + half4 temp2N; + temp2N.xy = dir2_pos.zw - dir2_pos.xy * rcpFrameOpt.xy; + temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); + half4 rgby2; + rgby2.xy = dir2_pos.zw + dir2_pos.xy * rcpFrameOpt.xy; + half lumaRangeM = (lumaMaxM - lumaMinM) / FXAA_CONSOLE__EDGE_THRESHOLD; +/*--------------------------------------------------------------------------*/ +// (12) + rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); + rgby2 = (temp2N + rgby2) * 0.5; +/*--------------------------------------------------------------------------*/ +// (13) + rgby2 = (rgby2 + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (14) + bool twoTapLt = rgby2.w < lumaMin; + bool twoTapGt = rgby2.w > lumaMax; + bool earlyExit = lumaRangeM < lumaMax; + bool twoTap = twoTapLt || twoTapGt; +/*--------------------------------------------------------------------------*/ +// (15) + if(twoTap) rgby2 = rgby1; + if(earlyExit) rgby2 = rgbyM; +/*--------------------------------------------------------------------------*/ + return rgby2; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - PC PIXEL SHADER + +------------------------------------------------------------------------------ +Using a modified version of the PS3 version here to best target old hardware. +============================================================================*/ +#if (FXAA_PC_CONSOLE == 1) +/*--------------------------------------------------------------------------*/ +half4 FxaaPixelShader( + // {xy} = center of pixel + float2 pos, + // {xy__} = upper left of pixel + // {__zw} = lower right of pixel + float4 posPos, + // {rgb_} = color in linear or perceptual color space + // {___a} = alpha output is junk value + FxaaTex tex, + // This must be from a constant/uniform. + // {xy} = rcpFrame not used on PC version of FXAA Console + float2 rcpFrame, + // This must be from a constant/uniform. + // {x___} = 2.0/screenWidthInPixels + // {_y__} = 2.0/screenHeightInPixels + // {__z_} = 0.5/screenWidthInPixels + // {___w} = 0.5/screenHeightInPixels + float4 rcpFrameOpt +) { +/*--------------------------------------------------------------------------*/ + half4 dir; + dir.y = 0.0; + half4 lumaNe = FxaaTexTop(tex, posPos.zy); + lumaNe.w += half(1.0/384.0); + dir.x = -lumaNe.w; + dir.z = -lumaNe.w; +/*--------------------------------------------------------------------------*/ + half4 lumaSw = FxaaTexTop(tex, posPos.xw); + dir.x += lumaSw.w; + dir.z += lumaSw.w; +/*--------------------------------------------------------------------------*/ + half4 lumaNw = FxaaTexTop(tex, posPos.xy); + dir.x -= lumaNw.w; + dir.z += lumaNw.w; +/*--------------------------------------------------------------------------*/ + half4 lumaSe = FxaaTexTop(tex, posPos.zw); + dir.x += lumaSe.w; + dir.z -= lumaSe.w; +/*==========================================================================*/ + #if (FXAA_EARLY_EXIT == 1) + half4 rgbyM = FxaaTexTop(tex, pos.xy); +/*--------------------------------------------------------------------------*/ + half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w)); + half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w)); +/*--------------------------------------------------------------------------*/ + half lumaMinM = min(lumaMin, rgbyM.w); + half lumaMaxM = max(lumaMax, rgbyM.w); +/*--------------------------------------------------------------------------*/ + if((lumaMaxM - lumaMinM) < max(FXAA_CONSOLE__EDGE_THRESHOLD_MIN, lumaMax * FXAA_CONSOLE__EDGE_THRESHOLD)) + #if (FXAA_DISCARD == 1) + FxaaDiscard; + #else + return rgbyM; + #endif + #endif +/*==========================================================================*/ + half4 dir1_pos; + dir1_pos.xy = normalize(dir.xyz).xz; + half dirAbsMinTimesC = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__EDGE_SHARPNESS); +/*--------------------------------------------------------------------------*/ + half4 dir2_pos; + dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimesC, half(-2.0), half(2.0)); + dir1_pos.zw = pos.xy; + dir2_pos.zw = pos.xy; + half4 temp1N; + temp1N.xy = dir1_pos.zw - dir1_pos.xy * rcpFrameOpt.zw; +/*--------------------------------------------------------------------------*/ + temp1N = FxaaTexTop(tex, temp1N.xy); + half4 rgby1; + rgby1.xy = dir1_pos.zw + dir1_pos.xy * rcpFrameOpt.zw; +/*--------------------------------------------------------------------------*/ + rgby1 = FxaaTexTop(tex, rgby1.xy); + rgby1 = (temp1N + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ + half4 temp2N; + temp2N.xy = dir2_pos.zw - dir2_pos.xy * rcpFrameOpt.xy; + temp2N = FxaaTexTop(tex, temp2N.xy); +/*--------------------------------------------------------------------------*/ + half4 rgby2; + rgby2.xy = dir2_pos.zw + dir2_pos.xy * rcpFrameOpt.xy; + rgby2 = FxaaTexTop(tex, rgby2.xy); + rgby2 = (temp2N + rgby2) * 0.5; +/*--------------------------------------------------------------------------*/ + #if (FXAA_EARLY_EXIT == 0) + half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w)); + half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w)); + #endif + rgby2 = (rgby2 + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ + bool twoTapLt = rgby2.w < lumaMin; + bool twoTapGt = rgby2.w > lumaMax; +/*--------------------------------------------------------------------------*/ + if(twoTapLt || twoTapGt) rgby2 = rgby1; +/*--------------------------------------------------------------------------*/ + return rgby2; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 QUALITY - PC + +============================================================================*/ +#if (FXAA_PC == 1) +/*--------------------------------------------------------------------------*/ +float4 FxaaPixelShader( + // {xy} = center of pixel + float2 pos, + // {xyzw} = not used on FXAA3 Quality + float4 posPos, + // {rgb_} = color in linear or perceptual color space + // {___a} = luma in perceptual color space (not linear) + FxaaTex tex, + // This must be from a constant/uniform. + // {x_} = 1.0/screenWidthInPixels + // {_y} = 1.0/screenHeightInPixels + float2 rcpFrame, + // {xyzw} = not used on FXAA3 Quality + float4 rcpFrameOpt +) { +/*--------------------------------------------------------------------------*/ + float2 posM; + posM.x = pos.x; + posM.y = pos.y; + #if (FXAA_GATHER4_ALPHA == 1) + #if (FXAA_DISCARD == 0) + float4 rgbyM = FxaaTexTop(tex, posM); + #define lumaM rgbyM.w + #endif + float4 luma4A = FxaaTexAlpha4(tex, posM, rcpFrame.xy); + float4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1), rcpFrame.xy); + #if (FXAA_DISCARD == 1) + #define lumaM luma4A.w + #endif + #define lumaE luma4A.z + #define lumaS luma4A.x + #define lumaSE luma4A.y + #define lumaNW luma4B.w + #define lumaN luma4B.z + #define lumaW luma4B.x + #else + float4 rgbyM = FxaaTexTop(tex, posM); + #define lumaM rgbyM.w + float lumaS = FxaaTexOff(tex, posM, FxaaInt2( 0, 1), rcpFrame.xy).w; + float lumaE = FxaaTexOff(tex, posM, FxaaInt2( 1, 0), rcpFrame.xy).w; + float lumaN = FxaaTexOff(tex, posM, FxaaInt2( 0,-1), rcpFrame.xy).w; + float lumaW = FxaaTexOff(tex, posM, FxaaInt2(-1, 0), rcpFrame.xy).w; + #endif +/*--------------------------------------------------------------------------*/ + float maxSM = max(lumaS, lumaM); + float minSM = min(lumaS, lumaM); + float maxESM = max(lumaE, maxSM); + float minESM = min(lumaE, minSM); + float maxWN = max(lumaN, lumaW); + float minWN = min(lumaN, lumaW); + float rangeMax = max(maxWN, maxESM); + float rangeMin = min(minWN, minESM); + float rangeMaxScaled = rangeMax * FXAA_QUALITY__EDGE_THRESHOLD; + float range = rangeMax - rangeMin; + float rangeMaxClamped = max(FXAA_QUALITY__EDGE_THRESHOLD_MIN, rangeMaxScaled); + bool earlyExit = range < rangeMaxClamped; +/*--------------------------------------------------------------------------*/ + if(earlyExit) + #if (FXAA_DISCARD == 1) + FxaaDiscard; + #else + return rgbyM; + #endif +/*--------------------------------------------------------------------------*/ + #if (FXAA_GATHER4_ALPHA == 0) + float lumaNW = FxaaTexOff(tex, posM, FxaaInt2(-1,-1), rcpFrame.xy).w; + float lumaSE = FxaaTexOff(tex, posM, FxaaInt2( 1, 1), rcpFrame.xy).w; + float lumaNE = FxaaTexOff(tex, posM, FxaaInt2( 1,-1), rcpFrame.xy).w; + float lumaSW = FxaaTexOff(tex, posM, FxaaInt2(-1, 1), rcpFrame.xy).w; + #else + float lumaNE = FxaaTexOff(tex, posM, FxaaInt2(1, -1), rcpFrame.xy).w; + float lumaSW = FxaaTexOff(tex, posM, FxaaInt2(-1, 1), rcpFrame.xy).w; + #endif +/*--------------------------------------------------------------------------*/ + float lumaNS = lumaN + lumaS; + float lumaWE = lumaW + lumaE; + float subpixRcpRange = 1.0/range; + float subpixNSWE = lumaNS + lumaWE; + float edgeHorz1 = (-2.0 * lumaM) + lumaNS; + float edgeVert1 = (-2.0 * lumaM) + lumaWE; +/*--------------------------------------------------------------------------*/ + float lumaNESE = lumaNE + lumaSE; + float lumaNWNE = lumaNW + lumaNE; + float edgeHorz2 = (-2.0 * lumaE) + lumaNESE; + float edgeVert2 = (-2.0 * lumaN) + lumaNWNE; +/*--------------------------------------------------------------------------*/ + float lumaNWSW = lumaNW + lumaSW; + float lumaSWSE = lumaSW + lumaSE; + float edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2); + float edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2); + float edgeHorz3 = (-2.0 * lumaW) + lumaNWSW; + float edgeVert3 = (-2.0 * lumaS) + lumaSWSE; + float edgeHorz = abs(edgeHorz3) + edgeHorz4; + float edgeVert = abs(edgeVert3) + edgeVert4; +/*--------------------------------------------------------------------------*/ + float subpixNWSWNESE = lumaNWSW + lumaNESE; + float lengthSign = rcpFrame.x; + bool horzSpan = edgeHorz >= edgeVert; + float subpixA = subpixNSWE * 2.0 + subpixNWSWNESE; +/*--------------------------------------------------------------------------*/ + if(!horzSpan) lumaN = lumaW; + if(!horzSpan) lumaS = lumaE; + if(horzSpan) lengthSign = rcpFrame.y; + float subpixB = (subpixA * (1.0/12.0)) - lumaM; +/*--------------------------------------------------------------------------*/ + float gradientN = lumaN - lumaM; + float gradientS = lumaS - lumaM; + float lumaNN = lumaN + lumaM; + float lumaSS = lumaS + lumaM; + bool pairN = abs(gradientN) >= abs(gradientS); + float gradient = max(abs(gradientN), abs(gradientS)); + if(pairN) lengthSign = -lengthSign; + float subpixC = FxaaSat(abs(subpixB) * subpixRcpRange); +/*--------------------------------------------------------------------------*/ + float2 posB; + posB.x = posM.x; + posB.y = posM.y; + float2 offNP; + offNP.x = (!horzSpan) ? 0.0 : rcpFrame.x; + offNP.y = ( horzSpan) ? 0.0 : rcpFrame.y; + if(!horzSpan) posB.x += lengthSign * 0.5; + if( horzSpan) posB.y += lengthSign * 0.5; +/*--------------------------------------------------------------------------*/ + float2 posN; + posN.x = posB.x - offNP.x * FXAA_QUALITY__P0; + posN.y = posB.y - offNP.y * FXAA_QUALITY__P0; + float2 posP; + posP.x = posB.x + offNP.x * FXAA_QUALITY__P0; + posP.y = posB.y + offNP.y * FXAA_QUALITY__P0; + float subpixD = ((-2.0)*subpixC) + 3.0; + float lumaEndN = FxaaTexTop(tex, posN).w; + float subpixE = subpixC * subpixC; + float lumaEndP = FxaaTexTop(tex, posP).w; +/*--------------------------------------------------------------------------*/ + if(!pairN) lumaNN = lumaSS; + float gradientScaled = gradient * 1.0/4.0; + float lumaMM = lumaM - lumaNN * 0.5; + float subpixF = subpixD * subpixE; + bool lumaMLTZero = lumaMM < 0.0; +/*--------------------------------------------------------------------------*/ + lumaEndN -= lumaNN * 0.5; + lumaEndP -= lumaNN * 0.5; + bool doneN = abs(lumaEndN) >= gradientScaled; + bool doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1; + bool doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P1; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P1; +/*--------------------------------------------------------------------------*/ + if(doneNP) { + if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; + if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P2; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P2; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 3) + if(doneNP) { + if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; + if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P3; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P3; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 4) + if(doneNP) { + if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; + if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P4; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P4; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 5) + if(doneNP) { + if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; + if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P5; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P5; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 6) + if(doneNP) { + if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; + if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P6; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P6; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 7) + if(doneNP) { + if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; + if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P7; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P7; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 8) + if(doneNP) { + if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; + if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P8; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P8; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 9) + if(doneNP) { + if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; + if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P9; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P9; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P9; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P9; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 10) + if(doneNP) { + if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; + if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P10; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P10; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P10; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P10; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 11) + if(doneNP) { + if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; + if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P11; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P11; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P11; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P11; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 12) + if(doneNP) { + if(!doneN) lumaEndN = FxaaTexTop(tex, posN.xy).w; + if(!doneP) lumaEndP = FxaaTexTop(tex, posP.xy).w; + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P12; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P12; +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } +/*--------------------------------------------------------------------------*/ + float dstN = posM.x - posN.x; + float dstP = posP.x - posM.x; + if(!horzSpan) dstN = posM.y - posN.y; + if(!horzSpan) dstP = posP.y - posM.y; +/*--------------------------------------------------------------------------*/ + bool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero; + float spanLength = (dstP + dstN); + bool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero; + float spanLengthRcp = 1.0/spanLength; +/*--------------------------------------------------------------------------*/ + bool directionN = dstN < dstP; + float dst = min(dstN, dstP); + bool goodSpan = directionN ? goodSpanN : goodSpanP; + float subpixG = subpixF * subpixF; + float pixelOffset = (dst * (-spanLengthRcp)) + 0.5; + float subpixH = subpixG * FXAA_QUALITY__SUBPIX; +/*--------------------------------------------------------------------------*/ + float pixelOffsetGood = goodSpan ? pixelOffset : 0.0; + float pixelOffsetSubpix = max(pixelOffsetGood, subpixH); + if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign; + if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign; + #if (FXAA_DISCARD == 1) + return FxaaTexTop(tex, posM); + #else + return float4(FxaaTexTop(tex, posM).xyz, lumaM); + #endif +} +/*==========================================================================*/ +#endif + +PS_OUTPUT ps_main(PS_INPUT input) +{ + PS_OUTPUT output; + + float2 pos = input.t; + float4 posPos = (float4)0; + + FxaaTex tex; + + #if SHADER_MODEL >= 0x400 + + tex.tex = Texture; + tex.smpl = TextureSampler; + + #else + + tex = Texture; + + #endif + + output.c = FxaaPixelShader(pos, posPos, tex, _rcpFrame.xy, _rcpFrameOpt); + + return output; +} + +#endif diff --git a/plugins/GSdx/res/shadeboost.fx b/plugins/GSdx/res/shadeboost.fx index 929038ade..5f3c2474a 100644 --- a/plugins/GSdx/res/shadeboost.fx +++ b/plugins/GSdx/res/shadeboost.fx @@ -1,76 +1,76 @@ -#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency - -/* -** Contrast, saturation, brightness -** Code of this function is from TGM's shader pack -** http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=21057 -*/ - -// For all settings: 1.0 = 100% 0.5=50% 1.5 = 150% -float4 ContrastSaturationBrightness(float4 color) // Ported to HLSL -{ - const float sat = SB_SATURATION / 50.0; - const float brt = SB_BRIGHTNESS / 50.0; - const float con = SB_CONTRAST / 50.0; - - // Increase or decrease theese values to adjust r, g and b color channels seperately - const float AvgLumR = 0.5; - const float AvgLumG = 0.5; - const float AvgLumB = 0.5; - - const float3 LumCoeff = float3(0.2125, 0.7154, 0.0721); - - float3 AvgLumin = float3(AvgLumR, AvgLumG, AvgLumB); - float3 brtColor = color.rgb * brt; - float3 intensity = dot(brtColor, LumCoeff); - float3 satColor = lerp(intensity, brtColor, sat); - float3 conColor = lerp(AvgLumin, satColor, con); - - color.rgb = conColor; - return color; -} - -#if SHADER_MODEL >= 0x400 - -Texture2D Texture; -SamplerState Sampler; - -cbuffer cb0 -{ - float4 BGColor; -}; - -struct PS_INPUT -{ - float4 p : SV_Position; - float2 t : TEXCOORD0; -}; - -float4 ps_main(PS_INPUT input) : SV_Target0 -{ - float4 c = Texture.Sample(Sampler, input.t); - return ContrastSaturationBrightness(c); -} - - -#elif SHADER_MODEL <= 0x300 - -sampler Texture : register(s0); - -float4 g_params[1]; - -#define BGColor (g_params[0]) - -struct PS_INPUT -{ - float2 t : TEXCOORD0; -}; - -float4 ps_main(PS_INPUT input) : COLOR -{ - float4 c = tex2D(Texture, input.t); - return ContrastSaturationBrightness(c); -} - -#endif +#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency + +/* +** Contrast, saturation, brightness +** Code of this function is from TGM's shader pack +** http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=21057 +*/ + +// For all settings: 1.0 = 100% 0.5=50% 1.5 = 150% +float4 ContrastSaturationBrightness(float4 color) // Ported to HLSL +{ + const float sat = SB_SATURATION / 50.0; + const float brt = SB_BRIGHTNESS / 50.0; + const float con = SB_CONTRAST / 50.0; + + // Increase or decrease theese values to adjust r, g and b color channels seperately + const float AvgLumR = 0.5; + const float AvgLumG = 0.5; + const float AvgLumB = 0.5; + + const float3 LumCoeff = float3(0.2125, 0.7154, 0.0721); + + float3 AvgLumin = float3(AvgLumR, AvgLumG, AvgLumB); + float3 brtColor = color.rgb * brt; + float3 intensity = dot(brtColor, LumCoeff); + float3 satColor = lerp(intensity, brtColor, sat); + float3 conColor = lerp(AvgLumin, satColor, con); + + color.rgb = conColor; + return color; +} + +#if SHADER_MODEL >= 0x400 + +Texture2D Texture; +SamplerState Sampler; + +cbuffer cb0 +{ + float4 BGColor; +}; + +struct PS_INPUT +{ + float4 p : SV_Position; + float2 t : TEXCOORD0; +}; + +float4 ps_main(PS_INPUT input) : SV_Target0 +{ + float4 c = Texture.Sample(Sampler, input.t); + return ContrastSaturationBrightness(c); +} + + +#elif SHADER_MODEL <= 0x300 + +sampler Texture : register(s0); + +float4 g_params[1]; + +#define BGColor (g_params[0]) + +struct PS_INPUT +{ + float2 t : TEXCOORD0; +}; + +float4 ps_main(PS_INPUT input) : COLOR +{ + float4 c = tex2D(Texture, input.t); + return ContrastSaturationBrightness(c); +} + +#endif #endif \ No newline at end of file From 3a12cc05893eb1eda223829b6f14d00178c73445 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Mon, 23 Apr 2012 18:58:03 +0000 Subject: [PATCH 78/83] linux build: use turbo ;) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5174 96395faa-99c1-11dd-bbfe-3dabce05a288 --- build.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.sh b/build.sh index c6425f099..5deb1e5c8 100755 --- a/build.sh +++ b/build.sh @@ -53,7 +53,8 @@ if [ $clean_build = true ]; then echo "Doing a clean build." make clean 2>&1 | tee -a ../install_log.txt fi -make 2>&1 | tee -a ../install_log.txt +CORE=`grep -w -c processor /proc/cpuinfo` +make -j $CORE 2>&1 | tee -a ../install_log.txt make install 2>&1 | tee -a ../install_log.txt cd .. From 8eae370e8667a7e8e764758301c0a287e66194e4 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Tue, 24 Apr 2012 06:49:14 +0000 Subject: [PATCH 79/83] cmake: doc renaming broke the package mode git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5175 96395faa-99c1-11dd-bbfe-3dabce05a288 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b2a3ecd2..dc302264d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,5 +97,5 @@ if(PACKAGE_MODE) INSTALL(FILES "${PROJECT_SOURCE_DIR}/linux_various/pcsx2.xpm" DESTINATION "${CMAKE_INSTALL_PREFIX}/share/pixmaps") INSTALL(FILES "${PROJECT_SOURCE_DIR}/bin/docs/PCSX2_FAQ_0.9.8.pdf" DESTINATION "${CMAKE_INSTALL_PREFIX}/share/doc/pcsx2") INSTALL(FILES "${PROJECT_SOURCE_DIR}/bin/docs/PCSX2_Readme_0.9.8.pdf" DESTINATION "${CMAKE_INSTALL_PREFIX}/share/doc/pcsx2") - INSTALL(FILES "${PROJECT_SOURCE_DIR}/bin/docs/pcsx2.man" DESTINATION "${CMAKE_INSTALL_PREFIX}/share/man/man1/") + INSTALL(FILES "${PROJECT_SOURCE_DIR}/bin/docs/pcsx2.1" DESTINATION "${CMAKE_INSTALL_PREFIX}/share/man/man1/") endif(PACKAGE_MODE) From db39998f711d480ec617bcb54a33fead58757b76 Mon Sep 17 00:00:00 2001 From: "sudonim1@gmail.com" Date: Tue, 24 Apr 2012 14:02:34 +0000 Subject: [PATCH 80/83] GSDx: I screwed up when doing an untested last minute manual cleanup of gsdx.rc, the mouse over descriptions will actually work now. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5176 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSdx.rc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/GSdx/GSdx.rc b/plugins/GSdx/GSdx.rc index 3bbfaad9d..d3a216214 100644 --- a/plugins/GSdx/GSdx.rc +++ b/plugins/GSdx/GSdx.rc @@ -80,8 +80,8 @@ CAPTION "Hacks Configuration" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "OK",IDOK,258,182,50,14 - GROUPBOX "Hack",IDC_STATIC,7,7,76,165 - GROUPBOX "Description",IDC_STATIC,85,7,223,165,0,WS_EX_TRANSPARENT + GROUPBOX "Hack",IDC_STATIC,7,7,76,165,0,WS_EX_TRANSPARENT + GROUPBOX "Description",IDC_STATIC,85,7,223,165 LTEXT "MSAA",IDC_STATIC_MSAA,14,20,20,8 LTEXT "Skipdraw",IDC_STATIC_SKIPDRAW,14,37,30,8 EDITTEXT IDC_SKIPDRAWHACKEDIT,45,35,24,14,ES_RIGHT | ES_AUTOHSCROLL From 89ec3cb4e9fdd4ac86dcaf178965a53baf60983f Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Tue, 24 Apr 2012 14:24:58 +0000 Subject: [PATCH 81/83] GSdx: A couple minor tweaks to the hacks dialog text. Nothing much changed but sounds nicer to me :p git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5177 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSSettingsDlg.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/GSdx/GSSettingsDlg.cpp b/plugins/GSdx/GSSettingsDlg.cpp index 6de373635..e1ac03731 100644 --- a/plugins/GSdx/GSSettingsDlg.cpp +++ b/plugins/GSdx/GSSettingsDlg.cpp @@ -428,7 +428,7 @@ void GSHacksDlg::OnInit() // Hacks descriptions - SetWindowText(GetDlgItem(m_hWnd, IDC_HACK_DESCRIPTION), ""); // Blank it + SetWindowText(GetDlgItem(m_hWnd, IDC_HACK_DESCRIPTION), "Hover over an item to get a description."); } void GSHacksDlg::UpdateControls() @@ -459,32 +459,32 @@ bool GSHacksDlg::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) case IDC_SKIPDRAWHACKEDIT: case IDC_STATIC_SKIPDRAW: helpstr = "Skipdraw\n\nSkips drawing n surfaces completely. " - "Use it, for example, to try and get rid of messed up post processing effects." + "Use it, for example, to try and get rid of bad post processing effects." " Try values between 1 and 100."; break; case IDC_ALPHAHACK: - helpstr = "Alpha Hack\n\nDifferent alpha handling. Works around some shadow problems."; + helpstr = "Alpha Hack\n\nDifferent alpha handling. Can work around some shadow problems."; break; case IDC_OFFSETHACK: helpstr = "Halfpixel\n\nMight fix some misaligned fog, bloom, or blend effect."; break; case IDC_SPRITEHACK: helpstr = "Sprite Hack\n\nHelps getting rid of black inner lines in some filtered sprites." - " Half option should be the preferred one, for Mana Khemia and ArTonelico for example." - " Full should be used for Tales of Destiny."; + " Half option is the preferred one. Use it for Mana Khemia or ArTonelico for example." + " Full can be used for Tales of Destiny."; break; case IDC_WILDHACK: helpstr = "WildArms\n\nLowers the GS precission to avoid gaps between pixels when" " upscaling. Full option fixes the text on WildArms games, while Half option might improve portraits" - " in ArTonelico for example."; + " in ArTonelico."; break; case IDC_MSAACB: case IDC_STATIC_MSAA: helpstr = "Multisample Anti-Aliasing\n\nEnables hardware Anti-Aliasing. Needs lots of memory." - " The Z-24 modes might need to have LogarithmicZ to compensate for the bits lost (DX9 mode)."; + " The Z-24 modes might need to have LogarithmicZ to compensate for the bits lost (only in DX9 mode)."; break; default: - helpstr = ""; + helpstr = "Hover over an item to get a description."; break; } From 5dee597d9b602d5e8b640f565ab7eab48ebb56da Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Wed, 25 Apr 2012 08:46:51 +0000 Subject: [PATCH 82/83] GSdx: Auto interlace mode, no more flickering! :p git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5178 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSRenderer.cpp | 18 +++++++++++++----- plugins/GSdx/GSSettingsDlg.cpp | 2 +- plugins/GSdx/GSdx.cpp | 1 + 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/plugins/GSdx/GSRenderer.cpp b/plugins/GSdx/GSRenderer.cpp index 2d11c33e5..daf960574 100644 --- a/plugins/GSdx/GSRenderer.cpp +++ b/plugins/GSdx/GSRenderer.cpp @@ -249,10 +249,18 @@ bool GSRenderer::Merge(int field) if(m_regs->SMODE2.INT && m_interlace > 0) { - int field2 = 1 - ((m_interlace - 1) & 1); - int mode = (m_interlace - 1) >> 1; - - m_dev->Interlace(ds, field ^ field2, mode, tex[1] ? tex[1]->GetScale().y : tex[0]->GetScale().y); + if (m_interlace == 7 && m_regs->SMODE2.FFMD == 1) // Auto interlace enabled / Odd frame interlace setting + { + int field2 = 0; + int mode = 2; + m_dev->Interlace(ds, field ^ field2, mode, tex[1] ? tex[1]->GetScale().y : tex[0]->GetScale().y); + } + else + { + int field2 = 1 - ((m_interlace - 1) & 1); + int mode = (m_interlace - 1) >> 1; + m_dev->Interlace(ds, field ^ field2, mode, tex[1] ? tex[1]->GetScale().y : tex[0]->GetScale().y); + } } if(m_shadeboost) @@ -515,7 +523,7 @@ void GSRenderer::KeyEvent(GSKeyEventData* e) switch(e->key) { case VK_F5: - m_interlace = (m_interlace + 7 + step) % 7; + m_interlace = (m_interlace + 8 + step) % 8; printf("GSdx: Set deinterlace mode to %d (%s).\n", (int)m_interlace, theApp.m_gs_interlace.at(m_interlace).name.c_str()); return; case VK_F6: diff --git a/plugins/GSdx/GSSettingsDlg.cpp b/plugins/GSdx/GSSettingsDlg.cpp index e1ac03731..deaad5004 100644 --- a/plugins/GSdx/GSSettingsDlg.cpp +++ b/plugins/GSdx/GSSettingsDlg.cpp @@ -94,7 +94,7 @@ void GSSettingsDlg::OnInit() } ComboBoxInit(IDC_RENDERER, renderers, theApp.GetConfig("Renderer", 0)); - ComboBoxInit(IDC_INTERLACE, theApp.m_gs_interlace, theApp.GetConfig("Interlace", 0)); + ComboBoxInit(IDC_INTERLACE, theApp.m_gs_interlace, theApp.GetConfig("Interlace", 7)); // 7 = "auto", detects interlace based on SMODE2 register ComboBoxInit(IDC_ASPECTRATIO, theApp.m_gs_aspectratio, theApp.GetConfig("AspectRatio", 1)); ComboBoxInit(IDC_UPSCALE_MULTIPLIER, theApp.m_gs_upscale_multiplier, theApp.GetConfig("upscale_multiplier", 1)); diff --git a/plugins/GSdx/GSdx.cpp b/plugins/GSdx/GSdx.cpp index 88885b0a0..8289c57c4 100644 --- a/plugins/GSdx/GSdx.cpp +++ b/plugins/GSdx/GSdx.cpp @@ -124,6 +124,7 @@ GSdxApp::GSdxApp() m_gs_interlace.push_back(GSSetting(4, "Bob bff", "use blend if shaking")); m_gs_interlace.push_back(GSSetting(5, "Blend tff", "slight blur, 1/2 fps")); m_gs_interlace.push_back(GSSetting(6, "Blend bff", "slight blur, 1/2 fps")); + m_gs_interlace.push_back(GSSetting(7, "Auto", "")); m_gs_aspectratio.push_back(GSSetting(0, "Stretch", "")); m_gs_aspectratio.push_back(GSSetting(1, "4:3", "")); From 2cb99f0e05d2b82912739afbe92a61edbf273a22 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Thu, 26 Apr 2012 17:07:36 +0000 Subject: [PATCH 83/83] Preliminary NTSC progressive scan support. The detection is based on a quickly reversed smode1 flag and needs to be done properly. The timing itself also needs reversing and has only been tested on the VP2 intro video. (That video now runs without audio / video desync when progressive scan is enabled :) ) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5179 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/Counters.cpp | 28 ++++++++++++++++++++++------ pcsx2/GS.cpp | 3 ++- pcsx2/GS.h | 3 ++- plugins/GSdx/GSRenderer.cpp | 2 +- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/pcsx2/Counters.cpp b/pcsx2/Counters.cpp index 415cd0b57..0a908567a 100644 --- a/pcsx2/Counters.cpp +++ b/pcsx2/Counters.cpp @@ -209,6 +209,12 @@ static void vSyncInfoCalc( vSyncTimingInfo* info, Fixed100 framesPerSecond, u32 u64 Scanline = Frame / scansPerFrame; u64 hBlank = Scanline / 2; u64 hRender = Scanline - hBlank; + + if ( gsRegionMode == Region_NTSC_PROGRESSIVE ) + { + hBlank /= 2; + hRender /= 2; + } info->Framerate = framesPerSecond; info->Render = (u32)(Render/10000); @@ -226,12 +232,14 @@ static void vSyncInfoCalc( vSyncTimingInfo* info, Fixed100 framesPerSecond, u32 else if( ( hBlank - info->hBlank ) >= 5000 ) info->hBlank++; // Calculate accumulative hSync rounding error per half-frame: + if ( gsRegionMode != Region_NTSC_PROGRESSIVE ) // gets off the chart in that mode { - u32 hSyncCycles = ((info->hRender + info->hBlank) * scansPerFrame) / 2; - u32 vSyncCycles = (info->Render + info->Blank); - info->hSyncError = vSyncCycles - hSyncCycles; + u32 hSyncCycles = ((info->hRender + info->hBlank) * scansPerFrame) / 2; + u32 vSyncCycles = (info->Render + info->Blank); + info->hSyncError = vSyncCycles - hSyncCycles; + //Console.Warning("%d",info->hSyncError); } - + else info->hSyncError = 0; // Note: In NTSC modes there is some small rounding error in the vsync too, // however it would take thousands of frames for it to amount to anything and // is thus not worth the effort at this time. @@ -256,17 +264,25 @@ u32 UpdateVSyncRate() framerate = EmuConfig.GS.FrameratePAL / 2; scanlines = SCANLINES_TOTAL_PAL; } - else + else if ( gsRegionMode == Region_NTSC ) { isCustom = (EmuConfig.GS.FramerateNTSC != 59.94); framerate = EmuConfig.GS.FramerateNTSC / 2; scanlines = SCANLINES_TOTAL_NTSC; } + else if ( gsRegionMode == Region_NTSC_PROGRESSIVE ) + { + isCustom = (EmuConfig.GS.FramerateNTSC != 59.94); + framerate = 30; // Cheating here to avoid a complex change to the below "vSyncInfo.Framerate != framerate" branch + scanlines = SCANLINES_TOTAL_NTSC; + } if( vSyncInfo.Framerate != framerate ) { vSyncInfoCalc( &vSyncInfo, framerate, scanlines ); - Console.WriteLn( Color_Green, "(UpdateVSyncRate) Mode Changed to %s.", ( gsRegionMode == Region_PAL ) ? "PAL" : "NTSC" ); + Console.WriteLn( Color_Green, "(UpdateVSyncRate) Mode Changed to %s.", ( gsRegionMode == Region_PAL ) ? "PAL" : + ( gsRegionMode == Region_NTSC ) ? "NTSC" : "Progressive Scan" ); + if( isCustom ) Console.Indent().WriteLn( Color_StrongGreen, "... with user configured refresh rate: %.02f Hz", framerate.ToFloat() ); } diff --git a/pcsx2/GS.cpp b/pcsx2/GS.cpp index c43c79787..b5dc488ea 100644 --- a/pcsx2/GS.cpp +++ b/pcsx2/GS.cpp @@ -173,7 +173,8 @@ static __fi void _gsSMODEwrite( u32 mem, u32 value ) switch (mem) { case GS_SMODE1: - gsSetRegionMode( ((value & 0x6000) == 0x6000) ? Region_PAL : Region_NTSC ); + // ToDo: There's other flags determining which mode to set. The only tested one so far is the PAL / NTSC one. + gsSetRegionMode( ((value & 0x6000) == 0x6000) ? Region_PAL : (value & 0x400000) ? Region_NTSC_PROGRESSIVE : Region_NTSC ); break; case GS_SMODE2: diff --git a/pcsx2/GS.h b/pcsx2/GS.h index a9631824b..05943c921 100644 --- a/pcsx2/GS.h +++ b/pcsx2/GS.h @@ -220,7 +220,8 @@ struct GSRegSIGBLID enum GS_RegionMode { Region_NTSC, - Region_PAL + Region_PAL, + Region_NTSC_PROGRESSIVE }; extern GS_RegionMode gsRegionMode; diff --git a/plugins/GSdx/GSRenderer.cpp b/plugins/GSdx/GSRenderer.cpp index daf960574..a028e3398 100644 --- a/plugins/GSdx/GSRenderer.cpp +++ b/plugins/GSdx/GSRenderer.cpp @@ -94,7 +94,7 @@ bool GSRenderer::Merge(int field) baseline = min(dr[i].top, baseline); - // printf("[%d]: %d %d %d %d, %d %d %d %d\n", i, fr[i], dr[i]); + //printf("[%d]: %d %d %d %d, %d %d %d %d\n", i, fr[i].x,fr[i].y,fr[i].z,fr[i].w , dr[i].x,dr[i].y,dr[i].z,dr[i].w); } }