From b51f0b01dd8dd7453128d29776e1426d8124619f Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Fri, 8 Feb 2013 23:41:28 +0000 Subject: [PATCH 01/81] GIF Unit: Gave it some timing, kind of. Well the APATH and OPH flags in GIF Stat will now pretend it's transferring anyway, this makes games that read these flags and expect to see them busy very happy indeed. (187 Ride or Die as an example). I'm expecting something to break, it's my code, it's bound to. But i have tested some 40 games without problems, so my hopes are high! git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5551 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/GS.cpp | 2 +- pcsx2/Gif.cpp | 23 ++++++++++++++++++++++- pcsx2/Gif_Unit.h | 10 +++++----- pcsx2/Vif1_Dma.cpp | 19 +++++++++++++++++++ pcsx2/Vif1_MFIFO.cpp | 8 ++++++++ 5 files changed, 55 insertions(+), 7 deletions(-) diff --git a/pcsx2/GS.cpp b/pcsx2/GS.cpp index 2731da330..82960d2c8 100644 --- a/pcsx2/GS.cpp +++ b/pcsx2/GS.cpp @@ -110,7 +110,7 @@ static __fi void gsCSRwrite( const tGS_CSR& csr ) } else CSRreg.SIGNAL = false; gifUnit.gsSIGNAL.queued = false; - gifUnit.Execute(false); // Resume paused transfers + gifUnit.Execute(false, true); // Resume paused transfers } if(csr.FINISH) CSRreg.FINISH = false; diff --git a/pcsx2/Gif.cpp b/pcsx2/Gif.cpp index 3ede5edf5..4249b5257 100644 --- a/pcsx2/Gif.cpp +++ b/pcsx2/Gif.cpp @@ -50,7 +50,17 @@ void incGifChAddr(u32 qwc) { __fi void gifInterrupt() { GIF_LOG("gifInterrupt caught!"); - //Required for Path3 Masking timing! + if( gifRegs.stat.APATH == 3 ) + { + gifRegs.stat.APATH = 0; + gifRegs.stat.OPH = 0; + if(gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE || gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_WAIT) + { + if(gifUnit.checkPaths(1,1,0)) gifUnit.Execute(false, true); + } + + } + //Required for Path3 Masking timing! if(gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_WAIT) { gifUnit.gifPath[GIF_PATH_3].state = GIF_PATH_IDLE; @@ -456,6 +466,17 @@ void gifMFIFOInterrupt() GIF_LOG("gifMFIFOInterrupt"); mfifocycles = 0; + if( gifRegs.stat.APATH == 3 ) + { + gifRegs.stat.APATH = 0; + gifRegs.stat.OPH = 0; + if(gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE || gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_WAIT) + { + if(gifUnit.checkPaths(1,1,0)) gifUnit.Execute(false, true); + } + + } + if(gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_WAIT) { gifUnit.gifPath[GIF_PATH_3].state = GIF_PATH_IDLE; diff --git a/pcsx2/Gif_Unit.h b/pcsx2/Gif_Unit.h index 84e30e035..7bc1ac441 100644 --- a/pcsx2/Gif_Unit.h +++ b/pcsx2/Gif_Unit.h @@ -473,7 +473,7 @@ struct Gif_Unit { } if (tranType == GIF_TRANS_MTVU) { // This is on the EE thread path1.mtvu.fakePackets++; - if (CanDoGif()) Execute(false); + if (CanDoGif()) Execute(false, true); return 0; } } @@ -481,7 +481,7 @@ struct Gif_Unit { GUNIT_LOG("%s - [path=%d][size=%d]", Gif_TransferStr[(tranType>>8)&0xf], (tranType&3)+1, size); if (size == 0) { GUNIT_WARN("Gif Unit - Size == 0"); return 0; } if(!CanDoGif()) { GUNIT_WARN("Gif Unit - Signal or PSE Set or Dir = GS to EE"); } - pxAssertDev((stat.APATH==0) || checkPaths(1,1,1), "Gif Unit - APATH wasn't cleared?"); + //pxAssertDev((stat.APATH==0) || checkPaths(1,1,1), "Gif Unit - APATH wasn't cleared?"); lastTranType = tranType; if (tranType == GIF_TRANS_FIFO) { @@ -502,7 +502,7 @@ struct Gif_Unit { } gifPath[tranType&3].CopyGSPacketData(pMem, size, aligned); - size -= Execute(tranType == GIF_TRANS_DMA); + size -= Execute(tranType == GIF_TRANS_DMA, false); return size; } @@ -540,7 +540,7 @@ struct Gif_Unit { // Processes gif packets and performs path arbitration // on EOPs or on Path 3 Images when IMT is set. - int Execute(bool isPath3) { + int Execute(bool isPath3, bool isResume) { if (!CanDoGif()) { DevCon.Error("Gif Unit - Signal or PSE Set or Dir = GS to EE"); return 0; } bool didPath3 = false; int curPath = stat.APATH > 0 ? stat.APATH-1 : 0; //Init to zero if no path is already set. @@ -584,7 +584,7 @@ struct Gif_Unit { elif (!gsSIGNAL.queued && !gifPath[1].isDone()) { stat.APATH = 2; stat.P2Q = 0; curPath = 1; } elif (!gsSIGNAL.queued && !gifPath[2].isDone() && !Path3Masked() /*&& !stat.P2Q*/) { stat.APATH = 3; stat.P3Q = 0; stat.IP3 = 0; curPath = 2; } - else { stat.APATH = 0; stat.OPH = 0; break; } + else { if(isResume) { stat.APATH = 0; stat.OPH = 0; } break; } } //Some loaders/Refresh Rate selectors and things dont issue "End of Packet" commands diff --git a/pcsx2/Vif1_Dma.cpp b/pcsx2/Vif1_Dma.cpp index 0b3724af9..b8af59799 100644 --- a/pcsx2/Vif1_Dma.cpp +++ b/pcsx2/Vif1_Dma.cpp @@ -230,6 +230,18 @@ __fi void vif1VUFinish() vif1Regs.stat.VEW = false; VIF_LOG("VU1 finished"); + + if( gifRegs.stat.APATH == 1 ) + { + VIF_LOG("Clear APATH1"); + gifRegs.stat.APATH = 0; + gifRegs.stat.OPH = 0; + if(!vif1.waitforvu) + { + if(gifUnit.checkPaths(0,1,1)) gifUnit.Execute(false, true); + } + + } if(vif1.waitforvu == true) { vif1.waitforvu = false; @@ -253,6 +265,13 @@ __fi void vif1Interrupt() g_vif1Cycles = 0; + if( gifRegs.stat.APATH == 2 && gifUnit.gifPath[1].isDone()) + { + gifRegs.stat.APATH = 0; + gifRegs.stat.OPH = 0; + + if(gifUnit.checkPaths(1,0,1)) gifUnit.Execute(false, true); + } //Some games (Fahrenheit being one) start vif first, let it loop through blankness while it sets MFIFO mode, so we need to check it here. if (dmacRegs.ctrl.MFD == MFD_VIF1) { //Console.WriteLn("VIFMFIFO\n"); diff --git a/pcsx2/Vif1_MFIFO.cpp b/pcsx2/Vif1_MFIFO.cpp index 5daa3ffac..68c94afec 100644 --- a/pcsx2/Vif1_MFIFO.cpp +++ b/pcsx2/Vif1_MFIFO.cpp @@ -250,6 +250,14 @@ void vifMFIFOInterrupt() g_vif1Cycles = 0; VIF_LOG("vif mfifo interrupt"); + if( gifRegs.stat.APATH == 2 && gifUnit.gifPath[1].isDone()) + { + gifRegs.stat.APATH = 0; + gifRegs.stat.OPH = 0; + + if(gifUnit.checkPaths(1,0,1)) gifUnit.Execute(false, true); + } + if (dmacRegs.ctrl.MFD != MFD_VIF1) { DevCon.Warning("Not in VIF MFIFO mode! Stopping VIF MFIFO"); return; From e8d865d01daa86cff4a9cfd4933c92563ee88a79 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Sun, 10 Feb 2013 15:06:10 +0000 Subject: [PATCH 02/81] Gif Unit/VIF: Fix up some bits from r5551. Fixes SSX 3 and Charlie and the Chocolate Factory. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5552 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/FiFo.cpp | 21 +++++++++++++++++++++ pcsx2/Vif1_Dma.cpp | 3 +++ pcsx2/Vif_Codes.cpp | 28 +++++++++++++++++++--------- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/pcsx2/FiFo.cpp b/pcsx2/FiFo.cpp index a4d57b003..5f0317ff2 100644 --- a/pcsx2/FiFo.cpp +++ b/pcsx2/FiFo.cpp @@ -109,6 +109,15 @@ void __fastcall WriteFIFO_VIF1(const mem128_t *value) } else vif1Regs.stat.VPS = VPS_IDLE; + if( gifRegs.stat.APATH == 2 && gifUnit.gifPath[1].isDone()) + { + gifRegs.stat.APATH = 0; + gifRegs.stat.OPH = 0; + vif1Regs.stat.VGW = false; //Let vif continue if it's stuck on a flush + + if(gifUnit.checkPaths(1,0,1)) gifUnit.Execute(false, true); + } + pxAssertDev( ret, "vif stall code not implemented" ); } @@ -119,4 +128,16 @@ void __fastcall WriteFIFO_GIF(const mem128_t *value) if(gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_WAIT) gifUnit.gifPath[GIF_PATH_3].state = GIF_PATH_IDLE; + + if( gifRegs.stat.APATH == 3 ) + { + gifRegs.stat.APATH = 0; + gifRegs.stat.OPH = 0; + + if(gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE || gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_WAIT) + { + if(gifUnit.checkPaths(1,1,0)) gifUnit.Execute(false, true); + } + + } } diff --git a/pcsx2/Vif1_Dma.cpp b/pcsx2/Vif1_Dma.cpp index b8af59799..da5243568 100644 --- a/pcsx2/Vif1_Dma.cpp +++ b/pcsx2/Vif1_Dma.cpp @@ -236,6 +236,8 @@ __fi void vif1VUFinish() VIF_LOG("Clear APATH1"); gifRegs.stat.APATH = 0; gifRegs.stat.OPH = 0; + vif1Regs.stat.VGW = false; //Let vif continue if it's stuck on a flush + if(!vif1.waitforvu) { if(gifUnit.checkPaths(0,1,1)) gifUnit.Execute(false, true); @@ -269,6 +271,7 @@ __fi void vif1Interrupt() { gifRegs.stat.APATH = 0; gifRegs.stat.OPH = 0; + vif1Regs.stat.VGW = false; //Let vif continue if it's stuck on a flush if(gifUnit.checkPaths(1,0,1)) gifUnit.Execute(false, true); } diff --git a/pcsx2/Vif_Codes.cpp b/pcsx2/Vif_Codes.cpp index 38d2ee55a..dbb050705 100644 --- a/pcsx2/Vif_Codes.cpp +++ b/pcsx2/Vif_Codes.cpp @@ -181,9 +181,10 @@ vifOp(vifCode_Flush) { vif1Only(); vifStruct& vifX = GetVifX; pass1or2 { + bool p1or2 = (gifRegs.stat.APATH != 0 && gifRegs.stat.APATH != 3); vif1Regs.stat.VGW = false; vifFlush(idx); - if (gifUnit.checkPaths(1,1,0)) { + if (gifUnit.checkPaths(1,1,0) || p1or2) { GUNIT_WARN("Vif Flush: Stall!"); //gifUnit.PrintInfo(); vif1Regs.stat.VGW = true; @@ -202,15 +203,22 @@ vifOp(vifCode_FlushA) { vif1Only(); vifStruct& vifX = GetVifX; pass1or2 { - Gif_Path& p3 = gifUnit.gifPath[GIF_PATH_3]; - u32 p1or2 = gifUnit.checkPaths(1,1,0); - bool doStall = false; + //Gif_Path& p3 = gifUnit.gifPath[GIF_PATH_3]; + u32 gifBusy = gifUnit.checkPaths(1,1,1) || (gifRegs.stat.APATH != 0); + //bool doStall = false; vif1Regs.stat.VGW = false; vifFlush(idx); - if (p3.state != GIF_PATH_IDLE || p1or2) { + + if (gifBusy) + { GUNIT_WARN("Vif FlushA: Stall!"); + vif1Regs.stat.VGW = true; + vifX.vifstalled.enabled = true; + vifX.vifstalled.value = VIF_TIMING_BREAK; + return 0; + //gifUnit.PrintInfo(); - if (p3.state != GIF_PATH_IDLE && !p1or2) { // Only path 3 left... + /*if (p3.state != GIF_PATH_IDLE && !p1or2) { // Only path 3 left... GUNIT_WARN("Vif FlushA - Getting path3 to finish!"); if (gifUnit.lastTranType == GIF_TRANS_FIFO && p3.state != GIF_PATH_IDLE && !p3.hasDataRemaining()) { @@ -222,15 +230,17 @@ vifOp(vifCode_FlushA) { doStall = true; // If path3 still isn't finished... } } - else doStall = true; + else doStall = true;*/ } - if (doStall) { + /*if (doStall) { vif1Regs.stat.VGW = true; vifX.vifstalled.enabled = true; vifX.vifstalled.value = VIF_TIMING_BREAK; return 0; } - else vifX.cmd = 0; + else*/ + //Didn't need to stall! + vifX.cmd = 0; vifX.pass = 0; } pass3 { VifCodeLog("FlushA"); } From 7b195696a7eef35fa20e6c3da5df3f1f36127d08 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Sun, 10 Feb 2013 18:31:35 +0000 Subject: [PATCH 03/81] VIF: Hack for Dynasty Warriors 5 Empires. Completely harmless hack to make sure we aren't still waiting for PATH 2 data after a VIF reset. Something really odd is going off with the VIF packets in this game (probably SIF or something), but until we know what, this'll do. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5553 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/Vif.cpp | 22 ++++++++++++++++++++++ pcsx2/Vif1_Dma.cpp | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/pcsx2/Vif.cpp b/pcsx2/Vif.cpp index 7df6e5692..56ef28a81 100644 --- a/pcsx2/Vif.cpp +++ b/pcsx2/Vif.cpp @@ -21,6 +21,7 @@ #include "GS.h" #include "Gif.h" #include "MTVU.h" +#include "Gif_Unit.h" __aligned16 vifStruct vif0, vif1; @@ -178,6 +179,27 @@ __fi void vif1FBRST(u32 value) { psHu64(VIF1_FIFO + 8) = 0; vif1.done = true; vif1ch.chcr.STR = false; + + //HACK!! Dynasty Warriors 5 Empires has some sort of wierd packet alignment thing going off, meaning + //the packet ends before the DirectHL in progress has finished. Not sure what causes that, but the GIF + //Unit is still waiting for more data, so we have to "pretend" it is finished when the game issues a reset + //which it does without causing any pauses. + //In most cases, this will never ever happen, so doing the following won't matter. + if(!gifUnit.gifPath[GIF_PATH_2].isDone()) + { + DevCon.Warning("VIF1 FBRST While GIF Path2 is waiting for data!"); + gifUnit.gifPath[GIF_PATH_2].state = GIF_PATH_IDLE; + gifUnit.gifPath[GIF_PATH_2].curSize = gifUnit.gifPath[GIF_PATH_2].curOffset; + + if( gifRegs.stat.APATH == 2) + { + gifRegs.stat.APATH = 0; + gifRegs.stat.OPH = 0; + vif1Regs.stat.VGW = false; //Let vif continue if it's stuck on a flush + + if(gifUnit.checkPaths(1,0,1)) gifUnit.Execute(false, true); + } + } #if USE_OLD_GIF == 1 // ... if(vif1Regs.mskpath3 == 1 && GSTransferStatus.PTH3 == STOPPED_MODE && gifch.chcr.STR == true) { diff --git a/pcsx2/Vif1_Dma.cpp b/pcsx2/Vif1_Dma.cpp index da5243568..a48fa5c1c 100644 --- a/pcsx2/Vif1_Dma.cpp +++ b/pcsx2/Vif1_Dma.cpp @@ -267,7 +267,7 @@ __fi void vif1Interrupt() g_vif1Cycles = 0; - if( gifRegs.stat.APATH == 2 && gifUnit.gifPath[1].isDone()) + if( gifRegs.stat.APATH == 2 && gifUnit.gifPath[GIF_PATH_2].isDone()) { gifRegs.stat.APATH = 0; gifRegs.stat.OPH = 0; From b5e33f9c6c52eafe0deb772c38e1c40e27f66ef4 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Sun, 10 Feb 2013 19:50:46 +0000 Subject: [PATCH 04/81] Make dev and debug builds report "PS2DVD" disks instead of CDVD_TYPE_ILLEGAL. Need this for homebrew which wants to read disks. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5554 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/CDVD/CDVDaccess.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pcsx2/CDVD/CDVDaccess.cpp b/pcsx2/CDVD/CDVDaccess.cpp index cf71955a2..3706f5ffd 100644 --- a/pcsx2/CDVD/CDVDaccess.cpp +++ b/pcsx2/CDVD/CDVDaccess.cpp @@ -113,6 +113,9 @@ static int CheckDiskTypeFS(int baseType) { } +#ifdef PCSX2_DEVBUILD + return CDVD_TYPE_PS2DVD; // need this hack for some homebrew (SMS) +#endif return CDVD_TYPE_ILLEGAL; // << Only for discs which aren't ps2 at all. } From 45e3e6d549b0a99f33f50a1ee3a916a3c335dcea Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Mon, 11 Feb 2013 17:10:22 +0000 Subject: [PATCH 05/81] GSdx: Added a crc hack for Steambot Chronicles, made by miseru99. It doesn't look perfect but at least it's rather playable now. Thanks miseru99 :) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5555 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSCrc.cpp | 1 + plugins/GSdx/GSCrc.h | 1 + plugins/GSdx/GSState.cpp | 23 +++++++++++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/plugins/GSdx/GSCrc.cpp b/plugins/GSdx/GSCrc.cpp index 960374d56..54356966f 100644 --- a/plugins/GSdx/GSCrc.cpp +++ b/plugins/GSdx/GSCrc.cpp @@ -500,6 +500,7 @@ CRC::Game CRC::m_games[] = {0x0098F740, SeintoSeiya, NoRegion, 0}, // cutie comment {0xBDD9BAAD, UrbanReign, US, 0}, // cutie comment {0xAE4BEBD3, UrbanReign, EU, 0}, + {0x9F391882, SteambotChronicles, US, 0}, }; hash_map CRC::m_map; diff --git a/plugins/GSdx/GSCrc.h b/plugins/GSdx/GSCrc.h index 77b3c55fc..8669f70c3 100644 --- a/plugins/GSdx/GSCrc.h +++ b/plugins/GSdx/GSCrc.h @@ -173,6 +173,7 @@ public: Simple2000Vol114, SeintoSeiya, UrbanReign, + SteambotChronicles, TitleCount, }; diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index 6a5851803..eef0ec79a 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -5040,6 +5040,28 @@ bool GSC_UrbanReign(const GSFrameInfo& fi, int& skip) return true; } +bool GSC_SteambotChronicles(const GSFrameInfo& fi, int& skip) +{ + // Author: miseru99 on forums.pcsx2.net + if(fi.TME && fi.TPSM == PSM_PSMCT16S) + { + if(fi.FBP == 0x1180) + { + skip=1;//1 deletes some of the glitched effects + } + else if(fi.FBP == 0) + { + skip=100;//deletes most others(too high deletes the buggy sea completely;c, too low causes glitches to be visible) + } + else if(g_aggressive && fi.FBP != 0)//Agressive CRC + { + skip=19;//"speedhack", makes the game very light, vaporized water can disappear when not looked at directly, possibly some interface still, other value to try: 6 breaks menu background, possibly nothing(?) during gameplay, but it's slower, hence not much of a speedhack anymore + } + } + + return true; +} + #ifdef ENABLE_DYNAMIC_CRC_HACK #include @@ -5311,6 +5333,7 @@ bool GSState::IsBadFrame(int& skip, int UserHacks_SkipDraw) map[CRC::SoulCalibur3] = GSC_SoulCalibur3; map[CRC::Simple2000Vol114] = GSC_Simple2000Vol114; map[CRC::UrbanReign] = GSC_UrbanReign; + map[CRC::SteambotChronicles] = GSC_SteambotChronicles; } // TODO: just set gsc in SetGameCRC once From 94cad4a61afd34a8fa7e7ef57ce98f7a5bedd144 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Tue, 12 Feb 2013 10:57:48 +0000 Subject: [PATCH 06/81] GSdx: New hack from KrossX lets users configure their own texture coordinate offset via hacks dialog. This can be used to fine tune correction of upscale glitches versus the problems that come with it. I guess this is able to correct nearly all ghosting and bad text issues games can have! Thanks for this nice patch, KrossX :) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5556 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSDeviceDX.h | 3 +++ plugins/GSdx/GSRendererDX.cpp | 15 ++++++++++----- plugins/GSdx/GSRendererDX.h | 4 +++- plugins/GSdx/GSRendererDX11.cpp | 21 ++++++++++----------- plugins/GSdx/GSRendererDX9.cpp | 16 +++++++--------- plugins/GSdx/GSSettingsDlg.cpp | 30 ++++++++++++++++++++++++++++-- plugins/GSdx/GSTextureFX11.cpp | 8 +++++--- plugins/GSdx/GSTextureFX9.cpp | 8 +++++--- plugins/GSdx/GSdx.rc | 26 ++++++++++++++++---------- plugins/GSdx/res/tfx.fx | 13 +++++++++---- plugins/GSdx/resource.h | 10 ++++++++-- 11 files changed, 104 insertions(+), 50 deletions(-) diff --git a/plugins/GSdx/GSDeviceDX.h b/plugins/GSdx/GSDeviceDX.h index 76f2911f8..e49a4d2e3 100644 --- a/plugins/GSdx/GSDeviceDX.h +++ b/plugins/GSdx/GSDeviceDX.h @@ -96,6 +96,8 @@ public: GSVector4 MinF_TA; GSVector4i MskFix; + GSVector4 TC_OffsetHack; + struct PSConstantBuffer() { FogColor_AREF = GSVector4::zero(); @@ -175,6 +177,7 @@ public: uint32 colclip:2; uint32 date:2; uint32 spritehack:1; + uint32 tcoffsethack:1; uint32 point_sampler:1; }; diff --git a/plugins/GSdx/GSRendererDX.cpp b/plugins/GSdx/GSRendererDX.cpp index 1349e76c4..36713b6ee 100644 --- a/plugins/GSdx/GSRendererDX.cpp +++ b/plugins/GSdx/GSRendererDX.cpp @@ -31,8 +31,12 @@ 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; + UserHacks_WildHack = !!theApp.GetConfig("UserHacks", 0) ? theApp.GetConfig("UserHacks_WildHack", 0) : 0; UserHacks_AlphaStencil = !!theApp.GetConfig("UserHacks_AlphaStencil", 0) && !!theApp.GetConfig("UserHacks", 0); + + UserHacks_TCOffset = !!theApp.GetConfig("UserHacks", 0) ? theApp.GetConfig("UserHacks_TCOffset", 0) : 0; + UserHacks_TCO_x = (UserHacks_TCOffset & 0xFFFF) / -1000.0f; + UserHacks_TCO_y = ((UserHacks_TCOffset >> 16) & 0xFFFF) / -1000.0f; } GSRendererDX::~GSRendererDX() @@ -287,10 +291,7 @@ void GSRendererDX::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sourc ps_sel.wms = context->CLAMP.WMS; ps_sel.wmt = context->CLAMP.WMT; - if (tex->m_palette) - ps_sel.fmt = cpsm.fmt | 4; - else - ps_sel.fmt = cpsm.fmt; + ps_sel.fmt = tex->m_palette? cpsm.fmt | 4 : cpsm.fmt; ps_sel.aem = env.TEXA.AEM; ps_sel.tfx = context->TEX0.TFX; ps_sel.tcc = context->TEX0.TCC; @@ -319,6 +320,10 @@ void GSRendererDX::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sourc ps_cb.HalfTexel = GSVector4(-0.5f, 0.5f).xxyy() / WH.zwzw(); ps_cb.MskFix = GSVector4i(context->CLAMP.MINU, context->CLAMP.MINV, context->CLAMP.MAXU, context->CLAMP.MAXV); + // TC Offset Hack + ps_sel.tcoffsethack = !!UserHacks_TCOffset; + ps_cb.TC_OffsetHack = GSVector4(UserHacks_TCO_x, UserHacks_TCO_y).xyxy() / WH.xyxy(); + GSVector4 clamp(ps_cb.MskFix); GSVector4 ta(env.TEXA & GSVector4i::x000000ff()); diff --git a/plugins/GSdx/GSRendererDX.h b/plugins/GSdx/GSRendererDX.h index cd1587c80..5325433ee 100644 --- a/plugins/GSdx/GSRendererDX.h +++ b/plugins/GSdx/GSRendererDX.h @@ -37,7 +37,9 @@ protected: virtual void SetupIA() = 0; virtual void UpdateFBA(GSTexture* rt) {} - int UserHacks_WildHack; + unsigned int UserHacks_WildHack; + unsigned int UserHacks_TCOffset; + float UserHacks_TCO_x, UserHacks_TCO_y; public: GSRendererDX(GSTextureCache* tc, const GSVector2& pixelcenter = GSVector2(0, 0)); diff --git a/plugins/GSdx/GSRendererDX11.cpp b/plugins/GSdx/GSRendererDX11.cpp index 380956ac8..cd44665eb 100644 --- a/plugins/GSdx/GSRendererDX11.cpp +++ b/plugins/GSdx/GSRendererDX11.cpp @@ -45,17 +45,16 @@ void GSRendererDX11::SetupIA() if(dev->IAMapVertexBuffer(&ptr, 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; - } - + 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 &= 0x3FEF3FEF; + } + dev->IAUnmapVertexBuffer(); } diff --git a/plugins/GSdx/GSRendererDX9.cpp b/plugins/GSdx/GSRendererDX9.cpp index 437a526e1..c56218bef 100644 --- a/plugins/GSdx/GSRendererDX9.cpp +++ b/plugins/GSdx/GSRendererDX9.cpp @@ -199,15 +199,13 @@ void GSRendererDX9::SetupIA() { if(PRIM->FST) { - 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()); + if(UserHacks_WildHack && !isPackedUV_HackFlag) + { + t = GSVector4(GSVector4i::load(s->UV & 0x3FEF3FEF).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/GSSettingsDlg.cpp b/plugins/GSdx/GSSettingsDlg.cpp index 65588c797..b93aef9a1 100644 --- a/plugins/GSdx/GSSettingsDlg.cpp +++ b/plugins/GSdx/GSSettingsDlg.cpp @@ -522,6 +522,11 @@ 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)); + SendMessage(GetDlgItem(m_hWnd, IDC_TCOFFSETX), UDM_SETRANGE, 0, MAKELPARAM(10000, 0)); + SendMessage(GetDlgItem(m_hWnd, IDC_TCOFFSETX), UDM_SETPOS, 0, MAKELPARAM(theApp.GetConfig("UserHacks_TCOffset", 0) & 0xFFFF, 0)); + + SendMessage(GetDlgItem(m_hWnd, IDC_TCOFFSETY), UDM_SETRANGE, 0, MAKELPARAM(10000, 0)); + SendMessage(GetDlgItem(m_hWnd, IDC_TCOFFSETY), UDM_SETPOS, 0, MAKELPARAM((theApp.GetConfig("UserHacks_TCOffset", 0) >> 16) & 0xFFFF, 0)); // Hacks descriptions SetWindowText(GetDlgItem(m_hWnd, IDC_HACK_DESCRIPTION), "Hover over an item to get a description."); @@ -537,6 +542,7 @@ bool GSHacksDlg::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) case WM_SETCURSOR: { const char *helpstr = ""; + bool updateText = true; POINT pos; GetCursorPos(&pos); @@ -597,12 +603,26 @@ bool GSHacksDlg::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) "CrcHacksExclusions=all\n" "CrcHacksExclusions=0x0F0C4A9C, 0x0EE5646B, 0x7ACF7E03"; break; + + case IDC_TCOFFSETX: + case IDC_TCOFFSETX2: + case IDC_STATIC_TCOFFSETX: + case IDC_TCOFFSETY: + case IDC_TCOFFSETY2: + case IDC_STATIC_TCOFFSETY: + helpstr = "Texture Coordinates Offset Hack\n\n" + "Offset for the ST/UV texture coordinates. Fixes some odd texture issues and might fix some post processing alignment too.\n\n" + " 0500 0500, fixes Persona 3 minimap, helps Haunting Ground.\n" + " 0000 1000, fixes Xenosaga hair edges (DX10+ Issue)\n"; + break; + default: - helpstr = "Hover over an item to get a description."; + updateText = false; break; } - SetWindowText(GetDlgItem(m_hWnd, IDC_HACK_DESCRIPTION), helpstr); + if(updateText) + SetWindowText(GetDlgItem(m_hWnd, IDC_HACK_DESCRIPTION), helpstr); } break; @@ -623,6 +643,12 @@ bool GSHacksDlg::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) theApp.SetConfig("UserHacks_AggressiveCRC", (int)IsDlgButtonChecked(m_hWnd, IDC_AGGRESSIVECRC)); theApp.SetConfig("UserHacks_AlphaStencil", (int)IsDlgButtonChecked(m_hWnd, IDC_ALPHASTENCIL)); theApp.SetConfig("UserHacks_DisableCrcHacks", (int)IsDlgButtonChecked(m_hWnd, IDC_CHECK_DISABLE_ALL_HACKS)); + + unsigned int TCOFFSET = SendMessage(GetDlgItem(m_hWnd, IDC_TCOFFSETX), UDM_GETPOS, 0, 0) & 0xFFFF; + TCOFFSET |= (SendMessage(GetDlgItem(m_hWnd, IDC_TCOFFSETY), UDM_GETPOS, 0, 0) & 0xFFFF) << 16; + + theApp.SetConfig("UserHacks_TCOffset", TCOFFSET); + EndDialog(m_hWnd, id); } break; } diff --git a/plugins/GSdx/GSTextureFX11.cpp b/plugins/GSdx/GSTextureFX11.cpp index 689248c13..d51ec6ec0 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[17]; + string str[18]; str[0] = format("%d", sel.fst); str[1] = format("%d", sel.wms); @@ -195,7 +195,8 @@ void GSDevice11::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSe str[13] = format("%d", sel.colclip); str[14] = format("%d", sel.date); str[15] = format("%d", sel.spritehack); - str[16] = format("%d", sel.point_sampler); + str[16] = format("%d", sel.tcoffsethack); + str[17] = format("%d", sel.point_sampler); D3D11_SHADER_MACRO macro[] = { @@ -215,7 +216,8 @@ void GSDevice11::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSe {"PS_COLCLIP", str[13].c_str()}, {"PS_DATE", str[14].c_str()}, {"PS_SPRITEHACK", str[15].c_str()}, - {"PS_POINT_SAMPLER", str[16].c_str()}, + {"PS_TCOFFSETHACK", str[16].c_str()}, + {"PS_POINT_SAMPLER", str[17].c_str()}, {NULL, NULL}, }; diff --git a/plugins/GSdx/GSTextureFX9.cpp b/plugins/GSdx/GSTextureFX9.cpp index 132228ff8..a929458a8 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[16]; + string str[17]; str[0] = format("%d", sel.fst); str[1] = format("%d", sel.wms); @@ -152,7 +152,8 @@ void GSDevice9::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSel str[12] = format("%d", sel.colclip); str[13] = format("%d", sel.date); str[14] = format("%d", sel.spritehack); - str[15] = format("%d", sel.point_sampler); + str[15] = format("%d", sel.tcoffsethack); + str[16] = format("%d", sel.point_sampler); D3DXMACRO macro[] = { @@ -171,7 +172,8 @@ void GSDevice9::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSel {"PS_COLCLIP", str[12].c_str()}, {"PS_DATE", str[13].c_str()}, {"PS_SPRITEHACK", str[14].c_str()}, - {"PS_POINT_SAMPLER", str[15].c_str()}, + {"PS_TCOFFSETHACK", str[15].c_str()}, + {"PS_POINT_SAMPLER", str[16].c_str()}, {NULL, NULL}, }; diff --git a/plugins/GSdx/GSdx.rc b/plugins/GSdx/GSdx.rc index a5b602546..0b293f825 100644 --- a/plugins/GSdx/GSdx.rc +++ b/plugins/GSdx/GSdx.rc @@ -74,28 +74,34 @@ IDB_LOGO10 BITMAP "res\\logo10.bmp" // Dialog // -IDD_HACKS DIALOGEX 0, 0, 315, 203 +IDD_HACKS DIALOGEX 0, 0, 315, 236 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,258,182,50,14 - GROUPBOX "Hack",IDC_STATIC,7,7,76,165,0,WS_EX_TRANSPARENT - GROUPBOX "Description",IDC_STATIC,85,7,223,165 + DEFPUSHBUTTON "OK",IDOK,258,215,50,14 + GROUPBOX "Hack",IDC_STATIC,7,7,86,201,0,WS_EX_TRANSPARENT + GROUPBOX "Description",IDC_STATIC,96,7,212,201 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 + EDITTEXT IDC_SKIPDRAWHACKEDIT,53,35,35,14,ES_RIGHT | ES_AUTOHSCROLL + CONTROL "",IDC_SKIPDRAWHACK,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,88,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 "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 + LTEXT "USE AT YOUR OWN RISK!",IDC_STATIC,7,218,84,11,WS_DISABLED + COMBOBOX IDC_MSAACB,35,18,54,63,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP CONTROL "WildArmsOffset",IDC_WILDHACK,"Button",BS_AUTO3STATE | WS_TABSTOP,14,105,64,10 - LTEXT "TEXT_GOES_HERE",IDC_HACK_DESCRIPTION,92,20,209,145 + LTEXT "TEXT_GOES_HERE",IDC_HACK_DESCRIPTION,102,20,199,183 CONTROL "Aggressive-CRC",IDC_AGGRESSIVECRC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,122,66,10 CONTROL "Alpha Stencil",IDC_ALPHASTENCIL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,139,66,10 CONTROL "Disable CRCs",IDC_CHECK_DISABLE_ALL_HACKS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,156,58,10 + LTEXT "TC Offset X",IDC_STATIC_TCOFFSETX,14,173,37,8 + EDITTEXT IDC_TCOFFSETX2,53,171,35,14,ES_RIGHT | ES_AUTOHSCROLL + CONTROL "",IDC_TCOFFSETX,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,87,171,11,14 + EDITTEXT IDC_TCOFFSETY2,53,188,35,14,ES_RIGHT | ES_AUTOHSCROLL + CONTROL "",IDC_TCOFFSETY,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,86,188,11,14 + LTEXT "TC Offset Y",IDC_STATIC_TCOFFSETY,14,190,37,8 END IDD_SHADEBOOST DIALOGEX 0, 0, 316, 129 @@ -262,7 +268,7 @@ BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 308 TOPMARGIN, 7 - BOTTOMMARGIN, 196 + BOTTOMMARGIN, 229 END IDD_SHADEBOOST, DIALOG diff --git a/plugins/GSdx/res/tfx.fx b/plugins/GSdx/res/tfx.fx index 7d56b2986..f78f9ebe7 100644 --- a/plugins/GSdx/res/tfx.fx +++ b/plugins/GSdx/res/tfx.fx @@ -37,6 +37,7 @@ #define PS_COLCLIP 0 #define PS_DATE 0 #define PS_SPRITEHACK 0 +#define PS_TCOFFSETHACK 0 #define PS_POINT_SAMPLER 0 #endif @@ -101,6 +102,7 @@ cbuffer cb1 float2 MinF; float2 TA; uint4 MskFix; + float4 TC_OffsetHack; }; float4 sample_c(float2 uv) @@ -202,6 +204,8 @@ float4 ps_params[7]; #define MinF ps_params[4].xy #define TA ps_params[4].zw +#define TC_OffsetHack ps_params[5] + float4 sample_c(float2 uv) { return tex2D(Texture, uv); @@ -365,10 +369,11 @@ float4x4 sample_4p(float4 u) float4 sample(float2 st, float q) { - if(!PS_FST) - { - st /= q; - } + if(!PS_FST) st /= q; + + #if PS_TCOFFSETHACK + st += TC_OffsetHack.xy; + #endif float4 t; float4x4 c; diff --git a/plugins/GSdx/resource.h b/plugins/GSdx/resource.h index 70062a104..a4b56979f 100644 --- a/plugins/GSdx/resource.h +++ b/plugins/GSdx/resource.h @@ -80,7 +80,13 @@ #define IDC_AGGRESSIVECRC 2076 #define IDC_CHECK_DISABLE_ALL_HACKS 2077 #define IDC_ALPHASTENCIL 2078 -#define IDC_ADAPTER 2078 +#define IDC_ADAPTER 2079 +#define IDC_STATIC_TCOFFSETX 2080 +#define IDC_STATIC_TCOFFSETY 2081 +#define IDC_TCOFFSETX 2082 +#define IDC_TCOFFSETX2 2083 +#define IDC_TCOFFSETY 2084 +#define IDC_TCOFFSETY2 2085 #define IDC_COLORSPACE 3000 #define IDR_CONVERT_FX 10000 #define IDR_TFX_FX 10001 @@ -99,7 +105,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 10012 #define _APS_NEXT_COMMAND_VALUE 32771 -#define _APS_NEXT_CONTROL_VALUE 2079 +#define _APS_NEXT_CONTROL_VALUE 2086 #define _APS_NEXT_SYMED_VALUE 5000 #endif #endif From fae268b2691b98c1ee4ed80693c461396f3968f6 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Tue, 12 Feb 2013 11:46:36 +0000 Subject: [PATCH 07/81] One more patch by KrossX: Should fix the VS2012 project files for when only VS2012 (and not VS2010) is installed. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5557 96395faa-99c1-11dd-bbfe-3dabce05a288 --- .../w32pthreads/pthreads_lib_vs11.vcxproj | 2 +- .../wxWidgets/build/msw/wx_adv_vs11.vcxproj | 2 +- .../wxWidgets/build/msw/wx_base_vs11.vcxproj | 2 +- .../wxWidgets/build/msw/wx_core_vs11.vcxproj | 4 ++-- common/build/Utilities/utilities_vs11.vcxproj | 2 +- pcsx2/windows/VCprojects/pcsx2_vs11.vcxproj | 18 +++++++-------- .../CDVDiso/src/Windows/CDVDiso_vs11.vcxproj | 4 ++-- .../spu2-x/src/Windows/Spu2-X_vs11.vcxproj | 22 +++++++++---------- plugins/zerogs/dx/Windows/zerogs_vs11.vcxproj | 2 +- .../opengl/Win32/zerogsogl-cg_vs11.vcxproj | 14 ++++++------ .../opengl/Win32/zerogsogl_vs11.vcxproj | 14 ++++++------ 11 files changed, 43 insertions(+), 43 deletions(-) diff --git a/3rdparty/w32pthreads/pthreads_lib_vs11.vcxproj b/3rdparty/w32pthreads/pthreads_lib_vs11.vcxproj index 89ee931f3..8ca75a68f 100644 --- a/3rdparty/w32pthreads/pthreads_lib_vs11.vcxproj +++ b/3rdparty/w32pthreads/pthreads_lib_vs11.vcxproj @@ -641,7 +641,7 @@ - + {26511268-2902-4997-8421-ecd7055f9e28} false diff --git a/3rdparty/wxWidgets/build/msw/wx_adv_vs11.vcxproj b/3rdparty/wxWidgets/build/msw/wx_adv_vs11.vcxproj index 90b3f601f..74a6515f3 100644 --- a/3rdparty/wxWidgets/build/msw/wx_adv_vs11.vcxproj +++ b/3rdparty/wxWidgets/build/msw/wx_adv_vs11.vcxproj @@ -221,7 +221,7 @@ - + {c34487af-228a-4d11-8e50-27803df76873} false diff --git a/3rdparty/wxWidgets/build/msw/wx_base_vs11.vcxproj b/3rdparty/wxWidgets/build/msw/wx_base_vs11.vcxproj index 6894f6120..bdee3c6f5 100644 --- a/3rdparty/wxWidgets/build/msw/wx_base_vs11.vcxproj +++ b/3rdparty/wxWidgets/build/msw/wx_base_vs11.vcxproj @@ -379,7 +379,7 @@ - + {c34487af-228a-4d11-8e50-27803df76873} false diff --git a/3rdparty/wxWidgets/build/msw/wx_core_vs11.vcxproj b/3rdparty/wxWidgets/build/msw/wx_core_vs11.vcxproj index 9f8289f6c..964b427cf 100644 --- a/3rdparty/wxWidgets/build/msw/wx_core_vs11.vcxproj +++ b/3rdparty/wxWidgets/build/msw/wx_core_vs11.vcxproj @@ -1527,11 +1527,11 @@ - + {bc236261-77e8-4567-8d09-45cd02965eb6} false - + {c34487af-228a-4d11-8e50-27803df76873} false diff --git a/common/build/Utilities/utilities_vs11.vcxproj b/common/build/Utilities/utilities_vs11.vcxproj index 1a08e88d8..81d2555c1 100644 --- a/common/build/Utilities/utilities_vs11.vcxproj +++ b/common/build/Utilities/utilities_vs11.vcxproj @@ -192,7 +192,7 @@ - + {48ad7e0a-25b1-4974-a1e3-03f8c438d34f} false diff --git a/pcsx2/windows/VCprojects/pcsx2_vs11.vcxproj b/pcsx2/windows/VCprojects/pcsx2_vs11.vcxproj index dbd787ddf..0ca74c6f0 100644 --- a/pcsx2/windows/VCprojects/pcsx2_vs11.vcxproj +++ b/pcsx2/windows/VCprojects/pcsx2_vs11.vcxproj @@ -868,39 +868,39 @@ - + {26511268-2902-4997-8421-ecd7055f9e28} false - + {7e9b2be7-cec3-4f14-847b-0ab8d562fb86} false - + {0e231fb1-f3c9-4724-accb-de8bcb3c089e} false - + {48ad7e0a-25b1-4974-a1e3-03f8c438d34f} false - + {0318ba30-ef48-441a-9e10-dc85efae39f0} false - + {2f6c0388-20cb-4242-9f6c-a6ebb6a83f47} false - + {4639972e-424e-4e13-8b07-ca403c481346} false - + {a51123f5-9505-4eae-85e7-d320290a272c} false - + {677b7d11-d5e1-40b3-88b1-9a4df83d2213} false diff --git a/plugins/CDVDiso/src/Windows/CDVDiso_vs11.vcxproj b/plugins/CDVDiso/src/Windows/CDVDiso_vs11.vcxproj index 222ecfcfa..e2ac007bf 100644 --- a/plugins/CDVDiso/src/Windows/CDVDiso_vs11.vcxproj +++ b/plugins/CDVDiso/src/Windows/CDVDiso_vs11.vcxproj @@ -154,11 +154,11 @@ - + {f4eb4ab2-c595-4b05-8bc0-059024bc796c} false - + {2f6c0388-20cb-4242-9f6c-a6ebb6a83f47} false diff --git a/plugins/spu2-x/src/Windows/Spu2-X_vs11.vcxproj b/plugins/spu2-x/src/Windows/Spu2-X_vs11.vcxproj index 6b9085852..d4808abcd 100644 --- a/plugins/spu2-x/src/Windows/Spu2-X_vs11.vcxproj +++ b/plugins/spu2-x/src/Windows/Spu2-X_vs11.vcxproj @@ -462,47 +462,47 @@ - + {0a18a071-125e-442f-aff7-a3f68abecf99} false - + {e9b51944-7e6d-4bcd-83f2-7bbd5a46182d} false - + {26511268-2902-4997-8421-ecd7055f9e28} false - + {7e9b2be7-cec3-4f14-847b-0ab8d562fb86} false - + {0e231fb1-f3c9-4724-accb-de8bcb3c089e} false - + {48ad7e0a-25b1-4974-a1e3-03f8c438d34f} false - + {c34487af-228a-4d11-8e50-27803df76873} false - + {0318ba30-ef48-441a-9e10-dc85efae39f0} false - + {2f6c0388-20cb-4242-9f6c-a6ebb6a83f47} false - + {4639972e-424e-4e13-8b07-ca403c481346} false - + {a51123f5-9505-4eae-85e7-d320290a272c} false diff --git a/plugins/zerogs/dx/Windows/zerogs_vs11.vcxproj b/plugins/zerogs/dx/Windows/zerogs_vs11.vcxproj index 90b731ef9..2ea7f8a78 100644 --- a/plugins/zerogs/dx/Windows/zerogs_vs11.vcxproj +++ b/plugins/zerogs/dx/Windows/zerogs_vs11.vcxproj @@ -196,7 +196,7 @@ - + {2f6c0388-20cb-4242-9f6c-a6ebb6a83f47} true false diff --git a/plugins/zzogl-pg-cg/opengl/Win32/zerogsogl-cg_vs11.vcxproj b/plugins/zzogl-pg-cg/opengl/Win32/zerogsogl-cg_vs11.vcxproj index 43dacdf0e..81ad89f66 100644 --- a/plugins/zzogl-pg-cg/opengl/Win32/zerogsogl-cg_vs11.vcxproj +++ b/plugins/zzogl-pg-cg/opengl/Win32/zerogsogl-cg_vs11.vcxproj @@ -223,7 +223,7 @@ - + {bc236261-77e8-4567-8d09-45cd02965eb6} true false @@ -231,7 +231,7 @@ true false - + {26511268-2902-4997-8421-ecd7055f9e28} true false @@ -239,7 +239,7 @@ true false - + {7e9b2be7-cec3-4f14-847b-0ab8d562fb86} true false @@ -247,7 +247,7 @@ true false - + {48ad7e0a-25b1-4974-a1e3-03f8c438d34f} true false @@ -255,7 +255,7 @@ true false - + {0318ba30-ef48-441a-9e10-dc85efae39f0} true false @@ -263,7 +263,7 @@ true false - + {2f6c0388-20cb-4242-9f6c-a6ebb6a83f47} true false @@ -271,7 +271,7 @@ true false - + {4639972e-424e-4e13-8b07-ca403c481346} true false diff --git a/plugins/zzogl-pg/opengl/Win32/zerogsogl_vs11.vcxproj b/plugins/zzogl-pg/opengl/Win32/zerogsogl_vs11.vcxproj index c2eada648..8b347299c 100644 --- a/plugins/zzogl-pg/opengl/Win32/zerogsogl_vs11.vcxproj +++ b/plugins/zzogl-pg/opengl/Win32/zerogsogl_vs11.vcxproj @@ -231,7 +231,7 @@ - + {bc236261-77e8-4567-8d09-45cd02965eb6} true false @@ -239,7 +239,7 @@ true false - + {26511268-2902-4997-8421-ecd7055f9e28} true false @@ -247,7 +247,7 @@ true false - + {7e9b2be7-cec3-4f14-847b-0ab8d562fb86} true false @@ -255,7 +255,7 @@ true false - + {48ad7e0a-25b1-4974-a1e3-03f8c438d34f} true false @@ -263,7 +263,7 @@ true false - + {0318ba30-ef48-441a-9e10-dc85efae39f0} true false @@ -271,7 +271,7 @@ true false - + {2f6c0388-20cb-4242-9f6c-a6ebb6a83f47} true false @@ -279,7 +279,7 @@ true false - + {4639972e-424e-4e13-8b07-ca403c481346} true false From 7af51edd8788a96e5f546f0f39e4f974b56c51e5 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Tue, 12 Feb 2013 12:08:46 +0000 Subject: [PATCH 08/81] GSdx: DX9 hardware fix for the new hack. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5558 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/res/tfx.fx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/GSdx/res/tfx.fx b/plugins/GSdx/res/tfx.fx index f78f9ebe7..ef48db6f3 100644 --- a/plugins/GSdx/res/tfx.fx +++ b/plugins/GSdx/res/tfx.fx @@ -204,7 +204,7 @@ float4 ps_params[7]; #define MinF ps_params[4].xy #define TA ps_params[4].zw -#define TC_OffsetHack ps_params[5] +#define TC_OffsetHack ps_params[6] float4 sample_c(float2 uv) { From 8f9e04dc9db427d3784f09fdbaef61b46c85e8c4 Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Tue, 12 Feb 2013 18:41:33 +0000 Subject: [PATCH 09/81] GSdx, SPU2-X: Remove old code and disable a now useless warning. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5559 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSTextureCache.cpp | 17 ----------------- plugins/GSdx/config.h | 2 -- plugins/spu2-x/src/Dma.cpp | 5 +++-- 3 files changed, 3 insertions(+), 21 deletions(-) diff --git a/plugins/GSdx/GSTextureCache.cpp b/plugins/GSdx/GSTextureCache.cpp index d82ed1242..9831fa530 100644 --- a/plugins/GSdx/GSTextureCache.cpp +++ b/plugins/GSdx/GSTextureCache.cpp @@ -196,24 +196,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, int if(multiplier > 1) // it's limited to a maximum of 4 on reading the config { - -#if 0 //#ifdef ENABLE_UPSCALE_HACKS //not happy with this yet.. - - float x = 1.0f; - float y = 1.0f; - - switch(multiplier) - { - case 2: x = 1.9375; y = 2.0f; break; // x res get's rid of vertical lines in many games - case 3: x = 2.9375f; y = 2.9375f; break; // not helping much - case 4: x = 3.875f; y = 3.875f; break; // not helping much - default: __assume(0); - } - - dst->m_texture->SetScale(GSVector2::_(x, y)); -#else dst->m_texture->SetScale(GSVector2((float)multiplier, (float)multiplier)); -#endif } else { diff --git a/plugins/GSdx/config.h b/plugins/GSdx/config.h index 7b5661fbc..a11724fcb 100644 --- a/plugins/GSdx/config.h +++ b/plugins/GSdx/config.h @@ -28,8 +28,6 @@ //#define ENABLE_DYNAMIC_CRC_HACK #define DYNA_DLL_PATH "c:/dev/pcsx2/trunk/tools/dynacrchack/DynaCrcHack.dll" -#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_BITMASKING diff --git a/plugins/spu2-x/src/Dma.cpp b/plugins/spu2-x/src/Dma.cpp index 141c41e9c..766816c5f 100644 --- a/plugins/spu2-x/src/Dma.cpp +++ b/plugins/spu2-x/src/Dma.cpp @@ -197,10 +197,11 @@ void V_Core::PlainDMAWrite(u16 *pMem, u32 size) // but it could be indicative of an emulation foopah elsewhere. if(MsgToConsole()) { - if((uptr)pMem & 15) + // Don't need this anymore. Target may still be good to know though. + /*if((uptr)pMem & 15) { ConLog("* SPU2 DMA Write > Misaligned source. Core: %d IOP: %p TSA: 0x%x Size: 0x%x\n", Index, (void*)pMem, TSA, size); - } + }*/ if(TSA & 7) { From a7c8da75786c3047914a968e12e7f0a6fffac2c1 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Wed, 13 Feb 2013 21:49:54 +0000 Subject: [PATCH 10/81] Path3 Masking: Fix up some timing issues (now we have some lol) which made puzzle quest look even worse than it already did. also as a test i have enabled Intermittent transfer modes on GIF, however it's only very loosely working as it should, just enough so Puzzle Quest looks right. If it slows things down too much (initial testing is showing minimal slowdowns), then we can always disable it again. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5560 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/Gif.cpp | 2 +- pcsx2/Vif_Codes.cpp | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pcsx2/Gif.cpp b/pcsx2/Gif.cpp index 4249b5257..695c70d28 100644 --- a/pcsx2/Gif.cpp +++ b/pcsx2/Gif.cpp @@ -112,7 +112,7 @@ __fi void gifInterrupt() } static u32 WRITERING_DMA(u32 *pMem, u32 qwc) { - //qwc = min(qwc, 1024u); + if(gifRegs.stat.IMT) qwc = std::min(qwc, 1024u); uint size = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, (u8*)pMem, qwc*16) / 16; incGifChAddr(size); return size; diff --git a/pcsx2/Vif_Codes.cpp b/pcsx2/Vif_Codes.cpp index dbb050705..02c6d7f1c 100644 --- a/pcsx2/Vif_Codes.cpp +++ b/pcsx2/Vif_Codes.cpp @@ -432,6 +432,14 @@ vifOp(vifCode_Nop) { GetVifX.cmd = 0; GetVifX.pass = 0; vifExecQueue(idx); + if(GetVifX.vifpacketsize > 1) + { + if(((data[1] >> 24) & 0x7f) == 0x6) //is mskpath3 next + { + GetVifX.vifstalled.enabled = true; + GetVifX.vifstalled.value = VIF_TIMING_BREAK; + } + } } pass3 { VifCodeLog("Nop"); } return 1; From 484065d0a82421f96109aa5b962a39ac0def8d8e Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Mon, 18 Feb 2013 15:39:22 +0000 Subject: [PATCH 11/81] microVU: Fixed linking on branch delays. There may still be some situations that don't work correctly, but i don't have any games which use it, have ammended console logging to inform us if the game is broken. Fixes in this commit: -Evil Dead - Fistful of Boomstick - Now goes ingame and works right (needs software mode on gsdx to fix lighting) -Tony Hawk's Project 8 - Graphics are no correct. Like earlier TH games, you need Negative rounding to fix it all. -Mark of Kri - The game now has collision detection! Apparently before you'd get stuck on objects, now you can walk freely. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5561 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/x86/microVU_Analyze.inl | 13 +++++- pcsx2/x86/microVU_Branch.inl | 88 ++++++++++++++++++++++++++++++++++- pcsx2/x86/microVU_Compile.inl | 58 ++++++++++++++++++++++- pcsx2/x86/microVU_Lower.inl | 48 +++++++++++++------ 4 files changed, 187 insertions(+), 20 deletions(-) diff --git a/pcsx2/x86/microVU_Analyze.inl b/pcsx2/x86/microVU_Analyze.inl index 7fd22f544..ed32f3f35 100644 --- a/pcsx2/x86/microVU_Analyze.inl +++ b/pcsx2/x86/microVU_Analyze.inl @@ -460,12 +460,21 @@ __ri int mVUbranchCheck(mV) { mVUlow.badBranch = 1; incPC(2); mVUlow.evilBranch = 1; - mVUregs.blockType = 2; + + if(mVUlow.branch == 2 || mVUlow.branch == 10) //Needs linking, we can only guess this if the next is not conditional + { + if(branchType <= 2 && branchType >= 9) //First branch is not conditional so we know what the link will be + { //So we can let the existing evil block do its thing! We know where to get the addr :) + mVUregs.blockType = 2; + } //Else it is conditional, so we need to do some nasty processing later in microVU_Branch.inl + } + else mVUregs.blockType = 2; //Second branch doesn't need linking, so can let it run its evil block course (MGS2 for testing) + mVUregs.needExactMatch |= 7; // This might not be necessary, but w/e... mVUregs.flagInfo = 0; mVUregs.fullFlags0 = 0; mVUregs.fullFlags1 = 0; - DevCon.Warning("microVU%d: %s in %s delay slot! [%04x]", mVU.index, + DevCon.Warning("microVU%d: %s in %s delay slot! [%04x] - If game broken report to PCSX2 Team", mVU.index, branchSTR[mVUlow.branch&0xf], branchSTR[branchType&0xf], xPC); return 1; } diff --git a/pcsx2/x86/microVU_Branch.inl b/pcsx2/x86/microVU_Branch.inl index f784d01f8..50c51060c 100644 --- a/pcsx2/x86/microVU_Branch.inl +++ b/pcsx2/x86/microVU_Branch.inl @@ -18,7 +18,7 @@ extern bool doEarlyExit (microVU& mVU); extern void mVUincCycles(microVU& mVU, int x); extern void* mVUcompile (microVU& mVU, u32 startPC, uptr pState); - +extern void* mVUcompileSingleInstruction(microVU& mVU, u32 startPC, uptr pState, microFlagCycles& mFC); __fi int getLastFlagInst(microRegInfo& pState, int* xFlag, int flagType, int isEbit) { if (isEbit) return findFlagInst(xFlag, 0x7fffffff); if (pState.needExactMatch & (1<reset(); // Reset regAlloc mVUinitFirstPass(mVU, pState, thisPtr); + mVUbranch = 0; for(int branch = 0; mVUcount < endCount; mVUcount++) { incPC(1); startLoop(mVU); @@ -478,6 +531,7 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) { mVUsetupRange(mVU, xPC, 0); mVUdebugPrintBlocks(mVU,1); incPC(-3); // Go back to branch opcode + switch (mVUlow.branch) { case 1: case 2: normBranch(mVU, mFC); return thisPtr; // B/BAL case 9: case 10: normJump (mVU, mFC); return thisPtr; // JR/JALR @@ -502,7 +556,7 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) { __fi void* mVUentryGet(microVU& mVU, microBlockManager* block, u32 startPC, uptr pState) { microBlock* pBlock = block->search((microRegInfo*)pState); if (pBlock) return pBlock->x86ptrStart; - else return mVUcompile(mVU, startPC, pState); + else { return mVUcompile(mVU, startPC, pState);} } // Search for Existing Compiled Block (if found, return x86ptr; else, compile and return x86ptr) diff --git a/pcsx2/x86/microVU_Lower.inl b/pcsx2/x86/microVU_Lower.inl index d816b11fa..69af6b215 100644 --- a/pcsx2/x86/microVU_Lower.inl +++ b/pcsx2/x86/microVU_Lower.inl @@ -1245,7 +1245,8 @@ void setBranchA(mP, int x, int _x_) { void condEvilBranch(mV, int JMPcc) { if (mVUlow.badBranch) { xMOV(ptr32[&mVU.branch], gprT1); - xMOV(ptr32[&mVU.badBranch], branchAddrN); + xMOV(ptr32[&mVU.badBranch], branchAddr); + xCMP(gprT1b, 0); xForwardJump8 cJMP((JccComparisonType)JMPcc); incPC(6); // Branch Not Taken Addr + 8 @@ -1277,10 +1278,14 @@ mVUop(mVU_BAL) { setBranchA(mX, 2, _It_); pass1 { mVUanalyzeNormBranch(mVU, _It_, 1); } pass2 { - xMOV(gprT1, bSaveAddr); - mVUallocVIb(mVU, gprT1, _It_); - if (mVUlow.badBranch) { xMOV(ptr32[&mVU.badBranch], branchAddrN); } - if (mVUlow.evilBranch) { xMOV(ptr32[&mVU.evilBranch], branchAddr); } + if(!mVUlow.evilBranch) + { + xMOV(gprT1, bSaveAddr); + mVUallocVIb(mVU, gprT1, _It_); + } + + if (mVUlow.badBranch) { xMOV(ptr32[&mVU.badBranch], branchAddr); } + if (mVUlow.evilBranch) { xMOV(ptr32[&mVU.evilBranch], branchAddr);} mVU.profiler.EmitOp(opBAL); } pass3 { mVUlog("BAL vi%02d [%04x]", _Ft_, branchAddr, branchAddr); } @@ -1377,13 +1382,9 @@ void normJumpPass2(mV) { mVUallocVIa(mVU, gprT1, _Is_); xSHL(gprT1, 3); xAND(gprT1, mVU.microMemSize - 8); - if (!mVUlow.evilBranch) xMOV(ptr32[&mVU.branch], gprT1); - else xMOV(ptr32[&mVU.evilBranch], gprT1); - if (mVUlow.badBranch) { - xADD(gprT1, 8); - xAND(gprT1, mVU.microMemSize - 8); - xMOV(ptr32[&mVU.badBranch], gprT1); - } + + if (!mVUlow.evilBranch) xMOV(ptr32[&mVU.branch], gprT1); + else { xMOV(ptr32[&mVU.evilBranch], gprT1);} } } @@ -1399,8 +1400,27 @@ mVUop(mVU_JALR) { pass1 { mVUanalyzeJump(mVU, _Is_, _It_, 1); } pass2 { normJumpPass2(mVU); - xMOV(gprT1, bSaveAddr); - mVUallocVIb(mVU, gprT1, _It_); + if(!mVUlow.evilBranch) + { + xMOV(gprT1, bSaveAddr); + mVUallocVIb(mVU, gprT1, _It_); + } + if(mVUlow.evilBranch) + { + incPC(-2); + if(mVUlow.branch >= 9) //Previous branch is a jump of some type so + //we need to take the branch address from the register it uses. + { + DevCon.Warning("Linking JALR from JALR/JR branch target! - If game broken report to PCSX2 Team"); + mVUallocVIa(mVU, gprT1, _Is_); + xADD(gprT1, 8); + xSHR(gprT1, 3); + incPC(2); + mVUallocVIb(mVU, gprT1, _It_); + } + else incPC(2); + } + mVU.profiler.EmitOp(opJALR); } pass3 { mVUlog("JALR vi%02d, [vi%02d]", _Ft_, _Fs_); } From 8cc03b1e2af9c51ae65f71f80bb76999f6e186c2 Mon Sep 17 00:00:00 2001 From: "avihal@gmail.com" Date: Mon, 18 Feb 2013 16:39:46 +0000 Subject: [PATCH 12/81] Multiple cheat files and WIP: widescreen cheats 1. Multiple cheats files (at the "cheats' folder) can be loaded, as long as they begin with the CRC and end in '.pnach' (e.g ABCD1234.Persona4(EU).god-mode.pnach) 2. Multiple cheats are also loaded from the Widescreen hacks folder ('cheats_ws'). File names rules are the same as for normal cheats. TODO: Add config and GUI for widescreen hacks. Right now the cheat files from cheat_ws folder are loaded if cheats are enabled. We need a separate config for that. Thanks to dlanor from the forum for his filenames wildcards patch: http://forums.pcsx2.net/Thread-PCSX2-Patch-Finder-Removed-completely-or-just-hidden?pid=263592#pid263592 git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5562 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/Patch.cpp | 65 ++++++++++++++++++++++++------------- pcsx2/Patch.h | 3 +- pcsx2/gui/AppCoreThread.cpp | 13 ++++++-- 3 files changed, 56 insertions(+), 25 deletions(-) diff --git a/pcsx2/Patch.cpp b/pcsx2/Patch.cpp index b6fbae5a5..a8ef7ba3b 100644 --- a/pcsx2/Patch.cpp +++ b/pcsx2/Patch.cpp @@ -21,6 +21,7 @@ #include "Patch.h" #include "GameDatabase.h" #include +#include IniPatch Patch[ MAX_PATCH ]; IniPatch Cheat[ MAX_CHEAT ]; @@ -165,35 +166,55 @@ void inifile_process(wxTextFile &f1 ) } } +void ResetCeatsCount() +{ + cheatnumber = 0; +} + +static int LoadCheatsFiles(const wxString& folderName, wxString& fileSpec, const wxString& friendlyName) +{ + if (!wxDir::Exists(folderName)) { + Console.WriteLn(Color_Red, L"The %s folder ('%s') is inaccessible. Skipping...", friendlyName.c_str(), folderName.c_str()); + return 0; + } + wxDir dir(folderName); + + int before = cheatnumber; + wxString buffer; + wxTextFile f; + bool found = dir.GetFirst(&buffer, fileSpec, wxDIR_FILES); + while (found) { + Console.WriteLn(Color_Gray, L"Found %s file: '%s'", friendlyName.c_str(), buffer.c_str()); + int before = cheatnumber; + f.Open(Path::Combine(dir.GetName(), buffer)); + inifile_process(f); + f.Close(); + int loaded = cheatnumber - before; + Console.WriteLn((loaded ? Color_Green : Color_Gray), L"Loaded %d %s from '%s'", loaded, friendlyName.c_str(), buffer.c_str()); + found = dir.GetNext(&buffer); + } + + return cheatnumber - before; +} + // This routine loads cheats from *.pnach files // Returns number of cheats loaded // Note: Should be called after InitPatches() -int InitCheats(const wxString& name) +int LoadCheats(const wxString& name, const wxString& folderName, const wxString& friendlyName) { - wxTextFile f1; - wxString buffer; - cheatnumber = 0; + int loaded = 0; - // FIXME : We need to add a 'cheats' folder to the AppConfig, and use that instead. --air + wxString filespec = name + L"*.pnach"; + loaded += LoadCheatsFiles(folderName, filespec, friendlyName); - buffer = Path::Combine(L"cheats", name + L".pnach"); + wxString nameUpper = name; nameUpper.Upper(); + if (wxFileName::IsCaseSensitive() && name != nameUpper) { + filespec = nameUpper + L"*.pnach"; + loaded += LoadCheatsFiles(folderName, filespec, friendlyName); + } - if(!f1.Open(buffer) && wxFileName::IsCaseSensitive()) - { - f1.Open( Path::Combine(L"cheats", name.Upper() + L".pnach") ); - } - - if(!f1.IsOpened()) - { - Console.WriteLn( Color_Gray, "No cheats found. Resuming execution without cheats..." ); - return 0; - } - - Console.WriteLn( Color_Green, "Cheats found!"); - inifile_process( f1 ); - - Console.WriteLn("Cheats Loaded: %d", cheatnumber); - return cheatnumber; + Console.WriteLn((loaded ? Color_Green : Color_Gray), L"Overall %d %s loaded", loaded, friendlyName.c_str()); + return loaded; } static u32 StrToU32(const wxString& str, int base = 10) diff --git a/pcsx2/Patch.h b/pcsx2/Patch.h index a4db00831..c049097cf 100644 --- a/pcsx2/Patch.h +++ b/pcsx2/Patch.h @@ -57,7 +57,8 @@ namespace PatchFunc PATCHTABLEFUNC cheat; } -extern int InitCheats(const wxString& name); +extern void ResetCeatsCount(); +extern int LoadCheats(const wxString& name, const wxString& folderName, const wxString& friendlyName); extern void inifile_command(bool isCheat, const wxString& cmd); extern void inifile_trim(wxString& buffer); diff --git a/pcsx2/gui/AppCoreThread.cpp b/pcsx2/gui/AppCoreThread.cpp index cf02c7e82..4a41ec00f 100644 --- a/pcsx2/gui/AppCoreThread.cpp +++ b/pcsx2/gui/AppCoreThread.cpp @@ -305,6 +305,7 @@ void AppCoreThread::ApplySettings( const Pcsx2Config& src ) wxString gamePatch; wxString gameFixes; wxString gameCheats; + wxString gameWsHacks; wxString gameName; wxString gameCompat; @@ -349,13 +350,21 @@ void AppCoreThread::ApplySettings( const Pcsx2Config& src ) gameName = L"Booting PS2 BIOS... "; } + ResetCeatsCount(); if (EmuConfig.EnableCheats) { - if (int cheats = InitCheats(gameCRC)) { + if (int cheats = LoadCheats(gameCRC, L"cheats", L"Cheats")) { gameCheats.Printf(L" [%d Cheats]", cheats); } } - Console.SetTitle(gameName+gameSerial+gameCompat+gameFixes+gamePatch+gameCheats); + // FIXME: we should have a widescreen hacks config + if (EmuConfig.EnableCheats) { + if (int cheats = LoadCheats(gameCRC, L"cheats_ws", L"Widescreen hacks")) { + gameWsHacks.Printf(L" [%d WS hacks]", cheats); + } + } + + Console.SetTitle(gameName+gameSerial+gameCompat+gameFixes+gamePatch+gameCheats+gameWsHacks); // Re-entry guard protects against cases where code wants to manually set core settings // which are not part of g_Conf. The subsequent call to apply g_Conf settings (which is From c64c9a16ad445db16afa1dc5f115ec479f47a602 Mon Sep 17 00:00:00 2001 From: "avihal@gmail.com" Date: Mon, 18 Feb 2013 16:45:21 +0000 Subject: [PATCH 13/81] Typo fix. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5563 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/Patch.cpp | 2 +- pcsx2/Patch.h | 2 +- pcsx2/gui/AppCoreThread.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pcsx2/Patch.cpp b/pcsx2/Patch.cpp index a8ef7ba3b..6a899da4d 100644 --- a/pcsx2/Patch.cpp +++ b/pcsx2/Patch.cpp @@ -166,7 +166,7 @@ void inifile_process(wxTextFile &f1 ) } } -void ResetCeatsCount() +void ResetCheatsCount() { cheatnumber = 0; } diff --git a/pcsx2/Patch.h b/pcsx2/Patch.h index c049097cf..ac696252f 100644 --- a/pcsx2/Patch.h +++ b/pcsx2/Patch.h @@ -57,7 +57,7 @@ namespace PatchFunc PATCHTABLEFUNC cheat; } -extern void ResetCeatsCount(); +extern void ResetCheatsCount(); extern int LoadCheats(const wxString& name, const wxString& folderName, const wxString& friendlyName); extern void inifile_command(bool isCheat, const wxString& cmd); extern void inifile_trim(wxString& buffer); diff --git a/pcsx2/gui/AppCoreThread.cpp b/pcsx2/gui/AppCoreThread.cpp index 4a41ec00f..dab97ce2e 100644 --- a/pcsx2/gui/AppCoreThread.cpp +++ b/pcsx2/gui/AppCoreThread.cpp @@ -350,7 +350,7 @@ void AppCoreThread::ApplySettings( const Pcsx2Config& src ) gameName = L"Booting PS2 BIOS... "; } - ResetCeatsCount(); + ResetCheatsCount(); if (EmuConfig.EnableCheats) { if (int cheats = LoadCheats(gameCRC, L"cheats", L"Cheats")) { gameCheats.Printf(L" [%d Cheats]", cheats); From 8c86009a2703d7ec546b498e8ab677ca6395bd3a Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Mon, 18 Feb 2013 20:42:27 +0000 Subject: [PATCH 14/81] microVU: Found another bug with double branches, when there is a conditional in a JR/JALR delay slot it may have ended up in the wrong place. Unknown what it fixes, if anything. VIF/Path3 Masking: Put a timing break in on Path2 transfers, this gives it chance to stop being busy incase it is closely followed by a path3 mask, which caused it to go out of time. Fixes Sensible Soccer. VIF: Fixed up a couple of typo's, which may or may not have done anything, one which was not setting an offset if it stalled on 1/4 of a quadword, which could have been disasterous if done by the wrong game. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5564 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/Vif_Codes.cpp | 18 ++++++++++-------- pcsx2/Vif_Transfer.cpp | 4 ++-- pcsx2/x86/microVU_Lower.inl | 15 ++++++++++----- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/pcsx2/Vif_Codes.cpp b/pcsx2/Vif_Codes.cpp index 02c6d7f1c..4b53ab884 100644 --- a/pcsx2/Vif_Codes.cpp +++ b/pcsx2/Vif_Codes.cpp @@ -161,6 +161,8 @@ template __fi int _vifCode_Direct(int pass, const u8* data, bool isDire if (vif1.tag.size == 0) { vif1.cmd = 0; vif1.pass = 0; + vif1.vifstalled.enabled = true; + vif1.vifstalled.value = VIF_TIMING_BREAK; } return ret / 4; } @@ -188,12 +190,12 @@ vifOp(vifCode_Flush) { GUNIT_WARN("Vif Flush: Stall!"); //gifUnit.PrintInfo(); vif1Regs.stat.VGW = true; - vifX.vifstalled.enabled = true; - vifX.vifstalled.value = VIF_TIMING_BREAK; + vif1.vifstalled.enabled = true; + vif1.vifstalled.value = VIF_TIMING_BREAK; return 0; } - else vifX.cmd = 0; - vifX.pass = 0; + else vif1.cmd = 0; + vif1.pass = 0; } pass3 { VifCodeLog("Flush"); } return 1; @@ -213,8 +215,8 @@ vifOp(vifCode_FlushA) { { GUNIT_WARN("Vif FlushA: Stall!"); vif1Regs.stat.VGW = true; - vifX.vifstalled.enabled = true; - vifX.vifstalled.value = VIF_TIMING_BREAK; + vif1.vifstalled.enabled = true; + vif1.vifstalled.value = VIF_TIMING_BREAK; return 0; //gifUnit.PrintInfo(); @@ -240,8 +242,8 @@ vifOp(vifCode_FlushA) { } else*/ //Didn't need to stall! - vifX.cmd = 0; - vifX.pass = 0; + vif1.cmd = 0; + vif1.pass = 0; } pass3 { VifCodeLog("FlushA"); } return 1; diff --git a/pcsx2/Vif_Transfer.cpp b/pcsx2/Vif_Transfer.cpp index 4b4361a70..6beb36a75 100644 --- a/pcsx2/Vif_Transfer.cpp +++ b/pcsx2/Vif_Transfer.cpp @@ -107,9 +107,9 @@ _vifT static __fi bool vifTransfer(u32 *data, int size, bool TTE) { } else { - if(vifX.irqoffset.value > 1) + if(vifX.irqoffset.value != 0){ vifX.irqoffset.enabled = true; - else + }else vifX.irqoffset.enabled = false; } diff --git a/pcsx2/x86/microVU_Lower.inl b/pcsx2/x86/microVU_Lower.inl index 69af6b215..f44e11501 100644 --- a/pcsx2/x86/microVU_Lower.inl +++ b/pcsx2/x86/microVU_Lower.inl @@ -1245,7 +1245,7 @@ void setBranchA(mP, int x, int _x_) { void condEvilBranch(mV, int JMPcc) { if (mVUlow.badBranch) { xMOV(ptr32[&mVU.branch], gprT1); - xMOV(ptr32[&mVU.badBranch], branchAddr); + xMOV(ptr32[&mVU.badBranch], branchAddrN); xCMP(gprT1b, 0); xForwardJump8 cJMP((JccComparisonType)JMPcc); @@ -1261,6 +1261,9 @@ void condEvilBranch(mV, int JMPcc) { xMOV(gprT1, ptr32[&mVU.badBranch]); // Branch Not Taken xMOV(ptr32[&mVU.evilBranch], gprT1); cJMP.SetTarget(); + incPC(-2); + if(mVUlow.branch >= 9) DevCon.Warning("Conditional in JALR/JR delay slot - If game broken report to PCSX2 Team"); + incPC(2); } mVUop(mVU_B) { @@ -1284,7 +1287,7 @@ mVUop(mVU_BAL) { mVUallocVIb(mVU, gprT1, _It_); } - if (mVUlow.badBranch) { xMOV(ptr32[&mVU.badBranch], branchAddr); } + if (mVUlow.badBranch) { xMOV(ptr32[&mVU.badBranch], branchAddrN); } if (mVUlow.evilBranch) { xMOV(ptr32[&mVU.evilBranch], branchAddr);} mVU.profiler.EmitOp(opBAL); } @@ -1382,9 +1385,11 @@ void normJumpPass2(mV) { mVUallocVIa(mVU, gprT1, _Is_); xSHL(gprT1, 3); xAND(gprT1, mVU.microMemSize - 8); - - if (!mVUlow.evilBranch) xMOV(ptr32[&mVU.branch], gprT1); - else { xMOV(ptr32[&mVU.evilBranch], gprT1);} + + if (!mVUlow.evilBranch) { xMOV(ptr32[&mVU.branch], gprT1 ); } + else { xMOV(ptr32[&mVU.evilBranch], gprT1 ); } + //If delay slot is conditional, it uses badBranch to go to its target + if (mVUlow.badBranch) { xADD(gprT1, 8); xMOV(ptr32[&mVU.badBranch], gprT1); } } } From a1bc42fa92cb80e239a7334acea27f7c2e685b61 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Mon, 18 Feb 2013 21:17:35 +0000 Subject: [PATCH 15/81] VIF: Put in a check to make sure VIF doesn't break during a FIFO write. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5565 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/Vif.cpp | 6 +++--- pcsx2/Vif.h | 2 ++ pcsx2/Vif0_Dma.cpp | 2 +- pcsx2/Vif1_Dma.cpp | 2 +- pcsx2/Vif_Codes.cpp | 18 +++++++++--------- pcsx2/Vif_Transfer.cpp | 2 +- 6 files changed, 17 insertions(+), 15 deletions(-) diff --git a/pcsx2/Vif.cpp b/pcsx2/Vif.cpp index 56ef28a81..07dc6ea7f 100644 --- a/pcsx2/Vif.cpp +++ b/pcsx2/Vif.cpp @@ -125,7 +125,7 @@ __fi void vif0FBRST(u32 value) { // just stoppin the VIF (linuz). vif0Regs.stat.VSS = true; vif0Regs.stat.VPS = VPS_IDLE; - vif0.vifstalled.enabled = true; + vif0.vifstalled.enabled = VifStallEnable(vif0ch); vif0.vifstalled.value = VIF_IRQ_STALL; } @@ -231,7 +231,7 @@ __fi void vif1FBRST(u32 value) { vif1Regs.stat.VFS = true; vif1Regs.stat.VPS = VPS_IDLE; cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's - vif1.vifstalled.enabled = true; + vif1.vifstalled.enabled = VifStallEnable(vif1ch); vif1.vifstalled.value = VIF_IRQ_STALL; Console.WriteLn("vif1 force break"); } @@ -243,7 +243,7 @@ __fi void vif1FBRST(u32 value) { vif1Regs.stat.VSS = true; vif1Regs.stat.VPS = VPS_IDLE; cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's - vif1.vifstalled.enabled = true; + vif1.vifstalled.enabled = VifStallEnable(vif1ch); vif1.vifstalled.value = VIF_IRQ_STALL; } diff --git a/pcsx2/Vif.h b/pcsx2/Vif.h index 235e23248..32825aa26 100644 --- a/pcsx2/Vif.h +++ b/pcsx2/Vif.h @@ -241,6 +241,8 @@ static VIFregisters& vif1Regs = (VIFregisters&)eeHw[0x3C00]; #define MTVU_VifX (idx ? ((THREAD_VU1) ? vu1Thread.vif : vif1) : (vif0)) #define MTVU_VifXRegs (idx ? ((THREAD_VU1) ? vu1Thread.vifRegs : vif1Regs) : (vif0Regs)) +#define VifStallEnable(vif) vif.chcr.STR ? true : false; + extern void dmaVIF0(); extern void dmaVIF1(); extern void mfifoVIF1transfer(int qwc); diff --git a/pcsx2/Vif0_Dma.cpp b/pcsx2/Vif0_Dma.cpp index ecd8a4978..909c88a44 100644 --- a/pcsx2/Vif0_Dma.cpp +++ b/pcsx2/Vif0_Dma.cpp @@ -28,7 +28,7 @@ __fi void vif0FLUSH() if(vif0Regs.stat.VEW == true) { vif0.waitforvu = true; - vif0.vifstalled.enabled = true; + vif0.vifstalled.enabled = VifStallEnable(vif0ch); vif0.vifstalled.value = VIF_TIMING_BREAK; } return; diff --git a/pcsx2/Vif1_Dma.cpp b/pcsx2/Vif1_Dma.cpp index a48fa5c1c..08b2c2d28 100644 --- a/pcsx2/Vif1_Dma.cpp +++ b/pcsx2/Vif1_Dma.cpp @@ -28,7 +28,7 @@ __fi void vif1FLUSH() if(vif1Regs.stat.VEW == true) { vif1.waitforvu = true; - vif1.vifstalled.enabled = true; + vif1.vifstalled.enabled = VifStallEnable(vif1ch); vif1.vifstalled.value = VIF_TIMING_BREAK; } } diff --git a/pcsx2/Vif_Codes.cpp b/pcsx2/Vif_Codes.cpp index 4b53ab884..0750026bb 100644 --- a/pcsx2/Vif_Codes.cpp +++ b/pcsx2/Vif_Codes.cpp @@ -54,7 +54,7 @@ __ri void vifExecQueue(int idx) 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); - //GetVifX.vifstalled.enabled = true; + //GetVifX.vifstalled.enabled = VifStallEnable(vifXch); //GetVifX.vifstalled.value = VIF_TIMING_BREAK; } @@ -153,7 +153,7 @@ template __fi int _vifCode_Direct(int pass, const u8* data, bool isDire if (size != ret) { // Stall if gif didn't process all the data (path2 queued) GUNIT_WARN("Vif %s: Stall! [size=%d][ret=%d]", name, size, ret); //gifUnit.PrintInfo(); - vif1.vifstalled.enabled = true; + vif1.vifstalled.enabled = VifStallEnable(vif1ch); vif1.vifstalled.value = VIF_TIMING_BREAK; vif1Regs.stat.VGW = true; return 0; @@ -161,7 +161,7 @@ template __fi int _vifCode_Direct(int pass, const u8* data, bool isDire if (vif1.tag.size == 0) { vif1.cmd = 0; vif1.pass = 0; - vif1.vifstalled.enabled = true; + vif1.vifstalled.enabled = VifStallEnable(vif1ch); vif1.vifstalled.value = VIF_TIMING_BREAK; } return ret / 4; @@ -190,7 +190,7 @@ vifOp(vifCode_Flush) { GUNIT_WARN("Vif Flush: Stall!"); //gifUnit.PrintInfo(); vif1Regs.stat.VGW = true; - vif1.vifstalled.enabled = true; + vif1.vifstalled.enabled = VifStallEnable(vif1ch); vif1.vifstalled.value = VIF_TIMING_BREAK; return 0; } @@ -215,7 +215,7 @@ vifOp(vifCode_FlushA) { { GUNIT_WARN("Vif FlushA: Stall!"); vif1Regs.stat.VGW = true; - vif1.vifstalled.enabled = true; + vif1.vifstalled.enabled = VifStallEnable(vif1ch); vif1.vifstalled.value = VIF_TIMING_BREAK; return 0; @@ -236,7 +236,7 @@ vifOp(vifCode_FlushA) { } /*if (doStall) { vif1Regs.stat.VGW = true; - vifX.vifstalled.enabled = true; + vifX.vifstalled.enabled = VifStallEnable(vifXch); vifX.vifstalled.value = VIF_TIMING_BREAK; return 0; } @@ -380,7 +380,7 @@ vifOp(vifCode_MSCALF) { if (u32 a = gifUnit.checkPaths(1,1,0)) { GUNIT_WARN("Vif MSCALF: Stall! [%d,%d]", !!(a&1), !!(a&2)); vif1Regs.stat.VGW = true; - vifX.vifstalled.enabled = true; + vifX.vifstalled.enabled = VifStallEnable(vifXch); vifX.vifstalled.value = VIF_TIMING_BREAK; } if(vifX.waitforvu == false) @@ -438,7 +438,7 @@ vifOp(vifCode_Nop) { { if(((data[1] >> 24) & 0x7f) == 0x6) //is mskpath3 next { - GetVifX.vifstalled.enabled = true; + GetVifX.vifstalled.enabled = VifStallEnable(vifXch); GetVifX.vifstalled.value = VIF_TIMING_BREAK; } } @@ -455,7 +455,7 @@ vifOp(vifCode_Null) { if (!(vifXRegs.err.ME1)) { // Ignore vifcode and tag mismatch error Console.WriteLn("Vif%d: Unknown VifCmd! [%x]", idx, vifX.cmd); vifXRegs.stat.ER1 = true; - vifX.vifstalled.enabled = true; + vifX.vifstalled.enabled = VifStallEnable(vifXch); vifX.vifstalled.value = VIF_IRQ_STALL; //vifX.irq++; } diff --git a/pcsx2/Vif_Transfer.cpp b/pcsx2/Vif_Transfer.cpp index 6beb36a75..93f189f81 100644 --- a/pcsx2/Vif_Transfer.cpp +++ b/pcsx2/Vif_Transfer.cpp @@ -86,7 +86,7 @@ _vifT static __fi bool vifTransfer(u32 *data, int size, bool TTE) { vifXRegs.stat.VIS = true; // Note: commenting this out fixes WALL-E? } //Always needs to be set to return to the correct offset if there is data left. - vifX.vifstalled.enabled = true; + vifX.vifstalled.enabled = VifStallEnable(vifXch); vifX.vifstalled.value = VIF_IRQ_STALL; } From adc075a098907afe047034c596f5b99f2bb6edad Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Thu, 21 Feb 2013 01:07:52 +0000 Subject: [PATCH 16/81] microVU: Fixed 1-Op flag linking (hopefully) if it kills stuff let me know and ill revert. Hopefully it'll help MGS2 a bit, but no guarantees. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5566 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/x86/microVU_Compile.inl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index fa0892c1d..2778454ee 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -407,7 +407,7 @@ __fi void mVUinitFirstPass(microVU& mVU, uptr pState, u8* thisPtr) { } mVUblock.x86ptrStart = thisPtr; mVUpBlock = mVUblocks[mVUstartPC/2]->add(&mVUblock); // Add this block to block manager - mVUregs.needExactMatch = /*(mVUregs.blockType||noFlagOpts)?7:*/0; // ToDo: Fix 1-Op block flag linking (MGS2:Demo/Sly Cooper) + mVUregs.needExactMatch = (isEvilBlock)?7:0; // ToDo: Fix 1-Op block flag linking (MGS2:Demo/Sly Cooper) mVUregs.blockType = 0; mVUregs.viBackUp = 0; mVUregs.flagInfo = 0; @@ -504,6 +504,7 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) { elif (branch == 1) { branch = 2; } if (mVUbranch) { mVUsetFlagInfo(mVU); eBitWarning(mVU); branch = 3; mVUbranch = 0; } incPC(1); + if(isEvilBlock){ mVUcount++; break; } //Need a count, else the flags do not update. } // Fix up vi15 const info for propagation through blocks From 03b15d395e194f92b6bc49f15807b7d87f77b983 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Thu, 21 Feb 2013 18:32:20 +0000 Subject: [PATCH 17/81] microVU: Slight modification to yesterdays work. Realised blocktype 1 needs its flag status's checking too. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5567 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/x86/microVU_Compile.inl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index 2778454ee..5faf910fb 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -407,7 +407,7 @@ __fi void mVUinitFirstPass(microVU& mVU, uptr pState, u8* thisPtr) { } mVUblock.x86ptrStart = thisPtr; mVUpBlock = mVUblocks[mVUstartPC/2]->add(&mVUblock); // Add this block to block manager - mVUregs.needExactMatch = (isEvilBlock)?7:0; // ToDo: Fix 1-Op block flag linking (MGS2:Demo/Sly Cooper) + mVUregs.needExactMatch = (mVUpBlock->pState.blockType)?7:0; // ToDo: Fix 1-Op block flag linking (MGS2:Demo/Sly Cooper) mVUregs.blockType = 0; mVUregs.viBackUp = 0; mVUregs.flagInfo = 0; @@ -484,7 +484,7 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) { mVU.regAlloc->reset(); // Reset regAlloc mVUinitFirstPass(mVU, pState, thisPtr); mVUbranch = 0; - for(int branch = 0; mVUcount < endCount; mVUcount++) { + for(int branch = 0; mVUcount < endCount;) { incPC(1); startLoop(mVU); mVUincCycles(mVU, 1); @@ -500,11 +500,11 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) { mVUinfo.writeQ = !mVU.q; mVUinfo.readP = mVU.p; mVUinfo.writeP = !mVU.p; - if (branch >= 2) { mVUinfo.isEOB = 1; if (branch == 3) { mVUinfo.isBdelay = 1; } mVUcount++; branchWarning(mVU); break; } + mVUcount++; + if (branch >= 2) { mVUinfo.isEOB = 1; if (branch == 3) { mVUinfo.isBdelay = 1; } branchWarning(mVU); break; } elif (branch == 1) { branch = 2; } if (mVUbranch) { mVUsetFlagInfo(mVU); eBitWarning(mVU); branch = 3; mVUbranch = 0; } incPC(1); - if(isEvilBlock){ mVUcount++; break; } //Need a count, else the flags do not update. } // Fix up vi15 const info for propagation through blocks From b76c57b37c3220a09850f637e8950220548e03ef Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Thu, 21 Feb 2013 21:27:25 +0000 Subject: [PATCH 18/81] One of the automatic patches for GT4 causes TLB misses. Disabled it for now. (EE full clamping, broke license test nr. 3 here.) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5568 96395faa-99c1-11dd-bbfe-3dabce05a288 --- bin/GameIndex.dbf | 96 +++++++++++++++++++++++------------------------ 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/bin/GameIndex.dbf b/bin/GameIndex.dbf index 939196640..32d9bf80e 100644 --- a/bin/GameIndex.dbf +++ b/bin/GameIndex.dbf @@ -840,7 +840,7 @@ Serial = SCUS-97328 Name = Gran Turismo 4 Region = NTSC-U Compat = 5 -eeClampMode = 3 // Text in races works +//eeClampMode = 3 // Text in races works vuClampMode = 2 // Text in GT mode works --------------------------------------------- Serial = SCUS-97329 @@ -1169,7 +1169,7 @@ Region = NTSC-U Serial = SCUS-97436 Name = Gran Turismo 4 [Online Public Beta] Region = NTSC-U -eeClampMode = 3 // Text in races works +//eeClampMode = 3 // Text in races works vuClampMode = 2 // Text in GT mode works --------------------------------------------- Serial = SCUS-97437 @@ -10908,7 +10908,7 @@ Region = NTSC-U Serial = PAPX-90512 Name = Gran Turismo 4 - Toyota Prius [Trial] Region = NTSC-J -eeClampMode = 3 // Text in races works +//eeClampMode = 3 // Text in races works vuClampMode = 2 // Text in GT mode works --------------------------------------------- Serial = PBPX-95503 @@ -10932,39 +10932,39 @@ Serial = PBPX-95524 Name = Gran Turismo 4 - Prologue Region = NTSC-Unk Compat = 5 -eeClampMode = 3 // Text in races works +//eeClampMode = 3 // Text in races works vuClampMode = 2 // Text in GT mode works -[patches = CA6243B9] +//[patches = CA6243B9] +// +// comment=patches by Nachbrenner - comment=patches by Nachbrenner - - //fix IPU DMA - patch=1,EE,00166814,word,00000000 - patch=1,EE,003a36b8,word,00000000 - patch=1,EE,003a36f4,word,00000000 - //Skip Videos - patch=1,EE,001e3718,word,03e00008 - patch=1,EE,001e371c,word,00000000 - -[/patches] +// //fix IPU DMA +// patch=1,EE,00166814,word,00000000 +// patch=1,EE,003a36b8,word,00000000 +// patch=1,EE,003a36f4,word,00000000 +// //Skip Videos +// patch=1,EE,001e3718,word,03e00008 +// patch=1,EE,001e371c,word,00000000 +// +//[/patches] --------------------------------------------- Serial = PCPX-96649 Name = Gran Turismo 4 [Demo] Region = NTSC-J Compat = 4 -eeClampMode = 3 // Text in races works +//eeClampMode = 3 // Text in races works vuClampMode = 2 // Text in GT mode works -[patches = E906EA37] - - comment=patches by mdr61 - - //Timelimit counter stop - patch=0,EE,002EF740,word,00000000 - //Pause counter stop - patch=0,EE,002C7394,word,00000000 - patch=0,EE,002F1F40,word,00000000 - -[/patches] +//[patches = E906EA37] +// +// comment=patches by mdr61 +// +// //Timelimit counter stop +// patch=0,EE,002EF740,word,00000000 +// //Pause counter stop +// patch=0,EE,002C7394,word,00000000 +// patch=0,EE,002F1F40,word,00000000 +// +//[/patches] --------------------------------------------- Serial = SCAJ-10001 Name = Makai Senki Disgaea @@ -11249,7 +11249,7 @@ Region = NTSC-Unk Serial = SCAJ-20066 Name = Gran Turismo 4 - Prologue Region = NTSC-Unk -eeClampMode = 3 // Text in races works +//eeClampMode = 3 // Text in races works vuClampMode = 2 // Text in GT mode works --------------------------------------------- Serial = SCAJ-20067 @@ -11825,28 +11825,28 @@ Region = NTSC-Unk Serial = SCAJ-30006 Name = Gran Turismo 4 Region = NTSC-Unk -eeClampMode = 3 // Text in races works +//eeClampMode = 3 // Text in races works vuClampMode = 2 // Text in GT mode works --------------------------------------------- Serial = SCAJ-30007 Name = Gran Turismo 4 Region = NTSC-Unk Compat = 5 -eeClampMode = 3 // Text in races works +//eeClampMode = 3 // Text in races works vuClampMode = 2 // Text in GT mode works -[patches = 7ABDBB5E] - - comment=patches by nachbrenner - - //skip Videos - patch=1,EE,00100D84,word,24100001 - -[/patches] +//[patches = 7ABDBB5E] +// +// comment=patches by nachbrenner +// +// //skip Videos +// patch=1,EE,00100D84,word,24100001 +// +//[/patches] --------------------------------------------- Serial = SCAJ-30008 Name = Gran Turismo 4 [PlayStation 2 The Best] Region = NTSC-Unk -eeClampMode = 3 // Text in races works +//eeClampMode = 3 // Text in races works vuClampMode = 2 // Text in GT mode works --------------------------------------------- Serial = SCAJ-30010 @@ -11923,7 +11923,7 @@ VIF1StallHack = 1 //HUD Serial = SCKA-20022 Name = Gran Turismo 4 Prologue Region = NTSC-K -eeClampMode = 3 // Text in races works +//eeClampMode = 3 // Text in races works vuClampMode = 2 // Text in GT mode works --------------------------------------------- Serial = SCKA-20023 @@ -12172,7 +12172,7 @@ Region = NTSC-K Serial = SCKA-30001 Name = Gran Turismo 4 Region = NTSC-K -eeClampMode = 3 // Text in races works +//eeClampMode = 3 // Text in races works vuClampMode = 2 // Text in GT mode works --------------------------------------------- Serial = SCKA-30002 @@ -12584,7 +12584,7 @@ Region = NTSC-J Serial = SCPS-15055 Name = Gran Turismo 4 - Prologue Region = NTSC-J -eeClampMode = 3 // Text in races works +//eeClampMode = 3 // Text in races works vuClampMode = 2 // Text in GT mode works --------------------------------------------- Serial = SCPS-15056 @@ -12863,7 +12863,7 @@ Serial = SCPS-17001 Name = Gran Turismo 4 Region = NTSC-J Compat = 5 -eeClampMode = 3 // Text in races works +//eeClampMode = 3 // Text in races works vuClampMode = 2 // Text in GT mode works --------------------------------------------- Serial = SCPS-17002 @@ -12991,7 +12991,7 @@ Region = NTSC-J Serial = SCPS-19252 Name = Gran Turismo 4 [PlayStation 2 The Best] Region = NTSC-J -eeClampMode = 3 // Text in races works +//eeClampMode = 3 // Text in races works vuClampMode = 2 // Text in GT mode works --------------------------------------------- Serial = SCPS-19253 @@ -13013,7 +13013,7 @@ Region = NTSC-J Serial = SCPS-19304 Name = Gran Turismo 4 - Prologue [PlayStation 2 The Best] Region = NTSC-J -eeClampMode = 3 // Text in races works +//eeClampMode = 3 // Text in races works vuClampMode = 2 // Text in GT mode works --------------------------------------------- Serial = SCPS-19305 @@ -30105,7 +30105,7 @@ Serial = SCES-51719 Name = Gran Turismo 4 Region = PAL-Unk Compat = 5 -eeClampMode = 3 // Text in races works +//eeClampMode = 3 // Text in races works vuClampMode = 2 // Text in GT mode works --------------------------------------------- Serial = SCES-51725 @@ -30288,7 +30288,7 @@ Serial = SCES-52438 Name = Gran Turismo 4 - Prologue Region = PAL-Unk Compat = 5 -eeClampMode = 3 // Text in races works +//eeClampMode = 3 // Text in races works vuClampMode = 2 // Text in GT mode works --------------------------------------------- Serial = SCES-52456 From 4cada4d0ff7af6d0608461b139e84d65eb531f3e Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Fri, 22 Feb 2013 16:30:59 +0000 Subject: [PATCH 19/81] microVU: Fixed random Unknown Opcode messages. Turns out the bios blanket writes MOV VF00, VF00 and NOP (for lower, upper respectively) ops to the VU's on boot, apparently some game designers new this and just left it being ran as part of their programs. Our problem being is it was writing it to the VU MicroMem in the wrong order! All fixed now :) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5569 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/Memory.cpp | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/pcsx2/Memory.cpp b/pcsx2/Memory.cpp index 1ad1469d6..e7fe6a6db 100644 --- a/pcsx2/Memory.cpp +++ b/pcsx2/Memory.cpp @@ -446,24 +446,28 @@ template static __fi void ClearVuFunc(u32 addr, u32 size) { template static mem8_t __fc vuMicroRead8(u32 addr) { VURegs* vu = vunum ? &VU1 : &VU0; addr &= vunum ? 0x3fff: 0xfff; + if (vunum && THREAD_VU1) vu1Thread.WaitVU(); return vu->Micro[addr]; } template static mem16_t __fc vuMicroRead16(u32 addr) { VURegs* vu = vunum ? &VU1 : &VU0; addr &= vunum ? 0x3fff: 0xfff; + if (vunum && THREAD_VU1) vu1Thread.WaitVU(); return *(u16*)&vu->Micro[addr]; } template static mem32_t __fc vuMicroRead32(u32 addr) { VURegs* vu = vunum ? &VU1 : &VU0; addr &= vunum ? 0x3fff: 0xfff; + if (vunum && THREAD_VU1) vu1Thread.WaitVU(); return *(u32*)&vu->Micro[addr]; } template static void __fc vuMicroRead64(u32 addr,mem64_t* data) { VURegs* vu = vunum ? &VU1 : &VU0; addr &= vunum ? 0x3fff: 0xfff; + if (vunum && THREAD_VU1) vu1Thread.WaitVU(); *data=*(u64*)&vu->Micro[addr]; } @@ -471,6 +475,7 @@ template static void __fc vuMicroRead128(u32 addr,mem128_t* data) { VURegs* vu = vunum ? &VU1 : &VU0; addr &= vunum ? 0x3fff: 0xfff; if (vunum && THREAD_VU1) vu1Thread.WaitVU(); + CopyQWC(data,&vu->Micro[addr]); } @@ -479,6 +484,7 @@ template static void __fc vuMicroRead128(u32 addr,mem128_t* data) { template static void __fc vuMicroWrite8(u32 addr,mem8_t data) { VURegs* vu = vunum ? &VU1 : &VU0; addr &= vunum ? 0x3fff: 0xfff; + if (vunum && THREAD_VU1) { vu1Thread.WriteMicroMem(addr, &data, sizeof(u8)); return; @@ -491,6 +497,7 @@ template static void __fc vuMicroWrite8(u32 addr,mem8_t data) { template static void __fc vuMicroWrite16(u32 addr, mem16_t data) { VURegs* vu = vunum ? &VU1 : &VU0; addr &= vunum ? 0x3fff: 0xfff; + if (vunum && THREAD_VU1) { vu1Thread.WriteMicroMem(addr, &data, sizeof(u16)); return; @@ -503,6 +510,7 @@ template static void __fc vuMicroWrite16(u32 addr, mem16_t data) { template static void __fc vuMicroWrite32(u32 addr, mem32_t data) { VURegs* vu = vunum ? &VU1 : &VU0; addr &= vunum ? 0x3fff: 0xfff; + if (vunum && THREAD_VU1) { vu1Thread.WriteMicroMem(addr, &data, sizeof(u32)); return; @@ -515,25 +523,33 @@ template static void __fc vuMicroWrite32(u32 addr, mem32_t data) { template static void __fc vuMicroWrite64(u32 addr, const mem64_t* data) { VURegs* vu = vunum ? &VU1 : &VU0; addr &= vunum ? 0x3fff: 0xfff; + u64 tempdata; + tempdata = (data[0] >> 32) | (data[0] << 32); //VU stores it in a different order + if (vunum && THREAD_VU1) { - vu1Thread.WriteMicroMem(addr, (void*)data, sizeof(u64)); + vu1Thread.WriteMicroMem(addr, &tempdata, sizeof(u64)); return; } - if (*(u64*)&vu->Micro[addr]!=data[0]) { + + if (*(u64*)&vu->Micro[addr]!=tempdata) { ClearVuFunc(addr, 8); - *(u64*)&vu->Micro[addr] =data[0]; + *(u64*)&vu->Micro[addr] =tempdata; } } template static void __fc vuMicroWrite128(u32 addr, const mem128_t* data) { VURegs* vu = vunum ? &VU1 : &VU0; addr &= vunum ? 0x3fff: 0xfff; + mem128_t tempdata; + tempdata.lo = (data->lo >> 32) | (data->lo << 32); //VU stores it in a different order + tempdata.hi = (data->hi >> 32) | (data->hi << 32); //VU stores it in a different order + if (vunum && THREAD_VU1) { - vu1Thread.WriteMicroMem(addr, (void*)data, sizeof(u128)); + vu1Thread.WriteMicroMem(addr, &tempdata, sizeof(u128)); return; } - if ((u128&)vu->Micro[addr]!=*data) { + if ((u128&)vu->Micro[addr]!=tempdata) { //Hmm, is that right? ClearVuFunc(addr, 16); - CopyQWC(&vu->Micro[addr],data); + CopyQWC(&vu->Micro[addr],&tempdata); } } From d3d9b520f027a666e84d118bf50903f4d7628845 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Sat, 23 Feb 2013 15:35:56 +0000 Subject: [PATCH 20/81] gsdx ogl: * port KrossX patch from r5556 to openGL * add a basic gui entry, would love an additional description * also add the pointsampler hack but don't activate it yet git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5570 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSDeviceOGL.h | 3 +++ plugins/GSdx/GSLinuxDialog.cpp | 42 ++++++++++++++++++++++++++------- plugins/GSdx/GSRendererOGL.cpp | 15 ++++++++---- plugins/GSdx/GSRendererOGL.h | 4 +++- plugins/GSdx/GSTextureFXOGL.cpp | 4 +++- plugins/GSdx/res/tfx.glsl | 25 ++++++++++++++++---- 6 files changed, 73 insertions(+), 20 deletions(-) diff --git a/plugins/GSdx/GSDeviceOGL.h b/plugins/GSdx/GSDeviceOGL.h index 0de576a9d..195e6697f 100644 --- a/plugins/GSdx/GSDeviceOGL.h +++ b/plugins/GSdx/GSDeviceOGL.h @@ -301,6 +301,8 @@ class GSDeviceOGL : public GSDevice GSVector4 MinF_TA; GSVector4i MskFix; + GSVector4 TC_OffsetHack; + PSConstantBuffer() { FogColor_AREF = GSVector4::zero(); @@ -380,6 +382,7 @@ class GSDeviceOGL : public GSDevice uint32 colclip:2; uint32 date:2; uint32 spritehack:1; + uint32 tcoffsethack:1; uint32 point_sampler:1; }; diff --git a/plugins/GSdx/GSLinuxDialog.cpp b/plugins/GSdx/GSLinuxDialog.cpp index 65ecbd1b7..c74b0cc82 100644 --- a/plugins/GSdx/GSLinuxDialog.cpp +++ b/plugins/GSdx/GSLinuxDialog.cpp @@ -29,8 +29,6 @@ GtkWidget *shadeboost_check, *paltex_check, *fba_check, *aa_check, *native_res_ GtkWidget *sb_contrast, *sb_brightness, *sb_saturation; GtkWidget *resx_spin, *resy_spin; -GtkWidget *hack_alpha_check, *hack_offset_check, *hack_skipdraw_spin, *hack_msaa_check, *hack_sprite_check, * hack_wild_check, *hack_enble_check; - static void SysMessage(const char *fmt, ...) { va_list list; @@ -212,6 +210,21 @@ void toggle_widget_states( GtkWidget *widget, gpointer callback_data ) } } +void set_hex_entry(GtkWidget *text_box, int hex_value) { + gchar* data=(gchar *)g_malloc(sizeof(gchar)*40); + sprintf(data,"%X", hex_value); + gtk_entry_set_text(GTK_ENTRY(text_box),data); +} + +int get_hex_entry(GtkWidget *text_box) { + int hex_value = 0; + const gchar *data = gtk_entry_get_text(GTK_ENTRY(text_box)); + + sscanf(data,"%X",&hex_value); + + return hex_value; +} + bool RunLinuxDialog() { GtkWidget *dialog; @@ -222,6 +235,9 @@ bool RunLinuxDialog() GtkWidget *interlace_label, *threads_label, *native_label, *msaa_label, *rexy_label, *render_label, *filter_label; GtkWidget *hack_table, *hack_skipdraw_label, *hack_box, *hack_frame; + GtkWidget *hack_alpha_check, *hack_offset_check, *hack_skipdraw_spin, *hack_msaa_check, *hack_sprite_check, * hack_wild_check, *hack_enble_check; + GtkWidget *hack_tco_label, *hack_tco_entry; + int return_value; GdkPixbuf* logo_pixmap; @@ -324,15 +340,20 @@ bool RunLinuxDialog() gtk_box_pack_start(GTK_BOX(resxy_box), resy_spin, false, false, 5); // Create our hack settings. - hack_alpha_check = gtk_check_button_new_with_label("Alpha Hack"); - hack_offset_check = gtk_check_button_new_with_label("Offset Hack"); + hack_alpha_check = gtk_check_button_new_with_label("Alpha Hack"); + hack_offset_check = gtk_check_button_new_with_label("Offset Hack"); hack_skipdraw_label = gtk_label_new("Skipdraw:"); - hack_skipdraw_spin = gtk_spin_button_new_with_range(0,1000,1); - hack_enble_check = gtk_check_button_new_with_label("Enable User Hacks"); - hack_wild_check = gtk_check_button_new_with_label("Wild arm Hack"); - hack_sprite_check = gtk_check_button_new_with_label("Sprite Hack"); - hack_msaa_check = gtk_check_button_new_with_label("Msaa Hack"); + hack_skipdraw_spin = gtk_spin_button_new_with_range(0,1000,1); + hack_enble_check = gtk_check_button_new_with_label("Enable User Hacks"); + hack_wild_check = gtk_check_button_new_with_label("Wild arm Hack"); + hack_sprite_check = gtk_check_button_new_with_label("Sprite Hack"); + hack_msaa_check = gtk_check_button_new_with_label("Msaa Hack"); + hack_tco_label = gtk_label_new("Texture offset: 0x"); + hack_tco_entry = gtk_entry_new(); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(hack_skipdraw_spin), theApp.GetConfig("UserHacks_SkipDraw", 0)); + set_hex_entry(hack_tco_entry, theApp.GetConfig("UserHacks_TCOffset", 0)); + // Tables are strange. The numbers are for their position: left, right, top, bottom. gtk_table_attach_defaults(GTK_TABLE(hack_table), hack_alpha_check, 0, 1, 0, 1); gtk_table_attach_defaults(GTK_TABLE(hack_table), hack_offset_check, 1, 2, 0, 1); @@ -342,6 +363,8 @@ bool RunLinuxDialog() //gtk_table_attach_defaults(GTK_TABLE(hack_table), hack_msaa_check, 2, 3, 1, 2); gtk_table_attach_defaults(GTK_TABLE(hack_table), hack_skipdraw_label, 0, 1, 2, 3); gtk_table_attach_defaults(GTK_TABLE(hack_table), hack_skipdraw_spin, 1, 2, 2, 3); + gtk_table_attach_defaults(GTK_TABLE(hack_table), hack_tco_label, 0, 1, 3, 4); + gtk_table_attach_defaults(GTK_TABLE(hack_table), hack_tco_entry, 1, 2, 3, 4); // Create our checkboxes. shadeboost_check = gtk_check_button_new_with_label("Shade boost"); @@ -473,6 +496,7 @@ bool RunLinuxDialog() theApp.SetConfig("UserHacks_WildHack", (int)gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(hack_wild_check))); theApp.SetConfig("UserHacks_SpriteHack", (int)gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(hack_sprite_check))); theApp.SetConfig("UserHacks", (int)gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(hack_enble_check))); + theApp.SetConfig("UserHacks_TCOffset", get_hex_entry(hack_tco_entry)); // Let's just be windowed for the moment. theApp.SetConfig("windowed", 1); diff --git a/plugins/GSdx/GSRendererOGL.cpp b/plugins/GSdx/GSRendererOGL.cpp index e8ebcb303..0fe4dd2cb 100644 --- a/plugins/GSdx/GSRendererOGL.cpp +++ b/plugins/GSdx/GSRendererOGL.cpp @@ -32,6 +32,10 @@ GSRendererOGL::GSRendererOGL() UserHacks_WildHack = !!theApp.GetConfig("UserHacks", 0) ? theApp.GetConfig("UserHacks_WildHack", 0) : 0; UserHacks_AlphaStencil = !!theApp.GetConfig("UserHacks_AlphaStencil", 0) && !!theApp.GetConfig("UserHacks", 0); m_pixelcenter = GSVector2(-0.5f, -0.5f); + + UserHacks_TCOffset = !!theApp.GetConfig("UserHacks", 0) ? theApp.GetConfig("UserHacks_TCOffset", 0) : 0; + UserHacks_TCO_x = (UserHacks_TCOffset & 0xFFFF) / -1000.0f; + UserHacks_TCO_y = ((UserHacks_TCOffset >> 16) & 0xFFFF) / -1000.0f; } bool GSRendererOGL::CreateDevice(GSDevice* dev) @@ -60,7 +64,7 @@ void GSRendererOGL::SetupIA() for(unsigned int i = 0; i < m_vertex.next; i++, d++) if(PRIM->TME && PRIM->FST) - d->UV &= UserHacks_WildHack == 1 ? 0x3FEF3FEF : 0x3FF73FF7; + d->UV &= 0x3FEF3FEF; } dev->IAUnmapVertexBuffer(); @@ -353,10 +357,7 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour ps_sel.wms = context->CLAMP.WMS; ps_sel.wmt = context->CLAMP.WMT; - if (tex->m_palette) - ps_sel.fmt = cpsm.fmt | 4; - else - ps_sel.fmt = cpsm.fmt; + ps_sel.fmt = tex->m_palette ? cpsm.fmt | 4 : cpsm.fmt; ps_sel.aem = env.TEXA.AEM; ps_sel.tfx = context->TEX0.TFX; ps_sel.tcc = context->TEX0.TCC; @@ -385,6 +386,10 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour ps_cb.HalfTexel = GSVector4(-0.5f, 0.5f).xxyy() / WH.zwzw(); ps_cb.MskFix = GSVector4i(context->CLAMP.MINU, context->CLAMP.MINV, context->CLAMP.MAXU, context->CLAMP.MAXV); + // TC Offset Hack + ps_sel.tcoffsethack = !!UserHacks_TCOffset; + ps_cb.TC_OffsetHack = GSVector4(UserHacks_TCO_x, UserHacks_TCO_y).xyxy() / WH.xyxy(); + GSVector4 clamp(ps_cb.MskFix); GSVector4 ta(env.TEXA & GSVector4i::x000000ff()); diff --git a/plugins/GSdx/GSRendererOGL.h b/plugins/GSdx/GSRendererOGL.h index fe815d199..502f699d8 100644 --- a/plugins/GSdx/GSRendererOGL.h +++ b/plugins/GSdx/GSRendererOGL.h @@ -39,7 +39,9 @@ class GSRendererOGL : public GSRendererHW bool m_fba; bool UserHacks_AlphaHack; bool UserHacks_AlphaStencil; - int UserHacks_WildHack; + unsigned int UserHacks_WildHack; + unsigned int UserHacks_TCOffset; + float UserHacks_TCO_x, UserHacks_TCO_y; protected: void SetupIA(); diff --git a/plugins/GSdx/GSTextureFXOGL.cpp b/plugins/GSdx/GSTextureFXOGL.cpp index c2835005b..ab062688b 100644 --- a/plugins/GSdx/GSTextureFXOGL.cpp +++ b/plugins/GSdx/GSTextureFXOGL.cpp @@ -153,7 +153,9 @@ void GSDeviceOGL::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerS + format("#define PS_LTF %d\n", sel.ltf) + format("#define PS_COLCLIP %d\n", sel.colclip) + format("#define PS_DATE %d\n", sel.date) - + format("#define PS_SPRITEHACK %d\n", sel.spritehack); + + format("#define PS_SPRITEHACK %d\n", sel.spritehack) + + format("#define PS_TCOFFSETHACK %d\n", sel.tcoffsethack) + + format("#define PS_POINT_SAMPLER %d\n", sel.point_sampler); CompileShaderFromSource("tfx.glsl", "ps_main", GL_FRAGMENT_SHADER, &ps, macro); diff --git a/plugins/GSdx/res/tfx.glsl b/plugins/GSdx/res/tfx.glsl index 127014ca4..85c1cb732 100644 --- a/plugins/GSdx/res/tfx.glsl +++ b/plugins/GSdx/res/tfx.glsl @@ -7,6 +7,10 @@ #define FMT_16 2 #define FMT_PAL 4 /* flag bit */ +// Not sure we have same issue on opengl. Doesn't work anyway on ATI card +// And I say this as an ATI user. +#define ATI_SUCKS 0 + #ifndef VS_BPPZ #define VS_BPPZ 0 #define VS_TME 1 @@ -36,6 +40,8 @@ #define PS_COLCLIP 0 #define PS_DATE 0 #define PS_SPRITEHACK 0 +#define PS_POINT_SAMPLER 0 +#define PS_TCOFFSETHACK 0 #endif struct vertex @@ -282,10 +288,22 @@ layout(std140, binding = 5) uniform cb1 vec2 MinF; vec2 TA; uvec4 MskFix; + vec4 TC_OffsetHack; }; vec4 sample_c(vec2 uv) { + // FIXME: check the issue on openGL + if (ATI_SUCKS == 1 && PS_POINT_SAMPLER == 1) + { + // Weird issue with ATI cards (happens on at least HD 4xxx and 5xxx), + // it looks like they add 127/128 of a texel to sampling coordinates + // occasionally causing point sampling to erroneously round up. + // I'm manually adjusting coordinates to the centre of texels here, + // though the centre is just paranoia, the top left corner works fine. + uv = (trunc(uv * WH.zw) + vec2(0.5, 0.5)) / WH.zw; + } + // FIXME I'm not sure it is a good solution to flip texture return texture(TextureSampler, uv); //FIXME another way to FLIP vertically @@ -403,10 +421,9 @@ mat4 sample_4p(vec4 u) vec4 sample_color(vec2 st, float q) { - if(PS_FST == 0) - { - st /= q; - } + if(PS_FST == 0) st /= q; + + if(PS_TCOFFSETHACK == 1) st += TC_OffsetHack.xy; vec4 t; mat4 c; From 3f27730f457d150a25b503d3463c07fb2c7cb2c2 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Sun, 24 Feb 2013 14:37:30 +0000 Subject: [PATCH 21/81] Fixed up my changes from r5569. Change it so it only reverses the order during the bios writes to VU memory. FFXII is fine again, games still not have the unknown op problems, also TOCA 3 no longer has the illegal opcode errors. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5571 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/Memory.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/pcsx2/Memory.cpp b/pcsx2/Memory.cpp index e7fe6a6db..4f820b101 100644 --- a/pcsx2/Memory.cpp +++ b/pcsx2/Memory.cpp @@ -524,8 +524,12 @@ template static void __fc vuMicroWrite64(u32 addr, const mem64_t* dat VURegs* vu = vunum ? &VU1 : &VU0; addr &= vunum ? 0x3fff: 0xfff; u64 tempdata; - tempdata = (data[0] >> 32) | (data[0] << 32); //VU stores it in a different order - + + if(cpuRegs.pc == 0x8000dff0) + tempdata = (data[0] >> 32) | (data[0] << 32); //BIOS writes them in the wrong order apparently... + else + tempdata = data[0]; + if (vunum && THREAD_VU1) { vu1Thread.WriteMicroMem(addr, &tempdata, sizeof(u64)); return; @@ -539,17 +543,14 @@ template static void __fc vuMicroWrite64(u32 addr, const mem64_t* dat template static void __fc vuMicroWrite128(u32 addr, const mem128_t* data) { VURegs* vu = vunum ? &VU1 : &VU0; addr &= vunum ? 0x3fff: 0xfff; - mem128_t tempdata; - tempdata.lo = (data->lo >> 32) | (data->lo << 32); //VU stores it in a different order - tempdata.hi = (data->hi >> 32) | (data->hi << 32); //VU stores it in a different order if (vunum && THREAD_VU1) { - vu1Thread.WriteMicroMem(addr, &tempdata, sizeof(u128)); + vu1Thread.WriteMicroMem(addr, (void*)data, sizeof(u128)); return; } - if ((u128&)vu->Micro[addr]!=tempdata) { //Hmm, is that right? + if ((u128&)vu->Micro[addr]!=*data) { //Hmm, is that right? ClearVuFunc(addr, 16); - CopyQWC(&vu->Micro[addr],&tempdata); + CopyQWC(&vu->Micro[addr],data); } } From 64474926f140f32ef2c380e674f0677744c365cd Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Sun, 24 Feb 2013 15:24:28 +0000 Subject: [PATCH 22/81] As previous commit - But check anywhere in the BIOS. It varies, the address i used was for Europe 1.7 only >.< git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5572 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/Memory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pcsx2/Memory.cpp b/pcsx2/Memory.cpp index 4f820b101..1b292b117 100644 --- a/pcsx2/Memory.cpp +++ b/pcsx2/Memory.cpp @@ -525,7 +525,7 @@ template static void __fc vuMicroWrite64(u32 addr, const mem64_t* dat addr &= vunum ? 0x3fff: 0xfff; u64 tempdata; - if(cpuRegs.pc == 0x8000dff0) + if(cpuRegs.pc >= 0x80000000 && cpuRegs.pc < 0x82000000) tempdata = (data[0] >> 32) | (data[0] << 32); //BIOS writes them in the wrong order apparently... else tempdata = data[0]; From 6255f7d8a8531c9f303cda3f6d3982d755ab9209 Mon Sep 17 00:00:00 2001 From: gigaherz Date: Sun, 24 Feb 2013 17:37:17 +0000 Subject: [PATCH 23/81] Updated zlib to 1.2.7. I skipped updating the CMakeLists.txt because ours is probably set up to work with the rest of the project.+ This probably doesn't fix anything important. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5573 96395faa-99c1-11dd-bbfe-3dabce05a288 --- 3rdparty/zlib/ChangeLog | 2539 +++++++++++++++++++++----------------- 3rdparty/zlib/FAQ | 734 +++++------ 3rdparty/zlib/README | 229 ++-- 3rdparty/zlib/adler32.c | 68 +- 3rdparty/zlib/crc32.c | 85 +- 3rdparty/zlib/crc32.h | 2 +- 3rdparty/zlib/deflate.c | 257 +++- 3rdparty/zlib/deflate.h | 32 +- 3rdparty/zlib/gzguts.h | 113 +- 3rdparty/zlib/gzlib.c | 179 ++- 3rdparty/zlib/gzread.c | 417 +++---- 3rdparty/zlib/gzwrite.c | 146 ++- 3rdparty/zlib/infback.c | 14 +- 3rdparty/zlib/inffast.c | 4 +- 3rdparty/zlib/inffast.h | 4 +- 3rdparty/zlib/inffixed.h | 6 +- 3rdparty/zlib/inflate.c | 90 +- 3rdparty/zlib/inftrees.c | 48 +- 3rdparty/zlib/inftrees.h | 4 +- 3rdparty/zlib/trees.c | 55 +- 3rdparty/zlib/trees.h | 4 +- 3rdparty/zlib/zconf.h | 210 +++- 3rdparty/zlib/zlib.h | 339 +++-- 3rdparty/zlib/zutil.c | 46 +- 3rdparty/zlib/zutil.h | 133 +- 25 files changed, 3233 insertions(+), 2525 deletions(-) diff --git a/3rdparty/zlib/ChangeLog b/3rdparty/zlib/ChangeLog index 64d60661a..c2c643a1a 100644 --- a/3rdparty/zlib/ChangeLog +++ b/3rdparty/zlib/ChangeLog @@ -1,1130 +1,1409 @@ - - ChangeLog file for zlib - -Changes in 1.2.4 (14 Mar 2010) -- Fix VER3 extraction in configure for no fourth subversion -- Update zlib.3, add docs to Makefile.in to make .pdf out of it -- Add zlib.3.pdf to distribution -- Don't set error code in gzerror() if passed pointer is NULL -- Apply destination directory fixes to CMakeLists.txt [Lowman] -- Move #cmakedefine's to a new zconf.in.cmakein -- Restore zconf.h for builds that don't use configure or cmake -- Add distclean to dummy Makefile for convenience -- Update and improve INDEX, README, and FAQ -- Update CMakeLists.txt for the return of zconf.h [Lowman] -- Update contrib/vstudio/vc9 and vc10 [Vollant] -- Change libz.dll.a back to libzdll.a in win32/Makefile.gcc -- Apply license and readme changes to contrib/asm686 [Raiter] -- Check file name lengths and add -c option in minigzip.c [Li] -- Update contrib/amd64 and contrib/masmx86/ [Vollant] -- Avoid use of "eof" parameter in trees.c to not shadow library variable -- Update make_vms.com for removal of zlibdefs.h [Zinser] -- Update assembler code and vstudio projects in contrib [Vollant] -- Remove outdated assembler code contrib/masm686 and contrib/asm586 -- Remove old vc7 and vc8 from contrib/vstudio -- Update win32/Makefile.msc, add ZLIB_VER_SUBREVISION [Rowe] -- Fix memory leaks in gzclose_r() and gzclose_w(), file leak in gz_open() -- Add contrib/gcc_gvmat64 for longest_match and inflate_fast [Vollant] -- Remove *64 functions from win32/zlib.def (they're not 64-bit yet) -- Fix bug in void-returning vsprintf() case in gzwrite.c -- Fix name change from inflate.h in contrib/inflate86/inffas86.c -- Check if temporary file exists before removing in make_vms.com [Zinser] -- Fix make install and uninstall for --static option -- Fix usage of _MSC_VER in gzguts.h and zutil.h [Truta] -- Update readme.txt in contrib/masmx64 and masmx86 to assemble - -Changes in 1.2.3.9 (21 Feb 2010) -- Expunge gzio.c -- Move as400 build information to old -- Fix updates in contrib/minizip and contrib/vstudio -- Add const to vsnprintf test in configure to avoid warnings [Weigelt] -- Delete zconf.h (made by configure) [Weigelt] -- Change zconf.in.h to zconf.h.in per convention [Weigelt] -- Check for NULL buf in gzgets() -- Return empty string for gzgets() with len == 1 (like fgets()) -- Fix description of gzgets() in zlib.h for end-of-file, NULL return -- Update minizip to 1.1 [Vollant] -- Avoid MSVC loss of data warnings in gzread.c, gzwrite.c -- Note in zlib.h that gzerror() should be used to distinguish from EOF -- Remove use of snprintf() from gzlib.c -- Fix bug in gzseek() -- Update contrib/vstudio, adding vc9 and vc10 [Kuno, Vollant] -- Fix zconf.h generation in CMakeLists.txt [Lowman] -- Improve comments in zconf.h where modified by configure - -Changes in 1.2.3.8 (13 Feb 2010) -- Clean up text files (tabs, trailing whitespace, etc.) [Oberhumer] -- Use z_off64_t in gz_zero() and gz_skip() to match state->skip -- Avoid comparison problem when sizeof(int) == sizeof(z_off64_t) -- Revert to Makefile.in from 1.2.3.6 (live with the clutter) -- Fix missing error return in gzflush(), add zlib.h note -- Add *64 functions to zlib.map [Levin] -- Fix signed/unsigned comparison in gz_comp() -- Use SFLAGS when testing shared linking in configure -- Add --64 option to ./configure to use -m64 with gcc -- Fix ./configure --help to correctly name options -- Have make fail if a test fails [Levin] -- Avoid buffer overrun in contrib/masmx64/gvmat64.asm [Simpson] -- Remove assembler object files from contrib - -Changes in 1.2.3.7 (24 Jan 2010) -- Always gzopen() with O_LARGEFILE if available -- Fix gzdirect() to work immediately after gzopen() or gzdopen() -- Make gzdirect() more precise when the state changes while reading -- Improve zlib.h documentation in many places -- Catch memory allocation failure in gz_open() -- Complete close operation if seek forward in gzclose_w() fails -- Return Z_ERRNO from gzclose_r() if close() fails -- Return Z_STREAM_ERROR instead of EOF for gzclose() being passed NULL -- Return zero for gzwrite() errors to match zlib.h description -- Return -1 on gzputs() error to match zlib.h description -- Add zconf.in.h to allow recovery from configure modification [Weigelt] -- Fix static library permissions in Makefile.in [Weigelt] -- Avoid warnings in configure tests that hide functionality [Weigelt] -- Add *BSD and DragonFly to Linux case in configure [gentoo 123571] -- Change libzdll.a to libz.dll.a in win32/Makefile.gcc [gentoo 288212] -- Avoid access of uninitialized data for first inflateReset2 call [Gomes] -- Keep object files in subdirectories to reduce the clutter somewhat -- Remove default Makefile and zlibdefs.h, add dummy Makefile -- Add new external functions to Z_PREFIX, remove duplicates, z_z_ -> z_ -- Remove zlibdefs.h completely -- modify zconf.h instead - -Changes in 1.2.3.6 (17 Jan 2010) -- Avoid void * arithmetic in gzread.c and gzwrite.c -- Make compilers happier with const char * for gz_error message -- Avoid unused parameter warning in inflate.c -- Avoid signed-unsigned comparison warning in inflate.c -- Indent #pragma's for traditional C -- Fix usage of strwinerror() in glib.c, change to gz_strwinerror() -- Correct email address in configure for system options -- Update make_vms.com and add make_vms.com to contrib/minizip [Zinser] -- Update zlib.map [Brown] -- Fix Makefile.in for Solaris 10 make of example64 and minizip64 [Tšršk] -- Apply various fixes to CMakeLists.txt [Lowman] -- Add checks on len in gzread() and gzwrite() -- Add error message for no more room for gzungetc() -- Remove zlib version check in gzwrite() -- Defer compression of gzprintf() result until need to -- Use snprintf() in gzdopen() if available -- Remove USE_MMAP configuration determination (only used by minigzip) -- Remove examples/pigz.c (available separately) -- Update examples/gun.c to 1.6 - -Changes in 1.2.3.5 (8 Jan 2010) -- Add space after #if in zutil.h for some compilers -- Fix relatively harmless bug in deflate_fast() [Exarevsky] -- Fix same problem in deflate_slow() -- Add $(SHAREDLIBV) to LIBS in Makefile.in [Brown] -- Add deflate_rle() for faster Z_RLE strategy run-length encoding -- Add deflate_huff() for faster Z_HUFFMAN_ONLY encoding -- Change name of "write" variable in inffast.c to avoid library collisions -- Fix premature EOF from gzread() in gzio.c [Brown] -- Use zlib header window size if windowBits is 0 in inflateInit2() -- Remove compressBound() call in deflate.c to avoid linking compress.o -- Replace use of errno in gz* with functions, support WinCE [Alves] -- Provide alternative to perror() in minigzip.c for WinCE [Alves] -- Don't use _vsnprintf on later versions of MSVC [Lowman] -- Add CMake build script and input file [Lowman] -- Update contrib/minizip to 1.1 [Svensson, Vollant] -- Moved nintendods directory from contrib to . -- Replace gzio.c with a new set of routines with the same functionality -- Add gzbuffer(), gzoffset(), gzclose_r(), gzclose_w() as part of above -- Update contrib/minizip to 1.1b -- Change gzeof() to return 0 on error instead of -1 to agree with zlib.h - -Changes in 1.2.3.4 (21 Dec 2009) -- Use old school .SUFFIXES in Makefile.in for FreeBSD compatibility -- Update comments in configure and Makefile.in for default --shared -- Fix test -z's in configure [Marquess] -- Build examplesh and minigzipsh when not testing -- Change NULL's to Z_NULL's in deflate.c and in comments in zlib.h -- Import LDFLAGS from the environment in configure -- Fix configure to populate SFLAGS with discovered CFLAGS options -- Adapt make_vms.com to the new Makefile.in [Zinser] -- Add zlib2ansi script for C++ compilation [Marquess] -- Add _FILE_OFFSET_BITS=64 test to make test (when applicable) -- Add AMD64 assembler code for longest match to contrib [Teterin] -- Include options from $SFLAGS when doing $LDSHARED -- Simplify 64-bit file support by introducing z_off64_t type -- Make shared object files in objs directory to work around old Sun cc -- Use only three-part version number for Darwin shared compiles -- Add rc option to ar in Makefile.in for when ./configure not run -- Add -WI,-rpath,. to LDFLAGS for OSF 1 V4* -- Set LD_LIBRARYN32_PATH for SGI IRIX shared compile -- Protect against _FILE_OFFSET_BITS being defined when compiling zlib -- Rename Makefile.in targets allstatic to static and allshared to shared -- Fix static and shared Makefile.in targets to be independent -- Correct error return bug in gz_open() by setting state [Brown] -- Put spaces before ;;'s in configure for better sh compatibility -- Add pigz.c (parallel implementation of gzip) to examples/ -- Correct constant in crc32.c to UL [Leventhal] -- Reject negative lengths in crc32_combine() -- Add inflateReset2() function to work like inflateEnd()/inflateInit2() -- Include sys/types.h for _LARGEFILE64_SOURCE [Brown] -- Correct typo in doc/algorithm.txt [Janik] -- Fix bug in adler32_combine() [Zhu] -- Catch missing-end-of-block-code error in all inflates and in puff - Assures that random input to inflate eventually results in an error -- Added enough.c (calculation of ENOUGH for inftrees.h) to examples/ -- Update ENOUGH and its usage to reflect discovered bounds -- Fix gzerror() error report on empty input file [Brown] -- Add ush casts in trees.c to avoid pedantic runtime errors -- Fix typo in zlib.h uncompress() description [Reiss] -- Correct inflate() comments with regard to automatic header detection -- Remove deprecation comment on Z_PARTIAL_FLUSH (it stays) -- Put new version of gzlog (2.0) in examples with interruption recovery -- Add puff compile option to permit invalid distance-too-far streams -- Add puff TEST command options, ability to read piped input -- Prototype the *64 functions in zlib.h when _FILE_OFFSET_BITS == 64, but - _LARGEFILE64_SOURCE not defined -- Fix Z_FULL_FLUSH to truly erase the past by resetting s->strstart -- Fix deflateSetDictionary() to use all 32K for output consistency -- Remove extraneous #define MIN_LOOKAHEAD in deflate.c (in deflate.h) -- Clear bytes after deflate lookahead to avoid use of uninitialized data -- Change a limit in inftrees.c to be more transparent to Coverity Prevent -- Update win32/zlib.def with exported symbols from zlib.h -- Correct spelling error in zlib.h [Willem] -- Allow Z_BLOCK for deflate() to force a new block -- Allow negative bits in inflatePrime() to delete existing bit buffer -- Add Z_TREES flush option to inflate() to return at end of trees -- Add inflateMark() to return current state information for random access -- Add Makefile for NintendoDS to contrib [Costa] -- Add -w in configure compile tests to avoid spurious warnings [Beucler] -- Fix typos in zlib.h comments for deflateSetDictionary() -- Fix EOF detection in transparent gzread() [Maier] - -Changes in 1.2.3.3 (2 October 2006) -- Make --shared the default for configure, add a --static option -- Add compile option to permit invalid distance-too-far streams -- Add inflateUndermine() function which is required to enable above -- Remove use of "this" variable name for C++ compatibility [Marquess] -- Add testing of shared library in make test, if shared library built -- Use ftello() and fseeko() if available instead of ftell() and fseek() -- Provide two versions of all functions that use the z_off_t type for - binary compatibility -- a normal version and a 64-bit offset version, - per the Large File Support Extension when _LARGEFILE64_SOURCE is - defined; use the 64-bit versions by default when _FILE_OFFSET_BITS - is defined to be 64 -- Add a --uname= option to configure to perhaps help with cross-compiling - -Changes in 1.2.3.2 (3 September 2006) -- Turn off silly Borland warnings [Hay] -- Use off64_t and define _LARGEFILE64_SOURCE when present -- Fix missing dependency on inffixed.h in Makefile.in -- Rig configure --shared to build both shared and static [Teredesai, Truta] -- Remove zconf.in.h and instead create a new zlibdefs.h file -- Fix contrib/minizip/unzip.c non-encrypted after encrypted [Vollant] -- Add treebuild.xml (see http://treebuild.metux.de/) [Weigelt] - -Changes in 1.2.3.1 (16 August 2006) -- Add watcom directory with OpenWatcom make files [Daniel] -- Remove #undef of FAR in zconf.in.h for MVS [Fedtke] -- Update make_vms.com [Zinser] -- Use -fPIC for shared build in configure [Teredesai, Nicholson] -- Use only major version number for libz.so on IRIX and OSF1 [Reinholdtsen] -- Use fdopen() (not _fdopen()) for Interix in zutil.h [BŠck] -- Add some FAQ entries about the contrib directory -- Update the MVS question in the FAQ -- Avoid extraneous reads after EOF in gzio.c [Brown] -- Correct spelling of "successfully" in gzio.c [Randers-Pehrson] -- Add comments to zlib.h about gzerror() usage [Brown] -- Set extra flags in gzip header in gzopen() like deflate() does -- Make configure options more compatible with double-dash conventions - [Weigelt] -- Clean up compilation under Solaris SunStudio cc [Rowe, Reinholdtsen] -- Fix uninstall target in Makefile.in [Truta] -- Add pkgconfig support [Weigelt] -- Use $(DESTDIR) macro in Makefile.in [Reinholdtsen, Weigelt] -- Replace set_data_type() with a more accurate detect_data_type() in - trees.c, according to the txtvsbin.txt document [Truta] -- Swap the order of #include and #include "zlib.h" in - gzio.c, example.c and minigzip.c [Truta] -- Shut up annoying VS2005 warnings about standard C deprecation [Rowe, - Truta] (where?) -- Fix target "clean" from win32/Makefile.bor [Truta] -- Create .pdb and .manifest files in win32/makefile.msc [Ziegler, Rowe] -- Update zlib www home address in win32/DLL_FAQ.txt [Truta] -- Update contrib/masmx86/inffas32.asm for VS2005 [Vollant, Van Wassenhove] -- Enable browse info in the "Debug" and "ASM Debug" configurations in - the Visual C++ 6 project, and set (non-ASM) "Debug" as default [Truta] -- Add pkgconfig support [Weigelt] -- Add ZLIB_VER_MAJOR, ZLIB_VER_MINOR and ZLIB_VER_REVISION in zlib.h, - for use in win32/zlib1.rc [Polushin, Rowe, Truta] -- Add a document that explains the new text detection scheme to - doc/txtvsbin.txt [Truta] -- Add rfc1950.txt, rfc1951.txt and rfc1952.txt to doc/ [Truta] -- Move algorithm.txt into doc/ [Truta] -- Synchronize FAQ with website -- Fix compressBound(), was low for some pathological cases [Fearnley] -- Take into account wrapper variations in deflateBound() -- Set examples/zpipe.c input and output to binary mode for Windows -- Update examples/zlib_how.html with new zpipe.c (also web site) -- Fix some warnings in examples/gzlog.c and examples/zran.c (it seems - that gcc became pickier in 4.0) -- Add zlib.map for Linux: "All symbols from zlib-1.1.4 remain - un-versioned, the patch adds versioning only for symbols introduced in - zlib-1.2.0 or later. It also declares as local those symbols which are - not designed to be exported." [Levin] -- Update Z_PREFIX list in zconf.in.h, add --zprefix option to configure -- Do not initialize global static by default in trees.c, add a response - NO_INIT_GLOBAL_POINTERS to initialize them if needed [Marquess] -- Don't use strerror() in gzio.c under WinCE [Yakimov] -- Don't use errno.h in zutil.h under WinCE [Yakimov] -- Move arguments for AR to its usage to allow replacing ar [Marot] -- Add HAVE_VISIBILITY_PRAGMA in zconf.in.h for Mozilla [Randers-Pehrson] -- Improve inflateInit() and inflateInit2() documentation -- Fix structure size comment in inflate.h -- Change configure help option from --h* to --help [Santos] - -Changes in 1.2.3 (18 July 2005) -- Apply security vulnerability fixes to contrib/infback9 as well -- Clean up some text files (carriage returns, trailing space) -- Update testzlib, vstudio, masmx64, and masmx86 in contrib [Vollant] - -Changes in 1.2.2.4 (11 July 2005) -- Add inflatePrime() function for starting inflation at bit boundary -- Avoid some Visual C warnings in deflate.c -- Avoid more silly Visual C warnings in inflate.c and inftrees.c for 64-bit - compile -- Fix some spelling errors in comments [Betts] -- Correct inflateInit2() error return documentation in zlib.h -- Add zran.c example of compressed data random access to examples - directory, shows use of inflatePrime() -- Fix cast for assignments to strm->state in inflate.c and infback.c -- Fix zlibCompileFlags() in zutil.c to use 1L for long shifts [Oberhumer] -- Move declarations of gf2 functions to right place in crc32.c [Oberhumer] -- Add cast in trees.c t avoid a warning [Oberhumer] -- Avoid some warnings in fitblk.c, gun.c, gzjoin.c in examples [Oberhumer] -- Update make_vms.com [Zinser] -- Initialize state->write in inflateReset() since copied in inflate_fast() -- Be more strict on incomplete code sets in inflate_table() and increase - ENOUGH and MAXD -- this repairs a possible security vulnerability for - invalid inflate input. Thanks to Tavis Ormandy and Markus Oberhumer for - discovering the vulnerability and providing test cases. -- Add ia64 support to configure for HP-UX [Smith] -- Add error return to gzread() for format or i/o error [Levin] -- Use malloc.h for OS/2 [Necasek] - -Changes in 1.2.2.3 (27 May 2005) -- Replace 1U constants in inflate.c and inftrees.c for 64-bit compile -- Typecast fread() return values in gzio.c [Vollant] -- Remove trailing space in minigzip.c outmode (VC++ can't deal with it) -- Fix crc check bug in gzread() after gzungetc() [Heiner] -- Add the deflateTune() function to adjust internal compression parameters -- Add a fast gzip decompressor, gun.c, to examples (use of inflateBack) -- Remove an incorrect assertion in examples/zpipe.c -- Add C++ wrapper in infback9.h [Donais] -- Fix bug in inflateCopy() when decoding fixed codes -- Note in zlib.h how much deflateSetDictionary() actually uses -- Remove USE_DICT_HEAD in deflate.c (would mess up inflate if used) -- Add _WIN32_WCE to define WIN32 in zconf.in.h [Spencer] -- Don't include stderr.h or errno.h for _WIN32_WCE in zutil.h [Spencer] -- Add gzdirect() function to indicate transparent reads -- Update contrib/minizip [Vollant] -- Fix compilation of deflate.c when both ASMV and FASTEST [Oberhumer] -- Add casts in crc32.c to avoid warnings [Oberhumer] -- Add contrib/masmx64 [Vollant] -- Update contrib/asm586, asm686, masmx86, testzlib, vstudio [Vollant] - -Changes in 1.2.2.2 (30 December 2004) -- Replace structure assignments in deflate.c and inflate.c with zmemcpy to - avoid implicit memcpy calls (portability for no-library compilation) -- Increase sprintf() buffer size in gzdopen() to allow for large numbers -- Add INFLATE_STRICT to check distances against zlib header -- Improve WinCE errno handling and comments [Chang] -- Remove comment about no gzip header processing in FAQ -- Add Z_FIXED strategy option to deflateInit2() to force fixed trees -- Add updated make_vms.com [Coghlan], update README -- Create a new "examples" directory, move gzappend.c there, add zpipe.c, - fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html. -- Add FAQ entry and comments in deflate.c on uninitialized memory access -- Add Solaris 9 make options in configure [Gilbert] -- Allow strerror() usage in gzio.c for STDC -- Fix DecompressBuf in contrib/delphi/ZLib.pas [ManChesTer] -- Update contrib/masmx86/inffas32.asm and gvmat32.asm [Vollant] -- Use z_off_t for adler32_combine() and crc32_combine() lengths -- Make adler32() much faster for small len -- Use OS_CODE in deflate() default gzip header - -Changes in 1.2.2.1 (31 October 2004) -- Allow inflateSetDictionary() call for raw inflate -- Fix inflate header crc check bug for file names and comments -- Add deflateSetHeader() and gz_header structure for custom gzip headers -- Add inflateGetheader() to retrieve gzip headers -- Add crc32_combine() and adler32_combine() functions -- Add alloc_func, free_func, in_func, out_func to Z_PREFIX list -- Use zstreamp consistently in zlib.h (inflate_back functions) -- Remove GUNZIP condition from definition of inflate_mode in inflate.h - and in contrib/inflate86/inffast.S [Truta, Anderson] -- Add support for AMD64 in contrib/inflate86/inffas86.c [Anderson] -- Update projects/README.projects and projects/visualc6 [Truta] -- Update win32/DLL_FAQ.txt [Truta] -- Avoid warning under NO_GZCOMPRESS in gzio.c; fix typo [Truta] -- Deprecate Z_ASCII; use Z_TEXT instead [Truta] -- Use a new algorithm for setting strm->data_type in trees.c [Truta] -- Do not define an exit() prototype in zutil.c unless DEBUG defined -- Remove prototype of exit() from zutil.c, example.c, minigzip.c [Truta] -- Add comment in zlib.h for Z_NO_FLUSH parameter to deflate() -- Fix Darwin build version identification [Peterson] - -Changes in 1.2.2 (3 October 2004) -- Update zlib.h comments on gzip in-memory processing -- Set adler to 1 in inflateReset() to support Java test suite [Walles] -- Add contrib/dotzlib [Ravn] -- Update win32/DLL_FAQ.txt [Truta] -- Update contrib/minizip [Vollant] -- Move contrib/visual-basic.txt to old/ [Truta] -- Fix assembler builds in projects/visualc6/ [Truta] - -Changes in 1.2.1.2 (9 September 2004) -- Update INDEX file -- Fix trees.c to update strm->data_type (no one ever noticed!) -- Fix bug in error case in inflate.c, infback.c, and infback9.c [Brown] -- Add "volatile" to crc table flag declaration (for DYNAMIC_CRC_TABLE) -- Add limited multitasking protection to DYNAMIC_CRC_TABLE -- Add NO_vsnprintf for VMS in zutil.h [Mozilla] -- Don't declare strerror() under VMS [Mozilla] -- Add comment to DYNAMIC_CRC_TABLE to use get_crc_table() to initialize -- Update contrib/ada [Anisimkov] -- Update contrib/minizip [Vollant] -- Fix configure to not hardcode directories for Darwin [Peterson] -- Fix gzio.c to not return error on empty files [Brown] -- Fix indentation; update version in contrib/delphi/ZLib.pas and - contrib/pascal/zlibpas.pas [Truta] -- Update mkasm.bat in contrib/masmx86 [Truta] -- Update contrib/untgz [Truta] -- Add projects/README.projects [Truta] -- Add project for MS Visual C++ 6.0 in projects/visualc6 [Cadieux, Truta] -- Update win32/DLL_FAQ.txt [Truta] -- Update list of Z_PREFIX symbols in zconf.h [Randers-Pehrson, Truta] -- Remove an unnecessary assignment to curr in inftrees.c [Truta] -- Add OS/2 to exe builds in configure [Poltorak] -- Remove err dummy parameter in zlib.h [Kientzle] - -Changes in 1.2.1.1 (9 January 2004) -- Update email address in README -- Several FAQ updates -- Fix a big fat bug in inftrees.c that prevented decoding valid - dynamic blocks with only literals and no distance codes -- - Thanks to "Hot Emu" for the bug report and sample file -- Add a note to puff.c on no distance codes case. - -Changes in 1.2.1 (17 November 2003) -- Remove a tab in contrib/gzappend/gzappend.c -- Update some interfaces in contrib for new zlib functions -- Update zlib version number in some contrib entries -- Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta] -- Support shared libraries on Hurd and KFreeBSD [Brown] -- Fix error in NO_DIVIDE option of adler32.c - -Changes in 1.2.0.8 (4 November 2003) -- Update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas -- Add experimental NO_DIVIDE #define in adler32.c - - Possibly faster on some processors (let me know if it is) -- Correct Z_BLOCK to not return on first inflate call if no wrap -- Fix strm->data_type on inflate() return to correctly indicate EOB -- Add deflatePrime() function for appending in the middle of a byte -- Add contrib/gzappend for an example of appending to a stream -- Update win32/DLL_FAQ.txt [Truta] -- Delete Turbo C comment in README [Truta] -- Improve some indentation in zconf.h [Truta] -- Fix infinite loop on bad input in configure script [Church] -- Fix gzeof() for concatenated gzip files [Johnson] -- Add example to contrib/visual-basic.txt [Michael B.] -- Add -p to mkdir's in Makefile.in [vda] -- Fix configure to properly detect presence or lack of printf functions -- Add AS400 support [Monnerat] -- Add a little Cygwin support [Wilson] - -Changes in 1.2.0.7 (21 September 2003) -- Correct some debug formats in contrib/infback9 -- Cast a type in a debug statement in trees.c -- Change search and replace delimiter in configure from % to # [Beebe] -- Update contrib/untgz to 0.2 with various fixes [Truta] -- Add build support for Amiga [Nikl] -- Remove some directories in old that have been updated to 1.2 -- Add dylib building for Mac OS X in configure and Makefile.in -- Remove old distribution stuff from Makefile -- Update README to point to DLL_FAQ.txt, and add comment on Mac OS X -- Update links in README - -Changes in 1.2.0.6 (13 September 2003) -- Minor FAQ updates -- Update contrib/minizip to 1.00 [Vollant] -- Remove test of gz functions in example.c when GZ_COMPRESS defined [Truta] -- Update POSTINC comment for 68060 [Nikl] -- Add contrib/infback9 with deflate64 decoding (unsupported) -- For MVS define NO_vsnprintf and undefine FAR [van Burik] -- Add pragma for fdopen on MVS [van Burik] - -Changes in 1.2.0.5 (8 September 2003) -- Add OF to inflateBackEnd() declaration in zlib.h -- Remember start when using gzdopen in the middle of a file -- Use internal off_t counters in gz* functions to properly handle seeks -- Perform more rigorous check for distance-too-far in inffast.c -- Add Z_BLOCK flush option to return from inflate at block boundary -- Set strm->data_type on return from inflate - - Indicate bits unused, if at block boundary, and if in last block -- Replace size_t with ptrdiff_t in crc32.c, and check for correct size -- Add condition so old NO_DEFLATE define still works for compatibility -- FAQ update regarding the Windows DLL [Truta] -- INDEX update: add qnx entry, remove aix entry [Truta] -- Install zlib.3 into mandir [Wilson] -- Move contrib/zlib_dll_FAQ.txt to win32/DLL_FAQ.txt; update [Truta] -- Adapt the zlib interface to the new DLL convention guidelines [Truta] -- Introduce ZLIB_WINAPI macro to allow the export of functions using - the WINAPI calling convention, for Visual Basic [Vollant, Truta] -- Update msdos and win32 scripts and makefiles [Truta] -- Export symbols by name, not by ordinal, in win32/zlib.def [Truta] -- Add contrib/ada [Anisimkov] -- Move asm files from contrib/vstudio/vc70_32 to contrib/asm386 [Truta] -- Rename contrib/asm386 to contrib/masmx86 [Truta, Vollant] -- Add contrib/masm686 [Truta] -- Fix offsets in contrib/inflate86 and contrib/masmx86/inffas32.asm - [Truta, Vollant] -- Update contrib/delphi; rename to contrib/pascal; add example [Truta] -- Remove contrib/delphi2; add a new contrib/delphi [Truta] -- Avoid inclusion of the nonstandard in contrib/iostream, - and fix some method prototypes [Truta] -- Fix the ZCR_SEED2 constant to avoid warnings in contrib/minizip - [Truta] -- Avoid the use of backslash (\) in contrib/minizip [Vollant] -- Fix file time handling in contrib/untgz; update makefiles [Truta] -- Update contrib/vstudio/vc70_32 to comply with the new DLL guidelines - [Vollant] -- Remove contrib/vstudio/vc15_16 [Vollant] -- Rename contrib/vstudio/vc70_32 to contrib/vstudio/vc7 [Truta] -- Update README.contrib [Truta] -- Invert the assignment order of match_head and s->prev[...] in - INSERT_STRING [Truta] -- Compare TOO_FAR with 32767 instead of 32768, to avoid 16-bit warnings - [Truta] -- Compare function pointers with 0, not with NULL or Z_NULL [Truta] -- Fix prototype of syncsearch in inflate.c [Truta] -- Introduce ASMINF macro to be enabled when using an ASM implementation - of inflate_fast [Truta] -- Change NO_DEFLATE to NO_GZCOMPRESS [Truta] -- Modify test_gzio in example.c to take a single file name as a - parameter [Truta] -- Exit the example.c program if gzopen fails [Truta] -- Add type casts around strlen in example.c [Truta] -- Remove casting to sizeof in minigzip.c; give a proper type - to the variable compared with SUFFIX_LEN [Truta] -- Update definitions of STDC and STDC99 in zconf.h [Truta] -- Synchronize zconf.h with the new Windows DLL interface [Truta] -- Use SYS16BIT instead of __32BIT__ to distinguish between - 16- and 32-bit platforms [Truta] -- Use far memory allocators in small 16-bit memory models for - Turbo C [Truta] -- Add info about the use of ASMV, ASMINF and ZLIB_WINAPI in - zlibCompileFlags [Truta] -- Cygwin has vsnprintf [Wilson] -- In Windows16, OS_CODE is 0, as in MSDOS [Truta] -- In Cygwin, OS_CODE is 3 (Unix), not 11 (Windows32) [Wilson] - -Changes in 1.2.0.4 (10 August 2003) -- Minor FAQ updates -- Be more strict when checking inflateInit2's windowBits parameter -- Change NO_GUNZIP compile option to NO_GZIP to cover deflate as well -- Add gzip wrapper option to deflateInit2 using windowBits -- Add updated QNX rule in configure and qnx directory [Bonnefoy] -- Make inflate distance-too-far checks more rigorous -- Clean up FAR usage in inflate -- Add casting to sizeof() in gzio.c and minigzip.c - -Changes in 1.2.0.3 (19 July 2003) -- Fix silly error in gzungetc() implementation [Vollant] -- Update contrib/minizip and contrib/vstudio [Vollant] -- Fix printf format in example.c -- Correct cdecl support in zconf.in.h [Anisimkov] -- Minor FAQ updates - -Changes in 1.2.0.2 (13 July 2003) -- Add ZLIB_VERNUM in zlib.h for numerical preprocessor comparisons -- Attempt to avoid warnings in crc32.c for pointer-int conversion -- Add AIX to configure, remove aix directory [Bakker] -- Add some casts to minigzip.c -- Improve checking after insecure sprintf() or vsprintf() calls -- Remove #elif's from crc32.c -- Change leave label to inf_leave in inflate.c and infback.c to avoid - library conflicts -- Remove inflate gzip decoding by default--only enable gzip decoding by - special request for stricter backward compatibility -- Add zlibCompileFlags() function to return compilation information -- More typecasting in deflate.c to avoid warnings -- Remove leading underscore from _Capital #defines [Truta] -- Fix configure to link shared library when testing -- Add some Windows CE target adjustments [Mai] -- Remove #define ZLIB_DLL in zconf.h [Vollant] -- Add zlib.3 [Rodgers] -- Update RFC URL in deflate.c and algorithm.txt [Mai] -- Add zlib_dll_FAQ.txt to contrib [Truta] -- Add UL to some constants [Truta] -- Update minizip and vstudio [Vollant] -- Remove vestigial NEED_DUMMY_RETURN from zconf.in.h -- Expand use of NO_DUMMY_DECL to avoid all dummy structures -- Added iostream3 to contrib [Schwardt] -- Replace rewind() with fseek() for WinCE [Truta] -- Improve setting of zlib format compression level flags - - Report 0 for huffman and rle strategies and for level == 0 or 1 - - Report 2 only for level == 6 -- Only deal with 64K limit when necessary at compile time [Truta] -- Allow TOO_FAR check to be turned off at compile time [Truta] -- Add gzclearerr() function [Souza] -- Add gzungetc() function - -Changes in 1.2.0.1 (17 March 2003) -- Add Z_RLE strategy for run-length encoding [Truta] - - When Z_RLE requested, restrict matches to distance one - - Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE -- Correct FASTEST compilation to allow level == 0 -- Clean up what gets compiled for FASTEST -- Incorporate changes to zconf.in.h [Vollant] - - Refine detection of Turbo C need for dummy returns - - Refine ZLIB_DLL compilation - - Include additional header file on VMS for off_t typedef -- Try to use _vsnprintf where it supplants vsprintf [Vollant] -- Add some casts in inffast.c -- Enchance comments in zlib.h on what happens if gzprintf() tries to - write more than 4095 bytes before compression -- Remove unused state from inflateBackEnd() -- Remove exit(0) from minigzip.c, example.c -- Get rid of all those darn tabs -- Add "check" target to Makefile.in that does the same thing as "test" -- Add "mostlyclean" and "maintainer-clean" targets to Makefile.in -- Update contrib/inflate86 [Anderson] -- Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant] -- Add msdos and win32 directories with makefiles [Truta] -- More additions and improvements to the FAQ - -Changes in 1.2.0 (9 March 2003) -- New and improved inflate code - - About 20% faster - - Does not allocate 32K window unless and until needed - - Automatically detects and decompresses gzip streams - - Raw inflate no longer needs an extra dummy byte at end - - Added inflateBack functions using a callback interface--even faster - than inflate, useful for file utilities (gzip, zip) - - Added inflateCopy() function to record state for random access on - externally generated deflate streams (e.g. in gzip files) - - More readable code (I hope) -- New and improved crc32() - - About 50% faster, thanks to suggestions from Rodney Brown -- Add deflateBound() and compressBound() functions -- Fix memory leak in deflateInit2() -- Permit setting dictionary for raw deflate (for parallel deflate) -- Fix const declaration for gzwrite() -- Check for some malloc() failures in gzio.c -- Fix bug in gzopen() on single-byte file 0x1f -- Fix bug in gzread() on concatenated file with 0x1f at end of buffer - and next buffer doesn't start with 0x8b -- Fix uncompress() to return Z_DATA_ERROR on truncated input -- Free memory at end of example.c -- Remove MAX #define in trees.c (conflicted with some libraries) -- Fix static const's in deflate.c, gzio.c, and zutil.[ch] -- Declare malloc() and free() in gzio.c if STDC not defined -- Use malloc() instead of calloc() in zutil.c if int big enough -- Define STDC for AIX -- Add aix/ with approach for compiling shared library on AIX -- Add HP-UX support for shared libraries in configure -- Add OpenUNIX support for shared libraries in configure -- Use $cc instead of gcc to build shared library -- Make prefix directory if needed when installing -- Correct Macintosh avoidance of typedef Byte in zconf.h -- Correct Turbo C memory allocation when under Linux -- Use libz.a instead of -lz in Makefile (assure use of compiled library) -- Update configure to check for snprintf or vsnprintf functions and their - return value, warn during make if using an insecure function -- Fix configure problem with compile-time knowledge of HAVE_UNISTD_H that - is lost when library is used--resolution is to build new zconf.h -- Documentation improvements (in zlib.h): - - Document raw deflate and inflate - - Update RFCs URL - - Point out that zlib and gzip formats are different - - Note that Z_BUF_ERROR is not fatal - - Document string limit for gzprintf() and possible buffer overflow - - Note requirement on avail_out when flushing - - Note permitted values of flush parameter of inflate() -- Add some FAQs (and even answers) to the FAQ -- Add contrib/inflate86/ for x86 faster inflate -- Add contrib/blast/ for PKWare Data Compression Library decompression -- Add contrib/puff/ simple inflate for deflate format description - -Changes in 1.1.4 (11 March 2002) -- ZFREE was repeated on same allocation on some error conditions. - This creates a security problem described in - http://www.zlib.org/advisory-2002-03-11.txt -- Returned incorrect error (Z_MEM_ERROR) on some invalid data -- Avoid accesses before window for invalid distances with inflate window - less than 32K. -- force windowBits > 8 to avoid a bug in the encoder for a window size - of 256 bytes. (A complete fix will be available in 1.1.5). - -Changes in 1.1.3 (9 July 1998) -- fix "an inflate input buffer bug that shows up on rare but persistent - occasions" (Mark) -- fix gzread and gztell for concatenated .gz files (Didier Le Botlan) -- fix gzseek(..., SEEK_SET) in write mode -- fix crc check after a gzeek (Frank Faubert) -- fix miniunzip when the last entry in a zip file is itself a zip file - (J Lillge) -- add contrib/asm586 and contrib/asm686 (Brian Raiter) - See http://www.muppetlabs.com/~breadbox/software/assembly.html -- add support for Delphi 3 in contrib/delphi (Bob Dellaca) -- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti) -- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren) -- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks) -- added a FAQ file - -- Support gzdopen on Mac with Metrowerks (Jason Linhart) -- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart) -- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young) -- avoid some warnings with Borland C (Tom Tanner) -- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant) -- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant) -- allow several arguments to configure (Tim Mooney, Frodo Looijaard) -- use libdir and includedir in Makefile.in (Tim Mooney) -- support shared libraries on OSF1 V4 (Tim Mooney) -- remove so_locations in "make clean" (Tim Mooney) -- fix maketree.c compilation error (Glenn, Mark) -- Python interface to zlib now in Python 1.5 (Jeremy Hylton) -- new Makefile.riscos (Rich Walker) -- initialize static descriptors in trees.c for embedded targets (Nick Smith) -- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith) -- add the OS/2 files in Makefile.in too (Andrew Zabolotny) -- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane) -- fix maketree.c to allow clean compilation of inffixed.h (Mark) -- fix parameter check in deflateCopy (Gunther Nikl) -- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler) -- Many portability patches by Christian Spieler: - . zutil.c, zutil.h: added "const" for zmem* - . Make_vms.com: fixed some typos - . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists - . msdos/Makefile.msc: remove "default rtl link library" info from obj files - . msdos/Makefile.*: use model-dependent name for the built zlib library - . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc: - new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT) -- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane) -- replace __far with _far for better portability (Christian Spieler, Tom Lane) -- fix test for errno.h in configure (Tim Newsham) - -Changes in 1.1.2 (19 March 98) -- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant) - See http://www.winimage.com/zLibDll/unzip.html -- preinitialize the inflate tables for fixed codes, to make the code - completely thread safe (Mark) -- some simplifications and slight speed-up to the inflate code (Mark) -- fix gzeof on non-compressed files (Allan Schrum) -- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs) -- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn) -- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny) -- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori) -- do not wrap extern "C" around system includes (Tom Lane) -- mention zlib binding for TCL in README (Andreas Kupries) -- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert) -- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson) -- allow "configure --prefix $HOME" (Tim Mooney) -- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson) -- move Makefile.sas to amiga/Makefile.sas - -Changes in 1.1.1 (27 Feb 98) -- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson) -- remove block truncation heuristic which had very marginal effect for zlib - (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the - compression ratio on some files. This also allows inlining _tr_tally for - matches in deflate_slow. -- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier) - -Changes in 1.1.0 (24 Feb 98) -- do not return STREAM_END prematurely in inflate (John Bowler) -- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler) -- compile with -DFASTEST to get compression code optimized for speed only -- in minigzip, try mmap'ing the input file first (Miguel Albrecht) -- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain - on Sun but significant on HP) - -- add a pointer to experimental unzip library in README (Gilles Vollant) -- initialize variable gcc in configure (Chris Herborth) - -Changes in 1.0.9 (17 Feb 1998) -- added gzputs and gzgets functions -- do not clear eof flag in gzseek (Mark Diekhans) -- fix gzseek for files in transparent mode (Mark Diekhans) -- do not assume that vsprintf returns the number of bytes written (Jens Krinke) -- replace EXPORT with ZEXPORT to avoid conflict with other programs -- added compress2 in zconf.h, zlib.def, zlib.dnt -- new asm code from Gilles Vollant in contrib/asm386 -- simplify the inflate code (Mark): - . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new() - . ZALLOC the length list in inflate_trees_fixed() instead of using stack - . ZALLOC the value area for huft_build() instead of using stack - . Simplify Z_FINISH check in inflate() - -- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8 -- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi) -- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with - the declaration of FAR (Gilles VOllant) -- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann) -- read_buf buf parameter of type Bytef* instead of charf* -- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout) -- do not redeclare unlink in minigzip.c for WIN32 (John Bowler) -- fix check for presence of directories in "make install" (Ian Willis) - -Changes in 1.0.8 (27 Jan 1998) -- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant) -- fix gzgetc and gzputc for big endian systems (Markus Oberhumer) -- added compress2() to allow setting the compression level -- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong) -- use constant arrays for the static trees in trees.c instead of computing - them at run time (thanks to Ken Raeburn for this suggestion). To create - trees.h, compile with GEN_TREES_H and run "make test". -- check return code of example in "make test" and display result -- pass minigzip command line options to file_compress -- simplifying code of inflateSync to avoid gcc 2.8 bug - -- support CC="gcc -Wall" in configure -s (QingLong) -- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn) -- fix test for shared library support to avoid compiler warnings -- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant) -- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit) -- do not use fdopen for Metrowerks on Mac (Brad Pettit)) -- add checks for gzputc and gzputc in example.c -- avoid warnings in gzio.c and deflate.c (Andreas Kleinert) -- use const for the CRC table (Ken Raeburn) -- fixed "make uninstall" for shared libraries -- use Tracev instead of Trace in infblock.c -- in example.c use correct compressed length for test_sync -- suppress +vnocompatwarnings in configure for HPUX (not always supported) - -Changes in 1.0.7 (20 Jan 1998) -- fix gzseek which was broken in write mode -- return error for gzseek to negative absolute position -- fix configure for Linux (Chun-Chung Chen) -- increase stack space for MSC (Tim Wegner) -- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant) -- define EXPORTVA for gzprintf (Gilles Vollant) -- added man page zlib.3 (Rick Rodgers) -- for contrib/untgz, fix makedir() and improve Makefile - -- check gzseek in write mode in example.c -- allocate extra buffer for seeks only if gzseek is actually called -- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant) -- add inflateSyncPoint in zconf.h -- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def - -Changes in 1.0.6 (19 Jan 1998) -- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and - gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code) -- Fix a deflate bug occurring only with compression level 0 (thanks to - Andy Buckler for finding this one). -- In minigzip, pass transparently also the first byte for .Z files. -- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress() -- check Z_FINISH in inflate (thanks to Marc Schluper) -- Implement deflateCopy (thanks to Adam Costello) -- make static libraries by default in configure, add --shared option. -- move MSDOS or Windows specific files to directory msdos -- suppress the notion of partial flush to simplify the interface - (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4) -- suppress history buffer provided by application to simplify the interface - (this feature was not implemented anyway in 1.0.4) -- next_in and avail_in must be initialized before calling inflateInit or - inflateInit2 -- add EXPORT in all exported functions (for Windows DLL) -- added Makefile.nt (thanks to Stephen Williams) -- added the unsupported "contrib" directory: - contrib/asm386/ by Gilles Vollant - 386 asm code replacing longest_match(). - contrib/iostream/ by Kevin Ruland - A C++ I/O streams interface to the zlib gz* functions - contrib/iostream2/ by Tyge Løvset - Another C++ I/O streams interface - contrib/untgz/ by "Pedro A. Aranda Guti\irrez" - A very simple tar.gz file extractor using zlib - contrib/visual-basic.txt by Carlos Rios - How to use compress(), uncompress() and the gz* functions from VB. -- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression - level) in minigzip (thanks to Tom Lane) - -- use const for rommable constants in deflate -- added test for gzseek and gztell in example.c -- add undocumented function inflateSyncPoint() (hack for Paul Mackerras) -- add undocumented function zError to convert error code to string - (for Tim Smithers) -- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code. -- Use default memcpy for Symantec MSDOS compiler. -- Add EXPORT keyword for check_func (needed for Windows DLL) -- add current directory to LD_LIBRARY_PATH for "make test" -- create also a link for libz.so.1 -- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura) -- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX) -- added -soname for Linux in configure (Chun-Chung Chen, -- assign numbers to the exported functions in zlib.def (for Windows DLL) -- add advice in zlib.h for best usage of deflateSetDictionary -- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn) -- allow compilation with ANSI keywords only enabled for TurboC in large model -- avoid "versionString"[0] (Borland bug) -- add NEED_DUMMY_RETURN for Borland -- use variable z_verbose for tracing in debug mode (L. Peter Deutsch). -- allow compilation with CC -- defined STDC for OS/2 (David Charlap) -- limit external names to 8 chars for MVS (Thomas Lund) -- in minigzip.c, use static buffers only for 16-bit systems -- fix suffix check for "minigzip -d foo.gz" -- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee) -- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau) -- added makelcc.bat for lcc-win32 (Tom St Denis) -- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe) -- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion. -- check for unistd.h in configure (for off_t) -- remove useless check parameter in inflate_blocks_free -- avoid useless assignment of s->check to itself in inflate_blocks_new -- do not flush twice in gzclose (thanks to Ken Raeburn) -- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h -- use NO_ERRNO_H instead of enumeration of operating systems with errno.h -- work around buggy fclose on pipes for HP/UX -- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson) -- fix configure if CC is already equal to gcc - -Changes in 1.0.5 (3 Jan 98) -- Fix inflate to terminate gracefully when fed corrupted or invalid data -- Use const for rommable constants in inflate -- Eliminate memory leaks on error conditions in inflate -- Removed some vestigial code in inflate -- Update web address in README - -Changes in 1.0.4 (24 Jul 96) -- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF - bit, so the decompressor could decompress all the correct data but went - on to attempt decompressing extra garbage data. This affected minigzip too. -- zlibVersion and gzerror return const char* (needed for DLL) -- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno) -- use z_error only for DEBUG (avoid problem with DLLs) - -Changes in 1.0.3 (2 Jul 96) -- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS - small and medium models; this makes the library incompatible with previous - versions for these models. (No effect in large model or on other systems.) -- return OK instead of BUF_ERROR if previous deflate call returned with - avail_out as zero but there is nothing to do -- added memcmp for non STDC compilers -- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly) -- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO) -- better check for 16-bit mode MSC (avoids problem with Symantec) - -Changes in 1.0.2 (23 May 96) -- added Windows DLL support -- added a function zlibVersion (for the DLL support) -- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model) -- Bytef is define's instead of typedef'd only for Borland C -- avoid reading uninitialized memory in example.c -- mention in README that the zlib format is now RFC1950 -- updated Makefile.dj2 -- added algorithm.doc - -Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion] -- fix array overlay in deflate.c which sometimes caused bad compressed data -- fix inflate bug with empty stored block -- fix MSDOS medium model which was broken in 0.99 -- fix deflateParams() which could generated bad compressed data. -- Bytef is define'd instead of typedef'ed (work around Borland bug) -- added an INDEX file -- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32), - Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas) -- speed up adler32 for modern machines without auto-increment -- added -ansi for IRIX in configure -- static_init_done in trees.c is an int -- define unlink as delete for VMS -- fix configure for QNX -- add configure branch for SCO and HPUX -- avoid many warnings (unused variables, dead assignments, etc...) -- no fdopen for BeOS -- fix the Watcom fix for 32 bit mode (define FAR as empty) -- removed redefinition of Byte for MKWERKS -- work around an MWKERKS bug (incorrect merge of all .h files) - -Changes in 0.99 (27 Jan 96) -- allow preset dictionary shared between compressor and decompressor -- allow compression level 0 (no compression) -- add deflateParams in zlib.h: allow dynamic change of compression level - and compression strategy. -- test large buffers and deflateParams in example.c -- add optional "configure" to build zlib as a shared library -- suppress Makefile.qnx, use configure instead -- fixed deflate for 64-bit systems (detected on Cray) -- fixed inflate_blocks for 64-bit systems (detected on Alpha) -- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2) -- always return Z_BUF_ERROR when deflate() has nothing to do -- deflateInit and inflateInit are now macros to allow version checking -- prefix all global functions and types with z_ with -DZ_PREFIX -- make falloc completely reentrant (inftrees.c) -- fixed very unlikely race condition in ct_static_init -- free in reverse order of allocation to help memory manager -- use zlib-1.0/* instead of zlib/* inside the tar.gz -- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith - -Wconversion -Wstrict-prototypes -Wmissing-prototypes" -- allow gzread on concatenated .gz files -- deflateEnd now returns Z_DATA_ERROR if it was premature -- deflate is finally (?) fully deterministic (no matches beyond end of input) -- Document Z_SYNC_FLUSH -- add uninstall in Makefile -- Check for __cpluplus in zlib.h -- Better test in ct_align for partial flush -- avoid harmless warnings for Borland C++ -- initialize hash_head in deflate.c -- avoid warning on fdopen (gzio.c) for HP cc -Aa -- include stdlib.h for STDC compilers -- include errno.h for Cray -- ignore error if ranlib doesn't exist -- call ranlib twice for NeXTSTEP -- use exec_prefix instead of prefix for libz.a -- renamed ct_* as _tr_* to avoid conflict with applications -- clear z->msg in inflateInit2 before any error return -- initialize opaque in example.c, gzio.c, deflate.c and inflate.c -- fixed typo in zconf.h (_GNUC__ => __GNUC__) -- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode) -- fix typo in Make_vms.com (f$trnlnm -> f$getsyi) -- in fcalloc, normalize pointer if size > 65520 bytes -- don't use special fcalloc for 32 bit Borland C++ -- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc... -- use Z_BINARY instead of BINARY -- document that gzclose after gzdopen will close the file -- allow "a" as mode in gzopen. -- fix error checking in gzread -- allow skipping .gz extra-field on pipes -- added reference to Perl interface in README -- put the crc table in FAR data (I dislike more and more the medium model :) -- added get_crc_table -- added a dimension to all arrays (Borland C can't count). -- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast -- guard against multiple inclusion of *.h (for precompiled header on Mac) -- Watcom C pretends to be Microsoft C small model even in 32 bit mode. -- don't use unsized arrays to avoid silly warnings by Visual C++: - warning C4746: 'inflate_mask' : unsized array treated as '__far' - (what's wrong with far data in far model?). -- define enum out of inflate_blocks_state to allow compilation with C++ - -Changes in 0.95 (16 Aug 95) -- fix MSDOS small and medium model (now easier to adapt to any compiler) -- inlined send_bits -- fix the final (:-) bug for deflate with flush (output was correct but - not completely flushed in rare occasions). -- default window size is same for compression and decompression - (it's now sufficient to set MAX_WBITS in zconf.h). -- voidp -> voidpf and voidnp -> voidp (for consistency with other - typedefs and because voidnp was not near in large model). - -Changes in 0.94 (13 Aug 95) -- support MSDOS medium model -- fix deflate with flush (could sometimes generate bad output) -- fix deflateReset (zlib header was incorrectly suppressed) -- added support for VMS -- allow a compression level in gzopen() -- gzflush now calls fflush -- For deflate with flush, flush even if no more input is provided. -- rename libgz.a as libz.a -- avoid complex expression in infcodes.c triggering Turbo C bug -- work around a problem with gcc on Alpha (in INSERT_STRING) -- don't use inline functions (problem with some gcc versions) -- allow renaming of Byte, uInt, etc... with #define. -- avoid warning about (unused) pointer before start of array in deflate.c -- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c -- avoid reserved word 'new' in trees.c - -Changes in 0.93 (25 June 95) -- temporarily disable inline functions -- make deflate deterministic -- give enough lookahead for PARTIAL_FLUSH -- Set binary mode for stdin/stdout in minigzip.c for OS/2 -- don't even use signed char in inflate (not portable enough) -- fix inflate memory leak for segmented architectures - -Changes in 0.92 (3 May 95) -- don't assume that char is signed (problem on SGI) -- Clear bit buffer when starting a stored block -- no memcpy on Pyramid -- suppressed inftest.c -- optimized fill_window, put longest_match inline for gcc -- optimized inflate on stored blocks. -- untabify all sources to simplify patches - -Changes in 0.91 (2 May 95) -- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h -- Document the memory requirements in zconf.h -- added "make install" -- fix sync search logic in inflateSync -- deflate(Z_FULL_FLUSH) now works even if output buffer too short -- after inflateSync, don't scare people with just "lo world" -- added support for DJGPP - -Changes in 0.9 (1 May 95) -- don't assume that zalloc clears the allocated memory (the TurboC bug - was Mark's bug after all :) -- let again gzread copy uncompressed data unchanged (was working in 0.71) -- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented -- added a test of inflateSync in example.c -- moved MAX_WBITS to zconf.h because users might want to change that. -- document explicitly that zalloc(64K) on MSDOS must return a normalized - pointer (zero offset) -- added Makefiles for Microsoft C, Turbo C, Borland C++ -- faster crc32() - -Changes in 0.8 (29 April 95) -- added fast inflate (inffast.c) -- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this - is incompatible with previous versions of zlib which returned Z_OK. -- work around a TurboC compiler bug (bad code for b << 0, see infutil.h) - (actually that was not a compiler bug, see 0.81 above) -- gzread no longer reads one extra byte in certain cases -- In gzio destroy(), don't reference a freed structure -- avoid many warnings for MSDOS -- avoid the ERROR symbol which is used by MS Windows - -Changes in 0.71 (14 April 95) -- Fixed more MSDOS compilation problems :( There is still a bug with - TurboC large model. - -Changes in 0.7 (14 April 95) -- Added full inflate support. -- Simplified the crc32() interface. The pre- and post-conditioning - (one's complement) is now done inside crc32(). WARNING: this is - incompatible with previous versions; see zlib.h for the new usage. - -Changes in 0.61 (12 April 95) -- workaround for a bug in TurboC. example and minigzip now work on MSDOS. - -Changes in 0.6 (11 April 95) -- added minigzip.c -- added gzdopen to reopen a file descriptor as gzFile -- added transparent reading of non-gziped files in gzread. -- fixed bug in gzread (don't read crc as data) -- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose). -- don't allocate big arrays in the stack (for MSDOS) -- fix some MSDOS compilation problems - -Changes in 0.5: -- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but - not yet Z_FULL_FLUSH. -- support decompression but only in a single step (forced Z_FINISH) -- added opaque object for zalloc and zfree. -- added deflateReset and inflateReset -- added a variable zlib_version for consistency checking. -- renamed the 'filter' parameter of deflateInit2 as 'strategy'. - Added Z_FILTERED and Z_HUFFMAN_ONLY constants. - -Changes in 0.4: -- avoid "zip" everywhere, use zlib instead of ziplib. -- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush - if compression method == 8. -- added adler32 and crc32 -- renamed deflateOptions as deflateInit2, call one or the other but not both -- added the method parameter for deflateInit2. -- added inflateInit2 -- simplied considerably deflateInit and inflateInit by not supporting - user-provided history buffer. This is supported only in deflateInit2 - and inflateInit2. - -Changes in 0.3: -- prefix all macro names with Z_ -- use Z_FINISH instead of deflateEnd to finish compression. -- added Z_HUFFMAN_ONLY -- added gzerror() + + ChangeLog file for zlib + +Changes in 1.2.7 (2 May 2012) +- Replace use of memmove() with a simple copy for portability +- Test for existence of strerror +- Restore gzgetc_ for backward compatibility with 1.2.6 +- Fix build with non-GNU make on Solaris +- Require gcc 4.0 or later on Mac OS X to use the hidden attribute +- Include unistd.h for Watcom C +- Use __WATCOMC__ instead of __WATCOM__ +- Do not use the visibility attribute if NO_VIZ defined +- Improve the detection of no hidden visibility attribute +- Avoid using __int64 for gcc or solo compilation +- Cast to char * in gzprintf to avoid warnings [Zinser] +- Fix make_vms.com for VAX [Zinser] +- Don't use library or built-in byte swaps +- Simplify test and use of gcc hidden attribute +- Fix bug in gzclose_w() when gzwrite() fails to allocate memory +- Add "x" (O_EXCL) and "e" (O_CLOEXEC) modes support to gzopen() +- Fix bug in test/minigzip.c for configure --solo +- Fix contrib/vstudio project link errors [Mohanathas] +- Add ability to choose the builder in make_vms.com [Schweda] +- Add DESTDIR support to mingw32 win32/Makefile.gcc +- Fix comments in win32/Makefile.gcc for proper usage +- Allow overriding the default install locations for cmake +- Generate and install the pkg-config file with cmake +- Build both a static and a shared version of zlib with cmake +- Include version symbols for cmake builds +- If using cmake with MSVC, add the source directory to the includes +- Remove unneeded EXTRA_CFLAGS from win32/Makefile.gcc [Truta] +- Move obsolete emx makefile to old [Truta] +- Allow the use of -Wundef when compiling or using zlib +- Avoid the use of the -u option with mktemp +- Improve inflate() documentation on the use of Z_FINISH +- Recognize clang as gcc +- Add gzopen_w() in Windows for wide character path names +- Rename zconf.h in CMakeLists.txt to move it out of the way +- Add source directory in CMakeLists.txt for building examples +- Look in build directory for zlib.pc in CMakeLists.txt +- Remove gzflags from zlibvc.def in vc9 and vc10 +- Fix contrib/minizip compilation in the MinGW environment +- Update ./configure for Solaris, support --64 [Mooney] +- Remove -R. from Solaris shared build (possible security issue) +- Avoid race condition for parallel make (-j) running example +- Fix type mismatch between get_crc_table() and crc_table +- Fix parsing of version with "-" in CMakeLists.txt [Snider, Ziegler] +- Fix the path to zlib.map in CMakeLists.txt +- Force the native libtool in Mac OS X to avoid GNU libtool [Beebe] +- Add instructions to win32/Makefile.gcc for shared install [Torri] + +Changes in 1.2.6.1 (12 Feb 2012) +- Avoid the use of the Objective-C reserved name "id" +- Include io.h in gzguts.h for Microsoft compilers +- Fix problem with ./configure --prefix and gzgetc macro +- Include gz_header definition when compiling zlib solo +- Put gzflags() functionality back in zutil.c +- Avoid library header include in crc32.c for Z_SOLO +- Use name in GCC_CLASSIC as C compiler for coverage testing, if set +- Minor cleanup in contrib/minizip/zip.c [Vollant] +- Update make_vms.com [Zinser] +- Remove unnecessary gzgetc_ function +- Use optimized byte swap operations for Microsoft and GNU [Snyder] +- Fix minor typo in zlib.h comments [Rzesniowiecki] + +Changes in 1.2.6 (29 Jan 2012) +- Update the Pascal interface in contrib/pascal +- Fix function numbers for gzgetc_ in zlibvc.def files +- Fix configure.ac for contrib/minizip [Schiffer] +- Fix large-entry detection in minizip on 64-bit systems [Schiffer] +- Have ./configure use the compiler return code for error indication +- Fix CMakeLists.txt for cross compilation [McClure] +- Fix contrib/minizip/zip.c for 64-bit architectures [Dalsnes] +- Fix compilation of contrib/minizip on FreeBSD [Marquez] +- Correct suggested usages in win32/Makefile.msc [Shachar, Horvath] +- Include io.h for Turbo C / Borland C on all platforms [Truta] +- Make version explicit in contrib/minizip/configure.ac [Bosmans] +- Avoid warning for no encryption in contrib/minizip/zip.c [Vollant] +- Minor cleanup up contrib/minizip/unzip.c [Vollant] +- Fix bug when compiling minizip with C++ [Vollant] +- Protect for long name and extra fields in contrib/minizip [Vollant] +- Avoid some warnings in contrib/minizip [Vollant] +- Add -I../.. -L../.. to CFLAGS for minizip and miniunzip +- Add missing libs to minizip linker command +- Add support for VPATH builds in contrib/minizip +- Add an --enable-demos option to contrib/minizip/configure +- Add the generation of configure.log by ./configure +- Exit when required parameters not provided to win32/Makefile.gcc +- Have gzputc return the character written instead of the argument +- Use the -m option on ldconfig for BSD systems [Tobias] +- Correct in zlib.map when deflateResetKeep was added + +Changes in 1.2.5.3 (15 Jan 2012) +- Restore gzgetc function for binary compatibility +- Do not use _lseeki64 under Borland C++ [Truta] +- Update win32/Makefile.msc to build test/*.c [Truta] +- Remove old/visualc6 given CMakefile and other alternatives +- Update AS400 build files and documentation [Monnerat] +- Update win32/Makefile.gcc to build test/*.c [Truta] +- Permit stronger flushes after Z_BLOCK flushes +- Avoid extraneous empty blocks when doing empty flushes +- Permit Z_NULL arguments to deflatePending +- Allow deflatePrime() to insert bits in the middle of a stream +- Remove second empty static block for Z_PARTIAL_FLUSH +- Write out all of the available bits when using Z_BLOCK +- Insert the first two strings in the hash table after a flush + +Changes in 1.2.5.2 (17 Dec 2011) +- fix ld error: unable to find version dependency 'ZLIB_1.2.5' +- use relative symlinks for shared libs +- Avoid searching past window for Z_RLE strategy +- Assure that high-water mark initialization is always applied in deflate +- Add assertions to fill_window() in deflate.c to match comments +- Update python link in README +- Correct spelling error in gzread.c +- Fix bug in gzgets() for a concatenated empty gzip stream +- Correct error in comment for gz_make() +- Change gzread() and related to ignore junk after gzip streams +- Allow gzread() and related to continue after gzclearerr() +- Allow gzrewind() and gzseek() after a premature end-of-file +- Simplify gzseek() now that raw after gzip is ignored +- Change gzgetc() to a macro for speed (~40% speedup in testing) +- Fix gzclose() to return the actual error last encountered +- Always add large file support for windows +- Include zconf.h for windows large file support +- Include zconf.h.cmakein for windows large file support +- Update zconf.h.cmakein on make distclean +- Merge vestigial vsnprintf determination from zutil.h to gzguts.h +- Clarify how gzopen() appends in zlib.h comments +- Correct documentation of gzdirect() since junk at end now ignored +- Add a transparent write mode to gzopen() when 'T' is in the mode +- Update python link in zlib man page +- Get inffixed.h and MAKEFIXED result to match +- Add a ./config --solo option to make zlib subset with no libary use +- Add undocumented inflateResetKeep() function for CAB file decoding +- Add --cover option to ./configure for gcc coverage testing +- Add #define ZLIB_CONST option to use const in the z_stream interface +- Add comment to gzdopen() in zlib.h to use dup() when using fileno() +- Note behavior of uncompress() to provide as much data as it can +- Add files in contrib/minizip to aid in building libminizip +- Split off AR options in Makefile.in and configure +- Change ON macro to Z_ARG to avoid application conflicts +- Facilitate compilation with Borland C++ for pragmas and vsnprintf +- Include io.h for Turbo C / Borland C++ +- Move example.c and minigzip.c to test/ +- Simplify incomplete code table filling in inflate_table() +- Remove code from inflate.c and infback.c that is impossible to execute +- Test the inflate code with full coverage +- Allow deflateSetDictionary, inflateSetDictionary at any time (in raw) +- Add deflateResetKeep and fix inflateResetKeep to retain dictionary +- Fix gzwrite.c to accommodate reduced memory zlib compilation +- Have inflate() with Z_FINISH avoid the allocation of a window +- Do not set strm->adler when doing raw inflate +- Fix gzeof() to behave just like feof() when read is not past end of file +- Fix bug in gzread.c when end-of-file is reached +- Avoid use of Z_BUF_ERROR in gz* functions except for premature EOF +- Document gzread() capability to read concurrently written files +- Remove hard-coding of resource compiler in CMakeLists.txt [Blammo] + +Changes in 1.2.5.1 (10 Sep 2011) +- Update FAQ entry on shared builds (#13) +- Avoid symbolic argument to chmod in Makefile.in +- Fix bug and add consts in contrib/puff [Oberhumer] +- Update contrib/puff/zeros.raw test file to have all block types +- Add full coverage test for puff in contrib/puff/Makefile +- Fix static-only-build install in Makefile.in +- Fix bug in unzGetCurrentFileInfo() in contrib/minizip [Kuno] +- Add libz.a dependency to shared in Makefile.in for parallel builds +- Spell out "number" (instead of "nb") in zlib.h for total_in, total_out +- Replace $(...) with `...` in configure for non-bash sh [Bowler] +- Add darwin* to Darwin* and solaris* to SunOS\ 5* in configure [Groffen] +- Add solaris* to Linux* in configure to allow gcc use [Groffen] +- Add *bsd* to Linux* case in configure [Bar-Lev] +- Add inffast.obj to dependencies in win32/Makefile.msc +- Correct spelling error in deflate.h [Kohler] +- Change libzdll.a again to libz.dll.a (!) in win32/Makefile.gcc +- Add test to configure for GNU C looking for gcc in output of $cc -v +- Add zlib.pc generation to win32/Makefile.gcc [Weigelt] +- Fix bug in zlib.h for _FILE_OFFSET_BITS set and _LARGEFILE64_SOURCE not +- Add comment in zlib.h that adler32_combine with len2 < 0 makes no sense +- Make NO_DIVIDE option in adler32.c much faster (thanks to John Reiser) +- Make stronger test in zconf.h to include unistd.h for LFS +- Apply Darwin patches for 64-bit file offsets to contrib/minizip [Slack] +- Fix zlib.h LFS support when Z_PREFIX used +- Add updated as400 support (removed from old) [Monnerat] +- Avoid deflate sensitivity to volatile input data +- Avoid division in adler32_combine for NO_DIVIDE +- Clarify the use of Z_FINISH with deflateBound() amount of space +- Set binary for output file in puff.c +- Use u4 type for crc_table to avoid conversion warnings +- Apply casts in zlib.h to avoid conversion warnings +- Add OF to prototypes for adler32_combine_ and crc32_combine_ [Miller] +- Improve inflateSync() documentation to note indeterminancy +- Add deflatePending() function to return the amount of pending output +- Correct the spelling of "specification" in FAQ [Randers-Pehrson] +- Add a check in configure for stdarg.h, use for gzprintf() +- Check that pointers fit in ints when gzprint() compiled old style +- Add dummy name before $(SHAREDLIBV) in Makefile [Bar-Lev, Bowler] +- Delete line in configure that adds -L. libz.a to LDFLAGS [Weigelt] +- Add debug records in assmebler code [Londer] +- Update RFC references to use http://tools.ietf.org/html/... [Li] +- Add --archs option, use of libtool to configure for Mac OS X [Borstel] + +Changes in 1.2.5 (19 Apr 2010) +- Disable visibility attribute in win32/Makefile.gcc [Bar-Lev] +- Default to libdir as sharedlibdir in configure [Nieder] +- Update copyright dates on modified source files +- Update trees.c to be able to generate modified trees.h +- Exit configure for MinGW, suggesting win32/Makefile.gcc +- Check for NULL path in gz_open [Homurlu] + +Changes in 1.2.4.5 (18 Apr 2010) +- Set sharedlibdir in configure [Torok] +- Set LDFLAGS in Makefile.in [Bar-Lev] +- Avoid mkdir objs race condition in Makefile.in [Bowler] +- Add ZLIB_INTERNAL in front of internal inter-module functions and arrays +- Define ZLIB_INTERNAL to hide internal functions and arrays for GNU C +- Don't use hidden attribute when it is a warning generator (e.g. Solaris) + +Changes in 1.2.4.4 (18 Apr 2010) +- Fix CROSS_PREFIX executable testing, CHOST extract, mingw* [Torok] +- Undefine _LARGEFILE64_SOURCE in zconf.h if it is zero, but not if empty +- Try to use bash or ksh regardless of functionality of /bin/sh +- Fix configure incompatibility with NetBSD sh +- Remove attempt to run under bash or ksh since have better NetBSD fix +- Fix win32/Makefile.gcc for MinGW [Bar-Lev] +- Add diagnostic messages when using CROSS_PREFIX in configure +- Added --sharedlibdir option to configure [Weigelt] +- Use hidden visibility attribute when available [Frysinger] + +Changes in 1.2.4.3 (10 Apr 2010) +- Only use CROSS_PREFIX in configure for ar and ranlib if they exist +- Use CROSS_PREFIX for nm [Bar-Lev] +- Assume _LARGEFILE64_SOURCE defined is equivalent to true +- Avoid use of undefined symbols in #if with && and || +- Make *64 prototypes in gzguts.h consistent with functions +- Add -shared load option for MinGW in configure [Bowler] +- Move z_off64_t to public interface, use instead of off64_t +- Remove ! from shell test in configure (not portable to Solaris) +- Change +0 macro tests to -0 for possibly increased portability + +Changes in 1.2.4.2 (9 Apr 2010) +- Add consistent carriage returns to readme.txt's in masmx86 and masmx64 +- Really provide prototypes for *64 functions when building without LFS +- Only define unlink() in minigzip.c if unistd.h not included +- Update README to point to contrib/vstudio project files +- Move projects/vc6 to old/ and remove projects/ +- Include stdlib.h in minigzip.c for setmode() definition under WinCE +- Clean up assembler builds in win32/Makefile.msc [Rowe] +- Include sys/types.h for Microsoft for off_t definition +- Fix memory leak on error in gz_open() +- Symbolize nm as $NM in configure [Weigelt] +- Use TEST_LDSHARED instead of LDSHARED to link test programs [Weigelt] +- Add +0 to _FILE_OFFSET_BITS and _LFS64_LARGEFILE in case not defined +- Fix bug in gzeof() to take into account unused input data +- Avoid initialization of structures with variables in puff.c +- Updated win32/README-WIN32.txt [Rowe] + +Changes in 1.2.4.1 (28 Mar 2010) +- Remove the use of [a-z] constructs for sed in configure [gentoo 310225] +- Remove $(SHAREDLIB) from LIBS in Makefile.in [Creech] +- Restore "for debugging" comment on sprintf() in gzlib.c +- Remove fdopen for MVS from gzguts.h +- Put new README-WIN32.txt in win32 [Rowe] +- Add check for shell to configure and invoke another shell if needed +- Fix big fat stinking bug in gzseek() on uncompressed files +- Remove vestigial F_OPEN64 define in zutil.h +- Set and check the value of _LARGEFILE_SOURCE and _LARGEFILE64_SOURCE +- Avoid errors on non-LFS systems when applications define LFS macros +- Set EXE to ".exe" in configure for MINGW [Kahle] +- Match crc32() in crc32.c exactly to the prototype in zlib.h [Sherrill] +- Add prefix for cross-compilation in win32/makefile.gcc [Bar-Lev] +- Add DLL install in win32/makefile.gcc [Bar-Lev] +- Allow Linux* or linux* from uname in configure [Bar-Lev] +- Allow ldconfig to be redefined in configure and Makefile.in [Bar-Lev] +- Add cross-compilation prefixes to configure [Bar-Lev] +- Match type exactly in gz_load() invocation in gzread.c +- Match type exactly of zcalloc() in zutil.c to zlib.h alloc_func +- Provide prototypes for *64 functions when building zlib without LFS +- Don't use -lc when linking shared library on MinGW +- Remove errno.h check in configure and vestigial errno code in zutil.h + +Changes in 1.2.4 (14 Mar 2010) +- Fix VER3 extraction in configure for no fourth subversion +- Update zlib.3, add docs to Makefile.in to make .pdf out of it +- Add zlib.3.pdf to distribution +- Don't set error code in gzerror() if passed pointer is NULL +- Apply destination directory fixes to CMakeLists.txt [Lowman] +- Move #cmakedefine's to a new zconf.in.cmakein +- Restore zconf.h for builds that don't use configure or cmake +- Add distclean to dummy Makefile for convenience +- Update and improve INDEX, README, and FAQ +- Update CMakeLists.txt for the return of zconf.h [Lowman] +- Update contrib/vstudio/vc9 and vc10 [Vollant] +- Change libz.dll.a back to libzdll.a in win32/Makefile.gcc +- Apply license and readme changes to contrib/asm686 [Raiter] +- Check file name lengths and add -c option in minigzip.c [Li] +- Update contrib/amd64 and contrib/masmx86/ [Vollant] +- Avoid use of "eof" parameter in trees.c to not shadow library variable +- Update make_vms.com for removal of zlibdefs.h [Zinser] +- Update assembler code and vstudio projects in contrib [Vollant] +- Remove outdated assembler code contrib/masm686 and contrib/asm586 +- Remove old vc7 and vc8 from contrib/vstudio +- Update win32/Makefile.msc, add ZLIB_VER_SUBREVISION [Rowe] +- Fix memory leaks in gzclose_r() and gzclose_w(), file leak in gz_open() +- Add contrib/gcc_gvmat64 for longest_match and inflate_fast [Vollant] +- Remove *64 functions from win32/zlib.def (they're not 64-bit yet) +- Fix bug in void-returning vsprintf() case in gzwrite.c +- Fix name change from inflate.h in contrib/inflate86/inffas86.c +- Check if temporary file exists before removing in make_vms.com [Zinser] +- Fix make install and uninstall for --static option +- Fix usage of _MSC_VER in gzguts.h and zutil.h [Truta] +- Update readme.txt in contrib/masmx64 and masmx86 to assemble + +Changes in 1.2.3.9 (21 Feb 2010) +- Expunge gzio.c +- Move as400 build information to old +- Fix updates in contrib/minizip and contrib/vstudio +- Add const to vsnprintf test in configure to avoid warnings [Weigelt] +- Delete zconf.h (made by configure) [Weigelt] +- Change zconf.in.h to zconf.h.in per convention [Weigelt] +- Check for NULL buf in gzgets() +- Return empty string for gzgets() with len == 1 (like fgets()) +- Fix description of gzgets() in zlib.h for end-of-file, NULL return +- Update minizip to 1.1 [Vollant] +- Avoid MSVC loss of data warnings in gzread.c, gzwrite.c +- Note in zlib.h that gzerror() should be used to distinguish from EOF +- Remove use of snprintf() from gzlib.c +- Fix bug in gzseek() +- Update contrib/vstudio, adding vc9 and vc10 [Kuno, Vollant] +- Fix zconf.h generation in CMakeLists.txt [Lowman] +- Improve comments in zconf.h where modified by configure + +Changes in 1.2.3.8 (13 Feb 2010) +- Clean up text files (tabs, trailing whitespace, etc.) [Oberhumer] +- Use z_off64_t in gz_zero() and gz_skip() to match state->skip +- Avoid comparison problem when sizeof(int) == sizeof(z_off64_t) +- Revert to Makefile.in from 1.2.3.6 (live with the clutter) +- Fix missing error return in gzflush(), add zlib.h note +- Add *64 functions to zlib.map [Levin] +- Fix signed/unsigned comparison in gz_comp() +- Use SFLAGS when testing shared linking in configure +- Add --64 option to ./configure to use -m64 with gcc +- Fix ./configure --help to correctly name options +- Have make fail if a test fails [Levin] +- Avoid buffer overrun in contrib/masmx64/gvmat64.asm [Simpson] +- Remove assembler object files from contrib + +Changes in 1.2.3.7 (24 Jan 2010) +- Always gzopen() with O_LARGEFILE if available +- Fix gzdirect() to work immediately after gzopen() or gzdopen() +- Make gzdirect() more precise when the state changes while reading +- Improve zlib.h documentation in many places +- Catch memory allocation failure in gz_open() +- Complete close operation if seek forward in gzclose_w() fails +- Return Z_ERRNO from gzclose_r() if close() fails +- Return Z_STREAM_ERROR instead of EOF for gzclose() being passed NULL +- Return zero for gzwrite() errors to match zlib.h description +- Return -1 on gzputs() error to match zlib.h description +- Add zconf.in.h to allow recovery from configure modification [Weigelt] +- Fix static library permissions in Makefile.in [Weigelt] +- Avoid warnings in configure tests that hide functionality [Weigelt] +- Add *BSD and DragonFly to Linux case in configure [gentoo 123571] +- Change libzdll.a to libz.dll.a in win32/Makefile.gcc [gentoo 288212] +- Avoid access of uninitialized data for first inflateReset2 call [Gomes] +- Keep object files in subdirectories to reduce the clutter somewhat +- Remove default Makefile and zlibdefs.h, add dummy Makefile +- Add new external functions to Z_PREFIX, remove duplicates, z_z_ -> z_ +- Remove zlibdefs.h completely -- modify zconf.h instead + +Changes in 1.2.3.6 (17 Jan 2010) +- Avoid void * arithmetic in gzread.c and gzwrite.c +- Make compilers happier with const char * for gz_error message +- Avoid unused parameter warning in inflate.c +- Avoid signed-unsigned comparison warning in inflate.c +- Indent #pragma's for traditional C +- Fix usage of strwinerror() in glib.c, change to gz_strwinerror() +- Correct email address in configure for system options +- Update make_vms.com and add make_vms.com to contrib/minizip [Zinser] +- Update zlib.map [Brown] +- Fix Makefile.in for Solaris 10 make of example64 and minizip64 [Torok] +- Apply various fixes to CMakeLists.txt [Lowman] +- Add checks on len in gzread() and gzwrite() +- Add error message for no more room for gzungetc() +- Remove zlib version check in gzwrite() +- Defer compression of gzprintf() result until need to +- Use snprintf() in gzdopen() if available +- Remove USE_MMAP configuration determination (only used by minigzip) +- Remove examples/pigz.c (available separately) +- Update examples/gun.c to 1.6 + +Changes in 1.2.3.5 (8 Jan 2010) +- Add space after #if in zutil.h for some compilers +- Fix relatively harmless bug in deflate_fast() [Exarevsky] +- Fix same problem in deflate_slow() +- Add $(SHAREDLIBV) to LIBS in Makefile.in [Brown] +- Add deflate_rle() for faster Z_RLE strategy run-length encoding +- Add deflate_huff() for faster Z_HUFFMAN_ONLY encoding +- Change name of "write" variable in inffast.c to avoid library collisions +- Fix premature EOF from gzread() in gzio.c [Brown] +- Use zlib header window size if windowBits is 0 in inflateInit2() +- Remove compressBound() call in deflate.c to avoid linking compress.o +- Replace use of errno in gz* with functions, support WinCE [Alves] +- Provide alternative to perror() in minigzip.c for WinCE [Alves] +- Don't use _vsnprintf on later versions of MSVC [Lowman] +- Add CMake build script and input file [Lowman] +- Update contrib/minizip to 1.1 [Svensson, Vollant] +- Moved nintendods directory from contrib to . +- Replace gzio.c with a new set of routines with the same functionality +- Add gzbuffer(), gzoffset(), gzclose_r(), gzclose_w() as part of above +- Update contrib/minizip to 1.1b +- Change gzeof() to return 0 on error instead of -1 to agree with zlib.h + +Changes in 1.2.3.4 (21 Dec 2009) +- Use old school .SUFFIXES in Makefile.in for FreeBSD compatibility +- Update comments in configure and Makefile.in for default --shared +- Fix test -z's in configure [Marquess] +- Build examplesh and minigzipsh when not testing +- Change NULL's to Z_NULL's in deflate.c and in comments in zlib.h +- Import LDFLAGS from the environment in configure +- Fix configure to populate SFLAGS with discovered CFLAGS options +- Adapt make_vms.com to the new Makefile.in [Zinser] +- Add zlib2ansi script for C++ compilation [Marquess] +- Add _FILE_OFFSET_BITS=64 test to make test (when applicable) +- Add AMD64 assembler code for longest match to contrib [Teterin] +- Include options from $SFLAGS when doing $LDSHARED +- Simplify 64-bit file support by introducing z_off64_t type +- Make shared object files in objs directory to work around old Sun cc +- Use only three-part version number for Darwin shared compiles +- Add rc option to ar in Makefile.in for when ./configure not run +- Add -WI,-rpath,. to LDFLAGS for OSF 1 V4* +- Set LD_LIBRARYN32_PATH for SGI IRIX shared compile +- Protect against _FILE_OFFSET_BITS being defined when compiling zlib +- Rename Makefile.in targets allstatic to static and allshared to shared +- Fix static and shared Makefile.in targets to be independent +- Correct error return bug in gz_open() by setting state [Brown] +- Put spaces before ;;'s in configure for better sh compatibility +- Add pigz.c (parallel implementation of gzip) to examples/ +- Correct constant in crc32.c to UL [Leventhal] +- Reject negative lengths in crc32_combine() +- Add inflateReset2() function to work like inflateEnd()/inflateInit2() +- Include sys/types.h for _LARGEFILE64_SOURCE [Brown] +- Correct typo in doc/algorithm.txt [Janik] +- Fix bug in adler32_combine() [Zhu] +- Catch missing-end-of-block-code error in all inflates and in puff + Assures that random input to inflate eventually results in an error +- Added enough.c (calculation of ENOUGH for inftrees.h) to examples/ +- Update ENOUGH and its usage to reflect discovered bounds +- Fix gzerror() error report on empty input file [Brown] +- Add ush casts in trees.c to avoid pedantic runtime errors +- Fix typo in zlib.h uncompress() description [Reiss] +- Correct inflate() comments with regard to automatic header detection +- Remove deprecation comment on Z_PARTIAL_FLUSH (it stays) +- Put new version of gzlog (2.0) in examples with interruption recovery +- Add puff compile option to permit invalid distance-too-far streams +- Add puff TEST command options, ability to read piped input +- Prototype the *64 functions in zlib.h when _FILE_OFFSET_BITS == 64, but + _LARGEFILE64_SOURCE not defined +- Fix Z_FULL_FLUSH to truly erase the past by resetting s->strstart +- Fix deflateSetDictionary() to use all 32K for output consistency +- Remove extraneous #define MIN_LOOKAHEAD in deflate.c (in deflate.h) +- Clear bytes after deflate lookahead to avoid use of uninitialized data +- Change a limit in inftrees.c to be more transparent to Coverity Prevent +- Update win32/zlib.def with exported symbols from zlib.h +- Correct spelling errors in zlib.h [Willem, Sobrado] +- Allow Z_BLOCK for deflate() to force a new block +- Allow negative bits in inflatePrime() to delete existing bit buffer +- Add Z_TREES flush option to inflate() to return at end of trees +- Add inflateMark() to return current state information for random access +- Add Makefile for NintendoDS to contrib [Costa] +- Add -w in configure compile tests to avoid spurious warnings [Beucler] +- Fix typos in zlib.h comments for deflateSetDictionary() +- Fix EOF detection in transparent gzread() [Maier] + +Changes in 1.2.3.3 (2 October 2006) +- Make --shared the default for configure, add a --static option +- Add compile option to permit invalid distance-too-far streams +- Add inflateUndermine() function which is required to enable above +- Remove use of "this" variable name for C++ compatibility [Marquess] +- Add testing of shared library in make test, if shared library built +- Use ftello() and fseeko() if available instead of ftell() and fseek() +- Provide two versions of all functions that use the z_off_t type for + binary compatibility -- a normal version and a 64-bit offset version, + per the Large File Support Extension when _LARGEFILE64_SOURCE is + defined; use the 64-bit versions by default when _FILE_OFFSET_BITS + is defined to be 64 +- Add a --uname= option to configure to perhaps help with cross-compiling + +Changes in 1.2.3.2 (3 September 2006) +- Turn off silly Borland warnings [Hay] +- Use off64_t and define _LARGEFILE64_SOURCE when present +- Fix missing dependency on inffixed.h in Makefile.in +- Rig configure --shared to build both shared and static [Teredesai, Truta] +- Remove zconf.in.h and instead create a new zlibdefs.h file +- Fix contrib/minizip/unzip.c non-encrypted after encrypted [Vollant] +- Add treebuild.xml (see http://treebuild.metux.de/) [Weigelt] + +Changes in 1.2.3.1 (16 August 2006) +- Add watcom directory with OpenWatcom make files [Daniel] +- Remove #undef of FAR in zconf.in.h for MVS [Fedtke] +- Update make_vms.com [Zinser] +- Use -fPIC for shared build in configure [Teredesai, Nicholson] +- Use only major version number for libz.so on IRIX and OSF1 [Reinholdtsen] +- Use fdopen() (not _fdopen()) for Interix in zutil.h [BŠck] +- Add some FAQ entries about the contrib directory +- Update the MVS question in the FAQ +- Avoid extraneous reads after EOF in gzio.c [Brown] +- Correct spelling of "successfully" in gzio.c [Randers-Pehrson] +- Add comments to zlib.h about gzerror() usage [Brown] +- Set extra flags in gzip header in gzopen() like deflate() does +- Make configure options more compatible with double-dash conventions + [Weigelt] +- Clean up compilation under Solaris SunStudio cc [Rowe, Reinholdtsen] +- Fix uninstall target in Makefile.in [Truta] +- Add pkgconfig support [Weigelt] +- Use $(DESTDIR) macro in Makefile.in [Reinholdtsen, Weigelt] +- Replace set_data_type() with a more accurate detect_data_type() in + trees.c, according to the txtvsbin.txt document [Truta] +- Swap the order of #include and #include "zlib.h" in + gzio.c, example.c and minigzip.c [Truta] +- Shut up annoying VS2005 warnings about standard C deprecation [Rowe, + Truta] (where?) +- Fix target "clean" from win32/Makefile.bor [Truta] +- Create .pdb and .manifest files in win32/makefile.msc [Ziegler, Rowe] +- Update zlib www home address in win32/DLL_FAQ.txt [Truta] +- Update contrib/masmx86/inffas32.asm for VS2005 [Vollant, Van Wassenhove] +- Enable browse info in the "Debug" and "ASM Debug" configurations in + the Visual C++ 6 project, and set (non-ASM) "Debug" as default [Truta] +- Add pkgconfig support [Weigelt] +- Add ZLIB_VER_MAJOR, ZLIB_VER_MINOR and ZLIB_VER_REVISION in zlib.h, + for use in win32/zlib1.rc [Polushin, Rowe, Truta] +- Add a document that explains the new text detection scheme to + doc/txtvsbin.txt [Truta] +- Add rfc1950.txt, rfc1951.txt and rfc1952.txt to doc/ [Truta] +- Move algorithm.txt into doc/ [Truta] +- Synchronize FAQ with website +- Fix compressBound(), was low for some pathological cases [Fearnley] +- Take into account wrapper variations in deflateBound() +- Set examples/zpipe.c input and output to binary mode for Windows +- Update examples/zlib_how.html with new zpipe.c (also web site) +- Fix some warnings in examples/gzlog.c and examples/zran.c (it seems + that gcc became pickier in 4.0) +- Add zlib.map for Linux: "All symbols from zlib-1.1.4 remain + un-versioned, the patch adds versioning only for symbols introduced in + zlib-1.2.0 or later. It also declares as local those symbols which are + not designed to be exported." [Levin] +- Update Z_PREFIX list in zconf.in.h, add --zprefix option to configure +- Do not initialize global static by default in trees.c, add a response + NO_INIT_GLOBAL_POINTERS to initialize them if needed [Marquess] +- Don't use strerror() in gzio.c under WinCE [Yakimov] +- Don't use errno.h in zutil.h under WinCE [Yakimov] +- Move arguments for AR to its usage to allow replacing ar [Marot] +- Add HAVE_VISIBILITY_PRAGMA in zconf.in.h for Mozilla [Randers-Pehrson] +- Improve inflateInit() and inflateInit2() documentation +- Fix structure size comment in inflate.h +- Change configure help option from --h* to --help [Santos] + +Changes in 1.2.3 (18 July 2005) +- Apply security vulnerability fixes to contrib/infback9 as well +- Clean up some text files (carriage returns, trailing space) +- Update testzlib, vstudio, masmx64, and masmx86 in contrib [Vollant] + +Changes in 1.2.2.4 (11 July 2005) +- Add inflatePrime() function for starting inflation at bit boundary +- Avoid some Visual C warnings in deflate.c +- Avoid more silly Visual C warnings in inflate.c and inftrees.c for 64-bit + compile +- Fix some spelling errors in comments [Betts] +- Correct inflateInit2() error return documentation in zlib.h +- Add zran.c example of compressed data random access to examples + directory, shows use of inflatePrime() +- Fix cast for assignments to strm->state in inflate.c and infback.c +- Fix zlibCompileFlags() in zutil.c to use 1L for long shifts [Oberhumer] +- Move declarations of gf2 functions to right place in crc32.c [Oberhumer] +- Add cast in trees.c t avoid a warning [Oberhumer] +- Avoid some warnings in fitblk.c, gun.c, gzjoin.c in examples [Oberhumer] +- Update make_vms.com [Zinser] +- Initialize state->write in inflateReset() since copied in inflate_fast() +- Be more strict on incomplete code sets in inflate_table() and increase + ENOUGH and MAXD -- this repairs a possible security vulnerability for + invalid inflate input. Thanks to Tavis Ormandy and Markus Oberhumer for + discovering the vulnerability and providing test cases. +- Add ia64 support to configure for HP-UX [Smith] +- Add error return to gzread() for format or i/o error [Levin] +- Use malloc.h for OS/2 [Necasek] + +Changes in 1.2.2.3 (27 May 2005) +- Replace 1U constants in inflate.c and inftrees.c for 64-bit compile +- Typecast fread() return values in gzio.c [Vollant] +- Remove trailing space in minigzip.c outmode (VC++ can't deal with it) +- Fix crc check bug in gzread() after gzungetc() [Heiner] +- Add the deflateTune() function to adjust internal compression parameters +- Add a fast gzip decompressor, gun.c, to examples (use of inflateBack) +- Remove an incorrect assertion in examples/zpipe.c +- Add C++ wrapper in infback9.h [Donais] +- Fix bug in inflateCopy() when decoding fixed codes +- Note in zlib.h how much deflateSetDictionary() actually uses +- Remove USE_DICT_HEAD in deflate.c (would mess up inflate if used) +- Add _WIN32_WCE to define WIN32 in zconf.in.h [Spencer] +- Don't include stderr.h or errno.h for _WIN32_WCE in zutil.h [Spencer] +- Add gzdirect() function to indicate transparent reads +- Update contrib/minizip [Vollant] +- Fix compilation of deflate.c when both ASMV and FASTEST [Oberhumer] +- Add casts in crc32.c to avoid warnings [Oberhumer] +- Add contrib/masmx64 [Vollant] +- Update contrib/asm586, asm686, masmx86, testzlib, vstudio [Vollant] + +Changes in 1.2.2.2 (30 December 2004) +- Replace structure assignments in deflate.c and inflate.c with zmemcpy to + avoid implicit memcpy calls (portability for no-library compilation) +- Increase sprintf() buffer size in gzdopen() to allow for large numbers +- Add INFLATE_STRICT to check distances against zlib header +- Improve WinCE errno handling and comments [Chang] +- Remove comment about no gzip header processing in FAQ +- Add Z_FIXED strategy option to deflateInit2() to force fixed trees +- Add updated make_vms.com [Coghlan], update README +- Create a new "examples" directory, move gzappend.c there, add zpipe.c, + fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html. +- Add FAQ entry and comments in deflate.c on uninitialized memory access +- Add Solaris 9 make options in configure [Gilbert] +- Allow strerror() usage in gzio.c for STDC +- Fix DecompressBuf in contrib/delphi/ZLib.pas [ManChesTer] +- Update contrib/masmx86/inffas32.asm and gvmat32.asm [Vollant] +- Use z_off_t for adler32_combine() and crc32_combine() lengths +- Make adler32() much faster for small len +- Use OS_CODE in deflate() default gzip header + +Changes in 1.2.2.1 (31 October 2004) +- Allow inflateSetDictionary() call for raw inflate +- Fix inflate header crc check bug for file names and comments +- Add deflateSetHeader() and gz_header structure for custom gzip headers +- Add inflateGetheader() to retrieve gzip headers +- Add crc32_combine() and adler32_combine() functions +- Add alloc_func, free_func, in_func, out_func to Z_PREFIX list +- Use zstreamp consistently in zlib.h (inflate_back functions) +- Remove GUNZIP condition from definition of inflate_mode in inflate.h + and in contrib/inflate86/inffast.S [Truta, Anderson] +- Add support for AMD64 in contrib/inflate86/inffas86.c [Anderson] +- Update projects/README.projects and projects/visualc6 [Truta] +- Update win32/DLL_FAQ.txt [Truta] +- Avoid warning under NO_GZCOMPRESS in gzio.c; fix typo [Truta] +- Deprecate Z_ASCII; use Z_TEXT instead [Truta] +- Use a new algorithm for setting strm->data_type in trees.c [Truta] +- Do not define an exit() prototype in zutil.c unless DEBUG defined +- Remove prototype of exit() from zutil.c, example.c, minigzip.c [Truta] +- Add comment in zlib.h for Z_NO_FLUSH parameter to deflate() +- Fix Darwin build version identification [Peterson] + +Changes in 1.2.2 (3 October 2004) +- Update zlib.h comments on gzip in-memory processing +- Set adler to 1 in inflateReset() to support Java test suite [Walles] +- Add contrib/dotzlib [Ravn] +- Update win32/DLL_FAQ.txt [Truta] +- Update contrib/minizip [Vollant] +- Move contrib/visual-basic.txt to old/ [Truta] +- Fix assembler builds in projects/visualc6/ [Truta] + +Changes in 1.2.1.2 (9 September 2004) +- Update INDEX file +- Fix trees.c to update strm->data_type (no one ever noticed!) +- Fix bug in error case in inflate.c, infback.c, and infback9.c [Brown] +- Add "volatile" to crc table flag declaration (for DYNAMIC_CRC_TABLE) +- Add limited multitasking protection to DYNAMIC_CRC_TABLE +- Add NO_vsnprintf for VMS in zutil.h [Mozilla] +- Don't declare strerror() under VMS [Mozilla] +- Add comment to DYNAMIC_CRC_TABLE to use get_crc_table() to initialize +- Update contrib/ada [Anisimkov] +- Update contrib/minizip [Vollant] +- Fix configure to not hardcode directories for Darwin [Peterson] +- Fix gzio.c to not return error on empty files [Brown] +- Fix indentation; update version in contrib/delphi/ZLib.pas and + contrib/pascal/zlibpas.pas [Truta] +- Update mkasm.bat in contrib/masmx86 [Truta] +- Update contrib/untgz [Truta] +- Add projects/README.projects [Truta] +- Add project for MS Visual C++ 6.0 in projects/visualc6 [Cadieux, Truta] +- Update win32/DLL_FAQ.txt [Truta] +- Update list of Z_PREFIX symbols in zconf.h [Randers-Pehrson, Truta] +- Remove an unnecessary assignment to curr in inftrees.c [Truta] +- Add OS/2 to exe builds in configure [Poltorak] +- Remove err dummy parameter in zlib.h [Kientzle] + +Changes in 1.2.1.1 (9 January 2004) +- Update email address in README +- Several FAQ updates +- Fix a big fat bug in inftrees.c that prevented decoding valid + dynamic blocks with only literals and no distance codes -- + Thanks to "Hot Emu" for the bug report and sample file +- Add a note to puff.c on no distance codes case. + +Changes in 1.2.1 (17 November 2003) +- Remove a tab in contrib/gzappend/gzappend.c +- Update some interfaces in contrib for new zlib functions +- Update zlib version number in some contrib entries +- Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta] +- Support shared libraries on Hurd and KFreeBSD [Brown] +- Fix error in NO_DIVIDE option of adler32.c + +Changes in 1.2.0.8 (4 November 2003) +- Update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas +- Add experimental NO_DIVIDE #define in adler32.c + - Possibly faster on some processors (let me know if it is) +- Correct Z_BLOCK to not return on first inflate call if no wrap +- Fix strm->data_type on inflate() return to correctly indicate EOB +- Add deflatePrime() function for appending in the middle of a byte +- Add contrib/gzappend for an example of appending to a stream +- Update win32/DLL_FAQ.txt [Truta] +- Delete Turbo C comment in README [Truta] +- Improve some indentation in zconf.h [Truta] +- Fix infinite loop on bad input in configure script [Church] +- Fix gzeof() for concatenated gzip files [Johnson] +- Add example to contrib/visual-basic.txt [Michael B.] +- Add -p to mkdir's in Makefile.in [vda] +- Fix configure to properly detect presence or lack of printf functions +- Add AS400 support [Monnerat] +- Add a little Cygwin support [Wilson] + +Changes in 1.2.0.7 (21 September 2003) +- Correct some debug formats in contrib/infback9 +- Cast a type in a debug statement in trees.c +- Change search and replace delimiter in configure from % to # [Beebe] +- Update contrib/untgz to 0.2 with various fixes [Truta] +- Add build support for Amiga [Nikl] +- Remove some directories in old that have been updated to 1.2 +- Add dylib building for Mac OS X in configure and Makefile.in +- Remove old distribution stuff from Makefile +- Update README to point to DLL_FAQ.txt, and add comment on Mac OS X +- Update links in README + +Changes in 1.2.0.6 (13 September 2003) +- Minor FAQ updates +- Update contrib/minizip to 1.00 [Vollant] +- Remove test of gz functions in example.c when GZ_COMPRESS defined [Truta] +- Update POSTINC comment for 68060 [Nikl] +- Add contrib/infback9 with deflate64 decoding (unsupported) +- For MVS define NO_vsnprintf and undefine FAR [van Burik] +- Add pragma for fdopen on MVS [van Burik] + +Changes in 1.2.0.5 (8 September 2003) +- Add OF to inflateBackEnd() declaration in zlib.h +- Remember start when using gzdopen in the middle of a file +- Use internal off_t counters in gz* functions to properly handle seeks +- Perform more rigorous check for distance-too-far in inffast.c +- Add Z_BLOCK flush option to return from inflate at block boundary +- Set strm->data_type on return from inflate + - Indicate bits unused, if at block boundary, and if in last block +- Replace size_t with ptrdiff_t in crc32.c, and check for correct size +- Add condition so old NO_DEFLATE define still works for compatibility +- FAQ update regarding the Windows DLL [Truta] +- INDEX update: add qnx entry, remove aix entry [Truta] +- Install zlib.3 into mandir [Wilson] +- Move contrib/zlib_dll_FAQ.txt to win32/DLL_FAQ.txt; update [Truta] +- Adapt the zlib interface to the new DLL convention guidelines [Truta] +- Introduce ZLIB_WINAPI macro to allow the export of functions using + the WINAPI calling convention, for Visual Basic [Vollant, Truta] +- Update msdos and win32 scripts and makefiles [Truta] +- Export symbols by name, not by ordinal, in win32/zlib.def [Truta] +- Add contrib/ada [Anisimkov] +- Move asm files from contrib/vstudio/vc70_32 to contrib/asm386 [Truta] +- Rename contrib/asm386 to contrib/masmx86 [Truta, Vollant] +- Add contrib/masm686 [Truta] +- Fix offsets in contrib/inflate86 and contrib/masmx86/inffas32.asm + [Truta, Vollant] +- Update contrib/delphi; rename to contrib/pascal; add example [Truta] +- Remove contrib/delphi2; add a new contrib/delphi [Truta] +- Avoid inclusion of the nonstandard in contrib/iostream, + and fix some method prototypes [Truta] +- Fix the ZCR_SEED2 constant to avoid warnings in contrib/minizip + [Truta] +- Avoid the use of backslash (\) in contrib/minizip [Vollant] +- Fix file time handling in contrib/untgz; update makefiles [Truta] +- Update contrib/vstudio/vc70_32 to comply with the new DLL guidelines + [Vollant] +- Remove contrib/vstudio/vc15_16 [Vollant] +- Rename contrib/vstudio/vc70_32 to contrib/vstudio/vc7 [Truta] +- Update README.contrib [Truta] +- Invert the assignment order of match_head and s->prev[...] in + INSERT_STRING [Truta] +- Compare TOO_FAR with 32767 instead of 32768, to avoid 16-bit warnings + [Truta] +- Compare function pointers with 0, not with NULL or Z_NULL [Truta] +- Fix prototype of syncsearch in inflate.c [Truta] +- Introduce ASMINF macro to be enabled when using an ASM implementation + of inflate_fast [Truta] +- Change NO_DEFLATE to NO_GZCOMPRESS [Truta] +- Modify test_gzio in example.c to take a single file name as a + parameter [Truta] +- Exit the example.c program if gzopen fails [Truta] +- Add type casts around strlen in example.c [Truta] +- Remove casting to sizeof in minigzip.c; give a proper type + to the variable compared with SUFFIX_LEN [Truta] +- Update definitions of STDC and STDC99 in zconf.h [Truta] +- Synchronize zconf.h with the new Windows DLL interface [Truta] +- Use SYS16BIT instead of __32BIT__ to distinguish between + 16- and 32-bit platforms [Truta] +- Use far memory allocators in small 16-bit memory models for + Turbo C [Truta] +- Add info about the use of ASMV, ASMINF and ZLIB_WINAPI in + zlibCompileFlags [Truta] +- Cygwin has vsnprintf [Wilson] +- In Windows16, OS_CODE is 0, as in MSDOS [Truta] +- In Cygwin, OS_CODE is 3 (Unix), not 11 (Windows32) [Wilson] + +Changes in 1.2.0.4 (10 August 2003) +- Minor FAQ updates +- Be more strict when checking inflateInit2's windowBits parameter +- Change NO_GUNZIP compile option to NO_GZIP to cover deflate as well +- Add gzip wrapper option to deflateInit2 using windowBits +- Add updated QNX rule in configure and qnx directory [Bonnefoy] +- Make inflate distance-too-far checks more rigorous +- Clean up FAR usage in inflate +- Add casting to sizeof() in gzio.c and minigzip.c + +Changes in 1.2.0.3 (19 July 2003) +- Fix silly error in gzungetc() implementation [Vollant] +- Update contrib/minizip and contrib/vstudio [Vollant] +- Fix printf format in example.c +- Correct cdecl support in zconf.in.h [Anisimkov] +- Minor FAQ updates + +Changes in 1.2.0.2 (13 July 2003) +- Add ZLIB_VERNUM in zlib.h for numerical preprocessor comparisons +- Attempt to avoid warnings in crc32.c for pointer-int conversion +- Add AIX to configure, remove aix directory [Bakker] +- Add some casts to minigzip.c +- Improve checking after insecure sprintf() or vsprintf() calls +- Remove #elif's from crc32.c +- Change leave label to inf_leave in inflate.c and infback.c to avoid + library conflicts +- Remove inflate gzip decoding by default--only enable gzip decoding by + special request for stricter backward compatibility +- Add zlibCompileFlags() function to return compilation information +- More typecasting in deflate.c to avoid warnings +- Remove leading underscore from _Capital #defines [Truta] +- Fix configure to link shared library when testing +- Add some Windows CE target adjustments [Mai] +- Remove #define ZLIB_DLL in zconf.h [Vollant] +- Add zlib.3 [Rodgers] +- Update RFC URL in deflate.c and algorithm.txt [Mai] +- Add zlib_dll_FAQ.txt to contrib [Truta] +- Add UL to some constants [Truta] +- Update minizip and vstudio [Vollant] +- Remove vestigial NEED_DUMMY_RETURN from zconf.in.h +- Expand use of NO_DUMMY_DECL to avoid all dummy structures +- Added iostream3 to contrib [Schwardt] +- Replace rewind() with fseek() for WinCE [Truta] +- Improve setting of zlib format compression level flags + - Report 0 for huffman and rle strategies and for level == 0 or 1 + - Report 2 only for level == 6 +- Only deal with 64K limit when necessary at compile time [Truta] +- Allow TOO_FAR check to be turned off at compile time [Truta] +- Add gzclearerr() function [Souza] +- Add gzungetc() function + +Changes in 1.2.0.1 (17 March 2003) +- Add Z_RLE strategy for run-length encoding [Truta] + - When Z_RLE requested, restrict matches to distance one + - Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE +- Correct FASTEST compilation to allow level == 0 +- Clean up what gets compiled for FASTEST +- Incorporate changes to zconf.in.h [Vollant] + - Refine detection of Turbo C need for dummy returns + - Refine ZLIB_DLL compilation + - Include additional header file on VMS for off_t typedef +- Try to use _vsnprintf where it supplants vsprintf [Vollant] +- Add some casts in inffast.c +- Enchance comments in zlib.h on what happens if gzprintf() tries to + write more than 4095 bytes before compression +- Remove unused state from inflateBackEnd() +- Remove exit(0) from minigzip.c, example.c +- Get rid of all those darn tabs +- Add "check" target to Makefile.in that does the same thing as "test" +- Add "mostlyclean" and "maintainer-clean" targets to Makefile.in +- Update contrib/inflate86 [Anderson] +- Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant] +- Add msdos and win32 directories with makefiles [Truta] +- More additions and improvements to the FAQ + +Changes in 1.2.0 (9 March 2003) +- New and improved inflate code + - About 20% faster + - Does not allocate 32K window unless and until needed + - Automatically detects and decompresses gzip streams + - Raw inflate no longer needs an extra dummy byte at end + - Added inflateBack functions using a callback interface--even faster + than inflate, useful for file utilities (gzip, zip) + - Added inflateCopy() function to record state for random access on + externally generated deflate streams (e.g. in gzip files) + - More readable code (I hope) +- New and improved crc32() + - About 50% faster, thanks to suggestions from Rodney Brown +- Add deflateBound() and compressBound() functions +- Fix memory leak in deflateInit2() +- Permit setting dictionary for raw deflate (for parallel deflate) +- Fix const declaration for gzwrite() +- Check for some malloc() failures in gzio.c +- Fix bug in gzopen() on single-byte file 0x1f +- Fix bug in gzread() on concatenated file with 0x1f at end of buffer + and next buffer doesn't start with 0x8b +- Fix uncompress() to return Z_DATA_ERROR on truncated input +- Free memory at end of example.c +- Remove MAX #define in trees.c (conflicted with some libraries) +- Fix static const's in deflate.c, gzio.c, and zutil.[ch] +- Declare malloc() and free() in gzio.c if STDC not defined +- Use malloc() instead of calloc() in zutil.c if int big enough +- Define STDC for AIX +- Add aix/ with approach for compiling shared library on AIX +- Add HP-UX support for shared libraries in configure +- Add OpenUNIX support for shared libraries in configure +- Use $cc instead of gcc to build shared library +- Make prefix directory if needed when installing +- Correct Macintosh avoidance of typedef Byte in zconf.h +- Correct Turbo C memory allocation when under Linux +- Use libz.a instead of -lz in Makefile (assure use of compiled library) +- Update configure to check for snprintf or vsnprintf functions and their + return value, warn during make if using an insecure function +- Fix configure problem with compile-time knowledge of HAVE_UNISTD_H that + is lost when library is used--resolution is to build new zconf.h +- Documentation improvements (in zlib.h): + - Document raw deflate and inflate + - Update RFCs URL + - Point out that zlib and gzip formats are different + - Note that Z_BUF_ERROR is not fatal + - Document string limit for gzprintf() and possible buffer overflow + - Note requirement on avail_out when flushing + - Note permitted values of flush parameter of inflate() +- Add some FAQs (and even answers) to the FAQ +- Add contrib/inflate86/ for x86 faster inflate +- Add contrib/blast/ for PKWare Data Compression Library decompression +- Add contrib/puff/ simple inflate for deflate format description + +Changes in 1.1.4 (11 March 2002) +- ZFREE was repeated on same allocation on some error conditions. + This creates a security problem described in + http://www.zlib.org/advisory-2002-03-11.txt +- Returned incorrect error (Z_MEM_ERROR) on some invalid data +- Avoid accesses before window for invalid distances with inflate window + less than 32K. +- force windowBits > 8 to avoid a bug in the encoder for a window size + of 256 bytes. (A complete fix will be available in 1.1.5). + +Changes in 1.1.3 (9 July 1998) +- fix "an inflate input buffer bug that shows up on rare but persistent + occasions" (Mark) +- fix gzread and gztell for concatenated .gz files (Didier Le Botlan) +- fix gzseek(..., SEEK_SET) in write mode +- fix crc check after a gzeek (Frank Faubert) +- fix miniunzip when the last entry in a zip file is itself a zip file + (J Lillge) +- add contrib/asm586 and contrib/asm686 (Brian Raiter) + See http://www.muppetlabs.com/~breadbox/software/assembly.html +- add support for Delphi 3 in contrib/delphi (Bob Dellaca) +- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti) +- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren) +- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks) +- added a FAQ file + +- Support gzdopen on Mac with Metrowerks (Jason Linhart) +- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart) +- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young) +- avoid some warnings with Borland C (Tom Tanner) +- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant) +- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant) +- allow several arguments to configure (Tim Mooney, Frodo Looijaard) +- use libdir and includedir in Makefile.in (Tim Mooney) +- support shared libraries on OSF1 V4 (Tim Mooney) +- remove so_locations in "make clean" (Tim Mooney) +- fix maketree.c compilation error (Glenn, Mark) +- Python interface to zlib now in Python 1.5 (Jeremy Hylton) +- new Makefile.riscos (Rich Walker) +- initialize static descriptors in trees.c for embedded targets (Nick Smith) +- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith) +- add the OS/2 files in Makefile.in too (Andrew Zabolotny) +- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane) +- fix maketree.c to allow clean compilation of inffixed.h (Mark) +- fix parameter check in deflateCopy (Gunther Nikl) +- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler) +- Many portability patches by Christian Spieler: + . zutil.c, zutil.h: added "const" for zmem* + . Make_vms.com: fixed some typos + . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists + . msdos/Makefile.msc: remove "default rtl link library" info from obj files + . msdos/Makefile.*: use model-dependent name for the built zlib library + . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc: + new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT) +- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane) +- replace __far with _far for better portability (Christian Spieler, Tom Lane) +- fix test for errno.h in configure (Tim Newsham) + +Changes in 1.1.2 (19 March 98) +- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant) + See http://www.winimage.com/zLibDll/unzip.html +- preinitialize the inflate tables for fixed codes, to make the code + completely thread safe (Mark) +- some simplifications and slight speed-up to the inflate code (Mark) +- fix gzeof on non-compressed files (Allan Schrum) +- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs) +- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn) +- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny) +- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori) +- do not wrap extern "C" around system includes (Tom Lane) +- mention zlib binding for TCL in README (Andreas Kupries) +- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert) +- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson) +- allow "configure --prefix $HOME" (Tim Mooney) +- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson) +- move Makefile.sas to amiga/Makefile.sas + +Changes in 1.1.1 (27 Feb 98) +- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson) +- remove block truncation heuristic which had very marginal effect for zlib + (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the + compression ratio on some files. This also allows inlining _tr_tally for + matches in deflate_slow. +- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier) + +Changes in 1.1.0 (24 Feb 98) +- do not return STREAM_END prematurely in inflate (John Bowler) +- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler) +- compile with -DFASTEST to get compression code optimized for speed only +- in minigzip, try mmap'ing the input file first (Miguel Albrecht) +- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain + on Sun but significant on HP) + +- add a pointer to experimental unzip library in README (Gilles Vollant) +- initialize variable gcc in configure (Chris Herborth) + +Changes in 1.0.9 (17 Feb 1998) +- added gzputs and gzgets functions +- do not clear eof flag in gzseek (Mark Diekhans) +- fix gzseek for files in transparent mode (Mark Diekhans) +- do not assume that vsprintf returns the number of bytes written (Jens Krinke) +- replace EXPORT with ZEXPORT to avoid conflict with other programs +- added compress2 in zconf.h, zlib.def, zlib.dnt +- new asm code from Gilles Vollant in contrib/asm386 +- simplify the inflate code (Mark): + . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new() + . ZALLOC the length list in inflate_trees_fixed() instead of using stack + . ZALLOC the value area for huft_build() instead of using stack + . Simplify Z_FINISH check in inflate() + +- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8 +- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi) +- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with + the declaration of FAR (Gilles VOllant) +- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann) +- read_buf buf parameter of type Bytef* instead of charf* +- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout) +- do not redeclare unlink in minigzip.c for WIN32 (John Bowler) +- fix check for presence of directories in "make install" (Ian Willis) + +Changes in 1.0.8 (27 Jan 1998) +- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant) +- fix gzgetc and gzputc for big endian systems (Markus Oberhumer) +- added compress2() to allow setting the compression level +- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong) +- use constant arrays for the static trees in trees.c instead of computing + them at run time (thanks to Ken Raeburn for this suggestion). To create + trees.h, compile with GEN_TREES_H and run "make test". +- check return code of example in "make test" and display result +- pass minigzip command line options to file_compress +- simplifying code of inflateSync to avoid gcc 2.8 bug + +- support CC="gcc -Wall" in configure -s (QingLong) +- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn) +- fix test for shared library support to avoid compiler warnings +- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant) +- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit) +- do not use fdopen for Metrowerks on Mac (Brad Pettit)) +- add checks for gzputc and gzputc in example.c +- avoid warnings in gzio.c and deflate.c (Andreas Kleinert) +- use const for the CRC table (Ken Raeburn) +- fixed "make uninstall" for shared libraries +- use Tracev instead of Trace in infblock.c +- in example.c use correct compressed length for test_sync +- suppress +vnocompatwarnings in configure for HPUX (not always supported) + +Changes in 1.0.7 (20 Jan 1998) +- fix gzseek which was broken in write mode +- return error for gzseek to negative absolute position +- fix configure for Linux (Chun-Chung Chen) +- increase stack space for MSC (Tim Wegner) +- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant) +- define EXPORTVA for gzprintf (Gilles Vollant) +- added man page zlib.3 (Rick Rodgers) +- for contrib/untgz, fix makedir() and improve Makefile + +- check gzseek in write mode in example.c +- allocate extra buffer for seeks only if gzseek is actually called +- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant) +- add inflateSyncPoint in zconf.h +- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def + +Changes in 1.0.6 (19 Jan 1998) +- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and + gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code) +- Fix a deflate bug occurring only with compression level 0 (thanks to + Andy Buckler for finding this one). +- In minigzip, pass transparently also the first byte for .Z files. +- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress() +- check Z_FINISH in inflate (thanks to Marc Schluper) +- Implement deflateCopy (thanks to Adam Costello) +- make static libraries by default in configure, add --shared option. +- move MSDOS or Windows specific files to directory msdos +- suppress the notion of partial flush to simplify the interface + (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4) +- suppress history buffer provided by application to simplify the interface + (this feature was not implemented anyway in 1.0.4) +- next_in and avail_in must be initialized before calling inflateInit or + inflateInit2 +- add EXPORT in all exported functions (for Windows DLL) +- added Makefile.nt (thanks to Stephen Williams) +- added the unsupported "contrib" directory: + contrib/asm386/ by Gilles Vollant + 386 asm code replacing longest_match(). + contrib/iostream/ by Kevin Ruland + A C++ I/O streams interface to the zlib gz* functions + contrib/iostream2/ by Tyge Løvset + Another C++ I/O streams interface + contrib/untgz/ by "Pedro A. Aranda Guti\irrez" + A very simple tar.gz file extractor using zlib + contrib/visual-basic.txt by Carlos Rios + How to use compress(), uncompress() and the gz* functions from VB. +- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression + level) in minigzip (thanks to Tom Lane) + +- use const for rommable constants in deflate +- added test for gzseek and gztell in example.c +- add undocumented function inflateSyncPoint() (hack for Paul Mackerras) +- add undocumented function zError to convert error code to string + (for Tim Smithers) +- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code. +- Use default memcpy for Symantec MSDOS compiler. +- Add EXPORT keyword for check_func (needed for Windows DLL) +- add current directory to LD_LIBRARY_PATH for "make test" +- create also a link for libz.so.1 +- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura) +- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX) +- added -soname for Linux in configure (Chun-Chung Chen, +- assign numbers to the exported functions in zlib.def (for Windows DLL) +- add advice in zlib.h for best usage of deflateSetDictionary +- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn) +- allow compilation with ANSI keywords only enabled for TurboC in large model +- avoid "versionString"[0] (Borland bug) +- add NEED_DUMMY_RETURN for Borland +- use variable z_verbose for tracing in debug mode (L. Peter Deutsch). +- allow compilation with CC +- defined STDC for OS/2 (David Charlap) +- limit external names to 8 chars for MVS (Thomas Lund) +- in minigzip.c, use static buffers only for 16-bit systems +- fix suffix check for "minigzip -d foo.gz" +- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee) +- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau) +- added makelcc.bat for lcc-win32 (Tom St Denis) +- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe) +- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion. +- check for unistd.h in configure (for off_t) +- remove useless check parameter in inflate_blocks_free +- avoid useless assignment of s->check to itself in inflate_blocks_new +- do not flush twice in gzclose (thanks to Ken Raeburn) +- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h +- use NO_ERRNO_H instead of enumeration of operating systems with errno.h +- work around buggy fclose on pipes for HP/UX +- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson) +- fix configure if CC is already equal to gcc + +Changes in 1.0.5 (3 Jan 98) +- Fix inflate to terminate gracefully when fed corrupted or invalid data +- Use const for rommable constants in inflate +- Eliminate memory leaks on error conditions in inflate +- Removed some vestigial code in inflate +- Update web address in README + +Changes in 1.0.4 (24 Jul 96) +- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF + bit, so the decompressor could decompress all the correct data but went + on to attempt decompressing extra garbage data. This affected minigzip too. +- zlibVersion and gzerror return const char* (needed for DLL) +- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno) +- use z_error only for DEBUG (avoid problem with DLLs) + +Changes in 1.0.3 (2 Jul 96) +- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS + small and medium models; this makes the library incompatible with previous + versions for these models. (No effect in large model or on other systems.) +- return OK instead of BUF_ERROR if previous deflate call returned with + avail_out as zero but there is nothing to do +- added memcmp for non STDC compilers +- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly) +- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO) +- better check for 16-bit mode MSC (avoids problem with Symantec) + +Changes in 1.0.2 (23 May 96) +- added Windows DLL support +- added a function zlibVersion (for the DLL support) +- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model) +- Bytef is define's instead of typedef'd only for Borland C +- avoid reading uninitialized memory in example.c +- mention in README that the zlib format is now RFC1950 +- updated Makefile.dj2 +- added algorithm.doc + +Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion] +- fix array overlay in deflate.c which sometimes caused bad compressed data +- fix inflate bug with empty stored block +- fix MSDOS medium model which was broken in 0.99 +- fix deflateParams() which could generated bad compressed data. +- Bytef is define'd instead of typedef'ed (work around Borland bug) +- added an INDEX file +- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32), + Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas) +- speed up adler32 for modern machines without auto-increment +- added -ansi for IRIX in configure +- static_init_done in trees.c is an int +- define unlink as delete for VMS +- fix configure for QNX +- add configure branch for SCO and HPUX +- avoid many warnings (unused variables, dead assignments, etc...) +- no fdopen for BeOS +- fix the Watcom fix for 32 bit mode (define FAR as empty) +- removed redefinition of Byte for MKWERKS +- work around an MWKERKS bug (incorrect merge of all .h files) + +Changes in 0.99 (27 Jan 96) +- allow preset dictionary shared between compressor and decompressor +- allow compression level 0 (no compression) +- add deflateParams in zlib.h: allow dynamic change of compression level + and compression strategy. +- test large buffers and deflateParams in example.c +- add optional "configure" to build zlib as a shared library +- suppress Makefile.qnx, use configure instead +- fixed deflate for 64-bit systems (detected on Cray) +- fixed inflate_blocks for 64-bit systems (detected on Alpha) +- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2) +- always return Z_BUF_ERROR when deflate() has nothing to do +- deflateInit and inflateInit are now macros to allow version checking +- prefix all global functions and types with z_ with -DZ_PREFIX +- make falloc completely reentrant (inftrees.c) +- fixed very unlikely race condition in ct_static_init +- free in reverse order of allocation to help memory manager +- use zlib-1.0/* instead of zlib/* inside the tar.gz +- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith + -Wconversion -Wstrict-prototypes -Wmissing-prototypes" +- allow gzread on concatenated .gz files +- deflateEnd now returns Z_DATA_ERROR if it was premature +- deflate is finally (?) fully deterministic (no matches beyond end of input) +- Document Z_SYNC_FLUSH +- add uninstall in Makefile +- Check for __cpluplus in zlib.h +- Better test in ct_align for partial flush +- avoid harmless warnings for Borland C++ +- initialize hash_head in deflate.c +- avoid warning on fdopen (gzio.c) for HP cc -Aa +- include stdlib.h for STDC compilers +- include errno.h for Cray +- ignore error if ranlib doesn't exist +- call ranlib twice for NeXTSTEP +- use exec_prefix instead of prefix for libz.a +- renamed ct_* as _tr_* to avoid conflict with applications +- clear z->msg in inflateInit2 before any error return +- initialize opaque in example.c, gzio.c, deflate.c and inflate.c +- fixed typo in zconf.h (_GNUC__ => __GNUC__) +- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode) +- fix typo in Make_vms.com (f$trnlnm -> f$getsyi) +- in fcalloc, normalize pointer if size > 65520 bytes +- don't use special fcalloc for 32 bit Borland C++ +- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc... +- use Z_BINARY instead of BINARY +- document that gzclose after gzdopen will close the file +- allow "a" as mode in gzopen. +- fix error checking in gzread +- allow skipping .gz extra-field on pipes +- added reference to Perl interface in README +- put the crc table in FAR data (I dislike more and more the medium model :) +- added get_crc_table +- added a dimension to all arrays (Borland C can't count). +- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast +- guard against multiple inclusion of *.h (for precompiled header on Mac) +- Watcom C pretends to be Microsoft C small model even in 32 bit mode. +- don't use unsized arrays to avoid silly warnings by Visual C++: + warning C4746: 'inflate_mask' : unsized array treated as '__far' + (what's wrong with far data in far model?). +- define enum out of inflate_blocks_state to allow compilation with C++ + +Changes in 0.95 (16 Aug 95) +- fix MSDOS small and medium model (now easier to adapt to any compiler) +- inlined send_bits +- fix the final (:-) bug for deflate with flush (output was correct but + not completely flushed in rare occasions). +- default window size is same for compression and decompression + (it's now sufficient to set MAX_WBITS in zconf.h). +- voidp -> voidpf and voidnp -> voidp (for consistency with other + typedefs and because voidnp was not near in large model). + +Changes in 0.94 (13 Aug 95) +- support MSDOS medium model +- fix deflate with flush (could sometimes generate bad output) +- fix deflateReset (zlib header was incorrectly suppressed) +- added support for VMS +- allow a compression level in gzopen() +- gzflush now calls fflush +- For deflate with flush, flush even if no more input is provided. +- rename libgz.a as libz.a +- avoid complex expression in infcodes.c triggering Turbo C bug +- work around a problem with gcc on Alpha (in INSERT_STRING) +- don't use inline functions (problem with some gcc versions) +- allow renaming of Byte, uInt, etc... with #define. +- avoid warning about (unused) pointer before start of array in deflate.c +- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c +- avoid reserved word 'new' in trees.c + +Changes in 0.93 (25 June 95) +- temporarily disable inline functions +- make deflate deterministic +- give enough lookahead for PARTIAL_FLUSH +- Set binary mode for stdin/stdout in minigzip.c for OS/2 +- don't even use signed char in inflate (not portable enough) +- fix inflate memory leak for segmented architectures + +Changes in 0.92 (3 May 95) +- don't assume that char is signed (problem on SGI) +- Clear bit buffer when starting a stored block +- no memcpy on Pyramid +- suppressed inftest.c +- optimized fill_window, put longest_match inline for gcc +- optimized inflate on stored blocks. +- untabify all sources to simplify patches + +Changes in 0.91 (2 May 95) +- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h +- Document the memory requirements in zconf.h +- added "make install" +- fix sync search logic in inflateSync +- deflate(Z_FULL_FLUSH) now works even if output buffer too short +- after inflateSync, don't scare people with just "lo world" +- added support for DJGPP + +Changes in 0.9 (1 May 95) +- don't assume that zalloc clears the allocated memory (the TurboC bug + was Mark's bug after all :) +- let again gzread copy uncompressed data unchanged (was working in 0.71) +- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented +- added a test of inflateSync in example.c +- moved MAX_WBITS to zconf.h because users might want to change that. +- document explicitly that zalloc(64K) on MSDOS must return a normalized + pointer (zero offset) +- added Makefiles for Microsoft C, Turbo C, Borland C++ +- faster crc32() + +Changes in 0.8 (29 April 95) +- added fast inflate (inffast.c) +- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this + is incompatible with previous versions of zlib which returned Z_OK. +- work around a TurboC compiler bug (bad code for b << 0, see infutil.h) + (actually that was not a compiler bug, see 0.81 above) +- gzread no longer reads one extra byte in certain cases +- In gzio destroy(), don't reference a freed structure +- avoid many warnings for MSDOS +- avoid the ERROR symbol which is used by MS Windows + +Changes in 0.71 (14 April 95) +- Fixed more MSDOS compilation problems :( There is still a bug with + TurboC large model. + +Changes in 0.7 (14 April 95) +- Added full inflate support. +- Simplified the crc32() interface. The pre- and post-conditioning + (one's complement) is now done inside crc32(). WARNING: this is + incompatible with previous versions; see zlib.h for the new usage. + +Changes in 0.61 (12 April 95) +- workaround for a bug in TurboC. example and minigzip now work on MSDOS. + +Changes in 0.6 (11 April 95) +- added minigzip.c +- added gzdopen to reopen a file descriptor as gzFile +- added transparent reading of non-gziped files in gzread. +- fixed bug in gzread (don't read crc as data) +- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose). +- don't allocate big arrays in the stack (for MSDOS) +- fix some MSDOS compilation problems + +Changes in 0.5: +- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but + not yet Z_FULL_FLUSH. +- support decompression but only in a single step (forced Z_FINISH) +- added opaque object for zalloc and zfree. +- added deflateReset and inflateReset +- added a variable zlib_version for consistency checking. +- renamed the 'filter' parameter of deflateInit2 as 'strategy'. + Added Z_FILTERED and Z_HUFFMAN_ONLY constants. + +Changes in 0.4: +- avoid "zip" everywhere, use zlib instead of ziplib. +- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush + if compression method == 8. +- added adler32 and crc32 +- renamed deflateOptions as deflateInit2, call one or the other but not both +- added the method parameter for deflateInit2. +- added inflateInit2 +- simplied considerably deflateInit and inflateInit by not supporting + user-provided history buffer. This is supported only in deflateInit2 + and inflateInit2. + +Changes in 0.3: +- prefix all macro names with Z_ +- use Z_FINISH instead of deflateEnd to finish compression. +- added Z_HUFFMAN_ONLY +- added gzerror() diff --git a/3rdparty/zlib/FAQ b/3rdparty/zlib/FAQ index c154978f1..99b7cf92e 100644 --- a/3rdparty/zlib/FAQ +++ b/3rdparty/zlib/FAQ @@ -1,366 +1,368 @@ - - Frequently Asked Questions about zlib - - -If your question is not there, please check the zlib home page -http://zlib.net/ which may have more recent information. -The lastest zlib FAQ is at http://zlib.net/zlib_faq.html - - - 1. Is zlib Y2K-compliant? - - Yes. zlib doesn't handle dates. - - 2. Where can I get a Windows DLL version? - - The zlib sources can be compiled without change to produce a DLL. See the - file win32/DLL_FAQ.txt in the zlib distribution. Pointers to the - precompiled DLL are found in the zlib web site at http://zlib.net/ . - - 3. Where can I get a Visual Basic interface to zlib? - - See - * http://marknelson.us/1997/01/01/zlib-engine/ - * win32/DLL_FAQ.txt in the zlib distribution - - 4. compress() returns Z_BUF_ERROR. - - Make sure that before the call of compress(), the length of the compressed - buffer is equal to the available size of the compressed buffer and not - zero. For Visual Basic, check that this parameter is passed by reference - ("as any"), not by value ("as long"). - - 5. deflate() or inflate() returns Z_BUF_ERROR. - - Before making the call, make sure that avail_in and avail_out are not zero. - When setting the parameter flush equal to Z_FINISH, also make sure that - avail_out is big enough to allow processing all pending input. Note that a - Z_BUF_ERROR is not fatal--another call to deflate() or inflate() can be - made with more input or output space. A Z_BUF_ERROR may in fact be - unavoidable depending on how the functions are used, since it is not - possible to tell whether or not there is more output pending when - strm.avail_out returns with zero. See http://zlib.net/zlib_how.html for a - heavily annotated example. - - 6. Where's the zlib documentation (man pages, etc.)? - - It's in zlib.h . Examples of zlib usage are in the files example.c and - minigzip.c, with more in examples/ . - - 7. Why don't you use GNU autoconf or libtool or ...? - - Because we would like to keep zlib as a very small and simple package. - zlib is rather portable and doesn't need much configuration. - - 8. I found a bug in zlib. - - Most of the time, such problems are due to an incorrect usage of zlib. - Please try to reproduce the problem with a small program and send the - corresponding source to us at zlib@gzip.org . Do not send multi-megabyte - data files without prior agreement. - - 9. Why do I get "undefined reference to gzputc"? - - If "make test" produces something like - - example.o(.text+0x154): undefined reference to `gzputc' - - check that you don't have old files libz.* in /usr/lib, /usr/local/lib or - /usr/X11R6/lib. Remove any old versions, then do "make install". - -10. I need a Delphi interface to zlib. - - See the contrib/delphi directory in the zlib distribution. - -11. Can zlib handle .zip archives? - - Not by itself, no. See the directory contrib/minizip in the zlib - distribution. - -12. Can zlib handle .Z files? - - No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt - the code of uncompress on your own. - -13. How can I make a Unix shared library? - - make clean - ./configure -s - make - -14. How do I install a shared zlib library on Unix? - - After the above, then: - - make install - - However, many flavors of Unix come with a shared zlib already installed. - Before going to the trouble of compiling a shared version of zlib and - trying to install it, you may want to check if it's already there! If you - can #include , it's there. The -lz option will probably link to - it. You can check the version at the top of zlib.h or with the - ZLIB_VERSION symbol defined in zlib.h . - -15. I have a question about OttoPDF. - - We are not the authors of OttoPDF. The real author is on the OttoPDF web - site: Joel Hainley, jhainley@myndkryme.com. - -16. Can zlib decode Flate data in an Adobe PDF file? - - Yes. See http://www.pdflib.com/ . To modify PDF forms, see - http://sourceforge.net/projects/acroformtool/ . - -17. Why am I getting this "register_frame_info not found" error on Solaris? - - After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib - generates an error such as: - - ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so: - symbol __register_frame_info: referenced symbol not found - - The symbol __register_frame_info is not part of zlib, it is generated by - the C compiler (cc or gcc). You must recompile applications using zlib - which have this problem. This problem is specific to Solaris. See - http://www.sunfreeware.com for Solaris versions of zlib and applications - using zlib. - -18. Why does gzip give an error on a file I make with compress/deflate? - - The compress and deflate functions produce data in the zlib format, which - is different and incompatible with the gzip format. The gz* functions in - zlib on the other hand use the gzip format. Both the zlib and gzip formats - use the same compressed data format internally, but have different headers - and trailers around the compressed data. - -19. Ok, so why are there two different formats? - - The gzip format was designed to retain the directory information about a - single file, such as the name and last modification date. The zlib format - on the other hand was designed for in-memory and communication channel - applications, and has a much more compact header and trailer and uses a - faster integrity check than gzip. - -20. Well that's nice, but how do I make a gzip file in memory? - - You can request that deflate write the gzip format instead of the zlib - format using deflateInit2(). You can also request that inflate decode the - gzip format using inflateInit2(). Read zlib.h for more details. - -21. Is zlib thread-safe? - - Yes. However any library routines that zlib uses and any application- - provided memory allocation routines must also be thread-safe. zlib's gz* - functions use stdio library routines, and most of zlib's functions use the - library memory allocation routines by default. zlib's *Init* functions - allow for the application to provide custom memory allocation routines. - - Of course, you should only operate on any given zlib or gzip stream from a - single thread at a time. - -22. Can I use zlib in my commercial application? - - Yes. Please read the license in zlib.h. - -23. Is zlib under the GNU license? - - No. Please read the license in zlib.h. - -24. The license says that altered source versions must be "plainly marked". So - what exactly do I need to do to meet that requirement? - - You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In - particular, the final version number needs to be changed to "f", and an - identification string should be appended to ZLIB_VERSION. Version numbers - x.x.x.f are reserved for modifications to zlib by others than the zlib - maintainers. For example, if the version of the base zlib you are altering - is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and - ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also - update the version strings in deflate.c and inftrees.c. - - For altered source distributions, you should also note the origin and - nature of the changes in zlib.h, as well as in ChangeLog and README, along - with the dates of the alterations. The origin should include at least your - name (or your company's name), and an email address to contact for help or - issues with the library. - - Note that distributing a compiled zlib library along with zlib.h and - zconf.h is also a source distribution, and so you should change - ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes - in zlib.h as you would for a full source distribution. - -25. Will zlib work on a big-endian or little-endian architecture, and can I - exchange compressed data between them? - - Yes and yes. - -26. Will zlib work on a 64-bit machine? - - Yes. It has been tested on 64-bit machines, and has no dependence on any - data types being limited to 32-bits in length. If you have any - difficulties, please provide a complete problem report to zlib@gzip.org - -27. Will zlib decompress data from the PKWare Data Compression Library? - - No. The PKWare DCL uses a completely different compressed data format than - does PKZIP and zlib. However, you can look in zlib's contrib/blast - directory for a possible solution to your problem. - -28. Can I access data randomly in a compressed stream? - - No, not without some preparation. If when compressing you periodically use - Z_FULL_FLUSH, carefully write all the pending data at those points, and - keep an index of those locations, then you can start decompression at those - points. You have to be careful to not use Z_FULL_FLUSH too often, since it - can significantly degrade compression. Alternatively, you can scan a - deflate stream once to generate an index, and then use that index for - random access. See examples/zran.c . - -29. Does zlib work on MVS, OS/390, CICS, etc.? - - It has in the past, but we have not heard of any recent evidence. There - were working ports of zlib 1.1.4 to MVS, but those links no longer work. - If you know of recent, successful applications of zlib on these operating - systems, please let us know. Thanks. - -30. Is there some simpler, easier to read version of inflate I can look at to - understand the deflate format? - - First off, you should read RFC 1951. Second, yes. Look in zlib's - contrib/puff directory. - -31. Does zlib infringe on any patents? - - As far as we know, no. In fact, that was originally the whole point behind - zlib. Look here for some more information: - - http://www.gzip.org/#faq11 - -32. Can zlib work with greater than 4 GB of data? - - Yes. inflate() and deflate() will process any amount of data correctly. - Each call of inflate() or deflate() is limited to input and output chunks - of the maximum value that can be stored in the compiler's "unsigned int" - type, but there is no limit to the number of chunks. Note however that the - strm.total_in and strm_total_out counters may be limited to 4 GB. These - counters are provided as a convenience and are not used internally by - inflate() or deflate(). The application can easily set up its own counters - updated after each call of inflate() or deflate() to count beyond 4 GB. - compress() and uncompress() may be limited to 4 GB, since they operate in a - single call. gzseek() and gztell() may be limited to 4 GB depending on how - zlib is compiled. See the zlibCompileFlags() function in zlib.h. - - The word "may" appears several times above since there is a 4 GB limit only - if the compiler's "long" type is 32 bits. If the compiler's "long" type is - 64 bits, then the limit is 16 exabytes. - -33. Does zlib have any security vulnerabilities? - - The only one that we are aware of is potentially in gzprintf(). If zlib is - compiled to use sprintf() or vsprintf(), then there is no protection - against a buffer overflow of an 8K string space (or other value as set by - gzbuffer()), other than the caller of gzprintf() assuring that the output - will not exceed 8K. On the other hand, if zlib is compiled to use - snprintf() or vsnprintf(), which should normally be the case, then there is - no vulnerability. The ./configure script will display warnings if an - insecure variation of sprintf() will be used by gzprintf(). Also the - zlibCompileFlags() function will return information on what variant of - sprintf() is used by gzprintf(). - - If you don't have snprintf() or vsnprintf() and would like one, you can - find a portable implementation here: - - http://www.ijs.si/software/snprintf/ - - Note that you should be using the most recent version of zlib. Versions - 1.1.3 and before were subject to a double-free vulnerability, and versions - 1.2.1 and 1.2.2 were subject to an access exception when decompressing - invalid compressed data. - -34. Is there a Java version of zlib? - - Probably what you want is to use zlib in Java. zlib is already included - as part of the Java SDK in the java.util.zip package. If you really want - a version of zlib written in the Java language, look on the zlib home - page for links: http://zlib.net/ . - -35. I get this or that compiler or source-code scanner warning when I crank it - up to maximally-pedantic. Can't you guys write proper code? - - Many years ago, we gave up attempting to avoid warnings on every compiler - in the universe. It just got to be a waste of time, and some compilers - were downright silly as well as contradicted each other. So now, we simply - make sure that the code always works. - -36. Valgrind (or some similar memory access checker) says that deflate is - performing a conditional jump that depends on an uninitialized value. - Isn't that a bug? - - No. That is intentional for performance reasons, and the output of deflate - is not affected. This only started showing up recently since zlib 1.2.x - uses malloc() by default for allocations, whereas earlier versions used - calloc(), which zeros out the allocated memory. Even though the code was - correct, versions 1.2.4 and later was changed to not stimulate these - checkers. - -37. Will zlib read the (insert any ancient or arcane format here) compressed - data format? - - Probably not. Look in the comp.compression FAQ for pointers to various - formats and associated software. - -38. How can I encrypt/decrypt zip files with zlib? - - zlib doesn't support encryption. The original PKZIP encryption is very - weak and can be broken with freely available programs. To get strong - encryption, use GnuPG, http://www.gnupg.org/ , which already includes zlib - compression. For PKZIP compatible "encryption", look at - http://www.info-zip.org/ - -39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings? - - "gzip" is the gzip format, and "deflate" is the zlib format. They should - probably have called the second one "zlib" instead to avoid confusion with - the raw deflate compressed data format. While the HTTP 1.1 RFC 2616 - correctly points to the zlib specification in RFC 1950 for the "deflate" - transfer encoding, there have been reports of servers and browsers that - incorrectly produce or expect raw deflate data per the deflate - specficiation in RFC 1951, most notably Microsoft. So even though the - "deflate" transfer encoding using the zlib format would be the more - efficient approach (and in fact exactly what the zlib format was designed - for), using the "gzip" transfer encoding is probably more reliable due to - an unfortunate choice of name on the part of the HTTP 1.1 authors. - - Bottom line: use the gzip format for HTTP 1.1 encoding. - -40. Does zlib support the new "Deflate64" format introduced by PKWare? - - No. PKWare has apparently decided to keep that format proprietary, since - they have not documented it as they have previous compression formats. In - any case, the compression improvements are so modest compared to other more - modern approaches, that it's not worth the effort to implement. - -41. I'm having a problem with the zip functions in zlib, can you help? - - There are no zip functions in zlib. You are probably using minizip by - Giles Vollant, which is found in the contrib directory of zlib. It is not - part of zlib. In fact none of the stuff in contrib is part of zlib. The - files in there are not supported by the zlib authors. You need to contact - the authors of the respective contribution for help. - -42. The match.asm code in contrib is under the GNU General Public License. - Since it's part of zlib, doesn't that mean that all of zlib falls under the - GNU GPL? - - No. The files in contrib are not part of zlib. They were contributed by - other authors and are provided as a convenience to the user within the zlib - distribution. Each item in contrib has its own license. - -43. Is zlib subject to export controls? What is its ECCN? - - zlib is not subject to export controls, and so is classified as EAR99. - -44. Can you please sign these lengthy legal documents and fax them back to us - so that we can use your software in our product? - - No. Go away. Shoo. + + Frequently Asked Questions about zlib + + +If your question is not there, please check the zlib home page +http://zlib.net/ which may have more recent information. +The lastest zlib FAQ is at http://zlib.net/zlib_faq.html + + + 1. Is zlib Y2K-compliant? + + Yes. zlib doesn't handle dates. + + 2. Where can I get a Windows DLL version? + + The zlib sources can be compiled without change to produce a DLL. See the + file win32/DLL_FAQ.txt in the zlib distribution. Pointers to the + precompiled DLL are found in the zlib web site at http://zlib.net/ . + + 3. Where can I get a Visual Basic interface to zlib? + + See + * http://marknelson.us/1997/01/01/zlib-engine/ + * win32/DLL_FAQ.txt in the zlib distribution + + 4. compress() returns Z_BUF_ERROR. + + Make sure that before the call of compress(), the length of the compressed + buffer is equal to the available size of the compressed buffer and not + zero. For Visual Basic, check that this parameter is passed by reference + ("as any"), not by value ("as long"). + + 5. deflate() or inflate() returns Z_BUF_ERROR. + + Before making the call, make sure that avail_in and avail_out are not zero. + When setting the parameter flush equal to Z_FINISH, also make sure that + avail_out is big enough to allow processing all pending input. Note that a + Z_BUF_ERROR is not fatal--another call to deflate() or inflate() can be + made with more input or output space. A Z_BUF_ERROR may in fact be + unavoidable depending on how the functions are used, since it is not + possible to tell whether or not there is more output pending when + strm.avail_out returns with zero. See http://zlib.net/zlib_how.html for a + heavily annotated example. + + 6. Where's the zlib documentation (man pages, etc.)? + + It's in zlib.h . Examples of zlib usage are in the files test/example.c + and test/minigzip.c, with more in examples/ . + + 7. Why don't you use GNU autoconf or libtool or ...? + + Because we would like to keep zlib as a very small and simple package. + zlib is rather portable and doesn't need much configuration. + + 8. I found a bug in zlib. + + Most of the time, such problems are due to an incorrect usage of zlib. + Please try to reproduce the problem with a small program and send the + corresponding source to us at zlib@gzip.org . Do not send multi-megabyte + data files without prior agreement. + + 9. Why do I get "undefined reference to gzputc"? + + If "make test" produces something like + + example.o(.text+0x154): undefined reference to `gzputc' + + check that you don't have old files libz.* in /usr/lib, /usr/local/lib or + /usr/X11R6/lib. Remove any old versions, then do "make install". + +10. I need a Delphi interface to zlib. + + See the contrib/delphi directory in the zlib distribution. + +11. Can zlib handle .zip archives? + + Not by itself, no. See the directory contrib/minizip in the zlib + distribution. + +12. Can zlib handle .Z files? + + No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt + the code of uncompress on your own. + +13. How can I make a Unix shared library? + + By default a shared (and a static) library is built for Unix. So: + + make distclean + ./configure + make + +14. How do I install a shared zlib library on Unix? + + After the above, then: + + make install + + However, many flavors of Unix come with a shared zlib already installed. + Before going to the trouble of compiling a shared version of zlib and + trying to install it, you may want to check if it's already there! If you + can #include , it's there. The -lz option will probably link to + it. You can check the version at the top of zlib.h or with the + ZLIB_VERSION symbol defined in zlib.h . + +15. I have a question about OttoPDF. + + We are not the authors of OttoPDF. The real author is on the OttoPDF web + site: Joel Hainley, jhainley@myndkryme.com. + +16. Can zlib decode Flate data in an Adobe PDF file? + + Yes. See http://www.pdflib.com/ . To modify PDF forms, see + http://sourceforge.net/projects/acroformtool/ . + +17. Why am I getting this "register_frame_info not found" error on Solaris? + + After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib + generates an error such as: + + ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so: + symbol __register_frame_info: referenced symbol not found + + The symbol __register_frame_info is not part of zlib, it is generated by + the C compiler (cc or gcc). You must recompile applications using zlib + which have this problem. This problem is specific to Solaris. See + http://www.sunfreeware.com for Solaris versions of zlib and applications + using zlib. + +18. Why does gzip give an error on a file I make with compress/deflate? + + The compress and deflate functions produce data in the zlib format, which + is different and incompatible with the gzip format. The gz* functions in + zlib on the other hand use the gzip format. Both the zlib and gzip formats + use the same compressed data format internally, but have different headers + and trailers around the compressed data. + +19. Ok, so why are there two different formats? + + The gzip format was designed to retain the directory information about a + single file, such as the name and last modification date. The zlib format + on the other hand was designed for in-memory and communication channel + applications, and has a much more compact header and trailer and uses a + faster integrity check than gzip. + +20. Well that's nice, but how do I make a gzip file in memory? + + You can request that deflate write the gzip format instead of the zlib + format using deflateInit2(). You can also request that inflate decode the + gzip format using inflateInit2(). Read zlib.h for more details. + +21. Is zlib thread-safe? + + Yes. However any library routines that zlib uses and any application- + provided memory allocation routines must also be thread-safe. zlib's gz* + functions use stdio library routines, and most of zlib's functions use the + library memory allocation routines by default. zlib's *Init* functions + allow for the application to provide custom memory allocation routines. + + Of course, you should only operate on any given zlib or gzip stream from a + single thread at a time. + +22. Can I use zlib in my commercial application? + + Yes. Please read the license in zlib.h. + +23. Is zlib under the GNU license? + + No. Please read the license in zlib.h. + +24. The license says that altered source versions must be "plainly marked". So + what exactly do I need to do to meet that requirement? + + You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In + particular, the final version number needs to be changed to "f", and an + identification string should be appended to ZLIB_VERSION. Version numbers + x.x.x.f are reserved for modifications to zlib by others than the zlib + maintainers. For example, if the version of the base zlib you are altering + is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and + ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also + update the version strings in deflate.c and inftrees.c. + + For altered source distributions, you should also note the origin and + nature of the changes in zlib.h, as well as in ChangeLog and README, along + with the dates of the alterations. The origin should include at least your + name (or your company's name), and an email address to contact for help or + issues with the library. + + Note that distributing a compiled zlib library along with zlib.h and + zconf.h is also a source distribution, and so you should change + ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes + in zlib.h as you would for a full source distribution. + +25. Will zlib work on a big-endian or little-endian architecture, and can I + exchange compressed data between them? + + Yes and yes. + +26. Will zlib work on a 64-bit machine? + + Yes. It has been tested on 64-bit machines, and has no dependence on any + data types being limited to 32-bits in length. If you have any + difficulties, please provide a complete problem report to zlib@gzip.org + +27. Will zlib decompress data from the PKWare Data Compression Library? + + No. The PKWare DCL uses a completely different compressed data format than + does PKZIP and zlib. However, you can look in zlib's contrib/blast + directory for a possible solution to your problem. + +28. Can I access data randomly in a compressed stream? + + No, not without some preparation. If when compressing you periodically use + Z_FULL_FLUSH, carefully write all the pending data at those points, and + keep an index of those locations, then you can start decompression at those + points. You have to be careful to not use Z_FULL_FLUSH too often, since it + can significantly degrade compression. Alternatively, you can scan a + deflate stream once to generate an index, and then use that index for + random access. See examples/zran.c . + +29. Does zlib work on MVS, OS/390, CICS, etc.? + + It has in the past, but we have not heard of any recent evidence. There + were working ports of zlib 1.1.4 to MVS, but those links no longer work. + If you know of recent, successful applications of zlib on these operating + systems, please let us know. Thanks. + +30. Is there some simpler, easier to read version of inflate I can look at to + understand the deflate format? + + First off, you should read RFC 1951. Second, yes. Look in zlib's + contrib/puff directory. + +31. Does zlib infringe on any patents? + + As far as we know, no. In fact, that was originally the whole point behind + zlib. Look here for some more information: + + http://www.gzip.org/#faq11 + +32. Can zlib work with greater than 4 GB of data? + + Yes. inflate() and deflate() will process any amount of data correctly. + Each call of inflate() or deflate() is limited to input and output chunks + of the maximum value that can be stored in the compiler's "unsigned int" + type, but there is no limit to the number of chunks. Note however that the + strm.total_in and strm_total_out counters may be limited to 4 GB. These + counters are provided as a convenience and are not used internally by + inflate() or deflate(). The application can easily set up its own counters + updated after each call of inflate() or deflate() to count beyond 4 GB. + compress() and uncompress() may be limited to 4 GB, since they operate in a + single call. gzseek() and gztell() may be limited to 4 GB depending on how + zlib is compiled. See the zlibCompileFlags() function in zlib.h. + + The word "may" appears several times above since there is a 4 GB limit only + if the compiler's "long" type is 32 bits. If the compiler's "long" type is + 64 bits, then the limit is 16 exabytes. + +33. Does zlib have any security vulnerabilities? + + The only one that we are aware of is potentially in gzprintf(). If zlib is + compiled to use sprintf() or vsprintf(), then there is no protection + against a buffer overflow of an 8K string space (or other value as set by + gzbuffer()), other than the caller of gzprintf() assuring that the output + will not exceed 8K. On the other hand, if zlib is compiled to use + snprintf() or vsnprintf(), which should normally be the case, then there is + no vulnerability. The ./configure script will display warnings if an + insecure variation of sprintf() will be used by gzprintf(). Also the + zlibCompileFlags() function will return information on what variant of + sprintf() is used by gzprintf(). + + If you don't have snprintf() or vsnprintf() and would like one, you can + find a portable implementation here: + + http://www.ijs.si/software/snprintf/ + + Note that you should be using the most recent version of zlib. Versions + 1.1.3 and before were subject to a double-free vulnerability, and versions + 1.2.1 and 1.2.2 were subject to an access exception when decompressing + invalid compressed data. + +34. Is there a Java version of zlib? + + Probably what you want is to use zlib in Java. zlib is already included + as part of the Java SDK in the java.util.zip package. If you really want + a version of zlib written in the Java language, look on the zlib home + page for links: http://zlib.net/ . + +35. I get this or that compiler or source-code scanner warning when I crank it + up to maximally-pedantic. Can't you guys write proper code? + + Many years ago, we gave up attempting to avoid warnings on every compiler + in the universe. It just got to be a waste of time, and some compilers + were downright silly as well as contradicted each other. So now, we simply + make sure that the code always works. + +36. Valgrind (or some similar memory access checker) says that deflate is + performing a conditional jump that depends on an uninitialized value. + Isn't that a bug? + + No. That is intentional for performance reasons, and the output of deflate + is not affected. This only started showing up recently since zlib 1.2.x + uses malloc() by default for allocations, whereas earlier versions used + calloc(), which zeros out the allocated memory. Even though the code was + correct, versions 1.2.4 and later was changed to not stimulate these + checkers. + +37. Will zlib read the (insert any ancient or arcane format here) compressed + data format? + + Probably not. Look in the comp.compression FAQ for pointers to various + formats and associated software. + +38. How can I encrypt/decrypt zip files with zlib? + + zlib doesn't support encryption. The original PKZIP encryption is very + weak and can be broken with freely available programs. To get strong + encryption, use GnuPG, http://www.gnupg.org/ , which already includes zlib + compression. For PKZIP compatible "encryption", look at + http://www.info-zip.org/ + +39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings? + + "gzip" is the gzip format, and "deflate" is the zlib format. They should + probably have called the second one "zlib" instead to avoid confusion with + the raw deflate compressed data format. While the HTTP 1.1 RFC 2616 + correctly points to the zlib specification in RFC 1950 for the "deflate" + transfer encoding, there have been reports of servers and browsers that + incorrectly produce or expect raw deflate data per the deflate + specification in RFC 1951, most notably Microsoft. So even though the + "deflate" transfer encoding using the zlib format would be the more + efficient approach (and in fact exactly what the zlib format was designed + for), using the "gzip" transfer encoding is probably more reliable due to + an unfortunate choice of name on the part of the HTTP 1.1 authors. + + Bottom line: use the gzip format for HTTP 1.1 encoding. + +40. Does zlib support the new "Deflate64" format introduced by PKWare? + + No. PKWare has apparently decided to keep that format proprietary, since + they have not documented it as they have previous compression formats. In + any case, the compression improvements are so modest compared to other more + modern approaches, that it's not worth the effort to implement. + +41. I'm having a problem with the zip functions in zlib, can you help? + + There are no zip functions in zlib. You are probably using minizip by + Giles Vollant, which is found in the contrib directory of zlib. It is not + part of zlib. In fact none of the stuff in contrib is part of zlib. The + files in there are not supported by the zlib authors. You need to contact + the authors of the respective contribution for help. + +42. The match.asm code in contrib is under the GNU General Public License. + Since it's part of zlib, doesn't that mean that all of zlib falls under the + GNU GPL? + + No. The files in contrib are not part of zlib. They were contributed by + other authors and are provided as a convenience to the user within the zlib + distribution. Each item in contrib has its own license. + +43. Is zlib subject to export controls? What is its ECCN? + + zlib is not subject to export controls, and so is classified as EAR99. + +44. Can you please sign these lengthy legal documents and fax them back to us + so that we can use your software in our product? + + No. Go away. Shoo. diff --git a/3rdparty/zlib/README b/3rdparty/zlib/README index 5fb367d0a..6f1255ffe 100644 --- a/3rdparty/zlib/README +++ b/3rdparty/zlib/README @@ -1,114 +1,115 @@ -ZLIB DATA COMPRESSION LIBRARY - -zlib 1.2.4 is a general purpose data compression library. All the code is -thread safe. 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). - -All functions of the compression library are documented in the file zlib.h -(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example -of the library is given in the file example.c which also tests that the library -is working correctly. Another example is given in the file minigzip.c. The -compression library itself is composed of all source files except example.c and -minigzip.c. - -To compile all files and run the test program, follow the instructions given at -the top of Makefile.in. In short "./configure; make test", and if that goes -well, "make install" should work for most flavors of Unix. For Windows, use one -of the special makefiles in win32/ or projects/ . For VMS, use make_vms.com. - -Questions about zlib should be sent to , or to Gilles Vollant - for the Windows DLL version. The zlib home page is -http://zlib.net/ . Before reporting a problem, please check this site to -verify that you have the latest version of zlib; otherwise get the latest -version and check whether the problem still exists or not. - -PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help. - -Mark Nelson wrote an article about zlib for the Jan. 1997 -issue of Dr. Dobb's Journal; a copy of the article is available at -http://marknelson.us/1997/01/01/zlib-engine/ . - -The changes made in version 1.2.4 are documented in the file ChangeLog. - -Unsupported third party contributions are provided in directory contrib/ . - -zlib is available in Java using the java.util.zip package, documented at -http://java.sun.com/developer/technicalArticles/Programming/compression/ . - -A Perl interface to zlib written by Paul Marquess is available -at CPAN (Comprehensive Perl Archive Network) sites, including -http://search.cpan.org/~pmqs/IO-Compress-Zlib/ . - -A Python interface to zlib written by A.M. Kuchling is -available in Python 1.5 and later versions, see -http://www.python.org/doc/lib/module-zlib.html . - -zlib is built into tcl: http://wiki.tcl.tk/4610 . - -An experimental package to read and write files in .zip format, written on top -of zlib by Gilles Vollant , is available in the -contrib/minizip directory of zlib. - - -Notes for some targets: - -- For Windows DLL versions, please see win32/DLL_FAQ.txt - -- For 64-bit Irix, deflate.c must be compiled without any optimization. With - -O, one libpng test fails. The test works in 32 bit mode (with the -n32 - compiler flag). The compiler bug has been reported to SGI. - -- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works - when compiled with cc. - -- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is - necessary to get gzprintf working correctly. This is done by configure. - -- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with - other compilers. Use "make test" to check your compiler. - -- gzdopen is not supported on RISCOS or BEOS. - -- For PalmOs, see http://palmzlib.sourceforge.net/ - - -Acknowledgments: - - The deflate format used by zlib was defined by Phil Katz. The deflate and - zlib specifications were written by L. Peter Deutsch. Thanks to all the - people who reported problems and suggested various improvements in zlib; they - are too numerous to cite here. - -Copyright notice: - - (C) 1995-2010 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 - -If you use the zlib library in a product, we would appreciate *not* receiving -lengthy legal documents to sign. The sources are provided for free but without -warranty of any kind. The library has been entirely written by Jean-loup -Gailly and Mark Adler; it does not include third-party code. - -If you redistribute modified sources, we would appreciate that you include in -the file ChangeLog history information documenting your changes. Please read -the FAQ for more information on the distribution of modified source versions. +ZLIB DATA COMPRESSION LIBRARY + +zlib 1.2.7 is a general purpose data compression library. All the code is +thread safe. The data format used by the zlib library is described by RFCs +(Request for Comments) 1950 to 1952 in the files +http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and +rfc1952 (gzip format). + +All functions of the compression library are documented in the file zlib.h +(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example +of the library is given in the file test/example.c which also tests that +the library is working correctly. Another example is given in the file +test/minigzip.c. The compression library itself is composed of all source +files in the root directory. + +To compile all files and run the test program, follow the instructions given at +the top of Makefile.in. In short "./configure; make test", and if that goes +well, "make install" should work for most flavors of Unix. For Windows, use +one of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use +make_vms.com. + +Questions about zlib should be sent to , or to Gilles Vollant + for the Windows DLL version. The zlib home page is +http://zlib.net/ . Before reporting a problem, please check this site to +verify that you have the latest version of zlib; otherwise get the latest +version and check whether the problem still exists or not. + +PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help. + +Mark Nelson wrote an article about zlib for the Jan. 1997 +issue of Dr. Dobb's Journal; a copy of the article is available at +http://marknelson.us/1997/01/01/zlib-engine/ . + +The changes made in version 1.2.7 are documented in the file ChangeLog. + +Unsupported third party contributions are provided in directory contrib/ . + +zlib is available in Java using the java.util.zip package, documented at +http://java.sun.com/developer/technicalArticles/Programming/compression/ . + +A Perl interface to zlib written by Paul Marquess is available +at CPAN (Comprehensive Perl Archive Network) sites, including +http://search.cpan.org/~pmqs/IO-Compress-Zlib/ . + +A Python interface to zlib written by A.M. Kuchling is +available in Python 1.5 and later versions, see +http://docs.python.org/library/zlib.html . + +zlib is built into tcl: http://wiki.tcl.tk/4610 . + +An experimental package to read and write files in .zip format, written on top +of zlib by Gilles Vollant , is available in the +contrib/minizip directory of zlib. + + +Notes for some targets: + +- For Windows DLL versions, please see win32/DLL_FAQ.txt + +- For 64-bit Irix, deflate.c must be compiled without any optimization. With + -O, one libpng test fails. The test works in 32 bit mode (with the -n32 + compiler flag). The compiler bug has been reported to SGI. + +- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works + when compiled with cc. + +- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is + necessary to get gzprintf working correctly. This is done by configure. + +- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with + other compilers. Use "make test" to check your compiler. + +- gzdopen is not supported on RISCOS or BEOS. + +- For PalmOs, see http://palmzlib.sourceforge.net/ + + +Acknowledgments: + + The deflate format used by zlib was defined by Phil Katz. The deflate and + zlib specifications were written by L. Peter Deutsch. Thanks to all the + people who reported problems and suggested various improvements in zlib; they + are too numerous to cite here. + +Copyright notice: + + (C) 1995-2012 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 + +If you use the zlib library in a product, we would appreciate *not* receiving +lengthy legal documents to sign. The sources are provided for free but without +warranty of any kind. The library has been entirely written by Jean-loup +Gailly and Mark Adler; it does not include third-party code. + +If you redistribute modified sources, we would appreciate that you include in +the file ChangeLog history information documenting your changes. Please read +the FAQ for more information on the distribution of modified source versions. diff --git a/3rdparty/zlib/adler32.c b/3rdparty/zlib/adler32.c index 65ad6a5ad..a868f073d 100644 --- a/3rdparty/zlib/adler32.c +++ b/3rdparty/zlib/adler32.c @@ -1,5 +1,5 @@ /* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-2007 Mark Adler + * Copyright (C) 1995-2011 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -9,9 +9,9 @@ #define local static -local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2); +local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); -#define BASE 65521UL /* largest prime smaller than 65536 */ +#define BASE 65521 /* largest prime smaller than 65536 */ #define NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ @@ -21,39 +21,44 @@ local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2); #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); #define DO16(buf) DO8(buf,0); DO8(buf,8); -/* use NO_DIVIDE if your processor does not do division in hardware */ +/* use NO_DIVIDE if your processor does not do division in hardware -- + try it both ways to see which is faster */ #ifdef NO_DIVIDE -# define MOD(a) \ +/* note that this assumes BASE is 65521, where 65536 % 65521 == 15 + (thank you to John Reiser for pointing this out) */ +# define CHOP(a) \ do { \ - if (a >= (BASE << 16)) a -= (BASE << 16); \ - if (a >= (BASE << 15)) a -= (BASE << 15); \ - if (a >= (BASE << 14)) a -= (BASE << 14); \ - if (a >= (BASE << 13)) a -= (BASE << 13); \ - if (a >= (BASE << 12)) a -= (BASE << 12); \ - if (a >= (BASE << 11)) a -= (BASE << 11); \ - if (a >= (BASE << 10)) a -= (BASE << 10); \ - if (a >= (BASE << 9)) a -= (BASE << 9); \ - if (a >= (BASE << 8)) a -= (BASE << 8); \ - if (a >= (BASE << 7)) a -= (BASE << 7); \ - if (a >= (BASE << 6)) a -= (BASE << 6); \ - if (a >= (BASE << 5)) a -= (BASE << 5); \ - if (a >= (BASE << 4)) a -= (BASE << 4); \ - if (a >= (BASE << 3)) a -= (BASE << 3); \ - if (a >= (BASE << 2)) a -= (BASE << 2); \ - if (a >= (BASE << 1)) a -= (BASE << 1); \ + unsigned long tmp = a >> 16; \ + a &= 0xffffUL; \ + a += (tmp << 4) - tmp; \ + } while (0) +# define MOD28(a) \ + do { \ + CHOP(a); \ if (a >= BASE) a -= BASE; \ } while (0) -# define MOD4(a) \ +# define MOD(a) \ do { \ - if (a >= (BASE << 4)) a -= (BASE << 4); \ - if (a >= (BASE << 3)) a -= (BASE << 3); \ - if (a >= (BASE << 2)) a -= (BASE << 2); \ - if (a >= (BASE << 1)) a -= (BASE << 1); \ + CHOP(a); \ + MOD28(a); \ + } while (0) +# define MOD63(a) \ + do { /* this assumes a is not negative */ \ + z_off64_t tmp = a >> 32; \ + a &= 0xffffffffL; \ + a += (tmp << 8) - (tmp << 5) + tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ if (a >= BASE) a -= BASE; \ } while (0) #else # define MOD(a) a %= BASE -# define MOD4(a) a %= BASE +# define MOD28(a) a %= BASE +# define MOD63(a) a %= BASE #endif /* ========================================================================= */ @@ -92,7 +97,7 @@ uLong ZEXPORT adler32(adler, buf, len) } if (adler >= BASE) adler -= BASE; - MOD4(sum2); /* only added so many BASE's */ + MOD28(sum2); /* only added so many BASE's */ return adler | (sum2 << 16); } @@ -137,8 +142,13 @@ local uLong adler32_combine_(adler1, adler2, len2) unsigned long sum2; unsigned rem; + /* for negative len, return invalid adler32 as a clue for debugging */ + if (len2 < 0) + return 0xffffffffUL; + /* the derivation of this formula is left as an exercise for the reader */ - rem = (unsigned)(len2 % BASE); + MOD63(len2); /* assumes len2 >= 0 */ + rem = (unsigned)len2; sum1 = adler1 & 0xffff; sum2 = rem * sum1; MOD(sum2); diff --git a/3rdparty/zlib/crc32.c b/3rdparty/zlib/crc32.c index 1acc7ed8e..979a7190a 100644 --- a/3rdparty/zlib/crc32.c +++ b/3rdparty/zlib/crc32.c @@ -1,5 +1,5 @@ /* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2006 Mark Adler + * Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h * * Thanks to Rodney Brown for his contribution of faster @@ -17,6 +17,8 @@ of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should first call get_crc_table() to initialize the tables before allowing more than one thread to use crc32(). + + DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h. */ #ifdef MAKECRCH @@ -30,31 +32,11 @@ #define local static -/* Find a four-byte integer type for crc32_little() and crc32_big(). */ -#ifndef NOBYFOUR -# ifdef STDC /* need ANSI C limits.h to determine sizes */ -# include -# define BYFOUR -# if (UINT_MAX == 0xffffffffUL) - typedef unsigned int u4; -# else -# if (ULONG_MAX == 0xffffffffUL) - typedef unsigned long u4; -# else -# if (USHRT_MAX == 0xffffffffUL) - typedef unsigned short u4; -# else -# undef BYFOUR /* can't find a four-byte integer type! */ -# endif -# endif -# endif -# endif /* STDC */ -#endif /* !NOBYFOUR */ - /* Definitions for doing the crc four data bytes at a time. */ +#if !defined(NOBYFOUR) && defined(Z_U4) +# define BYFOUR +#endif #ifdef BYFOUR -# define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \ - (((w)&0xff00)<<8)+(((w)&0xff)<<24)) local unsigned long crc32_little OF((unsigned long, const unsigned char FAR *, unsigned)); local unsigned long crc32_big OF((unsigned long, @@ -68,16 +50,16 @@ local unsigned long gf2_matrix_times OF((unsigned long *mat, unsigned long vec)); local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); -local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2); +local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2)); #ifdef DYNAMIC_CRC_TABLE local volatile int crc_table_empty = 1; -local unsigned long FAR crc_table[TBLS][256]; +local z_crc_t FAR crc_table[TBLS][256]; local void make_crc_table OF((void)); #ifdef MAKECRCH - local void write_table OF((FILE *, const unsigned long FAR *)); + local void write_table OF((FILE *, const z_crc_t FAR *)); #endif /* MAKECRCH */ /* Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: @@ -107,9 +89,9 @@ local void make_crc_table OF((void)); */ local void make_crc_table() { - unsigned long c; + z_crc_t c; int n, k; - unsigned long poly; /* polynomial exclusive-or pattern */ + z_crc_t poly; /* polynomial exclusive-or pattern */ /* terms of polynomial defining this crc (except x^32): */ static volatile int first = 1; /* flag to limit concurrent making */ static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; @@ -121,13 +103,13 @@ local void make_crc_table() first = 0; /* make exclusive-or pattern from polynomial (0xedb88320UL) */ - poly = 0UL; - for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) - poly |= 1UL << (31 - p[n]); + poly = 0; + for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++) + poly |= (z_crc_t)1 << (31 - p[n]); /* generate a crc for every 8-bit value */ for (n = 0; n < 256; n++) { - c = (unsigned long)n; + c = (z_crc_t)n; for (k = 0; k < 8; k++) c = c & 1 ? poly ^ (c >> 1) : c >> 1; crc_table[0][n] = c; @@ -138,11 +120,11 @@ local void make_crc_table() and then the byte reversal of those as well as the first table */ for (n = 0; n < 256; n++) { c = crc_table[0][n]; - crc_table[4][n] = REV(c); + crc_table[4][n] = ZSWAP32(c); for (k = 1; k < 4; k++) { c = crc_table[0][c & 0xff] ^ (c >> 8); crc_table[k][n] = c; - crc_table[k + 4][n] = REV(c); + crc_table[k + 4][n] = ZSWAP32(c); } } #endif /* BYFOUR */ @@ -164,7 +146,7 @@ local void make_crc_table() if (out == NULL) return; fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); - fprintf(out, "local const unsigned long FAR "); + fprintf(out, "local const z_crc_t FAR "); fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); write_table(out, crc_table[0]); # ifdef BYFOUR @@ -184,12 +166,13 @@ local void make_crc_table() #ifdef MAKECRCH local void write_table(out, table) FILE *out; - const unsigned long FAR *table; + const z_crc_t FAR *table; { int n; for (n = 0; n < 256; n++) - fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", + (unsigned long)(table[n]), n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); } #endif /* MAKECRCH */ @@ -204,13 +187,13 @@ local void write_table(out, table) /* ========================================================================= * This function can be used by asm versions of crc32() */ -const unsigned long FAR * ZEXPORT get_crc_table() +const z_crc_t FAR * ZEXPORT get_crc_table() { #ifdef DYNAMIC_CRC_TABLE if (crc_table_empty) make_crc_table(); #endif /* DYNAMIC_CRC_TABLE */ - return (const unsigned long FAR *)crc_table; + return (const z_crc_t FAR *)crc_table; } /* ========================================================================= */ @@ -221,7 +204,7 @@ const unsigned long FAR * ZEXPORT get_crc_table() unsigned long ZEXPORT crc32(crc, buf, len) unsigned long crc; const unsigned char FAR *buf; - unsigned len; + uInt len; { if (buf == Z_NULL) return 0UL; @@ -232,7 +215,7 @@ unsigned long ZEXPORT crc32(crc, buf, len) #ifdef BYFOUR if (sizeof(void *) == sizeof(ptrdiff_t)) { - u4 endian; + z_crc_t endian; endian = 1; if (*((unsigned char *)(&endian))) @@ -266,17 +249,17 @@ local unsigned long crc32_little(crc, buf, len) const unsigned char FAR *buf; unsigned len; { - register u4 c; - register const u4 FAR *buf4; + register z_crc_t c; + register const z_crc_t FAR *buf4; - c = (u4)crc; + c = (z_crc_t)crc; c = ~c; while (len && ((ptrdiff_t)buf & 3)) { c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); len--; } - buf4 = (const u4 FAR *)(const void FAR *)buf; + buf4 = (const z_crc_t FAR *)(const void FAR *)buf; while (len >= 32) { DOLIT32; len -= 32; @@ -306,17 +289,17 @@ local unsigned long crc32_big(crc, buf, len) const unsigned char FAR *buf; unsigned len; { - register u4 c; - register const u4 FAR *buf4; + register z_crc_t c; + register const z_crc_t FAR *buf4; - c = REV((u4)crc); + c = ZSWAP32((z_crc_t)crc); c = ~c; while (len && ((ptrdiff_t)buf & 3)) { c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); len--; } - buf4 = (const u4 FAR *)(const void FAR *)buf; + buf4 = (const z_crc_t FAR *)(const void FAR *)buf; buf4--; while (len >= 32) { DOBIG32; @@ -333,7 +316,7 @@ local unsigned long crc32_big(crc, buf, len) c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); } while (--len); c = ~c; - return (unsigned long)(REV(c)); + return (unsigned long)(ZSWAP32(c)); } #endif /* BYFOUR */ diff --git a/3rdparty/zlib/crc32.h b/3rdparty/zlib/crc32.h index 8053b6117..9e0c77810 100644 --- a/3rdparty/zlib/crc32.h +++ b/3rdparty/zlib/crc32.h @@ -2,7 +2,7 @@ * Generated automatically by crc32.c */ -local const unsigned long FAR crc_table[TBLS][256] = +local const z_crc_t FAR crc_table[TBLS][256] = { { 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, diff --git a/3rdparty/zlib/deflate.c b/3rdparty/zlib/deflate.c index fcd698cc6..9e4c2cbc8 100644 --- a/3rdparty/zlib/deflate.c +++ b/3rdparty/zlib/deflate.c @@ -1,5 +1,5 @@ /* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + * Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -37,7 +37,7 @@ * REFERENCES * * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". - * Available in http://www.ietf.org/rfc/rfc1951.txt + * Available in http://tools.ietf.org/html/rfc1951 * * A description of the Rabin and Karp algorithm is given in the book * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. @@ -52,7 +52,7 @@ #include "deflate.h" const char deflate_copyright[] = - " deflate 1.2.4 Copyright 1995-2010 Jean-loup Gailly and Mark Adler "; + " deflate 1.2.7 Copyright 1995-2012 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -155,6 +155,9 @@ local const config configuration_table[10] = { struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ #endif +/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ +#define RANK(f) (((f) << 1) - ((f) > 4 ? 9 : 0)) + /* =========================================================================== * Update a hash value with the given input byte * IN assertion: all calls to to UPDATE_HASH are made with consecutive @@ -235,10 +238,19 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, strm->msg = Z_NULL; if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else strm->zalloc = zcalloc; strm->opaque = (voidpf)0; +#endif } - if (strm->zfree == (free_func)0) strm->zfree = zcfree; + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif #ifdef FASTEST if (level != 0) level = 1; @@ -314,43 +326,70 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) uInt dictLength; { deflate_state *s; - uInt length = dictLength; - uInt n; - IPos hash_head = 0; + uInt str, n; + int wrap; + unsigned avail; + unsigned char *next; - if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || - strm->state->wrap == 2 || - (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL) + return Z_STREAM_ERROR; + s = strm->state; + wrap = s->wrap; + if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead) return Z_STREAM_ERROR; - s = strm->state; - if (s->wrap) + /* when using zlib wrappers, compute Adler-32 for provided dictionary */ + if (wrap == 1) strm->adler = adler32(strm->adler, dictionary, dictLength); + s->wrap = 0; /* avoid computing Adler-32 in read_buf */ - if (length < MIN_MATCH) return Z_OK; - if (length > s->w_size) { - length = s->w_size; - dictionary += dictLength - length; /* use the tail of the dictionary */ + /* if dictionary would fill window, just replace the history */ + if (dictLength >= s->w_size) { + if (wrap == 0) { /* already empty otherwise */ + CLEAR_HASH(s); + s->strstart = 0; + s->block_start = 0L; + s->insert = 0; + } + dictionary += dictLength - s->w_size; /* use the tail */ + dictLength = s->w_size; } - zmemcpy(s->window, dictionary, length); - s->strstart = length; - s->block_start = (long)length; - /* Insert all strings in the hash table (except for the last two bytes). - * s->lookahead stays null, so s->ins_h will be recomputed at the next - * call of fill_window. - */ - s->ins_h = s->window[0]; - UPDATE_HASH(s, s->ins_h, s->window[1]); - for (n = 0; n <= length - MIN_MATCH; n++) { - INSERT_STRING(s, n, hash_head); + /* insert dictionary into window and hash */ + avail = strm->avail_in; + next = strm->next_in; + strm->avail_in = dictLength; + strm->next_in = (Bytef *)dictionary; + fill_window(s); + while (s->lookahead >= MIN_MATCH) { + str = s->strstart; + n = s->lookahead - (MIN_MATCH-1); + do { + UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); +#ifndef FASTEST + s->prev[str & s->w_mask] = s->head[s->ins_h]; +#endif + s->head[s->ins_h] = (Pos)str; + str++; + } while (--n); + s->strstart = str; + s->lookahead = MIN_MATCH-1; + fill_window(s); } - if (hash_head) hash_head = 0; /* to make compiler happy */ + s->strstart += s->lookahead; + s->block_start = (long)s->strstart; + s->insert = s->lookahead; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + strm->next_in = next; + strm->avail_in = avail; + s->wrap = wrap; return Z_OK; } /* ========================================================================= */ -int ZEXPORT deflateReset (strm) +int ZEXPORT deflateResetKeep (strm) z_streamp strm; { deflate_state *s; @@ -380,11 +419,22 @@ int ZEXPORT deflateReset (strm) s->last_flush = Z_NO_FLUSH; _tr_init(s); - lm_init(s); return Z_OK; } +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + int ret; + + ret = deflateResetKeep(strm); + if (ret == Z_OK) + lm_init(strm->state); + return ret; +} + /* ========================================================================= */ int ZEXPORT deflateSetHeader (strm, head) z_streamp strm; @@ -396,15 +446,43 @@ int ZEXPORT deflateSetHeader (strm, head) return Z_OK; } +/* ========================================================================= */ +int ZEXPORT deflatePending (strm, pending, bits) + unsigned *pending; + int *bits; + z_streamp strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (pending != Z_NULL) + *pending = strm->state->pending; + if (bits != Z_NULL) + *bits = strm->state->bi_valid; + return Z_OK; +} + /* ========================================================================= */ int ZEXPORT deflatePrime (strm, bits, value) z_streamp strm; int bits; int value; { + deflate_state *s; + int put; + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - strm->state->bi_valid = bits; - strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + s = strm->state; + if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) + return Z_BUF_ERROR; + do { + put = Buf_size - s->bi_valid; + if (put > bits) + put = bits; + s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid); + s->bi_valid += put; + _tr_flush_bits(s); + value >>= put; + bits -= put; + } while (bits); return Z_OK; } @@ -562,19 +640,22 @@ local void putShortMSB (s, b) local void flush_pending(strm) z_streamp strm; { - unsigned len = strm->state->pending; + unsigned len; + deflate_state *s = strm->state; + _tr_flush_bits(s); + len = s->pending; if (len > strm->avail_out) len = strm->avail_out; if (len == 0) return; - zmemcpy(strm->next_out, strm->state->pending_out, len); + zmemcpy(strm->next_out, s->pending_out, len); strm->next_out += len; - strm->state->pending_out += len; + s->pending_out += len; strm->total_out += len; strm->avail_out -= len; - strm->state->pending -= len; - if (strm->state->pending == 0) { - strm->state->pending_out = strm->state->pending_buf; + s->pending -= len; + if (s->pending == 0) { + s->pending_out = s->pending_buf; } } @@ -801,7 +882,7 @@ int ZEXPORT deflate (strm, flush) * flushes. For repeated and useless calls with Z_FINISH, we keep * returning Z_STREAM_END instead of Z_BUF_ERROR. */ - } else if (strm->avail_in == 0 && flush <= old_flush && + } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && flush != Z_FINISH) { ERR_RETURN(strm, Z_BUF_ERROR); } @@ -850,6 +931,7 @@ int ZEXPORT deflate (strm, flush) if (s->lookahead == 0) { s->strstart = 0; s->block_start = 0L; + s->insert = 0; } } } @@ -945,12 +1027,12 @@ int ZEXPORT deflateCopy (dest, source) ss = source->state; - zmemcpy(dest, source, sizeof(z_stream)); + zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); if (ds == Z_NULL) return Z_MEM_ERROR; dest->state = (struct internal_state FAR *) ds; - zmemcpy(ds, ss, sizeof(deflate_state)); + zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state)); ds->strm = dest; ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); @@ -966,8 +1048,8 @@ int ZEXPORT deflateCopy (dest, source) } /* following zmemcpy do not work for 16-bit MSDOS */ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); - zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); - zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos)); zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); @@ -1001,15 +1083,15 @@ local int read_buf(strm, buf, size) strm->avail_in -= len; + zmemcpy(buf, strm->next_in, len); if (strm->state->wrap == 1) { - strm->adler = adler32(strm->adler, strm->next_in, len); + strm->adler = adler32(strm->adler, buf, len); } #ifdef GZIP else if (strm->state->wrap == 2) { - strm->adler = crc32(strm->adler, strm->next_in, len); + strm->adler = crc32(strm->adler, buf, len); } #endif - zmemcpy(buf, strm->next_in, len); strm->next_in += len; strm->total_in += len; @@ -1036,6 +1118,7 @@ local void lm_init (s) s->strstart = 0; s->block_start = 0L; s->lookahead = 0; + s->insert = 0; s->match_length = s->prev_length = MIN_MATCH-1; s->match_available = 0; s->ins_h = 0; @@ -1310,6 +1393,8 @@ local void fill_window(s) unsigned more; /* Amount of free space at the end of the window. */ uInt wsize = s->w_size; + Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); + do { more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); @@ -1362,7 +1447,7 @@ local void fill_window(s) #endif more += wsize; } - if (s->strm->avail_in == 0) return; + if (s->strm->avail_in == 0) break; /* If there was no sliding: * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && @@ -1381,12 +1466,24 @@ local void fill_window(s) s->lookahead += n; /* Initialize the hash value now that we have some input: */ - if (s->lookahead >= MIN_MATCH) { - s->ins_h = s->window[s->strstart]; - UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); + if (s->lookahead + s->insert >= MIN_MATCH) { + uInt str = s->strstart - s->insert; + s->ins_h = s->window[str]; + UPDATE_HASH(s, s->ins_h, s->window[str + 1]); #if MIN_MATCH != 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif + while (s->insert) { + UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); +#ifndef FASTEST + s->prev[str & s->w_mask] = s->head[s->ins_h]; +#endif + s->head[s->ins_h] = (Pos)str; + str++; + s->insert--; + if (s->lookahead + s->insert < MIN_MATCH) + break; + } } /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, * but this is not important since only literal bytes will be emitted. @@ -1427,6 +1524,9 @@ local void fill_window(s) s->high_water += init; } } + + Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, + "not enough room for search"); } /* =========================================================================== @@ -1506,8 +1606,14 @@ local block_state deflate_stored(s, flush) FLUSH_BLOCK(s, 0); } } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; + s->insert = 0; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if ((long)s->strstart > s->block_start) + FLUSH_BLOCK(s, 0); + return block_done; } /* =========================================================================== @@ -1603,8 +1709,14 @@ local block_state deflate_fast(s, flush) } if (bflush) FLUSH_BLOCK(s, 0); } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; + s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->last_lit) + FLUSH_BLOCK(s, 0); + return block_done; } #ifndef FASTEST @@ -1728,8 +1840,14 @@ local block_state deflate_slow(s, flush) _tr_tally_lit(s, s->window[s->strstart-1], bflush); s->match_available = 0; } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; + s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->last_lit) + FLUSH_BLOCK(s, 0); + return block_done; } #endif /* FASTEST */ @@ -1749,11 +1867,11 @@ local block_state deflate_rle(s, flush) for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes - * for the longest encodable run. + * for the longest run, plus one for the unrolled loop. */ - if (s->lookahead < MAX_MATCH) { + if (s->lookahead <= MAX_MATCH) { fill_window(s); - if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { + if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ @@ -1776,6 +1894,7 @@ local block_state deflate_rle(s, flush) if (s->match_length > s->lookahead) s->match_length = s->lookahead; } + Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); } /* Emit match if have run of MIN_MATCH or longer, else emit literal */ @@ -1796,8 +1915,14 @@ local block_state deflate_rle(s, flush) } if (bflush) FLUSH_BLOCK(s, 0); } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; + s->insert = 0; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->last_lit) + FLUSH_BLOCK(s, 0); + return block_done; } /* =========================================================================== @@ -1829,6 +1954,12 @@ local block_state deflate_huff(s, flush) s->strstart++; if (bflush) FLUSH_BLOCK(s, 0); } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; + s->insert = 0; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->last_lit) + FLUSH_BLOCK(s, 0); + return block_done; } diff --git a/3rdparty/zlib/deflate.h b/3rdparty/zlib/deflate.h index f53deba85..fbac44d90 100644 --- a/3rdparty/zlib/deflate.h +++ b/3rdparty/zlib/deflate.h @@ -1,5 +1,5 @@ /* deflate.h -- internal compression state - * Copyright (C) 1995-2009 Jean-loup Gailly + * Copyright (C) 1995-2012 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -48,6 +48,9 @@ #define MAX_BITS 15 /* All codes must not exceed MAX_BITS bits */ +#define Buf_size 16 +/* size of bit buffer in bi_buf */ + #define INIT_STATE 42 #define EXTRA_STATE 69 #define NAME_STATE 73 @@ -188,7 +191,7 @@ typedef struct internal_state { 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 */ + /* Didn't use ct_data typedef below to suppress 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 */ @@ -244,7 +247,7 @@ typedef struct internal_state { 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 */ + uInt insert; /* bytes at end of window left to insert */ #ifdef DEBUG ulg compressed_len; /* total bit length of compressed file mod 2^32 */ @@ -290,13 +293,14 @@ typedef struct internal_state { memory checker errors from longest match routines */ /* 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 last)); -void _tr_align OF((deflate_state *s)); -void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, - int last)); +void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); +int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); +void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s)); +void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); +void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); #define d_code(dist) \ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) @@ -309,11 +313,11 @@ void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, /* Inline versions of _tr_tally for speed: */ #if defined(GEN_TREES_H) || !defined(STDC) - extern uch _length_code[]; - extern uch _dist_code[]; + extern uch ZLIB_INTERNAL _length_code[]; + extern uch ZLIB_INTERNAL _dist_code[]; #else - extern const uch _length_code[]; - extern const uch _dist_code[]; + extern const uch ZLIB_INTERNAL _length_code[]; + extern const uch ZLIB_INTERNAL _dist_code[]; #endif # define _tr_tally_lit(s, c, flush) \ diff --git a/3rdparty/zlib/gzguts.h b/3rdparty/zlib/gzguts.h index 0e7ed4330..ee3f281aa 100644 --- a/3rdparty/zlib/gzguts.h +++ b/3rdparty/zlib/gzguts.h @@ -1,18 +1,22 @@ /* gzguts.h -- zlib internal header definitions for gz* operations - * Copyright (C) 2004, 2005, 2010 Mark Adler + * Copyright (C) 2004, 2005, 2010, 2011, 2012 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #ifdef _LARGEFILE64_SOURCE # ifndef _LARGEFILE_SOURCE -# define _LARGEFILE_SOURCE +# define _LARGEFILE_SOURCE 1 # endif # ifdef _FILE_OFFSET_BITS # undef _FILE_OFFSET_BITS # endif #endif -#define ZLIB_INTERNAL +#ifdef HAVE_HIDDEN +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif #include #include "zlib.h" @@ -23,13 +27,65 @@ #endif #include +#ifdef _WIN32 +# include +#endif + +#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) +# include +#endif + #ifdef NO_DEFLATE /* for compatibility with old definition */ # define NO_GZCOMPRESS #endif -#ifdef _MSC_VER -# include -# define vsnprintf _vsnprintf +#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 + +#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410) +# 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) +# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) +# define vsnprintf _vsnprintf +# endif +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +# ifdef VMS +# define NO_vsnprintf +# endif +# ifdef __OS400__ +# define NO_vsnprintf +# endif +# ifdef __MVS__ +# define NO_vsnprintf +# endif #endif #ifndef local @@ -44,11 +100,11 @@ #endif /* get errno and strerror definition */ -#if defined UNDER_CE && defined NO_ERRNO_H +#if defined UNDER_CE # include # define zstrerror() gz_strwinerror((DWORD)GetLastError()) #else -# ifdef STDC +# ifndef NO_STRERROR # include # define zstrerror() strerror(errno) # else @@ -56,16 +112,19 @@ # endif #endif -/* MVS fdopen() */ -#ifdef __MVS__ - #pragma map (fdopen , "\174\174FDOPEN") - FILE *fdopen(int, const char *); +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); #endif -#ifdef _LARGEFILE64_SOURCE -# define z_off64_t off64_t +/* default memLevel */ +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 #else -# define z_off64_t z_off_t +# define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif /* default i/o buffer size -- double this for output when reading */ @@ -84,23 +143,25 @@ /* internal gzip file state data structure */ typedef struct { + /* exposed contents for gzgetc() macro */ + struct gzFile_s x; /* "x" for exposed */ + /* x.have: number of bytes available at x.next */ + /* x.next: next output data to deliver or write */ + /* x.pos: current position in uncompressed data */ /* used for both reading and writing */ int mode; /* see gzip modes above */ int fd; /* file descriptor */ char *path; /* path or fd for error messages */ - z_off64_t pos; /* current position in uncompressed data */ unsigned size; /* buffer size, zero if not allocated yet */ unsigned want; /* requested buffer size, default is GZBUFSIZE */ unsigned char *in; /* input buffer */ unsigned char *out; /* output buffer (double-sized when reading) */ - unsigned char *next; /* next output data to deliver or write */ + int direct; /* 0 if processing gzip, 1 if transparent */ /* just for reading */ - unsigned have; /* amount of output data unused at next */ - int eof; /* true if end of input file reached */ - z_off64_t start; /* where the gzip data started, for rewinding */ - z_off64_t raw; /* where the raw data started, for seeking */ int how; /* 0: get header, 1: copy, 2: decompress */ - int direct; /* true if last read direct, false if gzip */ + z_off64_t start; /* where the gzip data started, for rewinding */ + int eof; /* true if end of input file reached */ + int past; /* true if read requested past end */ /* just for writing */ int level; /* compression level */ int strategy; /* compression strategy */ @@ -116,9 +177,9 @@ typedef struct { typedef gz_state FAR *gz_statep; /* shared functions */ -ZEXTERN void ZEXPORT gz_error OF((gz_statep, int, const char *)); -#if defined UNDER_CE && defined NO_ERRNO_H -ZEXTERN char ZEXPORT *gz_strwinerror OF((DWORD error)); +void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); +#if defined UNDER_CE +char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); #endif /* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t @@ -127,6 +188,6 @@ ZEXTERN char ZEXPORT *gz_strwinerror OF((DWORD error)); #ifdef INT_MAX # define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) #else -ZEXTERN unsigned ZEXPORT gz_intmax OF((void)); +unsigned ZLIB_INTERNAL gz_intmax OF((void)); # define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) #endif diff --git a/3rdparty/zlib/gzlib.c b/3rdparty/zlib/gzlib.c index 6fdb08a81..ca55c6ea9 100644 --- a/3rdparty/zlib/gzlib.c +++ b/3rdparty/zlib/gzlib.c @@ -1,21 +1,25 @@ /* gzlib.c -- zlib functions common to reading and writing gzip files - * Copyright (C) 2004, 2010 Mark Adler + * Copyright (C) 2004, 2010, 2011, 2012 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "gzguts.h" -#ifdef _LARGEFILE64_SOURCE +#if defined(_WIN32) && !defined(__BORLANDC__) +# define LSEEK _lseeki64 +#else +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 # define LSEEK lseek64 #else # define LSEEK lseek #endif +#endif /* Local functions */ local void gz_reset OF((gz_statep)); -local gzFile gz_open OF((const char *, int, const char *)); +local gzFile gz_open OF((const void *, int, const char *)); -#if defined UNDER_CE && defined NO_ERRNO_H +#if defined UNDER_CE /* Map the Windows error number in ERROR to a locale-dependent error message string and return a pointer to it. Typically, the values for ERROR come @@ -26,7 +30,7 @@ local gzFile gz_open OF((const char *, int, const char *)); The gz_strwinerror function does not change the current setting of GetLastError. */ -char ZEXPORT *gz_strwinerror (error) +char ZLIB_INTERNAL *gz_strwinerror (error) DWORD error; { static char buf[1024]; @@ -65,31 +69,43 @@ char ZEXPORT *gz_strwinerror (error) return buf; } -#endif /* UNDER_CE && NO_ERRNO_H */ +#endif /* UNDER_CE */ /* Reset gzip file state */ local void gz_reset(state) gz_statep state; { + state->x.have = 0; /* no output data available */ if (state->mode == GZ_READ) { /* for reading ... */ - state->have = 0; /* no output data available */ state->eof = 0; /* not at end of file */ + state->past = 0; /* have not read past end yet */ state->how = LOOK; /* look for gzip header */ - state->direct = 1; /* default for empty file */ } state->seek = 0; /* no seek request pending */ gz_error(state, Z_OK, NULL); /* clear error */ - state->pos = 0; /* no uncompressed data yet */ + state->x.pos = 0; /* no uncompressed data yet */ state->strm.avail_in = 0; /* no input data yet */ } /* Open a gzip file either by name or file descriptor. */ local gzFile gz_open(path, fd, mode) - const char *path; + const void *path; int fd; const char *mode; { gz_statep state; + size_t len; + int oflag; +#ifdef O_CLOEXEC + int cloexec = 0; +#endif +#ifdef O_EXCL + int exclusive = 0; +#endif + + /* check input */ + if (path == NULL) + return NULL; /* allocate gzFile structure to return */ state = malloc(sizeof(gz_state)); @@ -103,6 +119,7 @@ local gzFile gz_open(path, fd, mode) state->mode = GZ_NONE; state->level = Z_DEFAULT_COMPRESSION; state->strategy = Z_DEFAULT_STRATEGY; + state->direct = 0; while (*mode) { if (*mode >= '0' && *mode <= '9') state->level = *mode - '0'; @@ -124,6 +141,16 @@ local gzFile gz_open(path, fd, mode) return NULL; case 'b': /* ignore -- will request binary anyway */ break; +#ifdef O_CLOEXEC + case 'e': + cloexec = 1; + break; +#endif +#ifdef O_EXCL + case 'x': + exclusive = 1; + break; +#endif case 'f': state->strategy = Z_FILTERED; break; @@ -135,6 +162,8 @@ local gzFile gz_open(path, fd, mode) break; case 'F': state->strategy = Z_FIXED; + case 'T': + state->direct = 1; default: /* could consider as an error, but just ignore */ ; } @@ -147,31 +176,69 @@ local gzFile gz_open(path, fd, mode) return NULL; } + /* can't force transparent read */ + if (state->mode == GZ_READ) { + if (state->direct) { + free(state); + return NULL; + } + state->direct = 1; /* for empty file */ + } + /* save the path name for error messages */ - state->path = malloc(strlen(path) + 1); +#ifdef _WIN32 + if (fd == -2) { + len = wcstombs(NULL, path, 0); + if (len == (size_t)-1) + len = 0; + } + else +#endif + len = strlen(path); + state->path = malloc(len + 1); if (state->path == NULL) { free(state); return NULL; } - strcpy(state->path, path); +#ifdef _WIN32 + if (fd == -2) + if (len) + wcstombs(state->path, path, len + 1); + else + *(state->path) = 0; + else +#endif + strcpy(state->path, path); - /* open the file with the appropriate mode (or just use fd) */ - state->fd = fd != -1 ? fd : - open(path, + /* compute the flags for open() */ + oflag = #ifdef O_LARGEFILE - O_LARGEFILE | + O_LARGEFILE | #endif #ifdef O_BINARY - O_BINARY | + O_BINARY | #endif - (state->mode == GZ_READ ? - O_RDONLY : - (O_WRONLY | O_CREAT | ( - state->mode == GZ_WRITE ? - O_TRUNC : - O_APPEND))), - 0666); +#ifdef O_CLOEXEC + (cloexec ? O_CLOEXEC : 0) | +#endif + (state->mode == GZ_READ ? + O_RDONLY : + (O_WRONLY | O_CREAT | +#ifdef O_EXCL + (exclusive ? O_EXCL : 0) | +#endif + (state->mode == GZ_WRITE ? + O_TRUNC : + O_APPEND))); + + /* open the file with the appropriate flags (or just use fd) */ + state->fd = fd > -1 ? fd : ( +#ifdef _WIN32 + fd == -2 ? _wopen(path, oflag, 0666) : +#endif + open(path, oflag, 0666)); if (state->fd == -1) { + free(state->path); free(state); return NULL; } @@ -217,12 +284,22 @@ gzFile ZEXPORT gzdopen(fd, mode) if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL) return NULL; - sprintf(path, "", fd); + sprintf(path, "", fd); /* for debugging */ gz = gz_open(path, fd, mode); free(path); return gz; } +/* -- see zlib.h -- */ +#ifdef _WIN32 +gzFile ZEXPORT gzopen_w(path, mode) + const wchar_t *path; + const char *mode; +{ + return gz_open(path, -2, mode); +} +#endif + /* -- see zlib.h -- */ int ZEXPORT gzbuffer(file, size) gzFile file; @@ -242,8 +319,8 @@ int ZEXPORT gzbuffer(file, size) return -1; /* check and set requested size */ - if (size == 0) - return -1; + if (size < 2) + size = 2; /* need two bytes to check magic header */ state->want = size; return 0; } @@ -260,7 +337,8 @@ int ZEXPORT gzrewind(file) state = (gz_statep)file; /* check that we're reading and that there's no error */ - if (state->mode != GZ_READ || state->err != Z_OK) + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) return -1; /* back up and start over */ @@ -288,7 +366,7 @@ z_off64_t ZEXPORT gzseek64(file, offset, whence) return -1; /* check that there's no error */ - if (state->err != Z_OK) + if (state->err != Z_OK && state->err != Z_BUF_ERROR) return -1; /* can only seek from start or relative to current position */ @@ -297,31 +375,32 @@ z_off64_t ZEXPORT gzseek64(file, offset, whence) /* normalize offset to a SEEK_CUR specification */ if (whence == SEEK_SET) - offset -= state->pos; + offset -= state->x.pos; else if (state->seek) offset += state->skip; state->seek = 0; /* if within raw area while reading, just go there */ if (state->mode == GZ_READ && state->how == COPY && - state->pos + offset >= state->raw) { - ret = LSEEK(state->fd, offset, SEEK_CUR); + state->x.pos + offset >= 0) { + ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR); if (ret == -1) return -1; - state->have = 0; + state->x.have = 0; state->eof = 0; + state->past = 0; state->seek = 0; gz_error(state, Z_OK, NULL); state->strm.avail_in = 0; - state->pos += offset; - return state->pos; + state->x.pos += offset; + return state->x.pos; } /* calculate skip amount, rewinding if needed for back seek when reading */ if (offset < 0) { if (state->mode != GZ_READ) /* writing -- can't go backwards */ return -1; - offset += state->pos; + offset += state->x.pos; if (offset < 0) /* before start of file! */ return -1; if (gzrewind(file) == -1) /* rewind, then skip to offset */ @@ -330,11 +409,11 @@ z_off64_t ZEXPORT gzseek64(file, offset, whence) /* if reading, skip what's in output buffer (one less gzgetc() check) */ if (state->mode == GZ_READ) { - n = GT_OFF(state->have) || (z_off64_t)state->have > offset ? - (unsigned)offset : state->have; - state->have -= n; - state->next += n; - state->pos += n; + n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? + (unsigned)offset : state->x.have; + state->x.have -= n; + state->x.next += n; + state->x.pos += n; offset -= n; } @@ -343,7 +422,7 @@ z_off64_t ZEXPORT gzseek64(file, offset, whence) state->seek = 1; state->skip = offset; } - return state->pos + offset; + return state->x.pos + offset; } /* -- see zlib.h -- */ @@ -372,7 +451,7 @@ z_off64_t ZEXPORT gztell64(file) return -1; /* return position */ - return state->pos + (state->seek ? state->skip : 0); + return state->x.pos + (state->seek ? state->skip : 0); } /* -- see zlib.h -- */ @@ -432,7 +511,7 @@ int ZEXPORT gzeof(file) return 0; /* return end-of-file state */ - return state->mode == GZ_READ ? (state->eof && state->have == 0) : 0; + return state->mode == GZ_READ ? state->past : 0; } /* -- see zlib.h -- */ @@ -469,8 +548,10 @@ void ZEXPORT gzclearerr(file) return; /* clear error and end-of-file */ - if (state->mode == GZ_READ) + if (state->mode == GZ_READ) { state->eof = 0; + state->past = 0; + } gz_error(state, Z_OK, NULL); } @@ -480,7 +561,7 @@ void ZEXPORT gzclearerr(file) memory). Simply save the error message as a static string. If there is an allocation failure constructing the error message, then convert the error to out of memory. */ -void ZEXPORT gz_error(state, err, msg) +void ZLIB_INTERNAL gz_error(state, err, msg) gz_statep state; int err; const char *msg; @@ -492,6 +573,10 @@ void ZEXPORT gz_error(state, err, msg) state->msg = NULL; } + /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */ + if (err != Z_OK && err != Z_BUF_ERROR) + state->x.have = 0; + /* set error code, and if no message, then done */ state->err = err; if (msg == NULL) @@ -520,7 +605,7 @@ void ZEXPORT gz_error(state, err, msg) available) -- we need to do this to cover cases where 2's complement not used, since C standard permits 1's complement and sign-bit representations, otherwise we could just use ((unsigned)-1) >> 1 */ -unsigned ZEXPORT gz_intmax() +unsigned ZLIB_INTERNAL gz_intmax() { unsigned p, q; diff --git a/3rdparty/zlib/gzread.c b/3rdparty/zlib/gzread.c index 434ef023e..3493d34d4 100644 --- a/3rdparty/zlib/gzread.c +++ b/3rdparty/zlib/gzread.c @@ -1,5 +1,5 @@ /* gzread.c -- zlib functions for reading gzip files - * Copyright (C) 2004, 2005, 2010 Mark Adler + * Copyright (C) 2004, 2005, 2010, 2011, 2012 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -8,10 +8,9 @@ /* Local functions */ local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *)); local int gz_avail OF((gz_statep)); -local int gz_next4 OF((gz_statep, unsigned long *)); -local int gz_head OF((gz_statep)); +local int gz_look OF((gz_statep)); local int gz_decomp OF((gz_statep)); -local int gz_make OF((gz_statep)); +local int gz_fetch OF((gz_statep)); local int gz_skip OF((gz_statep, z_off64_t)); /* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from @@ -46,66 +45,47 @@ local int gz_load(state, buf, len, have) error, 0 otherwise. Note that the eof flag is set when the end of the input file is reached, even though there may be unused data in the buffer. Once that data has been used, no more attempts will be made to read the file. - gz_avail() assumes that strm->avail_in == 0. */ + If strm->avail_in != 0, then the current data is moved to the beginning of + the input buffer, and then the remainder of the buffer is loaded with the + available data from the input file. */ local int gz_avail(state) gz_statep state; { + unsigned got; z_streamp strm = &(state->strm); - if (state->err != Z_OK) + if (state->err != Z_OK && state->err != Z_BUF_ERROR) return -1; if (state->eof == 0) { - if (gz_load(state, state->in, state->size, &(strm->avail_in)) == -1) + if (strm->avail_in) { /* copy what's there to the start */ + unsigned char *p = state->in, *q = strm->next_in; + unsigned n = strm->avail_in; + do { + *p++ = *q++; + } while (--n); + } + if (gz_load(state, state->in + strm->avail_in, + state->size - strm->avail_in, &got) == -1) return -1; + strm->avail_in += got; strm->next_in = state->in; } return 0; } -/* Get next byte from input, or -1 if end or error. */ -#define NEXT() ((strm->avail_in == 0 && gz_avail(state) == -1) ? -1 : \ - (strm->avail_in == 0 ? -1 : \ - (strm->avail_in--, *(strm->next_in)++))) - -/* Get a four-byte little-endian integer and return 0 on success and the value - in *ret. Otherwise -1 is returned and *ret is not modified. */ -local int gz_next4(state, ret) - gz_statep state; - unsigned long *ret; -{ - int ch; - unsigned long val; - z_streamp strm = &(state->strm); - - val = NEXT(); - val += (unsigned)NEXT() << 8; - val += (unsigned long)NEXT() << 16; - ch = NEXT(); - if (ch == -1) - return -1; - val += (unsigned long)ch << 24; - *ret = val; - return 0; -} - -/* Look for gzip header, set up for inflate or copy. state->have must be zero. +/* Look for gzip header, set up for inflate or copy. state->x.have must be 0. If this is the first time in, allocate required memory. state->how will be left unchanged if there is no more input data available, will be set to COPY if there is no gzip header and direct copying will be performed, or it will - be set to GZIP for decompression, and the gzip header will be skipped so - that the next available input data is the raw deflate stream. If direct - copying, then leftover input data from the input buffer will be copied to - the output buffer. In that case, all further file reads will be directly to - either the output buffer or a user buffer. If decompressing, the inflate - state and the check value will be initialized. gz_head() will return 0 on - success or -1 on failure. Failures may include read errors or gzip header - errors. */ -local int gz_head(state) + be set to GZIP for decompression. If direct copying, then leftover input + data from the input buffer will be copied to the output buffer. In that + case, all further file reads will be directly to either the output buffer or + a user buffer. If decompressing, the inflate state will be initialized. + gz_look() will return 0 on success or -1 on failure. */ +local int gz_look(state) gz_statep state; { z_streamp strm = &(state->strm); - int flags; - unsigned len; /* allocate read buffers and inflate memory */ if (state->size == 0) { @@ -128,7 +108,7 @@ local int gz_head(state) state->strm.opaque = Z_NULL; state->strm.avail_in = 0; state->strm.next_in = Z_NULL; - if (inflateInit2(&(state->strm), -15) != Z_OK) { /* raw inflate */ + if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */ free(state->out); free(state->in); state->size = 0; @@ -137,83 +117,45 @@ local int gz_head(state) } } - /* get some data in the input buffer */ - if (strm->avail_in == 0) { + /* get at least the magic bytes in the input buffer */ + if (strm->avail_in < 2) { if (gz_avail(state) == -1) return -1; if (strm->avail_in == 0) return 0; } - /* look for the gzip magic header bytes 31 and 139 */ - if (strm->next_in[0] == 31) { - strm->avail_in--; - strm->next_in++; - if (strm->avail_in == 0 && gz_avail(state) == -1) - return -1; - if (strm->avail_in && strm->next_in[0] == 139) { - /* we have a gzip header, woo hoo! */ - strm->avail_in--; - strm->next_in++; - - /* skip rest of header */ - if (NEXT() != 8) { /* compression method */ - gz_error(state, Z_DATA_ERROR, "unknown compression method"); - return -1; - } - flags = NEXT(); - if (flags & 0xe0) { /* reserved flag bits */ - gz_error(state, Z_DATA_ERROR, "unknown header flags set"); - return -1; - } - NEXT(); /* modification time */ - NEXT(); - NEXT(); - NEXT(); - NEXT(); /* extra flags */ - NEXT(); /* operating system */ - if (flags & 4) { /* extra field */ - len = (unsigned)NEXT(); - len += (unsigned)NEXT() << 8; - while (len--) - if (NEXT() < 0) - break; - } - if (flags & 8) /* file name */ - while (NEXT() > 0) - ; - if (flags & 16) /* comment */ - while (NEXT() > 0) - ; - if (flags & 2) { /* header crc */ - NEXT(); - NEXT(); - } - /* an unexpected end of file is not checked for here -- it will be - noticed on the first request for uncompressed data */ - - /* set up for decompression */ - inflateReset(strm); - strm->adler = crc32(0L, Z_NULL, 0); - state->how = GZIP; - state->direct = 0; - return 0; - } - else { - /* not a gzip file -- save first byte (31) and fall to raw i/o */ - state->out[0] = 31; - state->have = 1; - } + /* look for gzip magic bytes -- if there, do gzip decoding (note: there is + a logical dilemma here when considering the case of a partially written + gzip file, to wit, if a single 31 byte is written, then we cannot tell + whether this is a single-byte file, or just a partially written gzip + file -- for here we assume that if a gzip file is being written, then + the header will be written in a single operation, so that reading a + single byte is sufficient indication that it is not a gzip file) */ + if (strm->avail_in > 1 && + strm->next_in[0] == 31 && strm->next_in[1] == 139) { + inflateReset(strm); + state->how = GZIP; + state->direct = 0; + return 0; } - /* doing raw i/o, save start of raw data for seeking, copy any leftover - input to output -- this assumes that the output buffer is larger than - the input buffer, which also assures space for gzungetc() */ - state->raw = state->pos; - state->next = state->out; + /* no gzip header -- if we were decoding gzip before, then this is trailing + garbage. Ignore the trailing garbage and finish. */ + if (state->direct == 0) { + strm->avail_in = 0; + state->eof = 1; + state->x.have = 0; + return 0; + } + + /* doing raw i/o, copy any leftover input to output -- this assumes that + the output buffer is larger than the input buffer, which also assures + space for gzungetc() */ + state->x.next = state->out; if (strm->avail_in) { - memcpy(state->next + state->have, strm->next_in, strm->avail_in); - state->have += strm->avail_in; + memcpy(state->x.next, strm->next_in, strm->avail_in); + state->x.have = strm->avail_in; strm->avail_in = 0; } state->how = COPY; @@ -222,19 +164,15 @@ local int gz_head(state) } /* Decompress from input to the provided next_out and avail_out in the state. - If the end of the compressed data is reached, then verify the gzip trailer - check value and length (modulo 2^32). state->have and state->next are set - to point to the just decompressed data, and the crc is updated. If the - trailer is verified, state->how is reset to LOOK to look for the next gzip - stream or raw data, once state->have is depleted. Returns 0 on success, -1 - on failure. Failures may include invalid compressed data or a failed gzip - trailer verification. */ + On return, state->x.have and state->x.next point to the just decompressed + data. If the gzip stream completes, state->how is reset to LOOK to look for + the next gzip stream or raw data, once state->x.have is depleted. Returns 0 + on success, -1 on failure. */ local int gz_decomp(state) gz_statep state; { - int ret; + int ret = Z_OK; unsigned had; - unsigned long crc, len; z_streamp strm = &(state->strm); /* fill output buffer up to end of deflate stream */ @@ -244,15 +182,15 @@ local int gz_decomp(state) if (strm->avail_in == 0 && gz_avail(state) == -1) return -1; if (strm->avail_in == 0) { - gz_error(state, Z_DATA_ERROR, "unexpected end of file"); - return -1; + gz_error(state, Z_BUF_ERROR, "unexpected end of file"); + break; } /* decompress and handle errors */ ret = inflate(strm, Z_NO_FLUSH); if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { gz_error(state, Z_STREAM_ERROR, - "internal error: inflate stream corrupt"); + "internal error: inflate stream corrupt"); return -1; } if (ret == Z_MEM_ERROR) { @@ -261,67 +199,55 @@ local int gz_decomp(state) } if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ gz_error(state, Z_DATA_ERROR, - strm->msg == NULL ? "compressed data error" : strm->msg); + strm->msg == NULL ? "compressed data error" : strm->msg); return -1; } } while (strm->avail_out && ret != Z_STREAM_END); - /* update available output and crc check value */ - state->have = had - strm->avail_out; - state->next = strm->next_out - state->have; - strm->adler = crc32(strm->adler, state->next, state->have); + /* update available output */ + state->x.have = had - strm->avail_out; + state->x.next = strm->next_out - state->x.have; - /* check gzip trailer if at end of deflate stream */ - if (ret == Z_STREAM_END) { - if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) { - gz_error(state, Z_DATA_ERROR, "unexpected end of file"); - return -1; - } - if (crc != strm->adler) { - gz_error(state, Z_DATA_ERROR, "incorrect data check"); - return -1; - } - if (len != (strm->total_out & 0xffffffffL)) { - gz_error(state, Z_DATA_ERROR, "incorrect length check"); - return -1; - } - state->how = LOOK; /* ready for next stream, once have is 0 (leave - state->direct unchanged to remember how) */ - } + /* if the gzip stream completed successfully, look for another */ + if (ret == Z_STREAM_END) + state->how = LOOK; /* good decompression */ return 0; } -/* Make data and put in the output buffer. Assumes that state->have == 0. +/* Fetch data and put it in the output buffer. Assumes state->x.have is 0. Data is either copied from the input file or decompressed from the input file depending on state->how. If state->how is LOOK, then a gzip header is - looked for (and skipped if found) to determine wither to copy or decompress. - Returns -1 on error, otherwise 0. gz_make() will leave state->have as COPY - or GZIP unless the end of the input file has been reached and all data has - been processed. */ -local int gz_make(state) + looked for to determine whether to copy or decompress. Returns -1 on error, + otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the + end of the input file has been reached and all data has been processed. */ +local int gz_fetch(state) gz_statep state; { z_streamp strm = &(state->strm); - if (state->how == LOOK) { /* look for gzip header */ - if (gz_head(state) == -1) - return -1; - if (state->have) /* got some data from gz_head() */ + do { + switch(state->how) { + case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */ + if (gz_look(state) == -1) + return -1; + if (state->how == LOOK) + return 0; + break; + case COPY: /* -> COPY */ + if (gz_load(state, state->out, state->size << 1, &(state->x.have)) + == -1) + return -1; + state->x.next = state->out; return 0; - } - if (state->how == COPY) { /* straight copy */ - if (gz_load(state, state->out, state->size << 1, &(state->have)) == -1) - return -1; - state->next = state->out; - } - else if (state->how == GZIP) { /* decompress */ - strm->avail_out = state->size << 1; - strm->next_out = state->out; - if (gz_decomp(state) == -1) - return -1; - } + case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */ + strm->avail_out = state->size << 1; + strm->next_out = state->out; + if (gz_decomp(state) == -1) + return -1; + } + } while (state->x.have == 0 && (!state->eof || strm->avail_in)); return 0; } @@ -335,12 +261,12 @@ local int gz_skip(state, len) /* skip over len bytes or reach end-of-file, whichever comes first */ while (len) /* skip over whatever is in output buffer */ - if (state->have) { - n = GT_OFF(state->have) || (z_off64_t)state->have > len ? - (unsigned)len : state->have; - state->have -= n; - state->next += n; - state->pos += n; + if (state->x.have) { + n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ? + (unsigned)len : state->x.have; + state->x.have -= n; + state->x.next += n; + state->x.pos += n; len -= n; } @@ -351,7 +277,7 @@ local int gz_skip(state, len) /* need more data to skip -- load up output buffer */ else { /* get more output, looking for header if required */ - if (gz_make(state) == -1) + if (gz_fetch(state) == -1) return -1; } return 0; @@ -373,14 +299,15 @@ int ZEXPORT gzread(file, buf, len) state = (gz_statep)file; strm = &(state->strm); - /* check that we're reading and that there's no error */ - if (state->mode != GZ_READ || state->err != Z_OK) + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) return -1; /* since an int is returned, make sure len fits in one, otherwise return with an error (this avoids the flaw in the interface) */ if ((int)len < 0) { - gz_error(state, Z_BUF_ERROR, "requested length does not fit in int"); + gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); return -1; } @@ -399,24 +326,26 @@ int ZEXPORT gzread(file, buf, len) got = 0; do { /* first just try copying data from the output buffer */ - if (state->have) { - n = state->have > len ? len : state->have; - memcpy(buf, state->next, n); - state->next += n; - state->have -= n; + if (state->x.have) { + n = state->x.have > len ? len : state->x.have; + memcpy(buf, state->x.next, n); + state->x.next += n; + state->x.have -= n; } /* output buffer empty -- return if we're at the end of the input */ - else if (state->eof && strm->avail_in == 0) + else if (state->eof && strm->avail_in == 0) { + state->past = 1; /* tried to read past end */ break; + } /* need output data -- for small len or new stream load up our output buffer */ else if (state->how == LOOK || len < (state->size << 1)) { /* get more output, looking for header if required */ - if (gz_make(state) == -1) + if (gz_fetch(state) == -1) return -1; - continue; /* no progress yet -- go back to memcpy() above */ + continue; /* no progress yet -- go back to copy above */ /* the copy above assures that we will leave with space in the output buffer, allowing at least one gzungetc() to succeed */ } @@ -433,15 +362,15 @@ int ZEXPORT gzread(file, buf, len) strm->next_out = buf; if (gz_decomp(state) == -1) return -1; - n = state->have; - state->have = 0; + n = state->x.have; + state->x.have = 0; } /* update progress */ len -= n; buf = (char *)buf + n; got += n; - state->pos += n; + state->x.pos += n; } while (len); /* return number of bytes read into user buffer (will fit in int) */ @@ -449,6 +378,7 @@ int ZEXPORT gzread(file, buf, len) } /* -- see zlib.h -- */ +#undef gzgetc int ZEXPORT gzgetc(file) gzFile file; { @@ -461,15 +391,16 @@ int ZEXPORT gzgetc(file) return -1; state = (gz_statep)file; - /* check that we're reading and that there's no error */ - if (state->mode != GZ_READ || state->err != Z_OK) + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) return -1; /* try output buffer (no need to check for skip request) */ - if (state->have) { - state->have--; - state->pos++; - return *(state->next)++; + if (state->x.have) { + state->x.have--; + state->x.pos++; + return *(state->x.next)++; } /* nothing there -- try gzread() */ @@ -477,6 +408,12 @@ int ZEXPORT gzgetc(file) return ret < 1 ? -1 : buf[0]; } +int ZEXPORT gzgetc_(file) +gzFile file; +{ + return gzgetc(file); +} + /* -- see zlib.h -- */ int ZEXPORT gzungetc(c, file) int c; @@ -489,8 +426,9 @@ int ZEXPORT gzungetc(c, file) return -1; state = (gz_statep)file; - /* check that we're reading and that there's no error */ - if (state->mode != GZ_READ || state->err != Z_OK) + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) return -1; /* process a skip request */ @@ -505,32 +443,34 @@ int ZEXPORT gzungetc(c, file) return -1; /* if output buffer empty, put byte at end (allows more pushing) */ - if (state->have == 0) { - state->have = 1; - state->next = state->out + (state->size << 1) - 1; - state->next[0] = c; - state->pos--; + if (state->x.have == 0) { + state->x.have = 1; + state->x.next = state->out + (state->size << 1) - 1; + state->x.next[0] = c; + state->x.pos--; + state->past = 0; return c; } /* if no room, give up (must have already done a gzungetc()) */ - if (state->have == (state->size << 1)) { - gz_error(state, Z_BUF_ERROR, "out of room to push characters"); + if (state->x.have == (state->size << 1)) { + gz_error(state, Z_DATA_ERROR, "out of room to push characters"); return -1; } /* slide output data if needed and insert byte before existing data */ - if (state->next == state->out) { - unsigned char *src = state->out + state->have; + if (state->x.next == state->out) { + unsigned char *src = state->out + state->x.have; unsigned char *dest = state->out + (state->size << 1); while (src > state->out) *--dest = *--src; - state->next = dest; + state->x.next = dest; } - state->have++; - state->next--; - state->next[0] = c; - state->pos--; + state->x.have++; + state->x.next--; + state->x.next[0] = c; + state->x.pos--; + state->past = 0; return c; } @@ -550,8 +490,9 @@ char * ZEXPORT gzgets(file, buf, len) return NULL; state = (gz_statep)file; - /* check that we're reading and that there's no error */ - if (state->mode != GZ_READ || state->err != Z_OK) + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) return NULL; /* process a skip request */ @@ -568,32 +509,31 @@ char * ZEXPORT gzgets(file, buf, len) left = (unsigned)len - 1; if (left) do { /* assure that something is in the output buffer */ - if (state->have == 0) { - if (gz_make(state) == -1) - return NULL; /* error */ - if (state->have == 0) { /* end of file */ - if (buf == str) /* got bupkus */ - return NULL; - break; /* got something -- return it */ - } + if (state->x.have == 0 && gz_fetch(state) == -1) + return NULL; /* error */ + if (state->x.have == 0) { /* end of file */ + state->past = 1; /* read past end */ + break; /* return what we have */ } /* look for end-of-line in current output buffer */ - n = state->have > left ? left : state->have; - eol = memchr(state->next, '\n', n); + n = state->x.have > left ? left : state->x.have; + eol = memchr(state->x.next, '\n', n); if (eol != NULL) - n = (unsigned)(eol - state->next) + 1; + n = (unsigned)(eol - state->x.next) + 1; /* copy through end-of-line, or remainder if not found */ - memcpy(buf, state->next, n); - state->have -= n; - state->next += n; - state->pos += n; + memcpy(buf, state->x.next, n); + state->x.have -= n; + state->x.next += n; + state->x.pos += n; left -= n; buf += n; } while (left && eol == NULL); - /* found end-of-line or out of space -- terminate string and return it */ + /* return terminated string, or if nothing, end of file */ + if (buf == str) + return NULL; buf[0] = 0; return str; } @@ -609,16 +549,12 @@ int ZEXPORT gzdirect(file) return 0; state = (gz_statep)file; - /* check that we're reading */ - if (state->mode != GZ_READ) - return 0; - /* if the state is not known, but we can find out, then do so (this is mainly for right after a gzopen() or gzdopen()) */ - if (state->how == LOOK && state->have == 0) - (void)gz_head(state); + if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) + (void)gz_look(state); - /* return 1 if reading direct, 0 if decompressing a gzip stream */ + /* return 1 if transparent, 0 if processing a gzip stream */ return state->direct; } @@ -626,7 +562,7 @@ int ZEXPORT gzdirect(file) int ZEXPORT gzclose_r(file) gzFile file; { - int ret; + int ret, err; gz_statep state; /* get internal structure */ @@ -644,9 +580,10 @@ int ZEXPORT gzclose_r(file) free(state->out); free(state->in); } + err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK; gz_error(state, Z_OK, NULL); free(state->path); ret = close(state->fd); free(state); - return ret ? Z_ERRNO : Z_OK; + return ret ? Z_ERRNO : err; } diff --git a/3rdparty/zlib/gzwrite.c b/3rdparty/zlib/gzwrite.c index e8defc688..27cb3428e 100644 --- a/3rdparty/zlib/gzwrite.c +++ b/3rdparty/zlib/gzwrite.c @@ -1,5 +1,5 @@ /* gzwrite.c -- zlib functions for writing gzip files - * Copyright (C) 2004, 2005, 2010 Mark Adler + * Copyright (C) 2004, 2005, 2010, 2011, 2012 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -18,44 +18,55 @@ local int gz_init(state) int ret; z_streamp strm = &(state->strm); - /* allocate input and output buffers */ + /* allocate input buffer */ state->in = malloc(state->want); - state->out = malloc(state->want); - if (state->in == NULL || state->out == NULL) { - if (state->out != NULL) - free(state->out); - if (state->in != NULL) - free(state->in); + if (state->in == NULL) { gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } - /* allocate deflate memory, set up for gzip compression */ - strm->zalloc = Z_NULL; - strm->zfree = Z_NULL; - strm->opaque = Z_NULL; - ret = deflateInit2(strm, state->level, Z_DEFLATED, - 15 + 16, 8, state->strategy); - if (ret != Z_OK) { - free(state->in); - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; + /* only need output buffer and deflate state if compressing */ + if (!state->direct) { + /* allocate output buffer */ + state->out = malloc(state->want); + if (state->out == NULL) { + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + + /* allocate deflate memory, set up for gzip compression */ + strm->zalloc = Z_NULL; + strm->zfree = Z_NULL; + strm->opaque = Z_NULL; + ret = deflateInit2(strm, state->level, Z_DEFLATED, + MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy); + if (ret != Z_OK) { + free(state->out); + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } } /* mark state as initialized */ state->size = state->want; - /* initialize write buffer */ - strm->avail_out = state->size; - strm->next_out = state->out; - state->next = strm->next_out; + /* initialize write buffer if compressing */ + if (!state->direct) { + strm->avail_out = state->size; + strm->next_out = state->out; + state->x.next = strm->next_out; + } return 0; } /* Compress whatever is at avail_in and next_in and write to the output file. Return -1 if there is an error writing to the output file, otherwise 0. flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH, - then the deflate() state is reset to start a new gzip stream. */ + then the deflate() state is reset to start a new gzip stream. If gz->direct + is true, then simply write to the output file without compressing, and + ignore flush. */ local int gz_comp(state, flush) gz_statep state; int flush; @@ -68,6 +79,17 @@ local int gz_comp(state, flush) if (state->size == 0 && gz_init(state) == -1) return -1; + /* write directly if requested */ + if (state->direct) { + got = write(state->fd, strm->next_in, strm->avail_in); + if (got < 0 || (unsigned)got != strm->avail_in) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + strm->avail_in = 0; + return 0; + } + /* run deflate() on provided input until it produces no more output */ ret = Z_OK; do { @@ -75,8 +97,8 @@ local int gz_comp(state, flush) doing Z_FINISH then don't write until we get to Z_STREAM_END */ if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && (flush != Z_FINISH || ret == Z_STREAM_END))) { - have = (unsigned)(strm->next_out - state->next); - if (have && ((got = write(state->fd, state->next, have)) < 0 || + have = (unsigned)(strm->next_out - state->x.next); + if (have && ((got = write(state->fd, state->x.next, have)) < 0 || (unsigned)got != have)) { gz_error(state, Z_ERRNO, zstrerror()); return -1; @@ -85,7 +107,7 @@ local int gz_comp(state, flush) strm->avail_out = state->size; strm->next_out = state->out; } - state->next = strm->next_out; + state->x.next = strm->next_out; } /* compress */ @@ -131,7 +153,7 @@ local int gz_zero(state, len) } strm->avail_in = n; strm->next_in = state->in; - state->pos += n; + state->x.pos += n; if (gz_comp(state, Z_NO_FLUSH) == -1) return -1; len -= n; @@ -163,7 +185,7 @@ int ZEXPORT gzwrite(file, buf, len) /* since an int is returned, make sure len fits in one, otherwise return with an error (this avoids the flaw in the interface) */ if ((int)len < 0) { - gz_error(state, Z_BUF_ERROR, "requested length does not fit in int"); + gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); return 0; } @@ -193,7 +215,7 @@ int ZEXPORT gzwrite(file, buf, len) n = len; memcpy(strm->next_in + strm->avail_in, buf, n); strm->avail_in += n; - state->pos += n; + state->x.pos += n; buf = (char *)buf + n; len -= n; if (len && gz_comp(state, Z_NO_FLUSH) == -1) @@ -208,7 +230,7 @@ int ZEXPORT gzwrite(file, buf, len) /* directly compress user buffer to file */ strm->avail_in = len; strm->next_in = (voidp)buf; - state->pos += len; + state->x.pos += len; if (gz_comp(state, Z_NO_FLUSH) == -1) return 0; } @@ -249,15 +271,15 @@ int ZEXPORT gzputc(file, c) if (strm->avail_in == 0) strm->next_in = state->in; strm->next_in[strm->avail_in++] = c; - state->pos++; - return c; + state->x.pos++; + return c & 0xff; } /* no room in buffer or not initialized, use gz_write() */ buf[0] = c; if (gzwrite(file, buf, 1) != 1) return -1; - return c; + return c & 0xff; } /* -- see zlib.h -- */ @@ -274,7 +296,7 @@ int ZEXPORT gzputs(file, str) return ret == 0 && len != 0 ? -1 : ret; } -#ifdef STDC +#if defined(STDC) || defined(Z_HAVE_STDARG_H) #include /* -- see zlib.h -- */ @@ -316,19 +338,19 @@ int ZEXPORTVA gzprintf (gzFile file, const char *format, ...) va_start(va, format); #ifdef NO_vsnprintf # ifdef HAS_vsprintf_void - (void)vsprintf(state->in, format, va); + (void)vsprintf((char *)(state->in), format, va); va_end(va); for (len = 0; len < size; len++) if (state->in[len] == 0) break; # else - len = vsprintf(state->in, format, va); + len = vsprintf((char *)(state->in), format, va); va_end(va); # endif #else # ifdef HAS_vsnprintf_void - (void)vsnprintf(state->in, size, format, va); + (void)vsnprintf((char *)(state->in), size, format, va); va_end(va); - len = strlen(state->in); + len = strlen((char *)(state->in)); # else len = vsnprintf((char *)(state->in), size, format, va); va_end(va); @@ -342,11 +364,11 @@ int ZEXPORTVA gzprintf (gzFile file, const char *format, ...) /* update buffer and position, defer compression until needed */ strm->avail_in = (unsigned)len; strm->next_in = state->in; - state->pos += len; + state->x.pos += len; return len; } -#else /* !STDC */ +#else /* !STDC && !Z_HAVE_STDARG_H */ /* -- see zlib.h -- */ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, @@ -366,6 +388,10 @@ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, state = (gz_statep)file; strm = &(state->strm); + /* check that can really pass pointer in ints */ + if (sizeof(int) != sizeof(void *)) + return 0; + /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return 0; @@ -390,22 +416,23 @@ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, state->in[size - 1] = 0; #ifdef NO_snprintf # ifdef HAS_sprintf_void - sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8, + sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); for (len = 0; len < size; len++) if (state->in[len] == 0) break; # else - len = sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); # endif #else # ifdef HAS_snprintf_void - snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8, + snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); - len = strlen(state->in); + len = strlen((char *)(state->in)); # else - len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, + a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, + a19, a20); # endif #endif @@ -416,7 +443,7 @@ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, /* update buffer and position, defer compression until needed */ strm->avail_in = (unsigned)len; strm->next_in = state->in; - state->pos += len; + state->x.pos += len; return len; } @@ -500,7 +527,7 @@ int ZEXPORT gzsetparams(file, level, strategy) int ZEXPORT gzclose_w(file) gzFile file; { - int ret = 0; + int ret = Z_OK; gz_statep state; /* get internal structure */ @@ -515,17 +542,24 @@ int ZEXPORT gzclose_w(file) /* check for seek request */ if (state->seek) { state->seek = 0; - ret += gz_zero(state, state->skip); + if (gz_zero(state, state->skip) == -1) + ret = state->err; } /* flush, free memory, and close file */ - ret += gz_comp(state, Z_FINISH); - (void)deflateEnd(&(state->strm)); - free(state->out); - free(state->in); + if (state->size) { + if (gz_comp(state, Z_FINISH) == -1) + ret = state->err; + if (!state->direct) { + (void)deflateEnd(&(state->strm)); + free(state->out); + } + free(state->in); + } gz_error(state, Z_OK, NULL); free(state->path); - ret += close(state->fd); + if (close(state->fd) == -1) + ret = Z_ERRNO; free(state); - return ret ? Z_ERRNO : Z_OK; + return ret; } diff --git a/3rdparty/zlib/infback.c b/3rdparty/zlib/infback.c index af3a8c965..981aff17c 100644 --- a/3rdparty/zlib/infback.c +++ b/3rdparty/zlib/infback.c @@ -1,5 +1,5 @@ /* infback.c -- inflate using a call-back interface - * Copyright (C) 1995-2009 Mark Adler + * Copyright (C) 1995-2011 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -42,10 +42,19 @@ int stream_size; return Z_STREAM_ERROR; strm->msg = Z_NULL; /* in case we return an error */ if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else strm->zalloc = zcalloc; strm->opaque = (voidpf)0; +#endif } - if (strm->zfree == (free_func)0) strm->zfree = zcfree; + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif state = (struct inflate_state FAR *)ZALLOC(strm, 1, sizeof(struct inflate_state)); if (state == Z_NULL) return Z_MEM_ERROR; @@ -394,7 +403,6 @@ void FAR *out_desc; PULLBYTE(); } if (here.val < 16) { - NEEDBITS(here.bits); DROPBITS(here.bits); state->lens[state->have++] = here.val; } diff --git a/3rdparty/zlib/inffast.c b/3rdparty/zlib/inffast.c index 0a0761f3d..2f1d60b43 100644 --- a/3rdparty/zlib/inffast.c +++ b/3rdparty/zlib/inffast.c @@ -1,5 +1,5 @@ /* inffast.c -- fast decoding - * Copyright (C) 1995-2008 Mark Adler + * Copyright (C) 1995-2008, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -64,7 +64,7 @@ requires strm->avail_out >= 258 for each loop to avoid checking for output space. */ -void inflate_fast(strm, start) +void ZLIB_INTERNAL inflate_fast(strm, start) z_streamp strm; unsigned start; /* inflate()'s starting value for strm->avail_out */ { diff --git a/3rdparty/zlib/inffast.h b/3rdparty/zlib/inffast.h index 1e88d2d97..e5c1aa4ca 100644 --- a/3rdparty/zlib/inffast.h +++ b/3rdparty/zlib/inffast.h @@ -1,5 +1,5 @@ /* inffast.h -- header to use inffast.c - * Copyright (C) 1995-2003 Mark Adler + * Copyright (C) 1995-2003, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -8,4 +8,4 @@ subject to change. Applications should only use zlib.h. */ -void inflate_fast OF((z_streamp strm, unsigned start)); +void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/3rdparty/zlib/inffixed.h b/3rdparty/zlib/inffixed.h index 75ed4b597..d62832776 100644 --- a/3rdparty/zlib/inffixed.h +++ b/3rdparty/zlib/inffixed.h @@ -2,9 +2,9 @@ * 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. + /* WARNING: this file should *not* be used by applications. + It is part of the implementation of this library and is + subject to change. Applications should only use zlib.h. */ static const code lenfix[512] = { diff --git a/3rdparty/zlib/inflate.c b/3rdparty/zlib/inflate.c index a8431abea..47418a1e1 100644 --- a/3rdparty/zlib/inflate.c +++ b/3rdparty/zlib/inflate.c @@ -1,5 +1,5 @@ /* inflate.c -- zlib decompression - * Copyright (C) 1995-2010 Mark Adler + * Copyright (C) 1995-2012 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -100,7 +100,7 @@ local int updatewindow OF((z_streamp strm, unsigned out)); local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, unsigned len)); -int ZEXPORT inflateReset(strm) +int ZEXPORT inflateResetKeep(strm) z_streamp strm; { struct inflate_state FAR *state; @@ -109,15 +109,13 @@ z_streamp strm; state = (struct inflate_state FAR *)strm->state; strm->total_in = strm->total_out = state->total = 0; strm->msg = Z_NULL; - strm->adler = 1; /* to support ill-conceived Java test suite */ + if (state->wrap) /* to support ill-conceived Java test suite */ + strm->adler = state->wrap & 1; state->mode = HEAD; state->last = 0; state->havedict = 0; state->dmax = 32768U; state->head = Z_NULL; - state->wsize = 0; - state->whave = 0; - state->wnext = 0; state->hold = 0; state->bits = 0; state->lencode = state->distcode = state->next = state->codes; @@ -127,6 +125,19 @@ z_streamp strm; return Z_OK; } +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + state->wsize = 0; + state->whave = 0; + state->wnext = 0; + return inflateResetKeep(strm); +} + int ZEXPORT inflateReset2(strm, windowBits) z_streamp strm; int windowBits; @@ -180,10 +191,19 @@ int stream_size; if (strm == Z_NULL) return Z_STREAM_ERROR; strm->msg = Z_NULL; /* in case we return an error */ if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else strm->zalloc = zcalloc; strm->opaque = (voidpf)0; +#endif } - if (strm->zfree == (free_func)0) strm->zfree = zcfree; + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif state = (struct inflate_state FAR *) ZALLOC(strm, 1, sizeof(struct inflate_state)); if (state == Z_NULL) return Z_MEM_ERROR; @@ -321,8 +341,8 @@ void makefixed() low = 0; for (;;) { if ((low % 7) == 0) printf("\n "); - printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, - state.lencode[low].val); + printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, + state.lencode[low].bits, state.lencode[low].val); if (++low == size) break; putchar(','); } @@ -499,11 +519,6 @@ unsigned out; bits -= bits & 7; \ } while (0) -/* Reverse the bytes in a 32-bit value */ -#define REVERSE(q) \ - ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ - (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) - /* inflate() uses a state machine to process as much input data and generate as much output data as possible before returning. The state machine is @@ -797,7 +812,7 @@ int flush; #endif case DICTID: NEEDBITS(32); - strm->adler = state->check = REVERSE(hold); + strm->adler = state->check = ZSWAP32(hold); INITBITS(); state->mode = DICT; case DICT: @@ -925,7 +940,6 @@ int flush; PULLBYTE(); } if (here.val < 16) { - NEEDBITS(here.bits); DROPBITS(here.bits); state->lens[state->have++] = here.val; } @@ -1170,7 +1184,7 @@ int flush; #ifdef GUNZIP state->flags ? hold : #endif - REVERSE(hold)) != state->check) { + ZSWAP32(hold)) != state->check) { strm->msg = (char *)"incorrect data check"; state->mode = BAD; break; @@ -1214,7 +1228,8 @@ int flush; */ inf_leave: RESTORE(); - if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (state->wsize || (out != strm->avail_out && state->mode < BAD && + (state->mode < CHECK || flush != Z_FINISH))) if (updatewindow(strm, out)) { state->mode = MEM; return Z_MEM_ERROR; @@ -1255,7 +1270,10 @@ const Bytef *dictionary; uInt dictLength; { struct inflate_state FAR *state; - unsigned long id; + unsigned long dictid; + unsigned char *next; + unsigned avail; + int ret; /* check state */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; @@ -1263,29 +1281,27 @@ uInt dictLength; if (state->wrap != 0 && state->mode != DICT) return Z_STREAM_ERROR; - /* check for correct dictionary id */ + /* check for correct dictionary identifier */ if (state->mode == DICT) { - id = adler32(0L, Z_NULL, 0); - id = adler32(id, dictionary, dictLength); - if (id != state->check) + dictid = adler32(0L, Z_NULL, 0); + dictid = adler32(dictid, dictionary, dictLength); + if (dictid != state->check) return Z_DATA_ERROR; } - /* copy dictionary to window */ - if (updatewindow(strm, strm->avail_out)) { + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + next = strm->next_out; + avail = strm->avail_out; + strm->next_out = (Bytef *)dictionary + dictLength; + strm->avail_out = 0; + ret = updatewindow(strm, dictLength); + strm->avail_out = avail; + strm->next_out = next; + if (ret) { state->mode = MEM; return Z_MEM_ERROR; } - if (dictLength > state->wsize) { - zmemcpy(state->window, dictionary + dictLength - state->wsize, - state->wsize); - state->whave = state->wsize; - } - else { - zmemcpy(state->window + state->wsize - dictLength, dictionary, - dictLength); - state->whave = dictLength; - } state->havedict = 1; Tracev((stderr, "inflate: dictionary set\n")); return Z_OK; @@ -1433,8 +1449,8 @@ z_streamp source; } /* copy state */ - zmemcpy(dest, source, sizeof(z_stream)); - zmemcpy(copy, state, sizeof(struct inflate_state)); + zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); + zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); if (state->lencode >= state->codes && state->lencode <= state->codes + ENOUGH - 1) { copy->lencode = copy->codes + (state->lencode - state->codes); diff --git a/3rdparty/zlib/inftrees.c b/3rdparty/zlib/inftrees.c index ccf7fa965..abcd7c45e 100644 --- a/3rdparty/zlib/inftrees.c +++ b/3rdparty/zlib/inftrees.c @@ -1,5 +1,5 @@ /* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2010 Mark Adler + * Copyright (C) 1995-2012 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -9,7 +9,7 @@ #define MAXBITS 15 const char inflate_copyright[] = - " inflate 1.2.4 Copyright 1995-2010 Mark Adler "; + " inflate 1.2.7 Copyright 1995-2012 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -29,7 +29,7 @@ const char inflate_copyright[] = table index bits. It will differ if the request is greater than the longest code or if it is less than the shortest code. */ -int inflate_table(type, lens, codes, table, bits, work) +int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work) codetype type; unsigned short FAR *lens; unsigned codes; @@ -62,7 +62,7 @@ unsigned short FAR *work; 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 64, 195}; + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 78, 68}; static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, @@ -289,38 +289,14 @@ unsigned short FAR *work; } } - /* - Fill in rest of table for incomplete codes. This loop is similar to the - loop above in incrementing huff for table indices. It is assumed that - len is equal to curr + drop, so there is no loop needed to increment - through high index bits. When the current sub-table is filled, the loop - drops back to the root table to fill in any remaining entries there. - */ - here.op = (unsigned char)64; /* invalid code marker */ - here.bits = (unsigned char)(len - drop); - here.val = (unsigned short)0; - while (huff != 0) { - /* when done with sub-table, drop back to root table */ - if (drop != 0 && (huff & mask) != low) { - drop = 0; - len = root; - next = *table; - here.bits = (unsigned char)len; - } - - /* put invalid code marker in table */ - next[huff >> drop] = here; - - /* backwards increment the len-bit code huff */ - incr = 1U << (len - 1); - while (huff & incr) - incr >>= 1; - if (incr != 0) { - huff &= incr - 1; - huff += incr; - } - else - huff = 0; + /* fill in remaining table entry if code is incomplete (guaranteed to have + at most one remaining entry, since if the code is incomplete, the + maximum code length that was allowed to get this far is one bit) */ + if (huff != 0) { + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)(len - drop); + here.val = (unsigned short)0; + next[huff] = here; } /* set return parameters */ diff --git a/3rdparty/zlib/inftrees.h b/3rdparty/zlib/inftrees.h index 67461da03..baa53a0b1 100644 --- a/3rdparty/zlib/inftrees.h +++ b/3rdparty/zlib/inftrees.h @@ -1,5 +1,5 @@ /* inftrees.h -- header to use inftrees.c - * Copyright (C) 1995-2005 Mark Adler + * Copyright (C) 1995-2005, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -57,6 +57,6 @@ typedef enum { DISTS } codetype; -extern int inflate_table OF((codetype type, unsigned short FAR *lens, +int ZLIB_INTERNAL 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/3rdparty/zlib/trees.c b/3rdparty/zlib/trees.c index 1a6e997ac..8c32b214b 100644 --- a/3rdparty/zlib/trees.c +++ b/3rdparty/zlib/trees.c @@ -1,5 +1,5 @@ /* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1995-2009 Jean-loup Gailly + * Copyright (C) 1995-2012 Jean-loup Gailly * detect_data_type() function provided freely by Cosmin Truta, 2006 * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -74,11 +74,6 @@ local const uch bl_order[BL_CODES] * probability, to avoid transmitting the lengths for unused bit length codes. */ -#define Buf_size (8 * 2*sizeof(char)) -/* Number of bits used within bi_buf. (bi_buf might be implemented on - * more than 16 bits on some systems.) - */ - /* =========================================================================== * Local data. These are initialized only once. */ @@ -351,13 +346,14 @@ void gen_trees_header() static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); } - fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); for (i = 0; i < DIST_CODE_LEN; i++) { fprintf(header, "%2u%s", _dist_code[i], SEPARATOR(i, DIST_CODE_LEN-1, 20)); } - fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + fprintf(header, + "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { fprintf(header, "%2u%s", _length_code[i], SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); @@ -382,7 +378,7 @@ void gen_trees_header() /* =========================================================================== * Initialize the tree data structures for a new zlib stream. */ -void _tr_init(s) +void ZLIB_INTERNAL _tr_init(s) deflate_state *s; { tr_static_init(); @@ -398,7 +394,6 @@ void _tr_init(s) s->bi_buf = 0; s->bi_valid = 0; - s->last_eob_len = 8; /* enough lookahead for inflate */ #ifdef DEBUG s->compressed_len = 0L; s->bits_sent = 0L; @@ -867,7 +862,7 @@ local void send_all_trees(s, lcodes, dcodes, blcodes) /* =========================================================================== * Send a stored block */ -void _tr_stored_block(s, buf, stored_len, last) +void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) deflate_state *s; charf *buf; /* input block */ ulg stored_len; /* length of input block */ @@ -881,18 +876,20 @@ void _tr_stored_block(s, buf, stored_len, last) copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ } +/* =========================================================================== + * Flush the bits in the bit buffer to pending output (leaves at most 7 bits) + */ +void ZLIB_INTERNAL _tr_flush_bits(s) + deflate_state *s; +{ + bi_flush(s); +} + /* =========================================================================== * Send one empty static block to give enough lookahead for inflate. * This takes 10 bits, of which 7 may remain in the bit buffer. - * The current inflate code requires 9 bits of lookahead. If the - * last two codes for the previous block (real code plus EOB) were coded - * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode - * the last real code. In this case we send two empty static blocks instead - * of one. (There are no problems if the previous block is stored or fixed.) - * To simplify the code, we assume the worst case of last real code encoded - * on one bit only. */ -void _tr_align(s) +void ZLIB_INTERNAL _tr_align(s) deflate_state *s; { send_bits(s, STATIC_TREES<<1, 3); @@ -901,27 +898,13 @@ void _tr_align(s) s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ #endif bi_flush(s); - /* Of the 10 bits for the empty block, we have already sent - * (10 - bi_valid) bits. The lookahead for the last real code (before - * the EOB of the previous block) was thus at least one plus the length - * of the EOB plus what we have just sent of the empty static block. - */ - if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { - send_bits(s, STATIC_TREES<<1, 3); - send_code(s, END_BLOCK, static_ltree); -#ifdef DEBUG - s->compressed_len += 10L; -#endif - bi_flush(s); - } - s->last_eob_len = 7; } /* =========================================================================== * Determine the best encoding for the current block: dynamic trees, static * trees or store, and output the encoded block to the zip file. */ -void _tr_flush_block(s, buf, stored_len, last) +void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) deflate_state *s; charf *buf; /* input block, or NULL if too old */ ulg stored_len; /* length of input block */ @@ -1022,7 +1005,7 @@ void _tr_flush_block(s, buf, stored_len, last) * Save the match info and tally the frequency counts. Return true if * the current block must be flushed. */ -int _tr_tally (s, dist, lc) +int ZLIB_INTERNAL _tr_tally (s, dist, lc) deflate_state *s; unsigned dist; /* distance of matched string */ unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ @@ -1117,7 +1100,6 @@ local void compress_block(s, ltree, dtree) } while (lx < s->last_lit); send_code(s, END_BLOCK, ltree); - s->last_eob_len = ltree[END_BLOCK].Len; } /* =========================================================================== @@ -1225,7 +1207,6 @@ local void copy_block(s, buf, len, header) int header; /* true if block header must be written */ { bi_windup(s); /* align on byte boundary */ - s->last_eob_len = 8; /* enough lookahead for inflate */ if (header) { put_short(s, (ush)len); diff --git a/3rdparty/zlib/trees.h b/3rdparty/zlib/trees.h index 72facf900..d35639d82 100644 --- a/3rdparty/zlib/trees.h +++ b/3rdparty/zlib/trees.h @@ -70,7 +70,7 @@ local const ct_data static_dtree[D_CODES] = { {{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} }; -const uch _dist_code[DIST_CODE_LEN] = { +const uch ZLIB_INTERNAL _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, @@ -99,7 +99,7 @@ const uch _dist_code[DIST_CODE_LEN] = { 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 }; -const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { +const uch ZLIB_INTERNAL _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, diff --git a/3rdparty/zlib/zconf.h b/3rdparty/zlib/zconf.h index 58880245c..8a46a58b3 100644 --- a/3rdparty/zlib/zconf.h +++ b/3rdparty/zlib/zconf.h @@ -1,5 +1,5 @@ /* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2010 Jean-loup Gailly. + * Copyright (C) 1995-2012 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -15,6 +15,7 @@ * this permanently in zconf.h using "./configure --zprefix". */ #ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET /* all linked symbols */ # define _dist_code z__dist_code @@ -27,9 +28,11 @@ # define adler32 z_adler32 # define adler32_combine z_adler32_combine # define adler32_combine64 z_adler32_combine64 -# define compress z_compress -# define compress2 z_compress2 -# define compressBound z_compressBound +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif # define crc32 z_crc32 # define crc32_combine z_crc32_combine # define crc32_combine64 z_crc32_combine64 @@ -40,44 +43,52 @@ # define deflateInit2_ z_deflateInit2_ # define deflateInit_ z_deflateInit_ # define deflateParams z_deflateParams +# define deflatePending z_deflatePending # define deflatePrime z_deflatePrime # define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep # define deflateSetDictionary z_deflateSetDictionary # define deflateSetHeader z_deflateSetHeader # define deflateTune z_deflateTune # define deflate_copyright z_deflate_copyright # define get_crc_table z_get_crc_table -# define gz_error z_gz_error -# define gz_intmax z_gz_intmax -# define gz_strwinerror z_gz_strwinerror -# define gzbuffer z_gzbuffer -# define gzclearerr z_gzclearerr -# define gzclose z_gzclose -# define gzclose_r z_gzclose_r -# define gzclose_w z_gzclose_w -# define gzdirect z_gzdirect -# define gzdopen z_gzdopen -# define gzeof z_gzeof -# define gzerror z_gzerror -# define gzflush z_gzflush -# define gzgetc z_gzgetc -# define gzgets z_gzgets -# define gzoffset z_gzoffset -# define gzoffset64 z_gzoffset64 -# define gzopen z_gzopen -# define gzopen64 z_gzopen64 -# define gzprintf z_gzprintf -# define gzputc z_gzputc -# define gzputs z_gzputs -# define gzread z_gzread -# define gzrewind z_gzrewind -# define gzseek z_gzseek -# define gzseek64 z_gzseek64 -# define gzsetparams z_gzsetparams -# define gztell z_gztell -# define gztell64 z_gztell64 -# define gzungetc z_gzungetc -# define gzwrite z_gzwrite +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzwrite z_gzwrite +# endif # define inflate z_inflate # define inflateBack z_inflateBack # define inflateBackEnd z_inflateBackEnd @@ -95,13 +106,18 @@ # define inflateSync z_inflateSync # define inflateSyncPoint z_inflateSyncPoint # define inflateUndermine z_inflateUndermine +# define inflateResetKeep z_inflateResetKeep # define inflate_copyright z_inflate_copyright # define inflate_fast z_inflate_fast # define inflate_table z_inflate_table -# define uncompress z_uncompress +# ifndef Z_SOLO +# define uncompress z_uncompress +# endif # define zError z_zError -# define zcalloc z_zcalloc -# define zcfree z_zcfree +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif # define zlibCompileFlags z_zlibCompileFlags # define zlibVersion z_zlibVersion @@ -111,7 +127,9 @@ # define alloc_func z_alloc_func # define charf z_charf # define free_func z_free_func -# define gzFile z_gzFile +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif # define gz_header z_gz_header # define gz_headerp z_gz_headerp # define in_func z_in_func @@ -197,6 +215,12 @@ # endif #endif +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + /* Some Mac compilers merge all .h files incorrectly: */ #if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) # define NO_DUMMY_DECL @@ -243,6 +267,14 @@ # endif #endif +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(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 @@ -315,10 +347,6 @@ # endif #endif -#ifdef HAVE_VISIBILITY_PRAGMA -# define ZEXTERN __attribute__((visibility ("default"))) extern -#endif - #ifndef ZEXTERN # define ZEXTERN extern #endif @@ -360,40 +388,102 @@ typedef uLong FAR uLongf; typedef Byte *voidp; #endif +/* ./configure may #define Z_U4 here */ + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# else +# if (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# else +# if (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +# endif +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + #ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ # define Z_HAVE_UNISTD_H #endif -#ifdef Z_HAVE_UNISTD_H -# include /* for off_t */ -# include /* for SEEK_* and off_t */ -# ifdef VMS -# include /* for off_t */ -# endif -# ifndef z_off_t -# define z_off_t off_t +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ # endif #endif -#ifdef _LARGEFILE64_SOURCE -# include +#ifdef _WIN32 +# include /* for wchar_t */ #endif -#ifndef SEEK_SET +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) # 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 +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif #endif /* MVS linker does not support external names larger than 8 bytes */ diff --git a/3rdparty/zlib/zlib.h b/3rdparty/zlib/zlib.h index f5785be7e..3edf3acdb 100644 --- a/3rdparty/zlib/zlib.h +++ b/3rdparty/zlib/zlib.h @@ -1,7 +1,7 @@ /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.4, Mar 14th, 2010 + version 1.2.7, May 2nd, 2012 - Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + Copyright (C) 1995-2012 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 @@ -24,8 +24,8 @@ 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). + Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ #ifndef ZLIB_H @@ -37,11 +37,11 @@ extern "C" { #endif -#define ZLIB_VERSION "1.2.4" -#define ZLIB_VERNUM 0x1240 +#define ZLIB_VERSION "1.2.7" +#define ZLIB_VERNUM 0x1270 #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 4 +#define ZLIB_VER_REVISION 7 #define ZLIB_VER_SUBREVISION 0 /* @@ -83,15 +83,15 @@ typedef void (*free_func) OF((voidpf opaque, voidpf address)); struct internal_state; typedef struct z_stream_s { - Bytef *next_in; /* next input byte */ + z_const 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 */ + uLong total_in; /* total number 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 */ + uLong total_out; /* total number of bytes output so far */ - char *msg; /* last error message, NULL if no error */ + z_const 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 */ @@ -327,8 +327,9 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); 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. + value returned by deflateBound (see below). Then deflate is guaranteed to + return Z_STREAM_END. If not enough output space is provided, deflate will + not return Z_STREAM_END, and 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). @@ -451,23 +452,29 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); 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. + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. 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 or Z_TREES is used. + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH 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 + below), inflate sets strm->adler to the Adler-32 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, + strm->adler to the Adler-32 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 @@ -478,7 +485,9 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); initializing with inflateInit2(). 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. + perform their own processing of the gzip header and trailer. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + producted so far. The CRC-32 is checked against the gzip 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 @@ -580,10 +589,15 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, 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). + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. 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 @@ -610,8 +624,8 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) 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(). + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, @@ -688,9 +702,29 @@ ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, deflation of sourceLen bytes. It must be called after deflateInit() or deflateInit2(), and after deflateSetHeader(), if used. This would be used to allocate an output buffer for deflation in a single pass, and so would be - called before deflate(). + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. */ +ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, + unsigned *pending, + int *bits)); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, int bits, int value)); @@ -703,8 +737,9 @@ ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, 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. + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. */ ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, @@ -790,10 +825,11 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, 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. + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. 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 (e.g. dictionary being Z_NULL) or the stream state is @@ -805,17 +841,21 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, 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 + Skips invalid compressed data until a possible full flush point (see above + for 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. + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible 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, @@ -962,7 +1002,7 @@ ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, 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 + the parameters 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. */ @@ -1088,6 +1128,7 @@ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); 27-31: 0 (reserved) */ +#ifndef Z_SOLO /* utility functions */ @@ -1149,10 +1190,11 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, 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. + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. */ - /* gzip file access functions */ /* @@ -1162,7 +1204,7 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, wrapper, documented in RFC 1952, wrapped around a deflate stream. */ -typedef voidp gzFile; /* opaque gzip file descriptor */ +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ /* ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); @@ -1172,13 +1214,28 @@ ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression as in "wb9F". (See the description of - deflateInit2 for more information about the strategy parameter.) Also "a" - can be used instead of "w" to request that the gzip stream that will be - written be appended to the file. "+" will result in an error, since reading - and writing to the same gzip file is not supported. + deflateInit2 for more information about the strategy parameter.) 'T' will + request transparent writing or appending with no compression and not using + the gzip format. + + "a" can be used instead of "w" to request that the gzip stream that will + be written be appended to the file. "+" will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + "x" when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of "e" when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. 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. + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. gzopen returns NULL if the file could not be opened, if there was insufficient memory to allocate the gzFile state, or if an invalid mode was @@ -1197,7 +1254,11 @@ ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, mode);. The duplicated descriptor should be saved to avoid a leak, since - gzdopen does not close fd if it fails. + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. gzdopen returns NULL if there was insufficient memory to allocate the gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not @@ -1235,14 +1296,26 @@ ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); 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. + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. After reaching the end of a gzip stream in the input, gzread will continue - to read, looking for another gzip stream, or failing that, reading the rest - of the input file directly without decompression. The entire input file - will be read if gzread is called until it returns less than the requested - len. + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. gzread returns the number of uncompressed bytes actually read, less than len for end of file, or -1 for error. @@ -1256,7 +1329,7 @@ ZEXTERN int ZEXPORT gzwrite OF((gzFile file, error. */ -ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); /* Converts, formats, and writes the arguments to the compressed file under control of the format string, as in fprintf. gzprintf returns the number of @@ -1301,7 +1374,10 @@ ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); 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. + in case of end of file or error. This is implemented as a macro for speed. + As such, it does not do all of the checking the other functions do. I.e. + it does not check to see if file is NULL, nor whether the structure file + points to has been clobbered or not. */ ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); @@ -1397,9 +1473,7 @@ ZEXTERN int ZEXPORT gzeof OF((gzFile file)); ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); /* Returns true (1) if file is being copied directly while reading, or false - (0) if file is a gzip stream being decompressed. This state can change from - false to true while reading the input file if the end of a gzip stream is - reached, but is followed by data that is not another gzip stream. + (0) if file is a gzip stream being decompressed. If the input file is empty, gzdirect() will return true, since the input does not contain a gzip stream. @@ -1408,6 +1482,13 @@ ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); cause buffers to be allocated to allow reading the file to determine if it is a gzip file. Therefore if gzbuffer() is used, it should be called before gzdirect(). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) */ ZEXTERN int ZEXPORT gzclose OF((gzFile file)); @@ -1419,7 +1500,8 @@ ZEXTERN int ZEXPORT gzclose OF((gzFile file)); must not be called more than once on the same allocation. gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a - file operation error, or Z_OK on success. + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. */ ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); @@ -1457,6 +1539,7 @@ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); file that is being written concurrently. */ +#endif /* !Z_SOLO */ /* checksum functions */ @@ -1492,16 +1575,17 @@ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, 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. + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. */ 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 Z_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. + initial value 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: @@ -1544,41 +1628,81 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, const char *version, int stream_size)); #define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) #define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) #define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, sizeof(z_stream)) + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) #define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) #define inflateBackInit(strm, windowBits, window) \ inflateBackInit_((strm), (windowBits), (window), \ - ZLIB_VERSION, sizeof(z_stream)) + ZLIB_VERSION, (int)sizeof(z_stream)) -#ifdef _LARGEFILE64_SOURCE - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN off64_t ZEXPORT gzseek64 OF((gzFile, off64_t, int)); - ZEXTERN off64_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN off64_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, off64_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, off64_t)); +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) #endif -#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS == 64 -# define gzopen gzopen64 -# define gzseek gzseek64 -# define gztell gztell64 -# define gzoffset gzoffset64 -# define adler32_combine adler32_combine64 -# define crc32_combine crc32_combine64 -# ifndef _LARGEFILE64_SOURCE +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#ifdef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# endif +# ifndef Z_LARGE64 ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN off_t ZEXPORT gzseek64 OF((gzFile, off_t, int)); - ZEXTERN off_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN off_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, off_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, off_t)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); # endif #else ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); @@ -1589,14 +1713,29 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); #endif +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + +#endif /* !Z_SOLO */ + +/* hack for buggy compilers */ #if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) - struct internal_state {int dummy;}; /* hack for buggy compilers */ + struct internal_state {int dummy;}; #endif +/* undocumented functions */ ZEXTERN const char * ZEXPORT zError OF((int)); ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); -ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); +ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); +#if defined(_WIN32) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, + const char *mode)); +#endif #ifdef __cplusplus } diff --git a/3rdparty/zlib/zutil.c b/3rdparty/zlib/zutil.c index 98a55a883..65e0d3b72 100644 --- a/3rdparty/zlib/zutil.c +++ b/3rdparty/zlib/zutil.c @@ -1,11 +1,14 @@ /* zutil.c -- target dependent utility functions for the compression library - * Copyright (C) 1995-2005 Jean-loup Gailly. + * Copyright (C) 1995-2005, 2010, 2011, 2012 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #include "zutil.h" +#ifndef Z_SOLO +# include "gzguts.h" +#endif #ifndef NO_DUMMY_DECL struct internal_state {int dummy;}; /* for buggy compilers */ @@ -85,27 +88,27 @@ uLong ZEXPORT zlibCompileFlags() #ifdef FASTEST flags += 1L << 21; #endif -#ifdef STDC +#if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifdef NO_vsnprintf - flags += 1L << 25; + flags += 1L << 25; # ifdef HAS_vsprintf_void - flags += 1L << 26; + flags += 1L << 26; # endif # else # ifdef HAS_vsnprintf_void - flags += 1L << 26; + flags += 1L << 26; # endif # endif #else - flags += 1L << 24; + flags += 1L << 24; # ifdef NO_snprintf - flags += 1L << 25; + flags += 1L << 25; # ifdef HAS_sprintf_void - flags += 1L << 26; + flags += 1L << 26; # endif # else # ifdef HAS_snprintf_void - flags += 1L << 26; + flags += 1L << 26; # endif # endif #endif @@ -117,9 +120,9 @@ uLong ZEXPORT zlibCompileFlags() # ifndef verbose # define verbose 0 # endif -int z_verbose = verbose; +int ZLIB_INTERNAL z_verbose = verbose; -void z_error (m) +void ZLIB_INTERNAL z_error (m) char *m; { fprintf(stderr, "%s\n", m); @@ -146,7 +149,7 @@ const char * ZEXPORT zError(err) #ifndef HAVE_MEMCPY -void zmemcpy(dest, source, len) +void ZLIB_INTERNAL zmemcpy(dest, source, len) Bytef* dest; const Bytef* source; uInt len; @@ -157,7 +160,7 @@ void zmemcpy(dest, source, len) } while (--len != 0); } -int zmemcmp(s1, s2, len) +int ZLIB_INTERNAL zmemcmp(s1, s2, len) const Bytef* s1; const Bytef* s2; uInt len; @@ -170,7 +173,7 @@ int zmemcmp(s1, s2, len) return 0; } -void zmemzero(dest, len) +void ZLIB_INTERNAL zmemzero(dest, len) Bytef* dest; uInt len; { @@ -181,6 +184,7 @@ void zmemzero(dest, len) } #endif +#ifndef Z_SOLO #ifdef SYS16BIT @@ -213,7 +217,7 @@ local ptr_table table[MAX_PTR]; * a protected system like OS/2. Use Microsoft C instead. */ -voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) { voidpf buf = opaque; /* just to make some compilers happy */ ulg bsize = (ulg)items*size; @@ -237,7 +241,7 @@ voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) return buf; } -void zcfree (voidpf opaque, voidpf ptr) +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) { int n; if (*(ush*)&ptr != 0) { /* object < 64K */ @@ -272,13 +276,13 @@ void zcfree (voidpf opaque, voidpf ptr) # define _hfree hfree #endif -voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) { if (opaque) opaque = 0; /* to make compiler happy */ return _halloc((long)items, size); } -void zcfree (voidpf opaque, voidpf ptr) +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) { if (opaque) opaque = 0; /* to make compiler happy */ _hfree(ptr); @@ -297,7 +301,7 @@ extern voidp calloc OF((uInt items, uInt size)); extern void free OF((voidpf ptr)); #endif -voidpf zcalloc (opaque, items, size) +voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) voidpf opaque; unsigned items; unsigned size; @@ -307,7 +311,7 @@ voidpf zcalloc (opaque, items, size) (voidpf)calloc(items, size); } -void zcfree (opaque, ptr) +void ZLIB_INTERNAL zcfree (opaque, ptr) voidpf opaque; voidpf ptr; { @@ -316,3 +320,5 @@ void zcfree (opaque, ptr) } #endif /* MY_ZCALLOC */ + +#endif /* !Z_SOLO */ diff --git a/3rdparty/zlib/zutil.h b/3rdparty/zlib/zutil.h index 025035dbe..4e3dcc6ae 100644 --- a/3rdparty/zlib/zutil.h +++ b/3rdparty/zlib/zutil.h @@ -1,5 +1,5 @@ /* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2010 Jean-loup Gailly. + * Copyright (C) 1995-2012 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -13,10 +13,15 @@ #ifndef ZUTIL_H #define ZUTIL_H -#define ZLIB_INTERNAL +#ifdef HAVE_HIDDEN +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + #include "zlib.h" -#ifdef STDC +#if defined(STDC) && !defined(Z_SOLO) # if !(defined(_WIN32_WCE) && defined(_MSC_VER)) # include # endif @@ -24,17 +29,8 @@ # include #endif -#if defined(UNDER_CE) && defined(NO_ERRNO_H) -# define zseterrno(ERR) SetLastError((DWORD)(ERR)) -# define zerrno() ((int)GetLastError()) -#else -# ifdef NO_ERRNO_H - extern int errno; -# else -# include -# endif -# define zseterrno(ERR) do { errno = (ERR); } while (0) -# define zerrno() errno +#ifdef Z_SOLO + typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ #endif #ifndef local @@ -86,16 +82,18 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #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 +# ifndef Z_SOLO +# 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 -# else /* MSC or DJGPP */ -# include # endif #endif @@ -115,18 +113,20 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #ifdef OS2 # define OS_CODE 0x06 -# ifdef M_I86 +# if defined(M_I86) && !defined(Z_SOLO) # 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() */ +# ifndef Z_SOLO +# 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 #endif @@ -161,16 +161,16 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ # endif #endif -#if defined(__BORLANDC__) +#if defined(__BORLANDC__) && !defined(MSDOS) #pragma warn -8004 #pragma warn -8008 #pragma warn -8066 #endif -#ifdef _LARGEFILE64_SOURCE -# define z_off64_t off64_t -#else -# define z_off64_t z_off_t +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_WIN32) && (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); #endif /* common defaults */ @@ -181,52 +181,11 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #ifndef F_OPEN # define F_OPEN(name, mode) fopen((name), (mode)) -#endif - -#ifdef _LARGEFILE64_SOURCE -# define F_OPEN64(name, mode) fopen64((name), (mode)) -#else -# define F_OPEN64(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) -# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) -# define vsnprintf _vsnprintf -# endif -# endif -# endif -# ifdef __SASC -# define NO_vsnprintf -# endif -#endif -#ifdef VMS -# define NO_vsnprintf -#endif - -#if defined(pyr) +#if defined(pyr) || defined(Z_SOLO) # define NO_MEMCPY #endif #if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) @@ -250,16 +209,16 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ # 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)); + void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); #endif /* Diagnostic functions */ #ifdef DEBUG # include - extern int z_verbose; - extern void z_error OF((char *m)); + extern int ZLIB_INTERNAL z_verbose; + extern void ZLIB_INTERNAL 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 ;} @@ -275,13 +234,19 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ # define Tracecv(c,x) #endif - -voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); -void zcfree OF((voidpf opaque, voidpf ptr)); +#ifndef Z_SOLO + voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, + unsigned size)); + void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); +#endif #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);} +/* Reverse the bytes in a 32-bit value */ +#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + #endif /* ZUTIL_H */ From ef6cc1d71558751a7c14a6efcac8d445ea152473 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Sun, 24 Feb 2013 18:58:52 +0000 Subject: [PATCH 24/81] Implemented VI Backing up for branch instructions on the VU Interpreter. Fixes Kingdom Hearts 2 and possibly others when running off the interpreters. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5574 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/VU.h | 4 ++ pcsx2/VU0microInterp.cpp | 4 ++ pcsx2/VU1microInterp.cpp | 4 ++ pcsx2/VUops.cpp | 150 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 155 insertions(+), 7 deletions(-) diff --git a/pcsx2/VU.h b/pcsx2/VU.h index af87cd16b..18377b0fc 100644 --- a/pcsx2/VU.h +++ b/pcsx2/VU.h @@ -154,6 +154,10 @@ struct __aligned16 VURegs { u32 ebit; + u8 VIBackupCycles; + u32 VIOldValue; + u32 VIRegNumber; + fmacPipe fmac[8]; fdivPipe fdiv; efuPipe efu; diff --git a/pcsx2/VU0microInterp.cpp b/pcsx2/VU0microInterp.cpp index c4aca7aa7..6d02cbaa2 100644 --- a/pcsx2/VU0microInterp.cpp +++ b/pcsx2/VU0microInterp.cpp @@ -144,6 +144,9 @@ static void _vu0Exec(VURegs* VU) _vuTestPipes(VU); + if(VU->VIBackupCycles > 0) + VU->VIBackupCycles--; + if (VU->branch > 0) { if (VU->branch-- == 1) { VU->VI[REG_TPC].UL = VU->branchpc; @@ -161,6 +164,7 @@ static void _vu0Exec(VURegs* VU) if( VU->ebit > 0 ) { if( VU->ebit-- == 1 ) { + VU->VIBackupCycles = 0; _vuFlushAll(VU); VU0.VI[REG_VPU_STAT].UL&= ~0x1; /* E flag */ vif0Regs.stat.VEW = false; diff --git a/pcsx2/VU1microInterp.cpp b/pcsx2/VU1microInterp.cpp index 85ce8ff55..3ddfec751 100644 --- a/pcsx2/VU1microInterp.cpp +++ b/pcsx2/VU1microInterp.cpp @@ -141,6 +141,9 @@ static void _vu1Exec(VURegs* VU) _vuTestPipes(VU); + if(VU->VIBackupCycles > 0) + VU->VIBackupCycles--; + if (VU->branch > 0) { if (VU->branch-- == 1) { VU->VI[REG_TPC].UL = VU->branchpc; @@ -158,6 +161,7 @@ static void _vu1Exec(VURegs* VU) if( VU->ebit > 0 ) { if( VU->ebit-- == 1 ) { + VU->VIBackupCycles = 0; _vuFlushAll(VU); VU0.VI[REG_VPU_STAT].UL &= ~0x100; vif1Regs.stat.VEW = false; diff --git a/pcsx2/VUops.cpp b/pcsx2/VUops.cpp index f61992731..b3601335a 100644 --- a/pcsx2/VUops.cpp +++ b/pcsx2/VUops.cpp @@ -43,6 +43,7 @@ #define _Imm11_ (s32)(VU->code & 0x400 ? 0xfffffc00 | (VU->code & 0x3ff) : VU->code & 0x3ff) #define _UImm11_ (s32)(VU->code & 0x7ff) +#define VI_BACKUP static __aligned16 VECTOR RDzero; @@ -1456,7 +1457,7 @@ static __fi void _vuCLIP(VURegs * VU) { if ( vuDouble(VU->VF[_Fs_].i.z) > +value ) VU->clipflag|= 0x10; if ( vuDouble(VU->VF[_Fs_].i.z) < -value ) VU->clipflag|= 0x20; VU->clipflag = VU->clipflag & 0xFFFFFF; - VU->VI[REG_CLIP_FLAG].UL = VU->clipflag; + //VU->VI[REG_CLIP_FLAG].UL = VU->clipflag; //Shouldn't need to do this, let the pipes sort it out. }/*last update 16/07/05 refraction - Needs checking */ @@ -1546,36 +1547,81 @@ static __fi void _vuIADDI(VURegs * VU) { s16 imm = ((VU->code >> 6) & 0x1f); imm = ((imm & 0x10 ? 0xfff0 : 0) | (imm & 0xf)); if(_It_ == 0) return; + +#ifdef VI_BACKUP + VU->VIBackupCycles = 2; + VU->VIRegNumber = _It_; + VU->VIOldValue = VU->VI[_It_].US[0]; +#endif + VU->VI[_It_].SS[0] = VU->VI[_Is_].SS[0] + imm; }//last checked 17/05/03 shadow NOTE: not quite sure about that static __fi void _vuIADDIU(VURegs * VU) { if(_It_ == 0) return; + +#ifdef VI_BACKUP + VU->VIBackupCycles = 2; + VU->VIRegNumber = _It_; + VU->VIOldValue = VU->VI[_It_].US[0]; +#endif + VU->VI[_It_].SS[0] = VU->VI[_Is_].SS[0] + (((VU->code >> 10) & 0x7800) | (VU->code & 0x7ff)); }//last checked 17/05/03 shadow static __fi void _vuIADD(VURegs * VU) { if(_Id_ == 0) return; + +#ifdef VI_BACKUP + VU->VIBackupCycles = 2; + VU->VIRegNumber = _It_; + VU->VIOldValue = VU->VI[_Id_].US[0]; +#endif + VU->VI[_Id_].SS[0] = VU->VI[_Is_].SS[0] + VU->VI[_It_].SS[0]; }//last checked 17/05/03 shadow static __fi void _vuIAND(VURegs * VU) { if(_Id_ == 0) return; + +#ifdef VI_BACKUP + VU->VIBackupCycles = 2; + VU->VIRegNumber = _It_; + VU->VIOldValue = VU->VI[_Id_].US[0]; +#endif + VU->VI[_Id_].US[0] = VU->VI[_Is_].US[0] & VU->VI[_It_].US[0]; }//last checked 17/05/03 shadow static __fi void _vuIOR(VURegs * VU) { if(_Id_ == 0) return; + +#ifdef VI_BACKUP + VU->VIBackupCycles = 2; + VU->VIRegNumber = _It_; + VU->VIOldValue = VU->VI[_Id_].US[0]; +#endif + VU->VI[_Id_].US[0] = VU->VI[_Is_].US[0] | VU->VI[_It_].US[0]; } static __fi void _vuISUB(VURegs * VU) { if(_Id_ == 0) return; +#ifdef VI_BACKUP + VU->VIBackupCycles = 2; + VU->VIRegNumber = _It_; + VU->VIOldValue = VU->VI[_Id_].US[0]; +#endif VU->VI[_Id_].SS[0] = VU->VI[_Is_].SS[0] - VU->VI[_It_].SS[0]; } static __fi void _vuISUBIU(VURegs * VU) { if(_It_ == 0) return; +#ifdef VI_BACKUP + VU->VIBackupCycles = 2; + VU->VIRegNumber = _It_; + VU->VIOldValue = VU->VI[_It_].US[0]; +#endif VU->VI[_It_].SS[0] = VU->VI[_Is_].SS[0] - (((VU->code >> 10) & 0x7800) | (VU->code & 0x7ff)); } @@ -1600,6 +1646,11 @@ static __fi void _vuMFIR(VURegs * VU) { // Big bug!!! mov from fs to ft not ft to fs. asadr static __fi void _vuMTIR(VURegs * VU) { if(_It_ == 0) return; +#ifdef VI_BACKUP + VU->VIBackupCycles = 2; + VU->VIRegNumber = _It_; + VU->VIOldValue = VU->VI[_It_].US[0]; +#endif VU->VI[_It_].US[0] = *(u16*)&VU->VF[_Fs_].F[_Fsf_]; } @@ -1703,6 +1754,13 @@ static __ri void _vuILW(VURegs * VU) { s16 imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff); u16 addr = ((imm + VU->VI[_Is_].SS[0]) * 16); u16* ptr = (u16*)GET_VU_MEM(VU, addr); + +#ifdef VI_BACKUP + VU->VIBackupCycles = 2; + VU->VIRegNumber = _It_; + VU->VIOldValue = VU->VI[_It_].US[0]; +#endif + if (_X) VU->VI[_It_].US[0] = ptr[0]; if (_Y) VU->VI[_It_].US[0] = ptr[2]; if (_Z) VU->VI[_It_].US[0] = ptr[4]; @@ -1724,6 +1782,13 @@ static __ri void _vuILWR(VURegs * VU) { u32 addr = (VU->VI[_Is_].US[0] * 16); u16* ptr = (u16*)GET_VU_MEM(VU, addr); + +#ifdef VI_BACKUP + VU->VIBackupCycles = 2; + VU->VIRegNumber = _It_; + VU->VIOldValue = VU->VI[_It_].US[0]; +#endif + if (_X) VU->VI[_It_].US[0] = ptr[0]; if (_Y) VU->VI[_It_].US[0] = ptr[2]; if (_Z) VU->VI[_It_].US[0] = ptr[4]; @@ -1888,42 +1953,113 @@ static __fi void _setBranch(VURegs * VU, u32 bpc) { } static __ri void _vuIBEQ(VURegs * VU) { - if (VU->VI[_It_].US[0] == VU->VI[_Is_].US[0]) { + s16 dest = VU->VI[_It_].US[0] ; + s16 src = VU->VI[_Is_].US[0]; +#ifdef VI_BACKUP + if(VU->VIBackupCycles > 0) + { + if(VU->VIRegNumber == _It_) + { + dest = VU->VIOldValue; + } + if(VU->VIRegNumber == _Is_) + { + src = VU->VIOldValue; + } + } +#endif + if (dest == src) { s32 bpc = _branchAddr(VU); _setBranch(VU, bpc); } } static __ri void _vuIBGEZ(VURegs * VU) { - if (VU->VI[_Is_].SS[0] >= 0) { + s16 src = VU->VI[_Is_].US[0]; +#ifdef VI_BACKUP + if(VU->VIBackupCycles > 0) + { + if(VU->VIRegNumber == _Is_) + { + src = VU->VIOldValue; + } + } +#endif + if (src >= 0) { s32 bpc = _branchAddr(VU); _setBranch(VU, bpc); } } static __ri void _vuIBGTZ(VURegs * VU) { - if (VU->VI[_Is_].SS[0] > 0) { + s16 src = VU->VI[_Is_].US[0]; +#ifdef VI_BACKUP + if(VU->VIBackupCycles > 0) + { + if(VU->VIRegNumber == _Is_) + { + src = VU->VIOldValue; + } + } +#endif + + if (src > 0) { s32 bpc = _branchAddr(VU); _setBranch(VU, bpc); } } static __ri void _vuIBLEZ(VURegs * VU) { - if (VU->VI[_Is_].SS[0] <= 0) { + s16 src = VU->VI[_Is_].US[0]; +#ifdef VI_BACKUP + if(VU->VIBackupCycles > 0) + { + if(VU->VIRegNumber == _Is_) + { + src = VU->VIOldValue; + } + } +#endif + if (src <= 0) { s32 bpc = _branchAddr(VU); _setBranch(VU, bpc); } } static __ri void _vuIBLTZ(VURegs * VU) { - if (VU->VI[_Is_].SS[0] < 0) { + s16 src = VU->VI[_Is_].US[0]; +#ifdef VI_BACKUP + if(VU->VIBackupCycles > 0) + { + if(VU->VIRegNumber == _Is_) + { + src = VU->VIOldValue; + } + } +#endif + if (src < 0) { s32 bpc = _branchAddr(VU); _setBranch(VU, bpc); } } static __ri void _vuIBNE(VURegs * VU) { - if (VU->VI[_It_].US[0] != VU->VI[_Is_].US[0]) { + s16 dest = VU->VI[_It_].US[0] ; + s16 src = VU->VI[_Is_].US[0]; +#ifdef VI_BACKUP + if(VU->VIBackupCycles > 0) + { + if(VU->VIRegNumber == _It_) + { + dest = VU->VIOldValue; + } + if(VU->VIRegNumber == _Is_) + { + src = VU->VIOldValue; + } + } +#endif + if (dest != src) { s32 bpc = _branchAddr(VU); _setBranch(VU, bpc); } From f984c7027f44eb32de9d428d462d59ca1d397758 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Sun, 24 Feb 2013 20:29:51 +0000 Subject: [PATCH 25/81] Decided after discussion amongst the team to let the BIOS bugs run wild. Altered microVU to just ignore these problems and end silently (The real VU would probably do this anyway) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5575 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/Memory.cpp | 14 ++++---------- pcsx2/x86/microVU_Compile.inl | 18 +++++++++++++----- pcsx2/x86/microVU_Tables.inl | 2 +- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/pcsx2/Memory.cpp b/pcsx2/Memory.cpp index 1b292b117..e188643f5 100644 --- a/pcsx2/Memory.cpp +++ b/pcsx2/Memory.cpp @@ -523,21 +523,15 @@ template static void __fc vuMicroWrite32(u32 addr, mem32_t data) { template static void __fc vuMicroWrite64(u32 addr, const mem64_t* data) { VURegs* vu = vunum ? &VU1 : &VU0; addr &= vunum ? 0x3fff: 0xfff; - u64 tempdata; - - if(cpuRegs.pc >= 0x80000000 && cpuRegs.pc < 0x82000000) - tempdata = (data[0] >> 32) | (data[0] << 32); //BIOS writes them in the wrong order apparently... - else - tempdata = data[0]; if (vunum && THREAD_VU1) { - vu1Thread.WriteMicroMem(addr, &tempdata, sizeof(u64)); + vu1Thread.WriteMicroMem(addr, (void*)data, sizeof(u64)); return; } - if (*(u64*)&vu->Micro[addr]!=tempdata) { + if (*(u64*)&vu->Micro[addr]!=data[0]) { ClearVuFunc(addr, 8); - *(u64*)&vu->Micro[addr] =tempdata; + *(u64*)&vu->Micro[addr] =data[0]; } } template static void __fc vuMicroWrite128(u32 addr, const mem128_t* data) { @@ -548,7 +542,7 @@ template static void __fc vuMicroWrite128(u32 addr, const mem128_t* d vu1Thread.WriteMicroMem(addr, (void*)data, sizeof(u128)); return; } - if ((u128&)vu->Micro[addr]!=*data) { //Hmm, is that right? + if ((u128&)vu->Micro[addr]!=*data) { ClearVuFunc(addr, 16); CopyQWC(&vu->Micro[addr],data); } diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index 5faf910fb..fbafa479c 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -19,8 +19,8 @@ // Messages Called at Execution Time... //------------------------------------------------------------------ -static void __fc mVUbadOp0 (u32 prog, u32 pc) { Console.Error("microVU0 Warning: Exiting... Block started with illegal opcode. [%04x] [%03d]", pc, prog); } -static void __fc mVUbadOp1 (u32 prog, u32 pc) { Console.Error("microVU1 Warning: Exiting... Block started with illegal opcode. [%04x] [%03d]", pc, prog); } +static void __fc mVUbadOp0 (u32 prog, u32 pc) { Console.Error("microVU0 Warning: Exiting... Block contains an illegal opcode. [%04x] [%03d]", pc, prog); } +static void __fc mVUbadOp1 (u32 prog, u32 pc) { Console.Error("microVU1 Warning: Exiting... Block contains an illegal opcode. [%04x] [%03d]", pc, prog); } static void __fc mVUwarning0(u32 prog, u32 pc) { Console.Error("microVU0 Warning: Exiting from Possible Infinite Loop [%04x] [%03d]", pc, prog); } static void __fc mVUwarning1(u32 prog, u32 pc) { Console.Error("microVU1 Warning: Exiting from Possible Infinite Loop [%04x] [%03d]", pc, prog); } static void __fc mVUprintPC1(u32 pc) { Console.WriteLn("Block Start PC = 0x%04x", pc); } @@ -160,15 +160,22 @@ void mVUexecuteInstruction(mV) { // If 1st op in block is a bad opcode, then don't compile rest of block (Dawn of Mana Level 2) __fi void mVUcheckBadOp(mV) { - if (mVUinfo.isBadOp && mVUcount == 0) { + if (mVUinfo.isBadOp) { mVUinfo.isEOB = true; - Console.Warning("microVU Warning: First Instruction of block contains illegal opcode..."); + + // The BIOS writes upper and lower NOPs in reversed slots (bug) + //So to prevent spamming we ignore these, however its possible the real VU will bomb out if + //this happens, so we will bomb out without warning. + if(mVU.code != 0x8000033c) + DevCon.Warning("microVU Warning: First Instruction of block contains illegal opcode..."); + else + mVUinfo.isBadOp = false; //End quietly } } // Prints msg when exiting block early if 1st op was a bad opcode (Dawn of Mana Level 2) __fi void handleBadOp(mV, int count) { - if (mVUinfo.isBadOp && count == 0) { + if (mVUinfo.isBadOp) { mVUbackupRegs(mVU, true); xMOV(gprT2, mVU.prog.cur->idx); xMOV(gprT3, xPC); @@ -504,6 +511,7 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) { if (branch >= 2) { mVUinfo.isEOB = 1; if (branch == 3) { mVUinfo.isBdelay = 1; } branchWarning(mVU); break; } elif (branch == 1) { branch = 2; } if (mVUbranch) { mVUsetFlagInfo(mVU); eBitWarning(mVU); branch = 3; mVUbranch = 0; } + if (mVUinfo.isEOB) break; incPC(1); } diff --git a/pcsx2/x86/microVU_Tables.inl b/pcsx2/x86/microVU_Tables.inl index 983af8332..fdca6d772 100644 --- a/pcsx2/x86/microVU_Tables.inl +++ b/pcsx2/x86/microVU_Tables.inl @@ -212,7 +212,7 @@ mVUop(mVUopU) { mVU_UPPER_OPCODE [ (mVU.code & 0x3f) ](mX); } // Gets Upper mVUop(mVUopL) { mVULOWER_OPCODE [ (mVU.code >> 25) ](mX); } // Gets Lower Opcode mVUop(mVUunknown) { pass1 { mVUinfo.isBadOp = true; } - pass2 { Console.Error("microVU%d: Unknown Micro VU opcode called (%x) [%04x]\n", getIndex, mVU.code, xPC); } + pass2 { if(mVU.code != 0x8000033c) Console.Error("microVU%d: Unknown Micro VU opcode called (%x) [%04x]\n", getIndex, mVU.code, xPC); } pass3 { mVUlog("Unknown", mVU.code); } } From a467075ae0ea43029f2eaabbecd4f6ec291bc7f8 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Sun, 24 Feb 2013 20:34:50 +0000 Subject: [PATCH 26/81] Missed a log. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5576 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/x86/microVU_Compile.inl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index fbafa479c..383b991b6 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -167,7 +167,7 @@ __fi void mVUcheckBadOp(mV) { //So to prevent spamming we ignore these, however its possible the real VU will bomb out if //this happens, so we will bomb out without warning. if(mVU.code != 0x8000033c) - DevCon.Warning("microVU Warning: First Instruction of block contains illegal opcode..."); + DevCon.Warning("microVU Warning: Block contains an illegal opcode..."); else mVUinfo.isBadOp = false; //End quietly } From d438ac3d0c92f672cc11b72b2e5ed2ac59f64212 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Thu, 28 Feb 2013 18:19:56 +0000 Subject: [PATCH 27/81] cmake: remove useless line that failed to build on older cmake version git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5577 96395faa-99c1-11dd-bbfe-3dabce05a288 --- cmake/FindAio.cmake | 2 -- 1 file changed, 2 deletions(-) diff --git a/cmake/FindAio.cmake b/cmake/FindAio.cmake index 9aad0020a..c3e8f6993 100644 --- a/cmake/FindAio.cmake +++ b/cmake/FindAio.cmake @@ -9,8 +9,6 @@ if(AIO_INCLUDE_DIR AND AIO_LIBRARIES) set(AIO_FIND_QUIETLY TRUE) endif(AIO_INCLUDE_DIR AND AIO_LIBRARIES) -INCLUDE(CheckCXXSymbolExists) - # include dir find_path(AIO_INCLUDE_DIR libaio.h) From 2157fb49071c05fc180507f7d70a3047a467b866 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Thu, 28 Feb 2013 18:24:27 +0000 Subject: [PATCH 28/81] zzogl-pg: use the red channel instead of the alpha channel for the block data. Alpha channel isn't supported (normally) in OGL3 and later. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5578 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/zzogl-pg/opengl/ZZoglCreate.cpp | 6 ++++-- plugins/zzogl-pg/opengl/ps2hw.dat | Bin 113923 -> 112769 bytes plugins/zzogl-pg/opengl/ps2hw.fx | 12 ++++++------ plugins/zzogl-pg/opengl/ps2hw.glsl | 12 ++++++------ plugins/zzogl-pg/opengl/ps2hw_gl4.glsl | 12 ++++++------ 5 files changed, 22 insertions(+), 20 deletions(-) diff --git a/plugins/zzogl-pg/opengl/ZZoglCreate.cpp b/plugins/zzogl-pg/opengl/ZZoglCreate.cpp index caa46e8f1..b481b0e77 100644 --- a/plugins/zzogl-pg/opengl/ZZoglCreate.cpp +++ b/plugins/zzogl-pg/opengl/ZZoglCreate.cpp @@ -417,7 +417,7 @@ void LoadglFunctions() 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); + glTexImage2D(GL_TEXTURE_2D, 0, g_internalFloatFmt, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, GL_RED, GL_FLOAT, vBlockData); return (glGetError() == GL_NO_ERROR); } @@ -611,8 +611,10 @@ bool ZZCreate(int _width, int _height) // 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. + + // Note: GL_ALPHA was dropped in GL3.0 in favor of GL_RED ... Time to upgrade -- gregory - glTexImage2D(GL_TEXTURE_2D, 0, g_internalFloatFmt, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, GL_ALPHA, GL_UNSIGNED_SHORT, &vBlockData[0]); + glTexImage2D(GL_TEXTURE_2D, 0, g_internalFloatFmt, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, GL_RED, GL_UNSIGNED_SHORT, &vBlockData[0]); if( glGetError() != GL_NO_ERROR ) { ZZLog::Error_Log("ZZogl ERROR: could not fill blocks"); return false; diff --git a/plugins/zzogl-pg/opengl/ps2hw.dat b/plugins/zzogl-pg/opengl/ps2hw.dat index 2d3b43cae0cdc3de4925148f558b574b9dd1d7ea..47e82b7c5a347db92b8d3716e3e8809c7e436850 100644 GIT binary patch literal 112769 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 ` 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 bfo43Tr9Q>IF^RKfG{i3d7y0^Yx%K}5_TOe% literal 113923 zcmZU4XIv9s&^3aHf>M+w9Z~6BK%@kz3euw>ErQZSKty_p1qA7e^b$HDQl+<`(rZ8r zz5J>a8k(cFb2Nf=W;B7>+w%<1Y|+gO z|B~BPo<`hM37Jl)RIgpRYvS~Es?tYTOXuR#^FJP3Zs=af`Y|9N-RhiTo~On1?dg;J zZFB$Y&S_`^@its&i>+1ai~fmrE9#L0q{BL3)3D`hIC12JNw}*W!5YhOaqK%32&_3z!hXfCE9dC3EoNwN0UhKlsA3 z++Z7qv9yHyU$z|n+y|R!e8TE@ZwMXchs75YQ$PW%pweJIG(F0nm0|SPqY~l=s6Q*q zxPOURJHD0KNxDKU1 zV@da7&~Kp_Gjc6v<4b|_`T!BeuP2Y*hifjiCOBP^2EnkUA%0i);WDKyiGLpIZk(4X zAa?yRS+=~F+YMF$`&}&^lb2${kG#FgVrG9Uk^0VLSz~6s5)26o6y4)P8?8MLa}nJW z_N-0ChE?s}L>BLy#$o4i+c(4Yw*FWegr2&I?%hSVnvnPaaGxDo4ZH>NRb95JhAy4VODk26V zsUH#_vrT4M7*sFmK#I zB0;t+eD}C=S?j{UFZvFfmUNRVwu87RK3roOEfDR2m08?IgLbm0o%#7L z-n!i@c%13mYvheUuWuMC!K*-}BIFu+1%$hO+bm2G{g}Ts7CP$hRT{iJy1Q&aBniU9 zU%w2f5%t_>4zkZ2x6jrlkwXNye zgNve7$yRT-5M^sDf{kp1-zDbJFyq*A>#e$p#_2Yt!DGL@7 z=U^?d&)wCa#lagt1wwNL(+9l_X&`g;OLL;^P*)k_J2O2_AT*&hr7a`#)2qn zXq4BMaAm=cy6BPLE0#Sbo1>tUBj1qdT6p+<0hE$PS5VzV{R|lp+ID%|`D5zkp5gd!u-7b29X$seA;sv23@o zsdPgZ1v@GeXhMiWL_v8(Qw9RN#|F1%k&S9YY12Dw;;QfFT<)p$X)G27nY27jz$TVa zHgj{Ag=W^dz}_JZrNG!~H<~?>MZ4}U7-gGmQG}{ENJm$pB}6E=V`9!|PG^hqfDlxA zbQNVuzJ_KvElIl@-!PuBpxe=2m}aeyDP=-45QHcffm3$y$l#=>t*P;DT0%Yujj7xi#u?DT7xv#R zEX&pnzXvDYEocmk$KJ(-Wse)E8$(g0#3&C^^fk9Eda$6c zsi0=#cv}cv>!cm7^*Y@~dpsd)HrZU`v%-LCaTcrS}m>N1o@dAt8M6fTMBDKh;8`$rfa8 zuq9I%+&LP)tcysqBu^KGF9+0l)rZ=-9A4wHFcySFw6wvRvKuUA6QO<}bFHH-4467K zYO1a`JC}nMHQ5lo_XiIw)n9sY*E5@NdNgis)byYv*tD5UB7N?DOP-FxE~k+`x4O?i z#@CSGu&Lw(M+hP@IrKP-LME8nX&LFv4HphQHs;h%GM!i#9%u{qkdY#H8Zi!y;p!o z^oi2g2xdz3=5FmyLwDyh}GB-HXJwFY*iNn}P&MgQ>|2L_gw~rfr>@8$yEk)-cGShI^q?~jw~ddE#82A7{6+UPJonvC z(vgkVKoihpQUMEy$?e1yPO-xMa=L&%NYRSpRkOY`O2FtLP%u^NP^~SbE`e>3A@xMI^lJ$vqw=T|V8}lXPsa zwoVtj&CxYPhm_!N%&8^9!=LxY#Apkw-(!;~?8J+PS!yUN=sqf0ImyJ@LsfM{Zvg2` zruof9sLOFG)`}{p+or7)Mt`+YLph>qiJDK`fL><9S&*T4!ZA*G`Fb$r^nsr_DnB&m z^dVB;|GI=W-FawDs0I{nE!yF2VXx^8zx(bG{RO+V^(jUlp=Pe(Pd1~>&E{akSokG! zOLh+OTK}bd&46yb-12Om?{#O)&Kz-mKS z#fGc_*FV!%6jN{pQwlcbO6Q5%n{+HL>r<@h>X9*G5#-!-{B=UQfLJ{EDHfRO5@Mun zRIIPNnqt|)@zm@5(M4DDFuX@+_h8-bD})vFp4~zI&bZannzhm;C!zVHX0V`=n=6Iy zZX$M2bVtgeU`MKmn53!}8@q{10kgnoGeC+`1;INlIo%JzvL(dilAP|Py3?!8i;Di7 zt}LmrUz@d)DQdAIo2Ot){^kHzq{)OCIjdtwYN2SQEQJ&n;#zZ!ABBQz9(~X0em%n# zR?n&8&ntY}qMa9wisu&AEcUF-BZm7$+|6#N6-E0>82k%ZZHF%)doTLDJ4K4al6eiH zE9!P-;SRxF7k#*a+By7So6Sim%w#GNYgNfBEK|5sp5L;!z~&TSlZNbxEzK1WHYpC~ zM@udU2#*x`OY^cGMKXYmTI}3lPX3o*uM4#~5;_UYX^TA;%z^2w?(f9dAK#l6OT;ADcNyOMbQ=MK zzT)y}I7L1r5GVcFFyqQ1U@C6kzUwhqPy*$O`Le7vvu+MP5|IB&#<(E@26_7_zL(L8 zE{QLws;O9_v&b|wp^*43O#cU!&yF*g8<#6u;n20%QmRgvVA21 zK-WIf@zjGu7{o$jyB@HCw7a!~YZi;Vns0_b4U{Ai8Uoohmo_@lLhARO!<4I<_7vP@)7W6q13y+70 z3ig&7>|u5m2QX8%g;UUQQP?ab!HL?Oi(T~N9;WzyRL7{ruj7`4dzFlAr#okM3;@c}3d6d9_Y$QTjCR_>Xd5!&9S2H3s`gHW|k_RCBN z$nL#VGREkHPv8s}@u4RCgED&@=&IrCgH?M}GqT^j^&yN}7)@;e-}eFVg4sOz zx6d|62mZwSdM`!s8@5z{uUAI?k<9+@yZ)b-z$)#a1hT6uA|woyVDEGuU3zpKMJY7X z2%if)gvolR`9`+yt-UJSwlcmjsJ=?Cx)!n@svmV}~3 z2qK}hBvX1cL{sHG+4T|{7k2kOxikiQg_`pd6J&*`+R*rd+P6S3BxLqcYU8li(4Rwd z(*{?{vim5O288tX+j!UJ`BkK{@e68M8WiMogM>n@?VY{>a2G7we1-yGXlSo4aQB+E zZ}fjYMRt6}`gsHXK=C;ZF<$j;HLRTVyGlYK!B+9W_yhfB(WDM#1 zoJZpX6#)AI0;lP$KtlQ8PfvptvO4#`urSh#L)bMqa$~H28zgE$p8F2OGr`_mOcSl8 zWfkrj#SkwES<_D01X5>^8r6# zgV3p1T1~YRgA7^$dUG^(BmmHxt&t0YS-&a1m(Z~g7=UH!pJYn_KjA7C`%+-`CD+J2 znki(A1VT1P8Ninas=TWN38e&1tjHRm_*R5gRKNhFLmTiZr*x>zJs|w3E%`y6(U>kG*K7`rAcaIkURD&bQQDvbyZOK?9xwM8lr&q7w&qG290)?g< z4~R3sGHmv%`!?vvY(8Y|&LNCcHZm(8PsW@>P($YcyTgop(mXx|6(}NNtW2L%gQBr2 zyV*U99s(u7N4-Embs317_ai{iM#>=5dno%wp*ykahpsBOB0zUTNUs6)xUPzOMkd_(F0Mg@Jut_b!4 zXsPLsI&;$_(BswtG$wRa?N6Ow$R`$8o@|3~7V~%2VPuR>P&gxg8mjrVYVQP~sb41} zW`= z0ZheW7KZ^e+1;82#tW`0tDltdkJwI%_0QX*$=EH}nY$hVvUrB31QrNa zHT7~{uu0?QHi)iFK=su<5=scsX<1TB-PR?Xt1aC>%KQa}Jyy&Ca#qkQkJ4IdTpqDk z=SR6xav#TscEa@^Tn}J(e1jNFeMr`0l^4w}(J!CrDY`Jhe70 zXvy=ACc7%2sRF!C)C`~_S1f!8qeWDeU#bCeR?AViu>WUPwA#+a8Y4KEy4}P|GEK+Y zj1nn$ALKd4|c@|)rTN^KHWMMe6}Bw# zq>x=z(a=^~XKGn$;-;kpXhP`?#Jg-8R1Zd-K5?d=Tt}+~M@~ciONk$S91md{@bH$K zLoziVu*6%A{+~5~R*qFV*;N(+n&)##o65qrCNcvvCMkHd-?bV9XV1ATini)esku5OoMpR}KIr6H7~?K}Wf| z1l%NN%~_^mi`NUyHO+6???1z0A~H5+3aGw_eOWQb>M#?+j}CUg&zLYQ3yja!AvjYd zfVgSc0YSho9O&mEyU(hxeZ_`!GA0z!AtnQqHWAqURL=c?PNTK`&_$<1*dSb>wGhzX zAhJxwT&O2XXcmaw5M`eiA-Z4zWZw8t0ZM&(Rr2J3$L}p5-eiC8ZY?lwaljXEDG%f& zczA%>B@&8&KLM3RkTFMKm|7`-oCs8z^b)SG(V~4T{MI(8(cJ!z8IT~=(8(qej?@!6 z^feiAAc1CKK?@cD&w{Q}2Lo6YYTscE6hNW~>Zv0T7giR&9(9$%7bu8^9mzVMQmyssnqKOzhpi{q0Qf*y<+$4w&P`~q$j0r)cbtnMXfe#J8_mOO%yn9-(|Hxdt z0|azqe<_|QzA#0wWGPsdmv$T#5_2*XyTztqBD`TQU1A#DNu6ckA%sUh72A#Z#G;Z6 zCq-#c0@m9kS3G8w#Dun#$r2a%w%7rutgdIAUYC00x2B`m9ddAF(L5BZ*nR6qMNiZ&?>y`YY@bF!6(o2_EmuZw1AJ-Ln}QO=@|}T`_Y`8H8Qe)Y%l4h$s>`zY zBYH%q$`D&U{zSZS|0my`7@5p_!mR;{S~LJk>%7GEXqGjMJmTooG2yNmMROsxl8tUX zMyZZ005;9MYZYodi!&lbH~SW9n);z&!_HOQ`h>DAOpHWJhe%mCGDrpz)oa0jvSt^K zOV=fYSPgLqjxFxP!?Bgkr@3&8uq{j9ZvT@IdGyL6Op^I4(wI<1@vc1noC-4~G?Ujq zE3RP}nupSZoDioPX;|!X&@v}6}0>I27hFUpazrG$I^BuT@VoBxVlfysm3>~2vyVcQ5vokym+vnz9&y6 z%OPY>JAzI%j@%HE#38OL_#;CEjt>O8atKC%q%%;9Rj49jZSj7$`erd0gHwdGY0m;> zSf$!}Y}h6)&9a?xd~$ZJ2%&rJ?!X``9mT&i!kEq8=o(yVaA#zzJn)96e+X;IwjTz zf24q@QqRl2@=pn2dao_JW3gS&Z(4P&Z4qh_c7k48mOlyMMDy;-aEU$yvdzBe;E6AO z5)7sKH*eg8dKVC(i{D~>*Ko#Q7~1vyaq&UT!U4bGQ=y)|#YDJ_tiw;zjt-&g7E{-a zlMq&P))Sd$Mts0C$CK&UcU=ZdJvydecAKGa1HD?e_uOL8s(fOcEmt+cxRAIU#T7lc z23)tOP|x?=H`=4IGbqkz{gV(zbfQ0kwfNvD2u!_Oq&+7M70f4AwlO08ADf411x3P> zIs(kXR&qIPnfW z+k$qu7x2dE$2=#VKurTLw)hJ}sHkFMMoDBSxg!Z{Yhn+04#FLLy0wuM$U{PBqx9+) z)ek=y5iCE#r$3P?zL{(7H*D5N^ zoZJaIi@<^IM8bhnL09+l_irF6)I{vC4%Z%`nq%Aa`|MYS)} ztO*8`qXMESX?I|fN&!<({#VsUQDn5MDyq(}}bV7vEpo?+RYg^PO z2pq{DaNvc9w@oS_DJquazZ=fLI(@*RiwBR1P$@J7EWNTteF$c;u8%tkxrbg9sEezj zx>{BuA%WL9z6 z7QogrO%PNSSg%6j=E)#%2e6_=caYgt_R!+s_4jAQ9dwjnYjzbCWgdnKIwKU&r3=*n z0Te_Ba&BKThJT;=yi!kgFlSg0{T^R-Ofnq}9dHXFChFIF_F#)4&AR;lFN_Qi$ zp7Bbjz>9E#q$v8I_rvG#@PpqxWAPNtRBS2KN@QTo`w{r4we-`xsj^05;E&tECh+k6 z`i&aDq85B|=7wrMaaHi;adzMB^_{Sn-M_#AdBl%j>YcvUbZS&wCX*J^dt8e<7G)>pHfc!Y9 z>Z=iUWm7F-vlBbtc{ga*j8jFV&5S}4YH=CVc1IF+cwik3ydLA<+Hm7lt~6IJpQ#C* zU$1y;rkFw;-~d%sB3Pb!IhaP-Al+vv-#g!i=uI^gv{kr}iTqnUtDbuDjnZ>XK~ZhR zH`i0?vl=Q@%@)8e9c51A*x^};ES^9mbTD7tAAwmbZ(F3_&OPL?&rQFrC*D7{&Er+m z`L8f3S0wCO`th0WV6SWqwdSWb&xauQg?oc-1Iniq56icwJV}{)yp81xFLKR#X+v=V z=_*|JycWb@I^P@BxM~+m`8jMG`3h3+ypq1$*z~}$$??0*)qpSbyu3UryVh0??XM%7 zANjO7AKpo;fpzgew&j`dELCh9u`BrNBR3fCAc*@`UN!S3dTohG&C9;dPp5mr_+Til zaT+xde6NW!+wj!|uE0|JXlKjhOC9a`Ys#qmshvbKMgf2`k1-SaXjV@fg0RZC65`f0MCJKFX?@YoA4X!zSbFJ!S0qio8{wkGr{t`h5f znt5zZi(bTZjjji+)j@%Oqy^FzsQlDo4_{h&dc48nRAAXMXR5*imM^V->Q=l;$Hx1HYB-sk#3dWwQMb>p z&~n20q`JdhpG($b>F4m#*v1dVW!di?_4p5wdzGCH0kazgFAJiE@fWu3J}M(!wo>`8 z99Ye)@HI!)Z%tIChK!;}e8H2Jn;_v?<5WchCU*95=tk^d+_H8`uCXx1YALSThEGDW zw!$_0r>bE%Jnx160klbG`A6J@bXI;!Bz?Y9efixx&+WtEQ{ir*E*Lj8#*|Tq$3f}z zhus@RFMDNKWY=9ZQ^w*WT)w5U4-WqW#f4~7#iYk2cd8Q9UgR!sWb`HGGE-PQ8+4^* zuup9rtdMrO#A@}ys6SN1z*3M#$iXO5nq!nBlu*)+{y=;3AD`xT*RVCbO|eW77s4UJ zl~DdYsgeE8n)p^@)k1X!aDo#|nnw2;Y4>yQ zY>8^yO0?XvQHCtQ$xq`e?S3-w6c|7GM^{*t?JDK?O23t(eBeH&rj3+2C{%sV0(7}DU43yMz1uyDAhR(puH|BIKgv68BA28nR-uk+{ z%#`uvTly6pi_@Fpm6F>3BS8!ehr~zT6?LicN*gk+7D=z&WKX%KmL9>#xT^Ro>)F@; zY}Ih%$1>_VR0{9o^WPcnT-cY?48uP><^V}9;wN9-YdQzn-%}F&|NhJpJ;I0fFG2Rn zM@oxp>VeIUw2=MwLnVl&>RiWqS}@52Ntstaj78Qn z5}3p~k$HnwoG$WVzg7be&8phnw>0-?_}?*WF|<|Cc`9eq0+w4n^Atp4^xU0us}anB z`Im%TeqG*r7j~DvEw5sh7W`aGPk`SlTb?8T)%5$r`Nf3=@9j!+-mjytPHz>Ei~FbY zomnFr`srKu(m%R9FN$ce+VMs-Ja~)Vm?#jDli~$S^ZwNro$~)CNS5(lj%;oWECgx4 z;%Sh-HYU%i7n)YjdwEOFOOC-{RguqaklRD|5r55YC--r_H)0IQG6?e&QNGb)J{9Gh z4h`T>{n9*=P+eHt>2oys&p+_L2em=Z57?GOu5jJa6O52cyyl~>J@aWkv0Cis3$S%I z-*soB_|@LuKgjv|W+HI5zZYMgSNgznKYpgBw2SP=`C3Wa^z$-Q39oJX(Dpl99GpK+ ztfchjmdp!9uAQvbbv5R;B|7s$$hfpqk-lTs4ShuCOK>Z9nY{H2dr7S9m@Gk=(h#R(MyIEd)$nERG5u*=+my>?OiLO##qoAVDAROV8; za=l%@c^b0nC}ko4Sn}IN!}GU3TwSZY8svp|l2#aX)e$lAPK+%$mYphT9@DNTUpmZU z7*S?ZJO1=9wxPhy9L}W|Z2pSz0ekr6*w3rj=@n-1x9 zABKwzYT~zIDvt8>7QQO}m|6eiC+Ja}33n>rN{^h-wsItoX7Y-pev-I$nKAQ*F8sBJ|#n@gfjPv2QTj6ba`W?L^{9~(xt!TU8Q9$;L^*Q71E$c$)Lzt+t+M(>`@uU6j`I*H7Hh|Y#j)Jm_6ozF z{R%x+c}?T0-v>@?`tZ-Duy~paz|tQS{<3=#xXQbxv)MFuL(ir&$9E`)C(OqBNwHEE zzHV}tamA!(!2Y1CRXv?~PVz6#ck1v_-2#VanqF#ri&Oq*Uum4ei@O!hY27_VokU1y z4}_^Ou_bJ++S55+D82(BeK#-kYgvnX!vwufh5!A>puczQs;5+UtGk$znLUK8Ys#}7 zME_|83aPUSTx5x0=pks4@EbfI8Gh3(z4uC!3VdekAKxt%y>VMGBrmNXE7j_;+J&&E zNQ0{A=1WT^7X$ESR1W(J4gTHpFVEG#v(b{y*)30tzt1@_e|D?-s`aJv^G{+uMj^5Zp9wx@<{$Q@(Mk$KB$!StGQVY5j_EVF-#Sp7W$dYI@L>oQE*zMX zP(UP^N5&xz2jFj9CPTyv5tVOz9vc%RUQBj!I>uJ(P2G4U-`T)j8&n4uukMbUaw_0# z)NR;6YQAD?*kG`Iz3VxLcrG>REcng3ONi{nlY2Ud-#;tpd7DeGLO zeyKIPt;j@4btsuLXw*eAv)J4iE!;UXJGp8-{z^11!@ed~zhkhYX(|R@gmoF}j_jG28!2h@18D#S7=@KAijY?wOXH5cg0d z{fGVoJL_q$JG8$7GX2q|0Z%b-D zDNAV3_(|tpsJMz-uKB5~ii2D3{ksl%Ql(*?dw(N*vuz(lMcy~fS9~Vy`A7cKExpV9 z?g@8>e+=`kT)6q@-umVBJr{`8e1A`R!0iI}czZkWzFTI6NE|-iH-A{!t35Ws+@gDA zPm7IY@BXG4eT%lG&40?pJR&TK@By-{fKF=Vf86dEb@nT;zq|a@nzbfzBD`&G``5nQe`VvPJ4+9pP}I7SSXn3)m|dcgN%DCuLln7 z6rPapl#DVLkBwQSOX%VIFV32Ns=e~(m6&fq-nEzI>27uIk%jG%h<=MP*RMXPPM;8_ zdJUBxe#e*dwPUy4x2?8R|L!Vd2=#xzW!SYADzk*vWehDhF9kBJY%3V!E`7<9|LbEZ zm2`VQI?_o{KI(zK>C34f#$CyowtDK~%MaO1XH52roJY1VuyiN?ZgHHi_Oezf=bgwA z-b(P{d|M__y&Gp8P(Zl$w2?#vw17_)YKK4B3>ddYZ1~&@9M^dUYU9!cMFHg%WyA$@c9K0OkKA+Ye~gIGTdC- zs*dhaZbPp+4SBAmu4%s#0e&13{7MAKWHih)4DbFgncbxsk9be_C-=70>=o|+XsUeP zg}!O>)pGxNmxk@bb@m7+i0(ygw!DjG=f!B*fBDAzH`(8lfARj4h;sc4L<_c2aNaS5 zt!)(iuJ5N-vo=ZpLPNW}(45Tl>(<-PGk0mXnk_3Hew+y7rZdT2@~_DVX!vp?wYj>Y z^ZrnW$jnG$9oQN>ol(O-=0AFCEx-qUGWXN+j204p>=(=A8|dwI$OPpZ(3|_8 zt1fDY`{5x9dSl{c?_#2x<297&b#K$TBI8=jYF0zhOvwko3q7g@li=288_7i_tkoqw zChQdq<&oK=FHES8ySlxKT@}J!!~5_er-7$#SMOZPJZ~IBl2(Cdt~QIivQ>Q&cm4SN z;l^W&)2fH!hZ4dLS6U(h>+6=$2MsCb_g*%5_88wW>T~mQbd_ez3YYTw_?y+s*^6W8 z$;C$PrpIcLwj64|#^{!w94tLXHQHEPJ+*!6z~UEiPn$nK;l7oDjU##D$_U5b4MxNu z3=9WT*ltd4CRWW(iIYJeh?2+DEc9N+eKR;6_fGDsNecx%O8{TA1Y_+CI=T( zdNGj;eNq9M%ZKWZtuk4%Y65Lnot>F{cnw*wn(z!mG z7c>eq*VQ8~dur%hP0Hs_`o*Mp^W62&xXTU?_O!*UwCry5zp5%%25nq|R9~7p|B6=m zT-L=T<3N`~mosbnncKTQ=d6Fg_oqL8(H3(!3|`RrYb9BTyfGs+7L;1d=b`6xbZyL_ zdujzKHL)Ua>^uZ=g3;N)#%>0)MxPEmZ8CKHijkU0$q>BI`oaEJG}U)dA~j_^mYL^Le1yKXNdA}6z9ILbu%Nd?_s@(6jYgbzen_jWTcm$xtZ~kr zd?4GMDqV$WIC3aU_1=?o^3txp{$cpTWQe|%i{SaJbHOwk?*z11@@_Y%7atN(R*W!gmZqqdfC9;?|! zvGeS-jQMBB4(1mhjTRk4gxloqUt|B>%eWNzU#+smMcu+678%1+_V^2JG!8Vf@3?-( z{`@b})g|o$U?s(U;*7EDVUn#g6S^*Kmc3N}qVAhJ-L!k3i7zhkzJF$#^Y`kZm1`Di zwd3z>e@g$y`I@PTevZ~l{HL_3|GLnnMy>N!{h(GpQa;T zX)6n7B@L(J-X{(FCl99&7iyTkf90a9e69ZI)>q>r0-zd$`dk>VxeAvK@Bf(2RrSQT zHf-G>3K=WsZsd*Jw$D27S8eYYQof-$b59RPq>mp?6|c+OJ~np}M8E?kGb9a$+~hso zN}Au)H2+YuYIyOr=Re~x*ZdTHM{ly?UG&D+SPSp28P>F_#TzU$uR3e*Y?j?Cv?lRn z@p&lE8WdvZ@@;5mc!t^1$My;bWq6{-UKv-jc)xd}&Ixn3JbFh?DrpS~X$&HWG|=fC-u|KTrF~OG zSBg1Az3OL1`z3=2k>6}f(XVyy-r!?P*w~@e>N0abFwmuDEJFG~&p{44swWPNn=$W@=0A*XRCo%pRd z)t(_f3&jzk{(qLUZ|y#D`y7|?$P(|o$bZ#fA$xPPf+d$3x6}!p9)vV_RMp^WGCOudGw$qa`cir_n3R8ooA8u^(MK->ugNj znoi6t@wtDiowK6Xlp15K9lG#0QYRrbZO$WqSyA11?HS>nB>x9$Mf`tqrQH+F1>SB* zBpt>*2m$Jjhpi+cpoM%Y)&S~`P9}Gh&1LU``xKr_w)!VC-J?FqUshl0R^E0q)zy`{ z;Y6PB%vg;}oQ{uf~8HgQ&FwtKMn3LJF1KB zQ4gkG)tc~JLr)U}S*>QS>W;RSgO&~7v;DmI?7SQ;_qjM4eHxK>Y}36LAF-4k3yN4| z3&_k4i~hV=~pT}STw%5mlT z&cr`*qh|TXi*jwFX7AxcT4nkqedmVu*FqC)H3_@(3ekQC3a>dv{vEe%Cs-SBbHy?B z(60c+Qqwa#IhjPlW)bhohS7>PEMXbCg4c#IJMqy8*?3-GnKFr4%eHAB%D$j6AAR3G z_0Qn-JEGtERU(b*jdiy#8@=sfM)-rqN;iy!?abnHO6*v;E>G9=^T@jG>WZrCUb*p7 zuJM6UcSLWslr^UmQ!4$S;ftraS^v1lKBWJ<+msp^F5OK{O>yerETDI^jplqLX=CO+ z{g74KZPsP(PDeyEhVx*u0Jqt@tSrUy%WM4!+xDktD(72IB&RB-`g1OQoPYUp>-$Rt z2k{6|KWn8@IfMI;ur=wqDE~c-2AmjT`@i*vX}5siV?xSz&L z=k&UoLy5N$vfpRY9v2P{P#Gm@{-&NoQ#|>G-_d|+5K%Nr%&F(h!W90im%hED?Uao< zhc^1`bMc*})JGFGn#m^`uglyMLai%|a21trRYds1e?J^DUKb{~kNPgsfZhrIWciQb zAKkGJDH~Q{p7&1B^jBh{!F$?pK!Z(;yiKJ&eZ~&QiH3T-0Xk&#t3#2NgxZ~4M%N65*?aoEr>$Gu{4ajf8#FN*ea*c& zYuo3n|La`yJ3B2IA+98*J`PuR00(>d)gC0%y*ato+%{VC@lG>M(i7$JRaWLwA-<7m z@5tA8r=IXmrN%t{^8SB15oS#Al-SxEB2SoWZ!mDxk2V({3)Wj~&uN$QB{9{!c^aLf zvytV?7J(E#xRURk!5rrCyhqBPS=;ZDzwh245m8>!@>oi;bdu-zYUm~8dB_LZUuh2i z837%Ve!BlLfDXw&XWPToV!2pO?Rj-nnggSst;6FT?sIM@GaWb9Z+9Vu4~Jp%o^Oi} zUAK8(Ja~Wk{wE=wB;mfK*t8d}b+=#iSt_iqjAa50>kD|j<=0{%9qx)v)k}CStZmOZ zvG|jUB&NyC&A%E&oT+wqt0QR}Xl&m}|KxneR82pnea`kcS6Z(B+cLD_-|w52&zJ;j zBe|TGW}>B8`O^3|#SVjB^VR9R_t#R(;~!;qi*hab`w1|Tc%yE|+f6Xb-fa<<)m`rW}@kg8&c{Gfe5KhMleOzdwWJ5O!U z9U6(e(Ks`=f(yTO*|A7XF?Mz=1EaCyAK9X*pj_=)#cq>u)c~M-B0C_)&JUR>+W)qY zR2on{eIZIetM>o8CuFN+dn3c`LQw)m~9H|8-A%^Ovgh z1s(o=5}8PC{on3MA*}d{8G62ZMs@nEdomHb5%vzTpauuJC(MlT%yvqaWIpM*i_E&O z^H_qf#s1d3!hC+<+}gW0TB><`W|g-P_-?pe9-sai?HSj68D*SCJKzYe#IRQK)1G(q zcBoZRaf%&$^KjahN3mD9cC1A2E&9;gMWpMZ(|P$1-1p;z^jSrs*}BBEoFane*r~DR zG5bx=T+0vL>^ckDj1vU-XpVvus^aI?5obqy|s(acg?Pa09KL>9X~@Hgv_#?HbAU|55dpaZz?()G#r0 z4c#?#cZWj{jg*w+(B0iNgmjm5cS%Zjhe#*_(xHHWps4TQ?f-e6_rrB|ocYZs=A6CP zTKnQ_snw)Oi>I5xXvm8^6Z`28ZN>#)#)Sep?2U3|Xu4v17ff?gbD>q7F|2D;1Z;F7Y*d>6Eu4gLujN z=I@1i-N^bH8<#P_mX6pej$LNle2q&L+h;rbyRQl=6PF}oW&tBc1})yX%}u9&DFn_a%@-wbT=a&sTS)sc+Z!ZVm{B%iU2Y>a(T-^i{Sm&wXy%^P3^8%^9 z6DfLv_K)H&@wXqKG%Z@^42KA-$I3XyopC#so^|Nlif()n3H_udCWnd2R|;-?b~J)` zd1!Nyhce&ZmOYS>$l^64zd4y6bR1m4~)fk;S0zPUS z^4}Epf?6&T&?2Sl2wY7q>)CbzwpZ(n1;5BQsUDNY^@=tH^AwXVVjZL0AO#@yhne0R z@bHcm?uGV4+~a$l-n;?x^i`5xPwh66Rv@lmMJ3pvNvZ_VaAV#e{MQdAQz_yN%%9=i zpz{Ynh16EFkHfQY#{L}dMrYwf#i7Q_Y>KG0Unm1wvZuyPg~NDUSW9p>md;CEH< zeqw*3`bawtWviNmD>WtbH+4xiVs`T|{~vYPuh{*77{rk4YZXvg z#-Fa<98!3lEE;{RAmpRrBNf26@5SeNO5w@Ub4w4ymq`?}FlV>%)ekcp;@!*7#7BOO@8sJy2g&^`yqU4nSAhZ5{jcuv)2Fd|5uw-WQcbF_YaumlDZ1fs#aD{s=U^Hhp_fE{i?&6uZE2On`Be1>GZ4|pvVUV41Zr) z=ylg9FU@nKXw&@--xrggR@mw)F;Yjgf>FxXv$knEPfUo+Kfs)&nQ$HB9N>c_(GgK- z!pkhdU^t{vWXVFC3`LO$FC5fpC|u)0@fn8bFYu+KrQHMTk6iJT`Cl)1GFmF1M8*xu zn}c}qbI{cQ%t(acar@;PzbMD;{518;kgHQPp~Ri{`Q}LPT{l> zT1=#c$%>MJq=H!CXRk{Lcb6ShWE|)=RXtL)`xZ?jRtLem@$a>f@sZZ2frBt%`oJP< zwh5!u^S6Rc%y^ip+_5zz6FzS+0f5v4YaFlZz!fPv3fO=r2d;TZ#ynKVjk&FT>A z)|;Ke(MGNbUj;kN6N4R0>4X;Mre2lH%}!C9Xv=-i+Y8lJZ3)Ctj-?Z3q_&|y0g6S< zE2PN5sATtnHsZ01v@oM{D%5iV+haZ{Ap#r@INE|m>W3+bQiP-#UNxv=wpSDEf5Y%! z07qLc+qr(?>*OflgvS(3=bxp%pfNBQFu(Vu+d_+PG&mr+CX-h5a!2^1W8o=Hj*YRsdG zaE9pdzFOLX*g#s`bC zZ`#q6iPp`xi9HhjDeW6}`LQ2)U8`XEv54+L6LW4}(j2VWgQ3(sxcj0mcjmV?qGt&g z2TRTjmb2l7gf-0$hgNEf!!QslA(U_8c%wdMxctB@t$8*hE=T!{N<^$`GlA@Gm5PsL zAl^>jnpd%HuI%Px*XX>FpNf#kwiETS?Ps{k&I?-)-bqX+tmBUCxqSKQozM(h$0e%i zgB&QZyYkMpbuBh6(ar0cHnXe~o@3kr0wbh`ip&@2T5OFz2FI=Qr<})qkskYVeiHrV zZKsVUUDd*h|I)|o-7jzDU-{)a|MX;#RTnQ)rpv{U?_9JwYfYKMIiTcY&SH60dsfQy zxPEs}?)mB9J^8oKxfo+M9+0$_$yLS z=56O@9DqOG07bGOLMuy8JWy0#?bbgYXlm_T)eEy$r=$MbK@cIPtgx=u-tT`r(2Ku3 z(77|52O4sO^Fa3Rz6i6dcdicQn@BW}+~GUxwD0(eZV!nD=4`#O-Kd$GlC&&YSDGDq zvy@KJ=|mX*5#Fk=zZ!G__@D_l_s)_pel8nydE^bFMZFwB2q7E9L&gjtLx03W=3|Zi zZHw{@8@eAGE`P@I!(uQv`0wZVA4kCF;S9x;@I9_#iKRrmJaglipsnx~I4X1H6vfA4 z_gmgiaJUTl!%W`3Q^j^`4Jv~q#s4`wG5y%>i#%i~&9E2HG%ft3{~oK;m-Xdrmqal~ zfk|bX^qk^bn3>~@37y<*0CL+&^;PXpXyhXr|E@aur%Mg)r&F~OsySERf6~w{*yP=6 zkZLAu+K7W=Gh52`gXe&fp0|ftt>CEBi2wD&3W(j%P(k8Jl>KD~kCp*lFt^={DGZM* z*^r`YJk;Qsss zW41o2Zs~pmIE|{OnCMS>0clV1X5K!6n>3!EGmDpJC0Ryp9P&v_@+mOO6sbmxT>CAC zN3HX`t8HQ}LyB&PXRMuMVsD@Vw0^+OzY5<0yCIvb$z9esJR$Rg!2 z&JAjS4%l_0N@QVrO3~fd1)5{wL60yLAYMIf5P$9fgf1~|M>|knQhFj$TA?b~4zTbFaW9t=V-flucRWK7BHM_A zQ`-MA+}Dwa-IEX>#e(55No%k)jXUOF(mRL`!vy`6>&4o=q8X?0r=M9|$SPLaytZHq z$JGeesrM9N6zRHHWg|0G2DSN-{dnUVgo;PHv%1zl<_@zS*+@?l%g0GNpP3pgW0m~B z1@lw=d{IK`EM-P=Q%ZdUB0ZduMN`$#wD?*F1Gn2l2_=S=HOez8^l=y@fIEnn2!05X z2s9xGcnfMkTzEv+hIc{HjZGu=z7g?q()|()Fl)sR>T%D3S*ULOg>+u*Cw>xO9hVAP z;D7hVdo}sN_xp*Q~YY4a`WfN^?W+;I00>_kt!Sy77I>Ob?_4Wuh> zwigp^?PrF9%R!U<*}Cs3iaEJe3n;TY7Q5oD4{i_;m=V*%lm{8j33zj{)i$%0UeLf@ zj2y3CC?d1ea%SwTDD7bR1pjBa3}$PqOLyk`DKVc2y&i6j2if>Wo^ChDwQ3qME=(Q_ zqQg&_M1$#J`BXybH*lwX$Rv(< z7amAJhE9P#;m!ix=HpwUq&S|NVwj2q!W2 z0Uk(V;RVj&1$_BRSj9;Dv*;eo4)khK1z*mP;Two@8d3WX2x41ejG7@opQJF74na*K z0c}p7zR4x|$o69;Z2!Qb$mbG>5Za(FAC=C~c3l;Ck(ATzlE<3EL7LCeJ7cXXX`d+i z&bQLn@Tzu=TUJj0RZMU755@X^?}r~;*Tr*5(y9ZmYwKb=6k4ZRDmOk6^NGrTrEC)l z$-T64sBU|K-yJo{G|Kuh3I}GrJJcZv{`{A74VNQRP#q=;A+_FQ_Hb$}Tkp)4ZtxuN>O z4U=NY92~GwJTS>8szw$AA} zhQ&*4v1{iWDGK7LB90dc^4pvy{Dl5(2+CoMU;;Xf6aXZEH*M(P7%>e7MMsB}l4@T) zgLGQ(l#9p^^ruLlL}Pn>sn0X{Qg38FQ}|AFuAM2iwX&+V#iphu`iXKfo zc=4sp&g-en*$P<+lw~|#_5MIK)BCU1*{yl1b%b&Ae#DtT_dyJ#8wS+flk|jNkuwrZ z^!Ij6pv4l4)W^79Xg$au1(Lq-?L=~$qZ}9Edug_ZfV_OoXyJPcygd^%q8=&XUpD4s zGz1aDD@U@PPd1J`s*A3bdcCsvjUi5*x|EP;ip}i$jxlRv_Bfh&DBfJ58Dx+e+c2r1 z6~t#rr5}a=8J@tehmW!9S&sTGDkj=)#V_X+F08Rc^%>xyD;eB|m~v(y|6e2%mlZ7o z`P&|wR?_TTLiR-x8MfSQx<|XFbiGIh@-UerzWhY^9D#LQ6HDr8F%SimQuf)>pm>(jGW3T zux6}8nH#E9$t+pVB~@QN+2;9PLO@8yl8!Hh41&#wN`M>}KKhtea-vEg*91T52xhuX z=@VhYuxkC(98c39{GPZEUf-y_D^+;*mkJ_SKJD|r6HaIos98>ZsNQ_8`1+G*G*n5* zC&^c8gKxiGz;l=ij>@2cj_}2jn_D}l`~hi*Q(;grKb;{rDEFu`N3oHiG6$DCt;ALB z>RDRFx=4(P5*@h*^()gR{Uhh>2`oo0$E%>~fuB}V^+M$aotfn&u^C zZw>^N)c{Q~d2Um($LZDmYBa|;I-|2eX$xqkr!5d^#&dfX5E|iK>k|J_JELpo>_$G* z!{}0A(?LmmSAXql=HY_~iEBdhTPJ*7IN$hx;Pq-Sdq%<>)YguJXj%vJ;B!d>9C0Ti znkH@Qx3F_;#Bo;eG2@M)uvt=1OGKC@DKv;cu=u}#&VPk&QG0r45ec@>GOkaA{m@h4 zYanr@1ET91OZbom?K0Ol)=PxR!1*4OeIyUWZa|ueqyV7=Jc@9WZLizs@7_1*#Y9zq zfTq=Sf=Hn_%=toOadBw^F{USfl19I2%yFHNw(6CROfC_fq`C>~ zvM@J5a_3M9QMuzR&1V_~9;138_aJ@@a{-GKQ!dW^4Ay`>1N1x)eq1~Pc+E6Ovy_vA z=79Dw$NrInxky!(X>R{YSmgeWm~BZBWl>pTK4m|*6P#Zz@qbRZ#zI7**dw-qwRVCX z9iG)75ME&d-8C>Zc065ro*Uo)IDc}4^V&|C)!oA~YlQF#h$+J$K}m>E7%DY?-fWlO zTn(4KF#Z?9ff$2T2I{y;jT^*-08R;af4z?WX!VYuIx{#5vrL@Y2$N|y)Of*pCD#MW z!Bj)3MA8YbiI~*o_De4eZ!>4ts#~r0D4H2Ge7$V*m7`9semLvP@ zKwubZ&d*DpgRRC4WB#0*yJrE9Mg>ZDnX=WHk0?xexo22b^sE=4z#SNZ()SQ1fT-oU z;do^-&)xma)jWbyHI*(dJ6dMsw9G-VhnCoauL}JDKKqeord$<~E^eWABYSL=(#lH8 zB`iwGYwmz|sU~NNN*FCaa&G9*+_RxsY+(+X6s9x_r7_8un}Bx?`Km2exQNNkVgN}B zb=M23%WAeVF^mAOMQho>_6BpcY8qbz7Fp0-1Bj7;J{3Jq9s>2CPo4MQ>mwyF{Qs35 zFyc{6OO%!f17ctuDNM-bn_Z|bxSpJTP5vT14)!iM7{~z=G9Qg^hR^~XC1Mq(ziv0e z-&pL2qsRMW*=ZW+(XM?;ZFjR~wz%$;OWruu$jfvWULTNN+U+qqE3zs%V$!{Cvhh*f zc=)-MUDI2E{*lBN9X?tVjgEqpigRL?7aX(iT~pDVeFTgGsP#UY)L)dSCkf?WSY>+u z*0LI}Fj6Fym;h1+=S?2TOS6na-Z0>i#6G4hV9-YaWzpfwFdbG&LjHqgm|zqTx%_Xo zIe;p{#h+N)Ws{Od$&_U32DA&y~oc-Mgzcz35lDV>T-$g$3Wm%ttyQO%IaL-Ro z#+ZtuKE-!@Fm$-8ffp%^uS>`?(%9Bd^5rNw0yY9l7!nw<7(okx6@duhG(TieK8zfK zpzy4CFBHDgArSovJ4S22Lmt04RqcJg*g(7Zia-eeRb?WSIdEf7qaop?uth?El9FaWy@0K}jTU;9SrnoD1q0hI2s-Ud9fO>Wx@0RB7XUM2t8kpSYlgg^R7z z^U;HUG|=LQ|7aj5H_y6BR3%~2)}d6KqE#M5YwMx~RJ4c4N15Mrp()QMpZ(mY9Z^3H z(+B@1r~d;-P(Y#IZ{d4?u+u}~@Cg>x{_BsNm-0GbJ7H&XWS1({33bJS_SByR#WRFr z?<1duR zjv)SL`L=eb8?BRB-d{~+J2_FytyK==RV0f_cV@Ft<`Iv=JO{;gsN8Tx(F$}nfk(@y z`6@&qKuCeyCphg6Uy0msgLS5M3Iym&X4M2BB1gJtZ8yUjb0<01>Rmd{-{K?)jj1=P zY73)payxY(qIy;$*T@EymIBY*{(I{y|**PiPH-skHKDa;y`K`H%jTZ z5747Ykum7e5R>@L0^4tv9-^N|DXy5Ma&K#vzO9`G>GUVF%e<{|&Ua@}AS5U^-n2^) zuc1xYqSGu_h3lhx7?+t+x#PU1%0G0Bius6H^gz{}gZ0!qWdE3U`20K_*Mm<3hy3cf zkg(}U9;L`l|F5{vJ%9c}&#c?Q!rJ*4!7-;7i8xl_9DQMCFHAIBlh*duTJLA8gO}lh znFUJPR_p$zA;Mf%iV37KmQf^WQ^q40J`=&kNZOJqonn$arVonNZoyWbZy-{MEOsjE zCu}F6h|iqt6C7<#3Q7_SXAVCxo(`e3aKL4H9ky2SUH?UoV|FTk?xdhq#bh>jzLcygLF{kuhwTjMJ{MIvk7amP-+_C>Tx z=r}ZB(ufly+$ z`HG3tM!NcZFj?emK}kjoRkxD15p(AoTttCCU&H~NN62hL9){-KrNiY_E#I?d4f$E= zJyXOcsi3(0Xt|NIGKZ4fp7!1v^y38lN1C}a-SceNIx|-m4v-3Yb|!5$zG-~u8;vo} z<7ROK>Uvy#w7Quq!^KqFIK#zANAKfOokv%1HlHQ>1p@t8N!2pF#=>u$slq2F0Q+=E zzF^UfyH8xZ@~3k3&Xy{Y1xNww2~y3ip5d$XdINn8JP;Le5~fmg+3@q-Y8p>nxV*(b z>Tdv-w}{p%1<<52pCBvU8szO?*E$5I7dTjiJ;5HX1pet{D_i6K>0{D!`BC;m?dC?j zTsb6aGwB%Uyj+^OS;-Su!+(=zv(2&Yeci%IBA+WW$DuChH@SqrQ4%;aVd zN}AK~;^m;tA|DR!P5Ms+WS#w2fc;UH8W(a%euKgO)we#Mf?`}x#t3e~)}KBb9Z z=1~uRGm6pY4u1zX(R>$6Tcuhuv_pV*%9e{4?uH_pFZ@^|<&?jNwfdPXI8B0~k|aDwy1HZo?$Ka1vcOG;eO(EU->~K6{Z+Z6^23 z+*YPj;HN5zPYiQwL33MyBPg;EWoCXgs)UwA*s6Xh()|_g>-LRVG9+?7K&_bN9qyO{ ztBrubGJ`2q-08gKIMGXd_0jX%iaeziC+fKz*8(iAkdXjVY6gC;;TJBn;wJ!!?^3?0 zeck{HVJj!n#$=1mkX8A(jtKYkBv~r#y~&x==D{j#J=ny5RPE=z$t}CMVzx?Wn#Z_D zy80vR-_Z7WllR1xp;j%iX3jEdZ>6e4uILU|Ke0bzyie?pXAV>FCY=2dKs|g<-iDcn zzhrZxlGeT2iE+=#eHx|V$nHIf)CMW-^eF_zQ6!#bGCJI|JradrK8t=mtoe}_5~_*qPb*$ny#?|X3?&jV$!Zd>6CX+|D%TKS?m^oPNiC( z*ZL%2u`5%57yM7aa_e}fDUPyMW2xUQ)I%^rVUUYT7R*fkU6Sferv8?v)d!igH7UxM zL*pSGB*qsmp3QEmQj=5O-yQHdmbR6#ief)gC$`my_p``HNZU=Qw@?($GLXavk5WBS zO4V368dt`3K-82h#R*nky-UrZ;SY73oEyDq)qciY`B?<%QL%XEX$|{?en}})Q1J`C zCTf;U7!A1s$RA$OE&YfKVQ@2}9l+laiNOA&2n^hTKqg!P8|n~ELCWZujV$_;Mo;OS z`G#mGN>6FVV+Mr)k>y^#Hn6eg;3@rk2j1mg8RKFuly;O&BKDl2jZ;&fMVGwL*g z^zQimsjVRW3Uk^kk9)u*WwHk zsdo`muE|s+dss(7SygQNHl|?JR^tx(MgB;YaS((^(taeisl%5qp@vt9wi00I-*ee`*N)fAjkoR0vfW{fXe2z;yYmw7%7rQ%D9)`~oSpbw5dM_R<*{KO6+JScJWAAEFi(`YMf=7`j(aM0(jp%f5dfAd zrqRNyMq5QbMZ66Q@F)z}3{a8K(v;A`t87PxXDn+bG!07@>0h5|rL~k5eJ(*YzGsa> zmj%#A0A*lw@-);kXmGc~2nIBcw<)F~DlKqC9Yz;_t(LN;FB?U)4Ap@!@X@D_i%S0b z^jFK0>UYPeolw(ln@ZuSurY#vvr&cZB}-9*76vQ>2%tr=mDBnyp>thT^2(CYCju4G z8KUrq(Ji861cuvtCV`2V3^!Hyr3u)IImR!clVS?`yfU+#ix1ZU3?O!ORv>N&cpU?f27)h`$tj7!R8a5qiMeXqpUB&;-fz z32ZbK%WHvH@&69tvlo@iFGQol*?w015=6uj`5OlI-&LbTKk=Gv{lC5Z?fC}*OHC7AqAWMNj(oNJ*|BYou@or zxo`iNzxgd?`fl^J18@7%G&$2Xtiw^jY(RmgeS^c{gi+5M)GGW*SZvLy6VK#*hvF;p zawl?!FH~ACUPGX6(y4wj-mmI&och6qAFvhy|I@_UXjF9~2=W=xz$HllyC443>WNu+ zn|A(THkUF2uk87qKW3q;&nri8aNY*n@sr_Vqs1VPgzpZznTzsL!Na59K}aJH$-CMG z?fhH8(SNhtFUWEI-=*~Wr1!Rh_x0qy7W*zr98=%m1{_^HAA-9t>u%?NYlm-_#BsCS za3AFz^RlnAe3NIc@pTxUB**&DVtS0Y6q8<#;=8;(tCo|aOhFCTrer0O*{xCW9hoH9 zP1?X>ZWl`h;JqRvq3vDA*t@?|LRaO&(rxf5A(%k|Z`M|9qxjHb@PJFW0RC3^CR#a& zf@*08hB^T`s-N8=yLL=T7NDRq#cGOvKkT^MacSho)hAqRny>%H8sv&o{=Rfe`)UBb z5|}2qsCpS2^>Tf_Q>*+KbF$`q!u*35SxOZhevN!dY)z8M;@7)BQ(fTat5- zUzf26Ic-!rXt!Mba4Q!w^!n&GE+j%RfUs`fQp~mt_40HaUax;-oSnq88-D@B^ z-$dyiQn9#=ls{)CG`uupAo?TBIK)Wr;+bsqVH07}QK7@H%;BKPSNNQpcqk3Oc0sGB zwA{MCs2)yZ6I#iWXt`B_QraqhS%#ajUSdT@Jgq1pC4)Rf-8WbYiAf~`CPO?#ZFK z?nVMCz(Df&rRdLfCE4POW{BOy0$?By6eLjmv4-v=Pdu9s%XoqCr#Mg#VeoPx+3~(r zzbco^bqgG>8i^r{uQA4TPspi-!&NY|{dqWC^@Y>JHdP|w!-krGdz>d-;P8hH9}9B^ zaE5qq(^R=}BiUVnz0Q(6^Wu}PzT^Aqw&#n-adVa~g6`wWrC1%BT&gHj}_X%}PvE7b1+)+W^;2|34b{vug&TD%4nc-bDt z-%wb|gOXvd$3O+F~} z5`iy_42(^O3XBX>8%N>0d_&f*K#4Xw=x9mzn(B+C)~Pe!q<$qs%1|6O)08?(Mnxxp zVF|d1V22=xK!JcG9gey%`vV6a(a8WCFv4QaJDJUsioi>e?+F0-=rHhL`40_AAUb-q z2dl1y;c~i>ElMe;yI&Y9n1~J&hyp{BM=V8n4tp&(fkiis49xVJP&Jk#TCbsAXRG|o zbhaARCrTKXLV7gSC)$-B`ayY2ts8+QjBpTR2jCXp=GHmH_Rg#I11igG#u<;B>`{7} z=MGVr7e9h-;H?yW4yWf36o%u;9kI?k8sq;=Sj}_yzWli5rV;*UVR?k0noZYOU*YyN zUqwo8hu@BF1mKDwkx5WqE`{rnTf^aQu>zb1vuoiB+|bVH$DlVUs#4&Ic6*xs_Eq@x zEYSD;mT*?(uirtTm`DruPIgmSR%OYF?DT}i?ACtRYKV9d<~EuyUON?s7hyY{thg%g z2ON|_;)%MyjQyEX>)}*cO(?vdID5-;@Tl_J_Cj^l>-kEiI=fS*k2kr(8wt==LJk$Lp{_;uEV-F0OF&Dj;vxjH79C*LPaj{EWgz zl!8=_zy`+rXE=o-h-_G*9RV_Q(W?;pXo@C|R3rtn8rD%;as@Mpe7HOvJ_JBOFAGXD zY)XU&H$nI=V9+6s$l|xmO!e}$Z|}C)?2yVZIEze5FgT?udjeH_7(CYjF}lPMV(n;M zdcD8qIY7|{wI=Unt+=fXE7Hth#UUqB?`ml^W?Q_x9+{rS;Hs#e1xz;_Laz-Y0(Cg0 zs<;&Ls9V&3n|o0{sX?4T$d)$@WX~J6vBRueoO40qu39o;o0k}LB6cZoDs!IQ=5V%Z zf3+mcTjdhxX*^q zI68=QOl8|Z08%)Z4u}p&iw0|FPeg*n7#8b=VnJ}RmL?+7b5C@vIU~<%qZcz0;$Fj; zA6e`YEmLr*!zaFkG;z&fz9nkB-=xglxVTs@3}zBTW$`ImJC2RhWfJ!*J1_kD0iPYu z^^t`PJKTBLy{g}rB1vV8R;1G)%(1f5*mXZW>JKQjX`k{g7D5dh)DbcSE0&R$JVreCdb(`Z{O7nT&F zKQ6<(IGz69^TO#sp!s=SUKOd;#Q>QFc*SN@)(m@Y!dsb;#yGo1$vV33kulfyt;?*G ze)8kCsN$J)t8!@GM8kE;yA|mU?jqGtp9D*Nj{6x{zTC)JWje;Urj^5&a*h|*Ne!o8 z4Z`vd5_){Tq^B7MHf79e^Q%tPN2P5{Gz&9Sq#3SL3CGS^c*4y9YX1Alm~$t@{N&+7 z=ZQBh{*Qj}G;QwO8H+{@r<1gCjnfuq@Imi9Z^J_9P_`OR4I9uI16SKmWw$1g3YyIo z=Sfl&A+m$xhrAsoV*gn^N>CnKI#T56fhPs7g-2=pMs_?s3VSuq@;8^`w^7|u96-+j^#3KV%HZ{$FaH{sc))Q%k1H$g%i$GJ9D z0~gL0Y_5c^2ERx%j@fACZjv@>^!#hzRvEuIXb2MXn7KZWv`a1%P2TJ43sz~ldV^3I z#%7M0V;-CE(8 zcrbU%iHO7WdB3)fqB^;dHG#u4jcl)4apn0XkJ*au-QV*GF$aM;48xooix&^=@pd6J z3a$DYfmjUTiV9TpyJ5 z2~^^v0GhV4Pie0c@fI4!Q7;=0KnB>8Lcy-vP+>y4qq}R^UT=is60;AfY4CqW`!?Ru zHGP-^8aO5d;`CE+Fin-ErMz_jDjj8Y8ZwYq*5Mq6iJ9Z(ARkUQPtZ**m7s=?fb~Kmraa@=**FdJiMvWXY=Oz2kuh}Kum++>%HH&eP}dF(IWb#G!^%EX{t+%qWF)!;rvBXB{QmEcdPGX$|&>dqMH;oh56n7U$Q?H;eBcu zWNyZALdu65f3Ec#SIs26b%1dA+eh;vpNfL_J!TKJLC#KgWlw3y;bt)xz7T7C#1>u#}hr%{xkkye!0#=h_) ze%Sc6azJIy0SG|LdAasVAX@NzBe23EIYx@&j%2m@d$Y=0i?7~456);mh4i_YbuPHl zu|Y7?BFf<=4>N7;OVOe^Vp>u}xpT>gFykv)JopwtO8Z0_U*27s(lT5AUD80Ol51&| zmZpiWMni~Q*D}3yVZb*KuY>va3^aR`r*B3EdmU;EW}7qzd7p$C4;!c@odXqhDBBF+!^RNdbuoI46w zt1Q2MOv=eZZrvrTkCW1NfpqVdeoMq7n8w)^@4{`2JlpA+?dFa!0NDiXia$N@B&9#8 zDPE)1xQJL$e(^pqQ&s)I@_r57r%=~rFh-n5L8)o~9o5ODD=U3}ngKyp6qAMW|BUut z*676Cg^=RJ5kPV4X-6M`P)DN1xWCL4Kkv4%}1*r%Vp1IV|o5Szv zi<yX3I`qmAg0v{ce}<`IZxh0&n#M@{0-Q!*#DDR^I`?rrEikuIcNejMb-Wy2A&4O}A_?8*YJ?THdZ1 zzqGkL(KV~fn|6GW`QW2ugL1?sz)P{yWqB$z_<|PXWaO(bF_y)X>v(p@=dn zbP#cJ)<*TJE`4u~M!h$t?#@h(S-D7V)Ts5|Z|nOi#52Fs^=-V@)#Mr94CNbktDXB6 z-9sLqURTO2`i7hE_4E&;2W9?+ppQ8Z^)wIt?qM6j(DWdoWMgZYx~gCY3aRX%3lh18 zc-m>d*T^eRS9ROKicPTG$-k=_T=(BqZD}3YM8u&}uhw!M5uZsr(wcP>pD7c#NYjpX zA@dWdT@&%b(Oll83*kaZ=4a>Utwre&NjtpF7z;lAvB(pSL zqm%v~x`Hw_Uq8qSn%BI}<}P)+bEqsSDkqxXqv%3y40qh2K>53NDH=5nvG*grFE;nt zZFGNh8-4lN)2318!QPa} zYWZNM%o_Ow1ap?;q+8DW#l%|9J2jk#6yA$JHs=s>N6zfuJ@Z=Ku5cNY6~MsP+RR8>|i_0DwkAvP!W1u~)yd#};YKB6o)vpRh_=1I7kOJ>3(}YrzG?# zqV|CX{{NdB4u5_=xPYHq@gskJUw!)XW8pjPpWA`ZU$@^we=U5fY|+(O|Ni$%r~Z9O z+hq2s^I6Epw|&1T-^MrX)!m=A2HoBRe_q~=`0IVre|V#J;GF!&^`&{s5!c$Eu_73V zBw>sh+Jf^XX6%sU`FYDu;{3oqmvF`WGxkSJ+uAJ50Y|29%uywm9DiN}CvRoeoSZdJ zaM6Q**ysJ^WyHpi8%}{6whg8SGHvY`M!#9&r%bu(o8ent#&MH$fil4KpX2Lv7-j5$ zUT-1^^FF0UH0>aw8(gY@_CJ$K>t+&|OgczUDcXpihA66yoJ3@Vz;an_6^~kBDAHYt)3#-e=qykq*EIUe?N|$ z&-Yb-C4VEA!;BxhHeKW{G5P;Y#aEliYxx_bJ)5qL3V%=lqJUPbSRi7}14s1(){6P+ z;}EolFV~VyNIE8Y*Xo{3dR*H96Uk7euqio}gM;MAiU_c0O$3w5m73a}@`iuzthnB(ONr=WaT2B!#-oUn<+z z-Sf-+a6)rF|NdqAyQCBgux#HFLZrHyKI;2vbYA1V`_5} zKanJ{WjVXAnKZHi=qL2E4Y8Ler8L9c+HskcZ(RncG(Jz9-C6&9jHxZHt!A%{hns7? z4xjI%1X#M>M0(B%LY*}ZkAAwudYQ$wQX~~iN;!SC8XHP}k5bRz4LMohb%jUDot$cR z62_@Xp$Lkx;`qOYJky?5x=-@{bBVZ~9lRmO?02AA``eJ$+!Vy-g&Y2B$oH4D8kNzq zX8U|2!~Sc?ujE(?ss(qu{OA8RCmCDaGn-Jwt2c7zFg{?}U6lWUTF1wDPY+aJs;9-lho^JX(Z>rSyQ}Eyo!IXZ zp( z^oWRNSvKOF(YVSuAzG5Lwd`;W;`ZGsJ=ZSY;L>d!de{wB8^f9-6TRfmOmV1cgXxJK zmsz|Dds+#v5Ws{2Ij+aXTlrq$`n#*+ouu}YYpPt0|?vw?N!F3wXi0cUIv5I zjMg`A-rkGv&D*Q)tKPqPdo1@$E4PuQPCcEhshaHto$u;d8fq71=`?;Ch>^-iN4reJ z`XVU^4V|gvW}mf;lL55ckwgqFnIxkteKbzqW`G-04$@K<6Yj9*x$Z30>8NVGKJ=xH zsAIr@K4FTh@HU5Jn=5ID`aRhR?d`=p{}PEZU|?&^v_1KySXY95s@*k>S`Bl1L?PaD z_h>-X@_Ohjnsx4!G{dICbCt$coBu@R{ZWgJZBvf*oSV`+Xo6vV&MetfhOZoQ_|pz4 z?lx-vgJ6;L2D1&$*|Q2O-UWW?50-~TtYz7L@OV~YvkG}nRDvV17XZFH>{P*^4R3?( zycfS;iLqCCx%&+~6Rf>hP{?exO!RMTJ!tHQ#gODpnCn!3XTTEOU#Q(oo-B>QqBgWt zAlqhhCkvhKmrnDs9LBmQy_y1m6(%-{%DE=m+nNtyk8U5X3ukAB%+92jQ}pHIq(;z` z-QP(m-XRDf3ip2hr`|9O(CO%Ai$b5QG zo@#ch+I9sAxh}ZF?F_5hwElB&~*xK0UylCA}^@)yaOkcA|9GK)>zSIIUf ze~Y9-^$H{3bhp6C=sETs`VPbo!ogm0J1f!pP-}T&DsvjYj!?&wko4@L3w@Et!&R-6 zOJIszD`)$r9N6#?BzvbE>aBUTokklJDDdm1HQ_AHo7EzH*(xzeS zc(k#puz~E;%-zw_ncYLh3(fDET&IN$L&sJ&Ow|h96qTx2gN6UuIbl>D?$4ir*t>8t zdUKCp->>sqz1?+q-HU6Z%KwFwZ-cH`BB1eMu_~_#%7PM1`?bk8CFlyDzGz|R94qZ|`_>V=);`1eGV$1ItqhHs zyA$x{C@6FgaNQ!+$aE0a)rR7_=3kZcAZV$(QTa+E4T&|O=L^cty`VAkT8BTYfn`Og zk};&J^Kj4?vITffV-(q==m%Nm3vZW1 z{7sz5E@!MA#Y`1(RNo~Dn<}Pt(zZ5YuqFp4Xgcr=*wVvCPl-GL#0Jq5#lK)tZ4=g_(Iy8@Pp9cHD&ldl*D@>O6U8tS#loby zWJrWt%j4v0UdiH!6S&ATYST&!Gfwh@N+8#!v?V*+4x(0skgC;MYXKM(a7 zRi(ur*Eq(=jBFEd6v&MH{O)&o={E8^QqbDqTYdbr%taVhiu$^qwl?=IqTnaEUqQ`8 z3;;&TR6&2qL^MMnfr;uOWA(WnJaiKF^%FTbbE5vDf-i>^z|c(78ekIcDtVw_(1(6 z|KUD-VjY{w?=#qWBYPL4s$av^S+=GN_OqrcYhCuBBP~gBS?z2`(V|QTxW702js`Du zv0wHs@J=|DYvnvxkBU1Dj$i4xZ+&*+N_bzjl5%p1R~UI<+?vWzh({Q3z|iGl?XEyp z*X1I~yw)gXo^db`JLtl!2UECWBCOxL5_V8%(yHR-K$t`fxb%3R=?bTidr{tu7^y?q zTuy)8ft`OYUCr~oz$4#Xa0`!;CE(JRhpdp7{SCRd!etYW1g9qINV(hpP5JA&a` zoL zWY#`-X3;U^x@}1%6xP0DW9G~6YRIfT#-EnNjA|?w;EXM_l3q&ZPm#l?_DwhBTe7*u702>1F9sN&ZvqdC?bcX7@FoUtU7~u zsGJumaR5%a8gXBvE~exIYsBn z`Zj{gEG~Gs;3A>VoN4buC0XLFwJJ zDm=7?InwW(@^x*oHctJ!j%E3_*YyeneS1#*Ya*R$gEBZ@UGRO^Tv&{1y_U&bp=b2g zYt)_z;K-VNlolp@m0Rr2l15x<7D{xBocP@iHkpsbQB_+e*xyw$J46Rs!|R%C;Py^e zGSB)%s=9TvhbdJu*Ax77izfEtTflA}V7g!rd-$wUGr=CVL^HpluC0oFI#&Ovj_WgA z?~=iDk}O4Y{d3kop_-t6iJg8IkPzSF81mr`L|VTvzZLn=kpRT2v~R1oN=^{=n-q9cL`X_h zX=eVKvttnct$84CYs1q}!&5k?jCZtVZlYpMYcL?A`(va~AY~DmrXcG^pZX-fK4Ds3 zhSy~B5n06E+H#NVi**FIK@;Q3UQ_S;^~Tqin=Q{r-sH#~;}*@+TDm6EhHphm{MY^% z3Pj*qw{lnL{CcHdIizsBS~uXgp+i&iNs7w)_*ggj^k^x_Q$ks-=$f`K7E-*OF|$Yf zxjeUKMx`T4j)%uFV74bDeAm^lQoxV*FU*G_Z=sRQ#$?vv=5> zyV7q)Z@%s-(8?Dps0r_idb>GzDLh!>G7*zY!6*kM5|Ml6qX#B?4pKs8w-81ftGe=K>;)(kI;~=c~1(Hh-{34zQQ+-MSKLEcP9XqN+q$!e9S=n{@8EE)BTYyXqSzi!~z;O zC@hEgFUB*4zHK54i%v=r5nCKkeko?npHP&@%0-taji!j6LD#8u{7=?hHGRB2!Pafe zt0C7(&WjTRF8>xdF7WYU32|b17EH|wRv;yy`R^2s5e(7A@C@sM##5VWe0)qeQ z$Xk6}%o9NHKZ-T3oJcMJEQ+;;qU%jU^qP*`V?6&@PT7aer~RTer_~B3ShR-miQ7m% z6>T?!8)JHmnuPgstjJhiIxS)2UUdw{xhGT1#=}Iw)$+0=FJmTv+&B@&tbmLF>(>u$ zici2F^UvQD{m;&}3aZ>g!I)2$;erVKp~*k)!zQ#M9Aq8fz*APqq^K`;XfzPzIw zE|-A2Np}$vK zpT(#h;We-z9aX18TrQ@C02Z5L{pTZCT9$g9uF<6db*U>vCcJ*UJ+czM`dgVD;-qj@ zLS;{n$_u8|ie%-T&7+&q1;Nf|kF`#l?4Re#?dXjCAAT#hv$<_KcGLq&c{I3o7j#Bj zIF3e7%O?-u@%Y$>5&`s$0yK^Hg#K|c>tYHcxFk%UnPcJAg@=^PdlCJw-*WM`R__H$ z`0g&h@d&(K{Tn-BDUZAHydCg`e@GXl<;)=!))^FuuG!=XYomeFfqI@%yx3i7#8BEg zhsnb#SqeD@XT0x@=`5NJj^ zMH}@+fk0yphrfMW-M$Xl+iLz}#Csfowe!OleE!l?nm1y31>>sJ=} ziYtbh0daj!xsqA~qGM~1hK=}n|f?b*-_C-Jw47388U~WSFaalVi#TWKB$!3X+9c$g1=>c` z$;GFO#HVXbGjKo5|#0D9ny6`%(~tM^D+)-C|gFOkOUV(9&*2dF%k zk)5de|LFmX#y@&s+Qs%Psn9yT(z3Pi-~s+fP=I{ZCHm*qEu>#8u-`qqK6jc)eoTOS z@2G19L0+iM(R8o`IEF z@W;guZk?1|%KegnuQ`7#4;E~z%YAP2#0pm4ywu0kVRgI|Ry3>FWp76ZpR%B^^ z4^wkr#*pAt-%M;$ zjk?iy%hm&LJ*)}CLuV#>?}lTUXXz%ZswvI}a09mWuD^hl&bHido5iy^J3W5@czt2B zGRlEg)*s4wfY+xZ*ZX{ z7}9#>`GkmfN7=8?NQyh4G)^E_JR$neKes;fh*V8li(D<|1;W#pwa_v0jeEW1b*Q^H{JhX zdRhZr^A}(p&^|FdUt#zrUMWpWN~0o;;lW&@w=F6CRb;>$uiWcYB8Tm6d@y3sfoo-d z9wr*FX2eb?D*N;6S=wO=k`mR^k$ihaEAbEPjP-hV64fWPw5ip!-=8kGF`8F?f7)r< z>y-pG64yjg55WLHiLCy5vrYEL0&esonrOq)(|*)KnrPPFpWc%2nnn0TZ%OzE=7YhH zGMY^8Yy8stgJSK-jD2vwMcOa0sy=~_v*JW~kdx~NQ3j*D9i!GP#SU*2$i0hY&<9T* z^z@{MWn)hN$`0?0W$}xR3qd}3X5&8`@FL)?!e&aW9#aCxQNP&OY(#ijrze8*!{j`m z)&t!)2s|kL*QL#b1>3>T6sx7-q1Lq&;lsOGiOV{6w+LvsN;aa3ii>s!<>WqfV}U5`U^_B@8aN;fED)>?9OS(eriful9C|n7WK(%zg2G2(Z|c+CS6s&{o&C?Twa9s}BHv*!vidQnlnB@WbPj z?AfzE%9q^241(f>UJ;b8|@CNGOzhV*$U%K599guK5O*Afz)bUwk81P>9h0Em2M zfQb|Sh^&<^HW1$jMuNu4kML%v$&%!0V5?;)%$;h)dxgfae?-s{o&VCXGn792fbx;v zTno6Oe_`)2AJUH5WTnsxJtjYl1EBpxY-gFu@L1JlQvHe4pQl&UB~TJmO$4 zWZl%n+j)Z#fMe^RP_fEXIHDd|owvx$XnN+eHzDO!za!XfI5IQ!-P|9awXYorypKo% zf%gZ|WK}MeP1#V^nKnzI!(N`>%D_-(oDcoVHL7$N08I7+3XDs@lp}00(+djXmFcQg zl_NB1sQcTMBcio>yMOm<$}ktkV^k*ZFl^PE^M<%;IX1reW7)Sm`T$E2^$OsR3wr>6 zJU%(EwZf7bL$JL5OE6Eh2+1pS2|=h&4VWFM+_}-^*FVUu5?;* zm9gYbH$ybObZJ90)N^237?frCs-gL+b#_10*Ou$%Di*%#wd9D`21JJcb|5gI^)Hd% z;g_1d!PuOMthq6WVq&%tP0k$;)89?6lxD4@9jWEf^ot*3HQ;>bSSIObk00*-eyJ~R zd`lg4?a(q?=F5-%xHi+^vgs5S=Y#5p)`O2dLO1oG$CD*(?IvXpyqH}M_uneB9`o1M z)@e^p>)U2d<=Y;w8EN=RwpZ3#yt?LsgUX)8wRrvl%gjPYHw>~e zeS(zEiB&d4A5a6xb4Xxc>d^=Z7Na8r>C}`00qm}n?VU5d> zrQAy6n~b2u6$=gsx+-1lzz)8^w#o|ZUF?_62#=(2%@V7LZ?H+{I?Pb@g-WFqZ-pc|i?=Z-75jN7Gg5SZ5GGT60bXcFt8 zF7&7;M-|PmYUn^HD{Ck#vnvOsv5)p%Y{9EvpfO0j3c4gDXeiac$lIZ7Ku{>Xk_siioxxV+usX(A{c`)W)wmw$XpoZ%tFBcP7^JKpn?26|O zDwD&s&jj#380oOH&SQCF@?5v{6>1(pHQdSwQa$Hf1y3V+`S$oihu7&m3cq@IK0XXK z{W|~d|8)EPia)*-|= z*`~SAFVH8@{_L5rw!Ct%Tl&73h_S1JD(W3|f4=UP)%mg4o(K0ZA zoZK)dJO|~?MyomgLcCvqAgn@_KB#ClV&;6eQZ~9_DPpsA_30N!GlE_4%ElYe{0o6S z;q!{Fw5A<%zInf`Lk6OqXdTt8v*}^WS)&OZ@zMPOMnn(41JWw^Z5O{oY)B%{W+51g{E=x_%{-@$HzpA7{U z?ImtL*b(#77trPZNO>N*$A~l$)Rr*w$BU}N53~pGY_6r?=0UuJF_-lIwRJ8a|V2&ej(U#(fBcmY5 z1(V{aiJ5%6XyctZ=mENVG-PW{8=F)#d#u0n>_JxfjMv)T*M)DzI2m*;# z^p9=KOWZs10Z*MUYv>(aSDu+mN%2gLHwp2Aqm@J;fg#i)s9V54WMvwK)4M=cliJ~9 z0LQ>%FR7XwTAj(=Uxd>wVHuEc;Q*Q@6y>T{VJ1^{6W52|T2d5t&@W^bS4e<2s8K`ISx)EMa9d9Xj z4qLI_?caQxnvf{US?&KkJqM`Y9oW?d64H@FA>iq~`Dj1<_4IZ8P<3XR+JdR_^MI#M z$QwwM8>+oJ?Z_zl>*?hjd2kd8ItHWr|9JX)2RX)44!C1kmvHA5ifkDqdj9&cf+Dem zjD|@c;%$2(u48RzH?jxPsK%UiXFTk?UYCLBHgCvoAo({52Qi2#y@<%d*g}0U2m2VawpTmdFooF33@$Npu!PdxTf7?GWh9{j3p+ zAH{M#SuLtPweA!QY9$FD8K<t~A0+#bbNTS_>DwW8orHCE9)80JOPGfZY!1DJ%Km0_~); z{$<9sr`bBX5+g)FBl^tRm*3c&L6*x~Q^6Ogz_JS_EZFdiwLf_-nt|IwALJdrnL#^` zI9`*WxrH5G|E#xyl{LJO(v3U8mv~*wv*E=tmcWi>*Gr zSx5OJ-@oM?7lds%7p;CkyrJi;BTwFCY=y09y`u@4u8IpNLslr;py?Bx7FU_ufnwlv zXbBuekYj{N!E0VsbZ8M?-3h~WjeBBfUS%5D2?InB11BJYoWN7?Bsy0C5yW%WvdUz? z=ex2TJ<^}m;+-uAh@fSc8T<8kyMov(0k?TdvhU3t#1xN~4~uau`S8@%UeaG!^2;@= z6UCpT`eGpRqX=N6aFoLmrS%m@V?tKl$j0bR!5baD?wMMx3u`|ReYC7wPKASX1sPZ z7~Ia72%v=M#EzjbN0@JV12Vt(`V3bi6O6b}4XWt4P_aUArNOQXj#wW<^Ckug8zN)d zcu5Bc8&-q711u(DZ2UwlYue=@)OW*?7+pl3%!W*t?Wrr7oAr)-%ezszzMZ&7VM!0m z*E*b-2uV$C0yY$gJbpuSq5}0F+Rfv(7#1e5tp(1fYc8 zSz9UrN+^iFU6Ot{#CVQ&TPa5w#>ZA?VoUYm&iw>qgO@J zC9A|;A4cGTt0L*LK_CUri%G)6{qhsZ-RW*!gVM$4WeLB%C~u4GyHM(40Nd|KRDom1Cpx z^hoDyN4BEg75#B#LqcnbBi+ifw4fw8lk_I_3qOq&vd|zHP&f_1Yugi_EaVF=Nn-j3z_)MW`hfEK0OU9>e@wC3!T-c8J6dwv#ce(vWuRJzIp6{)p!m4*Q5_T76(3AH=n4)61Gz&3!GMsM2F-_$~vsRNGg zyOeHI2hXKu-8OHMD#&I&ScWEXvlRz!KR%%D*gR|$5IW77s0<3a5I(Bm`*K%Zt-sL| z#IJlzG5XA156{mvUQZq;mO$<|A7_FE8!LiKZZms1MWPd7NMsH;O@Lql_!-ipP)P=DQ z1$dd>+G^yf{(wY{k_|duzeLRx?V^Pkym&cymxLBnK(uk*V)6EMemVG%EddBe`uAu= zP3l8ap^^@XORw0;s=ft%Qm;>h-@^Ba{|7h$l#a#m{^;pHk0@2HEbyT~O^I?wzB%GU z|JT_EMjp)%9w@ZYkG$_+1`;Ut7|?~E=NrWjw^Xu(0;Xm?6KfJc2|b1JGfej#&Ia(Z z2@D0>T+{Oc2ZX)#yA?b8+nE#EDpsyvU$t8Z6p|oWjJ#V!UEXRA2vV=fCV-lQp{n4d zA1^j`7O}qvqpzQiJJ7Bv?Wo<0RD^q6*MaIb*RCC=o>d43y4B&3)hK5fl_Jd2?Lr2TDMtowp$ znSGlcfyJ3$17l}w#o1=0^7CGNPp?A8Fhm0QK=AL4kzkBDNg*a=cnI)rNMt(XAZyOA zctND*NDwN%i7*fepbPxj_G^O4(KlNt4^me@T4g_gQN58B6MSpuFiG=iHrq;D$ zSGDG-Y)Vo!j8 zXMpeD;>O(?+Yt8r?Ju{wK^$6BuH^QZtfPNx8&jR%Y8%^7RwX%%>@S7*{3Ey+C_E%QA8THj za4unK-5)MXg9iEeb*i{W)m+dF8MfvoVByrn6RtfIr4y?w0D1he#0pWDRUG7bg#17~z_e5QK0W*{jko$Le+*K@;3%VKvA z3iKWs%RB0oI?v-cS(_gmi?T15AIVx33cQBA_vG_5RF3B&FOjtPckmu7?hmfqRUFjJ zZC{S`?kgXmsyc$N$s1jJL*v8X2b+p=q}Vq*C#l~ruqJj)qWGL9dUyAB z?wC~$M7)SE2&rQkfGa()YfrF$DROl{*cKM*&~p7997&*iykRUk^P#67k-^QO#sn0L z*J@JYuw%n`kP3@;ImW(i5k>Ip+mB)28%sX-6?H65oi{qxkQPJ|95G<=&RUe*Hil9r zjqu_j`P3tHs!|udRGkd3N1%_5ThlTowwQVjPBg?x@hvB)`tR8XhlNop;@t0SY_^i(&V7WQ7Y054x#0J7P(=f2v)ud zo53SgD4)WcxGP{wSS`=L=?m%DtR|y_`M}XZ_J=+3)%h05_=!o@W$wfA=F?%rF|<}1tT~hEk`_{t8y%rK=0~8I*T^UHI<)5=Rb9NV zM;1hzzAp=W;?Qa>Kd2p`Vjj6+uy#PrgrLmONBu*UuHo%Nd=hgcdF8z?F!J$fbeQ1@ z4H=QW(kuxgED2if8b`;vAKV+X;NSm*w#c!|mbx|jhpzJR-E(_+3TsMyz^Nhk{cORHA(`|0k$n9Qnwt3-#od9{`U`w@ zh@j#qc=}hzbJj+(1XkOmn?bvCKaqOmlP9s2E=S~(R584k$KlJo20Z-+N35KzQhWE8 z+O@`t&)MHoUT=BUS`_9{vn!{w+CIDN*~Ont_&T*ZXHU59(eUb?ZmS6gnwTAHVUv|KC;v*L273A7pT;qS@SEbsywEE(nxTec$z$e_VK~mQ$W{ zqg%>FdQEvSvW?do>C$WJ=VyfkkWZtg67`3slB5?~3Hs-iF};T-OPc2uAEXqsGKF0Z;i{jKci3jkRFqbW#cFrb_;6E4`IW zYrPeCJH3^trPg`4Ph<_1f#M0qamH%2G9jqBVpLO3NmMOB?}4p06-t>lBrVF)H<3=% z>oH8z$-+=vxg@$)zqsU@Pah-dqxf9urk7o)rkAhETOMpQ`rheS5VV%g>Ds1SRdVQA zSGLd9PogCSqS?+epQD@AUA^8Yzy&^ww9*2bRv5TlN|?}n?V`tBH7TkKJ#iQq?F zqu?e87YJei_y!2%pPdUN(#s(r5$k#bB#3}0^rDEC8{}G%bh^7E%8Tj_L?8fZ1N<&W zDiJAu=@Je|64r~NkZQ8L&qpTBA)ujEl&T;oS@b%u%V~ zlY|0;2;bU!7Sw}$5dqR`S;{F!NZKhzcG2&u=zRHo0=0I%NYeO;-Z*mc*HEJ-puVjj8@VFr8^u?bZJ7P| zfJZXb{e+PTxa%A?%mg}_wPlBZq`ac=5RnZcp8C#;S_B6ykq?)#IQ zHc`OG&*L0w*QIBSu)XP8W`~qpw-%VT(S4o?o8BVwYr^$ zW#o6hE&4c2DK!F)UE>)k*Yv>f4Npm-OKZhLPg@o^ojHcBy9RP?9$}PMb<4E#EzOA+ zQzG1sNQ)vvBCYFA#A56xVcEn;V7(nmte?$^wqWvGZt9j^S4O zTEmRn=q)ep*_j0!5@AEX3kv)Xi=mL+Q5|sBr#UDP3Ao+(KhL?k`9zqIWfg*Q(e1?= zJQI~7!dHnnhY*~CSMwP-m77vYIk`upUn_!Ek-ut%tmY$sO>=ujPfk$d{%W=6c=}~R z8ruafD=@S>-((>EMnclTCoz#IDvWvtL9z=43(1xf?q<4_I3-lKxsFe*X_0WS3I9O9$GM8y+k&qH2_T5zs+ zKQDBauXMxj+KZJ?M3KOdCN1(dc7bCevHvPC{}f`P&52Vf{~j{HxWHfxeVS{)K&nGq z7ngdm+I~{gQMFn%R3B@jX{1f*i&c5u=UOuzkG+Yp8w>N^6U`e#bZSEB@_ZdbECI5R z<|8-E%LNw%ABZ}VWMf7`$9C0)D)BM%Z>Gk#=vjkPm^P@@>q*^*2%N%K>GeZ#7jPJWnRaY>OAKGZ9wm7ztr-eaqTdrl$ROwqrWNT zmYz;@&wp(|M7B9}V%^AAy0UD{6|QOYs>uca+JJ0~-lQ^GAWaMX5)<4 z>gM7aqti5~j>gg@!do;tm$>H==u!AfSxQD^t&V<1sipmwG5Fy0i=-h1)X|6m+fi5- zIVG;?@fsOxHz)xu8K#tZFDwZZZZuhOrT8?V$~FY}8v6Hb^aq+~@1WrI(Ky^ez!9aQ z!DHUXa6$P@M1dD0<0~O^kkCLVL7;<*3!x~6Y@-Vw);gjSn~R@+S5t%#fs9lHMrK0J zRMPce)Rw}xcQPy5Ei|m2_Ld)Xx*G8Aa3HkC8oiV6accA0%i^T|b=>1ND17W+v@B0T zzve6N#_FbM8~*EEGa#bJmsN<0(2Idg?Vy1X^*5eF+X&MCcoOq;_&%$%Nd;c z1~aUPRZSh`b(+O$CWc~tl}^Kb@)Ca7c~xJfdIn9M(8-Sr{)Hl68W>Lp*Qr1|S)X3KIv%$6aPYRuFmC3~?0u{gYO zZ5(=aH#hagtCqg79;&9=TbUM&9rZ*VIaRv`m~Q4kr?Or_eb?`ERezfx4nOgHizzla zJ@ok39VCF@UvJ@-m zTUnV|$J6TSfh+fu_%7eQ@3C`f=StJ~>JzT7mNW5$!diOh)&>_BVodPX$89c@wN!Ht zltJkcM+hXwUvJ0G2Ug{TF}>%;PId`GKQXVhV8BENF)Lf5y4@TD;fcV9Kv)9)0}OF* z11DJ^JQ|TGEMC0OyY8VcB9T}Hx@pZ~gLYL~y-2N_aBp)k-o{}J4N=4|tw#Z2IhSCR z0L@yteB^*sx1WgGHPv=ZrJW4r56c=l-vqgvU}KgS-kVny89%i$4to6xH86Yq^c`H= zo{d@|Xr!vYM=h582kUau2~uxmHSIBMThCv}uxp^b3XHB+4$YxooX~{ojyIgZmW;G} zMv>G6k<>6@h{s{8y2_O*)4>iDGtorB=Jgcw;Hf!90vGF8r5Y+Ov^)|6wIR;ZulJ?P zqZHl6n&`6GX;%WQ%LBl?4-SbHY+DnPrs(nF_zZ^&R%LAtXZt0_@BHsO4<@D9P@~02 zr=-}N_@aT5Ut`2KYX~e_)*Vd^=v0v?%!{L*OMZU2&dBaip0NMzKi?@XeWGV>Qz&D7!?IlzYaOul_)i8>m&@tI^k%KTuLVwlKQbWvH9CY^w z=UcIzgSCS&cEO#K;I&JcwXu1C>Q6>V09hH2IFS(J<#B$8fu8g!ubFpimM%s8m&`6j z1#~*@v7Z_95!+_E=pEoz!J7VnrmKQ1f&2Ga-I!zKM|tA+P0CWcx_C`FQ_7z>I6g zQ|;If)~u3dmc)m4QgzGLJ)u$yMxsgGuj+v5AKB4<91lw&*LA+~o!KY<&+v~SirUXM zBpE|yC$~Z$omrO3*Z6<8gDv5UbFBRGwXMYwBwP~XARjV|?biaLcC~3SHu6g|Zclo= zKzcIYljW;Z@ujGBLd@uaPa0>OmPFCN_8|=I_rM&5ySxY!HDz~Rc!;C z{8SPY!M36=u^ zxn2$Aa36vNkwFNEvG>3aAOs}>DW(Kbf=X~t6nTJB5nltHCk!8IU5!T0)Vh@w zNRdZa|0uX)zKtm)H0l(WcFDJL;X1vqw|79fu>4Ahv*z0vkf8`cJDaMPbzY^nUa)*` z6=V{-`Omi)A!`|2Br%^ze|`D~%e^1V_)H%p$^6xa-22ck%op6mW)(f4DDUgyF3oL~ zY8--P6*ag?H~bZz_!4RQMCSOeiOddo=#xW7(P3X<3cBR zJ@1Ia%;Q_Gs&aiWk}G{Ezs5&`)0cU#sDv1R_baTK*zOY^$EvzKx6t;nqv!}Ii=*g8 zc&HDjY%adx@)L24)X70+Ls6;DNlELql>#kd9S1tq0TV_=hDj*dn>1h^?nL(bCk=pi z3NVljfBCFC!iLh|npUBT+5b-(xR}04gUb#;8bp-<(!f;kvlz*CBiX^wK4#XzN>fn$BGagjEm^&s~t5Nbyd`)RUe_J?c*D zs}Q2LLQV@r)Hf0Qq&WG#73Y@k`_Zy0n~S|&>d}V1-B$Dk1BO?nvlAQW5SFVfbZQ{~ zDkV;bQ8PWAOu#8Hp@R~6yTR{)v>tprbW2zgP2_=uw)Dr0YF~Q&}p)URyfS z-szxtBvoO;M=x4oGScOGn|P;xlQWO9)zi$x5C!)av^AOXD?Hb9(UF<*#6O#rhYoaC znvv-@*<;YC)tj}Shbx8OYcm&{T5A5t(W7!U3H{(1`KhNWdL ztFFV2NrDce#d|R{LbYI31cu0Zbhy|WIy$(~p4#eij!_xAO~>uy8ahlub7QUT2H5-L zIo2vQ?I1mC3Tbm62YcG1)x;|RD z83bfQlRvn)u#zG=`Z$4jEK&`Uz2K_YwQZ8Wj@tUo-RnGLfES_S^UnboaIj(!E0KWZ z08^0CFM$izbSG9GD8Klx%BES zA{2d?y0Q&=Xo@{&9z$1Lge$r#Bd`y3RyS*7<+=GTY3{NgGAh}8O31@FEDzUWgMmK; z=@h6-gav?o6?Yq~1%lG;*H7~_QmoHeA_7hYUlv<9oP@R0nue7SH53uCb}OjDdmAea zbs{Q;{$1yD=24qS0GBpvOzT8ZEbaujG;RI_oi~?eRfCbH&3(||l-L={nR^vI%_;M9 zfWfzo#l)_Mcvh-LhsDoQd(H2yd8p%^K~Ks#xep8g>hl7BZx+u#7UsEWt4=*|)xBdO z=#(v)J-My=83ZG=xA5{-)N~WQ%$au3*sEZb)?h!R7zj@+I)uy;0x#bF@vEiWM=EL@ zRKAMOZ>N(5w8LIQ$TR7~(u!ae_Icow0nh4JJ$kkB{KO3oUYmxIV2uIvhH#6202s(W zFzM2)fdAY8dSy)(NF8XiNOY^s%05i=!EsUoyv=?`3&}vY90CidRFH z()^l_CsM@u%qKU*PbNkkjve$NX58sJ7RetXyG{j0S2_teMsp1zVZ(xQ4XLpIK->wI zgX;24!0C1mJ)vJ<(1niuXuyEK9BJ1)Ro?sNH9>&C!N3K5PVW?NGelZp> zUSn=Nu1>N;b1n0;SKKqrcA3VHV~rEjgdF{HyFyQSuS;D>Z?_|7?wW-WUm)-h?6P(B z{>1f0-?A#NBj%t8}kqR9a04nucM-d1dl?ytoEgW*AlEsq; z@FYnnmp|DL_y$$9;6djxja>VkatS2=+V^2XNA9PQ##MN}6rtIyJ6PaM@H|z#6*bTM z``&3^Y$zxkK79pBogx=TB%NH$O^{+9ce(r6L<=9fXWcKM1a&Q*=C;pe@YdVn+VGx} zwxm~bveCd*m-SY+wgy)qcLU&g~D( z!KZ>633LMB9#bkNyA$N}wg8j!!j6aI_Xmk)7+8p!rrBe937crTh2iygHZgg1Q#0Rs z6>M9wqCcS+hhP&+{0Aio<37Ts#`iWrE`E=&sl`P1laiJ3+b}WXt53ks@%Mjf9rOHh zAnlnK+j(v*#az`A&dg}AGIJ!uZOmfAx>vIIb_?XE?btJ)27^jo`n%} z5iD^0(hX*6Hhc5V`A__TH`e&8Gb)u1=A^1i&aa-2ZWJf9x)*^`OLa>vTV|ZQ4aJy` zZ3@iTX)7VUM&7R_K4O+50#4=fhOfg6(0Lj4qMQevrIB~rt0QNW6@oIFBDgGi?OC%+ z*J>H;bl>$XD93g1Ic4;PMHl5^d4ghcNcW-t;{WjVRsmgf;r6f~-QC^YUD6#&mq>Sa zO1E@(cXuP*-QCg+q6p$QKlDB4e{Q}DX3gHi6*_zNUe9{gN@d|gl5J_qGe|y`Zm)`s ziKZ=Fua1gFDY#Bnp0gn@Szik<-yhmC6wshGS{-IlWUcIvNO9>~1H@4#Xn;5>&E=2n zW60f0+HW)N8dIrs8_TBOh=gYbT`q=5WFd6N$^F#?gM}zd3jFc*6EpajHZa2EGcX+B zQNsHH>nH%r&oLJg3(FC2%WxoO1ZM*?UyScB6=8715TdpjVX#=GfuQr4HdyGV7RqW# zNK3Ews)M$9NSgnrgEqF@_sla0sXkaMf$gmtKPaw`Q2#50rs94TLUX$kuLivbgwWwr zfDk%eU|K@2BUq+lESRnQ==u&MghsfkMHZJk=lZF<>GV$x{l@aI8oG4__)HCAV5{h6 z>N(sPX(o{6x8kIS9_D$N69F(d>m3z5@& z{eRTK1jDQuzy+1VtmQjw;h{#$?6N0m1KC?;P zT8V9N-O56&|C2R0K0$eY`C$v~SM5F8fBn+0-O~)D2>6L_EY}HhC`01j&>a|Q!olWR z8R6Vhb{;sAUBdksdAFK%B?gbfDS~Ka&^T^y%MeU!cjl-`iJQnqN344B!S zQG>Z!6uY6q3a}JCD+r4t8O2|7ujLe zft|<>_Iehro_vY>htL4+2y9>{a?WS1_Ei&cPYVU`Ey+MBe3;szZ*p7M`rwtKcdLOI_*r@$4lz#Y)Jo0a^OgE3g1C>6gF^O|Xx`@ly^e22g7mfTr7>t8|cE4dXd^ zO=WY#V+;jXiRS8Zn0e70w12Un%0r;{ivI_366qsNEnWs>=&90h>s>6Uy;Sj{Ux{6O z#*GrAt9(a!$CPTGkbx3mF2-wxP&wT)Ksh%tl6LTqy1#N*3PXT0aFy?%htt*4v?8JO z!%lv4SrL4mlc@tKb#WHcuuQJ}88uf-<%UkUfq(c@OLfalBDDxE$<)%NwctZpiL{Mk z0|{WJEn@Q?xHYbrz39Pdnsjpz-C=w)$|93-hv zZm*a^fJBG~YX)2#4tV=hviCGc7dXOQlcvm>3;$O4hkfc(uSl5u7euN?(yZ ztuEcedY@KGg!!a^Q+=zdG83h{A{OXLnViPlcYE4H;{>Nt2s~t|qY^N$$z$-Uh04hk}>)=O~3u}({bj134pH=`nJ_sT$gcC55BmJoYW+{SY2k7%)i^B7>zByqP zg=@6h4ZQRUP48d;ce>V$fM9P)RM-S{DIU14RjC}0_wk{7$strlG|~;t zOEuD&f;+e=DZ70Qt%}gp_5aV~W$<%a-(D?`0TwsS5758H#@>h^<}D*r@Wy--Ba+8> zr|ONeO@ZqyA8u3R0+XoS=xm0e1J7Ydn}KaA{$X-%8)XZRfa60deq=v8EBCEku(#7$ znr}syHQGef;BF(6tlh^-&Dl!=W-}_Cx>^37b7s5DuZ3;1TlAAr9Ncposdi5L1sjJ$ z|F7c6Pm=^I4ARhFlf)Gj1&~(v#XzF)!wmrC`gIbZi3*@jWc^l%il`|IjZ!1x~@9x&Cyw0mGHXWN=8z5 zYJb>?66C3_ID%P}zdePf|DDgbfT)i5n-h0Hx%h|e#`Rz6(ZR7eNs>A-H|H;q^hhe9 zX^N(#{bnNkcceDlPB~r1;?U7C?Z=ONId)PJX%w^|2mtIo1W{s1?q*_1C}3ct zJ2PU5U`8Q$L_DZ&Q_`OY{c2Dl`A4_?qWtfZ^h`qBDZ6VhYWga!={n*51MPZ^y00}C z&>3%PPTRiPUBck&C8cW+ZeO=*2=1x5t0~pw)2VYflrfYW8Zf289|pAPGo{k^$|wN$ z?Wt{m#xFHebBQdKK3H?9k^auFrjpJ`%_=;2{}Xle>}I8;0o3DiT&?xExQ)d}K#R1v zwY4&DYnSrrg1&<7OWmD->^u2F*QH%rkk}gOmxlnTvr5$g9qHRe*S!4(sLvTL66kYo zyqz19qqoaGY->x!aAGEQvZjG*fvv*wC>P>zY zSbuMwA;z~v=2dZkV4o$VUS5Xb@lBdeV#IbWA&7cywGIXsFbw$T8-Q*+wH9?`IyJJ| zpLuU@+?QF%5C1rkCW<`Vc%rzHAbP+HAE(wLYV2}`Nv7dxMoTZeX%MDEJvZiDuHu0# zTI#d;aBo=o8=D+qbxqfhrZms8?bZ_9?~JXjymB`whvIHxIcjzBG;SL|v};p}3sw)% z02Ma@8X%~3C)h1phqdzaf-kguKf6GMjeY?eQ{IJxe>Dwno!6QM?RoPLSp)9iO$=8v zot57>Sobh==ZAf7u%TL6dV;~25HNIcMqc`a5sOCNVe8`HeCrclzp=rF+8cH<@PmI# z{t2fvhX-;~7bmqUx5H*%jB;gaqy;$>@H8E6pf$3E^;ITP@Ngc|T8dtmov$y;DHgy3 zt#Y*PaM^S_Wm5u_P2SMih62Q($+EbXc;#;Lv;r!c$ZVZFCH$1zLHRyRd zD~8v`_|PHAF_tj+OTv~Zq??+tDqB-mwUV4P6ly|0j%`*1Ev3}DP=%MHtG)4^BBd?@ z%^eDZ648_)F89!sUweFkR^KYWt;3R*1J_94H0x>9;!brhiB}z~WG6Up4?4|u)#+r; z%{t3Uxsa3>IWGVv<=NBfPG8jgvcE|KCgr#abi@~3%8%0D$dh7L)rEwD_|~-_dBVHX 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 Date: Fri, 1 Mar 2013 17:37:05 +0000 Subject: [PATCH 29/81] revert previous commit r5578. Didn't work as expected on CG and didn't solve radeon driver issue neither. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5579 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/zzogl-pg/opengl/ZZoglCreate.cpp | 6 ++---- plugins/zzogl-pg/opengl/ps2hw.dat | Bin 112769 -> 113923 bytes plugins/zzogl-pg/opengl/ps2hw.fx | 12 ++++++------ plugins/zzogl-pg/opengl/ps2hw.glsl | 12 ++++++------ plugins/zzogl-pg/opengl/ps2hw_gl4.glsl | 12 ++++++------ 5 files changed, 20 insertions(+), 22 deletions(-) diff --git a/plugins/zzogl-pg/opengl/ZZoglCreate.cpp b/plugins/zzogl-pg/opengl/ZZoglCreate.cpp index b481b0e77..caa46e8f1 100644 --- a/plugins/zzogl-pg/opengl/ZZoglCreate.cpp +++ b/plugins/zzogl-pg/opengl/ZZoglCreate.cpp @@ -417,7 +417,7 @@ void LoadglFunctions() inline bool TryBlockFormat(GLint fmt, const GLvoid* vBlockData) { g_internalFloatFmt = fmt; - glTexImage2D(GL_TEXTURE_2D, 0, g_internalFloatFmt, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, GL_RED, GL_FLOAT, vBlockData); + glTexImage2D(GL_TEXTURE_2D, 0, g_internalFloatFmt, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, GL_ALPHA, GL_FLOAT, vBlockData); return (glGetError() == GL_NO_ERROR); } @@ -611,10 +611,8 @@ bool ZZCreate(int _width, int _height) // 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. - - // Note: GL_ALPHA was dropped in GL3.0 in favor of GL_RED ... Time to upgrade -- gregory - glTexImage2D(GL_TEXTURE_2D, 0, g_internalFloatFmt, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, GL_RED, GL_UNSIGNED_SHORT, &vBlockData[0]); + 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; diff --git a/plugins/zzogl-pg/opengl/ps2hw.dat b/plugins/zzogl-pg/opengl/ps2hw.dat index 47e82b7c5a347db92b8d3716e3e8809c7e436850..2d3b43cae0cdc3de4925148f558b574b9dd1d7ea 100644 GIT binary patch literal 113923 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%0D$dh7L)rEwD_|~-_dBVHX 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 ` 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 bfo43Tr9Q>IF^RKfG{i3d7y0^Yx%K}5_TOe% diff --git a/plugins/zzogl-pg/opengl/ps2hw.fx b/plugins/zzogl-pg/opengl/ps2hw.fx index b0b878c31..0965c3adc 100644 --- a/plugins/zzogl-pg/opengl/ps2hw.fx +++ b/plugins/zzogl-pg/opengl/ps2hw.fx @@ -96,7 +96,7 @@ float2 ps2memcoord(float2 realtex) off.xy = realtex.xy-fblock.xy; #ifdef ACCURATE_DECOMPRESSION - off.z = tex2D(g_sBlocks, g_fTexBlock.xy*fblock + g_fTexBlock.zw).r; + off.zw = tex2D(g_sBlocks, g_fTexBlock.xy*fblock + g_fTexBlock.zw).ar; off.x = dot(off.xy, g_fTexOffset.xy); float r = g_fTexOffset.w; float f = frac(off.x); @@ -105,7 +105,7 @@ float2 ps2memcoord(float2 realtex) off.x = frac(f + fadd + r); off.w -= off.x ; #else - off.z = tex2D(g_sBlocks, g_fTexBlock.xy*fblock + g_fTexBlock.zw).r; + off.z = tex2D(g_sBlocks, g_fTexBlock.xy*fblock + g_fTexBlock.zw).a; // combine the two off.x = dot(off.xyz, g_fTexOffset.xyz)+g_fTexOffset.w; @@ -135,10 +135,10 @@ void ps2memcoord4(float4 orgtex, out float4 off0, out float4 off1) float4 colors;// = tex2D(g_sBilinearBlocks, ftransblock.xy); // this is faster on ffx ingame - colors.x = tex2D(g_sBlocks, ftransblock.xy).r; - colors.y = tex2D(g_sBlocks, ftransblock.zy).r; - colors.z = tex2D(g_sBlocks, ftransblock.xw).r; - colors.w = tex2D(g_sBlocks, ftransblock.zw).r; + colors.x = tex2D(g_sBlocks, ftransblock.xy).a; + colors.y = tex2D(g_sBlocks, ftransblock.zy).a; + colors.z = tex2D(g_sBlocks, ftransblock.xw).a; + colors.w = tex2D(g_sBlocks, ftransblock.zw).a; float4 fr, rem; diff --git a/plugins/zzogl-pg/opengl/ps2hw.glsl b/plugins/zzogl-pg/opengl/ps2hw.glsl index 4cd47f66b..2e48e8caf 100644 --- a/plugins/zzogl-pg/opengl/ps2hw.glsl +++ b/plugins/zzogl-pg/opengl/ps2hw.glsl @@ -141,7 +141,7 @@ float2 ps2memcoord(float2 realtex) off.xy = realtex.xy-fblock.xy; #ifdef ACCURATE_DECOMPRESSION - off.z = texture(g_sBlocks, g_fTexBlock[CTX].xy*fblock + g_fTexBlock[CTX].zw).r; + off.zw = texture(g_sBlocks, g_fTexBlock[CTX].xy*fblock + g_fTexBlock[CTX].zw).ar; off.x = dot(off.xy, g_fTexOffset[CTX].xy); float r = g_fTexOffset[CTX].w; float f = fract(off.x); @@ -150,7 +150,7 @@ float2 ps2memcoord(float2 realtex) off.x = fract(f + fadd + r); off.w -= off.x ; #else - off.z = texture(g_sBlocks, g_fTexBlock[CTX].xy*fblock + g_fTexBlock[CTX].zw).r; + off.z = texture(g_sBlocks, g_fTexBlock[CTX].xy*fblock + g_fTexBlock[CTX].zw).a; // combine the two off.x = dot(off.xyz, g_fTexOffset[CTX].xyz)+g_fTexOffset[CTX].w; @@ -180,10 +180,10 @@ void ps2memcoord4(float4 orgtex, out float4 off0, out float4 off1) float4 colors;// = texture(g_sBilinearBlocks, ftransblock.xy); // this is faster on ffx ingame - colors.x = texture(g_sBlocks, ftransblock.xy).r; - colors.y = texture(g_sBlocks, ftransblock.zy).r; - colors.z = texture(g_sBlocks, ftransblock.xw).r; - colors.w = texture(g_sBlocks, ftransblock.zw).r; + colors.x = texture(g_sBlocks, ftransblock.xy).a; + colors.y = texture(g_sBlocks, ftransblock.zy).a; + colors.z = texture(g_sBlocks, ftransblock.xw).a; + colors.w = texture(g_sBlocks, ftransblock.zw).a; float4 fr, rem; diff --git a/plugins/zzogl-pg/opengl/ps2hw_gl4.glsl b/plugins/zzogl-pg/opengl/ps2hw_gl4.glsl index 8227dae51..f69dea94d 100644 --- a/plugins/zzogl-pg/opengl/ps2hw_gl4.glsl +++ b/plugins/zzogl-pg/opengl/ps2hw_gl4.glsl @@ -193,7 +193,7 @@ float2 ps2memcoord(float2 realtex) off.xy = realtex.xy-fblock.xy; #ifdef ACCURATE_DECOMPRESSION - off.z = texture(g_sBlocks, g_fTexBlock.xy*fblock + g_fTexBlock.zw).r; + off.zw = texture(g_sBlocks, g_fTexBlock.xy*fblock + g_fTexBlock.zw).ar; off.x = dot(off.xy, g_fTexOffset.xy); float r = g_fTexOffset.w; float f = fract(off.x); @@ -202,7 +202,7 @@ float2 ps2memcoord(float2 realtex) off.x = fract(f + fadd + r); off.w -= off.x ; #else - off.z = texture(g_sBlocks, g_fTexBlock.xy*fblock + g_fTexBlock.zw).r; + off.z = texture(g_sBlocks, g_fTexBlock.xy*fblock + g_fTexBlock.zw).a; // combine the two off.x = dot(off.xyz, g_fTexOffset.xyz)+g_fTexOffset.w; @@ -232,10 +232,10 @@ void ps2memcoord4(float4 orgtex, out float4 off0, out float4 off1) float4 colors;// = texture(g_sBilinearBlocks, ftransblock.xy); // this is faster on ffx ingame - colors.x = texture(g_sBlocks, ftransblock.xy).r; - colors.y = texture(g_sBlocks, ftransblock.zy).r; - colors.z = texture(g_sBlocks, ftransblock.xw).r; - colors.w = texture(g_sBlocks, ftransblock.zw).r; + colors.x = texture(g_sBlocks, ftransblock.xy).a; + colors.y = texture(g_sBlocks, ftransblock.zy).a; + colors.z = texture(g_sBlocks, ftransblock.xw).a; + colors.w = texture(g_sBlocks, ftransblock.zw).a; float4 fr, rem; From fd7b16364314c13952cee868bb3c1f54bcbcce9f Mon Sep 17 00:00:00 2001 From: "ramapcsx2.code" Date: Sat, 2 Mar 2013 11:51:14 +0000 Subject: [PATCH 30/81] GSdx: Committing a fix for the Steambot Chronicles hack, thanks miseru99. Also: using a new alias, yay :p git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5580 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSSettingsDlg.cpp | 3 ++- plugins/GSdx/GSState.cpp | 28 +++++++++++++++------------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/plugins/GSdx/GSSettingsDlg.cpp b/plugins/GSdx/GSSettingsDlg.cpp index b93aef9a1..b2413f01d 100644 --- a/plugins/GSdx/GSSettingsDlg.cpp +++ b/plugins/GSdx/GSSettingsDlg.cpp @@ -588,7 +588,8 @@ bool GSHacksDlg::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) case IDC_AGGRESSIVECRC: helpstr = "Use more aggressive CRC hacks on some games\n\n" "Only affects few games, removing some effects which might make the image sharper/clearer.\n" - "Affected games: FFX, FFX2, FFXII, GOW2, ICO, SoTC, SSX3."; + "Affected games: FFX, FFX2, FFXII, GOW2, ICO, SoTC, SSX3.\n" + "Works as a speedhack for: Steambot Chronicles."; break; case IDC_ALPHASTENCIL: helpstr = "Extend stencil based emulation of destination alpha to perform stencil operations while drawing.\n\n" diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index eef0ec79a..093b2ec81 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -5042,23 +5042,25 @@ bool GSC_UrbanReign(const GSFrameInfo& fi, int& skip) bool GSC_SteambotChronicles(const GSFrameInfo& fi, int& skip) { - // Author: miseru99 on forums.pcsx2.net - if(fi.TME && fi.TPSM == PSM_PSMCT16S) + if(skip == 0) { - if(fi.FBP == 0x1180) + // Author: miseru99 on forums.pcsx2.net + if(fi.TME && fi.TPSM == PSM_PSMCT16S) { - skip=1;//1 deletes some of the glitched effects - } - else if(fi.FBP == 0) - { - skip=100;//deletes most others(too high deletes the buggy sea completely;c, too low causes glitches to be visible) - } - else if(g_aggressive && fi.FBP != 0)//Agressive CRC - { - skip=19;//"speedhack", makes the game very light, vaporized water can disappear when not looked at directly, possibly some interface still, other value to try: 6 breaks menu background, possibly nothing(?) during gameplay, but it's slower, hence not much of a speedhack anymore + if(fi.FBP == 0x1180) + { + skip=1;//1 deletes some of the glitched effects + } + else if(fi.FBP == 0) + { + skip=100;//deletes most others(too high deletes the buggy sea completely;c, too low causes glitches to be visible) + } + else if(g_aggressive && fi.FBP != 0)//Agressive CRC + { + skip=19;//"speedhack", makes the game very light, vaporized water can disappear when not looked at directly, possibly some interface still, other value to try: 6 breaks menu background, possibly nothing(?) during gameplay, but it's slower, hence not much of a speedhack anymore + } } } - return true; } From 2ae4c62a414664ef1323f8dc485c26eda4406fdf Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Tue, 5 Mar 2013 12:38:22 +0000 Subject: [PATCH 31/81] cmake: update wx-config option order for fedora git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5581 96395faa-99c1-11dd-bbfe-3dabce05a288 --- cmake/SearchForStuff.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/SearchForStuff.cmake b/cmake/SearchForStuff.cmake index e96395fee..a39d1858f 100644 --- a/cmake/SearchForStuff.cmake +++ b/cmake/SearchForStuff.cmake @@ -40,9 +40,9 @@ find_package(Subversion) # Warning do not put any double-quote for the argument... # set(wxWidgets_CONFIG_OPTIONS --unicode=yes --debug=yes) # In case someone want to debug inside wx # -# Fedora uses an extra non-standard option ... +# Fedora uses an extra non-standard option ... Arch must be the first option. if(Fedora) - set(wxWidgets_CONFIG_OPTIONS --unicode=yes --arch i686) + set(wxWidgets_CONFIG_OPTIONS --arch i686 --unicode=yes) else() set(wxWidgets_CONFIG_OPTIONS --unicode=yes) endif() From 2e363b376eef99bc6e2797c1c9cc8bbbfaa874d9 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Fri, 8 Mar 2013 15:24:30 +0000 Subject: [PATCH 32/81] CDVD: Corrected logging output for sector being read for DVD/CD reads. It was reporting the sector it was currently at, not the one it was actually reading. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5582 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/CDVD/CDVD.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pcsx2/CDVD/CDVD.cpp b/pcsx2/CDVD/CDVD.cpp index f0b531d42..3647c6733 100644 --- a/pcsx2/CDVD/CDVD.cpp +++ b/pcsx2/CDVD/CDVD.cpp @@ -1209,12 +1209,12 @@ static void cdvdWrite04(u8 rt) { // NCOMMAND default: cdvd.ReadMode = CDVD_MODE_2048; cdvd.BlockSize = 2048; break; } - CDVD_LOG( "CdRead > startSector=%d, nSectors=%d, RetryCnt=%x, Speed=%x(%x), ReadMode=%x(%x) (1074=%x)", - cdvd.Sector, cdvd.nSectors, cdvd.RetryCnt, cdvd.Speed, cdvd.Param[9], cdvd.ReadMode, cdvd.Param[10], psxHu32(0x1074)); + CDVD_LOG( "CdRead > startSector=%d, seekTo=%d, nSectors=%d, RetryCnt=%x, Speed=%x(%x), ReadMode=%x(%x) (1074=%x)", + cdvd.Sector, cdvd.SeekToSector, cdvd.nSectors, cdvd.RetryCnt, cdvd.Speed, cdvd.Param[9], cdvd.ReadMode, cdvd.Param[10], psxHu32(0x1074)); if( EmuConfig.CdvdVerboseReads ) Console.WriteLn( Color_Gray, L"CdRead: Reading Sector %d(%d Blocks of Size %d) at Speed=%dx", - cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed); + cdvd.SeekToSector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed); cdvd.ReadTime = cdvdBlockReadTime( MODE_CDROM ); CDVDREAD_INT( cdvdStartSeek( cdvd.SeekToSector,MODE_CDROM ) ); @@ -1293,12 +1293,12 @@ static void cdvdWrite04(u8 rt) { // NCOMMAND cdvd.ReadMode = CDVD_MODE_2048; cdvd.BlockSize = 2064; // Why oh why was it 2064 - CDVD_LOG( "DvdRead > startSector=%d, nSectors=%d, RetryCnt=%x, Speed=%x(%x), ReadMode=%x(%x) (1074=%x)", - cdvd.Sector, cdvd.nSectors, cdvd.RetryCnt, cdvd.Speed, cdvd.Param[9], cdvd.ReadMode, cdvd.Param[10], psxHu32(0x1074)); + CDVD_LOG( "DvdRead > startSector=%d, seekTo=%d nSectors=%d, RetryCnt=%x, Speed=%x(%x), ReadMode=%x(%x) (1074=%x)", + cdvd.Sector, cdvd.SeekToSector, cdvd.nSectors, cdvd.RetryCnt, cdvd.Speed, cdvd.Param[9], cdvd.ReadMode, cdvd.Param[10], psxHu32(0x1074)); if( EmuConfig.CdvdVerboseReads ) Console.WriteLn( Color_Gray, L"DvdRead: Reading Sector %d(%d Blocks of Size %d) at Speed=%dx", - cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed); + cdvd.SeekToSector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed); cdvd.ReadTime = cdvdBlockReadTime( MODE_DVDROM ); CDVDREAD_INT( cdvdStartSeek( cdvd.SeekToSector, MODE_DVDROM ) ); From 8d0f6701b7cca96e544e2042b0472d0d43f4d2a0 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Sat, 9 Mar 2013 11:03:59 +0000 Subject: [PATCH 33/81] microVU/VU Int: Implemented T-Bit/D-Bit handling on microVU. -Dreamworks Over The Hedge actually requires this to load. Interpreter kind of had it right, but didn't stop the VU on these flags, causing the graphics to look bad and hang on the start button, works fine now. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5583 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/Dmac.h | 2 +- pcsx2/Hw.cpp | 3 ++- pcsx2/VU0microInterp.cpp | 2 ++ pcsx2/VU1microInterp.cpp | 2 ++ pcsx2/x86/microVU_Compile.inl | 28 ++++++++++++++++++++++++++-- pcsx2/x86/microVU_IR.h | 2 ++ 6 files changed, 35 insertions(+), 4 deletions(-) diff --git a/pcsx2/Dmac.h b/pcsx2/Dmac.h index 9dededbe0..1a3df3728 100644 --- a/pcsx2/Dmac.h +++ b/pcsx2/Dmac.h @@ -553,7 +553,7 @@ extern void setDmacStat(u32 num); extern tDMA_TAG *SPRdmaGetAddr(u32 addr, bool write); extern tDMA_TAG *dmaGetAddr(u32 addr, bool write); -extern void hwIntcIrq(int n); +extern void __fastcall hwIntcIrq(int n); extern void hwDmacIrq(int n); extern void FireMFIFOEmpty(); diff --git a/pcsx2/Hw.cpp b/pcsx2/Hw.cpp index bcfca1fc7..55a03a7ea 100644 --- a/pcsx2/Hw.cpp +++ b/pcsx2/Hw.cpp @@ -129,7 +129,8 @@ __fi uint dmacInterrupt() return 0x800; } -void hwIntcIrq(int n) +//Fastcall required for VU recompilers. Test Over the Hedge when changing. +void __fastcall hwIntcIrq(int n) { psHu32(INTC_STAT) |= 1<ebit = 1; } if (ptr[1] & 0x08000000) { /* T flag */ if (VU0.VI[REG_FBRST].UL & 0x8) { VU0.VI[REG_VPU_STAT].UL|= 0x4; hwIntcIrq(INTC_VU0); } + VU->ebit = 1; } VU->code = ptr[1]; diff --git a/pcsx2/VU1microInterp.cpp b/pcsx2/VU1microInterp.cpp index 3ddfec751..2edb5fb73 100644 --- a/pcsx2/VU1microInterp.cpp +++ b/pcsx2/VU1microInterp.cpp @@ -60,12 +60,14 @@ static void _vu1Exec(VURegs* VU) VU0.VI[REG_VPU_STAT].UL|= 0x200; hwIntcIrq(INTC_VU1); } + VU->ebit = 1; } if (ptr[1] & 0x08000000) { /* T flag */ if (VU0.VI[REG_FBRST].UL & 0x800) { VU0.VI[REG_VPU_STAT].UL|= 0x400; hwIntcIrq(INTC_VU1); } + VU->ebit = 1; } //VUM_LOG("VU->cycle = %d (flags st=%x;mac=%x;clip=%x,q=%f)", VU->cycle, VU->statusflag, VU->macflag, VU->clipflag, VU->q.F); diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index 383b991b6..7a5e2e1fc 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -479,6 +479,26 @@ void* mVUcompileSingleInstruction(microVU& mVU, u32 startPC, uptr pState, microF return thisPtr; } +void mVUDoDBit(microVU& mVU) +{ + xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4)); + xForwardJump32 eJMP(Jcc_Zero); + xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x200 : 0x2)); + xMOV( gprT2, (isVU1 ? 7 : 6)); + xCALL( hwIntcIrq ); + eJMP.SetTarget(); +} + +void mVUDoTBit(microVU& mVU) +{ + xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x800 : 0x8)); + xForwardJump32 eJMP(Jcc_Zero); + xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x400 : 0x4)); + xMOV( gprT2, (isVU1 ? 7 : 6)); + xCALL( hwIntcIrq ); + eJMP.SetTarget(); +} + void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) { microFlagCycles mFC; @@ -498,8 +518,9 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) { mVUopU(mVU, 0); mVUcheckBadOp(mVU); if (curI & _Ebit_) { eBitPass1(mVU, branch); } - if (curI & _DTbit_) { branch = 4; } + if (curI & _Dbit_) { mVUup.dBit = 1; branch = 2; } if (curI & _Mbit_) { mVUup.mBit = 1; } + if (curI & _Tbit_) { mVUup.tBit = 1; branch = 2; } if (curI & _Ibit_) { mVUlow.isNOP = 1; mVUup.iBit = 1; } else { incPC(-1); mVUopL(mVU, 0); incPC(1); } mVUsetCycles(mVU); @@ -554,7 +575,10 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) { } } if ((x == endCount) && (x!=1)) { Console.Error("microVU%d: Possible infinite compiling loop!", mVU.index); } - + incPC(-1); + if(mVUup.tBit) mVUDoTBit(mVU); + if(mVUup.dBit) mVUDoDBit(mVU); + incPC(1); // E-bit End mVUsetupRange(mVU, xPC-8, 0); mVUendProgram(mVU, &mFC, 1); diff --git a/pcsx2/x86/microVU_IR.h b/pcsx2/x86/microVU_IR.h index ef7c24fef..5f045d6b1 100644 --- a/pcsx2/x86/microVU_IR.h +++ b/pcsx2/x86/microVU_IR.h @@ -112,6 +112,8 @@ struct microUpperOp { bool eBit; // Has E-bit set bool iBit; // Has I-bit set bool mBit; // Has M-bit set + bool tBit; // Has T-bit set + bool dBit; // Has D-bit set microVFreg VF_write; // VF Vectors written to by this instruction microVFreg VF_read[2]; // VF Vectors read by this instruction }; From e8b09949f87164e477a49c04b5159d4de538e45e Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Sun, 10 Mar 2013 23:24:00 +0000 Subject: [PATCH 34/81] MFIFO: Just over the top of the ring buffer is not classed as in the buffer (reaching the top is masked anyway). Fixes DDR X and Supernova games. Bug was introduced between r4034 and r4039. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5584 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/Gif.cpp | 2 +- pcsx2/Vif1_MFIFO.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pcsx2/Gif.cpp b/pcsx2/Gif.cpp index 695c70d28..6fbfedee5 100644 --- a/pcsx2/Gif.cpp +++ b/pcsx2/Gif.cpp @@ -360,7 +360,7 @@ static __fi bool mfifoGIFchain() if (gifch.qwc == 0) return true; if (gifch.madr >= dmacRegs.rbor.ADDR && - gifch.madr <=(dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16)) + gifch.madr < (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16)) { bool ret = true; // if(gifch.madr == (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16)) DevCon.Warning("Edge GIF"); diff --git a/pcsx2/Vif1_MFIFO.cpp b/pcsx2/Vif1_MFIFO.cpp index 68c94afec..8f93d17c3 100644 --- a/pcsx2/Vif1_MFIFO.cpp +++ b/pcsx2/Vif1_MFIFO.cpp @@ -116,7 +116,7 @@ static __fi void mfifo_VIF1chain() } if (vif1ch.madr >= dmacRegs.rbor.ADDR && - vif1ch.madr <= (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16)) + vif1ch.madr < (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16)) { //if(vif1ch.madr == (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16)) DevCon.Warning("Edge VIF1"); From b7d28572a292222992d9a544bc18525e1cb58d87 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Mon, 11 Mar 2013 16:02:56 +0000 Subject: [PATCH 35/81] MFIFO: Added protection on MADR when it is on the edge of the ring buffer when setting the DMA Tag where the data follows the Tag. Fixes Front Mission 4. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5585 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/Gif.cpp | 30 +++++++++++++++++++++++++++++- pcsx2/Vif1_MFIFO.cpp | 28 ++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/pcsx2/Gif.cpp b/pcsx2/Gif.cpp index 6fbfedee5..5d7c26bfa 100644 --- a/pcsx2/Gif.cpp +++ b/pcsx2/Gif.cpp @@ -360,7 +360,7 @@ static __fi bool mfifoGIFchain() if (gifch.qwc == 0) return true; if (gifch.madr >= dmacRegs.rbor.ADDR && - gifch.madr < (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16)) + gifch.madr <= (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16)) { bool ret = true; // if(gifch.madr == (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16)) DevCon.Warning("Edge GIF"); @@ -390,6 +390,32 @@ static u32 qwctag(u32 mask) { return (dmacRegs.rbor.ADDR + (mask & dmacRegs.rbsr.RMSK)); } +void mfifoGifMaskMem(int id) +{ + switch (id) { + //These five transfer data following the tag, need to check its within the buffer (Front Mission 4) + case TAG_CNT: + case TAG_NEXT: + case TAG_CALL: + case TAG_RET: + case TAG_END: + if(gifch.madr < dmacRegs.rbor.ADDR) //probably not needed but we will check anyway. + { + //DevCon.Warning("GIF MFIFO MADR below bottom of ring buffer, wrapping GIF MADR = %x Ring Bottom %x", gifch.madr, dmacRegs.rbor.ADDR); + gifch.madr = qwctag(gifch.madr); + } + if(gifch.madr > (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK)) //Usual scenario is the tag is near the end (Front Mission 4) + { + //DevCon.Warning("GIF MFIFO MADR outside top of ring buffer, wrapping GIF MADR = %x Ring Top %x", gifch.madr, (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK)+16); + gifch.madr = qwctag(gifch.madr); + } + break; + default: + //Do nothing as the MADR could be outside + break; + } +} + void mfifoGIFtransfer(int qwc) { tDMA_TAG *ptag; @@ -426,6 +452,8 @@ void mfifoGIFtransfer(int qwc) gspath3done = hwDmacSrcChainWithStack(gifch, ptag->ID); + mfifoGifMaskMem(ptag->ID); + if(gspath3done == true) gifstate = GIF_STATE_DONE; else gifstate = GIF_STATE_READY; diff --git a/pcsx2/Vif1_MFIFO.cpp b/pcsx2/Vif1_MFIFO.cpp index 8f93d17c3..65eb9d5f1 100644 --- a/pcsx2/Vif1_MFIFO.cpp +++ b/pcsx2/Vif1_MFIFO.cpp @@ -145,6 +145,32 @@ static __fi void mfifo_VIF1chain() } } +void mfifoVifMaskMem(int id) +{ + switch (id) { + //These five transfer data following the tag, need to check its within the buffer (Front Mission 4) + case TAG_CNT: + case TAG_NEXT: + case TAG_CALL: + case TAG_RET: + case TAG_END: + if(vif1ch.madr < dmacRegs.rbor.ADDR) //probably not needed but we will check anyway. + { + //DevCon.Warning("VIF MFIFO MADR below bottom of ring buffer, wrapping VIF MADR = %x Ring Bottom %x", vif1ch.madr, dmacRegs.rbor.ADDR); + vif1ch.madr = qwctag(vif1ch.madr); + } + if(vif1ch.madr > (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK)) //Usual scenario is the tag is near the end (Front Mission 4) + { + //DevCon.Warning("VIF MFIFO MADR outside top of ring buffer, wrapping VIF MADR = %x Ring Top %x", vif1ch.madr, (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK)+16); + vif1ch.madr = qwctag(vif1ch.madr); + } + break; + default: + //Do nothing as the MADR could be outside + break; + } +} + void mfifoVIF1transfer(int qwc) { tDMA_TAG *ptag; @@ -223,6 +249,8 @@ void mfifoVIF1transfer(int qwc) vif1.done |= hwDmacSrcChainWithStack(vif1ch, ptag->ID); + mfifoVifMaskMem(ptag->ID); + if (vif1ch.chcr.TIE && ptag->IRQ) { VIF_LOG("dmaIrq Set"); From c81eab917e60cde91f1bda0ce2350fc3d7f8781e Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Mon, 11 Mar 2013 16:36:32 +0000 Subject: [PATCH 36/81] microVU: T/D Bit handling. Improved it so it doesn't kill the BIOS. Also adjusted the bios bug handling, there were reports of our new handling breaking a game called Triggerheart Excelica Enhanced, hopefully this should make it work again. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5586 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/x86/microVU_Compile.inl | 36 +++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index 7a5e2e1fc..28b391c88 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -160,16 +160,15 @@ void mVUexecuteInstruction(mV) { // If 1st op in block is a bad opcode, then don't compile rest of block (Dawn of Mana Level 2) __fi void mVUcheckBadOp(mV) { - if (mVUinfo.isBadOp) { - mVUinfo.isEOB = true; - // The BIOS writes upper and lower NOPs in reversed slots (bug) - //So to prevent spamming we ignore these, however its possible the real VU will bomb out if - //this happens, so we will bomb out without warning. - if(mVU.code != 0x8000033c) - DevCon.Warning("microVU Warning: Block contains an illegal opcode..."); - else - mVUinfo.isBadOp = false; //End quietly + // The BIOS writes upper and lower NOPs in reversed slots (bug) + //So to prevent spamming we ignore these, however its possible the real VU will bomb out if + //this happens, so we will bomb out without warning. + if (mVUinfo.isBadOp && mVU.code != 0x8000033c) { + + mVUinfo.isEOB = true; + DevCon.Warning("microVU Warning: Block contains an illegal opcode..."); + } } @@ -479,23 +478,31 @@ void* mVUcompileSingleInstruction(microVU& mVU, u32 startPC, uptr pState, microF return thisPtr; } -void mVUDoDBit(microVU& mVU) +void mVUDoDBit(microVU& mVU, microFlagCycles* mFC) { xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4)); xForwardJump32 eJMP(Jcc_Zero); xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x200 : 0x2)); xMOV( gprT2, (isVU1 ? 7 : 6)); xCALL( hwIntcIrq ); + mVUendProgram(mVU, mFC, 2); + xMOV(gprT1, ptr32[&mVU.branch]); + xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT1); + xJMP(mVU.exitFunct); eJMP.SetTarget(); } -void mVUDoTBit(microVU& mVU) +void mVUDoTBit(microVU& mVU, microFlagCycles* mFC) { xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x800 : 0x8)); xForwardJump32 eJMP(Jcc_Zero); xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x400 : 0x4)); xMOV( gprT2, (isVU1 ? 7 : 6)); xCALL( hwIntcIrq ); + mVUendProgram(mVU, mFC, 2); + xMOV(gprT1, ptr32[&mVU.branch]); + xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT1); + xJMP(mVU.exitFunct); eJMP.SetTarget(); } @@ -518,7 +525,7 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) { mVUopU(mVU, 0); mVUcheckBadOp(mVU); if (curI & _Ebit_) { eBitPass1(mVU, branch); } - if (curI & _Dbit_) { mVUup.dBit = 1; branch = 2; } + if (curI & _Dbit_) { mVUup.dBit = 1; } if (curI & _Mbit_) { mVUup.mBit = 1; } if (curI & _Tbit_) { mVUup.tBit = 1; branch = 2; } if (curI & _Ibit_) { mVUlow.isNOP = 1; mVUup.iBit = 1; } @@ -554,6 +561,7 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) { if (mVUinfo.isEOB) { handleBadOp(mVU, x); x = 0xffff; } if (mVUup.mBit) { xOR(ptr32[&mVU.regs().flags], VUFLAG_MFLAGSET); } mVUexecuteInstruction(mVU); + if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); } if (isEvilBlock) { mVUsetupRange(mVU, xPC, 0); normJumpCompile(mVU, mFC, 1); return thisPtr; } else if (!mVUinfo.isBdelay) { incPC(1); } @@ -576,8 +584,8 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) { } if ((x == endCount) && (x!=1)) { Console.Error("microVU%d: Possible infinite compiling loop!", mVU.index); } incPC(-1); - if(mVUup.tBit) mVUDoTBit(mVU); - if(mVUup.dBit) mVUDoDBit(mVU); + if(mVUup.tBit) mVUDoTBit(mVU, &mFC); + if(mVUup.dBit) mVUDoDBit(mVU, &mFC); incPC(1); // E-bit End mVUsetupRange(mVU, xPC-8, 0); From e3fead7f09114094b0673c8eca13b136c79f5261 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Mon, 11 Mar 2013 21:54:05 +0000 Subject: [PATCH 37/81] microVU: - Fixed up the T/D Bit handling properly this time (or at least much better). - Moved the interrupt outside of the recompiled code. VU Interpreter: -Fixed the T/D Bit handling when the interrupt wasn't enabled. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5587 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/Dmac.h | 2 +- pcsx2/Hw.cpp | 3 +- pcsx2/VU.h | 2 +- pcsx2/VU0microInterp.cpp | 6 ++-- pcsx2/VU1microInterp.cpp | 6 ++-- pcsx2/x86/microVU.cpp | 12 ++++++++ pcsx2/x86/microVU_Branch.inl | 56 +++++++++++++++++++++++++++++++++++ pcsx2/x86/microVU_Compile.inl | 40 +++++++++++++------------ pcsx2/x86/microVU_IR.h | 12 ++++++++ 9 files changed, 112 insertions(+), 27 deletions(-) diff --git a/pcsx2/Dmac.h b/pcsx2/Dmac.h index 1a3df3728..9dededbe0 100644 --- a/pcsx2/Dmac.h +++ b/pcsx2/Dmac.h @@ -553,7 +553,7 @@ extern void setDmacStat(u32 num); extern tDMA_TAG *SPRdmaGetAddr(u32 addr, bool write); extern tDMA_TAG *dmaGetAddr(u32 addr, bool write); -extern void __fastcall hwIntcIrq(int n); +extern void hwIntcIrq(int n); extern void hwDmacIrq(int n); extern void FireMFIFOEmpty(); diff --git a/pcsx2/Hw.cpp b/pcsx2/Hw.cpp index 55a03a7ea..bcfca1fc7 100644 --- a/pcsx2/Hw.cpp +++ b/pcsx2/Hw.cpp @@ -129,8 +129,7 @@ __fi uint dmacInterrupt() return 0x800; } -//Fastcall required for VU recompilers. Test Over the Hedge when changing. -void __fastcall hwIntcIrq(int n) +void hwIntcIrq(int n) { psHu32(INTC_STAT) |= 1<ebit = 1; } - VU->ebit = 1; + } if (ptr[1] & 0x08000000) { /* T flag */ if (VU0.VI[REG_FBRST].UL & 0x8) { VU0.VI[REG_VPU_STAT].UL|= 0x4; hwIntcIrq(INTC_VU0); + VU->ebit = 1; } - VU->ebit = 1; + } VU->code = ptr[1]; diff --git a/pcsx2/VU1microInterp.cpp b/pcsx2/VU1microInterp.cpp index 2edb5fb73..c440ac33c 100644 --- a/pcsx2/VU1microInterp.cpp +++ b/pcsx2/VU1microInterp.cpp @@ -59,15 +59,17 @@ static void _vu1Exec(VURegs* VU) if (VU0.VI[REG_FBRST].UL & 0x400) { VU0.VI[REG_VPU_STAT].UL|= 0x200; hwIntcIrq(INTC_VU1); + VU->ebit = 1; } - VU->ebit = 1; + } if (ptr[1] & 0x08000000) { /* T flag */ if (VU0.VI[REG_FBRST].UL & 0x800) { VU0.VI[REG_VPU_STAT].UL|= 0x400; hwIntcIrq(INTC_VU1); + VU->ebit = 1; } - VU->ebit = 1; + } //VUM_LOG("VU->cycle = %d (flags st=%x;mac=%x;clip=%x,q=%f)", VU->cycle, VU->statusflag, VU->macflag, VU->clipflag, VU->q.F); diff --git a/pcsx2/x86/microVU.cpp b/pcsx2/x86/microVU.cpp index 8ec9b1f0f..f88c6be5b 100644 --- a/pcsx2/x86/microVU.cpp +++ b/pcsx2/x86/microVU.cpp @@ -327,6 +327,12 @@ void recMicroVU0::Execute(u32 cycles) { // woody hangs if too high on sVU (untested on mVU) // Edit: Need to test this again, if anyone ever has a "Woody" game :p ((mVUrecCall)microVU0.startFunct)(VU0.VI[REG_TPC].UL, cycles); + + if(microVU0.regs().flags & 0x4) + { + microVU0.regs().flags &= ~0x4; + hwIntcIrq(6); + } } void recMicroVU1::Execute(u32 cycles) { pxAssert(m_Reserved); // please allocate me first! :| @@ -335,6 +341,12 @@ void recMicroVU1::Execute(u32 cycles) { if(!(VU0.VI[REG_VPU_STAT].UL & 0x100)) return; } ((mVUrecCall)microVU1.startFunct)(VU1.VI[REG_TPC].UL, cycles); + + if(microVU1.regs().flags & 0x4) + { + microVU1.regs().flags &= ~0x4; + hwIntcIrq(7); + } } void recMicroVU0::Clear(u32 addr, u32 size) { diff --git a/pcsx2/x86/microVU_Branch.inl b/pcsx2/x86/microVU_Branch.inl index 50c51060c..46cc4ec8c 100644 --- a/pcsx2/x86/microVU_Branch.inl +++ b/pcsx2/x86/microVU_Branch.inl @@ -28,6 +28,62 @@ __fi int getLastFlagInst(microRegInfo& pState, int* xFlag, int flagType, int isE void mVU0clearlpStateJIT() { if (!microVU0.prog.cleared) memzero(microVU0.prog.lpState); } void mVU1clearlpStateJIT() { if (!microVU1.prog.cleared) memzero(microVU1.prog.lpState); } +void mVUDTendProgram(mV, microFlagCycles* mFC, int isEbit) { + + int fStatus = getLastFlagInst(mVUpBlock->pState, mFC->xStatus, 0, isEbit); + int fMac = getLastFlagInst(mVUpBlock->pState, mFC->xMac, 1, isEbit); + int fClip = getLastFlagInst(mVUpBlock->pState, mFC->xClip, 2, isEbit); + int qInst = 0; + int pInst = 0; + mVU.regAlloc->TDwritebackAll(); //Writing back ok, invalidating early kills the rec, so don't do it :P + + if (isEbit) { + memzero(mVUinfo); + memzero(mVUregsTemp); + mVUincCycles(mVU, 100); // Ensures Valid P/Q instances (And sets all cycle data to 0) + mVUcycles -= 100; + qInst = mVU.q; + pInst = mVU.p; + if (mVUinfo.doDivFlag) { + sFLAG.doFlag = 1; + sFLAG.write = fStatus; + mVUdivSet(mVU); + } + if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); } + if (doEarlyExit(mVU)) { + if (!isVU1) xCALL(mVU0clearlpStateJIT); + else xCALL(mVU1clearlpStateJIT); + } + } + + // Save P/Q Regs + if (qInst) { xPSHUF.D(xmmPQ, xmmPQ, 0xe5); } + xMOVSS(ptr32[&mVU.regs().VI[REG_Q].UL], xmmPQ); + if (isVU1) { + xPSHUF.D(xmmPQ, xmmPQ, pInst ? 3 : 2); + xMOVSS(ptr32[&mVU.regs().VI[REG_P].UL], xmmPQ); + } + + // Save Flag Instances + xMOV(ptr32[&mVU.regs().VI[REG_STATUS_FLAG].UL], getFlagReg(fStatus)); + mVUallocMFLAGa(mVU, gprT1, fMac); + mVUallocCFLAGa(mVU, gprT2, fClip); + xMOV(ptr32[&mVU.regs().VI[REG_MAC_FLAG].UL], gprT1); + xMOV(ptr32[&mVU.regs().VI[REG_CLIP_FLAG].UL], gprT2); + + 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 + } + } + + if (isEbit != 2) { // Save PC, and Jump to Exit Point + xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC); + xJMP(mVU.exitFunct); + } +} + void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) { int fStatus = getLastFlagInst(mVUpBlock->pState, mFC->xStatus, 0, isEbit); diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index 28b391c88..b1fad803c 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -480,35 +480,37 @@ void* mVUcompileSingleInstruction(microVU& mVU, u32 startPC, uptr pState, microF void mVUDoDBit(microVU& mVU, microFlagCycles* mFC) { + incPC(2); xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4)); xForwardJump32 eJMP(Jcc_Zero); xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x200 : 0x2)); - xMOV( gprT2, (isVU1 ? 7 : 6)); - xCALL( hwIntcIrq ); - mVUendProgram(mVU, mFC, 2); - xMOV(gprT1, ptr32[&mVU.branch]); - xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT1); - xJMP(mVU.exitFunct); + xOR(ptr32[&mVU.regs().flags], VUFLAG_INTCINTERRUPT); + mVUDTendProgram(mVU, mFC, 1); eJMP.SetTarget(); + incPC(-2); } void mVUDoTBit(microVU& mVU, microFlagCycles* mFC) { + incPC(2); xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x800 : 0x8)); xForwardJump32 eJMP(Jcc_Zero); xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x400 : 0x4)); - xMOV( gprT2, (isVU1 ? 7 : 6)); - xCALL( hwIntcIrq ); - mVUendProgram(mVU, mFC, 2); - xMOV(gprT1, ptr32[&mVU.branch]); - xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT1); - xJMP(mVU.exitFunct); + xOR(ptr32[&mVU.regs().flags], VUFLAG_INTCINTERRUPT); + mVUDTendProgram(mVU, mFC, 1); eJMP.SetTarget(); + incPC(-2); } +void mVUSaveFlags(microVU& mVU,microFlagCycles &mFC, microFlagCycles &mFCBackup) +{ + memcpy_fast(&mFCBackup, &mFC, sizeof(microFlagCycles)); + mVUsetFlags(mVU, mFCBackup); // Sets Up Flag instances +} void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) { microFlagCycles mFC; + microFlagCycles mFCBackup; u8* thisPtr = x86Ptr; const u32 endCount = (((microRegInfo*)pState)->blockType) ? 1 : (mVU.microMemSize / 8); @@ -525,9 +527,9 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) { mVUopU(mVU, 0); mVUcheckBadOp(mVU); if (curI & _Ebit_) { eBitPass1(mVU, branch); } - if (curI & _Dbit_) { mVUup.dBit = 1; } + if (curI & _Dbit_) { mVUup.dBit = 1; mVUsetFlagInfo(mVU); mVUSaveFlags(mVU, mFC, mFCBackup); } if (curI & _Mbit_) { mVUup.mBit = 1; } - if (curI & _Tbit_) { mVUup.tBit = 1; branch = 2; } + if (curI & _Tbit_) { mVUup.tBit = 1; mVUsetFlagInfo(mVU); mVUSaveFlags(mVU, mFC, mFCBackup); } if (curI & _Ibit_) { mVUlow.isNOP = 1; mVUup.iBit = 1; } else { incPC(-1); mVUopL(mVU, 0); incPC(1); } mVUsetCycles(mVU); @@ -561,7 +563,10 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) { if (mVUinfo.isEOB) { handleBadOp(mVU, x); x = 0xffff; } if (mVUup.mBit) { xOR(ptr32[&mVU.regs().flags], VUFLAG_MFLAGSET); } mVUexecuteInstruction(mVU); - + incPC(-1); + if(mVUup.tBit) {mVUDoTBit(mVU, &mFC); } + else if(mVUup.dBit) { mVUDoDBit(mVU, &mFC);} + incPC(1); if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); } if (isEvilBlock) { mVUsetupRange(mVU, xPC, 0); normJumpCompile(mVU, mFC, 1); return thisPtr; } else if (!mVUinfo.isBdelay) { incPC(1); } @@ -583,10 +588,7 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) { } } if ((x == endCount) && (x!=1)) { Console.Error("microVU%d: Possible infinite compiling loop!", mVU.index); } - incPC(-1); - if(mVUup.tBit) mVUDoTBit(mVU, &mFC); - if(mVUup.dBit) mVUDoDBit(mVU, &mFC); - incPC(1); + // E-bit End mVUsetupRange(mVU, xPC-8, 0); mVUendProgram(mVU, &mFC, 1); diff --git a/pcsx2/x86/microVU_IR.h b/pcsx2/x86/microVU_IR.h index 5f045d6b1..2845b39b5 100644 --- a/pcsx2/x86/microVU_IR.h +++ b/pcsx2/x86/microVU_IR.h @@ -259,6 +259,18 @@ public: } } + void TDwritebackAll(bool clearState = 0) { + for(int i = 0; i < xmmTotal; i++) { + microMapXMM& mapX = xmmMap[xmm(i).Id]; + + if ((mapX.VFreg > 0) && mapX.xyzw) { // Reg was modified and not Temp or vf0 + if (mapX.VFreg == 33) xMOVSS(ptr32[&getVI(REG_I)], xmm(i)); + elif (mapX.VFreg == 32) mVUsaveReg(xmm(i), ptr[®s().ACC], mapX.xyzw, 1); + else mVUsaveReg(xmm(i), ptr[&getVF(mapX.VFreg)], mapX.xyzw, 1); + } + } + } + void clearReg(const xmm& reg) { clearReg(reg.Id); } void clearReg(int regId) { microMapXMM& clear = xmmMap[regId]; From ebe1f58cdbe9c9cc5287b5a16b92c378600fe650 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Tue, 12 Mar 2013 20:04:17 +0000 Subject: [PATCH 38/81] GameDB: Corrected Serial number for Ski Alpin 2006, should have been SLES-53867, was SLES-53866 which is actually Over The Hedge. Thanks for spotting that Nik1895 :) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5588 96395faa-99c1-11dd-bbfe-3dabce05a288 --- bin/GameIndex.dbf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/GameIndex.dbf b/bin/GameIndex.dbf index 32d9bf80e..8b19b86fb 100644 --- a/bin/GameIndex.dbf +++ b/bin/GameIndex.dbf @@ -39308,7 +39308,7 @@ Serial = SLES-53866 Name = Over the Hedge Region = PAL-Unk --------------------------------------------- -Serial = SLES-53866 +Serial = SLES-53867 Name = Ski Alpin 2006 Region = PAL-Unk vuClampMode = 2 From 232765f27fe62417a83c43fcb52c6d9006df700a Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Tue, 12 Mar 2013 20:34:16 +0000 Subject: [PATCH 39/81] GameDB: Found and removed 4 more duplicate entries. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5589 96395faa-99c1-11dd-bbfe-3dabce05a288 --- bin/GameIndex.dbf | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/bin/GameIndex.dbf b/bin/GameIndex.dbf index 8b19b86fb..97f0e1f81 100644 --- a/bin/GameIndex.dbf +++ b/bin/GameIndex.dbf @@ -16997,10 +16997,6 @@ Name = Guilty Gear X Plus "By Your Side" Region = NTSC-K Compat = 5 --------------------------------------------- -Serial = SLPM-64549 -Name = Shikigame no Shiro -Region = NTSC-K ---------------------------------------------- Serial = SLPM-65001 Name = Kessen Region = NTSC-J @@ -31145,14 +31141,6 @@ Serial = SLED-53745 Name = Total Overdose [Demo] Region = PAL-M5 --------------------------------------------- -Serial = SLED-53745 -Name = Total Overdose [Demo] -Region = PAL-M5 ---------------------------------------------- -Serial = SLED-53745 -Name = Total Overdose [Demo] -Region = PAL-M5 ---------------------------------------------- Serial = SLED-53845 Name = Matrix - Path of Neo [Demo] Region = PAL-E From 501766d852c08dc26d1c80402af6d94df6c892c0 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Tue, 12 Mar 2013 23:37:50 +0000 Subject: [PATCH 40/81] microVU: T/D Bit on branches fixed, kinda. It's ugly, possibly wrong in places, but it works for known games that fall for this. Fixes VP2. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5590 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/x86/microVU_Compile.inl | 107 ++++++++++++++++++++++++++++++---- 1 file changed, 97 insertions(+), 10 deletions(-) diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index b1fad803c..ad1e63819 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -480,26 +480,111 @@ void* mVUcompileSingleInstruction(microVU& mVU, u32 startPC, uptr pState, microF void mVUDoDBit(microVU& mVU, microFlagCycles* mFC) { - incPC(2); + bool isBranch = false; + JccComparisonType Jcc; + + incPC(2); //Check next slot for branch delay, if not, that's where the VU will resume anyway. + + if(mVUinfo.isBdelay) isBranch = true; + xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4)); xForwardJump32 eJMP(Jcc_Zero); xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x200 : 0x2)); xOR(ptr32[&mVU.regs().flags], VUFLAG_INTCINTERRUPT); - mVUDTendProgram(mVU, mFC, 1); + + if(isBranch) + { + incPC(-2); // Go back to branch opcode + + DevCon.Warning("D Bit on branch"); + mVUDTendProgram(mVU, mFC, 2); + xCMP(ptr16[&mVU.branch], 0); + switch (mVUlow.branch) { + case 1: case 2: Jcc = Jcc_Unconditional; DevCon.Warning("D Bit on B/BAL, might be buggy"); break; // B/BAL + case 9: case 10: DevCon.Warning("JR/JALR probably not supported on D Bit!"); break; // JR/JALR + case 3: Jcc = Jcc_Equal; break; // IBEQ + case 4: Jcc = Jcc_GreaterOrEqual; break; // IBGEZ + case 5: Jcc = Jcc_Greater; break; // IBGTZ + case 6: Jcc = Jcc_LessOrEqual; break; // IBLEQ + case 7: Jcc = Jcc_Less; break; // IBLTZ + case 8: Jcc = Jcc_NotEqual; break; // IBNEQ + } + if(mVUlow.branch < 9) + { + incPC(1); + xForwardJump8 bJMP((JccComparisonType)Jcc); + incPC(1); // Set PC to First instruction of Non-Taken Side + xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC); + xJMP(mVU.exitFunct); + bJMP.SetTarget(); + incPC(-4); // Go Back to Branch Opcode to get branchAddr + iPC = branchAddr/4; + xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC); + } + else + { + xMOV(gprT1, ptr32[&mVU.branch]); + xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT1); + } + xJMP(mVU.exitFunct); + } + else + mVUDTendProgram(mVU, mFC, 1); eJMP.SetTarget(); - incPC(-2); } void mVUDoTBit(microVU& mVU, microFlagCycles* mFC) { - incPC(2); + bool isBranch = false; + JccComparisonType Jcc; + + incPC(2); //Check next slot for branch delay, if not, that's where the VU will resume anyway. + + if(mVUinfo.isBdelay) isBranch = true; + xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x800 : 0x8)); xForwardJump32 eJMP(Jcc_Zero); xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x400 : 0x4)); xOR(ptr32[&mVU.regs().flags], VUFLAG_INTCINTERRUPT); - mVUDTendProgram(mVU, mFC, 1); + if(isBranch) + { + incPC(-2); // Go back to branch opcode + + DevCon.Warning("T Bit on branch"); + mVUDTendProgram(mVU, mFC, 2); + xCMP(ptr16[&mVU.branch], 0); + switch (mVUlow.branch) { + case 1: case 2: Jcc = Jcc_Unconditional; DevCon.Warning("T Bit on B/BAL, might be buggy"); break; // B/BAL + case 9: case 10: DevCon.Warning("JR/JALR probably not supported on T Bit!"); break; // JR/JALR + case 3: Jcc = Jcc_Equal; break; // IBEQ + case 4: Jcc = Jcc_GreaterOrEqual; break; // IBGEZ + case 5: Jcc = Jcc_Greater; break; // IBGTZ + case 6: Jcc = Jcc_LessOrEqual; break; // IBLEQ + case 7: Jcc = Jcc_Less; break; // IBLTZ + case 8: Jcc = Jcc_NotEqual; break; // IBNEQ + } + if(mVUlow.branch < 9) + { + incPC(1); + xForwardJump8 bJMP((JccComparisonType)Jcc); + incPC(1); // Set PC to First instruction of Non-Taken Side + xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC); + xJMP(mVU.exitFunct); + bJMP.SetTarget(); + incPC(-4); // Go Back to Branch Opcode to get branchAddr + iPC = branchAddr/4; + xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC); + } + else + { + xMOV(gprT1, ptr32[&mVU.branch]); + xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT1); + } + xJMP(mVU.exitFunct); + } + else + mVUDTendProgram(mVU, mFC, 1); eJMP.SetTarget(); - incPC(-2); } void mVUSaveFlags(microVU& mVU,microFlagCycles &mFC, microFlagCycles &mFCBackup) @@ -563,10 +648,6 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) { if (mVUinfo.isEOB) { handleBadOp(mVU, x); x = 0xffff; } if (mVUup.mBit) { xOR(ptr32[&mVU.regs().flags], VUFLAG_MFLAGSET); } mVUexecuteInstruction(mVU); - incPC(-1); - if(mVUup.tBit) {mVUDoTBit(mVU, &mFC); } - else if(mVUup.dBit) { mVUDoDBit(mVU, &mFC);} - incPC(1); if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); } if (isEvilBlock) { mVUsetupRange(mVU, xPC, 0); normJumpCompile(mVU, mFC, 1); return thisPtr; } else if (!mVUinfo.isBdelay) { incPC(1); } @@ -586,6 +667,12 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) { case 8: condBranch(mVU, mFC, Jcc_NotEqual); return thisPtr; // IBNEQ } } + + incPC(-2); + if(mVUup.tBit) { mVUDoTBit(mVU, &mFC); } + else if(mVUup.dBit) { mVUDoDBit(mVU, &mFC); } + else incPC(2); + } if ((x == endCount) && (x!=1)) { Console.Error("microVU%d: Possible infinite compiling loop!", mVU.index); } From cba8b0f6e56f108ac68802e23de4b1bc75a76bd4 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Tue, 12 Mar 2013 23:45:13 +0000 Subject: [PATCH 41/81] microVU: Made the new logs mVU logs for Rama <3 git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5591 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/x86/microVU_Compile.inl | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index ad1e63819..4d0e64ddd 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -496,12 +496,12 @@ void mVUDoDBit(microVU& mVU, microFlagCycles* mFC) { incPC(-2); // Go back to branch opcode - DevCon.Warning("D Bit on branch"); + DevCon.Warning("microVU%d: D-Bit on branch [%04x]", getIndex, xPC); mVUDTendProgram(mVU, mFC, 2); xCMP(ptr16[&mVU.branch], 0); switch (mVUlow.branch) { - case 1: case 2: Jcc = Jcc_Unconditional; DevCon.Warning("D Bit on B/BAL, might be buggy"); break; // B/BAL - case 9: case 10: DevCon.Warning("JR/JALR probably not supported on D Bit!"); break; // JR/JALR + case 1: case 2: Jcc = Jcc_Unconditional; DevCon.Warning("microVU%d: D Bit on B/BAL, might be buggy", getIndex); break; // B/BAL + case 9: case 10: DevCon.Warning("microVU%d: JR/JALR probably not supported on D Bit!", getIndex); break; // JR/JALR case 3: Jcc = Jcc_Equal; break; // IBEQ case 4: Jcc = Jcc_GreaterOrEqual; break; // IBGEZ case 5: Jcc = Jcc_Greater; break; // IBGTZ @@ -549,13 +549,12 @@ void mVUDoTBit(microVU& mVU, microFlagCycles* mFC) if(isBranch) { incPC(-2); // Go back to branch opcode - - DevCon.Warning("T Bit on branch"); + DevCon.Warning("microVU%d: T-Bit on branch [%04x]", getIndex, xPC); mVUDTendProgram(mVU, mFC, 2); xCMP(ptr16[&mVU.branch], 0); switch (mVUlow.branch) { - case 1: case 2: Jcc = Jcc_Unconditional; DevCon.Warning("T Bit on B/BAL, might be buggy"); break; // B/BAL - case 9: case 10: DevCon.Warning("JR/JALR probably not supported on T Bit!"); break; // JR/JALR + case 1: case 2: Jcc = Jcc_Unconditional; DevCon.Warning("microVU%d: T Bit on B/BAL, might be buggy", getIndex); break; // B/BAL + case 9: case 10: DevCon.Warning("microVU%d: JR/JALR probably not supported on T Bit!", getIndex); break; // JR/JALR case 3: Jcc = Jcc_Equal; break; // IBEQ case 4: Jcc = Jcc_GreaterOrEqual; break; // IBGEZ case 5: Jcc = Jcc_Greater; break; // IBGTZ From 2ef95df6e1ee79848d56c137734ccb44fa2d62ee Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Wed, 13 Mar 2013 00:51:39 +0000 Subject: [PATCH 42/81] microVU: Another branch delay slot fix. Extreme-G Racing now playable in microVU :) If anybody has Mark of Kri, can you please confirm that's still working okay? I'm expecting it to, but just to be sure. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5592 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/x86/microVU_Lower.inl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pcsx2/x86/microVU_Lower.inl b/pcsx2/x86/microVU_Lower.inl index f44e11501..8f6c848a3 100644 --- a/pcsx2/x86/microVU_Lower.inl +++ b/pcsx2/x86/microVU_Lower.inl @@ -1245,7 +1245,7 @@ void setBranchA(mP, int x, int _x_) { void condEvilBranch(mV, int JMPcc) { if (mVUlow.badBranch) { xMOV(ptr32[&mVU.branch], gprT1); - xMOV(ptr32[&mVU.badBranch], branchAddrN); + xMOV(ptr32[&mVU.badBranch], branchAddr); xCMP(gprT1b, 0); xForwardJump8 cJMP((JccComparisonType)JMPcc); From 31221a29bd3bf87cf838529ebd2f0f8371bdb567 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Wed, 13 Mar 2013 11:26:42 +0000 Subject: [PATCH 43/81] microVU: Save PC when processing T/D bits on branches, this is to ensure the rest of the block gets compiled correctly. Could have been the reason VP2 was freaking out after loading a save. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5593 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/x86/microVU_Compile.inl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index 4d0e64ddd..371f5f867 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -482,8 +482,10 @@ void mVUDoDBit(microVU& mVU, microFlagCycles* mFC) { bool isBranch = false; JccComparisonType Jcc; + u32 savedPC = 0; incPC(2); //Check next slot for branch delay, if not, that's where the VU will resume anyway. + savedPC = iPC; //Save PC as it's about to get modified if it's a branch! if(mVUinfo.isBdelay) isBranch = true; @@ -531,14 +533,17 @@ void mVUDoDBit(microVU& mVU, microFlagCycles* mFC) else mVUDTendProgram(mVU, mFC, 1); eJMP.SetTarget(); + iPC = savedPC; } void mVUDoTBit(microVU& mVU, microFlagCycles* mFC) { bool isBranch = false; JccComparisonType Jcc; + u32 savedPC = 0; incPC(2); //Check next slot for branch delay, if not, that's where the VU will resume anyway. + savedPC = iPC; //Save PC as it's about to get modified if it's a branch! if(mVUinfo.isBdelay) isBranch = true; @@ -584,6 +589,7 @@ void mVUDoTBit(microVU& mVU, microFlagCycles* mFC) else mVUDTendProgram(mVU, mFC, 1); eJMP.SetTarget(); + iPC = savedPC; } void mVUSaveFlags(microVU& mVU,microFlagCycles &mFC, microFlagCycles &mFCBackup) From 6d456b8a6994118737af12575f59a7a01e4d72f3 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Mon, 18 Mar 2013 09:32:41 +0000 Subject: [PATCH 44/81] microVU: T/D Bit cleanup, slightly better code, makes much more sense to how the PS2 does it. Fixed ICO's graphics. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5594 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/x86/microVU_Branch.inl | 99 +++++++++++++++++++++++++-- pcsx2/x86/microVU_Compile.inl | 122 +++++----------------------------- 2 files changed, 112 insertions(+), 109 deletions(-) diff --git a/pcsx2/x86/microVU_Branch.inl b/pcsx2/x86/microVU_Branch.inl index 46cc4ec8c..0de3029ae 100644 --- a/pcsx2/x86/microVU_Branch.inl +++ b/pcsx2/x86/microVU_Branch.inl @@ -38,8 +38,8 @@ void mVUDTendProgram(mV, microFlagCycles* mFC, int isEbit) { mVU.regAlloc->TDwritebackAll(); //Writing back ok, invalidating early kills the rec, so don't do it :P if (isEbit) { - memzero(mVUinfo); - memzero(mVUregsTemp); + /*memzero(mVUinfo); + memzero(mVUregsTemp);*/ mVUincCycles(mVU, 100); // Ensures Valid P/Q instances (And sets all cycle data to 0) mVUcycles -= 100; qInst = mVU.q; @@ -74,7 +74,7 @@ void mVUDTendProgram(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 } } @@ -181,7 +181,31 @@ void normJumpCompile(mV, microFlagCycles& mFC, bool isEvilJump) { void normBranch(mV, microFlagCycles& mFC) { - // E-bit Branch + // E-bit or T-Bit or D-Bit Branch + if (mVUup.dBit) + { + u32 tempPC = iPC; + xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4)); + xForwardJump32 eJMP(Jcc_Zero); + xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x200 : 0x2)); + xOR(ptr32[&mVU.regs().flags], VUFLAG_INTCINTERRUPT); + iPC = branchAddr/4; + mVUDTendProgram(mVU, &mFC, 1); + eJMP.SetTarget(); + iPC = tempPC; + } + if (mVUup.tBit) + { + u32 tempPC = iPC; + xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x800 : 0x8)); + xForwardJump32 eJMP(Jcc_Zero); + xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x400 : 0x4)); + xOR(ptr32[&mVU.regs().flags], VUFLAG_INTCINTERRUPT); + iPC = branchAddr/4; + mVUDTendProgram(mVU, &mFC, 1); + eJMP.SetTarget(); + iPC = tempPC; + } if (mVUup.eBit) { if(mVUlow.badBranch) DevCon.Warning("End on evil Unconditional branch! - Not implemented! - If game broken report to PCSX2 Team"); iPC = branchAddr/4; mVUendProgram(mVU, &mFC, 1); return; } if(mVUlow.badBranch) @@ -247,6 +271,49 @@ void condJumpProcessingEvil(mV, microFlagCycles& mFC, int JMPcc) { } void condBranch(mV, microFlagCycles& mFC, int JMPcc) { mVUsetupBranch(mVU, mFC); + + if (mVUup.tBit) + { + u32 tempPC = iPC; + xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x800 : 0x8)); + xForwardJump32 eJMP(Jcc_Zero); + xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x400 : 0x4)); + xOR(ptr32[&mVU.regs().flags], VUFLAG_INTCINTERRUPT); + mVUDTendProgram(mVU, &mFC, 2); + xCMP(ptr16[&mVU.branch], 0); + xForwardJump8 tJMP((JccComparisonType)JMPcc); + incPC(4); // Set PC to First instruction of Non-Taken Side + xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC); + xJMP(mVU.exitFunct); + eJMP.SetTarget(); + incPC(-4); // Go Back to Branch Opcode to get branchAddr + iPC = branchAddr/4; + xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC); + xJMP(mVU.exitFunct); + tJMP.SetTarget(); + iPC = tempPC; + } + if (mVUup.dBit) + { + u32 tempPC = iPC; + xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4)); + xForwardJump32 eJMP(Jcc_Zero); + xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x200 : 0x2)); + xOR(ptr32[&mVU.regs().flags], VUFLAG_INTCINTERRUPT); + mVUDTendProgram(mVU, &mFC, 2); + xCMP(ptr16[&mVU.branch], 0); + xForwardJump8 dJMP((JccComparisonType)JMPcc); + incPC(4); // Set PC to First instruction of Non-Taken Side + xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC); + xJMP(mVU.exitFunct); + dJMP.SetTarget(); + incPC(-4); // Go Back to Branch Opcode to get branchAddr + iPC = branchAddr/4; + xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC); + xJMP(mVU.exitFunct); + eJMP.SetTarget(); + iPC = tempPC; + } xCMP(ptr16[&mVU.branch], 0); incPC(3); if (mVUup.eBit) { // Conditional Branch With E-Bit Set @@ -331,6 +398,30 @@ void normJump(mV, microFlagCycles& mFC) { } incPC(-3); } + if (mVUup.dBit) + { + xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4)); + xForwardJump32 eJMP(Jcc_Zero); + xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x200 : 0x2)); + xOR(ptr32[&mVU.regs().flags], VUFLAG_INTCINTERRUPT); + mVUDTendProgram(mVU, &mFC, 2); + xMOV(gprT1, ptr32[&mVU.branch]); + xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT1); + xJMP(mVU.exitFunct); + eJMP.SetTarget(); + } + if (mVUup.tBit) + { + xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x800 : 0x8)); + xForwardJump32 eJMP(Jcc_Zero); + xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x400 : 0x4)); + xOR(ptr32[&mVU.regs().flags], VUFLAG_INTCINTERRUPT); + mVUDTendProgram(mVU, &mFC, 2); + xMOV(gprT1, ptr32[&mVU.branch]); + xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT1); + xJMP(mVU.exitFunct); + eJMP.SetTarget(); + } if (mVUup.eBit) { // E-bit Jump mVUendProgram(mVU, &mFC, 2); xMOV(gprT1, ptr32[&mVU.branch]); diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index 371f5f867..74e57bfbe 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -480,116 +480,27 @@ void* mVUcompileSingleInstruction(microVU& mVU, u32 startPC, uptr pState, microF void mVUDoDBit(microVU& mVU, microFlagCycles* mFC) { - bool isBranch = false; - JccComparisonType Jcc; - u32 savedPC = 0; - - incPC(2); //Check next slot for branch delay, if not, that's where the VU will resume anyway. - savedPC = iPC; //Save PC as it's about to get modified if it's a branch! - - if(mVUinfo.isBdelay) isBranch = true; - xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4)); xForwardJump32 eJMP(Jcc_Zero); xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x200 : 0x2)); xOR(ptr32[&mVU.regs().flags], VUFLAG_INTCINTERRUPT); - - if(isBranch) - { - incPC(-2); // Go back to branch opcode - - DevCon.Warning("microVU%d: D-Bit on branch [%04x]", getIndex, xPC); - mVUDTendProgram(mVU, mFC, 2); - xCMP(ptr16[&mVU.branch], 0); - switch (mVUlow.branch) { - case 1: case 2: Jcc = Jcc_Unconditional; DevCon.Warning("microVU%d: D Bit on B/BAL, might be buggy", getIndex); break; // B/BAL - case 9: case 10: DevCon.Warning("microVU%d: JR/JALR probably not supported on D Bit!", getIndex); break; // JR/JALR - case 3: Jcc = Jcc_Equal; break; // IBEQ - case 4: Jcc = Jcc_GreaterOrEqual; break; // IBGEZ - case 5: Jcc = Jcc_Greater; break; // IBGTZ - case 6: Jcc = Jcc_LessOrEqual; break; // IBLEQ - case 7: Jcc = Jcc_Less; break; // IBLTZ - case 8: Jcc = Jcc_NotEqual; break; // IBNEQ - } - if(mVUlow.branch < 9) - { - incPC(1); - xForwardJump8 bJMP((JccComparisonType)Jcc); - incPC(1); // Set PC to First instruction of Non-Taken Side - xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC); - xJMP(mVU.exitFunct); - bJMP.SetTarget(); - incPC(-4); // Go Back to Branch Opcode to get branchAddr - iPC = branchAddr/4; - xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC); - } - else - { - xMOV(gprT1, ptr32[&mVU.branch]); - xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT1); - } - xJMP(mVU.exitFunct); - } - else - mVUDTendProgram(mVU, mFC, 1); + incPC(1); + mVUDTendProgram(mVU, mFC, 1); + incPC(-1); eJMP.SetTarget(); - iPC = savedPC; } void mVUDoTBit(microVU& mVU, microFlagCycles* mFC) { - bool isBranch = false; - JccComparisonType Jcc; - u32 savedPC = 0; - - incPC(2); //Check next slot for branch delay, if not, that's where the VU will resume anyway. - savedPC = iPC; //Save PC as it's about to get modified if it's a branch! - - if(mVUinfo.isBdelay) isBranch = true; - xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x800 : 0x8)); xForwardJump32 eJMP(Jcc_Zero); xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x400 : 0x4)); xOR(ptr32[&mVU.regs().flags], VUFLAG_INTCINTERRUPT); - if(isBranch) - { - incPC(-2); // Go back to branch opcode - DevCon.Warning("microVU%d: T-Bit on branch [%04x]", getIndex, xPC); - mVUDTendProgram(mVU, mFC, 2); - xCMP(ptr16[&mVU.branch], 0); - switch (mVUlow.branch) { - case 1: case 2: Jcc = Jcc_Unconditional; DevCon.Warning("microVU%d: T Bit on B/BAL, might be buggy", getIndex); break; // B/BAL - case 9: case 10: DevCon.Warning("microVU%d: JR/JALR probably not supported on T Bit!", getIndex); break; // JR/JALR - case 3: Jcc = Jcc_Equal; break; // IBEQ - case 4: Jcc = Jcc_GreaterOrEqual; break; // IBGEZ - case 5: Jcc = Jcc_Greater; break; // IBGTZ - case 6: Jcc = Jcc_LessOrEqual; break; // IBLEQ - case 7: Jcc = Jcc_Less; break; // IBLTZ - case 8: Jcc = Jcc_NotEqual; break; // IBNEQ - } - if(mVUlow.branch < 9) - { - incPC(1); - xForwardJump8 bJMP((JccComparisonType)Jcc); - incPC(1); // Set PC to First instruction of Non-Taken Side - xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC); - xJMP(mVU.exitFunct); - bJMP.SetTarget(); - incPC(-4); // Go Back to Branch Opcode to get branchAddr - iPC = branchAddr/4; - xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC); - } - else - { - xMOV(gprT1, ptr32[&mVU.branch]); - xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT1); - } - xJMP(mVU.exitFunct); - } - else - mVUDTendProgram(mVU, mFC, 1); + incPC(1); + mVUDTendProgram(mVU, mFC, 1); + incPC(-1); + eJMP.SetTarget(); - iPC = savedPC; } void mVUSaveFlags(microVU& mVU,microFlagCycles &mFC, microFlagCycles &mFCBackup) @@ -600,7 +511,6 @@ void mVUSaveFlags(microVU& mVU,microFlagCycles &mFC, microFlagCycles &mFCBackup) void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) { microFlagCycles mFC; - microFlagCycles mFCBackup; u8* thisPtr = x86Ptr; const u32 endCount = (((microRegInfo*)pState)->blockType) ? 1 : (mVU.microMemSize / 8); @@ -617,11 +527,13 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) { mVUopU(mVU, 0); mVUcheckBadOp(mVU); if (curI & _Ebit_) { eBitPass1(mVU, branch); } - if (curI & _Dbit_) { mVUup.dBit = 1; mVUsetFlagInfo(mVU); mVUSaveFlags(mVU, mFC, mFCBackup); } + if (curI & _Mbit_) { mVUup.mBit = 1; } - if (curI & _Tbit_) { mVUup.tBit = 1; mVUsetFlagInfo(mVU); mVUSaveFlags(mVU, mFC, mFCBackup); } + if (curI & _Ibit_) { mVUlow.isNOP = 1; mVUup.iBit = 1; } else { incPC(-1); mVUopL(mVU, 0); incPC(1); } + if (curI & _Dbit_) { mVUup.dBit = 1; } + if (curI & _Tbit_) { mVUup.tBit = 1; } mVUsetCycles(mVU); mVUinfo.readQ = mVU.q; mVUinfo.writeQ = !mVU.q; @@ -653,6 +565,11 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) { if (mVUinfo.isEOB) { handleBadOp(mVU, x); x = 0xffff; } if (mVUup.mBit) { xOR(ptr32[&mVU.regs().flags], VUFLAG_MFLAGSET); } mVUexecuteInstruction(mVU); + if(!mVUinfo.isBdelay && !mVUlow.branch) //T/D Bit on branch is handled after the branch, branch delay slots are executed. + { + if(mVUup.tBit) { mVUDoTBit(mVU, &mFC); } + else if(mVUup.dBit) { mVUDoDBit(mVU, &mFC); } + } if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); } if (isEvilBlock) { mVUsetupRange(mVU, xPC, 0); normJumpCompile(mVU, mFC, 1); return thisPtr; } else if (!mVUinfo.isBdelay) { incPC(1); } @@ -671,13 +588,8 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) { case 7: condBranch(mVU, mFC, Jcc_Less); return thisPtr; // IBLTZ case 8: condBranch(mVU, mFC, Jcc_NotEqual); return thisPtr; // IBNEQ } + } - - incPC(-2); - if(mVUup.tBit) { mVUDoTBit(mVU, &mFC); } - else if(mVUup.dBit) { mVUDoDBit(mVU, &mFC); } - else incPC(2); - } if ((x == endCount) && (x!=1)) { Console.Error("microVU%d: Possible infinite compiling loop!", mVU.index); } From 90f0da8ec293dcdca8c71a5ad6564e3787c1c533 Mon Sep 17 00:00:00 2001 From: gigaherz Date: Tue, 19 Mar 2013 22:01:41 +0000 Subject: [PATCH 45/81] Include dev9ghzdrk into the main plugins folder, and integrate it into the build system (windows only). Most of the work done by Rama, I just integrated the vcxproj. Only done for vs2010, vs2008 or vs2012 will have to wait. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5595 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2_suite_2010.sln | 36 + plugins/dev9ghzdrk/DEV9.cpp | 612 +++ plugins/dev9ghzdrk/DEV9.h | 629 +++ plugins/dev9ghzdrk/PS2Edefs.h | 684 ++++ plugins/dev9ghzdrk/PS2Etypes.h | 31 + plugins/dev9ghzdrk/Packet32.h | 359 ++ plugins/dev9ghzdrk/Win32-Extensions.h | 113 + plugins/dev9ghzdrk/Win32/Config.cpp | 54 + plugins/dev9ghzdrk/Win32/Config.h | 2 + plugins/dev9ghzdrk/Win32/DEV9ghzdrk.def | 28 + plugins/dev9ghzdrk/Win32/DEV9ghzdrk.rc | 126 + plugins/dev9ghzdrk/Win32/DEV9ghzdrk.vcxproj | 136 + .../Win32/DEV9ghzdrk.vcxproj.filters | 97 + plugins/dev9ghzdrk/Win32/Devioctl.h | 90 + plugins/dev9ghzdrk/Win32/ProjectRootDir.props | 15 + .../dev9ghzdrk/Win32/ProjectRootDir.vsprops | 11 + plugins/dev9ghzdrk/Win32/Win32.cpp | 168 + plugins/dev9ghzdrk/Win32/_Ntddndis.h | 1400 +++++++ plugins/dev9ghzdrk/Win32/afxresmw.h | 5 + plugins/dev9ghzdrk/Win32/ata.cpp | 3442 +++++++++++++++++ plugins/dev9ghzdrk/Win32/ata.h | 13 + plugins/dev9ghzdrk/Win32/icmp.cpp | 105 + plugins/dev9ghzdrk/Win32/mtfifo.h | 70 + plugins/dev9ghzdrk/Win32/net.cpp | 51 + plugins/dev9ghzdrk/Win32/net.h | 29 + plugins/dev9ghzdrk/Win32/packet32.h | 450 +++ plugins/dev9ghzdrk/Win32/pcap_io.h | 161 + plugins/dev9ghzdrk/Win32/postBuild.cmd | 50 + plugins/dev9ghzdrk/Win32/resource.h | 25 + plugins/dev9ghzdrk/Win32/smap.cpp | 874 +++++ plugins/dev9ghzdrk/Win32/smap.h | 13 + plugins/dev9ghzdrk/Win32/socket_io.cpp | 294 ++ plugins/dev9ghzdrk/Win32/socks.c | 191 + plugins/dev9ghzdrk/Win32/socks.h | 12 + plugins/dev9ghzdrk/Win32/svnrev.h | 33 + plugins/dev9ghzdrk/Win32/tap-win32.cpp | 1080 ++++++ plugins/dev9ghzdrk/Win32/tap.h | 24 + plugins/dev9ghzdrk/Win32/vl.h | 1419 +++++++ plugins/dev9ghzdrk/bittypes.h | 137 + plugins/dev9ghzdrk/flash.cpp | 249 ++ plugins/dev9ghzdrk/ip6_misc.h | 163 + plugins/dev9ghzdrk/pcap-bpf.h | 47 + plugins/dev9ghzdrk/pcap-namedb.h | 42 + plugins/dev9ghzdrk/pcap-stdinc.h | 93 + plugins/dev9ghzdrk/pcap.h | 45 + plugins/dev9ghzdrk/pcap/bluetooth.h | 48 + plugins/dev9ghzdrk/pcap/bpf.h | 934 +++++ plugins/dev9ghzdrk/pcap/namedb.h | 89 + plugins/dev9ghzdrk/pcap/pcap.h | 407 ++ plugins/dev9ghzdrk/pcap/sll.h | 129 + plugins/dev9ghzdrk/pcap/usb.h | 90 + plugins/dev9ghzdrk/pcap/vlan.h | 46 + plugins/dev9ghzdrk/pcap/wpcap_32/Packet.dll | Bin 0 -> 88696 bytes plugins/dev9ghzdrk/pcap/wpcap_32/Packet.lib | Bin 0 -> 8674 bytes plugins/dev9ghzdrk/pcap/wpcap_32/wpcap.dll | Bin 0 -> 244336 bytes plugins/dev9ghzdrk/pcap/wpcap_32/wpcap.lib | Bin 0 -> 17658 bytes plugins/dev9ghzdrk/pcap/wpcap_64/Packet.dll | Bin 0 -> 80384 bytes plugins/dev9ghzdrk/pcap/wpcap_64/Packet.lib | Bin 0 -> 8286 bytes plugins/dev9ghzdrk/pcap/wpcap_64/wpcap.dll | Bin 0 -> 252416 bytes plugins/dev9ghzdrk/pcap/wpcap_64/wpcap.lib | Bin 0 -> 17046 bytes plugins/dev9ghzdrk/pcap_io.cpp | 419 ++ plugins/dev9ghzdrk/remote-ext.h | 444 +++ 62 files changed, 16314 insertions(+) create mode 100644 plugins/dev9ghzdrk/DEV9.cpp create mode 100644 plugins/dev9ghzdrk/DEV9.h create mode 100644 plugins/dev9ghzdrk/PS2Edefs.h create mode 100644 plugins/dev9ghzdrk/PS2Etypes.h create mode 100644 plugins/dev9ghzdrk/Packet32.h create mode 100644 plugins/dev9ghzdrk/Win32-Extensions.h create mode 100644 plugins/dev9ghzdrk/Win32/Config.cpp create mode 100644 plugins/dev9ghzdrk/Win32/Config.h create mode 100644 plugins/dev9ghzdrk/Win32/DEV9ghzdrk.def create mode 100644 plugins/dev9ghzdrk/Win32/DEV9ghzdrk.rc create mode 100644 plugins/dev9ghzdrk/Win32/DEV9ghzdrk.vcxproj create mode 100644 plugins/dev9ghzdrk/Win32/DEV9ghzdrk.vcxproj.filters create mode 100644 plugins/dev9ghzdrk/Win32/Devioctl.h create mode 100644 plugins/dev9ghzdrk/Win32/ProjectRootDir.props create mode 100644 plugins/dev9ghzdrk/Win32/ProjectRootDir.vsprops create mode 100644 plugins/dev9ghzdrk/Win32/Win32.cpp create mode 100644 plugins/dev9ghzdrk/Win32/_Ntddndis.h create mode 100644 plugins/dev9ghzdrk/Win32/afxresmw.h create mode 100644 plugins/dev9ghzdrk/Win32/ata.cpp create mode 100644 plugins/dev9ghzdrk/Win32/ata.h create mode 100644 plugins/dev9ghzdrk/Win32/icmp.cpp create mode 100644 plugins/dev9ghzdrk/Win32/mtfifo.h create mode 100644 plugins/dev9ghzdrk/Win32/net.cpp create mode 100644 plugins/dev9ghzdrk/Win32/net.h create mode 100644 plugins/dev9ghzdrk/Win32/packet32.h create mode 100644 plugins/dev9ghzdrk/Win32/pcap_io.h create mode 100644 plugins/dev9ghzdrk/Win32/postBuild.cmd create mode 100644 plugins/dev9ghzdrk/Win32/resource.h create mode 100644 plugins/dev9ghzdrk/Win32/smap.cpp create mode 100644 plugins/dev9ghzdrk/Win32/smap.h create mode 100644 plugins/dev9ghzdrk/Win32/socket_io.cpp create mode 100644 plugins/dev9ghzdrk/Win32/socks.c create mode 100644 plugins/dev9ghzdrk/Win32/socks.h create mode 100644 plugins/dev9ghzdrk/Win32/svnrev.h create mode 100644 plugins/dev9ghzdrk/Win32/tap-win32.cpp create mode 100644 plugins/dev9ghzdrk/Win32/tap.h create mode 100644 plugins/dev9ghzdrk/Win32/vl.h create mode 100644 plugins/dev9ghzdrk/bittypes.h create mode 100644 plugins/dev9ghzdrk/flash.cpp create mode 100644 plugins/dev9ghzdrk/ip6_misc.h create mode 100644 plugins/dev9ghzdrk/pcap-bpf.h create mode 100644 plugins/dev9ghzdrk/pcap-namedb.h create mode 100644 plugins/dev9ghzdrk/pcap-stdinc.h create mode 100644 plugins/dev9ghzdrk/pcap.h create mode 100644 plugins/dev9ghzdrk/pcap/bluetooth.h create mode 100644 plugins/dev9ghzdrk/pcap/bpf.h create mode 100644 plugins/dev9ghzdrk/pcap/namedb.h create mode 100644 plugins/dev9ghzdrk/pcap/pcap.h create mode 100644 plugins/dev9ghzdrk/pcap/sll.h create mode 100644 plugins/dev9ghzdrk/pcap/usb.h create mode 100644 plugins/dev9ghzdrk/pcap/vlan.h create mode 100644 plugins/dev9ghzdrk/pcap/wpcap_32/Packet.dll create mode 100644 plugins/dev9ghzdrk/pcap/wpcap_32/Packet.lib create mode 100644 plugins/dev9ghzdrk/pcap/wpcap_32/wpcap.dll create mode 100644 plugins/dev9ghzdrk/pcap/wpcap_32/wpcap.lib create mode 100644 plugins/dev9ghzdrk/pcap/wpcap_64/Packet.dll create mode 100644 plugins/dev9ghzdrk/pcap/wpcap_64/Packet.lib create mode 100644 plugins/dev9ghzdrk/pcap/wpcap_64/wpcap.dll create mode 100644 plugins/dev9ghzdrk/pcap/wpcap_64/wpcap.lib create mode 100644 plugins/dev9ghzdrk/pcap_io.cpp create mode 100644 plugins/dev9ghzdrk/remote-ext.h diff --git a/pcsx2_suite_2010.sln b/pcsx2_suite_2010.sln index 059889a74..ec7cc5d3d 100644 --- a/pcsx2_suite_2010.sln +++ b/pcsx2_suite_2010.sln @@ -114,6 +114,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "USBqemu", "plugins\USBqemu\ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZZOgl-cg", "plugins\zzogl-pg-cg\opengl\Win32\zerogsogl-cg.vcxproj", "{019773FA-2DAA-4C12-9511-BD2D4EB2A718}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DEV9ghzdrk", "plugins\dev9ghzdrk\Win32\DEV9ghzdrk.vcxproj", "{BBE4E5FB-530A-4D18-A633-35AF0577B7F3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug AVX|Win32 = Debug AVX|Win32 @@ -1221,6 +1223,39 @@ Global {019773FA-2DAA-4C12-9511-BD2D4EB2A718}.Release|Win32.ActiveCfg = Release|Win32 {019773FA-2DAA-4C12-9511-BD2D4EB2A718}.Release|Win32.Build.0 = Release|Win32 {019773FA-2DAA-4C12-9511-BD2D4EB2A718}.Release|x64.ActiveCfg = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug AVX|Win32.ActiveCfg = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug AVX|Win32.Build.0 = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug AVX|x64.ActiveCfg = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug SSE2|Win32.ActiveCfg = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug SSE2|Win32.Build.0 = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug SSE2|x64.ActiveCfg = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug SSE4|Win32.ActiveCfg = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug SSE4|Win32.Build.0 = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug SSE4|x64.ActiveCfg = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug SSSE3|Win32.ActiveCfg = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug SSSE3|Win32.Build.0 = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug SSSE3|x64.ActiveCfg = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug|Win32.ActiveCfg = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug|Win32.Build.0 = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug|x64.ActiveCfg = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Devel|Win32.ActiveCfg = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Devel|Win32.Build.0 = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Devel|x64.ActiveCfg = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release AVX|Win32.ActiveCfg = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release AVX|Win32.Build.0 = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release AVX|x64.ActiveCfg = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release SSE2|Win32.ActiveCfg = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release SSE2|Win32.Build.0 = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release SSE2|x64.ActiveCfg = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release SSE4|Win32.ActiveCfg = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release SSE4|Win32.Build.0 = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release SSE4|x64.ActiveCfg = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release SSSE3|Win32.ActiveCfg = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release SSSE3|Win32.Build.0 = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release SSSE3|x64.ActiveCfg = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release|Win32.ActiveCfg = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release|Win32.Build.0 = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release|x64.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1240,6 +1275,7 @@ Global {2D4E85B2-F47F-4D65-B091-701E5C031DAC} = {703FD00B-D7A0-41E3-BD03-CEC86B385DAF} {E613DA9F-41B4-4613-9911-E418EF5533BC} = {703FD00B-D7A0-41E3-BD03-CEC86B385DAF} {019773FA-2DAA-4C12-9511-BD2D4EB2A718} = {703FD00B-D7A0-41E3-BD03-CEC86B385DAF} + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3} = {703FD00B-D7A0-41E3-BD03-CEC86B385DAF} {E9B51944-7E6D-4BCD-83F2-7BBD5A46182D} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38} {2F6C0388-20CB-4242-9F6C-A6EBB6A83F47} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38} {F4EB4AB2-C595-4B05-8BC0-059024BC796C} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38} diff --git a/plugins/dev9ghzdrk/DEV9.cpp b/plugins/dev9ghzdrk/DEV9.cpp new file mode 100644 index 000000000..7c4a08acf --- /dev/null +++ b/plugins/dev9ghzdrk/DEV9.cpp @@ -0,0 +1,612 @@ + +#define WINVER 0x0600 +#define _WIN32_WINNT 0x0600 + +#include +#include +#include +#include +#include +#include +#include +#include +#define EXTERN +#include "DEV9.h" +#undef EXTERN +#include "Config.h" +#include "smap.h" +#include "ata.h" + +#ifdef __WIN32__ +#pragma warning(disable:4244) + +HINSTANCE hInst=NULL; +#endif + +//#define HDD_48BIT + +u8 eeprom[] = { + //0x6D, 0x76, 0x63, 0x61, 0x31, 0x30, 0x08, 0x01, + 0x76, 0x6D, 0x61, 0x63, 0x30, 0x31, 0x07, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + + +int Log = 1; + +u32 *iopPC; + +const unsigned char version = PS2E_DEV9_VERSION; +const unsigned char revision = 0; +const unsigned char build = 3; // increase that with each version + + +static char *libraryName = "GiGaHeRz's DEV9 Driver" +#ifdef _DEBUG + "(debug)" +#endif +; + +HANDLE hEeprom; +HANDLE mapping; + +u32 CALLBACK PS2EgetLibType() { + return PS2E_LT_DEV9; +} + +char* CALLBACK PS2EgetLibName() { + return libraryName; +} + +u32 CALLBACK PS2EgetLibVersion2(u32 type) { + return (version<<16) | (revision<<8) | build; +} + +void __Log(char *fmt, ...) { + va_list list; + + static int ticks=-1; + int nticks=GetTickCount(); + + if(ticks==-1) ticks=nticks; + +// if (!Log) return; + if(iopPC!=NULL) + { + fprintf(dev9Log,"[%10d + %4d, IOP PC = %08x] ",nticks,nticks-ticks,*iopPC); + } + else + { + fprintf(dev9Log,"[%10d + %4d] ",nticks,nticks-ticks); + } + ticks=nticks; + + va_start(list, fmt); + vfprintf(dev9Log, fmt, list); + va_end(list); +} + + +s32 CALLBACK DEV9init() +{ + +#ifdef DEV9_LOG_ENABLE + dev9Log = fopen("logs/dev9Log.txt", "w"); + setvbuf(dev9Log, NULL, _IONBF, 0); + DEV9_LOG("DEV9init\n"); +#endif + memset(&dev9, 0, sizeof(dev9)); + DEV9_LOG("DEV9init2\n"); + + DEV9_LOG("DEV9init3\n"); + + FLASHinit(); + + hEeprom = CreateFile( + "eeprom.dat", + GENERIC_READ|GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_FLAG_WRITE_THROUGH, + NULL + ); + + if(hEeprom==INVALID_HANDLE_VALUE) + { + dev9.eeprom=(u16*)eeprom; + } + else + { + mapping=CreateFileMapping(hEeprom,NULL,PAGE_READWRITE,0,0,NULL); + if(mapping==INVALID_HANDLE_VALUE) + { + CloseHandle(hEeprom); + dev9.eeprom=(u16*)eeprom; + } + else + { + dev9.eeprom = (u16*)MapViewOfFile(mapping,FILE_MAP_WRITE,0,0,0); + if(dev9.eeprom==NULL) + { + CloseHandle(mapping); + CloseHandle(hEeprom); + dev9.eeprom=(u16*)eeprom; + } + } + } + + + { + int rxbi; + + for(rxbi=0;rxbi<(SMAP_BD_SIZE/8);rxbi++) + { + smap_bd_t *pbd = (smap_bd_t *)&dev9.dev9R[SMAP_BD_RX_BASE & 0xffff]; + pbd = &pbd[rxbi]; + + pbd->ctrl_stat = SMAP_BD_RX_EMPTY; + pbd->length = 0; + } + } + + DEV9_LOG("DEV9init ok\n"); + + return 0; +} + +void CALLBACK DEV9shutdown() { + DEV9_LOG("DEV9shutdown\n"); +#ifdef DEV9_LOG_ENABLE + fclose(dev9Log); +#endif +} + +s32 CALLBACK DEV9open(void *pDsp) +{ + DEV9_LOG("DEV9open\n"); + LoadConf(); + DEV9_LOG("open r+: %s\n", config.Hdd); + config.HddSize = 8*1024; + + iopPC = (u32*)pDsp; + +#ifdef ENABLE_ATA + ata_init(); +#endif + return _DEV9open(); +} + +void CALLBACK DEV9close() +{ + DEV9_LOG("DEV9close\n"); +#ifdef ENABLE_ATA + ata_term(); +#endif + _DEV9close(); +} + +int CALLBACK _DEV9irqHandler(void) +{ + //dev9Ru16(SPD_R_INTR_STAT)|= dev9.irqcause; + DEV9_LOG("_DEV9irqHandler %x, %x\n", dev9.irqcause, dev9Ru16(SPD_R_INTR_MASK)); + if (dev9.irqcause & dev9Ru16(SPD_R_INTR_MASK)) + return 1; + return 0; +} + +DEV9handler CALLBACK DEV9irqHandler(void) { + return (DEV9handler)_DEV9irqHandler; +} + +void _DEV9irq(int cause, int cycles) +{ + DEV9_LOG("_DEV9irq %x, %x\n", cause, dev9Ru16(SPD_R_INTR_MASK)); + + dev9.irqcause|= cause; + + if(cycles<1) + DEV9irq(1); + else + DEV9irq(cycles); +} + + +u8 CALLBACK DEV9read8(u32 addr) { + u8 hard; + if (addr>=ATA_DEV9_HDD_BASE && addr(addr); +#else + return 0; +#endif + } + if (addr>=SMAP_REGBASE && addr>11; + dev9.eeprom_bit++; + if(dev9.eeprom_bit==16) + { + dev9.eeprom_address++; + dev9.eeprom_bit=0; + } + } + else hard=0; + } + else hard=0; + return hard; + + case DEV9_R_REV: + hard = 0x32; // expansion bay + break; + + default: + if ((addr >= FLASH_REGBASE) && (addr < (FLASH_REGBASE + FLASH_REGSIZE))) { + return (u8)FLASHread32(addr, 1); + } + + hard = dev9Ru8(addr); + DEV9_LOG("*Unknown 8bit read at address %lx value %x\n", addr, hard); + return hard; + } + + DEV9_LOG("*Known 8bit read at address %lx value %x\n", addr, hard); + return hard; +} + +u16 CALLBACK DEV9read16(u32 addr) +{ + u16 hard; + if (addr>=ATA_DEV9_HDD_BASE && addr(addr); +#else + return 0; +#endif + } + if (addr>=SMAP_REGBASE && addr= FLASH_REGBASE) && (addr < (FLASH_REGBASE + FLASH_REGSIZE))) { + return (u16)FLASHread32(addr, 2); + } + + hard = dev9Ru16(addr); + DEV9_LOG("*Unknown 16bit read at address %lx value %x\n", addr, hard); + return hard; + } + + DEV9_LOG("*Known 16bit read at address %lx value %x\n", addr, hard); + return hard; +} + +u32 CALLBACK DEV9read32(u32 addr) +{ + u32 hard; + if (addr>=ATA_DEV9_HDD_BASE && addr(addr); +#else + return 0; +#endif + } + if (addr>=SMAP_REGBASE && addr= FLASH_REGBASE) && (addr < (FLASH_REGBASE + FLASH_REGSIZE))) { + return (u32)FLASHread32(addr, 4); + } + + hard = dev9Ru32(addr); + DEV9_LOG("*Unknown 32bit read at address %lx value %x\n", addr, hard); + return hard; + } + + DEV9_LOG("*Known 32bit read at address %lx: %lx\n", addr, hard); + return hard; +} + +void CALLBACK DEV9write8(u32 addr, u8 value) +{ + if (addr>=ATA_DEV9_HDD_BASE && addr(addr,value); +#endif + return; + } + if (addr>=SMAP_REGBASE && addr>4)&3; + + return; + + case SPD_R_PIO_DATA: + //DEV9_LOG("SPD_R_PIO_DATA 8bit write %x\n", value); + + if((value&0xc0)!=0xc0) + return; + + switch(dev9.eeprom_state) + { + case EEPROM_READY: + dev9.eeprom_command=0; + dev9.eeprom_state++; + break; + case EEPROM_OPCD0: + dev9.eeprom_command = (value>>4)&2; + dev9.eeprom_state++; + dev9.eeprom_bit=0xFF; + break; + case EEPROM_OPCD1: + dev9.eeprom_command |= (value>>5)&1; + dev9.eeprom_state++; + break; + case EEPROM_ADDR0: + case EEPROM_ADDR1: + case EEPROM_ADDR2: + case EEPROM_ADDR3: + case EEPROM_ADDR4: + case EEPROM_ADDR5: + dev9.eeprom_address = + (dev9.eeprom_address&(63^(1<<(dev9.eeprom_state-EEPROM_ADDR0))))| + ((value>>(dev9.eeprom_state-EEPROM_ADDR0))&(0x20>>(dev9.eeprom_state-EEPROM_ADDR0))); + dev9.eeprom_state++; + break; + case EEPROM_TDATA: + { + if(dev9.eeprom_command==1) //write + { + dev9.eeprom[dev9.eeprom_address] = + (dev9.eeprom[dev9.eeprom_address]&(63^(1<>dev9.eeprom_bit)&(0x8000>>dev9.eeprom_bit)); + dev9.eeprom_bit++; + if(dev9.eeprom_bit==16) + { + dev9.eeprom_address++; + dev9.eeprom_bit=0; + } + } + } + break; + } + + return; + + default: + if ((addr >= FLASH_REGBASE) && (addr < (FLASH_REGBASE + FLASH_REGSIZE))) { + FLASHwrite32(addr, (u32)value, 1); + return; + } + + dev9Ru8(addr) = value; + DEV9_LOG("*Unknown 8bit write at address %lx value %x\n", addr, value); + return; + } + dev9Ru8(addr) = value; + DEV9_LOG("*Known 8bit write at address %lx value %x\n", addr, value); +} + +void CALLBACK DEV9write16(u32 addr, u16 value) +{ + if (addr>=ATA_DEV9_HDD_BASE && addr(addr,value); +#endif + return; + } + if (addr>=SMAP_REGBASE && addr= FLASH_REGBASE) && (addr < (FLASH_REGBASE + FLASH_REGSIZE))) { + FLASHwrite32(addr, (u32)value, 2); + return; + } + + dev9Ru16(addr) = value; + DEV9_LOG("*Unknown 16bit write at address %lx value %x\n", addr, value); + return; + } + dev9Ru16(addr) = value; + DEV9_LOG("*Known 16bit write at address %lx value %x\n", addr, value); +} + +void CALLBACK DEV9write32(u32 addr, u32 value) +{ + if (addr>=ATA_DEV9_HDD_BASE && addr(addr,value); +#endif + return; + } + if (addr>=SMAP_REGBASE && addr= FLASH_REGBASE) && (addr < (FLASH_REGBASE + FLASH_REGSIZE))) { + FLASHwrite32(addr, (u32)value, 4); + return; + } + + dev9Ru32(addr) = value; + DEV9_LOG("*Unknown 32bit write at address %lx write %x\n", addr, value); + return; + } + dev9Ru32(addr) = value; + DEV9_LOG("*Known 32bit write at address %lx value %lx\n", addr, value); +} + +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size) +{ + DEV9_LOG("*DEV9readDMA8Mem: size %x\n", size); + emu_printf("rDMA\n"); + + smap_readDMA8Mem(pMem,size); +#ifdef ENABLE_ATA + ata_readDMA8Mem(pMem,size); +#endif +} + +void CALLBACK DEV9writeDMA8Mem(u32* pMem, int size) +{ + DEV9_LOG("*DEV9writeDMA8Mem: size %x\n", size); + emu_printf("wDMA\n"); + + smap_writeDMA8Mem(pMem,size); +#ifdef ENABLE_ATA + ata_writeDMA8Mem(pMem,size); +#endif +} + + +//plugin interface +void CALLBACK DEV9irqCallback(void (*callback)(int cycles)) { + DEV9irq = callback; +} + + +// extended funcs + +s32 CALLBACK DEV9test() { + return 0; +} + +void CALLBACK DEV9setSettingsDir(const char* dir) +{ + // Grab the ini directory. + // TODO: Use + // s_strIniPath = (dir == NULL) ? "inis" : dir; +} + + +int emu_printf(const char *fmt, ...) +{ + va_list vl; + int ret; + va_start(vl,fmt); + ret = vfprintf(stderr,fmt,vl); + va_end(vl); + fflush(stderr); + return ret; +} \ No newline at end of file diff --git a/plugins/dev9ghzdrk/DEV9.h b/plugins/dev9ghzdrk/DEV9.h new file mode 100644 index 000000000..ef9d140b2 --- /dev/null +++ b/plugins/dev9ghzdrk/DEV9.h @@ -0,0 +1,629 @@ +#ifndef __DEV9_H__ +#define __DEV9_H__ + +#include +#ifndef EXTERN +#define EXTERN extern +#endif +#define DEV9defs +//#define WINVER 0x0600 +//#define _WIN32_WINNT 0x0500 + +#include "PS2Edefs.h" +#include "net.h" + +#ifdef __WIN32__ + +#define usleep(x) Sleep(x / 1000) +#include +#include +#include + +#else + +#include + +#define __inline inline + +#endif + +#define DEV9_LOG_ENABLE + +#ifdef DEV9_LOG_ENABLE +#define DEV9_LOG __Log +#else +#define DEV9_LOG(...) () +#endif + +void rx_process(NetPacket* pk); +bool rx_fifo_can_rx(); + +#define ETH_DEF "eth0" +#define HDD_DEF "DEV9hdd.raw" + + typedef struct { + char Eth[256]; + char Hdd[256]; + int HddSize; + + int hddEnable; + int ethEnable; +} Config; + +EXTERN Config config; + +typedef struct { + s8 dev9R[0x10000]; + u8 eeprom_state; + u8 eeprom_command; + u8 eeprom_address; + u8 eeprom_bit; + u8 eeprom_dir; + u16 *eeprom;//[32]; + + u32 rxbdi; + u8 rxfifo[16*1024]; + u16 rxfifo_wr_ptr; + + u32 txbdi; + u8 txfifo[16*1024]; + u16 txfifo_rd_ptr; + + u8 bd_swap; + u16 atabuf[1024]; + u32 atacount; + u32 atasize; + u16 phyregs[32]; + int irqcause; + u8 atacmd; + u32 atasector; + u32 atansector; +} dev9Struct; + +//EEPROM states +#define EEPROM_READY 0 +#define EEPROM_OPCD0 1 //waiting for first bit of opcode +#define EEPROM_OPCD1 2 //waiting for second bit of opcode +#define EEPROM_ADDR0 3 //waiting for address bits +#define EEPROM_ADDR1 4 +#define EEPROM_ADDR2 5 +#define EEPROM_ADDR3 6 +#define EEPROM_ADDR4 7 +#define EEPROM_ADDR5 8 +#define EEPROM_TDATA 9 //ready to send/receive data + +EXTERN dev9Struct dev9; + +#define dev9_rxfifo_write(x) (dev9.rxfifo[dev9.rxfifo_wr_ptr++]=x) + +#define dev9Rs8(mem) dev9.dev9R[(mem) & 0xffff] +#define dev9Rs16(mem) (*(s16*)&dev9.dev9R[(mem) & 0xffff]) +#define dev9Rs32(mem) (*(s32*)&dev9.dev9R[(mem) & 0xffff]) +#define dev9Ru8(mem) (*(u8*) &dev9.dev9R[(mem) & 0xffff]) +#define dev9Ru16(mem) (*(u16*)&dev9.dev9R[(mem) & 0xffff]) +#define dev9Ru32(mem) (*(u32*)&dev9.dev9R[(mem) & 0xffff]) + +EXTERN int ThreadRun; + +s32 _DEV9open(); +void _DEV9close(); +EXTERN DEV9callback DEV9irq; +//void DEV9thread(); + +EXTERN FILE *dev9Log; +void __Log(char *fmt, ...); + +void SysMessage(char *fmt, ...); + +#define DEV9_R_REV 0x1f80146e + + +/* + * SPEED (ASIC on SMAP) register definitions. + * + * Copyright (c) 2003 Marcus R. Brown + * + * * code included from the ps2smap iop driver, modified by linuzappz * + */ + +#define SPD_REGBASE 0x10000000 + +#define SPD_R_REV (SPD_REGBASE + 0x00) +#define SPD_R_REV_1 (SPD_REGBASE + 0x02) + // bit 0: smap + // bit 1: hdd + // bit 5: flash +#define SPD_R_REV_3 (SPD_REGBASE + 0x04) +#define SPD_R_0e (SPD_REGBASE + 0x0e) + +#define SPD_R_DMA_CTRL (SPD_REGBASE + 0x24) +#define SPD_R_INTR_STAT (SPD_REGBASE + 0x28) +#define SPD_R_INTR_MASK (SPD_REGBASE + 0x2a) +#define SPD_R_PIO_DIR (SPD_REGBASE + 0x2c) +#define SPD_R_PIO_DATA (SPD_REGBASE + 0x2e) +#define SPD_PP_DOUT (1<<4) /* Data output, read port */ +#define SPD_PP_DIN (1<<5) /* Data input, write port */ +#define SPD_PP_SCLK (1<<6) /* Clock, write port */ +#define SPD_PP_CSEL (1<<7) /* Chip select, write port */ +/* Operation codes */ +#define SPD_PP_OP_READ 2 +#define SPD_PP_OP_WRITE 1 +#define SPD_PP_OP_EWEN 0 +#define SPD_PP_OP_EWDS 0 + +#define SPD_R_XFR_CTRL (SPD_REGBASE + 0x32) +#define SPD_R_IF_CTRL (SPD_REGBASE + 0x64) +#define SPD_IF_ATA_RESET 0x80 +#define SPD_IF_DMA_ENABLE 0x04 +#define SPD_R_PIO_MODE (SPD_REGBASE + 0x70) +#define SPD_R_MWDMA_MODE (SPD_REGBASE + 0x72) +#define SPD_R_UDMA_MODE (SPD_REGBASE + 0x74) + + +/* + * SMAP (PS2 Network Adapter) register definitions. + * + * Copyright (c) 2003 Marcus R. Brown + * + * * code included from the ps2smap iop driver, modified by linuzappz * + */ + + +/* SMAP interrupt status bits (selected from the SPEED device). */ +#define SMAP_INTR_EMAC3 (1<<6) +#define SMAP_INTR_RXEND (1<<5) +#define SMAP_INTR_TXEND (1<<4) +#define SMAP_INTR_RXDNV (1<<3) /* descriptor not valid */ +#define SMAP_INTR_TXDNV (1<<2) /* descriptor not valid */ +#define SMAP_INTR_CLR_ALL (SMAP_INTR_RXEND|SMAP_INTR_TXEND|SMAP_INTR_RXDNV) +#define SMAP_INTR_ENA_ALL (SMAP_INTR_EMAC3|SMAP_INTR_CLR_ALL) +#define SMAP_INTR_BITMSK 0x7C + +/* SMAP Register Definitions. */ + +#define SMAP_REGBASE (SPD_REGBASE + 0x100) + +#define SMAP_R_BD_MODE (SMAP_REGBASE + 0x02) +#define SMAP_BD_SWAP (1<<0) + +#define SMAP_R_INTR_CLR (SMAP_REGBASE + 0x28) + +/* SMAP FIFO Registers. */ + +#define SMAP_R_TXFIFO_CTRL (SMAP_REGBASE + 0xf00) +#define SMAP_TXFIFO_RESET (1<<0) +#define SMAP_TXFIFO_DMAEN (1<<1) +#define SMAP_R_TXFIFO_WR_PTR (SMAP_REGBASE + 0xf04) +#define SMAP_R_TXFIFO_SIZE (SMAP_REGBASE + 0xf08) +#define SMAP_R_TXFIFO_FRAME_CNT (SMAP_REGBASE + 0xf0C) +#define SMAP_R_TXFIFO_FRAME_INC (SMAP_REGBASE + 0xf10) +#define SMAP_R_TXFIFO_DATA (SMAP_REGBASE + 0x1000) + +#define SMAP_R_RXFIFO_CTRL (SMAP_REGBASE + 0xf30) +#define SMAP_RXFIFO_RESET (1<<0) +#define SMAP_RXFIFO_DMAEN (1<<1) +#define SMAP_R_RXFIFO_RD_PTR (SMAP_REGBASE + 0xf34) +#define SMAP_R_RXFIFO_SIZE (SMAP_REGBASE + 0xf38) +#define SMAP_R_RXFIFO_FRAME_CNT (SMAP_REGBASE + 0xf3C) +#define SMAP_R_RXFIFO_FRAME_DEC (SMAP_REGBASE + 0xf40) +#define SMAP_R_RXFIFO_DATA (SMAP_REGBASE + 0x1100) + +#define SMAP_R_FIFO_ADDR (SMAP_REGBASE + 0x1200) +#define SMAP_FIFO_CMD_READ (1<<1) +#define SMAP_FIFO_DATA_SWAP (1<<0) +#define SMAP_R_FIFO_DATA (SMAP_REGBASE + 0x1208) + +/* EMAC3 Registers. */ + +#define SMAP_EMAC3_REGBASE (SMAP_REGBASE + 0x1f00) + +#define SMAP_R_EMAC3_MODE0_L (SMAP_EMAC3_REGBASE + 0x00) +#define SMAP_E3_RXMAC_IDLE (1<<(15+16)) +#define SMAP_E3_TXMAC_IDLE (1<<(14+16)) +#define SMAP_E3_SOFT_RESET (1<<(13+16)) +#define SMAP_E3_TXMAC_ENABLE (1<<(12+16)) +#define SMAP_E3_RXMAC_ENABLE (1<<(11+16)) +#define SMAP_E3_WAKEUP_ENABLE (1<<(10+16)) +#define SMAP_R_EMAC3_MODE0_H (SMAP_EMAC3_REGBASE + 0x02) + +#define SMAP_R_EMAC3_MODE1 (SMAP_EMAC3_REGBASE + 0x04) +#define SMAP_R_EMAC3_MODE1_L (SMAP_EMAC3_REGBASE + 0x04) +#define SMAP_R_EMAC3_MODE1_H (SMAP_EMAC3_REGBASE + 0x06) +#define SMAP_E3_FDX_ENABLE (1<<31) +#define SMAP_E3_INLPBK_ENABLE (1<<30) /* internal loop back */ +#define SMAP_E3_VLAN_ENABLE (1<<29) +#define SMAP_E3_FLOWCTRL_ENABLE (1<<28) /* integrated flow ctrl(pause frame) */ +#define SMAP_E3_ALLOW_PF (1<<27) /* allow pause frame */ +#define SMAP_E3_ALLOW_EXTMNGIF (1<<25) /* allow external management IF */ +#define SMAP_E3_IGNORE_SQE (1<<24) +#define SMAP_E3_MEDIA_FREQ_BITSFT (22) +#define SMAP_E3_MEDIA_10M (0<<22) +#define SMAP_E3_MEDIA_100M (1<<22) +#define SMAP_E3_MEDIA_1000M (2<<22) +#define SMAP_E3_MEDIA_MSK (3<<22) +#define SMAP_E3_RXFIFO_SIZE_BITSFT (20) +#define SMAP_E3_RXFIFO_512 (0<<20) +#define SMAP_E3_RXFIFO_1K (1<<20) +#define SMAP_E3_RXFIFO_2K (2<<20) +#define SMAP_E3_RXFIFO_4K (3<<20) +#define SMAP_E3_TXFIFO_SIZE_BITSFT (18) +#define SMAP_E3_TXFIFO_512 (0<<18) +#define SMAP_E3_TXFIFO_1K (1<<18) +#define SMAP_E3_TXFIFO_2K (2<<18) +#define SMAP_E3_TXREQ0_BITSFT (15) +#define SMAP_E3_TXREQ0_SINGLE (0<<15) +#define SMAP_E3_TXREQ0_MULTI (1<<15) +#define SMAP_E3_TXREQ0_DEPEND (2<<15) +#define SMAP_E3_TXREQ1_BITSFT (13) +#define SMAP_E3_TXREQ1_SINGLE (0<<13) +#define SMAP_E3_TXREQ1_MULTI (1<<13) +#define SMAP_E3_TXREQ1_DEPEND (2<<13) +#define SMAP_E3_JUMBO_ENABLE (1<<12) + +#define SMAP_R_EMAC3_TxMODE0_L (SMAP_EMAC3_REGBASE + 0x08) +#define SMAP_E3_TX_GNP_0 (1<<(15+16)) /* get new packet */ +#define SMAP_E3_TX_GNP_1 (1<<(14+16)) /* get new packet */ +#define SMAP_E3_TX_GNP_DEPEND (1<<(13+16)) /* get new packet */ +#define SMAP_E3_TX_FIRST_CHANNEL (1<<(12+16)) +#define SMAP_R_EMAC3_TxMODE0_H (SMAP_EMAC3_REGBASE + 0x0A) + +#define SMAP_R_EMAC3_TxMODE1_L (SMAP_EMAC3_REGBASE + 0x0C) +#define SMAP_R_EMAC3_TxMODE1_H (SMAP_EMAC3_REGBASE + 0x0E) +#define SMAP_E3_TX_LOW_REQ_MSK (0x1F) /* low priority request */ +#define SMAP_E3_TX_LOW_REQ_BITSFT (27) /* low priority request */ +#define SMAP_E3_TX_URG_REQ_MSK (0xFF) /* urgent priority request */ +#define SMAP_E3_TX_URG_REQ_BITSFT (16) /* urgent priority request */ + +#define SMAP_R_EMAC3_RxMODE (SMAP_EMAC3_REGBASE + 0x10) +#define SMAP_R_EMAC3_RxMODE_L (SMAP_EMAC3_REGBASE + 0x10) +#define SMAP_R_EMAC3_RxMODE_H (SMAP_EMAC3_REGBASE + 0x12) +#define SMAP_E3_RX_STRIP_PAD (1<<31) +#define SMAP_E3_RX_STRIP_FCS (1<<30) +#define SMAP_E3_RX_RX_RUNT_FRAME (1<<29) +#define SMAP_E3_RX_RX_FCS_ERR (1<<28) +#define SMAP_E3_RX_RX_TOO_LONG_ERR (1<<27) +#define SMAP_E3_RX_RX_IN_RANGE_ERR (1<<26) +#define SMAP_E3_RX_PROP_PF (1<<25) /* propagate pause frame */ +#define SMAP_E3_RX_PROMISC (1<<24) +#define SMAP_E3_RX_PROMISC_MCAST (1<<23) +#define SMAP_E3_RX_INDIVID_ADDR (1<<22) +#define SMAP_E3_RX_INDIVID_HASH (1<<21) +#define SMAP_E3_RX_BCAST (1<<20) +#define SMAP_E3_RX_MCAST (1<<19) + +#define SMAP_R_EMAC3_INTR_STAT (SMAP_EMAC3_REGBASE + 0x14) +#define SMAP_R_EMAC3_INTR_STAT_L (SMAP_EMAC3_REGBASE + 0x14) +#define SMAP_R_EMAC3_INTR_STAT_H (SMAP_EMAC3_REGBASE + 0x16) +#define SMAP_R_EMAC3_INTR_ENABLE (SMAP_EMAC3_REGBASE + 0x18) +#define SMAP_R_EMAC3_INTR_ENABLE_L (SMAP_EMAC3_REGBASE + 0x18) +#define SMAP_R_EMAC3_INTR_ENABLE_H (SMAP_EMAC3_REGBASE + 0x1A) +#define SMAP_E3_INTR_OVERRUN (1<<25) /* this bit does NOT WORKED */ +#define SMAP_E3_INTR_PF (1<<24) +#define SMAP_E3_INTR_BAD_FRAME (1<<23) +#define SMAP_E3_INTR_RUNT_FRAME (1<<22) +#define SMAP_E3_INTR_SHORT_EVENT (1<<21) +#define SMAP_E3_INTR_ALIGN_ERR (1<<20) +#define SMAP_E3_INTR_BAD_FCS (1<<19) +#define SMAP_E3_INTR_TOO_LONG (1<<18) +#define SMAP_E3_INTR_OUT_RANGE_ERR (1<<17) +#define SMAP_E3_INTR_IN_RANGE_ERR (1<<16) +#define SMAP_E3_INTR_DEAD_DEPEND (1<<9) +#define SMAP_E3_INTR_DEAD_0 (1<<8) +#define SMAP_E3_INTR_SQE_ERR_0 (1<<7) +#define SMAP_E3_INTR_TX_ERR_0 (1<<6) +#define SMAP_E3_INTR_DEAD_1 (1<<5) +#define SMAP_E3_INTR_SQE_ERR_1 (1<<4) +#define SMAP_E3_INTR_TX_ERR_1 (1<<3) +#define SMAP_E3_INTR_MMAOP_SUCCESS (1<<1) +#define SMAP_E3_INTR_MMAOP_FAIL (1<<0) +#define SMAP_E3_INTR_ALL \ + (SMAP_E3_INTR_OVERRUN|SMAP_E3_INTR_PF|SMAP_E3_INTR_BAD_FRAME| \ + SMAP_E3_INTR_RUNT_FRAME|SMAP_E3_INTR_SHORT_EVENT| \ + SMAP_E3_INTR_ALIGN_ERR|SMAP_E3_INTR_BAD_FCS| \ + SMAP_E3_INTR_TOO_LONG|SMAP_E3_INTR_OUT_RANGE_ERR| \ + SMAP_E3_INTR_IN_RANGE_ERR| \ + SMAP_E3_INTR_DEAD_DEPEND|SMAP_E3_INTR_DEAD_0| \ + SMAP_E3_INTR_SQE_ERR_0|SMAP_E3_INTR_TX_ERR_0| \ + SMAP_E3_INTR_DEAD_1|SMAP_E3_INTR_SQE_ERR_1| \ + SMAP_E3_INTR_TX_ERR_1| \ + SMAP_E3_INTR_MMAOP_SUCCESS|SMAP_E3_INTR_MMAOP_FAIL) +#define SMAP_E3_DEAD_ALL \ + (SMAP_E3_INTR_DEAD_DEPEND|SMAP_E3_INTR_DEAD_0| \ + SMAP_E3_INTR_DEAD_1) + +#define SMAP_R_EMAC3_ADDR_HI (SMAP_EMAC3_REGBASE + 0x1C) +#define SMAP_R_EMAC3_ADDR_LO (SMAP_EMAC3_REGBASE + 0x20) +#define SMAP_R_EMAC3_ADDR_HI_L (SMAP_EMAC3_REGBASE + 0x1C) +#define SMAP_R_EMAC3_ADDR_HI_H (SMAP_EMAC3_REGBASE + 0x1E) +#define SMAP_R_EMAC3_ADDR_LO_L (SMAP_EMAC3_REGBASE + 0x20) +#define SMAP_R_EMAC3_ADDR_LO_H (SMAP_EMAC3_REGBASE + 0x22) + +#define SMAP_R_EMAC3_VLAN_TPID (SMAP_EMAC3_REGBASE + 0x24) +#define SMAP_E3_VLAN_ID_MSK 0xFFFF + +#define SMAP_R_EMAC3_VLAN_TCI (SMAP_EMAC3_REGBASE + 0x28) +#define SMAP_E3_VLAN_TCITAG_MSK 0xFFFF + +#define SMAP_R_EMAC3_PAUSE_TIMER (SMAP_EMAC3_REGBASE + 0x2C) +#define SMAP_R_EMAC3_PAUSE_TIMER_L (SMAP_EMAC3_REGBASE + 0x2C) +#define SMAP_R_EMAC3_PAUSE_TIMER_H (SMAP_EMAC3_REGBASE + 0x2E) +#define SMAP_E3_PTIMER_MSK 0xFFFF + +#define SMAP_R_EMAC3_INDIVID_HASH1 (SMAP_EMAC3_REGBASE + 0x30) +#define SMAP_R_EMAC3_INDIVID_HASH2 (SMAP_EMAC3_REGBASE + 0x34) +#define SMAP_R_EMAC3_INDIVID_HASH3 (SMAP_EMAC3_REGBASE + 0x38) +#define SMAP_R_EMAC3_INDIVID_HASH4 (SMAP_EMAC3_REGBASE + 0x3C) +#define SMAP_R_EMAC3_GROUP_HASH1 (SMAP_EMAC3_REGBASE + 0x40) +#define SMAP_R_EMAC3_GROUP_HASH2 (SMAP_EMAC3_REGBASE + 0x44) +#define SMAP_R_EMAC3_GROUP_HASH3 (SMAP_EMAC3_REGBASE + 0x48) +#define SMAP_R_EMAC3_GROUP_HASH4 (SMAP_EMAC3_REGBASE + 0x4C) +#define SMAP_E3_HASH_MSK 0xFFFF + +#define SMAP_R_EMAC3_LAST_SA_HI (SMAP_EMAC3_REGBASE + 0x50) +#define SMAP_R_EMAC3_LAST_SA_LO (SMAP_EMAC3_REGBASE + 0x54) + +#define SMAP_R_EMAC3_INTER_FRAME_GAP (SMAP_EMAC3_REGBASE + 0x58) +#define SMAP_R_EMAC3_INTER_FRAME_GAP_L (SMAP_EMAC3_REGBASE + 0x58) +#define SMAP_R_EMAC3_INTER_FRAME_GAP_H (SMAP_EMAC3_REGBASE + 0x5A) +#define SMAP_E3_IFGAP_MSK 0x3F + + +#define SMAP_R_EMAC3_STA_CTRL_L (SMAP_EMAC3_REGBASE + 0x5C) +#define SMAP_R_EMAC3_STA_CTRL_H (SMAP_EMAC3_REGBASE + 0x5E) +#define SMAP_E3_PHY_DATA_MSK (0xFFFF) +#define SMAP_E3_PHY_DATA_BITSFT (16) +#define SMAP_E3_PHY_OP_COMP (1<<15) /* operation complete */ +#define SMAP_E3_PHY_ERR_READ (1<<14) +#define SMAP_E3_PHY_STA_CMD_BITSFT (12) +#define SMAP_E3_PHY_READ (1<<12) +#define SMAP_E3_PHY_WRITE (2<<12) +#define SMAP_E3_PHY_OPBCLCK_BITSFT (10) +#define SMAP_E3_PHY_50M (0<<10) +#define SMAP_E3_PHY_66M (1<<10) +#define SMAP_E3_PHY_83M (2<<10) +#define SMAP_E3_PHY_100M (3<<10) +#define SMAP_E3_PHY_ADDR_MSK (0x1F) +#define SMAP_E3_PHY_ADDR_BITSFT (5) +#define SMAP_E3_PHY_REG_ADDR_MSK (0x1F) + +#define SMAP_R_EMAC3_TX_THRESHOLD (SMAP_EMAC3_REGBASE + 0x60) +#define SMAP_R_EMAC3_TX_THRESHOLD_L (SMAP_EMAC3_REGBASE + 0x60) +#define SMAP_R_EMAC3_TX_THRESHOLD_H (SMAP_EMAC3_REGBASE + 0x62) +#define SMAP_E3_TX_THRESHLD_MSK (0x1F) +#define SMAP_E3_TX_THRESHLD_BITSFT (27) + +#define SMAP_R_EMAC3_RX_WATERMARK (SMAP_EMAC3_REGBASE + 0x64) +#define SMAP_R_EMAC3_RX_WATERMARK_L (SMAP_EMAC3_REGBASE + 0x64) +#define SMAP_R_EMAC3_RX_WATERMARK_H (SMAP_EMAC3_REGBASE + 0x66) +#define SMAP_E3_RX_LO_WATER_MSK (0x1FF) +#define SMAP_E3_RX_LO_WATER_BITSFT (23) +#define SMAP_E3_RX_HI_WATER_MSK (0x1FF) +#define SMAP_E3_RX_HI_WATER_BITSFT (7) + +#define SMAP_R_EMAC3_TX_OCTETS (SMAP_EMAC3_REGBASE + 0x68) +#define SMAP_R_EMAC3_RX_OCTETS (SMAP_EMAC3_REGBASE + 0x6C) +#define SMAP_EMAC3_REGEND (SMAP_EMAC3_REGBASE + 0x6C + 4) + +/* Buffer descriptors. */ + +typedef struct _smap_bd { + u16 ctrl_stat; + u16 reserved; /* must be zero */ + u16 length; /* number of bytes in pkt */ + u16 pointer; +} smap_bd_t; + +#define SMAP_BD_REGBASE (SMAP_REGBASE + 0x2f00) +#define SMAP_BD_TX_BASE (SMAP_BD_REGBASE + 0x0000) +#define SMAP_BD_RX_BASE (SMAP_BD_REGBASE + 0x0200) +#define SMAP_BD_SIZE 512 +#define SMAP_BD_MAX_ENTRY 64 + +#define SMAP_TX_BASE (SMAP_REGBASE + 0x1000) +#define SMAP_TX_BUFSIZE 4096 + +/* TX Control */ +#define SMAP_BD_TX_READY (1<<15) /* set:driver, clear:HW */ +#define SMAP_BD_TX_GENFCS (1<<9) /* generate FCS */ +#define SMAP_BD_TX_GENPAD (1<<8) /* generate padding */ +#define SMAP_BD_TX_INSSA (1<<7) /* insert source address */ +#define SMAP_BD_TX_RPLSA (1<<6) /* replace source address */ +#define SMAP_BD_TX_INSVLAN (1<<5) /* insert VLAN Tag */ +#define SMAP_BD_TX_RPLVLAN (1<<4) /* replace VLAN Tag */ + +/* TX Status */ +#define SMAP_BD_TX_READY (1<<15) /* set:driver, clear:HW */ +#define SMAP_BD_TX_BADFCS (1<<9) /* bad FCS */ +#define SMAP_BD_TX_BADPKT (1<<8) /* bad previous pkt in dependent mode */ +#define SMAP_BD_TX_LOSSCR (1<<7) /* loss of carrior sense */ +#define SMAP_BD_TX_EDEFER (1<<6) /* excessive deferal */ +#define SMAP_BD_TX_ECOLL (1<<5) /* excessive collision */ +#define SMAP_BD_TX_LCOLL (1<<4) /* late collision */ +#define SMAP_BD_TX_MCOLL (1<<3) /* multiple collision */ +#define SMAP_BD_TX_SCOLL (1<<2) /* single collision */ +#define SMAP_BD_TX_UNDERRUN (1<<1) /* underrun */ +#define SMAP_BD_TX_SQE (1<<0) /* SQE */ + +#define SMAP_BD_TX_ERROR (SMAP_BD_TX_LOSSCR|SMAP_BD_TX_EDEFER|SMAP_BD_TX_ECOLL| \ + SMAP_BD_TX_LCOLL|SMAP_BD_TX_UNDERRUN) + +/* RX Control */ +#define SMAP_BD_RX_EMPTY (1<<15) /* set:driver, clear:HW */ + +/* RX Status */ +#define SMAP_BD_RX_EMPTY (1<<15) /* set:driver, clear:HW */ +#define SMAP_BD_RX_OVERRUN (1<<9) /* overrun */ +#define SMAP_BD_RX_PFRM (1<<8) /* pause frame */ +#define SMAP_BD_RX_BADFRM (1<<7) /* bad frame */ +#define SMAP_BD_RX_RUNTFRM (1<<6) /* runt frame */ +#define SMAP_BD_RX_SHORTEVNT (1<<5) /* short event */ +#define SMAP_BD_RX_ALIGNERR (1<<4) /* alignment error */ +#define SMAP_BD_RX_BADFCS (1<<3) /* bad FCS */ +#define SMAP_BD_RX_FRMTOOLONG (1<<2) /* frame too long */ +#define SMAP_BD_RX_OUTRANGE (1<<1) /* out of range error */ +#define SMAP_BD_RX_INRANGE (1<<0) /* in range error */ + +#define SMAP_BD_RX_ERROR (SMAP_BD_RX_OVERRUN|SMAP_BD_RX_RUNTFRM|SMAP_BD_RX_SHORTEVNT| \ + SMAP_BD_RX_ALIGNERR|SMAP_BD_RX_BADFCS|SMAP_BD_RX_FRMTOOLONG| \ + SMAP_BD_RX_OUTRANGE|SMAP_BD_RX_INRANGE) + +/* PHY registers (National Semiconductor DP83846A). */ + +#define SMAP_NS_OUI 0x080017 +#define SMAP_DsPHYTER_ADDRESS 0x1 + +#define SMAP_DsPHYTER_BMCR 0x00 +#define SMAP_PHY_BMCR_RST (1<<15) /* ReSeT */ +#define SMAP_PHY_BMCR_LPBK (1<<14) /* LooPBacK */ +#define SMAP_PHY_BMCR_100M (1<<13) /* speed select, 1:100M, 0:10M */ +#define SMAP_PHY_BMCR_10M (0<<13) /* speed select, 1:100M, 0:10M */ +#define SMAP_PHY_BMCR_ANEN (1<<12) /* Auto-Negotiation ENable */ +#define SMAP_PHY_BMCR_PWDN (1<<11) /* PoWer DowN */ +#define SMAP_PHY_BMCR_ISOL (1<<10) /* ISOLate */ +#define SMAP_PHY_BMCR_RSAN (1<<9) /* ReStart Auto-Negotiation */ +#define SMAP_PHY_BMCR_DUPM (1<<8) /* DUPlex Mode, 1:FDX, 0:HDX */ +#define SMAP_PHY_BMCR_COLT (1<<7) /* COLlision Test */ + +#define SMAP_DsPHYTER_BMSR 0x01 +#define SMAP_PHY_BMSR_ANCP (1<<5) /* Auto-Negotiation ComPlete */ +#define SMAP_PHY_BMSR_LINK (1<<2) /* LINK status */ + +#define SMAP_DsPHYTER_PHYIDR1 0x02 +#define SMAP_PHY_IDR1_VAL (((SMAP_NS_OUI<<2)>>8)&0xffff) + +#define SMAP_DsPHYTER_PHYIDR2 0x03 +#define SMAP_PHY_IDR2_VMDL 0x2 /* Vendor MoDeL number */ +#define SMAP_PHY_IDR2_VAL \ + (((SMAP_NS_OUI<<10)&0xFC00)|((SMAP_PHY_IDR2_VMDL<<4)&0x3F0)) +#define SMAP_PHY_IDR2_MSK 0xFFF0 +#define SMAP_PHY_IDR2_REV_MSK 0x000F + +#define SMAP_DsPHYTER_ANAR 0x04 +#define SMAP_DsPHYTER_ANLPAR 0x05 +#define SMAP_DsPHYTER_ANLPARNP 0x05 +#define SMAP_DsPHYTER_ANER 0x06 +#define SMAP_DsPHYTER_ANNPTR 0x07 + +/* Extended registers. */ +#define SMAP_DsPHYTER_PHYSTS 0x10 +#define SMAP_PHY_STS_REL (1<<13) /* Receive Error Latch */ +#define SMAP_PHY_STS_POST (1<<12) /* POlarity STatus */ +#define SMAP_PHY_STS_FCSL (1<<11) /* False Carrier Sense Latch */ +#define SMAP_PHY_STS_SD (1<<10) /* 100BT unconditional Signal Detect */ +#define SMAP_PHY_STS_DSL (1<<9) /* 100BT DeScrambler Lock */ +#define SMAP_PHY_STS_PRCV (1<<8) /* Page ReCeiVed */ +#define SMAP_PHY_STS_RFLT (1<<6) /* Remote FauLT */ +#define SMAP_PHY_STS_JBDT (1<<5) /* JaBber DetecT */ +#define SMAP_PHY_STS_ANCP (1<<4) /* Auto-Negotiation ComPlete */ +#define SMAP_PHY_STS_LPBK (1<<3) /* LooPBacK status */ +#define SMAP_PHY_STS_DUPS (1<<2) /* DUPlex Status,1:FDX,0:HDX */ +#define SMAP_PHY_STS_FDX (1<<2) /* Full Duplex */ +#define SMAP_PHY_STS_HDX (0<<2) /* Half Duplex */ +#define SMAP_PHY_STS_SPDS (1<<1) /* SPeeD Status */ +#define SMAP_PHY_STS_10M (1<<1) /* 10Mbps */ +#define SMAP_PHY_STS_100M (0<<1) /* 100Mbps */ +#define SMAP_PHY_STS_LINK (1<<0) /* LINK status */ +#define SMAP_DsPHYTER_FCSCR 0x14 +#define SMAP_DsPHYTER_RECR 0x15 +#define SMAP_DsPHYTER_PCSR 0x16 +#define SMAP_DsPHYTER_PHYCTRL 0x19 +#define SMAP_DsPHYTER_10BTSCR 0x1A +#define SMAP_DsPHYTER_CDCTRL 0x1B + +/* + * ATA hardware types and definitions. + * + * Copyright (c) 2003 Marcus R. Brown + * + * * code included from the ps2drv iop driver, modified by linuzappz * + */ + + +#define ATA_DEV9_HDD_BASE (SPD_REGBASE + 0x40) +/* AIF on T10Ks - Not supported yet. */ +#define ATA_AIF_HDD_BASE (SPD_REGBASE + 0x4000000 + 0x60) + +#define ATA_R_DATA (ATA_DEV9_HDD_BASE + 0x00) +#define ATA_R_ERROR (ATA_DEV9_HDD_BASE + 0x02) +#define ATA_R_NSECTOR (ATA_DEV9_HDD_BASE + 0x04) +#define ATA_R_SECTOR (ATA_DEV9_HDD_BASE + 0x06) +#define ATA_R_LCYL (ATA_DEV9_HDD_BASE + 0x08) +#define ATA_R_HCYL (ATA_DEV9_HDD_BASE + 0x0a) +#define ATA_R_SELECT (ATA_DEV9_HDD_BASE + 0x0c) +#define ATA_R_STATUS (ATA_DEV9_HDD_BASE + 0x0e) +#define ATA_R_CONTROL (ATA_DEV9_HDD_BASE + 0x1c) +#define ATA_DEV9_INT (0x01) +#define ATA_DEV9_INT_DMA (0x02) //not sure rly +#define ATA_DEV9_HDD_END (ATA_R_CONTROL+4) +/* + * NAND Flash via Dev9 driver definitions + * + * Copyright (c) 2003 Marcus R. Brown + * + * * code included from the ps2sdk iop driver * + */ + +#define FLASH_ID_64MBIT 0xe6 +#define FLASH_ID_128MBIT 0x73 +#define FLASH_ID_256MBIT 0x75 +#define FLASH_ID_512MBIT 0x76 +#define FLASH_ID_1024MBIT 0x79 + +/* SmartMedia commands. */ +#define SM_CMD_READ1 0x00 +#define SM_CMD_READ2 0x01 +#define SM_CMD_READ3 0x50 +#define SM_CMD_RESET 0xff +#define SM_CMD_WRITEDATA 0x80 +#define SM_CMD_PROGRAMPAGE 0x10 +#define SM_CMD_ERASEBLOCK 0x60 +#define SM_CMD_ERASECONFIRM 0xd0 +#define SM_CMD_GETSTATUS 0x70 +#define SM_CMD_READID 0x90 + +typedef struct { + u32 id; + u32 mbits; + u32 page_bytes; /* bytes/page */ + u32 block_pages; /* pages/block */ + u32 blocks; +} flash_info_t; + +/* +static flash_info_t devices[] = { + { FLASH_ID_64MBIT, 64, 528, 16, 1024 }, + { FLASH_ID_128MBIT, 128, 528, 32, 1024 }, + { FLASH_ID_256MBIT, 256, 528, 32, 2048 }, + { FLASH_ID_512MBIT, 512, 528, 32, 4096 }, + { FLASH_ID_1024MBIT, 1024, 528, 32, 8192 } +}; +#define NUM_DEVICES (sizeof(devices)/sizeof(flash_info_t)) +*/ + +// definitions added by Florin + +#define FLASH_REGBASE 0x10004800 + +#define FLASH_R_DATA (FLASH_REGBASE + 0x00) +#define FLASH_R_CMD (FLASH_REGBASE + 0x04) +#define FLASH_R_ADDR (FLASH_REGBASE + 0x08) +#define FLASH_R_CTRL (FLASH_REGBASE + 0x0C) +#define FLASH_PP_READY (1<<0) // r/w /BUSY +#define FLASH_PP_WRITE (1<<7) // -/w WRITE data +#define FLASH_PP_CSEL (1<<8) // -/w CS +#define FLASH_PP_READ (1<<11) // -/w READ data +#define FLASH_PP_NOECC (1<<12) // -/w ECC disabled +//#define FLASH_R_10 (FLASH_REGBASE + 0x10) +#define FLASH_R_ID (FLASH_REGBASE + 0x14) + +#define FLASH_REGSIZE 0x20 + +void CALLBACK FLASHinit(); +u32 CALLBACK FLASHread32(u32 addr, int size); +void CALLBACK FLASHwrite32(u32 addr, u32 value, int size); +void _DEV9irq(int cause, int cycles); + +int emu_printf(const char *fmt, ...); + +#pragma warning(error:4013) +#endif diff --git a/plugins/dev9ghzdrk/PS2Edefs.h b/plugins/dev9ghzdrk/PS2Edefs.h new file mode 100644 index 000000000..0b15378dc --- /dev/null +++ b/plugins/dev9ghzdrk/PS2Edefs.h @@ -0,0 +1,684 @@ +#ifndef __PS2EDEFS_H__ +#define __PS2EDEFS_H__ + +/* + * PS2E Definitions v0.5.5 (beta) + * + * Author: linuzappz@hotmail.com + * shadowpcsx2@yahoo.gr + * florinsasu@hotmail.com + */ + +/* + Notes: + * Since this is still beta things may change. + + * OSflags: + __LINUX__ (linux OS) + __WIN32__ (win32 OS) + + * common return values (for ie. GSinit): + 0 - success + -1 - error + + * reserved keys: + F1 to F10 are reserved for the emulator + + * plugins should NOT change the current + working directory. + (on win32, add flag OFN_NOCHANGEDIR for + GetOpenFileName) + +*/ + +#include "PS2Etypes.h" + +#ifdef __LINUX__ +#define CALLBACK +#else +#include +#endif + +/* common defines */ + +#if defined(GSdefs) || defined(PADdefs) || \ + defined(SPU2defs)|| defined(CDVDdefs) +#define COMMONdefs +#endif + +// PS2EgetLibType returns (may be OR'd) +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FIREWIRE 0x40 + +// PS2EgetLibVersion2 (high 16 bits) +#define PS2E_GS_VERSION 0x0005 +#define PS2E_PAD_VERSION 0x0002 +#define PS2E_SPU2_VERSION 0x0004 +#define PS2E_CDVD_VERSION 0x0003 +#define PS2E_DEV9_VERSION 0x0003 +#define PS2E_USB_VERSION 0x0003 +#define PS2E_FIREWIRE_VERSION 0x0002 +#ifdef COMMONdefs + +u32 CALLBACK PS2EgetLibType(void); +u32 CALLBACK PS2EgetLibVersion2(u32 type); +char* CALLBACK PS2EgetLibName(void); + +#endif + +// key values: +/* key values must be OS dependant: + win32: the VK_XXX will be used (WinUser) + linux: the XK_XXX will be used (XFree86) +*/ + +// event values: +#define KEYPRESS 1 +#define KEYRELEASE 2 + +typedef struct { + u32 key; + u32 event; +} keyEvent; + +typedef struct { // NOT bcd coded + u8 minute; + u8 second; + u8 frame; + u8 type; +} cdvdTD; + +typedef struct { + u8 strack; //number of the first track (usualy 1) + u8 etrack; //number of the last track +} cdvdTN; + +// CDVDreadTrack mode values: +#define CDVD_MODE_2352 0 // full 2352 bytes +#define CDVD_MODE_2340 1 // skip sync (12) bytes +#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq + +// CDVDgetType returns: +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided +#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc + +// CDVDgetTrayStatus returns: +#define CDVD_TRAY_CLOSE 0x00 +#define CDVD_TRAY_OPEN 0x01 + +// cdvdLoc:track type +#define CDVD_AUDIO_TRACK 0x01 +#define CDVD_MODE1_TRACK 0x41 +#define CDVD_MODE2_TRACK 0x61 + +#define CDVD_AUDIO_MASK 0x00 +#define CDVD_DATA_MASK 0x40 +// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) + +typedef void (*DEV9callback)(int cycles); +typedef int (*DEV9handler)(void); + +typedef void (*USBcallback)(int cycles); +typedef int (*USBhandler)(void); + +// freeze modes: +#define FREEZE_LOAD 0 +#define FREEZE_SAVE 1 +#define FREEZE_SIZE 2 + +typedef struct { + int size; + s8 *data; +} freezeData; + +typedef struct { + char name[8]; + void *common; +} GSdriverInfo; + +#ifdef __WIN32__ +typedef struct { // unsupported values must be set to zero + HWND hWnd; + HMENU hMenu; + HWND hStatusWnd; +} winInfo; +#endif + +/* GS plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef GSdefs + +// basic funcs + +s32 CALLBACK GSinit(); +s32 CALLBACK GSopen(void *pDsp, char *Title); +void CALLBACK GSclose(); +void CALLBACK GSshutdown(); +void CALLBACK GSvsync(); +void CALLBACK GSgifTransfer1(u32 *pMem); +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size); +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); +void CALLBACK GSwrite32(u32 mem, u32 value); +void CALLBACK GSwrite64(u32 mem, u64 value); +u32 CALLBACK GSread32(u32 mem); +u64 CALLBACK GSread64(u32 mem); +void CALLBACK GSreadFIFO(u64 *mem); + +// extended funcs + +// GSkeyEvent gets called when there is a keyEvent from the PAD plugin +void CALLBACK GSkeyEvent(keyEvent *ev); +void CALLBACK GSmakeSnapshot(char *path); +void CALLBACK GSirqCallback(void (*callback)()); +void CALLBACK GSprintf(int timeout, char *fmt, ...); +void CALLBACK GSgetDriverInfo(GSdriverInfo *info); +#ifdef __WIN32__ +s32 CALLBACK GSsetWindowInfo(winInfo *info); +#endif +s32 CALLBACK GSfreeze(int mode, freezeData *data); +void CALLBACK GSconfigure(); +void CALLBACK GSabout(); +s32 CALLBACK GStest(); + +#endif + +/* PAD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef PADdefs + +// basic funcs + +s32 CALLBACK PADinit(u32 flags); +s32 CALLBACK PADopen(void *pDsp); +void CALLBACK PADclose(); +void CALLBACK PADshutdown(); +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent(); +u8 CALLBACK PADstartPoll(int pad); +u8 CALLBACK PADpoll(u8 value); +// returns: 1 if supported pad1 +// 2 if supported pad2 +// 3 if both are supported +u32 CALLBACK PADquery(); + +// extended funcs + +void CALLBACK PADgsDriverInfo(GSdriverInfo *info); +void CALLBACK PADconfigure(); +void CALLBACK PADabout(); +s32 CALLBACK PADtest(); + +#endif + +/* SPU2 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SPU2defs + +// basic funcs + +s32 CALLBACK SPU2init(); +s32 CALLBACK SPU2open(void *pDsp); +void CALLBACK SPU2close(); +void CALLBACK SPU2shutdown(); +void CALLBACK SPU2write(u32 mem, u16 value); +u16 CALLBACK SPU2read(u32 mem); +void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2writeDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA4(); +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size); +void CALLBACK SPU2writeDMA7Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA7(); +void CALLBACK SPU2irqCallback(void (*callback)()); + +// extended funcs + +void CALLBACK SPU2async(u32 cycles); +s32 CALLBACK SPU2freeze(int mode, freezeData *data); +void CALLBACK SPU2configure(); +void CALLBACK SPU2about(); +s32 CALLBACK SPU2test(); + +#endif + +/* CDVD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef CDVDdefs + +// basic funcs + +s32 CALLBACK CDVDinit(); +s32 CALLBACK CDVDopen(); +void CALLBACK CDVDclose(); +void CALLBACK CDVDshutdown(); +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer(); + +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type +s32 CALLBACK CDVDgetType(); //CDVD_TYPE_xxxx +s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx + +// extended funcs + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +s32 CALLBACK CDVDtest(); + +#endif + +/* DEV9 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef DEV9defs + +// basic funcs + +s32 CALLBACK DEV9init(); +s32 CALLBACK DEV9open(void *pDsp); +void CALLBACK DEV9close(); +void CALLBACK DEV9shutdown(); +u8 CALLBACK DEV9read8(u32 addr); +u16 CALLBACK DEV9read16(u32 addr); +u32 CALLBACK DEV9read32(u32 addr); +void CALLBACK DEV9write8(u32 addr, u8 value); +void CALLBACK DEV9write16(u32 addr, u16 value); +void CALLBACK DEV9write32(u32 addr, u32 value); +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size); +void CALLBACK DEV9writeDMA8Mem(u32 *pMem, int size); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK DEV9irqCallback(DEV9callback callback); +DEV9handler CALLBACK DEV9irqHandler(void); + +// extended funcs + +s32 CALLBACK DEV9freeze(int mode, freezeData *data); +void CALLBACK DEV9configure(); +void CALLBACK DEV9about(); +s32 CALLBACK DEV9test(); + +#endif + +/* USB plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef USBdefs + +// basic funcs + +s32 CALLBACK USBinit(); +s32 CALLBACK USBopen(void *pDsp); +void CALLBACK USBclose(); +void CALLBACK USBshutdown(); +u8 CALLBACK USBread8(u32 addr); +u16 CALLBACK USBread16(u32 addr); +u32 CALLBACK USBread32(u32 addr); +void CALLBACK USBwrite8(u32 addr, u8 value); +void CALLBACK USBwrite16(u32 addr, u16 value); +void CALLBACK USBwrite32(u32 addr, u32 value); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK USBirqCallback(USBcallback callback); +USBhandler CALLBACK USBirqHandler(void); +void CALLBACK USBsetRAM(void *mem); + +// extended funcs + +s32 CALLBACK USBfreeze(int mode, freezeData *data); +void CALLBACK USBconfigure(); +void CALLBACK USBabout(); +s32 CALLBACK USBtest(); + +#endif +/* Firewire plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef FIREWIREdefs +// basic funcs + +s32 CALLBACK FireWireinit(); +s32 CALLBACK FireWireopen(void *pDsp); +void CALLBACK FireWireclose(); +void CALLBACK FireWireshutdown(); +u32 CALLBACK FireWireread32(u32 addr); +void CALLBACK FireWirewrite32(u32 addr, u32 value); +void CALLBACK FireWireirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK FireWirefreeze(int mode, freezeData *data); +void CALLBACK FireWireconfigure(); +void CALLBACK FireWireabout(); +s32 CALLBACK FireWiretest(); +#endif + +// might be useful for emulators +#ifdef PLUGINtypedefs + +typedef u32 (CALLBACK* _PS2EgetLibType)(void); +typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type); +typedef char*(CALLBACK* _PS2EgetLibName)(void); + +// GS +typedef s32 (CALLBACK* _GSinit)(); +typedef s32 (CALLBACK* _GSopen)(void *pDsp, char *Title); +typedef void (CALLBACK* _GSclose)(); +typedef void (CALLBACK* _GSshutdown)(); +typedef void (CALLBACK* _GSvsync)(); +typedef void (CALLBACK* _GSwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _GSwrite64)(u32 mem, u64 value); +typedef u32 (CALLBACK* _GSread32)(u32 mem); +typedef u64 (CALLBACK* _GSread64)(u32 mem); +typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem); +typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); + +typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev); +typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); +typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); +typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info); +#ifdef __WIN32__ +typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info); +#endif +typedef void (CALLBACK* _GSmakeSnapshot)(char *path); +typedef s32 (CALLBACK* _GSfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _GSconfigure)(); +typedef s32 (CALLBACK* _GStest)(); +typedef void (CALLBACK* _GSabout)(); + +// PAD +typedef s32 (CALLBACK* _PADinit)(u32 flags); +typedef s32 (CALLBACK* _PADopen)(void *pDsp); +typedef void (CALLBACK* _PADclose)(); +typedef void (CALLBACK* _PADshutdown)(); +typedef keyEvent* (CALLBACK* _PADkeyEvent)(); +typedef u8 (CALLBACK* _PADstartPoll)(int pad); +typedef u8 (CALLBACK* _PADpoll)(u8 value); +typedef u32 (CALLBACK* _PADquery)(); + +typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info); +typedef void (CALLBACK* _PADconfigure)(); +typedef s32 (CALLBACK* _PADtest)(); +typedef void (CALLBACK* _PADabout)(); + +// SPU2 +typedef s32 (CALLBACK* _SPU2init)(); +typedef s32 (CALLBACK* _SPU2open)(void *pDsp); +typedef void (CALLBACK* _SPU2close)(); +typedef void (CALLBACK* _SPU2shutdown)(); +typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value); +typedef u16 (CALLBACK* _SPU2read)(u32 mem); +typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA4)(); +typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA7)(); +typedef void (CALLBACK* _SPU2irqCallback)(void (*callback)()); + +typedef void (CALLBACK* _SPU2async)(u32 cycles); +typedef s32 (CALLBACK* _SPU2freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _SPU2configure)(); +typedef s32 (CALLBACK* _SPU2test)(); +typedef void (CALLBACK* _SPU2about)(); + +// CDVD +typedef s32 (CALLBACK* _CDVDinit)(); +typedef s32 (CALLBACK* _CDVDopen)(); +typedef void (CALLBACK* _CDVDclose)(); +typedef void (CALLBACK* _CDVDshutdown)(); +typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef u8* (CALLBACK* _CDVDgetBuffer)(); +typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer); +typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer); +typedef s32 (CALLBACK* _CDVDgetType)(); +typedef s32 (CALLBACK* _CDVDgetTrayStatus)(); + +typedef void (CALLBACK* _CDVDconfigure)(); +typedef s32 (CALLBACK* _CDVDtest)(); +typedef void (CALLBACK* _CDVDabout)(); + +// DEV9 +typedef s32 (CALLBACK* _DEV9init)(); +typedef s32 (CALLBACK* _DEV9open)(void *pDsp); +typedef void (CALLBACK* _DEV9close)(); +typedef void (CALLBACK* _DEV9shutdown)(); +typedef u8 (CALLBACK* _DEV9read8)(u32 mem); +typedef u16 (CALLBACK* _DEV9read16)(u32 mem); +typedef u32 (CALLBACK* _DEV9read32)(u32 mem); +typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value); +typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value); +typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value); +typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback); +typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void); + +typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _DEV9configure)(); +typedef s32 (CALLBACK* _DEV9test)(); +typedef void (CALLBACK* _DEV9about)(); + +// USB +typedef s32 (CALLBACK* _USBinit)(); +typedef s32 (CALLBACK* _USBopen)(void *pDsp); +typedef void (CALLBACK* _USBclose)(); +typedef void (CALLBACK* _USBshutdown)(); +typedef u8 (CALLBACK* _USBread8)(u32 mem); +typedef u16 (CALLBACK* _USBread16)(u32 mem); +typedef u32 (CALLBACK* _USBread32)(u32 mem); +typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _USBirqCallback)(USBcallback callback); +typedef USBhandler (CALLBACK* _USBirqHandler)(void); +typedef void (CALLBACK* _USBsetRAM)(void *mem); + +typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _USBconfigure)(); +typedef s32 (CALLBACK* _USBtest)(); +typedef void (CALLBACK* _USBabout)(); + +//FireWire +typedef s32 (CALLBACK* _FireWireinit)(); +typedef s32 (CALLBACK* _FireWireopen)(void *pDsp); +typedef void (CALLBACK* _FireWireclose)(); +typedef void (CALLBACK* _FireWireshutdown)(); +typedef u32 (CALLBACK* _FireWireread32)(u32 mem); +typedef void (CALLBACK* _FireWirewrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _FireWireirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _FireWirefreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _FireWireconfigure)(); +typedef s32 (CALLBACK* _FireWiretest)(); +typedef void (CALLBACK* _FireWireabout)(); + +#endif + +#ifdef PLUGINfuncs + +// GS +_GSinit GSinit; +_GSopen GSopen; +_GSclose GSclose; +_GSshutdown GSshutdown; +_GSvsync GSvsync; +_GSwrite32 GSwrite32; +_GSwrite64 GSwrite64; +_GSread32 GSread32; +_GSread64 GSread64; +_GSgifTransfer1 GSgifTransfer1; +_GSgifTransfer2 GSgifTransfer2; +_GSgifTransfer3 GSgifTransfer3; +_GSreadFIFO GSreadFIFO; + +_GSkeyEvent GSkeyEvent; +_GSmakeSnapshot GSmakeSnapshot; +_GSirqCallback GSirqCallback; +_GSprintf GSprintf; +_GSgetDriverInfo GSgetDriverInfo; +#ifdef __WIN32__ +_GSsetWindowInfo GSsetWindowInfo; +#endif +_GSfreeze GSfreeze; +_GSconfigure GSconfigure; +_GStest GStest; +_GSabout GSabout; + +// PAD1 +_PADinit PAD1init; +_PADopen PAD1open; +_PADclose PAD1close; +_PADshutdown PAD1shutdown; +_PADkeyEvent PAD1keyEvent; +_PADstartPoll PAD1startPoll; +_PADpoll PAD1poll; +_PADquery PAD1query; + +_PADgsDriverInfo PAD1gsDriverInfo; +_PADconfigure PAD1configure; +_PADtest PAD1test; +_PADabout PAD1about; + +// PAD2 +_PADinit PAD2init; +_PADopen PAD2open; +_PADclose PAD2close; +_PADshutdown PAD2shutdown; +_PADkeyEvent PAD2keyEvent; +_PADstartPoll PAD2startPoll; +_PADpoll PAD2poll; +_PADquery PAD2query; + +_PADgsDriverInfo PAD2gsDriverInfo; +_PADconfigure PAD2configure; +_PADtest PAD2test; +_PADabout PAD2about; + +// SPU2 +_SPU2init SPU2init; +_SPU2open SPU2open; +_SPU2close SPU2close; +_SPU2shutdown SPU2shutdown; +_SPU2write SPU2write; +_SPU2read SPU2read; +_SPU2readDMA4Mem SPU2readDMA4Mem; +_SPU2writeDMA4Mem SPU2writeDMA4Mem; +_SPU2interruptDMA4 SPU2interruptDMA4; +_SPU2readDMA7Mem SPU2readDMA7Mem; +_SPU2writeDMA7Mem SPU2writeDMA7Mem; +_SPU2interruptDMA7 SPU2interruptDMA7; +_SPU2irqCallback SPU2irqCallback; + +_SPU2async SPU2async; +_SPU2freeze SPU2freeze; +_SPU2configure SPU2configure; +_SPU2test SPU2test; +_SPU2about SPU2about; + +// CDVD +_CDVDinit CDVDinit; +_CDVDopen CDVDopen; +_CDVDclose CDVDclose; +_CDVDshutdown CDVDshutdown; +_CDVDreadTrack CDVDreadTrack; +_CDVDgetBuffer CDVDgetBuffer; +_CDVDgetTN CDVDgetTN; +_CDVDgetTD CDVDgetTD; +_CDVDgetType CDVDgetType; +_CDVDgetTrayStatus CDVDgetTrayStatus; + +_CDVDconfigure CDVDconfigure; +_CDVDtest CDVDtest; +_CDVDabout CDVDabout; + +// DEV9 +_DEV9init DEV9init; +_DEV9open DEV9open; +_DEV9close DEV9close; +_DEV9shutdown DEV9shutdown; +_DEV9read8 DEV9read8; +_DEV9read16 DEV9read16; +_DEV9read32 DEV9read32; +_DEV9write8 DEV9write8; +_DEV9write16 DEV9write16; +_DEV9write32 DEV9write32; +_DEV9readDMA8Mem DEV9readDMA8Mem; +_DEV9writeDMA8Mem DEV9writeDMA8Mem; +_DEV9irqCallback DEV9irqCallback; +_DEV9irqHandler DEV9irqHandler; + +_DEV9configure DEV9configure; +_DEV9freeze DEV9freeze; +_DEV9test DEV9test; +_DEV9about DEV9about; + +// USB +_USBinit USBinit; +_USBopen USBopen; +_USBclose USBclose; +_USBshutdown USBshutdown; +_USBread8 USBread8; +_USBread16 USBread16; +_USBread32 USBread32; +_USBwrite8 USBwrite8; +_USBwrite16 USBwrite16; +_USBwrite32 USBwrite32; +_USBirqCallback USBirqCallback; +_USBirqHandler USBirqHandler; +_USBsetRAM USBsetRAM; + +_USBconfigure USBconfigure; +_USBfreeze USBfreeze; +_USBtest USBtest; +_USBabout USBabout; + +// FireWire +_FireWireinit FireWireinit; +_FireWireopen FireWireopen; +_FireWireclose FireWireclose; +_FireWireshutdown FireWireshutdown; +_FireWireread32 FireWireread32; +_FireWirewrite32 FireWirewrite32; +_FireWireirqCallback FireWireirqCallback; + +_FireWireconfigure FireWireconfigure; +_FireWirefreeze FireWirefreeze; +_FireWiretest FireWiretest; +_FireWireabout FireWireabout; +#endif + +#endif /* __PS2EDEFS_H__ */ diff --git a/plugins/dev9ghzdrk/PS2Etypes.h b/plugins/dev9ghzdrk/PS2Etypes.h new file mode 100644 index 000000000..f7a2fffda --- /dev/null +++ b/plugins/dev9ghzdrk/PS2Etypes.h @@ -0,0 +1,31 @@ +#ifndef __PS2ETYPES_H__ +#define __PS2ETYPES_H__ + +// Basic types +#if defined(__WIN32__) + +typedef __int8 s8; +typedef __int16 s16; +typedef __int32 s32; +typedef __int64 s64; + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +#elif defined(__LINUX__) + +typedef char s8; +typedef short s16; +typedef long s32; +typedef long long s64; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; +typedef unsigned long long u64; + +#endif + +#endif /* __PS2ETYPES_H__ */ diff --git a/plugins/dev9ghzdrk/Packet32.h b/plugins/dev9ghzdrk/Packet32.h new file mode 100644 index 000000000..64be055d9 --- /dev/null +++ b/plugins/dev9ghzdrk/Packet32.h @@ -0,0 +1,359 @@ +/* + * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy) + * Copyright (c) 2005 - 2007 CACE Technologies, Davis (California) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Politecnico di Torino, CACE Technologies + * nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** @ingroup packetapi + * @{ + */ + +/** @defgroup packet32h Packet.dll definitions and data structures + * Packet32.h contains the data structures and the definitions used by packet.dll. + * The file is used both by the Win9x and the WinNTx versions of packet.dll, and can be included + * by the applications that use the functions of this library + * @{ + */ + +#ifndef __PACKET32 +#define __PACKET32 + +#include + +#ifdef HAVE_AIRPCAP_API +#include +#else +#if !defined(AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_) +#define AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_ +typedef struct _AirpcapHandle *PAirpcapHandle; +#endif /* AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_ */ +#endif /* HAVE_AIRPCAP_API */ + +#ifdef HAVE_DAG_API +#include +#endif /* HAVE_DAG_API */ + +// Working modes +#define PACKET_MODE_CAPT 0x0 ///< Capture mode +#define PACKET_MODE_STAT 0x1 ///< Statistical mode +#define PACKET_MODE_MON 0x2 ///< Monitoring mode +#define PACKET_MODE_DUMP 0x10 ///< Dump mode +#define PACKET_MODE_STAT_DUMP MODE_DUMP | MODE_STAT ///< Statistical dump Mode + + +/// Alignment macro. Defines the alignment size. +#define Packet_ALIGNMENT sizeof(int) +/// Alignment macro. Rounds up to the next even multiple of Packet_ALIGNMENT. +#define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1)) + +#define NdisMediumNull -1 ///< Custom linktype: NDIS doesn't provide an equivalent +#define NdisMediumCHDLC -2 ///< Custom linktype: NDIS doesn't provide an equivalent +#define NdisMediumPPPSerial -3 ///< Custom linktype: NDIS doesn't provide an equivalent +#define NdisMediumBare80211 -4 ///< Custom linktype: NDIS doesn't provide an equivalent +#define NdisMediumRadio80211 -5 ///< Custom linktype: NDIS doesn't provide an equivalent +#define NdisMediumPpi -6 ///< Custom linktype: NDIS doesn't provide an equivalent + +// Loopback behaviour definitions +#define NPF_DISABLE_LOOPBACK 1 ///< Drop the packets sent by the NPF driver +#define NPF_ENABLE_LOOPBACK 2 ///< Capture the packets sent by the NPF driver + +/*! + \brief Network type structure. + + This structure is used by the PacketGetNetType() function to return information on the current adapter's type and speed. +*/ +typedef struct NetType +{ + UINT LinkType; ///< The MAC of the current network adapter (see function PacketGetNetType() for more information) + ULONGLONG LinkSpeed; ///< The speed of the network in bits per second +}NetType; + + +//some definitions stolen from libpcap + +#ifndef BPF_MAJOR_VERSION + +/*! + \brief A BPF pseudo-assembly program. + + The program will be injected in the kernel by the PacketSetBPF() function and applied to every incoming packet. +*/ +struct bpf_program +{ + UINT bf_len; ///< Indicates the number of instructions of the program, i.e. the number of struct bpf_insn that will follow. + struct bpf_insn *bf_insns; ///< A pointer to the first instruction of the program. +}; + +/*! + \brief A single BPF pseudo-instruction. + + bpf_insn contains a single instruction for the BPF register-machine. It is used to send a filter program to the driver. +*/ +struct bpf_insn +{ + USHORT code; ///< Instruction type and addressing mode. + UCHAR jt; ///< Jump if true + UCHAR jf; ///< Jump if false + int k; ///< Generic field used for various purposes. +}; + +/*! + \brief Structure that contains a couple of statistics values on the current capture. + + It is used by packet.dll to return statistics about a capture session. +*/ +struct bpf_stat +{ + UINT bs_recv; ///< Number of packets that the driver received from the network adapter + ///< from the beginning of the current capture. This value includes the packets + ///< lost by the driver. + UINT bs_drop; ///< number of packets that the driver lost from the beginning of a capture. + ///< Basically, a packet is lost when the the buffer of the driver is full. + ///< In this situation the packet cannot be stored and the driver rejects it. + UINT ps_ifdrop; ///< drops by interface. XXX not yet supported + UINT bs_capt; ///< number of packets that pass the filter, find place in the kernel buffer and + ///< thus reach the application. +}; + +/*! + \brief Packet header. + + This structure defines the header associated with every packet delivered to the application. +*/ +struct bpf_hdr +{ + struct timeval bh_tstamp; ///< The timestamp associated with the captured packet. + ///< It is stored in a TimeVal structure. + UINT bh_caplen; ///< Length of captured portion. The captured portion can be different + ///< from the original packet, because it is possible (with a proper filter) + ///< to instruct the driver to capture only a portion of the packets. + UINT bh_datalen; ///< Original length of packet + USHORT bh_hdrlen; ///< Length of bpf header (this struct plus alignment padding). In some cases, + ///< a padding could be added between the end of this structure and the packet + ///< data for performance reasons. This filed can be used to retrieve the actual data + ///< of the packet. +}; + +/*! + \brief Dump packet header. + + This structure defines the header associated with the packets in a buffer to be used with PacketSendPackets(). + It is simpler than the bpf_hdr, because it corresponds to the header associated by WinPcap and libpcap to a + packet in a dump file. This makes straightforward sending WinPcap dump files to the network. +*/ +struct dump_bpf_hdr{ + struct timeval ts; ///< Time stamp of the packet + UINT caplen; ///< Length of captured portion. The captured portion can smaller than the + ///< the original packet, because it is possible (with a proper filter) to + ///< instruct the driver to capture only a portion of the packets. + UINT len; ///< Length of the original packet (off wire). +}; + + +#endif + +struct bpf_stat; + +#define DOSNAMEPREFIX TEXT("Packet_") ///< Prefix added to the adapters device names to create the WinPcap devices +#define MAX_LINK_NAME_LENGTH 64 //< Maximum length of the devices symbolic links +#define NMAX_PACKET 65535 + +/*! + \brief Addresses of a network adapter. + + This structure is used by the PacketGetNetInfoEx() function to return the IP addresses associated with + an adapter. +*/ +typedef struct npf_if_addr { + struct sockaddr_storage IPAddress; ///< IP address. + struct sockaddr_storage SubnetMask; ///< Netmask for that address. + struct sockaddr_storage Broadcast; ///< Broadcast address. +}npf_if_addr; + + +#define ADAPTER_NAME_LENGTH 256 + 12 ///< Maximum length for the name of an adapter. The value is the same used by the IP Helper API. +#define ADAPTER_DESC_LENGTH 128 ///< Maximum length for the description of an adapter. The value is the same used by the IP Helper API. +#define MAX_MAC_ADDR_LENGTH 8 ///< Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API. +#define MAX_NETWORK_ADDRESSES 16 ///< Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API. + + +typedef struct WAN_ADAPTER_INT WAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API +typedef WAN_ADAPTER *PWAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API + +#define INFO_FLAG_NDIS_ADAPTER 0 ///< Flag for ADAPTER_INFO: this is a traditional ndis adapter +#define INFO_FLAG_NDISWAN_ADAPTER 1 ///< Flag for ADAPTER_INFO: this is a NdisWan adapter, and it's managed by WANPACKET +#define INFO_FLAG_DAG_CARD 2 ///< Flag for ADAPTER_INFO: this is a DAG card +#define INFO_FLAG_DAG_FILE 6 ///< Flag for ADAPTER_INFO: this is a DAG file +#define INFO_FLAG_DONT_EXPORT 8 ///< Flag for ADAPTER_INFO: when this flag is set, the adapter will not be listed or openend by winpcap. This allows to prevent exporting broken network adapters, like for example FireWire ones. +#define INFO_FLAG_AIRPCAP_CARD 16 ///< Flag for ADAPTER_INFO: this is an airpcap card +#define INFO_FLAG_NPFIM_DEVICE 32 + +/*! + \brief Describes an opened network adapter. + + This structure is the most important for the functioning of packet.dll, but the great part of its fields + should be ignored by the user, since the library offers functions that avoid to cope with low-level parameters +*/ +typedef struct _ADAPTER { + HANDLE hFile; ///< \internal Handle to an open instance of the NPF driver. + CHAR SymbolicLink[MAX_LINK_NAME_LENGTH]; ///< \internal A string containing the name of the network adapter currently opened. + int NumWrites; ///< \internal Number of times a packets written on this adapter will be repeated + ///< on the wire. + HANDLE ReadEvent; ///< A notification event associated with the read calls on the adapter. + ///< It can be passed to standard Win32 functions (like WaitForSingleObject + ///< or WaitForMultipleObjects) to wait until the driver's buffer contains some + ///< data. It is particularly useful in GUI applications that need to wait + ///< concurrently on several events. In Windows NT/2000 the PacketSetMinToCopy() + ///< function can be used to define the minimum amount of data in the kernel buffer + ///< that will cause the event to be signalled. + + UINT ReadTimeOut; ///< \internal The amount of time after which a read on the driver will be released and + ///< ReadEvent will be signaled, also if no packets were captured + CHAR Name[ADAPTER_NAME_LENGTH]; + PWAN_ADAPTER pWanAdapter; + UINT Flags; ///< Adapter's flags. Tell if this adapter must be treated in a different way, using the Netmon API or the dagc API. + +#ifdef HAVE_AIRPCAP_API + PAirpcapHandle AirpcapAd; +#endif // HAVE_AIRPCAP_API + +#ifdef HAVE_NPFIM_API + void* NpfImHandle; +#endif // HAVE_NPFIM_API + +#ifdef HAVE_DAG_API + dagc_t *pDagCard; ///< Pointer to the dagc API adapter descriptor for this adapter + PCHAR DagBuffer; ///< Pointer to the buffer with the packets that is received from the DAG card + struct timeval DagReadTimeout; ///< Read timeout. The dagc API requires a timeval structure + unsigned DagFcsLen; ///< Length of the frame check sequence attached to any packet by the card. Obtained from the registry + DWORD DagFastProcess; ///< True if the user requests fast capture processing on this card. Higher level applications can use this value to provide a faster but possibly unprecise capture (for example, libpcap doesn't convert the timestamps). +#endif // HAVE_DAG_API +} ADAPTER, *LPADAPTER; + +/*! + \brief Structure that contains a group of packets coming from the driver. + + This structure defines the header associated with every packet delivered to the application. +*/ +typedef struct _PACKET { + HANDLE hEvent; ///< \deprecated Still present for compatibility with old applications. + OVERLAPPED OverLapped; ///< \deprecated Still present for compatibility with old applications. + PVOID Buffer; ///< Buffer with containing the packets. See the PacketReceivePacket() for + ///< details about the organization of the data in this buffer + UINT Length; ///< Length of the buffer + DWORD ulBytesReceived; ///< Number of valid bytes present in the buffer, i.e. amount of data + ///< received by the last call to PacketReceivePacket() + BOOLEAN bIoComplete; ///< \deprecated Still present for compatibility with old applications. +} PACKET, *LPPACKET; + +/*! + \brief Structure containing an OID request. + + It is used by the PacketRequest() function to send an OID to the interface card driver. + It can be used, for example, to retrieve the status of the error counters on the adapter, its MAC address, + the list of the multicast groups defined on it, and so on. +*/ +struct _PACKET_OID_DATA { + ULONG Oid; ///< OID code. See the Microsoft DDK documentation or the file ntddndis.h + ///< for a complete list of valid codes. + ULONG Length; ///< Length of the data field + UCHAR Data[1]; ///< variable-lenght field that contains the information passed to or received + ///< from the adapter. +}; +typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @} + */ + +/* +BOOLEAN QueryWinPcapRegistryStringA(CHAR *SubKeyName, + CHAR *Value, + UINT *pValueLen, + CHAR *DefaultVal); + +BOOLEAN QueryWinPcapRegistryStringW(WCHAR *SubKeyName, + WCHAR *Value, + UINT *pValueLen, + WCHAR *DefaultVal); +*/ + +//--------------------------------------------------------------------------- +// EXPORTED FUNCTIONS +//--------------------------------------------------------------------------- + +PCHAR PacketGetVersion(); +PCHAR PacketGetDriverVersion(); +BOOLEAN PacketSetMinToCopy(LPADAPTER AdapterObject,int nbytes); +BOOLEAN PacketSetNumWrites(LPADAPTER AdapterObject,int nwrites); +BOOLEAN PacketSetMode(LPADAPTER AdapterObject,int mode); +BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout); +BOOLEAN PacketSetBpf(LPADAPTER AdapterObject,struct bpf_program *fp); +BOOLEAN PacketSetLoopbackBehavior(LPADAPTER AdapterObject, UINT LoopbackBehavior); +INT PacketSetSnapLen(LPADAPTER AdapterObject,int snaplen); +BOOLEAN PacketGetStats(LPADAPTER AdapterObject,struct bpf_stat *s); +BOOLEAN PacketGetStatsEx(LPADAPTER AdapterObject,struct bpf_stat *s); +BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim); +BOOLEAN PacketGetNetType (LPADAPTER AdapterObject,NetType *type); +LPADAPTER PacketOpenAdapter(PCHAR AdapterName); +BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET pPacket,BOOLEAN Sync); +INT PacketSendPackets(LPADAPTER AdapterObject,PVOID PacketBuff,ULONG Size, BOOLEAN Sync); +LPPACKET PacketAllocatePacket(void); +VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length); +VOID PacketFreePacket(LPPACKET lpPacket); +BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync); +BOOLEAN PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter); +BOOLEAN PacketGetAdapterNames(PTSTR pStr,PULONG BufferSize); +BOOLEAN PacketGetNetInfoEx(PCHAR AdapterName, npf_if_addr* buffer, PLONG NEntries); +BOOLEAN PacketRequest(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData); +HANDLE PacketGetReadEvent(LPADAPTER AdapterObject); +BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject, void *name, int len); +BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject, UINT maxfilesize, UINT maxnpacks); +BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject, BOOLEAN sync); +BOOL PacketStopDriver(); +VOID PacketCloseAdapter(LPADAPTER lpAdapter); +BOOLEAN PacketStartOem(PCHAR errorString, UINT errorStringLength); +BOOLEAN PacketStartOemEx(PCHAR errorString, UINT errorStringLength, ULONG flags); +PAirpcapHandle PacketGetAirPcapHandle(LPADAPTER AdapterObject); + +// +// Used by PacketStartOemEx +// +#define PACKET_START_OEM_NO_NETMON 0x00000001 + +#ifdef __cplusplus +} +#endif + +#endif //__PACKET32 diff --git a/plugins/dev9ghzdrk/Win32-Extensions.h b/plugins/dev9ghzdrk/Win32-Extensions.h new file mode 100644 index 000000000..ad3be25cf --- /dev/null +++ b/plugins/dev9ghzdrk/Win32-Extensions.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy) + * Copyright (c) 2005 - 2006 CACE Technologies, Davis (California) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Politecnico di Torino, CACE Technologies + * nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __WIN32_EXTENSIONS_H__ +#define __WIN32_EXTENSIONS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Definitions */ + +/*! + \brief A queue of raw packets that will be sent to the network with pcap_sendqueue_transmit(). +*/ +struct pcap_send_queue +{ + u_int maxlen; ///< Maximum size of the the queue, in bytes. This variable contains the size of the buffer field. + u_int len; ///< Current size of the queue, in bytes. + char *buffer; ///< Buffer containing the packets to be sent. +}; + +typedef struct pcap_send_queue pcap_send_queue; + +/*! + \brief This typedef is a support for the pcap_get_airpcap_handle() function +*/ +#if !defined(AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_) +#define AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_ +typedef struct _AirpcapHandle *PAirpcapHandle; +#endif + +#define BPF_MEM_EX_IMM 0xc0 +#define BPF_MEM_EX_IND 0xe0 + +/*used for ST*/ +#define BPF_MEM_EX 0xc0 +#define BPF_TME 0x08 + +#define BPF_LOOKUP 0x90 +#define BPF_EXECUTE 0xa0 +#define BPF_INIT 0xb0 +#define BPF_VALIDATE 0xc0 +#define BPF_SET_ACTIVE 0xd0 +#define BPF_RESET 0xe0 +#define BPF_SET_MEMORY 0x80 +#define BPF_GET_REGISTER_VALUE 0x70 +#define BPF_SET_REGISTER_VALUE 0x60 +#define BPF_SET_WORKING 0x50 +#define BPF_SET_ACTIVE_READ 0x40 +#define BPF_SET_AUTODELETION 0x30 +#define BPF_SEPARATION 0xff + +/* Prototypes */ +pcap_send_queue* pcap_sendqueue_alloc(u_int memsize); + +void pcap_sendqueue_destroy(pcap_send_queue* queue); + +int pcap_sendqueue_queue(pcap_send_queue* queue, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data); + +u_int pcap_sendqueue_transmit(pcap_t *p, pcap_send_queue* queue, int sync); + +HANDLE pcap_getevent(pcap_t *p); + +struct pcap_stat *pcap_stats_ex(pcap_t *p, int *pcap_stat_size); + +int pcap_setuserbuffer(pcap_t *p, int size); + +int pcap_live_dump(pcap_t *p, char *filename, int maxsize, int maxpacks); + +int pcap_live_dump_ended(pcap_t *p, int sync); + +int pcap_offline_filter(struct bpf_program *prog, const struct pcap_pkthdr *header, const u_char *pkt_data); + +int pcap_start_oem(char* err_str, int flags); + +PAirpcapHandle pcap_get_airpcap_handle(pcap_t *p); + +#ifdef __cplusplus +} +#endif + +#endif //__WIN32_EXTENSIONS_H__ diff --git a/plugins/dev9ghzdrk/Win32/Config.cpp b/plugins/dev9ghzdrk/Win32/Config.cpp new file mode 100644 index 000000000..9ef667743 --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/Config.cpp @@ -0,0 +1,54 @@ + +#include + +#include +#include "DEV9.h" + +#define GetKeyV(name, var, s, t) \ + size = s; type = t; \ + RegQueryValueEx(myKey, name, 0, &type, (LPBYTE) var, &size); + +#define GetKeyVdw(name, var) \ + GetKeyV(name, var, 4, REG_DWORD); + +#define SetKeyV(name, var, s, t) \ + RegSetValueEx(myKey, name, 0, t, (LPBYTE) var, s); + +#define SetKeyVdw(name, var) \ + SetKeyV(name, var, 4, REG_DWORD); + +void SaveConf() { + HKEY myKey; + DWORD myDisp; + + RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\PS2Eplugin\\DEV9\\DEV9linuz", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &myKey, &myDisp); + SetKeyV("Eth", config.Eth, strlen(config.Eth), REG_SZ); + SetKeyV("Hdd", config.Hdd, strlen(config.Hdd), REG_SZ); + SetKeyVdw("HddSize", &config.HddSize); + SetKeyVdw("ethEnable", &config.ethEnable); + SetKeyVdw("hddEnable", &config.hddEnable); + + RegCloseKey(myKey); +} + +void LoadConf() { + HKEY myKey; + DWORD type, size; + + memset(&config, 0, sizeof(config)); + strcpy(config.Hdd, HDD_DEF); + config.HddSize=8*1024; + strcpy(config.Eth, ETH_DEF); + + if (RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\PS2Eplugin\\DEV9\\DEV9linuz", 0, KEY_ALL_ACCESS, &myKey)!=ERROR_SUCCESS) { + SaveConf(); return; + } + GetKeyV("Eth", config.Eth, sizeof(config.Eth), REG_SZ); + GetKeyV("Hdd", config.Hdd, sizeof(config.Hdd), REG_SZ); + GetKeyVdw("HddSize", &config.HddSize); + GetKeyVdw("ethEnable", &config.ethEnable); + GetKeyVdw("hddEnable", &config.hddEnable); + + RegCloseKey(myKey); +} + diff --git a/plugins/dev9ghzdrk/Win32/Config.h b/plugins/dev9ghzdrk/Win32/Config.h new file mode 100644 index 000000000..4e767be7d --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/Config.h @@ -0,0 +1,2 @@ +void SaveConf(); +void LoadConf(); diff --git a/plugins/dev9ghzdrk/Win32/DEV9ghzdrk.def b/plugins/dev9ghzdrk/Win32/DEV9ghzdrk.def new file mode 100644 index 000000000..1bde44b8a --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/DEV9ghzdrk.def @@ -0,0 +1,28 @@ +; DEV9null.def : Declares the module parameters for the DLL. + +EXPORTS + + ; Explicit exports can go here + + PS2EgetLibType @2 + PS2EgetLibName @3 + PS2EgetLibVersion2 @4 + DEV9init @5 + DEV9shutdown @6 + DEV9open @7 + DEV9close @8 + DEV9read8 @9 + DEV9read16 @10 + DEV9read32 @11 + DEV9write8 @12 + DEV9write16 @13 + DEV9write32 @14 + DEV9readDMA8Mem @15 + DEV9writeDMA8Mem @16 + DEV9configure @17 + DEV9test @18 + DEV9about @19 + DEV9irqCallback @20 + DEV9irqHandler @21 + + DEV9setSettingsDir \ No newline at end of file diff --git a/plugins/dev9ghzdrk/Win32/DEV9ghzdrk.rc b/plugins/dev9ghzdrk/Win32/DEV9ghzdrk.rc new file mode 100644 index 000000000..2013fd27c --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/DEV9ghzdrk.rc @@ -0,0 +1,126 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Spanish (Argentina) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ESS) +#ifdef _WIN32 +LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_ARGENTINA +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CONFIG DIALOGEX 0, 0, 290, 170 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "HDD Configure" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,115,150,50,14 + PUSHBUTTON "Cancel",IDCANCEL,233,150,50,14 + COMBOBOX IDC_BAYTYPE,60,10,223,47,CBS_DROPDOWNLIST | CBS_SORT | WS_DISABLED + LTEXT "DEV9 Type",IDC_STATIC,15,10,41,11,SS_CENTERIMAGE + LTEXT "Ethernet Device",IDC_STATIC,15,60,60,10,SS_CENTERIMAGE + COMBOBOX IDC_ETHDEV,83,60,193,82,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + GROUPBOX "Ethernet",IDC_STATIC,7,30,276,50 + CONTROL "Enabled",IDC_ETHENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,45,42,10 + LTEXT "HDD File",IDC_STATIC,15,115,60,10,SS_CENTERIMAGE | WS_DISABLED + GROUPBOX "Hard Disk Drive (not yet properly implemented)",IDC_STATIC,7,90,276,50 + CONTROL "Enabled",IDC_HDDENABLED,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,15,100,42,10 + EDITTEXT IDC_HDDFILE,85,115,191,12,ES_AUTOHSCROLL | WS_DISABLED +END + +IDD_ABOUT DIALOGEX 0, 0, 177, 106 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "DEV9 About" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,65,85,50,14 + LTEXT "DEV9 Driver",IDC_NAME,59,7,42,8 + LTEXT "Original Authors:\n\tlinuzappz \n\tShadow ",IDC_STATIC,7,18,141,30 + LTEXT "Fixed and improved by:\n\tgigahez \n\tdrk||Raziel",IDC_STATIC,7,49,155,27 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_CONFIG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 283 + TOPMARGIN, 7 + BOTTOMMARGIN, 164 + END + + IDD_ABOUT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 170 + TOPMARGIN, 7 + BOTTOMMARGIN, 99 + END +END +#endif // APSTUDIO_INVOKED + +#endif // Spanish (Argentina) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/dev9ghzdrk/Win32/DEV9ghzdrk.vcxproj b/plugins/dev9ghzdrk/Win32/DEV9ghzdrk.vcxproj new file mode 100644 index 000000000..a2103b905 --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/DEV9ghzdrk.vcxproj @@ -0,0 +1,136 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + DEV9ghzdrk + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3} + DEV9ghzdrk + Win32Proj + + + + DynamicLibrary + MultiByte + true + + + DynamicLibrary + MultiByte + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + EnableFastChecks + MultiThreadedDebug + + + $(ProjectDir)\..;%(AdditionalIncludeDirectories) + + + NDEBUG;%(PreprocessorDefinitions) + 0x0408 + + + $(OutDir)$(TargetName)$(TargetExt) + .\DEV9ghzdrk.def + false + + + MachineX86 + ws2_32.lib;iphlpapi.lib;wpcap.lib;packet.lib;%(AdditionalDependencies) + $(ProjectDir)../pcap/wpcap_32;%(AdditionalLibraryDirectories) + + + + + + + $(ProjectDir)\..;%(AdditionalIncludeDirectories) + + + NDEBUG;%(PreprocessorDefinitions) + 0x0408 + + + DEV9ghzdrk.def + false + + + MachineX86 + $(ProjectDir)../pcap/wpcap_32;%(AdditionalLibraryDirectories) + ws2_32.lib;iphlpapi.lib;wpcap.lib;packet.lib;%(AdditionalDependencies) + + + + + + + + + + + + + true + true + + + true + true + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/dev9ghzdrk/Win32/DEV9ghzdrk.vcxproj.filters b/plugins/dev9ghzdrk/Win32/DEV9ghzdrk.vcxproj.filters new file mode 100644 index 000000000..4225c129d --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/DEV9ghzdrk.vcxproj.filters @@ -0,0 +1,97 @@ + + + + + {c269b350-967d-41e2-9e0e-e454d5bc53c4} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {c19bd699-ac94-4cd8-bb19-c8c47a0a4608} + + + {02c8fe11-fda9-4bc5-80c0-399198b16979} + + + {1c0eef21-bc05-4eaa-9984-27d43ea85743} + + + {8768cdfe-28b8-4cc5-a92e-c4f3f77d7660} + + + {63c91c1b-ddb1-49de-b9e1-198780595d23} + + + {068d3325-67a3-42e1-9091-91d5b4228dea} + h;hpp;hxx;hm;inl + + + {30994d8f-3093-437c-8bb0-5d22f02f59ef} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Source Files + + + Source Files + + + Source Files\smap + + + Source Files\ethernet i/o + + + Source Files\ethernet i/o\tap + + + Source Files\ethernet i/o\sock + + + Source Files\ethernet i/o\sock + + + Source Files + + + Source Files + + + Source Files\ethernet i/o\pcap + + + + + Source Files + + + + + Source Files + + + Source Files\smap + + + Source Files\ethernet i/o + + + Source Files\ethernet i/o\pcap + + + Source Files\ethernet i/o\tap + + + Header Files + + + Header Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/plugins/dev9ghzdrk/Win32/Devioctl.h b/plugins/dev9ghzdrk/Win32/Devioctl.h new file mode 100644 index 000000000..661fda029 --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/Devioctl.h @@ -0,0 +1,90 @@ +/*++ BUILD Version: 0004 // Increment this if a change has global effects + Copyright (c) 1992-1993 Microsoft Corporation + Module Name: + devioctl.h + Revision History: + -- */ +// begin_winioctl +#ifndef _DEVIOCTL_ +#define _DEVIOCTL_ +// begin_ntddk begin_nthal begin_ntifs +// +// Define the various device type values. Note that values used by Microsoft +// Corporation are in the range 0-32767, and 32768-65535 are reserved for use +// by customers. +// +#define DEVICE_TYPE ULONG +#define FILE_DEVICE_BEEP 0x00000001 +#define FILE_DEVICE_CD_ROM 0x00000002 +#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003 +#define FILE_DEVICE_CONTROLLER 0x00000004 +#define FILE_DEVICE_DATALINK 0x00000005 +#define FILE_DEVICE_DFS 0x00000006 +#define FILE_DEVICE_DISK 0x00000007 +#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008 +#define FILE_DEVICE_FILE_SYSTEM 0x00000009 +#define FILE_DEVICE_INPORT_PORT 0x0000000a +#define FILE_DEVICE_KEYBOARD 0x0000000b +#define FILE_DEVICE_MAILSLOT 0x0000000c +#define FILE_DEVICE_MIDI_IN 0x0000000d +#define FILE_DEVICE_MIDI_OUT 0x0000000e +#define FILE_DEVICE_MOUSE 0x0000000f +#define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010 +#define FILE_DEVICE_NAMED_PIPE 0x00000011 +#define FILE_DEVICE_NETWORK 0x00000012 +#define FILE_DEVICE_NETWORK_BROWSER 0x00000013 +#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014 +#define FILE_DEVICE_NULL 0x00000015 +#define FILE_DEVICE_PARALLEL_PORT 0x00000016 +#define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017 +#define FILE_DEVICE_PRINTER 0x00000018 +#define FILE_DEVICE_SCANNER 0x00000019 +#define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001a +#define FILE_DEVICE_SERIAL_PORT 0x0000001b +#define FILE_DEVICE_SCREEN 0x0000001c +#define FILE_DEVICE_SOUND 0x0000001d +#define FILE_DEVICE_STREAMS 0x0000001e +#define FILE_DEVICE_TAPE 0x0000001f +#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020 +#define FILE_DEVICE_TRANSPORT 0x00000021 +#define FILE_DEVICE_UNKNOWN 0x00000022 +#define FILE_DEVICE_VIDEO 0x00000023 +#define FILE_DEVICE_VIRTUAL_DISK 0x00000024 +#define FILE_DEVICE_WAVE_IN 0x00000025 +#define FILE_DEVICE_WAVE_OUT 0x00000026 +#define FILE_DEVICE_8042_PORT 0x00000027 +#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028 +#define FILE_DEVICE_BATTERY 0x00000029 +#define FILE_DEVICE_BUS_EXTENDER 0x0000002a +#define FILE_DEVICE_MODEM 0x0000002b +#define FILE_DEVICE_VDM 0x0000002c +#define FILE_DEVICE_MASS_STORAGE 0x0000002d +// +// Macro definition for defining IOCTL and FSCTL function control codes. Note +// that function codes 0-2047 are reserved for Microsoft Corporation, and +// 2048-4095 are reserved for customers. +// +#define CTL_CODE( DeviceType, Function, Method, Access ) ( \ + ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ +) +// +// Define the method codes for how buffers are passed for I/O and FS controls +// +#define METHOD_BUFFERED 0 +#define METHOD_IN_DIRECT 1 +#define METHOD_OUT_DIRECT 2 +#define METHOD_NEITHER 3 +// +// Define the access check value for any access +// +// +// The FILE_READ_ACCESS and FILE_WRITE_ACCESS constants are also defined in +// ntioapi.h as FILE_READ_DATA and FILE_WRITE_DATA. The values for these +// constants *MUST* always be in sync. +// +#define FILE_ANY_ACCESS 0 +#define FILE_READ_ACCESS ( 0x0001 ) // file & pipe +#define FILE_WRITE_ACCESS ( 0x0002 ) // file & pipe +// end_ntddk end_nthal end_ntifs +#endif // _DEVIOCTL_ +// end_winioctl diff --git a/plugins/dev9ghzdrk/Win32/ProjectRootDir.props b/plugins/dev9ghzdrk/Win32/ProjectRootDir.props new file mode 100644 index 000000000..8d9f9ad37 --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/ProjectRootDir.props @@ -0,0 +1,15 @@ + + + + $(ProjectRootDir)\..\.. + $(SvnRootDir)\common + + + <_ProjectFileVersion>10.0.30128.1 + + + + $(SvnRootDir) + + + \ No newline at end of file diff --git a/plugins/dev9ghzdrk/Win32/ProjectRootDir.vsprops b/plugins/dev9ghzdrk/Win32/ProjectRootDir.vsprops new file mode 100644 index 000000000..b8400f4c9 --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/ProjectRootDir.vsprops @@ -0,0 +1,11 @@ + + + + diff --git a/plugins/dev9ghzdrk/Win32/Win32.cpp b/plugins/dev9ghzdrk/Win32/Win32.cpp new file mode 100644 index 000000000..31224e87b --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/Win32.cpp @@ -0,0 +1,168 @@ +#include +#include +#include +#include + +#include "Config.h" +#include "resource.h" +#include "DEV9.h" +#include "pcap.h" +#include "pcap_io.h" +#include "net.h" +#include "tap.h" + +extern HINSTANCE hInst; +//HANDLE handleDEV9Thread = NULL; +//DWORD dwThreadId, dwThrdParam; + +void SysMessage(char *fmt, ...) { + va_list list; + char tmp[512]; + + va_start(list,fmt); + vsprintf(tmp,fmt,list); + va_end(list); + MessageBox(0, tmp, "Dev9linuz Msg", 0); +} + +void OnInitDialog(HWND hW) { + char *dev; + //int i; + + LoadConf(); + + ComboBox_AddString(GetDlgItem(hW, IDC_BAYTYPE), "Expansion"); + ComboBox_AddString(GetDlgItem(hW, IDC_BAYTYPE), "PC Card"); + for (int j=0;j<2;j++) + { + for (int i=0; i * al=GetTapAdapters(); + for (int i=0; isize(); i++) { + + int itm=ComboBox_AddString(GetDlgItem(hW, IDC_ETHDEV), al[0][i].name.c_str()); + ComboBox_SetItemData(GetDlgItem(hW, IDC_ETHDEV),itm,strdup( al[0][i].guid.c_str())); + if (strcmp(al[0][i].guid.c_str(), config.Eth) == 0) { + ComboBox_SetCurSel(GetDlgItem(hW, IDC_ETHDEV), itm); + } + } + + Edit_SetText(GetDlgItem(hW, IDC_HDDFILE), config.Hdd); + + Button_SetCheck(GetDlgItem(hW, IDC_ETHENABLED), config.ethEnable); + Button_SetCheck(GetDlgItem(hW, IDC_HDDENABLED), config.hddEnable); +} + +void OnOk(HWND hW) { + int i = ComboBox_GetCurSel(GetDlgItem(hW, IDC_ETHDEV)); + char* ptr=(char*)ComboBox_GetItemData(GetDlgItem(hW, IDC_ETHDEV),i); + strcpy(config.Eth, ptr); + Edit_GetText(GetDlgItem(hW, IDC_HDDFILE), config.Hdd, 256); + + config.ethEnable = Button_GetCheck(GetDlgItem(hW, IDC_ETHENABLED)); + config.hddEnable = Button_GetCheck(GetDlgItem(hW, IDC_HDDENABLED)); + + SaveConf(); + + EndDialog(hW, TRUE); +} + +BOOL CALLBACK ConfigureDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + + switch(uMsg) { + case WM_INITDIALOG: + OnInitDialog(hW); + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDCANCEL: + EndDialog(hW, FALSE); + return TRUE; + case IDOK: + OnOk(hW); + return TRUE; + } + } + return FALSE; +} + +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 DEV9configure() { + DialogBox(hInst, + MAKEINTRESOURCE(IDD_CONFIG), + GetActiveWindow(), + (DLGPROC)ConfigureDlgProc); + //SysMessage("Nothing to Configure"); +} + +void CALLBACK DEV9about() { + 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 :) +} +/* +UINT DEV9ThreadProc() { + DEV9thread(); + + return 0; +}*/ +NetAdapter* GetNetAdapter() +{ + if(config.Eth[0]=='p') + { + return new PCAPAdapter(); + } + else if (config.Eth[0]=='t') + { + return new TAPAdapter(); + } + else + return 0; +} +s32 _DEV9open() +{ + //handleDEV9Thread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) DEV9ThreadProc, &dwThrdParam, CREATE_SUSPENDED, &dwThreadId); + //SetThreadPriority(handleDEV9Thread,THREAD_PRIORITY_HIGHEST); + //ResumeThread (handleDEV9Thread); + NetAdapter* na=GetNetAdapter(); + if (!na) + emu_printf("Failed to GetNetAdapter()\n"); + InitNet( na); + return 0; +} + +void _DEV9close() { + //TerminateThread(handleDEV9Thread,0); + //handleDEV9Thread = NULL; + TermNet(); +} diff --git a/plugins/dev9ghzdrk/Win32/_Ntddndis.h b/plugins/dev9ghzdrk/Win32/_Ntddndis.h new file mode 100644 index 000000000..77a53d7af --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/_Ntddndis.h @@ -0,0 +1,1400 @@ +/*++ BUILD Version: 0001 // Increment this if a change has global effects + Copyright (c) 1990-1993 Microsoft Corporation + Module Name: + ntddndis.h + Abstract: + This is the include file that defines all constants and types for + accessing the Network driver interface device. + Author: + Steve Wood (stevewo) 27-May-1990 + Revision History: + Adam Barr (adamba) 04-Nov-1992 added the correct values for NDIS 3.0. + Jameel Hyder (jameelh) 01-Aug-95 added Pnp IoCTLs and structures + Kyle Brandon (kyleb) 09/24/96 added general co ndis oids. + -- */ +#ifndef _NTDDNDIS_ +#define _NTDDNDIS_ +// +// Device Name - this string is the name of the device. It is the name +// that should be passed to NtOpenFile when accessing the device. +// +// Note: For devices that support multiple units, it should be suffixed +// with the Ascii representation of the unit number. +// +#define DD_NDIS_DEVICE_NAME "\\Device\\UNKNOWN" +// +// NtDeviceIoControlFile IoControlCode values for this device. +// +// Warning: Remember that the low two bits of the code specify how the +// buffers are passed to the driver! +// +#define _NDIS_CONTROL_CODE(request,method) \ + CTL_CODE(FILE_DEVICE_PHYSICAL_NETCARD, request, method, FILE_ANY_ACCESS) +#define IOCTL_NDIS_QUERY_GLOBAL_STATS _NDIS_CONTROL_CODE( 0, METHOD_OUT_DIRECT ) +#define IOCTL_NDIS_QUERY_ALL_STATS _NDIS_CONTROL_CODE( 1, METHOD_OUT_DIRECT ) +#define IOCTL_NDIS_ADD_DEVICE _NDIS_CONTROL_CODE( 2, METHOD_BUFFERED ) +#define IOCTL_NDIS_DELETE_DEVICE _NDIS_CONTROL_CODE( 3, METHOD_BUFFERED ) +#define IOCTL_NDIS_TRANSLATE_NAME _NDIS_CONTROL_CODE( 4, METHOD_BUFFERED ) +#define IOCTL_NDIS_ADD_TDI_DEVICE _NDIS_CONTROL_CODE( 5, METHOD_BUFFERED ) +#define IOCTL_NDIS_NOTIFY_PROTOCOL _NDIS_CONTROL_CODE( 6, METHOD_BUFFERED ) +#define IOCTL_NDIS_GET_LOG_DATA _NDIS_CONTROL_CODE( 7, METHOD_OUT_DIRECT ) +// +// NtDeviceIoControlFile InputBuffer/OutputBuffer record structures for +// this device. +// +// +// This is the type of an NDIS OID value. +// +typedef ULONG NDIS_OID, *PNDIS_OID; +// +// IOCTL_NDIS_QUERY_ALL_STATS returns a sequence of these, packed +// together (no padding is required since statistics all have +// four or eight bytes of data). +// +typedef struct _NDIS_STATISTICS_VALUE { + NDIS_OID Oid; + ULONG DataLength; + UCHAR Data[1]; // variable length + +} NDIS_STATISTICS_VALUE, *PNDIS_STATISTICS_VALUE; + +// +// Structure used by TRANSLATE_NAME IOCTL +// +typedef struct _NET_PNP_ID { + ULONG ClassId; + ULONG Token; +} NET_PNP_ID, *PNET_PNP_ID; + +typedef struct _NET_PNP_TRANSLATE_LIST { + ULONG BytesNeeded; + NET_PNP_ID IdArray[ANYSIZE_ARRAY]; +} NET_PNP_TRANSLATE_LIST, *PNET_PNP_TRANSLATE_LIST; + +// +// Structure used to define a self-contained variable data structure +// +typedef struct _NDIS_VAR_DATA_DESC { + USHORT Length; // # of octects of data + + USHORT MaximumLength; // # of octects available + + LONG Offset; // Offset of data relative to the descriptor + +} NDIS_VAR_DATA_DESC, *PNDIS_VAR_DATA_DESC; + +// +// Object Identifiers used by NdisRequest Query/Set Information +// +// +// General Objects +// +#define OID_GEN_SUPPORTED_LIST 0x00010101 +#define OID_GEN_HARDWARE_STATUS 0x00010102 +#define OID_GEN_MEDIA_SUPPORTED 0x00010103 +#define OID_GEN_MEDIA_IN_USE 0x00010104 +#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 +#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 +#define OID_GEN_LINK_SPEED 0x00010107 +#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 +#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 +#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A +#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B +#define OID_GEN_VENDOR_ID 0x0001010C +#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D +#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E +#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F +#define OID_GEN_DRIVER_VERSION 0x00010110 +#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 +#define OID_GEN_PROTOCOL_OPTIONS 0x00010112 +#define OID_GEN_MAC_OPTIONS 0x00010113 +#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 +#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 +#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 +#define OID_GEN_XMIT_OK 0x00020101 +#define OID_GEN_RCV_OK 0x00020102 +#define OID_GEN_XMIT_ERROR 0x00020103 +#define OID_GEN_RCV_ERROR 0x00020104 +#define OID_GEN_RCV_NO_BUFFER 0x00020105 +#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 +#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 +#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 +#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 +#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 +#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 +#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 +#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 +#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 +#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A +#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B +#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C +#define OID_GEN_RCV_CRC_ERROR 0x0002020D +#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E +#define OID_GEN_GET_TIME_CAPS 0x0002020F +#define OID_GEN_GET_NETCARD_TIME 0x00020210 +// +// These are connection-oriented general OIDs. +// These replace the above OIDs for connection-oriented media. +// +#define OID_GEN_CO_SUPPORTED_LIST 0x00010101 +#define OID_GEN_CO_HARDWARE_STATUS 0x00010102 +#define OID_GEN_CO_MEDIA_SUPPORTED 0x00010103 +#define OID_GEN_CO_MEDIA_IN_USE 0x00010104 +#define OID_GEN_CO_LINK_SPEED 0x00010105 +#define OID_GEN_CO_VENDOR_ID 0x00010106 +#define OID_GEN_CO_VENDOR_DESCRIPTION 0x00010107 +#define OID_GEN_CO_DRIVER_VERSION 0x00010108 +#define OID_GEN_CO_PROTOCOL_OPTIONS 0x00010109 +#define OID_GEN_CO_MAC_OPTIONS 0x0001010A +#define OID_GEN_CO_MEDIA_CONNECT_STATUS 0x0001010B +#define OID_GEN_CO_VENDOR_DRIVER_VERSION 0x0001010C +#define OID_GEN_CO_MINIMUM_LINK_SPEED 0x0001010D +#define OID_GEN_CO_GET_TIME_CAPS 0x00010201 +#define OID_GEN_CO_GET_NETCARD_TIME 0x00010202 +// +// These are connection-oriented statistics OIDs. +// +#define OID_GEN_CO_XMIT_PDUS_OK 0x00020101 +#define OID_GEN_CO_RCV_PDUS_OK 0x00020102 +#define OID_GEN_CO_XMIT_PDUS_ERROR 0x00020103 +#define OID_GEN_CO_RCV_PDUS_ERROR 0x00020104 +#define OID_GEN_CO_RCV_PDUS_NO_BUFFER 0x00020105 +#define OID_GEN_CO_RCV_CRC_ERROR 0x00020201 +#define OID_GEN_CO_TRANSMIT_QUEUE_LENGTH 0x00020202 +#define OID_GEN_CO_BYTES_XMIT 0x00020203 +#define OID_GEN_CO_BYTES_RCV 0x00020204 +#define OID_GEN_CO_BYTES_XMIT_OUTSTANDING 0x00020205 +#define OID_GEN_CO_NETCARD_LOAD 0x00020206 +// +// These are objects for Connection-oriented media call-managers and are not +// valid for ndis drivers. Under construction. +// +#define OID_CO_ADD_PVC 0xFF000001 +#define OID_CO_DELETE_PVC 0xFF000002 +#define OID_CO_GET_CALL_INFORMATION 0xFF000003 +#define OID_CO_ADD_ADDRESS 0xFF000004 +#define OID_CO_DELETE_ADDRESS 0xFF000005 +#define OID_CO_GET_ADDRESSES 0xFF000006 +#define OID_CO_ADDRESS_CHANGE 0xFF000007 +#define OID_CO_SIGNALING_ENABLED 0xFF000008 +#define OID_CO_SIGNALING_DISABLED 0xFF000009 +// +// 802.3 Objects (Ethernet) +// +#define OID_802_3_PERMANENT_ADDRESS 0x01010101 +#define OID_802_3_CURRENT_ADDRESS 0x01010102 +#define OID_802_3_MULTICAST_LIST 0x01010103 +#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 +#define OID_802_3_MAC_OPTIONS 0x01010105 +// +// +#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001 +#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 +#define OID_802_3_XMIT_ONE_COLLISION 0x01020102 +#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 +#define OID_802_3_XMIT_DEFERRED 0x01020201 +#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 +#define OID_802_3_RCV_OVERRUN 0x01020203 +#define OID_802_3_XMIT_UNDERRUN 0x01020204 +#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205 +#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 +#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 +// +// 802.5 Objects (Token-Ring) +// +#define OID_802_5_PERMANENT_ADDRESS 0x02010101 +#define OID_802_5_CURRENT_ADDRESS 0x02010102 +#define OID_802_5_CURRENT_FUNCTIONAL 0x02010103 +#define OID_802_5_CURRENT_GROUP 0x02010104 +#define OID_802_5_LAST_OPEN_STATUS 0x02010105 +#define OID_802_5_CURRENT_RING_STATUS 0x02010106 +#define OID_802_5_CURRENT_RING_STATE 0x02010107 +#define OID_802_5_LINE_ERRORS 0x02020101 +#define OID_802_5_LOST_FRAMES 0x02020102 +#define OID_802_5_BURST_ERRORS 0x02020201 +#define OID_802_5_AC_ERRORS 0x02020202 +#define OID_802_5_ABORT_DELIMETERS 0x02020203 +#define OID_802_5_FRAME_COPIED_ERRORS 0x02020204 +#define OID_802_5_FREQUENCY_ERRORS 0x02020205 +#define OID_802_5_TOKEN_ERRORS 0x02020206 +#define OID_802_5_INTERNAL_ERRORS 0x02020207 +// +// FDDI Objects +// +#define OID_FDDI_LONG_PERMANENT_ADDR 0x03010101 +#define OID_FDDI_LONG_CURRENT_ADDR 0x03010102 +#define OID_FDDI_LONG_MULTICAST_LIST 0x03010103 +#define OID_FDDI_LONG_MAX_LIST_SIZE 0x03010104 +#define OID_FDDI_SHORT_PERMANENT_ADDR 0x03010105 +#define OID_FDDI_SHORT_CURRENT_ADDR 0x03010106 +#define OID_FDDI_SHORT_MULTICAST_LIST 0x03010107 +#define OID_FDDI_SHORT_MAX_LIST_SIZE 0x03010108 +#define OID_FDDI_ATTACHMENT_TYPE 0x03020101 +#define OID_FDDI_UPSTREAM_NODE_LONG 0x03020102 +#define OID_FDDI_DOWNSTREAM_NODE_LONG 0x03020103 +#define OID_FDDI_FRAME_ERRORS 0x03020104 +#define OID_FDDI_FRAMES_LOST 0x03020105 +#define OID_FDDI_RING_MGT_STATE 0x03020106 +#define OID_FDDI_LCT_FAILURES 0x03020107 +#define OID_FDDI_LEM_REJECTS 0x03020108 +#define OID_FDDI_LCONNECTION_STATE 0x03020109 +#define OID_FDDI_SMT_STATION_ID 0x03030201 +#define OID_FDDI_SMT_OP_VERSION_ID 0x03030202 +#define OID_FDDI_SMT_HI_VERSION_ID 0x03030203 +#define OID_FDDI_SMT_LO_VERSION_ID 0x03030204 +#define OID_FDDI_SMT_MANUFACTURER_DATA 0x03030205 +#define OID_FDDI_SMT_USER_DATA 0x03030206 +#define OID_FDDI_SMT_MIB_VERSION_ID 0x03030207 +#define OID_FDDI_SMT_MAC_CT 0x03030208 +#define OID_FDDI_SMT_NON_MASTER_CT 0x03030209 +#define OID_FDDI_SMT_MASTER_CT 0x0303020A +#define OID_FDDI_SMT_AVAILABLE_PATHS 0x0303020B +#define OID_FDDI_SMT_CONFIG_CAPABILITIES 0x0303020C +#define OID_FDDI_SMT_CONFIG_POLICY 0x0303020D +#define OID_FDDI_SMT_CONNECTION_POLICY 0x0303020E +#define OID_FDDI_SMT_T_NOTIFY 0x0303020F +#define OID_FDDI_SMT_STAT_RPT_POLICY 0x03030210 +#define OID_FDDI_SMT_TRACE_MAX_EXPIRATION 0x03030211 +#define OID_FDDI_SMT_PORT_INDEXES 0x03030212 +#define OID_FDDI_SMT_MAC_INDEXES 0x03030213 +#define OID_FDDI_SMT_BYPASS_PRESENT 0x03030214 +#define OID_FDDI_SMT_ECM_STATE 0x03030215 +#define OID_FDDI_SMT_CF_STATE 0x03030216 +#define OID_FDDI_SMT_HOLD_STATE 0x03030217 +#define OID_FDDI_SMT_REMOTE_DISCONNECT_FLAG 0x03030218 +#define OID_FDDI_SMT_STATION_STATUS 0x03030219 +#define OID_FDDI_SMT_PEER_WRAP_FLAG 0x0303021A +#define OID_FDDI_SMT_MSG_TIME_STAMP 0x0303021B +#define OID_FDDI_SMT_TRANSITION_TIME_STAMP 0x0303021C +#define OID_FDDI_SMT_SET_COUNT 0x0303021D +#define OID_FDDI_SMT_LAST_SET_STATION_ID 0x0303021E +#define OID_FDDI_MAC_FRAME_STATUS_FUNCTIONS 0x0303021F +#define OID_FDDI_MAC_BRIDGE_FUNCTIONS 0x03030220 +#define OID_FDDI_MAC_T_MAX_CAPABILITY 0x03030221 +#define OID_FDDI_MAC_TVX_CAPABILITY 0x03030222 +#define OID_FDDI_MAC_AVAILABLE_PATHS 0x03030223 +#define OID_FDDI_MAC_CURRENT_PATH 0x03030224 +#define OID_FDDI_MAC_UPSTREAM_NBR 0x03030225 +#define OID_FDDI_MAC_DOWNSTREAM_NBR 0x03030226 +#define OID_FDDI_MAC_OLD_UPSTREAM_NBR 0x03030227 +#define OID_FDDI_MAC_OLD_DOWNSTREAM_NBR 0x03030228 +#define OID_FDDI_MAC_DUP_ADDRESS_TEST 0x03030229 +#define OID_FDDI_MAC_REQUESTED_PATHS 0x0303022A +#define OID_FDDI_MAC_DOWNSTREAM_PORT_TYPE 0x0303022B +#define OID_FDDI_MAC_INDEX 0x0303022C +#define OID_FDDI_MAC_SMT_ADDRESS 0x0303022D +#define OID_FDDI_MAC_LONG_GRP_ADDRESS 0x0303022E +#define OID_FDDI_MAC_SHORT_GRP_ADDRESS 0x0303022F +#define OID_FDDI_MAC_T_REQ 0x03030230 +#define OID_FDDI_MAC_T_NEG 0x03030231 +#define OID_FDDI_MAC_T_MAX 0x03030232 +#define OID_FDDI_MAC_TVX_VALUE 0x03030233 +#define OID_FDDI_MAC_T_PRI0 0x03030234 +#define OID_FDDI_MAC_T_PRI1 0x03030235 +#define OID_FDDI_MAC_T_PRI2 0x03030236 +#define OID_FDDI_MAC_T_PRI3 0x03030237 +#define OID_FDDI_MAC_T_PRI4 0x03030238 +#define OID_FDDI_MAC_T_PRI5 0x03030239 +#define OID_FDDI_MAC_T_PRI6 0x0303023A +#define OID_FDDI_MAC_FRAME_CT 0x0303023B +#define OID_FDDI_MAC_COPIED_CT 0x0303023C +#define OID_FDDI_MAC_TRANSMIT_CT 0x0303023D +#define OID_FDDI_MAC_TOKEN_CT 0x0303023E +#define OID_FDDI_MAC_ERROR_CT 0x0303023F +#define OID_FDDI_MAC_LOST_CT 0x03030240 +#define OID_FDDI_MAC_TVX_EXPIRED_CT 0x03030241 +#define OID_FDDI_MAC_NOT_COPIED_CT 0x03030242 +#define OID_FDDI_MAC_LATE_CT 0x03030243 +#define OID_FDDI_MAC_RING_OP_CT 0x03030244 +#define OID_FDDI_MAC_FRAME_ERROR_THRESHOLD 0x03030245 +#define OID_FDDI_MAC_FRAME_ERROR_RATIO 0x03030246 +#define OID_FDDI_MAC_NOT_COPIED_THRESHOLD 0x03030247 +#define OID_FDDI_MAC_NOT_COPIED_RATIO 0x03030248 +#define OID_FDDI_MAC_RMT_STATE 0x03030249 +#define OID_FDDI_MAC_DA_FLAG 0x0303024A +#define OID_FDDI_MAC_UNDA_FLAG 0x0303024B +#define OID_FDDI_MAC_FRAME_ERROR_FLAG 0x0303024C +#define OID_FDDI_MAC_NOT_COPIED_FLAG 0x0303024D +#define OID_FDDI_MAC_MA_UNITDATA_AVAILABLE 0x0303024E +#define OID_FDDI_MAC_HARDWARE_PRESENT 0x0303024F +#define OID_FDDI_MAC_MA_UNITDATA_ENABLE 0x03030250 +#define OID_FDDI_PATH_INDEX 0x03030251 +#define OID_FDDI_PATH_RING_LATENCY 0x03030252 +#define OID_FDDI_PATH_TRACE_STATUS 0x03030253 +#define OID_FDDI_PATH_SBA_PAYLOAD 0x03030254 +#define OID_FDDI_PATH_SBA_OVERHEAD 0x03030255 +#define OID_FDDI_PATH_CONFIGURATION 0x03030256 +#define OID_FDDI_PATH_T_R_MODE 0x03030257 +#define OID_FDDI_PATH_SBA_AVAILABLE 0x03030258 +#define OID_FDDI_PATH_TVX_LOWER_BOUND 0x03030259 +#define OID_FDDI_PATH_T_MAX_LOWER_BOUND 0x0303025A +#define OID_FDDI_PATH_MAX_T_REQ 0x0303025B +#define OID_FDDI_PORT_MY_TYPE 0x0303025C +#define OID_FDDI_PORT_NEIGHBOR_TYPE 0x0303025D +#define OID_FDDI_PORT_CONNECTION_POLICIES 0x0303025E +#define OID_FDDI_PORT_MAC_INDICATED 0x0303025F +#define OID_FDDI_PORT_CURRENT_PATH 0x03030260 +#define OID_FDDI_PORT_REQUESTED_PATHS 0x03030261 +#define OID_FDDI_PORT_MAC_PLACEMENT 0x03030262 +#define OID_FDDI_PORT_AVAILABLE_PATHS 0x03030263 +#define OID_FDDI_PORT_MAC_LOOP_TIME 0x03030264 +#define OID_FDDI_PORT_PMD_CLASS 0x03030265 +#define OID_FDDI_PORT_CONNECTION_CAPABILITIES 0x03030266 +#define OID_FDDI_PORT_INDEX 0x03030267 +#define OID_FDDI_PORT_MAINT_LS 0x03030268 +#define OID_FDDI_PORT_BS_FLAG 0x03030269 +#define OID_FDDI_PORT_PC_LS 0x0303026A +#define OID_FDDI_PORT_EB_ERROR_CT 0x0303026B +#define OID_FDDI_PORT_LCT_FAIL_CT 0x0303026C +#define OID_FDDI_PORT_LER_ESTIMATE 0x0303026D +#define OID_FDDI_PORT_LEM_REJECT_CT 0x0303026E +#define OID_FDDI_PORT_LEM_CT 0x0303026F +#define OID_FDDI_PORT_LER_CUTOFF 0x03030270 +#define OID_FDDI_PORT_LER_ALARM 0x03030271 +#define OID_FDDI_PORT_CONNNECT_STATE 0x03030272 +#define OID_FDDI_PORT_PCM_STATE 0x03030273 +#define OID_FDDI_PORT_PC_WITHHOLD 0x03030274 +#define OID_FDDI_PORT_LER_FLAG 0x03030275 +#define OID_FDDI_PORT_HARDWARE_PRESENT 0x03030276 +#define OID_FDDI_SMT_STATION_ACTION 0x03030277 +#define OID_FDDI_PORT_ACTION 0x03030278 +#define OID_FDDI_IF_DESCR 0x03030279 +#define OID_FDDI_IF_TYPE 0x0303027A +#define OID_FDDI_IF_MTU 0x0303027B +#define OID_FDDI_IF_SPEED 0x0303027C +#define OID_FDDI_IF_PHYS_ADDRESS 0x0303027D +#define OID_FDDI_IF_ADMIN_STATUS 0x0303027E +#define OID_FDDI_IF_OPER_STATUS 0x0303027F +#define OID_FDDI_IF_LAST_CHANGE 0x03030280 +#define OID_FDDI_IF_IN_OCTETS 0x03030281 +#define OID_FDDI_IF_IN_UCAST_PKTS 0x03030282 +#define OID_FDDI_IF_IN_NUCAST_PKTS 0x03030283 +#define OID_FDDI_IF_IN_DISCARDS 0x03030284 +#define OID_FDDI_IF_IN_ERRORS 0x03030285 +#define OID_FDDI_IF_IN_UNKNOWN_PROTOS 0x03030286 +#define OID_FDDI_IF_OUT_OCTETS 0x03030287 +#define OID_FDDI_IF_OUT_UCAST_PKTS 0x03030288 +#define OID_FDDI_IF_OUT_NUCAST_PKTS 0x03030289 +#define OID_FDDI_IF_OUT_DISCARDS 0x0303028A +#define OID_FDDI_IF_OUT_ERRORS 0x0303028B +#define OID_FDDI_IF_OUT_QLEN 0x0303028C +#define OID_FDDI_IF_SPECIFIC 0x0303028D +// +// WAN objects +// +#define OID_WAN_PERMANENT_ADDRESS 0x04010101 +#define OID_WAN_CURRENT_ADDRESS 0x04010102 +#define OID_WAN_QUALITY_OF_SERVICE 0x04010103 +#define OID_WAN_PROTOCOL_TYPE 0x04010104 +#define OID_WAN_MEDIUM_SUBTYPE 0x04010105 +#define OID_WAN_HEADER_FORMAT 0x04010106 +#define OID_WAN_GET_INFO 0x04010107 +#define OID_WAN_SET_LINK_INFO 0x04010108 +#define OID_WAN_GET_LINK_INFO 0x04010109 +#define OID_WAN_LINE_COUNT 0x0401010A +#define OID_WAN_GET_BRIDGE_INFO 0x0401020A +#define OID_WAN_SET_BRIDGE_INFO 0x0401020B +#define OID_WAN_GET_COMP_INFO 0x0401020C +#define OID_WAN_SET_COMP_INFO 0x0401020D +#define OID_WAN_GET_STATS_INFO 0x0401020E +// +// LocalTalk objects +// +#define OID_LTALK_CURRENT_NODE_ID 0x05010102 +#define OID_LTALK_IN_BROADCASTS 0x05020101 +#define OID_LTALK_IN_LENGTH_ERRORS 0x05020102 +#define OID_LTALK_OUT_NO_HANDLERS 0x05020201 +#define OID_LTALK_COLLISIONS 0x05020202 +#define OID_LTALK_DEFERS 0x05020203 +#define OID_LTALK_NO_DATA_ERRORS 0x05020204 +#define OID_LTALK_RANDOM_CTS_ERRORS 0x05020205 +#define OID_LTALK_FCS_ERRORS 0x05020206 +// +// Arcnet objects +// +#define OID_ARCNET_PERMANENT_ADDRESS 0x06010101 +#define OID_ARCNET_CURRENT_ADDRESS 0x06010102 +#define OID_ARCNET_RECONFIGURATIONS 0x06020201 +// +// TAPI objects +// +#define OID_TAPI_ACCEPT 0x07030101 +#define OID_TAPI_ANSWER 0x07030102 +#define OID_TAPI_CLOSE 0x07030103 +#define OID_TAPI_CLOSE_CALL 0x07030104 +#define OID_TAPI_CONDITIONAL_MEDIA_DETECTION 0x07030105 +#define OID_TAPI_CONFIG_DIALOG 0x07030106 +#define OID_TAPI_DEV_SPECIFIC 0x07030107 +#define OID_TAPI_DIAL 0x07030108 +#define OID_TAPI_DROP 0x07030109 +#define OID_TAPI_GET_ADDRESS_CAPS 0x0703010A +#define OID_TAPI_GET_ADDRESS_ID 0x0703010B +#define OID_TAPI_GET_ADDRESS_STATUS 0x0703010C +#define OID_TAPI_GET_CALL_ADDRESS_ID 0x0703010D +#define OID_TAPI_GET_CALL_INFO 0x0703010E +#define OID_TAPI_GET_CALL_STATUS 0x0703010F +#define OID_TAPI_GET_DEV_CAPS 0x07030110 +#define OID_TAPI_GET_DEV_CONFIG 0x07030111 +#define OID_TAPI_GET_EXTENSION_ID 0x07030112 +#define OID_TAPI_GET_ID 0x07030113 +#define OID_TAPI_GET_LINE_DEV_STATUS 0x07030114 +#define OID_TAPI_MAKE_CALL 0x07030115 +#define OID_TAPI_NEGOTIATE_EXT_VERSION 0x07030116 +#define OID_TAPI_OPEN 0x07030117 +#define OID_TAPI_PROVIDER_INITIALIZE 0x07030118 +#define OID_TAPI_PROVIDER_SHUTDOWN 0x07030119 +#define OID_TAPI_SECURE_CALL 0x0703011A +#define OID_TAPI_SELECT_EXT_VERSION 0x0703011B +#define OID_TAPI_SEND_USER_USER_INFO 0x0703011C +#define OID_TAPI_SET_APP_SPECIFIC 0x0703011D +#define OID_TAPI_SET_CALL_PARAMS 0x0703011E +#define OID_TAPI_SET_DEFAULT_MEDIA_DETECTION 0x0703011F +#define OID_TAPI_SET_DEV_CONFIG 0x07030120 +#define OID_TAPI_SET_MEDIA_MODE 0x07030121 +#define OID_TAPI_SET_STATUS_MESSAGES 0x07030122 +// +// ATM Connection Oriented Ndis +// +#define OID_ATM_SUPPORTED_VC_RATES 0x08010101 +#define OID_ATM_SUPPORTED_SERVICE_CATEGORY 0x08010102 +#define OID_ATM_SUPPORTED_AAL_TYPES 0x08010103 +#define OID_ATM_HW_CURRENT_ADDRESS 0x08010104 +#define OID_ATM_MAX_ACTIVE_VCS 0x08010105 +#define OID_ATM_MAX_ACTIVE_VCI_BITS 0x08010106 +#define OID_ATM_MAX_ACTIVE_VPI_BITS 0x08010107 +#define OID_ATM_MAX_AAL0_PACKET_SIZE 0x08010108 +#define OID_ATM_MAX_AAL1_PACKET_SIZE 0x08010109 +#define OID_ATM_MAX_AAL34_PACKET_SIZE 0x0801010A +#define OID_ATM_MAX_AAL5_PACKET_SIZE 0x0801010B +#define OID_ATM_SIGNALING_VPIVCI 0x08010201 +#define OID_ATM_ASSIGNED_VPI 0x08010202 +#define OID_ATM_ACQUIRE_ACCESS_NET_RESOURCES 0x08010203 +#define OID_ATM_RELEASE_ACCESS_NET_RESOURCES 0x08010204 +#define OID_ATM_ILMI_VPIVCI 0x08010205 +#define OID_ATM_DIGITAL_BROADCAST_VPIVCI 0x08010206 +#define OID_ATM_GET_NEAREST_FLOW 0x08010207 +#define OID_ATM_ALIGNMENT_REQUIRED 0x08010208 +// +// ATM specific statistics OIDs. +// +#define OID_ATM_RCV_CELLS_OK 0x08020101 +#define OID_ATM_XMIT_CELLS_OK 0x08020102 +#define OID_ATM_RCV_CELLS_DROPPED 0x08020103 +#define OID_ATM_RCV_INVALID_VPI_VCI 0x08020201 +#define OID_ATM_CELLS_HEC_ERROR 0x08020202 +#define OID_ATM_RCV_REASSEMBLY_ERROR 0x08020203 +// +// PCCA (Wireless) object +// +// +// All WirelessWAN devices must support the following OIDs +// +#define OID_WW_GEN_NETWORK_TYPES_SUPPORTED 0x09010101 +#define OID_WW_GEN_NETWORK_TYPE_IN_USE 0x09010102 +#define OID_WW_GEN_HEADER_FORMATS_SUPPORTED 0x09010103 +#define OID_WW_GEN_HEADER_FORMAT_IN_USE 0x09010104 +#define OID_WW_GEN_INDICATION_REQUEST 0x09010105 +#define OID_WW_GEN_DEVICE_INFO 0x09010106 +#define OID_WW_GEN_OPERATION_MODE 0x09010107 +#define OID_WW_GEN_LOCK_STATUS 0x09010108 +#define OID_WW_GEN_DISABLE_TRANSMITTER 0x09010109 +#define OID_WW_GEN_NETWORK_ID 0x0901010A +#define OID_WW_GEN_PERMANENT_ADDRESS 0x0901010B +#define OID_WW_GEN_CURRENT_ADDRESS 0x0901010C +#define OID_WW_GEN_SUSPEND_DRIVER 0x0901010D +#define OID_WW_GEN_BASESTATION_ID 0x0901010E +#define OID_WW_GEN_CHANNEL_ID 0x0901010F +#define OID_WW_GEN_ENCRYPTION_SUPPORTED 0x09010110 +#define OID_WW_GEN_ENCRYPTION_IN_USE 0x09010111 +#define OID_WW_GEN_ENCRYPTION_STATE 0x09010112 +#define OID_WW_GEN_CHANNEL_QUALITY 0x09010113 +#define OID_WW_GEN_REGISTRATION_STATUS 0x09010114 +#define OID_WW_GEN_RADIO_LINK_SPEED 0x09010115 +#define OID_WW_GEN_LATENCY 0x09010116 +#define OID_WW_GEN_BATTERY_LEVEL 0x09010117 +#define OID_WW_GEN_EXTERNAL_POWER 0x09010118 +// +// Network Dependent OIDs - Mobitex: +// +#define OID_WW_MBX_SUBADDR 0x09050101 +// OID 0x09050102 is reserved and may not be used +#define OID_WW_MBX_FLEXLIST 0x09050103 +#define OID_WW_MBX_GROUPLIST 0x09050104 +#define OID_WW_MBX_TRAFFIC_AREA 0x09050105 +#define OID_WW_MBX_LIVE_DIE 0x09050106 +#define OID_WW_MBX_TEMP_DEFAULTLIST 0x09050107 +// +// Network Dependent OIDs - Pinpoint: +// +#define OID_WW_PIN_LOC_AUTHORIZE 0x09090101 +#define OID_WW_PIN_LAST_LOCATION 0x09090102 +#define OID_WW_PIN_LOC_FIX 0x09090103 +// +// Network Dependent - CDPD: +// +#define OID_WW_CDPD_SPNI 0x090D0101 +#define OID_WW_CDPD_WASI 0x090D0102 +#define OID_WW_CDPD_AREA_COLOR 0x090D0103 +#define OID_WW_CDPD_TX_POWER_LEVEL 0x090D0104 +#define OID_WW_CDPD_EID 0x090D0105 +#define OID_WW_CDPD_HEADER_COMPRESSION 0x090D0106 +#define OID_WW_CDPD_DATA_COMPRESSION 0x090D0107 +#define OID_WW_CDPD_CHANNEL_SELECT 0x090D0108 +#define OID_WW_CDPD_CHANNEL_STATE 0x090D0109 +#define OID_WW_CDPD_NEI 0x090D010A +#define OID_WW_CDPD_NEI_STATE 0x090D010B +#define OID_WW_CDPD_SERVICE_PROVIDER_IDENTIFIER 0x090D010C +#define OID_WW_CDPD_SLEEP_MODE 0x090D010D +#define OID_WW_CDPD_CIRCUIT_SWITCHED 0x090D010E +#define OID_WW_CDPD_TEI 0x090D010F +#define OID_WW_CDPD_RSSI 0x090D0110 +// +// Network Dependent - Ardis: +// +#define OID_WW_ARD_SNDCP 0x09110101 +#define OID_WW_ARD_TMLY_MSG 0x09110102 +#define OID_WW_ARD_DATAGRAM 0x09110103 +// +// Network Dependent - DataTac: +// +#define OID_WW_TAC_COMPRESSION 0x09150101 +#define OID_WW_TAC_SET_CONFIG 0x09150102 +#define OID_WW_TAC_GET_STATUS 0x09150103 +#define OID_WW_TAC_USER_HEADER 0x09150104 +// +// Network Dependent - Metricom: +// +#define OID_WW_MET_FUNCTION 0x09190101 +// +// IRDA objects +// +#define OID_IRDA_RECEIVING 0x0A010100 +#define OID_IRDA_TURNAROUND_TIME 0x0A010101 +#define OID_IRDA_SUPPORTED_SPEEDS 0x0A010102 +#define OID_IRDA_LINK_SPEED 0x0A010103 +#define OID_IRDA_MEDIA_BUSY 0x0A010104 +#define OID_IRDA_EXTRA_RCV_BOFS 0x0A010200 +#define OID_IRDA_RATE_SNIFF 0x0A010201 +#define OID_IRDA_UNICAST_LIST 0x0A010202 +#define OID_IRDA_MAX_UNICAST_LIST_SIZE 0x0A010203 +#define OID_IRDA_MAX_RECEIVE_WINDOW_SIZE 0x0A010204 +#define OID_IRDA_MAX_SEND_WINDOW_SIZE 0x0A010205 +// +// Medium the Ndis Driver is running on (OID_GEN_MEDIA_SUPPORTED/ +// OID_GEN_MEDIA_IN_USE). +// +typedef enum _NDIS_MEDIUM { + NdisMedium802_3, + NdisMedium802_5, + NdisMediumFddi, + NdisMediumWan, + NdisMediumLocalTalk, + NdisMediumDix, // defined for convenience, not a real medium + NdisMediumArcnetRaw, + NdisMediumArcnet878_2, + NdisMediumAtm, + NdisMediumWirelessWan, + NdisMediumIrda, + NdisMediumMax // Not a real medium, defined as an upper-bound +} NDIS_MEDIUM, *PNDIS_MEDIUM; + +// +// Hardware status codes (OID_GEN_HARDWARE_STATUS). +// +typedef enum _NDIS_HARDWARE_STATUS { + NdisHardwareStatusReady, + NdisHardwareStatusInitializing, + NdisHardwareStatusReset, + NdisHardwareStatusClosing, + NdisHardwareStatusNotReady +} NDIS_HARDWARE_STATUS, *PNDIS_HARDWARE_STATUS; + +// +// this is the type passed in the OID_GEN_GET_TIME_CAPS request +// +typedef struct _GEN_GET_TIME_CAPS { + ULONG Flags; // Bits defined below + + ULONG ClockPrecision; +} GEN_GET_TIME_CAPS, *PGEN_GET_TIME_CAPS; + +#define READABLE_LOCAL_CLOCK 0x000000001 +#define CLOCK_NETWORK_DERIVED 0x000000002 +#define CLOCK_PRECISION 0x000000004 +#define RECEIVE_TIME_INDICATION_CAPABLE 0x000000008 +#define TIMED_SEND_CAPABLE 0x000000010 +#define TIME_STAMP_CAPABLE 0x000000020 +// +// +// this is the type passed in the OID_GEN_GET_NETCARD_TIME request +// +typedef struct _GEN_GET_NETCARD_TIME { + ULONG ReadTime; +} GEN_GET_NETCARD_TIME, *PGEN_GET_NETCARD_TIME; + +// +// Defines the attachment types for FDDI (OID_FDDI_ATTACHMENT_TYPE). +// +typedef enum _NDIS_FDDI_ATTACHMENT_TYPE { + NdisFddiTypeIsolated = 1, + NdisFddiTypeLocalA, + NdisFddiTypeLocalB, + NdisFddiTypeLocalAB, + NdisFddiTypeLocalS, + NdisFddiTypeWrapA, + NdisFddiTypeWrapB, + NdisFddiTypeWrapAB, + NdisFddiTypeWrapS, + NdisFddiTypeCWrapA, + NdisFddiTypeCWrapB, + NdisFddiTypeCWrapS, + NdisFddiTypeThrough +} NDIS_FDDI_ATTACHMENT_TYPE, *PNDIS_FDDI_ATTACHMENT_TYPE; + +// +// Defines the ring management states for FDDI (OID_FDDI_RING_MGT_STATE). +// +typedef enum _NDIS_FDDI_RING_MGT_STATE { + NdisFddiRingIsolated = 1, + NdisFddiRingNonOperational, + NdisFddiRingOperational, + NdisFddiRingDetect, + NdisFddiRingNonOperationalDup, + NdisFddiRingOperationalDup, + NdisFddiRingDirected, + NdisFddiRingTrace +} NDIS_FDDI_RING_MGT_STATE, *PNDIS_FDDI_RING_MGT_STATE; + +// +// Defines the Lconnection state for FDDI (OID_FDDI_LCONNECTION_STATE). +// +typedef enum _NDIS_FDDI_LCONNECTION_STATE { + NdisFddiStateOff = 1, + NdisFddiStateBreak, + NdisFddiStateTrace, + NdisFddiStateConnect, + NdisFddiStateNext, + NdisFddiStateSignal, + NdisFddiStateJoin, + NdisFddiStateVerify, + NdisFddiStateActive, + NdisFddiStateMaintenance +} NDIS_FDDI_LCONNECTION_STATE, *PNDIS_FDDI_LCONNECTION_STATE; + +// +// Defines the medium subtypes for WAN medium (OID_WAN_MEDIUM_SUBTYPE). +// +typedef enum _NDIS_WAN_MEDIUM_SUBTYPE { + NdisWanMediumHub, + NdisWanMediumX_25, + NdisWanMediumIsdn, + NdisWanMediumSerial, + NdisWanMediumFrameRelay, + NdisWanMediumAtm, + NdisWanMediumSonet, + NdisWanMediumSW56K +} NDIS_WAN_MEDIUM_SUBTYPE, *PNDIS_WAN_MEDIUM_SUBTYPE; + +// +// Defines the header format for WAN medium (OID_WAN_HEADER_FORMAT). +// +typedef enum _NDIS_WAN_HEADER_FORMAT { + NdisWanHeaderNative, // src/dest based on subtype, followed by NLPID + NdisWanHeaderEthernet // emulation of ethernet header +} NDIS_WAN_HEADER_FORMAT, *PNDIS_WAN_HEADER_FORMAT; + +// +// Defines the line quality on a WAN line (OID_WAN_QUALITY_OF_SERVICE). +// +typedef enum _NDIS_WAN_QUALITY { + NdisWanRaw, + NdisWanErrorControl, + NdisWanReliable +} NDIS_WAN_QUALITY, *PNDIS_WAN_QUALITY; + +// +// Defines the state of a token-ring adapter (OID_802_5_CURRENT_RING_STATE). +// +typedef enum _NDIS_802_5_RING_STATE { + NdisRingStateOpened = 1, + NdisRingStateClosed, + NdisRingStateOpening, + NdisRingStateClosing, + NdisRingStateOpenFailure, + NdisRingStateRingFailure +} NDIS_802_5_RING_STATE, *PNDIS_802_5_RING_STATE; + +// +// Defines the state of the LAN media +// +typedef enum _NDIS_MEDIA_STATE { + NdisMediaStateConnected, + NdisMediaStateDisconnected +} NDIS_MEDIA_STATE, *PNDIS_MEDIA_STATE; + +// +// The following is set on a per-packet basis as OOB data with NdisClass802_3Priority +// +typedef ULONG Priority_802_3; // 0-7 priority levels +// +// The following structure is used to query OID_GEN_CO_LINK_SPEED and +// OID_GEN_CO_MINIMUM_LINK_SPEED. The first OID will return the current +// link speed of the adapter. The second will return the minimum link speed +// the adapter is capable of. +// + +typedef struct _NDIS_CO_LINK_SPEED { + ULONG Outbound; + ULONG Inbound; +} NDIS_CO_LINK_SPEED, + +*PNDIS_CO_LINK_SPEED; +// +// Ndis Packet Filter Bits (OID_GEN_CURRENT_PACKET_FILTER). +// +#define NDIS_PACKET_TYPE_DIRECTED 0x0001 +#define NDIS_PACKET_TYPE_MULTICAST 0x0002 +#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x0004 +#define NDIS_PACKET_TYPE_BROADCAST 0x0008 +#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x0010 +#define NDIS_PACKET_TYPE_PROMISCUOUS 0x0020 +#define NDIS_PACKET_TYPE_SMT 0x0040 +#define NDIS_PACKET_TYPE_ALL_LOCAL 0x0080 +#define NDIS_PACKET_TYPE_MAC_FRAME 0x8000 +#define NDIS_PACKET_TYPE_FUNCTIONAL 0x4000 +#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x2000 +#define NDIS_PACKET_TYPE_GROUP 0x1000 +// +// Ndis Token-Ring Ring Status Codes (OID_802_5_CURRENT_RING_STATUS). +// +#define NDIS_RING_SIGNAL_LOSS 0x00008000 +#define NDIS_RING_HARD_ERROR 0x00004000 +#define NDIS_RING_SOFT_ERROR 0x00002000 +#define NDIS_RING_TRANSMIT_BEACON 0x00001000 +#define NDIS_RING_LOBE_WIRE_FAULT 0x00000800 +#define NDIS_RING_AUTO_REMOVAL_ERROR 0x00000400 +#define NDIS_RING_REMOVE_RECEIVED 0x00000200 +#define NDIS_RING_COUNTER_OVERFLOW 0x00000100 +#define NDIS_RING_SINGLE_STATION 0x00000080 +#define NDIS_RING_RING_RECOVERY 0x00000040 +// +// Ndis protocol option bits (OID_GEN_PROTOCOL_OPTIONS). +// +#define NDIS_PROT_OPTION_ESTIMATED_LENGTH 0x00000001 +#define NDIS_PROT_OPTION_NO_LOOPBACK 0x00000002 +#define NDIS_PROT_OPTION_NO_RSVD_ON_RCVPKT 0x00000004 +// +// Ndis MAC option bits (OID_GEN_MAC_OPTIONS). +// +#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001 +#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002 +#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004 +#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008 +#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010 +#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020 +#define NDIS_MAC_OPTION_RESERVED 0x80000000 +// +// NDIS MAC option bits for OID_GEN_CO_MAC_OPTIONS. +// +#define NDIS_CO_MAC_OPTION_DYNAMIC_LINK_SPEED 0x00000001 +#ifdef IRDA +// +// The following is set on a per-packet basis as OOB data with NdisClassIrdaPacketInfo +// This is the per-packet info specified on a per-packet basis +// +typedef struct _NDIS_IRDA_PACKET_INFO { + UINT ExtraBOFs; + UINT MinTurnAroundTime; +} NDIS_IRDA_PACKET_INFO, *PNDIS_IRDA_PACKET_INFO; + +#endif +#ifdef WIRELESS_WAN +// +// Wireless WAN structure definitions +// +// +// currently defined Wireless network subtypes +// +typedef enum _NDIS_WW_NETWORK_TYPE { + NdisWWGeneric, + NdisWWMobitex, + NdisWWPinpoint, + NdisWWCDPD, + NdisWWArdis, + NdisWWDataTAC, + NdisWWMetricom, + NdisWWGSM, + NdisWWCDMA, + NdisWWTDMA, + NdisWWAMPS, + NdisWWInmarsat, + NdisWWpACT +} NDIS_WW_NETWORK_TYPE; + +// +// currently defined header formats +// +typedef enum _NDIS_WW_HEADER_FORMAT { + NdisWWDIXEthernetFrames, + NdisWWMPAKFrames, + NdisWWRDLAPFrames, + NdisWWMDC4800Frames +} NDIS_WW_HEADER_FORMAT; + +// +// currently defined encryption types +// +typedef enum _NDIS_WW_ENCRYPTION_TYPE { + NdisWWUnknownEncryption = -1, + NdisWWNoEncryption, + NdisWWDefaultEncryption +} NDIS_WW_ENCRYPTION_TYPE, *PNDIS_WW_ENCRYPTION_TYPE; + +// +// OID_WW_GEN_INDICATION_REQUEST +// +typedef struct _NDIS_WW_INDICATION_REQUEST { + NDIS_OID Oid; // IN + + UINT uIndicationFlag; // IN + + UINT uApplicationToken; // IN OUT + + HANDLE hIndicationHandle; // IN OUT + + INT iPollingInterval; // IN OUT + + NDIS_VAR_DATA_DESC InitialValue; // IN OUT + + NDIS_VAR_DATA_DESC OIDIndicationValue; // OUT - only valid after indication + + NDIS_VAR_DATA_DESC TriggerValue; // IN + +} NDIS_WW_INDICATION_REQUEST, *PNDIS_WW_INDICATION_REQUEST; + +#define OID_INDICATION_REQUEST_ENABLE 0x0000 +#define OID_INDICATION_REQUEST_CANCEL 0x0001 +// +// OID_WW_GEN_DEVICE_INFO +// +typedef struct _WW_DEVICE_INFO { + NDIS_VAR_DATA_DESC Manufacturer; + NDIS_VAR_DATA_DESC ModelNum; + NDIS_VAR_DATA_DESC SWVersionNum; + NDIS_VAR_DATA_DESC SerialNum; +} WW_DEVICE_INFO, *PWW_DEVICE_INFO; + +// +// OID_WW_GEN_OPERATION_MODE +// +typedef INT WW_OPERATION_MODE; // 0 = Normal mode + // 1 = Power saving mode + // -1 = mode unknown +// +// OID_WW_GEN_LOCK_STATUS +// + +typedef INT WW_LOCK_STATUS; // 0 = unlocked + // 1 = locked + // -1 = unknown lock status +// +// OID_WW_GEN_DISABLE_TRANSMITTER +// + +typedef INT WW_DISABLE_TRANSMITTER; // 0 = transmitter enabled + // 1 = transmitter disabled + // -1 = unknown value +// +// OID_WW_GEN_NETWORK_ID +// + +typedef NDIS_VAR_DATA_DESC WW_NETWORK_ID; +// +// OID_WW_GEN_PERMANENT_ADDRESS +// +typedef NDIS_VAR_DATA_DESC WW_PERMANENT_ADDRESS; +// +// OID_WW_GEN_CURRENT_ADDRESS +// +typedef struct _WW_CURRENT_ADDRESS { + NDIS_WW_HEADER_FORMAT Format; + NDIS_VAR_DATA_DESC Address; +} WW_CURRENT_ADDRESS, *PWW_CURRENT_ADDRESS; + +// +// OID_WW_GEN_SUSPEND_DRIVER +// +typedef BOOLEAN WW_SUSPEND_DRIVER; // 0 = driver operational + // 1 = driver suspended +// +// OID_WW_GEN_BASESTATION_ID +// + +typedef NDIS_VAR_DATA_DESC WW_BASESTATION_ID; +// +// OID_WW_GEN_CHANNEL_ID +// +typedef NDIS_VAR_DATA_DESC WW_CHANNEL_ID; +// +// OID_WW_GEN_ENCRYPTION_STATE +// +typedef BOOLEAN WW_ENCRYPTION_STATE; // 0 = if encryption is disabled + // 1 = if encryption is enabled +// +// OID_WW_GEN_CHANNEL_QUALITY +// + +typedef INT WW_CHANNEL_QUALITY; // 0 = Not in network contact, + // 1-100 = Quality of Channel (100 is highest quality). + // -1 = channel quality is unknown +// +// OID_WW_GEN_REGISTRATION_STATUS +// + +typedef INT WW_REGISTRATION_STATUS; // 0 = Registration denied + // 1 = Registration pending + // 2 = Registered + // -1 = unknown registration status +// +// OID_WW_GEN_RADIO_LINK_SPEED +// + +typedef UINT WW_RADIO_LINK_SPEED; // Bits per second. +// +// OID_WW_GEN_LATENCY +// + +typedef UINT WW_LATENCY; // milliseconds +// +// OID_WW_GEN_BATTERY_LEVEL +// + +typedef INT WW_BATTERY_LEVEL; // 0-100 = battery level in percentage + // (100=fully charged) + // -1 = unknown battery level. +// +// OID_WW_GEN_EXTERNAL_POWER +// + +typedef INT WW_EXTERNAL_POWER; // 0 = no external power connected + // 1 = external power connected + // -1 = unknown +// +// OID_WW_MET_FUNCTION +// + +typedef NDIS_VAR_DATA_DESC WW_MET_FUNCTION; +// +// OID_WW_TAC_COMPRESSION +// +typedef BOOLEAN WW_TAC_COMPRESSION; // Determines whether or not network level compression + // is being used. +// +// OID_WW_TAC_SET_CONFIG +// + +typedef struct _WW_TAC_SETCONFIG { + NDIS_VAR_DATA_DESC RCV_MODE; + NDIS_VAR_DATA_DESC TX_CONTROL; + NDIS_VAR_DATA_DESC RX_CONTROL; + NDIS_VAR_DATA_DESC FLOW_CONTROL; + NDIS_VAR_DATA_DESC RESET_CNF; + NDIS_VAR_DATA_DESC READ_CNF; +} WW_TAC_SETCONFIG, *PWW_TAC_SETCONFIG; + +// +// OID_WW_TAC_GET_STATUS +// +typedef struct _WW_TAC_GETSTATUS { + BOOLEAN Action; // Set = Execute command. + + NDIS_VAR_DATA_DESC Command; + NDIS_VAR_DATA_DESC Option; + NDIS_VAR_DATA_DESC Response; // The response to the requested command + // - max. length of string is 256 octets. + +} WW_TAC_GETSTATUS, *PWW_TAC_GETSTATUS; + +// +// OID_WW_TAC_USER_HEADER +// +typedef NDIS_VAR_DATA_DESC WW_TAC_USERHEADER; // This will hold the user header - Max. 64 octets. +// +// OID_WW_ARD_SNDCP +// + +typedef struct _WW_ARD_SNDCP { + NDIS_VAR_DATA_DESC Version; // The version of SNDCP protocol supported. + + INT BlockSize; // The block size used for SNDCP + + INT Window; // The window size used in SNDCP + +} WW_ARD_SNDCP, *PWW_ARD_SNDCP; + +// +// OID_WW_ARD_TMLY_MSG +// +typedef BOOLEAN WW_ARD_CHANNEL_STATUS; // The current status of the inbound RF Channel. +// +// OID_WW_ARD_DATAGRAM +// + +typedef struct _WW_ARD_DATAGRAM { + BOOLEAN LoadLevel; // Byte that contains the load level info. + + INT SessionTime; // Datagram session time remaining. + + NDIS_VAR_DATA_DESC HostAddr; // Host address. + + NDIS_VAR_DATA_DESC THostAddr; // Test host address. + +} WW_ARD_DATAGRAM, *PWW_ARD_DATAGRAM; + +// +// OID_WW_CDPD_SPNI +// +typedef struct _WW_CDPD_SPNI { + UINT SPNI[10]; //10 16-bit service provider network IDs + + INT OperatingMode; // 0 = ignore SPNI, + // 1 = require SPNI from list, + // 2 = prefer SPNI from list. + // 3 = exclude SPNI from list. + +} WW_CDPD_SPNI, *PWW_CDPD_SPNI; + +// +// OID_WW_CDPD_WASI +// +typedef struct _WW_CDPD_WIDE_AREA_SERVICE_ID { + UINT WASI[10]; //10 16-bit wide area service IDs + + INT OperatingMode; // 0 = ignore WASI, + // 1 = Require WASI from list, + // 2 = prefer WASI from list + // 3 = exclude WASI from list. + +} WW_CDPD_WIDE_AREA_SERVICE_ID, *PWW_CDPD_WIDE_AREA_SERVICE_ID; + +// +// OID_WW_CDPD_AREA_COLOR +// +typedef INT WW_CDPD_AREA_COLOR; +// +// OID_WW_CDPD_TX_POWER_LEVEL +// +typedef UINT WW_CDPD_TX_POWER_LEVEL; +// +// OID_WW_CDPD_EID +// +typedef NDIS_VAR_DATA_DESC WW_CDPD_EID; +// +// OID_WW_CDPD_HEADER_COMPRESSION +// +typedef INT WW_CDPD_HEADER_COMPRESSION; // 0 = no header compression, + // 1 = always compress headers, + // 2 = compress headers if MD-IS does + // -1 = unknown +// +// OID_WW_CDPD_DATA_COMPRESSION +// + +typedef INT WW_CDPD_DATA_COMPRESSION; // 0 = no data compression, + // 1 = data compression enabled + // -1 = unknown +// +// OID_WW_CDPD_CHANNEL_SELECT +// + +typedef struct _WW_CDPD_CHANNEL_SELECT { + UINT ChannelID; // channel number + + UINT fixedDuration; // duration in seconds + +} WW_CDPD_CHANNEL_SELECT, *PWW_CDPD_CHANNEL_SELECT; + +// +// OID_WW_CDPD_CHANNEL_STATE +// +typedef enum _WW_CDPD_CHANNEL_STATE { + CDPDChannelNotAvail, + CDPDChannelScanning, + CDPDChannelInitAcquired, + CDPDChannelAcquired, + CDPDChannelSleeping, + CDPDChannelWaking, + CDPDChannelCSDialing, + CDPDChannelCSRedial, + CDPDChannelCSAnswering, + CDPDChannelCSConnected, + CDPDChannelCSSuspended +} WW_CDPD_CHANNEL_STATE, *PWW_CDPD_CHANNEL_STATE; + +// +// OID_WW_CDPD_NEI +// +typedef enum _WW_CDPD_NEI_FORMAT { + CDPDNeiIPv4, + CDPDNeiCLNP, + CDPDNeiIPv6 +} WW_CDPD_NEI_FORMAT, *PWW_CDPD_NEI_FORMAT; +typedef enum _WW_CDPD_NEI_TYPE { + CDPDNeiIndividual, + CDPDNeiMulticast, + CDPDNeiBroadcast +} WW_CDPD_NEI_TYPE; +typedef struct _WW_CDPD_NEI { + UINT uNeiIndex; + WW_CDPD_NEI_FORMAT NeiFormat; + WW_CDPD_NEI_TYPE NeiType; + WORD NeiGmid; // group member identifier, only + // meaningful if NeiType == + // CDPDNeiMulticast + + NDIS_VAR_DATA_DESC NeiAddress; +} WW_CDPD_NEI; + +// +// OID_WW_CDPD_NEI_STATE +// +typedef enum _WW_CDPD_NEI_STATE { + CDPDUnknown, + CDPDRegistered, + CDPDDeregistered +} WW_CDPD_NEI_STATE, *PWW_CDPD_NEI_STATE; +typedef enum _WW_CDPD_NEI_SUB_STATE { + CDPDPending, // Registration pending + CDPDNoReason, // Registration denied - no reason given + CDPDMDISNotCapable, // Registration denied - MD-IS not capable of + // handling M-ES at this time + CDPDNEINotAuthorized, // Registration denied - NEI is not authorized to + // use this subnetwork + CDPDInsufficientAuth, // Registration denied - M-ES gave insufficient + // authentication credentials + CDPDUnsupportedAuth, // Registration denied - M-ES gave unsupported + // authentication credentials + CDPDUsageExceeded, // Registration denied - NEI has exceeded usage + // limitations + CDPDDeniedThisNetwork // Registration denied on this network, service + // may be obtained on alternate Service Provider + // network +} WW_CDPD_NEI_SUB_STATE; +typedef struct _WW_CDPD_NEI_REG_STATE { + UINT uNeiIndex; + WW_CDPD_NEI_STATE NeiState; + WW_CDPD_NEI_SUB_STATE NeiSubState; +} WW_CDPD_NEI_REG_STATE, *PWW_CDPD_NEI_REG_STATE; + +// +// OID_WW_CDPD_SERVICE_PROVIDER_IDENTIFIER +// +typedef struct _WW_CDPD_SERVICE_PROVIDER_ID { + UINT SPI[10]; //10 16-bit service provider IDs + + INT OperatingMode; // 0 = ignore SPI, + // 1 = require SPI from list, + // 2 = prefer SPI from list. + // 3 = exclude SPI from list. + +} WW_CDPD_SERVICE_PROVIDER_ID, *PWW_CDPD_SERVICE_PROVIDER_ID; + +// +// OID_WW_CDPD_SLEEP_MODE +// +typedef INT WW_CDPD_SLEEP_MODE; +// +// OID_WW_CDPD_TEI +// +typedef ULONG WW_CDPD_TEI; +// +// OID_WW_CDPD_CIRCUIT_SWITCHED +// +typedef struct _WW_CDPD_CIRCUIT_SWITCHED { + INT service_preference; // -1 = unknown, + // 0 = always use packet switched CDPD, + // 1 = always use CS CDPD via AMPS, + // 2 = always use CS CDPD via PSTN, + // 3 = use circuit switched via AMPS only + // when packet switched is not available. + // 4 = use packet switched only when circuit + // switched via AMPS is not available. + // 5 = device manuf. defined service + // preference. + // 6 = device manuf. defined service + // preference. + + INT service_status; // -1 = unknown, + // 0 = packet switched CDPD, + // 1 = circuit switched CDPD via AMPS, + // 2 = circuit switched CDPD via PSTN. + + INT connect_rate; // CS connection bit rate (bits per second). + // 0 = no active connection, + // -1 = unknown + // Dial code last used to dial. + + NDIS_VAR_DATA_DESC dial_code[20]; + + UINT sid; // Current AMPS system ID + + INT a_b_side_selection; // -1 = unknown, + // 0 = no AMPS service + // 1 = AMPS "A" side channels selected + // 2 = AMPS "B" side channels selected + + INT AMPS_channel; // -1= unknown + // 0 = no AMPS service. + // 1-1023 = AMPS channel number in use + + UINT action; // 0 = no action + // 1 = suspend (hangup) + // 2 = dial + + // Default dial code for CS CDPD service + // encoded as specified in the CS CDPD + // implementor guidelines. + NDIS_VAR_DATA_DESC default_dial[20]; + + // Number for the CS CDPD network to call + // back the mobile, encoded as specified in + // the CS CDPD implementor guidelines. + NDIS_VAR_DATA_DESC call_back[20]; + + UINT sid_list[10]; // List of 10 16-bit preferred AMPS + // system IDs for CS CDPD. + + UINT inactivity_timer; // Wait time after last data before dropping + // call. + // 0-65535 = inactivity time limit (seconds). + + UINT receive_timer; // secs. per CS-CDPD Implementor Guidelines. + + UINT conn_resp_timer; // secs. per CS-CDPD Implementor Guidelines. + + UINT reconn_resp_timer; // secs. per CS-CDPD Implementor Guidelines. + + UINT disconn_timer; // secs. per CS-CDPD Implementor Guidelines. + + UINT NEI_reg_timer; // secs. per CS-CDPD Implementor Guidelines. + + UINT reconn_retry_timer; // secs. per CS-CDPD Implementor Guidelines. + + UINT link_reset_timer; // secs. per CS-CDPD Implementor Guidelines. + + UINT link_reset_ack_timer; // secs. per CS-CDPD Implementor Guidelines. + + UINT n401_retry_limit; // per CS-CDPD Implementor Guidelines. + + UINT n402_retry_limit; // per CS-CDPD Implementor Guidelines. + + UINT n404_retry_limit; // per CS-CDPD Implementor Guidelines. + + UINT n405_retry_limit; // per CS-CDPD Implementor Guidelines. + +} WW_CDPD_CIRCUIT_SWITCHED, *WW_PCDPD_CIRCUIT_SWITCHED; +typedef UINT WW_CDPD_RSSI; +// +// OID_WW_PIN_LOC_AUTHORIZE +// +typedef INT WW_PIN_AUTHORIZED; // 0 = unauthorized + // 1 = authorized + // -1 = unknown +// +// OID_WW_PIN_LAST_LOCATION +// OID_WW_PIN_LOC_FIX +// + +typedef struct _WW_PIN_LOCATION { + INT Latitude; // Latitude in hundredths of a second + + INT Longitude; // Longitude in hundredths of a second + + INT Altitude; // Altitude in feet + + INT FixTime; // Time of the location fix, since midnight, local time (of the + // current day), in tenths of a second + + INT NetTime; // Current local network time of the current day, since midnight, + // in tenths of a second + + INT LocQuality; // 0-100 = location quality + + INT LatReg; // Latitude registration offset, in hundredths of a second + + INT LongReg; // Longitude registration offset, in hundredths of a second + + INT GMTOffset; // Offset in minutes of the local time zone from GMT + +} WW_PIN_LOCATION, *PWW_PIN_LOCATION; + +// +// The following is set on a per-packet basis as OOB data with NdisClassWirelessWanMbxMailbox +// +typedef ULONG WW_MBX_MAILBOX_FLAG; // 1 = set mailbox flag, 0 = do not set mailbox flag +// +// OID_WW_MBX_SUBADDR +// + +typedef struct _WW_MBX_PMAN { + BOOLEAN ACTION; // 0 = Login PMAN, 1 = Logout PMAN + + UINT MAN; + UCHAR PASSWORD[8]; // Password should be null for Logout and indications. + // Maximum length of password is 8 chars. + +} WW_MBX_PMAN, *PWW_MBX_PMAN; + +// +// OID_WW_MBX_FLEXLIST +// +typedef struct _WW_MBX_FLEXLIST { + INT count; // Number of MAN entries used. + // -1=unknown. + + UINT MAN[7]; // List of MANs. + +} WW_MBX_FLEXLIST; + +// +// OID_WW_MBX_GROUPLIST +// +typedef struct _WW_MBX_GROUPLIST { + INT count; // Number of MAN entries used. + // -1=unknown. + + UINT MAN[15]; // List of MANs. + +} WW_MBX_GROUPLIST; + +// +// OID_WW_MBX_TRAFFIC_AREA +// +typedef enum _WW_MBX_TRAFFIC_AREA { + unknown_traffic_area, // The driver has no information about the current traffic area. + in_traffic_area, // Mobile unit has entered a subscribed traffic area. + in_auth_traffic_area, // Mobile unit is outside traffic area but is authorized. + unauth_traffic_area // Mobile unit is outside traffic area but is un-authorized. +} WW_MBX_TRAFFIC_AREA; + +// +// OID_WW_MBX_LIVE_DIE +// +typedef INT WW_MBX_LIVE_DIE; // 0 = DIE last received + // 1 = LIVE last received + // -1 = unknown +// +// OID_WW_MBX_TEMP_DEFAULTLIST +// + +typedef struct _WW_MBX_CHANNEL_PAIR { + UINT Mobile_Tx; + UINT Mobile_Rx; +} WW_MBX_CHANNEL_PAIR, *PWW_MBX_CHANNEL_PAIR; +typedef struct _WW_MBX_TEMPDEFAULTLIST { + UINT Length; + WW_MBX_CHANNEL_PAIR ChannelPair[1]; +} WW_MBX_TEMPDEFAULTLIST, *WW_PMBX_TEMPDEFAULTLIST; + +#endif // WIRELESS_WAN +#endif // _NTDDNDIS_ diff --git a/plugins/dev9ghzdrk/Win32/afxresmw.h b/plugins/dev9ghzdrk/Win32/afxresmw.h new file mode 100644 index 000000000..99eace37c --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/afxresmw.h @@ -0,0 +1,5 @@ + +#include +#include + +#define IDC_STATIC (-1) diff --git a/plugins/dev9ghzdrk/Win32/ata.cpp b/plugins/dev9ghzdrk/Win32/ata.cpp new file mode 100644 index 000000000..de5f27305 --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/ata.cpp @@ -0,0 +1,3442 @@ +/* + * QEMU IDE disk and CD-ROM Emulator + * + * Copyright (c) 2003 Fabrice Bellard + * + * 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. + */ +#include "dev9.h" +#include "vl.h" + +/* debug IDE devices */ +//#define DEBUG_IDE +//#define DEBUG_IDE_ATAPI +//#define DEBUG_AIO + +#define USE_DMA_CDROM +#define QEMU_VERSION " PCSX2" +#define snprintf _snprintf + +#define le32_to_cpu(x) (x) +#define le16_to_cpu(x) (x) +#define cpu_to_le16(x) (x) +#define cpu_to_le32(x) (x) + +/* Bits of HD_STATUS */ +#define ERR_STAT 0x01 +#define INDEX_STAT 0x02 +#define ECC_STAT 0x04 /* Corrected error */ +#define DRQ_STAT 0x08 +#define SEEK_STAT 0x10 +#define SRV_STAT 0x10 +#define WRERR_STAT 0x20 +#define READY_STAT 0x40 +#define BUSY_STAT 0x80 + +/* Bits for HD_ERROR */ +#define MARK_ERR 0x01 /* Bad address mark */ +#define TRK0_ERR 0x02 /* couldn't find track 0 */ +#define ABRT_ERR 0x04 /* Command aborted */ +#define MCR_ERR 0x08 /* media change request */ +#define ID_ERR 0x10 /* ID field not found */ +#define MC_ERR 0x20 /* media changed */ +#define ECC_ERR 0x40 /* Uncorrectable ECC error */ +#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */ +#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */ + +/* Bits of HD_NSECTOR */ +#define CD 0x01 +#define IO 0x02 +#define REL 0x04 +#define TAG_MASK 0xf8 + +#define IDE_CMD_RESET 0x04 +#define IDE_CMD_DISABLE_IRQ 0x02 + +/* ATA/ATAPI Commands pre T13 Spec */ +#define WIN_NOP 0x00 +/* + * 0x01->0x02 Reserved + */ +#define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */ +/* + * 0x04->0x07 Reserved + */ +#define WIN_SRST 0x08 /* ATAPI soft reset command */ +#define WIN_DEVICE_RESET 0x08 +/* + * 0x09->0x0F Reserved + */ +#define WIN_RECAL 0x10 +#define WIN_RESTORE WIN_RECAL +/* + * 0x10->0x1F Reserved + */ +#define WIN_READ 0x20 /* 28-Bit */ +#define WIN_READ_ONCE 0x21 /* 28-Bit without retries */ +#define WIN_READ_LONG 0x22 /* 28-Bit */ +#define WIN_READ_LONG_ONCE 0x23 /* 28-Bit without retries */ +#define WIN_READ_EXT 0x24 /* 48-Bit */ +#define WIN_READDMA_EXT 0x25 /* 48-Bit */ +#define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit */ +#define WIN_READ_NATIVE_MAX_EXT 0x27 /* 48-Bit */ +/* + * 0x28 + */ +#define WIN_MULTREAD_EXT 0x29 /* 48-Bit */ +/* + * 0x2A->0x2F Reserved + */ +#define WIN_WRITE 0x30 /* 28-Bit */ +#define WIN_WRITE_ONCE 0x31 /* 28-Bit without retries */ +#define WIN_WRITE_LONG 0x32 /* 28-Bit */ +#define WIN_WRITE_LONG_ONCE 0x33 /* 28-Bit without retries */ +#define WIN_WRITE_EXT 0x34 /* 48-Bit */ +#define WIN_WRITEDMA_EXT 0x35 /* 48-Bit */ +#define WIN_WRITEDMA_QUEUED_EXT 0x36 /* 48-Bit */ +#define WIN_SET_MAX_EXT 0x37 /* 48-Bit */ +#define CFA_WRITE_SECT_WO_ERASE 0x38 /* CFA Write Sectors without erase */ +#define WIN_MULTWRITE_EXT 0x39 /* 48-Bit */ +/* + * 0x3A->0x3B Reserved + */ +#define WIN_WRITE_VERIFY 0x3C /* 28-Bit */ +/* + * 0x3D->0x3F Reserved + */ +#define WIN_VERIFY 0x40 /* 28-Bit - Read Verify Sectors */ +#define WIN_VERIFY_ONCE 0x41 /* 28-Bit - without retries */ +#define WIN_VERIFY_EXT 0x42 /* 48-Bit */ +/* + * 0x43->0x4F Reserved + */ +#define WIN_FORMAT 0x50 +/* + * 0x51->0x5F Reserved + */ +#define WIN_INIT 0x60 +/* + * 0x61->0x5F Reserved + */ +#define WIN_SEEK 0x70 /* 0x70-0x7F Reserved */ +#define CFA_TRANSLATE_SECTOR 0x87 /* CFA Translate Sector */ +#define WIN_DIAGNOSE 0x90 +#define WIN_SPECIFY 0x91 /* set drive geometry translation */ +#define WIN_DOWNLOAD_MICROCODE 0x92 +#define WIN_STANDBYNOW2 0x94 +#define WIN_STANDBY2 0x96 +#define WIN_SETIDLE2 0x97 +#define WIN_CHECKPOWERMODE2 0x98 +#define WIN_SLEEPNOW2 0x99 +/* + * 0x9A VENDOR + */ +#define WIN_PACKETCMD 0xA0 /* Send a packet command. */ +#define WIN_PIDENTIFY 0xA1 /* identify ATAPI device */ +#define WIN_QUEUED_SERVICE 0xA2 +#define WIN_SMART 0xB0 /* self-monitoring and reporting */ +#define CFA_ERASE_SECTORS 0xC0 +#define WIN_MULTREAD 0xC4 /* read sectors using multiple mode*/ +#define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */ +#define WIN_SETMULT 0xC6 /* enable/disable multiple mode */ +#define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers */ +#define WIN_READDMA 0xC8 /* read sectors using DMA transfers */ +#define WIN_READDMA_ONCE 0xC9 /* 28-Bit - without retries */ +#define WIN_WRITEDMA 0xCA /* write sectors using DMA transfers */ +#define WIN_WRITEDMA_ONCE 0xCB /* 28-Bit - without retries */ +#define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers */ +#define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */ +#define WIN_GETMEDIASTATUS 0xDA +#define WIN_ACKMEDIACHANGE 0xDB /* ATA-1, ATA-2 vendor */ +#define WIN_POSTBOOT 0xDC +#define WIN_PREBOOT 0xDD +#define WIN_DOORLOCK 0xDE /* lock door on removable drives */ +#define WIN_DOORUNLOCK 0xDF /* unlock door on removable drives */ +#define WIN_STANDBYNOW1 0xE0 +#define WIN_IDLEIMMEDIATE 0xE1 /* force drive to become "ready" */ +#define WIN_STANDBY 0xE2 /* Set device in Standby Mode */ +#define WIN_SETIDLE1 0xE3 +#define WIN_READ_BUFFER 0xE4 /* force read only 1 sector */ +#define WIN_CHECKPOWERMODE1 0xE5 +#define WIN_SLEEPNOW1 0xE6 +#define WIN_FLUSH_CACHE 0xE7 +#define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */ +#define WIN_WRITE_SAME 0xE9 /* read ata-2 to use */ + /* SET_FEATURES 0x22 or 0xDD */ +#define WIN_FLUSH_CACHE_EXT 0xEA /* 48-Bit */ +#define WIN_IDENTIFY 0xEC /* ask drive to identify itself */ +#define WIN_MEDIAEJECT 0xED +#define WIN_IDENTIFY_DMA 0xEE /* same as WIN_IDENTIFY, but DMA */ +#define WIN_SETFEATURES 0xEF /* set special drive features */ +#define EXABYTE_ENABLE_NEST 0xF0 +#define WIN_SECURITY_SET_PASS 0xF1 +#define WIN_SECURITY_UNLOCK 0xF2 +#define WIN_SECURITY_ERASE_PREPARE 0xF3 +#define WIN_SECURITY_ERASE_UNIT 0xF4 +#define WIN_SECURITY_FREEZE_LOCK 0xF5 +#define WIN_SECURITY_DISABLE 0xF6 +#define WIN_READ_NATIVE_MAX 0xF8 /* return the native maximum address */ +#define WIN_SET_MAX 0xF9 +#define DISABLE_SEAGATE 0xFB + +/* set to 1 set disable mult support */ +#define MAX_MULT_SECTORS 16 + +/* ATAPI defines */ + +#define ATAPI_PACKET_SIZE 12 + +/* The generic packet command opcodes for CD/DVD Logical Units, + * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ +#define GPCMD_BLANK 0xa1 +#define GPCMD_CLOSE_TRACK 0x5b +#define GPCMD_FLUSH_CACHE 0x35 +#define GPCMD_FORMAT_UNIT 0x04 +#define GPCMD_GET_CONFIGURATION 0x46 +#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a +#define GPCMD_GET_PERFORMANCE 0xac +#define GPCMD_INQUIRY 0x12 +#define GPCMD_LOAD_UNLOAD 0xa6 +#define GPCMD_MECHANISM_STATUS 0xbd +#define GPCMD_MODE_SELECT_10 0x55 +#define GPCMD_MODE_SENSE_10 0x5a +#define GPCMD_PAUSE_RESUME 0x4b +#define GPCMD_PLAY_AUDIO_10 0x45 +#define GPCMD_PLAY_AUDIO_MSF 0x47 +#define GPCMD_PLAY_AUDIO_TI 0x48 +#define GPCMD_PLAY_CD 0xbc +#define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e +#define GPCMD_READ_10 0x28 +#define GPCMD_READ_12 0xa8 +#define GPCMD_READ_CDVD_CAPACITY 0x25 +#define GPCMD_READ_CD 0xbe +#define GPCMD_READ_CD_MSF 0xb9 +#define GPCMD_READ_DISC_INFO 0x51 +#define GPCMD_READ_DVD_STRUCTURE 0xad +#define GPCMD_READ_FORMAT_CAPACITIES 0x23 +#define GPCMD_READ_HEADER 0x44 +#define GPCMD_READ_TRACK_RZONE_INFO 0x52 +#define GPCMD_READ_SUBCHANNEL 0x42 +#define GPCMD_READ_TOC_PMA_ATIP 0x43 +#define GPCMD_REPAIR_RZONE_TRACK 0x58 +#define GPCMD_REPORT_KEY 0xa4 +#define GPCMD_REQUEST_SENSE 0x03 +#define GPCMD_RESERVE_RZONE_TRACK 0x53 +#define GPCMD_SCAN 0xba +#define GPCMD_SEEK 0x2b +#define GPCMD_SEND_DVD_STRUCTURE 0xad +#define GPCMD_SEND_EVENT 0xa2 +#define GPCMD_SEND_KEY 0xa3 +#define GPCMD_SEND_OPC 0x54 +#define GPCMD_SET_READ_AHEAD 0xa7 +#define GPCMD_SET_STREAMING 0xb6 +#define GPCMD_START_STOP_UNIT 0x1b +#define GPCMD_STOP_PLAY_SCAN 0x4e +#define GPCMD_TEST_UNIT_READY 0x00 +#define GPCMD_VERIFY_10 0x2f +#define GPCMD_WRITE_10 0x2a +#define GPCMD_WRITE_AND_VERIFY_10 0x2e +/* This is listed as optional in ATAPI 2.6, but is (curiously) + * missing from Mt. Fuji, Table 57. It _is_ mentioned in Mt. Fuji + * Table 377 as an MMC command for SCSi devices though... Most ATAPI + * drives support it. */ +#define GPCMD_SET_SPEED 0xbb +/* This seems to be a SCSI specific CD-ROM opcode + * to play data at track/index */ +#define GPCMD_PLAYAUDIO_TI 0x48 +/* + * From MS Media Status Notification Support Specification. For + * older drives only. + */ +#define GPCMD_GET_MEDIA_STATUS 0xda + +/* Mode page codes for mode sense/set */ +#define GPMODE_R_W_ERROR_PAGE 0x01 +#define GPMODE_WRITE_PARMS_PAGE 0x05 +#define GPMODE_AUDIO_CTL_PAGE 0x0e +#define GPMODE_POWER_PAGE 0x1a +#define GPMODE_FAULT_FAIL_PAGE 0x1c +#define GPMODE_TO_PROTECT_PAGE 0x1d +#define GPMODE_CAPABILITIES_PAGE 0x2a +#define GPMODE_ALL_PAGES 0x3f +/* Not in Mt. Fuji, but in ATAPI 2.6 -- depricated now in favor + * of MODE_SENSE_POWER_PAGE */ +#define GPMODE_CDROM_PAGE 0x0d + +#define ATAPI_INT_REASON_CD 0x01 /* 0 = data transfer */ +#define ATAPI_INT_REASON_IO 0x02 /* 1 = transfer to the host */ +#define ATAPI_INT_REASON_REL 0x04 +#define ATAPI_INT_REASON_TAG 0xf8 + +/* same constants as bochs */ +#define ASC_ILLEGAL_OPCODE 0x20 +#define ASC_LOGICAL_BLOCK_OOR 0x21 +#define ASC_INV_FIELD_IN_CMD_PACKET 0x24 +#define ASC_MEDIUM_NOT_PRESENT 0x3a +#define ASC_SAVING_PARAMETERS_NOT_SUPPORTED 0x39 + +#define SENSE_NONE 0 +#define SENSE_NOT_READY 2 +#define SENSE_ILLEGAL_REQUEST 5 +#define SENSE_UNIT_ATTENTION 6 + +struct IDEState; + +typedef void EndTransferFunc(struct IDEState *); + +/* NOTE: IDEState represents in fact one drive */ +typedef struct IDEState { + /* ide config */ + int is_cdrom; + int cylinders, heads, sectors; + int64_t nb_sectors; + int mult_sectors; + int identify_set; + uint16_t identify_data[256]; + SetIRQFunc *set_irq; + void *irq_opaque; + int irq; + //* PCIDevice *pci_dev; + struct BMDMAState *bmdma; + int drive_serial; + /* ide regs */ + uint8_t feature; + uint8_t error; + uint32_t nsector; + uint8_t sector; + uint8_t lcyl; + uint8_t hcyl; + /* other part of tf for lba48 support */ + uint8_t hob_feature; + uint8_t hob_nsector; + uint8_t hob_sector; + uint8_t hob_lcyl; + uint8_t hob_hcyl; + + uint8_t select; + uint8_t status; + + /* 0x3f6 command, only meaningful for drive 0 */ + uint8_t cmd; + /* set for lba48 access */ + uint8_t lba48; + /* depends on bit 4 in select, only meaningful for drive 0 */ + struct IDEState *cur_drive; + BlockDriverState *bs; + /* ATAPI specific */ + uint8_t sense_key; + uint8_t asc; + int packet_transfer_size; + int elementary_transfer_size; + int io_buffer_index; + int lba; + int cd_sector_size; + int atapi_dma; /* true if dma is requested for the packet cmd */ + /* ATA DMA state */ + int io_buffer_size; + /* PIO transfer handling */ + int req_nb_sectors; /* number of sectors per interrupt */ + EndTransferFunc *end_transfer_func; + uint8_t *data_ptr; + uint8_t *data_end; + uint8_t io_buffer[MAX_MULT_SECTORS*512 + 4]; + QEMUTimer *sector_write_timer; /* only used for win2k instal hack */ + uint32_t irq_count; /* counts IRQs when using win2k install hack */ +} IDEState; + +#define BM_STATUS_DMAING 0x01 +#define BM_STATUS_ERROR 0x02 +#define BM_STATUS_INT 0x04 + +#define BM_CMD_START 0x01 +#define BM_CMD_READ 0x08 + +#define IDE_TYPE_PIIX3 0 +#define IDE_TYPE_CMD646 1 + +/* CMD646 specific */ +#define MRDMODE 0x71 +#define MRDMODE_INTR_CH0 0x04 +#define MRDMODE_INTR_CH1 0x08 +#define MRDMODE_BLK_CH0 0x10 +#define MRDMODE_BLK_CH1 0x20 +#define UDIDETCR0 0x73 +#define UDIDETCR1 0x7B + +typedef struct BMDMAState { + uint8_t cmd; + uint8_t status; + uint32_t addr; + + // struct PCIIDEState *pci_dev; + /* current transfer state */ + uint32_t cur_addr; + uint32_t cur_prd_last; + uint32_t cur_prd_addr; + uint32_t cur_prd_len; + IDEState *ide_if; + BlockDriverCompletionFunc *dma_cb; + BlockDriverAIOCB *aiocb; +} BMDMAState; +struct BlockDriverState { + int64_t total_sectors; /* if we are reading a disk image, give its + size in sectors */ + int read_only; /* if true, the media is read only */ + int removable; /* if true, the media can be removed */ + int locked; /* if true, the media cannot temporarily be ejected */ + int encrypted; /* if true, the media is encrypted */ + /* event callback when inserting/removing */ + void (*change_cb)(void *opaque); + void *change_opaque; + + BlockDriver *drv; /* NULL means no media */ + void *opaque; + + int boot_sector_enabled; + uint8_t boot_sector_data[512]; + + char filename[1024]; + char backing_file[1024]; /* if non zero, the image is a diff of + this file image */ + int is_temporary; + int media_changed; + + /* async read/write emulation */ + + void *sync_aiocb; + + /* NOTE: the following infos are only hints for real hardware + drivers. They are not used by the block driver */ + int cyls, heads, secs, translation; + int type; + char device_name[32]; +}; +#if 0 +typedef struct PCIIDEState { + PCIDevice dev; + IDEState ide_if[4]; + BMDMAState bmdma[2]; + int type; /* see IDE_TYPE_xxx */ +} PCIIDEState; +#endif +static void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb); +static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret); + +void cpu_physical_memory_write(u32 addr,void* ptr,u32 sz); +void cpu_physical_memory_read(u32 addr,void* ptr,u32 sz); + +static void padstr(char *str, const char *src, int len) +{ + int i, v; + for(i = 0; i < len; i++) { + if (*src) + v = *src++; + else + v = ' '; + *(char *)((long)str ^ 1) = v; + str++; + } +} + +static void padstr8(uint8_t *buf, int buf_size, const char *src) +{ + int i; + for(i = 0; i < buf_size; i++) { + if (*src) + buf[i] = *src++; + else + buf[i] = ' '; + } +} + +static void put_le16(uint16_t *p, unsigned int v) +{ + *p = (v); +} + +static void ide_identify(IDEState *s) +{ + uint16_t *p; + unsigned int oldsize; + char buf[20]; + + if (s->identify_set) { + memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data)); + return; + } + + memset(s->io_buffer, 0, 512); + p = (uint16_t *)s->io_buffer; + put_le16(p + 0, 0x0040); + put_le16(p + 1, s->cylinders); + put_le16(p + 3, s->heads); + put_le16(p + 4, 512 * s->sectors); /* XXX: retired, remove ? */ + put_le16(p + 5, 512); /* XXX: retired, remove ? */ + put_le16(p + 6, s->sectors); + snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial); + padstr((char *)(p + 10), buf, 20); /* serial number */ + put_le16(p + 20, 3); /* XXX: retired, remove ? */ + put_le16(p + 21, 512); /* cache size in sectors */ + put_le16(p + 22, 4); /* ecc bytes */ + padstr((char *)(p + 23), QEMU_VERSION, 8); /* firmware version */ + padstr((char *)(p + 27), "QEMU HARDDISK", 40); /* model */ +#if MAX_MULT_SECTORS > 1 + put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS); +#endif + put_le16(p + 48, 1); /* dword I/O */ + put_le16(p + 49, (1 << 11) | (1 << 9) | (1 << 8)); /* DMA and LBA supported */ + put_le16(p + 51, 0x200); /* PIO transfer cycle */ + put_le16(p + 52, 0x200); /* DMA transfer cycle */ + put_le16(p + 53, 1 | (1 << 1) | (1 << 2)); /* words 54-58,64-70,88 are valid */ + put_le16(p + 54, s->cylinders); + put_le16(p + 55, s->heads); + put_le16(p + 56, s->sectors); + oldsize = s->cylinders * s->heads * s->sectors; + put_le16(p + 57, oldsize); + put_le16(p + 58, oldsize >> 16); + if (s->mult_sectors) + put_le16(p + 59, 0x100 | s->mult_sectors); + put_le16(p + 60, s->nb_sectors); + put_le16(p + 61, s->nb_sectors >> 16); + put_le16(p + 63, 0x07); /* mdma0-2 supported */ + put_le16(p + 65, 120); + put_le16(p + 66, 120); + put_le16(p + 67, 120); + put_le16(p + 68, 120); + put_le16(p + 80, 0xf0); /* ata3 -> ata6 supported */ + put_le16(p + 81, 0x16); /* conforms to ata5 */ + put_le16(p + 82, (1 << 14)); + /* 13=flush_cache_ext,12=flush_cache,10=lba48 */ + put_le16(p + 83, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10)); + put_le16(p + 84, (1 << 14)); + put_le16(p + 85, (1 << 14)); + /* 13=flush_cache_ext,12=flush_cache,10=lba48 */ + put_le16(p + 86, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10)); + put_le16(p + 87, (1 << 14)); + put_le16(p + 88, 0x3f | (1 << 13)); /* udma5 set and supported */ + put_le16(p + 93, 1 | (1 << 14) | 0x2000); + put_le16(p + 100, s->nb_sectors); + put_le16(p + 101, s->nb_sectors >> 16); + put_le16(p + 102, s->nb_sectors >> 32); + put_le16(p + 103, s->nb_sectors >> 48); + + memcpy(s->identify_data, p, sizeof(s->identify_data)); + s->identify_set = 1; +} + +static void ide_atapi_identify(IDEState *s) +{ + uint16_t *p; + char buf[20]; + + if (s->identify_set) { + memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data)); + return; + } + + memset(s->io_buffer, 0, 512); + p = (uint16_t *)s->io_buffer; + /* Removable CDROM, 50us response, 12 byte packets */ + put_le16(p + 0, (2 << 14) | (5 << 8) | (1 << 7) | (2 << 5) | (0 << 0)); + snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial); + padstr((char *)(p + 10), buf, 20); /* serial number */ + put_le16(p + 20, 3); /* buffer type */ + put_le16(p + 21, 512); /* cache size in sectors */ + put_le16(p + 22, 4); /* ecc bytes */ + padstr((char *)(p + 23), QEMU_VERSION, 8); /* firmware version */ + padstr((char *)(p + 27), "QEMU CD-ROM", 40); /* model */ + put_le16(p + 48, 1); /* dword I/O (XXX: should not be set on CDROM) */ +#ifdef USE_DMA_CDROM + put_le16(p + 49, 1 << 9 | 1 << 8); /* DMA and LBA supported */ + put_le16(p + 53, 7); /* words 64-70, 54-58, 88 valid */ + put_le16(p + 63, 7); /* mdma0-2 supported */ + put_le16(p + 64, 0x3f); /* PIO modes supported */ +#else + put_le16(p + 49, 1 << 9); /* LBA supported, no DMA */ + put_le16(p + 53, 3); /* words 64-70, 54-58 valid */ + put_le16(p + 63, 0x103); /* DMA modes XXX: may be incorrect */ + put_le16(p + 64, 1); /* PIO modes */ +#endif + put_le16(p + 65, 0xb4); /* minimum DMA multiword tx cycle time */ + put_le16(p + 66, 0xb4); /* recommended DMA multiword tx cycle time */ + put_le16(p + 67, 0x12c); /* minimum PIO cycle time without flow control */ + put_le16(p + 68, 0xb4); /* minimum PIO cycle time with IORDY flow control */ + + put_le16(p + 71, 30); /* in ns */ + put_le16(p + 72, 30); /* in ns */ + + put_le16(p + 80, 0x1e); /* support up to ATA/ATAPI-4 */ +#ifdef USE_DMA_CDROM + put_le16(p + 88, 0x3f | (1 << 13)); /* udma5 set and supported */ +#endif + memcpy(s->identify_data, p, sizeof(s->identify_data)); + s->identify_set = 1; +} + +static void ide_set_signature(IDEState *s) +{ + s->select &= 0xf0; /* clear head */ + /* put signature */ + s->nsector = 1; + s->sector = 1; + if (s->is_cdrom) { + s->lcyl = 0x14; + s->hcyl = 0xeb; + } else if (s->bs) { + s->lcyl = 0; + s->hcyl = 0; + } else { + s->lcyl = 0xff; + s->hcyl = 0xff; + } +} + +static inline void ide_abort_command(IDEState *s) +{ + s->status = READY_STAT | ERR_STAT; + s->error = ABRT_ERR; +} + +static inline void ide_set_irq(IDEState *s) +{ + BMDMAState *bm = s->bmdma; + if (!(s->cmd & IDE_CMD_DISABLE_IRQ)) { + if (bm) { + bm->status |= BM_STATUS_INT; + } + s->set_irq(s->irq_opaque, s->irq, 1); + } +} + +/* prepare data transfer and tell what to do after */ +static void ide_transfer_start(IDEState *s, uint8_t *buf, int size, + EndTransferFunc *end_transfer_func) +{ + s->end_transfer_func = end_transfer_func; + s->data_ptr = buf; + s->data_end = buf + size; + s->status |= DRQ_STAT; +} + +static void ide_transfer_stop(IDEState *s) +{ + s->end_transfer_func = ide_transfer_stop; + s->data_ptr = s->io_buffer; + s->data_end = s->io_buffer; + s->status &= ~DRQ_STAT; +} + +static int64_t ide_get_sector(IDEState *s) +{ + int64_t sector_num; + if (s->select & 0x40) { + /* lba */ + if (!s->lba48) { + sector_num = ((s->select & 0x0f) << 24) | (s->hcyl << 16) | + (s->lcyl << 8) | s->sector; + } else { + sector_num = ((int64_t)s->hob_hcyl << 40) | + ((int64_t) s->hob_lcyl << 32) | + ((int64_t) s->hob_sector << 24) | + ((int64_t) s->hcyl << 16) | + ((int64_t) s->lcyl << 8) | s->sector; + } + } else { + sector_num = ((s->hcyl << 8) | s->lcyl) * s->heads * s->sectors + + (s->select & 0x0f) * s->sectors + (s->sector - 1); + } + return sector_num; +} + +static void ide_set_sector(IDEState *s, int64_t sector_num) +{ + unsigned int cyl, r; + if (s->select & 0x40) { + if (!s->lba48) { + s->select = (s->select & 0xf0) | (sector_num >> 24); + s->hcyl = (sector_num >> 16); + s->lcyl = (sector_num >> 8); + s->sector = (sector_num); + } else { + s->sector = sector_num; + s->lcyl = sector_num >> 8; + s->hcyl = sector_num >> 16; + s->hob_sector = sector_num >> 24; + s->hob_lcyl = sector_num >> 32; + s->hob_hcyl = sector_num >> 40; + } + } else { + cyl = sector_num / (s->heads * s->sectors); + r = sector_num % (s->heads * s->sectors); + s->hcyl = cyl >> 8; + s->lcyl = cyl; + s->select = (s->select & 0xf0) | ((r / s->sectors) & 0x0f); + s->sector = (r % s->sectors) + 1; + } +} + +static void ide_sector_read(IDEState *s) +{ + int64_t sector_num; + int ret, n; + + s->status = READY_STAT | SEEK_STAT; + s->error = 0; /* not needed by IDE spec, but needed by Windows */ + sector_num = ide_get_sector(s); + n = s->nsector; + if (n == 0) { + /* no more sector to read from disk */ + ide_transfer_stop(s); + } else { +#if defined(DEBUG_IDE) + // printf("read sector=%Ld\n", sector_num); +#endif + printf("ATA: read sector=%Ld\n", sector_num); + + if (n > s->req_nb_sectors) + n = s->req_nb_sectors; + ret = bdrv_read(s->bs, sector_num, s->io_buffer, n); + ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_read); + ide_set_irq(s); + ide_set_sector(s, sector_num + n); + s->nsector -= n; + } +} + +/* return 0 if buffer completed */ +static int dma_buf_rw(BMDMAState *bm, int is_write) +{ + IDEState *s = bm->ide_if; + struct { + uint32_t addr; + uint32_t size; + } prd; + int l, len; + + for(;;) { + l = s->io_buffer_size - s->io_buffer_index; + if (l <= 0) + break; + if (bm->cur_prd_len == 0) { + /* end of table (with a fail safe of one page) */ + if (bm->cur_prd_last || + (bm->cur_addr - bm->addr) >= 4096) + return 0; + emu_printf("dma seems to have ended .. duno what the code i removed from here does.. chan dma ?\n"); + return 2; + /* + ///i wonder what is this + //lets hope its not bad to remove it here xD + cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8); + bm->cur_addr += 8; + prd.addr = le32_to_cpu(prd.addr); + prd.size = le32_to_cpu(prd.size); + len = prd.size & 0xfffe; + if (len == 0) + len = 0x10000; + bm->cur_prd_len = len; + bm->cur_prd_addr = prd.addr; + bm->cur_prd_last = (prd.size & 0x80000000);*/ + } + if (l > bm->cur_prd_len) + l = bm->cur_prd_len; + if (l > 0) { + if (is_write) { + cpu_physical_memory_write(bm->cur_prd_addr, + s->io_buffer + s->io_buffer_index, l); + } else { + cpu_physical_memory_read(bm->cur_prd_addr, + s->io_buffer + s->io_buffer_index, l); + } + bm->cur_prd_addr += l; + bm->cur_prd_len -= l; + s->io_buffer_index += l; + } + } + return 1; +} + +/* XXX: handle errors */ +static void ide_read_dma_cb(void *opaque, int ret) +{ + BMDMAState* bm = (BMDMAState* )opaque; + IDEState *s = (IDEState*)bm->ide_if; + int n; + int64_t sector_num; + + n = s->io_buffer_size >> 9; + sector_num = ide_get_sector(s); + if (n > 0) { + sector_num += n; + ide_set_sector(s, sector_num); + s->nsector -= n; + int dmrv=dma_buf_rw(bm, 1); + if ( dmrv== 0) + goto eot; + else if (dmrv==2) + { + bm->status &= ~BM_STATUS_DMAING; + bm->status |= BM_STATUS_INT; + return; //end of dma buffer (ha !) + } + } + + /* end of transfer ? */ + if (s->nsector == 0) { + s->status = READY_STAT | SEEK_STAT; + ide_set_irq(s); + eot: + bm->status &= ~BM_STATUS_DMAING; + bm->status |= BM_STATUS_INT; + bm->dma_cb = NULL; + bm->ide_if = NULL; + bm->aiocb = NULL; + return; + } + + /* launch next transfer */ + n = s->nsector; + if (n > MAX_MULT_SECTORS) + n = MAX_MULT_SECTORS; + s->io_buffer_index = 0; + s->io_buffer_size = n * 512; +#ifdef DEBUG_AIO + printf("aio_read: sector_num=%lld n=%d\n", sector_num, n); +#endif + bm->aiocb = bdrv_aio_read(s->bs, sector_num, s->io_buffer, n, + ide_read_dma_cb, bm); +} + +static void ide_sector_read_dma(IDEState *s) +{ + s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT; + s->io_buffer_index = 0; + s->io_buffer_size = 0; + ide_dma_start(s, ide_read_dma_cb); +} + +static void ide_sector_write_timer_cb(void *opaque) +{ + IDEState* s = (IDEState*)opaque; + ide_set_irq(s); +} + +static void ide_sector_write(IDEState *s) +{ + int64_t sector_num; + int ret, n, n1; + + s->status = READY_STAT | SEEK_STAT; + sector_num = ide_get_sector(s); +#if defined(DEBUG_IDE) + printf("write sector=%Ld\n", sector_num); +#endif + printf("ATA: write sector=%Ld\n", sector_num); + n = s->nsector; + if (n > s->req_nb_sectors) + n = s->req_nb_sectors; + ret = bdrv_write(s->bs, sector_num, s->io_buffer, n); + s->nsector -= n; + if (s->nsector == 0) { + /* no more sector to write */ + ide_transfer_stop(s); + } else { + n1 = s->nsector; + if (n1 > s->req_nb_sectors) + n1 = s->req_nb_sectors; + ide_transfer_start(s, s->io_buffer, 512 * n1, ide_sector_write); + } + ide_set_sector(s, sector_num + n); + +#ifdef TARGET_I386 + if (win2k_install_hack && ((++s->irq_count % 16) == 0)) { + /* It seems there is a bug in the Windows 2000 installer HDD + IDE driver which fills the disk with empty logs when the + IDE write IRQ comes too early. This hack tries to correct + that at the expense of slower write performances. Use this + option _only_ to install Windows 2000. You must disable it + for normal use. */ + qemu_mod_timer(s->sector_write_timer, + qemu_get_clock(vm_clock) + (ticks_per_sec / 1000)); + } else +#endif + { + ide_set_irq(s); + } +} + +/* XXX: handle errors */ +static void ide_write_dma_cb(void *opaque, int ret) +{ + BMDMAState* bm =(BMDMAState*)opaque; + IDEState* s =(IDEState* ) bm->ide_if; + int n; + int64_t sector_num; + + n = s->io_buffer_size >> 9; + sector_num = ide_get_sector(s); + if (n > 0) { + sector_num += n; + ide_set_sector(s, sector_num); + s->nsector -= n; + } + + /* end of transfer ? */ + if (s->nsector == 0) { + s->status = READY_STAT | SEEK_STAT; + ide_set_irq(s); + eot: + bm->status &= ~BM_STATUS_DMAING; + bm->status |= BM_STATUS_INT; + bm->dma_cb = NULL; + bm->ide_if = NULL; + bm->aiocb = NULL; + return; + } + + /* launch next transfer */ + n = s->nsector; + if (n > MAX_MULT_SECTORS) + n = MAX_MULT_SECTORS; + s->io_buffer_index = 0; + s->io_buffer_size = n * 512; + + int dmrv=dma_buf_rw(bm, 0); + if ( dmrv== 0) + goto eot; + else if (dmrv==2) + { + bm->status &= ~BM_STATUS_DMAING; + bm->status |= BM_STATUS_INT; + return; //end of dma buffer (ha !) + } + +#ifdef DEBUG_AIO + printf("aio_write: sector_num=%lld n=%d\n", sector_num, n); +#endif + bm->aiocb = bdrv_aio_write(s->bs, sector_num, s->io_buffer, n, + ide_write_dma_cb, bm); +} + +static void ide_sector_write_dma(IDEState *s) +{ + s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT; + s->io_buffer_index = 0; + s->io_buffer_size = 0; + ide_dma_start(s, ide_write_dma_cb); +} + +static void ide_atapi_cmd_ok(IDEState *s) +{ + s->error = 0; + s->status = READY_STAT; + s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; + ide_set_irq(s); +} + +static void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc) +{ +#ifdef DEBUG_IDE_ATAPI + //printf("atapi_cmd_error: sense=0x%x asc=0x%x\n", sense_key, asc); +#endif + printf("atapi_cmd_error: sense=0x%x asc=0x%x\n", sense_key, asc); + s->error = sense_key << 4; + s->status = READY_STAT | ERR_STAT; + s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; + s->sense_key = sense_key; + s->asc = asc; + ide_set_irq(s); +} + +static inline void cpu_to_ube16(uint8_t *buf, int val) +{ + buf[0] = val >> 8; + buf[1] = val; +} + +static inline void cpu_to_ube32(uint8_t *buf, unsigned int val) +{ + buf[0] = val >> 24; + buf[1] = val >> 16; + buf[2] = val >> 8; + buf[3] = val; +} + +static inline int ube16_to_cpu(const uint8_t *buf) +{ + return (buf[0] << 8) | buf[1]; +} + +static inline int ube32_to_cpu(const uint8_t *buf) +{ + return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; +} + +static void lba_to_msf(uint8_t *buf, int lba) +{ + lba += 150; + buf[0] = (lba / 75) / 60; + buf[1] = (lba / 75) % 60; + buf[2] = lba % 75; +} + +static void cd_data_to_raw(uint8_t *buf, int lba) +{ + /* sync bytes */ + buf[0] = 0x00; + memset(buf + 1, 0xff, 10); + buf[11] = 0x00; + buf += 12; + /* MSF */ + lba_to_msf(buf, lba); + buf[3] = 0x01; /* mode 1 data */ + buf += 4; + /* data */ + buf += 2048; + /* XXX: ECC not computed */ + memset(buf, 0, 288); +} + +static int cd_read_sector(BlockDriverState *bs, int lba, uint8_t *buf, + int sector_size) +{ + int ret; + + switch(sector_size) { + case 2048: + ret = bdrv_read(bs, (int64_t)lba << 2, buf, 4); + break; + case 2352: + ret = bdrv_read(bs, (int64_t)lba << 2, buf + 16, 4); + if (ret < 0) + return ret; + cd_data_to_raw(buf, lba); + break; + default: + ret = -EIO; + break; + } + return ret; +} + +static void ide_atapi_io_error(IDEState *s, int ret) +{ + /* XXX: handle more errors */ + if (ret == -ENOMEDIUM) { + ide_atapi_cmd_error(s, SENSE_NOT_READY, + ASC_MEDIUM_NOT_PRESENT); + } else { + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, + ASC_LOGICAL_BLOCK_OOR); + } +} + +/* The whole ATAPI transfer logic is handled in this function */ +static void ide_atapi_cmd_reply_end(IDEState *s) +{ + int byte_count_limit, size, ret; +#ifdef DEBUG_IDE_ATAPI + printf("reply: tx_size=%d elem_tx_size=%d index=%d\n", + s->packet_transfer_size, + s->elementary_transfer_size, + s->io_buffer_index); +#endif + if (s->packet_transfer_size <= 0) { + /* end of transfer */ + ide_transfer_stop(s); + s->status = READY_STAT; + s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; + ide_set_irq(s); +#ifdef DEBUG_IDE_ATAPI + printf("status=0x%x\n", s->status); +#endif + } else { + /* see if a new sector must be read */ + if (s->lba != -1 && s->io_buffer_index >= s->cd_sector_size) { + ret = cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size); + if (ret < 0) { + ide_transfer_stop(s); + ide_atapi_io_error(s, ret); + return; + } + s->lba++; + s->io_buffer_index = 0; + } + if (s->elementary_transfer_size > 0) { + /* there are some data left to transmit in this elementary + transfer */ + size = s->cd_sector_size - s->io_buffer_index; + if (size > s->elementary_transfer_size) + size = s->elementary_transfer_size; + ide_transfer_start(s, s->io_buffer + s->io_buffer_index, + size, ide_atapi_cmd_reply_end); + s->packet_transfer_size -= size; + s->elementary_transfer_size -= size; + s->io_buffer_index += size; + } else { + /* a new transfer is needed */ + s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO; + byte_count_limit = s->lcyl | (s->hcyl << 8); +#ifdef DEBUG_IDE_ATAPI + printf("byte_count_limit=%d\n", byte_count_limit); +#endif + if (byte_count_limit == 0xffff) + byte_count_limit--; + size = s->packet_transfer_size; + if (size > byte_count_limit) { + /* byte count limit must be even if this case */ + if (byte_count_limit & 1) + byte_count_limit--; + size = byte_count_limit; + } + s->lcyl = size; + s->hcyl = size >> 8; + s->elementary_transfer_size = size; + /* we cannot transmit more than one sector at a time */ + if (s->lba != -1) { + if (size > (s->cd_sector_size - s->io_buffer_index)) + size = (s->cd_sector_size - s->io_buffer_index); + } + ide_transfer_start(s, s->io_buffer + s->io_buffer_index, + size, ide_atapi_cmd_reply_end); + s->packet_transfer_size -= size; + s->elementary_transfer_size -= size; + s->io_buffer_index += size; + ide_set_irq(s); +#ifdef DEBUG_IDE_ATAPI + printf("status=0x%x\n", s->status); +#endif + } + } +} + +/* send a reply of 'size' bytes in s->io_buffer to an ATAPI command */ +static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size) +{ + if (size > max_size) + size = max_size; + s->lba = -1; /* no sector read */ + s->packet_transfer_size = size; + s->io_buffer_size = size; /* dma: send the reply data as one chunk */ + s->elementary_transfer_size = 0; + s->io_buffer_index = 0; + + if (s->atapi_dma) { + s->status = READY_STAT | DRQ_STAT; + ide_dma_start(s, ide_atapi_cmd_read_dma_cb); + } else { + s->status = READY_STAT; + ide_atapi_cmd_reply_end(s); + } +} + +/* start a CD-CDROM read command */ +static void ide_atapi_cmd_read_pio(IDEState *s, int lba, int nb_sectors, + int sector_size) +{ + s->lba = lba; + s->packet_transfer_size = nb_sectors * sector_size; + s->elementary_transfer_size = 0; + s->io_buffer_index = sector_size; + s->cd_sector_size = sector_size; + + s->status = READY_STAT; + ide_atapi_cmd_reply_end(s); +} + +/* ATAPI DMA support */ + +/* XXX: handle read errors */ +static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret) +{ + BMDMAState* bm =(BMDMAState*) opaque; + IDEState* s =(IDEState*) bm->ide_if; + int data_offset, n; + + if (ret < 0) { + ide_atapi_io_error(s, ret); + goto eot; + } + + if (s->io_buffer_size > 0) { + /* + * For a cdrom read sector command (s->lba != -1), + * adjust the lba for the next s->io_buffer_size chunk + * and dma the current chunk. + * For a command != read (s->lba == -1), just transfer + * the reply data. + */ + if (s->lba != -1) { + if (s->cd_sector_size == 2352) { + n = 1; + cd_data_to_raw(s->io_buffer, s->lba); + } else { + n = s->io_buffer_size >> 11; + } + s->lba += n; + } + s->packet_transfer_size -= s->io_buffer_size; + if (dma_buf_rw(bm, 1) == 0) + goto eot; + } + + if (s->packet_transfer_size <= 0) { + s->status = READY_STAT; + s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; + ide_set_irq(s); + eot: + bm->status &= ~BM_STATUS_DMAING; + bm->status |= BM_STATUS_INT; + bm->dma_cb = NULL; + bm->ide_if = NULL; + bm->aiocb = NULL; + return; + } + + s->io_buffer_index = 0; + if (s->cd_sector_size == 2352) { + n = 1; + s->io_buffer_size = s->cd_sector_size; + data_offset = 16; + } else { + n = s->packet_transfer_size >> 11; + if (n > (MAX_MULT_SECTORS / 4)) + n = (MAX_MULT_SECTORS / 4); + s->io_buffer_size = n * 2048; + data_offset = 0; + } +#ifdef DEBUG_AIO + printf("aio_read_cd: lba=%u n=%d\n", s->lba, n); +#endif + bm->aiocb = bdrv_aio_read(s->bs, (int64_t)s->lba << 2, + s->io_buffer + data_offset, n * 4, + ide_atapi_cmd_read_dma_cb, bm); + if (!bm->aiocb) { + /* Note: media not present is the most likely case */ + ide_atapi_cmd_error(s, SENSE_NOT_READY, + ASC_MEDIUM_NOT_PRESENT); + goto eot; + } +} + +/* start a CD-CDROM read command with DMA */ +/* XXX: test if DMA is available */ +static void ide_atapi_cmd_read_dma(IDEState *s, int lba, int nb_sectors, + int sector_size) +{ + s->lba = lba; + s->packet_transfer_size = nb_sectors * sector_size; + s->io_buffer_index = 0; + s->io_buffer_size = 0; + s->cd_sector_size = sector_size; + + /* XXX: check if BUSY_STAT should be set */ + s->status = READY_STAT | DRQ_STAT | BUSY_STAT; + ide_dma_start(s, ide_atapi_cmd_read_dma_cb); +} + +static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors, + int sector_size) +{ +#ifdef DEBUG_IDE_ATAPI + printf("read %s: LBA=%d nb_sectors=%d\n", s->atapi_dma ? "dma" : "pio", + lba, nb_sectors); +#endif + if (s->atapi_dma) { + ide_atapi_cmd_read_dma(s, lba, nb_sectors, sector_size); + } else { + ide_atapi_cmd_read_pio(s, lba, nb_sectors, sector_size); + } +} + +static void ide_atapi_cmd(IDEState *s) +{ + const uint8_t *packet; + uint8_t *buf; + int max_len; + + packet = s->io_buffer; + buf = s->io_buffer; +#ifdef DEBUG_IDE_ATAPI + { + int i; + printf("ATAPI limit=0x%x packet:", s->lcyl | (s->hcyl << 8)); + for(i = 0; i < ATAPI_PACKET_SIZE; i++) { + printf(" %02x", packet[i]); + } + printf("\n"); + } +#endif + switch(s->io_buffer[0]) { + case GPCMD_TEST_UNIT_READY: + if (bdrv_is_inserted(s->bs)) { + ide_atapi_cmd_ok(s); + } else { + ide_atapi_cmd_error(s, SENSE_NOT_READY, + ASC_MEDIUM_NOT_PRESENT); + } + break; + case GPCMD_MODE_SENSE_10: + { + int action, code; + max_len = ube16_to_cpu(packet + 7); + action = packet[2] >> 6; + code = packet[2] & 0x3f; + switch(action) { + case 0: /* current values */ + switch(code) { + case 0x01: /* error recovery */ + cpu_to_ube16(&buf[0], 16 + 6); + buf[2] = 0x70; + buf[3] = 0; + buf[4] = 0; + buf[5] = 0; + buf[6] = 0; + buf[7] = 0; + + buf[8] = 0x01; + buf[9] = 0x06; + buf[10] = 0x00; + buf[11] = 0x05; + buf[12] = 0x00; + buf[13] = 0x00; + buf[14] = 0x00; + buf[15] = 0x00; + ide_atapi_cmd_reply(s, 16, max_len); + break; + case 0x2a: + cpu_to_ube16(&buf[0], 28 + 6); + buf[2] = 0x70; + buf[3] = 0; + buf[4] = 0; + buf[5] = 0; + buf[6] = 0; + buf[7] = 0; + + buf[8] = 0x2a; + buf[9] = 0x12; + buf[10] = 0x00; + buf[11] = 0x00; + + buf[12] = 0x70; + buf[13] = 3 << 5; + buf[14] = (1 << 0) | (1 << 3) | (1 << 5); + if (bdrv_is_locked(s->bs)) + buf[6] |= 1 << 1; + buf[15] = 0x00; + cpu_to_ube16(&buf[16], 706); + buf[18] = 0; + buf[19] = 2; + cpu_to_ube16(&buf[20], 512); + cpu_to_ube16(&buf[22], 706); + buf[24] = 0; + buf[25] = 0; + buf[26] = 0; + buf[27] = 0; + ide_atapi_cmd_reply(s, 28, max_len); + break; + default: + goto error_cmd; + } + break; + case 1: /* changeable values */ + goto error_cmd; + case 2: /* default values */ + goto error_cmd; + default: + case 3: /* saved values */ + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, + ASC_SAVING_PARAMETERS_NOT_SUPPORTED); + break; + } + } + break; + case GPCMD_REQUEST_SENSE: + max_len = packet[4]; + memset(buf, 0, 18); + buf[0] = 0x70 | (1 << 7); + buf[2] = s->sense_key; + buf[7] = 10; + buf[12] = s->asc; + ide_atapi_cmd_reply(s, 18, max_len); + break; + case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL: + if (bdrv_is_inserted(s->bs)) { + bdrv_set_locked(s->bs, packet[4] & 1); + ide_atapi_cmd_ok(s); + } else { + ide_atapi_cmd_error(s, SENSE_NOT_READY, + ASC_MEDIUM_NOT_PRESENT); + } + break; + case GPCMD_READ_10: + case GPCMD_READ_12: + { + int nb_sectors, lba; + + if (packet[0] == GPCMD_READ_10) + nb_sectors = ube16_to_cpu(packet + 7); + else + nb_sectors = ube32_to_cpu(packet + 6); + lba = ube32_to_cpu(packet + 2); + if (nb_sectors == 0) { + ide_atapi_cmd_ok(s); + break; + } + ide_atapi_cmd_read(s, lba, nb_sectors, 2048); + } + break; + case GPCMD_READ_CD: + { + int nb_sectors, lba, transfer_request; + + nb_sectors = (packet[6] << 16) | (packet[7] << 8) | packet[8]; + lba = ube32_to_cpu(packet + 2); + if (nb_sectors == 0) { + ide_atapi_cmd_ok(s); + break; + } + transfer_request = packet[9]; + switch(transfer_request & 0xf8) { + case 0x00: + /* nothing */ + ide_atapi_cmd_ok(s); + break; + case 0x10: + /* normal read */ + ide_atapi_cmd_read(s, lba, nb_sectors, 2048); + break; + case 0xf8: + /* read all data */ + ide_atapi_cmd_read(s, lba, nb_sectors, 2352); + break; + default: + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, + ASC_INV_FIELD_IN_CMD_PACKET); + break; + } + } + break; + case GPCMD_SEEK: + { + int lba; + int64_t total_sectors; + + bdrv_get_geometry(s->bs, &total_sectors); + total_sectors >>= 2; + if (total_sectors <= 0) { + ide_atapi_cmd_error(s, SENSE_NOT_READY, + ASC_MEDIUM_NOT_PRESENT); + break; + } + lba = ube32_to_cpu(packet + 2); + if (lba >= total_sectors) { + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, + ASC_LOGICAL_BLOCK_OOR); + break; + } + ide_atapi_cmd_ok(s); + } + break; + case GPCMD_START_STOP_UNIT: + { + int start, eject; + start = packet[4] & 1; + eject = (packet[4] >> 1) & 1; + + if (eject && !start) { + /* eject the disk */ + bdrv_eject(s->bs, 1); + } else if (eject && start) { + /* close the tray */ + bdrv_eject(s->bs, 0); + } + ide_atapi_cmd_ok(s); + } + break; + case GPCMD_MECHANISM_STATUS: + { + max_len = ube16_to_cpu(packet + 8); + cpu_to_ube16(buf, 0); + /* no current LBA */ + buf[2] = 0; + buf[3] = 0; + buf[4] = 0; + buf[5] = 1; + cpu_to_ube16(buf + 6, 0); + ide_atapi_cmd_reply(s, 8, max_len); + } + break; + case GPCMD_READ_TOC_PMA_ATIP: + { + int format, msf, start_track, len; + int64_t total_sectors; + + bdrv_get_geometry(s->bs, &total_sectors); + total_sectors >>= 2; + if (total_sectors <= 0) { + ide_atapi_cmd_error(s, SENSE_NOT_READY, + ASC_MEDIUM_NOT_PRESENT); + break; + } + max_len = ube16_to_cpu(packet + 7); + format = packet[9] >> 6; + msf = (packet[1] >> 1) & 1; + start_track = packet[6]; + switch(format) { + case 0: + emu_printf("CDROM ?TOC?\n"); + len = -1;//cdrom_read_toc(total_sectors, buf, msf, start_track); + if (len < 0) + goto error_cmd; + ide_atapi_cmd_reply(s, len, max_len); + break; + case 1: + /* multi session : only a single session defined */ + memset(buf, 0, 12); + buf[1] = 0x0a; + buf[2] = 0x01; + buf[3] = 0x01; + ide_atapi_cmd_reply(s, 12, max_len); + break; + case 2: + emu_printf("CDROM ?TOC?\n"); + len = -1;// + // len = cdrom_read_toc_raw(total_sectors, buf, msf, start_track); + if (len < 0) + goto error_cmd; + ide_atapi_cmd_reply(s, len, max_len); + break; + default: + error_cmd: + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, + ASC_INV_FIELD_IN_CMD_PACKET); + break; + } + } + break; + case GPCMD_READ_CDVD_CAPACITY: + { + int64_t total_sectors; + + bdrv_get_geometry(s->bs, &total_sectors); + total_sectors >>= 2; + if (total_sectors <= 0) { + ide_atapi_cmd_error(s, SENSE_NOT_READY, + ASC_MEDIUM_NOT_PRESENT); + break; + } + /* NOTE: it is really the number of sectors minus 1 */ + cpu_to_ube32(buf, total_sectors - 1); + cpu_to_ube32(buf + 4, 2048); + ide_atapi_cmd_reply(s, 8, 8); + } + break; + case GPCMD_INQUIRY: + max_len = packet[4]; + buf[0] = 0x05; /* CD-ROM */ + buf[1] = 0x80; /* removable */ + buf[2] = 0x00; /* ISO */ + buf[3] = 0x21; /* ATAPI-2 (XXX: put ATAPI-4 ?) */ + buf[4] = 31; /* additionnal length */ + buf[5] = 0; /* reserved */ + buf[6] = 0; /* reserved */ + buf[7] = 0; /* reserved */ + padstr8(buf + 8, 8, "QEMU"); + padstr8(buf + 16, 16, "QEMU CD-ROM"); + padstr8(buf + 32, 4, QEMU_VERSION); + ide_atapi_cmd_reply(s, 36, max_len); + break; + default: + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, + ASC_ILLEGAL_OPCODE); + break; + } +} + +/* called when the inserted state of the media has changed */ +static void cdrom_change_cb(void *opaque) +{ + IDEState* s = (IDEState*)opaque; + int64_t nb_sectors; + + /* XXX: send interrupt too */ + bdrv_get_geometry(s->bs, &nb_sectors); + s->nb_sectors = nb_sectors; +} + +static void ide_cmd_lba48_transform(IDEState *s, int lba48) +{ + s->lba48 = lba48; + + /* handle the 'magic' 0 nsector count conversion here. to avoid + * fiddling with the rest of the read logic, we just store the + * full sector count in ->nsector and ignore ->hob_nsector from now + */ + if (!s->lba48) { + if (!s->nsector) + s->nsector = 256; + } else { + if (!s->nsector && !s->hob_nsector) + s->nsector = 65536; + else { + int lo = s->nsector; + int hi = s->hob_nsector; + + s->nsector = (hi << 8) | lo; + } + } +} + +static void ide_clear_hob(IDEState *ide_if) +{ + /* any write clears HOB high bit of device control register */ + ide_if[0].select &= ~(1 << 7); + ide_if[1].select &= ~(1 << 7); +} + +static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) +{ + IDEState *ide_if =(IDEState*)opaque; + IDEState *s; + int unit, n; + int lba48 = 0; + +#ifdef DEBUG_IDE + printf("IDE: write addr=0x%x val=0x%02x\n", addr, val); +#endif + + addr &= 7; + switch(addr) { + case 0: + break; + case 1: + ide_clear_hob(ide_if); + /* NOTE: data is written to the two drives */ + ide_if[0].hob_feature = ide_if[0].feature; + ide_if[1].hob_feature = ide_if[1].feature; + ide_if[0].feature = val; + ide_if[1].feature = val; + break; + case 2: + ide_clear_hob(ide_if); + ide_if[0].hob_nsector = ide_if[0].nsector; + ide_if[1].hob_nsector = ide_if[1].nsector; + ide_if[0].nsector = val; + ide_if[1].nsector = val; + break; + case 3: + ide_clear_hob(ide_if); + ide_if[0].hob_sector = ide_if[0].sector; + ide_if[1].hob_sector = ide_if[1].sector; + ide_if[0].sector = val; + ide_if[1].sector = val; + break; + case 4: + ide_clear_hob(ide_if); + ide_if[0].hob_lcyl = ide_if[0].lcyl; + ide_if[1].hob_lcyl = ide_if[1].lcyl; + ide_if[0].lcyl = val; + ide_if[1].lcyl = val; + break; + case 5: + ide_clear_hob(ide_if); + ide_if[0].hob_hcyl = ide_if[0].hcyl; + ide_if[1].hob_hcyl = ide_if[1].hcyl; + ide_if[0].hcyl = val; + ide_if[1].hcyl = val; + break; + case 6: + /* FIXME: HOB readback uses bit 7 */ + ide_if[0].select = (val & ~0x10) | 0xa0; + ide_if[1].select = (val | 0x10) | 0xa0; + /* select drive */ + unit = (val >> 4) & 1; + s = ide_if + unit; + ide_if->cur_drive = s; + break; + default: + case 7: + /* command */ +#if defined(DEBUG_IDE) + printf("ide: CMD=%02x\n", val); +#endif + s = ide_if->cur_drive; + /* ignore commands to non existant slave */ + if (s != ide_if && !s->bs) + break; + + switch(val) { + case WIN_IDENTIFY: + if (s->bs && !s->is_cdrom) { + ide_identify(s); + s->status = READY_STAT | SEEK_STAT; + ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop); + } else { + if (s->is_cdrom) { + ide_set_signature(s); + } + ide_abort_command(s); + } + ide_set_irq(s); + break; + case WIN_SPECIFY: + case WIN_RECAL: + s->error = 0; + s->status = READY_STAT | SEEK_STAT; + ide_set_irq(s); + break; + case WIN_SETMULT: + if (s->nsector > MAX_MULT_SECTORS || + s->nsector == 0 || + (s->nsector & (s->nsector - 1)) != 0) { + ide_abort_command(s); + } else { + s->mult_sectors = s->nsector; + s->status = READY_STAT; + } + ide_set_irq(s); + break; + case WIN_VERIFY_EXT: + lba48 = 1; + case WIN_VERIFY: + case WIN_VERIFY_ONCE: + /* do sector number check ? */ + ide_cmd_lba48_transform(s, lba48); + s->status = READY_STAT; + ide_set_irq(s); + break; + case WIN_READ_EXT: + lba48 = 1; + case WIN_READ: + case WIN_READ_ONCE: + if (!s->bs) + goto abort_cmd; + ide_cmd_lba48_transform(s, lba48); + s->req_nb_sectors = 1; + ide_sector_read(s); + break; + case WIN_WRITE_EXT: + lba48 = 1; + case WIN_WRITE: + case WIN_WRITE_ONCE: + ide_cmd_lba48_transform(s, lba48); + s->error = 0; + s->status = SEEK_STAT | READY_STAT; + s->req_nb_sectors = 1; + ide_transfer_start(s, s->io_buffer, 512, ide_sector_write); + break; + case WIN_MULTREAD_EXT: + lba48 = 1; + case WIN_MULTREAD: + if (!s->mult_sectors) + goto abort_cmd; + ide_cmd_lba48_transform(s, lba48); + s->req_nb_sectors = s->mult_sectors; + ide_sector_read(s); + break; + case WIN_MULTWRITE_EXT: + lba48 = 1; + case WIN_MULTWRITE: + if (!s->mult_sectors) + goto abort_cmd; + ide_cmd_lba48_transform(s, lba48); + s->error = 0; + s->status = SEEK_STAT | READY_STAT; + s->req_nb_sectors = s->mult_sectors; + n = s->nsector; + if (n > s->req_nb_sectors) + n = s->req_nb_sectors; + ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_write); + break; + case WIN_READDMA_EXT: + lba48 = 1; + case WIN_READDMA: + case WIN_READDMA_ONCE: + if (!s->bs) + goto abort_cmd; + ide_cmd_lba48_transform(s, lba48); + ide_sector_read_dma(s); + break; + case WIN_WRITEDMA_EXT: + lba48 = 1; + case WIN_WRITEDMA: + case WIN_WRITEDMA_ONCE: + if (!s->bs) + goto abort_cmd; + ide_cmd_lba48_transform(s, lba48); + ide_sector_write_dma(s); + break; + case WIN_READ_NATIVE_MAX_EXT: + lba48 = 1; + case WIN_READ_NATIVE_MAX: + ide_cmd_lba48_transform(s, lba48); + ide_set_sector(s, s->nb_sectors - 1); + s->status = READY_STAT; + ide_set_irq(s); + break; + case WIN_CHECKPOWERMODE1: + s->nsector = 0xff; /* device active or idle */ + s->status = READY_STAT; + ide_set_irq(s); + break; + case WIN_SETFEATURES: + if (!s->bs) + goto abort_cmd; + /* XXX: valid for CDROM ? */ + switch(s->feature) { + case 0x02: /* write cache enable */ + case 0x82: /* write cache disable */ + case 0xaa: /* read look-ahead enable */ + case 0x55: /* read look-ahead disable */ + s->status = READY_STAT | SEEK_STAT; + ide_set_irq(s); + break; + case 0x03: { /* set transfer mode */ + uint8_t val = s->nsector & 0x07; + + switch (s->nsector >> 3) { + case 0x00: /* pio default */ + case 0x01: /* pio mode */ + put_le16(s->identify_data + 63,0x07); + put_le16(s->identify_data + 88,0x3f); + break; + case 0x04: /* mdma mode */ + put_le16(s->identify_data + 63,0x07 | (1 << (val + 8))); + put_le16(s->identify_data + 88,0x3f); + break; + case 0x08: /* udma mode */ + put_le16(s->identify_data + 63,0x07); + put_le16(s->identify_data + 88,0x3f | (1 << (val + 8))); + break; + default: + goto abort_cmd; + } + s->status = READY_STAT | SEEK_STAT; + ide_set_irq(s); + break; + } + default: + goto abort_cmd; + } + break; + case WIN_FLUSH_CACHE: + case WIN_FLUSH_CACHE_EXT: + if (s->bs) + bdrv_flush(s->bs); + s->status = READY_STAT; + ide_set_irq(s); + break; + case WIN_STANDBYNOW1: + case WIN_IDLEIMMEDIATE: + s->status = READY_STAT; + ide_set_irq(s); + break; + /* ATAPI commands */ + case WIN_PIDENTIFY: + if (s->is_cdrom) { + ide_atapi_identify(s); + s->status = READY_STAT | SEEK_STAT; + ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop); + } else { + ide_abort_command(s); + } + ide_set_irq(s); + break; + case WIN_DIAGNOSE: + ide_set_signature(s); + s->status = 0x00; /* NOTE: READY is _not_ set */ + s->error = 0x01; + break; + case WIN_SRST: + if (!s->is_cdrom) + goto abort_cmd; + ide_set_signature(s); + s->status = 0x00; /* NOTE: READY is _not_ set */ + s->error = 0x01; + break; + case WIN_PACKETCMD: + if (!s->is_cdrom) + goto abort_cmd; + /* overlapping commands not supported */ + if (s->feature & 0x02) + goto abort_cmd; + s->atapi_dma = s->feature & 1; + s->nsector = 1; + ide_transfer_start(s, s->io_buffer, ATAPI_PACKET_SIZE, + ide_atapi_cmd); + break; + default: + abort_cmd: + ide_abort_command(s); + ide_set_irq(s); + break; + } + } +} + +static uint32_t ide_ioport_read(void *opaque, uint32_t addr1) +{ + IDEState *ide_if = (IDEState*)opaque; + IDEState *s = (IDEState*)ide_if->cur_drive; + uint32_t addr; + int ret, hob; + + addr = addr1 & 7; + /* FIXME: HOB readback uses bit 7, but it's always set right now */ + //hob = s->select & (1 << 7); + hob = 0; + switch(addr) { + case 0: + ret = 0xff; + break; + case 1: + if (!ide_if[0].bs && !ide_if[1].bs) + ret = 0; + else if (!hob) + ret = s->error; + else + ret = s->hob_feature; + break; + case 2: + if (!ide_if[0].bs && !ide_if[1].bs) + ret = 0; + else if (!hob) + ret = s->nsector & 0xff; + else + ret = s->hob_nsector; + break; + case 3: + if (!ide_if[0].bs && !ide_if[1].bs) + ret = 0; + else if (!hob) + ret = s->sector; + else + ret = s->hob_sector; + break; + case 4: + if (!ide_if[0].bs && !ide_if[1].bs) + ret = 0; + else if (!hob) + ret = s->lcyl; + else + ret = s->hob_lcyl; + break; + case 5: + if (!ide_if[0].bs && !ide_if[1].bs) + ret = 0; + else if (!hob) + ret = s->hcyl; + else + ret = s->hob_hcyl; + break; + case 6: + if (!ide_if[0].bs && !ide_if[1].bs) + ret = 0; + else + ret = s->select; + break; + default: + case 7: + if ((!ide_if[0].bs && !ide_if[1].bs) || + (s != ide_if && !s->bs)) + ret = 0; + else + ret = s->status; + s->set_irq(s->irq_opaque, s->irq, 0); + break; + } +#ifdef DEBUG_IDE + printf("ide: read addr=0x%x val=%02x\n", addr1, ret); +#endif + return ret; +} + +static uint32_t ide_status_read(void *opaque, uint32_t addr) +{ + IDEState *ide_if =(IDEState*) opaque; + IDEState *s = (IDEState*)ide_if->cur_drive; + int ret; + + if ((!ide_if[0].bs && !ide_if[1].bs) || + (s != ide_if && !s->bs)) + ret = 0; + else + ret = s->status; +#ifdef DEBUG_IDE + printf("ide: read status addr=0x%x val=%02x\n", addr, ret); +#endif + return ret; +} + +static void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val) +{ + IDEState *ide_if = (IDEState*)opaque; + IDEState *s; + int i; + +#ifdef DEBUG_IDE + printf("ide: write control addr=0x%x val=%02x\n", addr, val); +#endif + /* common for both drives */ + if (!(ide_if[0].cmd & IDE_CMD_RESET) && + (val & IDE_CMD_RESET)) { + /* reset low to high */ + for(i = 0;i < 2; i++) { + s = &ide_if[i]; + s->status = BUSY_STAT | SEEK_STAT; + s->error = 0x01; + } + } else if ((ide_if[0].cmd & IDE_CMD_RESET) && + !(val & IDE_CMD_RESET)) { + /* high to low */ + for(i = 0;i < 2; i++) { + s = &ide_if[i]; + if (s->is_cdrom) + s->status = 0x00; /* NOTE: READY is _not_ set */ + else + s->status = READY_STAT | SEEK_STAT; + ide_set_signature(s); + } + } + + ide_if[0].cmd = val; + ide_if[1].cmd = val; +} + +static void ide_data_writew(void *opaque, uint32_t addr, uint32_t val) +{ + IDEState *s = ((IDEState *)opaque)->cur_drive; + uint8_t *p; + + p = s->data_ptr; + *(uint16_t *)p = le16_to_cpu(val); + p += 2; + s->data_ptr = p; + if (p >= s->data_end) + s->end_transfer_func(s); +} + +static uint32_t ide_data_readw(void *opaque, uint32_t addr) +{ + IDEState *s = ((IDEState *)opaque)->cur_drive; + uint8_t *p; + int ret; + p = s->data_ptr; + ret = cpu_to_le16(*(uint16_t *)p); + p += 2; + s->data_ptr = p; + if (p >= s->data_end) + s->end_transfer_func(s); + return ret; +} + +static void ide_data_writel(void *opaque, uint32_t addr, uint32_t val) +{ + IDEState *s = ((IDEState *)opaque)->cur_drive; + uint8_t *p; + + p = s->data_ptr; + *(uint32_t *)p = le32_to_cpu(val); + p += 4; + s->data_ptr = p; + if (p >= s->data_end) + s->end_transfer_func(s); +} + +static uint32_t ide_data_readl(void *opaque, uint32_t addr) +{ + IDEState *s = ((IDEState *)opaque)->cur_drive; + uint8_t *p; + int ret; + + p = s->data_ptr; + ret = cpu_to_le32(*(uint32_t *)p); + p += 4; + s->data_ptr = p; + if (p >= s->data_end) + s->end_transfer_func(s); + return ret; +} + +static void ide_dummy_transfer_stop(IDEState *s) +{ + s->data_ptr = s->io_buffer; + s->data_end = s->io_buffer; + s->io_buffer[0] = 0xff; + s->io_buffer[1] = 0xff; + s->io_buffer[2] = 0xff; + s->io_buffer[3] = 0xff; +} + +static void ide_reset(IDEState *s) +{ + s->mult_sectors = MAX_MULT_SECTORS; + s->cur_drive = s; + s->select = 0xa0; + s->status = READY_STAT; + ide_set_signature(s); + /* init the transfer handler so that 0xffff is returned on data + accesses */ + s->end_transfer_func = ide_dummy_transfer_stop; + ide_dummy_transfer_stop(s); +} + +#pragma pack(1) +struct partition { + uint8_t boot_ind; /* 0x80 - active */ + uint8_t head; /* starting head */ + uint8_t sector; /* starting sector */ + uint8_t cyl; /* starting cylinder */ + uint8_t sys_ind; /* What partition type */ + uint8_t end_head; /* end head */ + uint8_t end_sector; /* end sector */ + uint8_t end_cyl; /* end cylinder */ + uint32_t start_sect; /* starting sector counting from 0 */ + uint32_t nr_sects; /* nr of sectors in partition */ +} ; + +/* try to guess the disk logical geometry from the MSDOS partition table. Return 0 if OK, -1 if could not guess */ +static int guess_disk_lchs(IDEState *s, + int *pcylinders, int *pheads, int *psectors) +{ + uint8_t buf[512]; + int ret, i, heads, sectors, cylinders; + struct partition *p; + uint32_t nr_sects; + + ret = bdrv_read(s->bs, 0, buf, 1); + if (ret < 0) + return -1; + /* test msdos magic */ + if (buf[510] != 0x55 || buf[511] != 0xaa) + return -1; + for(i = 0; i < 4; i++) { + p = ((struct partition *)(buf + 0x1be)) + i; + nr_sects = le32_to_cpu(p->nr_sects); + if (nr_sects && p->end_head) { + /* We make the assumption that the partition terminates on + a cylinder boundary */ + heads = p->end_head + 1; + sectors = p->end_sector & 63; + if (sectors == 0) + continue; + cylinders = s->nb_sectors / (heads * sectors); + if (cylinders < 1 || cylinders > 16383) + continue; + *pheads = heads; + *psectors = sectors; + *pcylinders = cylinders; +#if 0 + printf("guessed geometry: LCHS=%d %d %d\n", + cylinders, heads, sectors); +#endif + return 0; + } + } + return -1; +} + +static void ide_init2(IDEState *ide_state, + BlockDriverState *hd0, BlockDriverState *hd1, + SetIRQFunc *set_irq, void *irq_opaque, int irq) +{ + IDEState *s; + static int drive_serial = 1; + int i, cylinders, heads, secs, translation, lba_detected = 0; + int64_t nb_sectors; + + for(i = 0; i < 2; i++) { + s = ide_state + i; + if (i == 0) + s->bs = hd0; + else + s->bs = hd1; + if (s->bs) + { + bdrv_get_geometry(s->bs, &nb_sectors); + s->nb_sectors = nb_sectors; + /* if a geometry hint is available, use it */ + bdrv_get_geometry_hint(s->bs, &cylinders, &heads, &secs); + translation = bdrv_get_translation_hint(s->bs); + if (cylinders != 0) { + s->cylinders = cylinders; + s->heads = heads; + s->sectors = secs; + } + else + { + if (guess_disk_lchs(s, &cylinders, &heads, &secs) == 0) + { + if (heads > 16) { + /* if heads > 16, it means that a BIOS LBA + translation was active, so the default + hardware geometry is OK */ + lba_detected = 1; + goto default_geometry; + } + else + { + s->cylinders = cylinders; + s->heads = heads; + s->sectors = secs; + /* disable any translation to be in sync with + the logical geometry */ + if (translation == BIOS_ATA_TRANSLATION_AUTO) { + bdrv_set_translation_hint(s->bs, + BIOS_ATA_TRANSLATION_NONE); + } + } + } + else + { +default_geometry: + /* if no geometry, use a standard physical disk geometry */ + cylinders = nb_sectors / (16 * 63); + if (cylinders > 16383) + cylinders = 16383; + else if (cylinders < 2) + cylinders = 2; + s->cylinders = cylinders; + s->heads = 16; + s->sectors = 63; + if ((lba_detected == 1) && (translation == BIOS_ATA_TRANSLATION_AUTO)) + { + if ((s->cylinders * s->heads) <= 131072) + { + bdrv_set_translation_hint(s->bs, + BIOS_ATA_TRANSLATION_LARGE); + } + else + { + bdrv_set_translation_hint(s->bs, + BIOS_ATA_TRANSLATION_LBA); + } + } + } + bdrv_set_geometry_hint(s->bs, s->cylinders, s->heads, s->sectors); + } + if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) { + s->is_cdrom = 1; + bdrv_set_change_cb(s->bs, cdrom_change_cb, s); + } + } + s->drive_serial = drive_serial++; + s->set_irq = set_irq; + s->irq_opaque = irq_opaque; + s->irq = irq; + s->sector_write_timer =0;//* qemu_new_timer(vm_clock, + //* ide_sector_write_timer_cb, s); + ide_reset(s); + } +} +#if 0 +static void ide_init_ioport(IDEState *ide_state, int iobase, int iobase2) +{ + register_ioport_write(iobase, 8, 1, ide_ioport_write, ide_state); + register_ioport_read(iobase, 8, 1, ide_ioport_read, ide_state); + if (iobase2) { + register_ioport_read(iobase2, 1, 1, ide_status_read, ide_state); + register_ioport_write(iobase2, 1, 1, ide_cmd_write, ide_state); + } + + /* data ports */ + register_ioport_write(iobase, 2, 2, ide_data_writew, ide_state); + register_ioport_read(iobase, 2, 2, ide_data_readw, ide_state); + register_ioport_write(iobase, 4, 4, ide_data_writel, ide_state); + register_ioport_read(iobase, 4, 4, ide_data_readl, ide_state); +} + +/***********************************************************/ +/* ISA IDE definitions */ + +void isa_ide_init(int iobase, int iobase2, int irq, + BlockDriverState *hd0, BlockDriverState *hd1) +{ + IDEState *ide_state; + + ide_state = qemu_mallocz(sizeof(IDEState) * 2); + if (!ide_state) + return; + + ide_init2(ide_state, hd0, hd1, pic_set_irq_new, isa_pic, irq); + ide_init_ioport(ide_state, iobase, iobase2); +} + +/***********************************************************/ +/* PCI IDE definitions */ + +static void cmd646_update_irq(PCIIDEState *d); + +static void ide_map(PCIDevice *pci_dev, int region_num, + uint32_t addr, uint32_t size, int type) +{ + PCIIDEState *d = (PCIIDEState *)pci_dev; + IDEState *ide_state; + + if (region_num <= 3) { + ide_state = &d->ide_if[(region_num >> 1) * 2]; + if (region_num & 1) { + register_ioport_read(addr + 2, 1, 1, ide_status_read, ide_state); + register_ioport_write(addr + 2, 1, 1, ide_cmd_write, ide_state); + } else { + register_ioport_write(addr, 8, 1, ide_ioport_write, ide_state); + register_ioport_read(addr, 8, 1, ide_ioport_read, ide_state); + + /* data ports */ + register_ioport_write(addr, 2, 2, ide_data_writew, ide_state); + register_ioport_read(addr, 2, 2, ide_data_readw, ide_state); + register_ioport_write(addr, 4, 4, ide_data_writel, ide_state); + register_ioport_read(addr, 4, 4, ide_data_readl, ide_state); + } + } +} + +#endif +static void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb) +{ + BMDMAState *bm = s->bmdma; + if(!bm) + return; + bm->ide_if = s; + bm->dma_cb = dma_cb; + bm->cur_prd_last = 0; + bm->cur_prd_addr = 0; + bm->cur_prd_len = 0; + if (bm->status & BM_STATUS_DMAING) { + bm->dma_cb(bm, 0); + } +} + +#if 0 +static void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val) +{ + BMDMAState *bm =(BMDMAState*) opaque; +#ifdef DEBUG_IDE + printf("%s: 0x%08x\n", __func__, val); +#endif + if (!(val & BM_CMD_START)) { + /* XXX: do it better */ + if (bm->status & BM_STATUS_DMAING) { + bm->status &= ~BM_STATUS_DMAING; + /* cancel DMA request */ + bm->ide_if = NULL; + bm->dma_cb = NULL; + if (bm->aiocb) { +#ifdef DEBUG_AIO + printf("aio_cancel\n"); +#endif + bdrv_aio_cancel(bm->aiocb); + bm->aiocb = NULL; + } + } + bm->cmd = val & 0x09; + } else { + if (!(bm->status & BM_STATUS_DMAING)) { + bm->status |= BM_STATUS_DMAING; + /* start dma transfer if possible */ + if (bm->dma_cb) + bm->dma_cb(bm, 0); + } + bm->cmd = val & 0x09; + } +} + +static uint32_t bmdma_readb(void *opaque, uint32_t addr) +{ + BMDMAState *bm =(BMDMAState*) opaque; + PCIIDEState *pci_dev; + uint32_t val; + + switch(addr & 3) { + case 0: + val = bm->cmd; + break; + case 1: + pci_dev = bm->pci_dev; + if (pci_dev->type == IDE_TYPE_CMD646) { + val = pci_dev->dev.config[MRDMODE]; + } else { + val = 0xff; + } + break; + case 2: + val = bm->status; + break; + case 3: + pci_dev = bm->pci_dev; + if (pci_dev->type == IDE_TYPE_CMD646) { + if (bm == &pci_dev->bmdma[0]) + val = pci_dev->dev.config[UDIDETCR0]; + else + val = pci_dev->dev.config[UDIDETCR1]; + } else { + val = 0xff; + } + break; + default: + val = 0xff; + break; + } +#ifdef DEBUG_IDE + printf("bmdma: readb 0x%02x : 0x%02x\n", addr, val); +#endif + return val; +} + +static void bmdma_writeb(void *opaque, uint32_t addr, uint32_t val) +{ + BMDMAState *bm = opaque; + PCIIDEState *pci_dev; +#ifdef DEBUG_IDE + printf("bmdma: writeb 0x%02x : 0x%02x\n", addr, val); +#endif + switch(addr & 3) { + case 1: + pci_dev = bm->pci_dev; + if (pci_dev->type == IDE_TYPE_CMD646) { + pci_dev->dev.config[MRDMODE] = + (pci_dev->dev.config[MRDMODE] & ~0x30) | (val & 0x30); + cmd646_update_irq(pci_dev); + } + break; + case 2: + bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 0x06); + break; + case 3: + pci_dev = bm->pci_dev; + if (pci_dev->type == IDE_TYPE_CMD646) { + if (bm == &pci_dev->bmdma[0]) + pci_dev->dev.config[UDIDETCR0] = val; + else + pci_dev->dev.config[UDIDETCR1] = val; + } + break; + } +} + +static uint32_t bmdma_addr_readl(void *opaque, uint32_t addr) +{ + BMDMAState *bm = opaque; + uint32_t val; + val = bm->addr; +#ifdef DEBUG_IDE + printf("%s: 0x%08x\n", __func__, val); +#endif + return val; +} + +static void bmdma_addr_writel(void *opaque, uint32_t addr, uint32_t val) +{ + BMDMAState *bm = opaque; +#ifdef DEBUG_IDE + printf("%s: 0x%08x\n", __func__, val); +#endif + bm->addr = val & ~3; + bm->cur_addr = bm->addr; +} + +static void bmdma_map(PCIDevice *pci_dev, int region_num, + uint32_t addr, uint32_t size, int type) +{ + PCIIDEState *d = (PCIIDEState *)pci_dev; + int i; + + for(i = 0;i < 2; i++) { + BMDMAState *bm = &d->bmdma[i]; + d->ide_if[2 * i].bmdma = bm; + d->ide_if[2 * i + 1].bmdma = bm; + bm->pci_dev = (PCIIDEState *)pci_dev; + + register_ioport_write(addr, 1, 1, bmdma_cmd_writeb, bm); + + register_ioport_write(addr + 1, 3, 1, bmdma_writeb, bm); + register_ioport_read(addr, 4, 1, bmdma_readb, bm); + + register_ioport_write(addr + 4, 4, 4, bmdma_addr_writel, bm); + register_ioport_read(addr + 4, 4, 4, bmdma_addr_readl, bm); + addr += 8; + } +} + + +/* XXX: call it also when the MRDMODE is changed from the PCI config + registers */ +static void cmd646_update_irq(PCIIDEState *d) +{ + int pci_level; + pci_level = ((d->dev.config[MRDMODE] & MRDMODE_INTR_CH0) && + !(d->dev.config[MRDMODE] & MRDMODE_BLK_CH0)) || + ((d->dev.config[MRDMODE] & MRDMODE_INTR_CH1) && + !(d->dev.config[MRDMODE] & MRDMODE_BLK_CH1)); + pci_set_irq((PCIDevice *)d, 0, pci_level); +} + +/* the PCI irq level is the logical OR of the two channels */ +static void cmd646_set_irq(void *opaque, int channel, int level) +{ + PCIIDEState *d = opaque; + int irq_mask; + + irq_mask = MRDMODE_INTR_CH0 << channel; + if (level) + d->dev.config[MRDMODE] |= irq_mask; + else + d->dev.config[MRDMODE] &= ~irq_mask; + cmd646_update_irq(d); +} + +/* CMD646 PCI IDE controller */ +void pci_cmd646_ide_init(PCIBus *bus, BlockDriverState **hd_table, + int secondary_ide_enabled) +{ + PCIIDEState *d; + uint8_t *pci_conf; + int i; + + d = (PCIIDEState *)pci_register_device(bus, "CMD646 IDE", + sizeof(PCIIDEState), + -1, + NULL, NULL); + d->type = IDE_TYPE_CMD646; + pci_conf = d->dev.config; + pci_conf[0x00] = 0x95; // CMD646 + pci_conf[0x01] = 0x10; + pci_conf[0x02] = 0x46; + pci_conf[0x03] = 0x06; + + pci_conf[0x08] = 0x07; // IDE controller revision + pci_conf[0x09] = 0x8f; + + pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE + pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage + pci_conf[0x0e] = 0x00; // header_type + + if (secondary_ide_enabled) { + /* XXX: if not enabled, really disable the seconday IDE controller */ + pci_conf[0x51] = 0x80; /* enable IDE1 */ + } + + pci_register_io_region((PCIDevice *)d, 0, 0x8, + PCI_ADDRESS_SPACE_IO, ide_map); + pci_register_io_region((PCIDevice *)d, 1, 0x4, + PCI_ADDRESS_SPACE_IO, ide_map); + pci_register_io_region((PCIDevice *)d, 2, 0x8, + PCI_ADDRESS_SPACE_IO, ide_map); + pci_register_io_region((PCIDevice *)d, 3, 0x4, + PCI_ADDRESS_SPACE_IO, ide_map); + pci_register_io_region((PCIDevice *)d, 4, 0x10, + PCI_ADDRESS_SPACE_IO, bmdma_map); + + pci_conf[0x3d] = 0x01; // interrupt on pin 1 + + for(i = 0; i < 4; i++) + d->ide_if[i].pci_dev = (PCIDevice *)d; + ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], + cmd646_set_irq, d, 0); + ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], + cmd646_set_irq, d, 1); +} + +static void pci_ide_save(QEMUFile* f, void *opaque) +{ + PCIIDEState *d = opaque; + int i; + + pci_device_save(&d->dev, f); + + for(i = 0; i < 2; i++) { + BMDMAState *bm = &d->bmdma[i]; + qemu_put_8s(f, &bm->cmd); + qemu_put_8s(f, &bm->status); + qemu_put_be32s(f, &bm->addr); + /* XXX: if a transfer is pending, we do not save it yet */ + } + + /* per IDE interface data */ + for(i = 0; i < 2; i++) { + IDEState *s = &d->ide_if[i * 2]; + uint8_t drive1_selected; + qemu_put_8s(f, &s->cmd); + drive1_selected = (s->cur_drive != s); + qemu_put_8s(f, &drive1_selected); + } + + /* per IDE drive data */ + for(i = 0; i < 4; i++) { + IDEState *s = &d->ide_if[i]; + qemu_put_be32s(f, &s->mult_sectors); + qemu_put_be32s(f, &s->identify_set); + if (s->identify_set) { + qemu_put_buffer(f, (const uint8_t *)s->identify_data, 512); + } + qemu_put_8s(f, &s->feature); + qemu_put_8s(f, &s->error); + qemu_put_be32s(f, &s->nsector); + qemu_put_8s(f, &s->sector); + qemu_put_8s(f, &s->lcyl); + qemu_put_8s(f, &s->hcyl); + qemu_put_8s(f, &s->hob_feature); + qemu_put_8s(f, &s->hob_nsector); + qemu_put_8s(f, &s->hob_sector); + qemu_put_8s(f, &s->hob_lcyl); + qemu_put_8s(f, &s->hob_hcyl); + qemu_put_8s(f, &s->select); + qemu_put_8s(f, &s->status); + qemu_put_8s(f, &s->lba48); + + qemu_put_8s(f, &s->sense_key); + qemu_put_8s(f, &s->asc); + /* XXX: if a transfer is pending, we do not save it yet */ + } +} + +static int pci_ide_load(QEMUFile* f, void *opaque, int version_id) +{ + PCIIDEState *d = opaque; + int ret, i; + + if (version_id != 1) + return -EINVAL; + ret = pci_device_load(&d->dev, f); + if (ret < 0) + return ret; + + for(i = 0; i < 2; i++) { + BMDMAState *bm = &d->bmdma[i]; + qemu_get_8s(f, &bm->cmd); + qemu_get_8s(f, &bm->status); + qemu_get_be32s(f, &bm->addr); + /* XXX: if a transfer is pending, we do not save it yet */ + } + + /* per IDE interface data */ + for(i = 0; i < 2; i++) { + IDEState *s = &d->ide_if[i * 2]; + uint8_t drive1_selected; + qemu_get_8s(f, &s->cmd); + qemu_get_8s(f, &drive1_selected); + s->cur_drive = &d->ide_if[i * 2 + (drive1_selected != 0)]; + } + + /* per IDE drive data */ + for(i = 0; i < 4; i++) { + IDEState *s = &d->ide_if[i]; + qemu_get_be32s(f, &s->mult_sectors); + qemu_get_be32s(f, &s->identify_set); + if (s->identify_set) { + qemu_get_buffer(f, (uint8_t *)s->identify_data, 512); + } + qemu_get_8s(f, &s->feature); + qemu_get_8s(f, &s->error); + qemu_get_be32s(f, &s->nsector); + qemu_get_8s(f, &s->sector); + qemu_get_8s(f, &s->lcyl); + qemu_get_8s(f, &s->hcyl); + qemu_get_8s(f, &s->hob_feature); + qemu_get_8s(f, &s->hob_nsector); + qemu_get_8s(f, &s->hob_sector); + qemu_get_8s(f, &s->hob_lcyl); + qemu_get_8s(f, &s->hob_hcyl); + qemu_get_8s(f, &s->select); + qemu_get_8s(f, &s->status); + qemu_get_8s(f, &s->lba48); + + qemu_get_8s(f, &s->sense_key); + qemu_get_8s(f, &s->asc); + /* XXX: if a transfer is pending, we do not save it yet */ + } + return 0; +} + +static void piix3_reset(PCIIDEState *d) +{ + uint8_t *pci_conf = d->dev.config; + + pci_conf[0x04] = 0x00; + pci_conf[0x05] = 0x00; + pci_conf[0x06] = 0x80; /* FBC */ + pci_conf[0x07] = 0x02; // PCI_status_devsel_medium + pci_conf[0x20] = 0x01; /* BMIBA: 20-23h */ +} + +void pci_piix_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn) +{ + PCIIDEState *d; + uint8_t *pci_conf; + + /* register a function 1 of PIIX */ + d = (PCIIDEState *)pci_register_device(bus, "PIIX IDE", + sizeof(PCIIDEState), + devfn, + NULL, NULL); + d->type = IDE_TYPE_PIIX3; + + pci_conf = d->dev.config; + pci_conf[0x00] = 0x86; // Intel + pci_conf[0x01] = 0x80; + pci_conf[0x02] = 0x30; + pci_conf[0x03] = 0x12; + pci_conf[0x08] = 0x02; // Step A1 + pci_conf[0x09] = 0x80; // legacy ATA mode + pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE + pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage + pci_conf[0x0e] = 0x00; // header_type + + piix3_reset(d); + + pci_register_io_region((PCIDevice *)d, 4, 0x10, + PCI_ADDRESS_SPACE_IO, bmdma_map); + + ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], + pic_set_irq_new, isa_pic, 14); + ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], + pic_set_irq_new, isa_pic, 15); + ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6); + ide_init_ioport(&d->ide_if[2], 0x170, 0x376); + + register_savevm("ide", 0, 1, pci_ide_save, pci_ide_load, d); +} + +/* hd_table must contain 4 block drivers */ +/* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */ +void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn) +{ + PCIIDEState *d; + uint8_t *pci_conf; + + /* register a function 1 of PIIX3 */ + d = (PCIIDEState *)pci_register_device(bus, "PIIX3 IDE", + sizeof(PCIIDEState), + devfn, + NULL, NULL); + d->type = IDE_TYPE_PIIX3; + + pci_conf = d->dev.config; + pci_conf[0x00] = 0x86; // Intel + pci_conf[0x01] = 0x80; + pci_conf[0x02] = 0x10; + pci_conf[0x03] = 0x70; + pci_conf[0x09] = 0x80; // legacy ATA mode + pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE + pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage + pci_conf[0x0e] = 0x00; // header_type + + piix3_reset(d); + + pci_register_io_region((PCIDevice *)d, 4, 0x10, + PCI_ADDRESS_SPACE_IO, bmdma_map); + + ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], + pic_set_irq_new, isa_pic, 14); + ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], + pic_set_irq_new, isa_pic, 15); + ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6); + ide_init_ioport(&d->ide_if[2], 0x170, 0x376); + + register_savevm("ide", 0, 1, pci_ide_save, pci_ide_load, d); +} + +/***********************************************************/ +/* MacIO based PowerPC IDE */ + +/* PowerMac IDE memory IO */ +static void pmac_ide_writeb (void *opaque, + target_phys_addr_t addr, uint32_t val) +{ + addr = (addr & 0xFFF) >> 4; + switch (addr) { + case 1 ... 7: + ide_ioport_write(opaque, addr, val); + break; + case 8: + case 22: + ide_cmd_write(opaque, 0, val); + break; + default: + break; + } +} + +static uint32_t pmac_ide_readb (void *opaque,target_phys_addr_t addr) +{ + uint8_t retval; + + addr = (addr & 0xFFF) >> 4; + switch (addr) { + case 1 ... 7: + retval = ide_ioport_read(opaque, addr); + break; + case 8: + case 22: + retval = ide_status_read(opaque, 0); + break; + default: + retval = 0xFF; + break; + } + return retval; +} + +static void pmac_ide_writew (void *opaque, + target_phys_addr_t addr, uint32_t val) +{ + addr = (addr & 0xFFF) >> 4; +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap16(val); +#endif + if (addr == 0) { + ide_data_writew(opaque, 0, val); + } +} + +static uint32_t pmac_ide_readw (void *opaque,target_phys_addr_t addr) +{ + uint16_t retval; + + addr = (addr & 0xFFF) >> 4; + if (addr == 0) { + retval = ide_data_readw(opaque, 0); + } else { + retval = 0xFFFF; + } +#ifdef TARGET_WORDS_BIGENDIAN + retval = bswap16(retval); +#endif + return retval; +} + +static void pmac_ide_writel (void *opaque, + target_phys_addr_t addr, uint32_t val) +{ + addr = (addr & 0xFFF) >> 4; +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap32(val); +#endif + if (addr == 0) { + ide_data_writel(opaque, 0, val); + } +} + +static uint32_t pmac_ide_readl (void *opaque,target_phys_addr_t addr) +{ + uint32_t retval; + + addr = (addr & 0xFFF) >> 4; + if (addr == 0) { + retval = ide_data_readl(opaque, 0); + } else { + retval = 0xFFFFFFFF; + } +#ifdef TARGET_WORDS_BIGENDIAN + retval = bswap32(retval); +#endif + return retval; +} + +static CPUWriteMemoryFunc *pmac_ide_write[] = { + pmac_ide_writeb, + pmac_ide_writew, + pmac_ide_writel, +}; + +static CPUReadMemoryFunc *pmac_ide_read[] = { + pmac_ide_readb, + pmac_ide_readw, + pmac_ide_readl, +}; + +/* hd_table must contain 4 block drivers */ +/* PowerMac uses memory mapped registers, not I/O. Return the memory + I/O index to access the ide. */ +int pmac_ide_init (BlockDriverState **hd_table, + SetIRQFunc *set_irq, void *irq_opaque, int irq) +{ + IDEState *ide_if; + int pmac_ide_memory; + + ide_if = qemu_mallocz(sizeof(IDEState) * 2); + ide_init2(&ide_if[0], hd_table[0], hd_table[1], + set_irq, irq_opaque, irq); + + pmac_ide_memory = cpu_register_io_memory(0, pmac_ide_read, + pmac_ide_write, &ide_if[0]); + return pmac_ide_memory; +} + +#endif +#define ATA_R_DATA (ATA_DEV9_HDD_BASE + 0x00) +#define ATA_R_ERROR (ATA_DEV9_HDD_BASE + 0x02) +#define ATA_R_NSECTOR (ATA_DEV9_HDD_BASE + 0x04) +#define ATA_R_SECTOR (ATA_DEV9_HDD_BASE + 0x06) +#define ATA_R_LCYL (ATA_DEV9_HDD_BASE + 0x08) +#define ATA_R_HCYL (ATA_DEV9_HDD_BASE + 0x0a) +#define ATA_R_SELECT (ATA_DEV9_HDD_BASE + 0x0c) +#define ATA_R_STATUS (ATA_DEV9_HDD_BASE + 0x0e) +#define ATA_R_CONTROL (ATA_DEV9_HDD_BASE + 0x1c) + +//Feature -> error +//command -> status + +//data : 1,2,4 +//command : 1 +IDEState ps2_hdd_data; +BMDMAState ps2_hdd_bmdma_data; +BlockDriverState ps2_hdd_bds_data; + +#define ps2_hdd (&ps2_hdd_data) +void dev9_ata_irq(void *opaque, int irq_num, int level) +{ + emu_printf("ATA INTERRUPT level %d\n",level); + if (level) + { + _DEV9irq(ATA_DEV9_INT,0); + } + else + { + dev9.irqcause&=~ATA_DEV9_INT; + _DEV9irq(0,0); + } + +} +HANDLE HddFile; +void ata_init() +{ + HddFile = ::CreateFile("d:\\ps2_hdd.raw", GENERIC_READ|GENERIC_WRITE, + 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + DWORD dwTemp; + ::DeviceIoControl(HddFile, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &dwTemp, NULL); + LARGE_INTEGER sp; + + //20 GBs + /* + //~7 GB + sp.LowPart=0xEFFFFFFF; + sp.HighPart=1; + */ + sp.QuadPart=(u64)20*1000*1000*1000; + + int64_t rcc=(sp.QuadPart/512/16/63)+1; + + ps2_hdd_bds_data.total_sectors=rcc*16*63; + sp.QuadPart=ps2_hdd_bds_data.total_sectors*512; + + ps2_hdd_bds_data.secs=0; + ps2_hdd_bds_data.heads=0; + ps2_hdd_bds_data.cyls=0; + + emu_printf("Hdd size #.2fGB\n",(double)sp.QuadPart/1024/1024/1024); + + ::SetFilePointerEx(HddFile, sp, 0, FILE_BEGIN); + ::SetEndOfFile(HddFile); + + + ide_init2(ps2_hdd,&ps2_hdd_bds_data,0,dev9_ata_irq,0,0); + ps2_hdd->bmdma=&ps2_hdd_bmdma_data; +} +void ata_term() +{ + ::CloseHandle(HddFile); +} +#define LOG_IRS (sz!=2) +template +u8 CALLBACK ata_read(u32 addr) +{ + //emu_printf("ata_read%d(0x%X)\n",sz*8,addr); + switch(addr) + { + case ATA_R_DATA: + if (sz==1) + { + emu_printf("ATA: Invalid ATA_R_DATA size: register cannot be readen using 8 bit\n"); + } + else if (sz==2) + { + return ide_data_readw(ps2_hdd,0); + } + else + { + return ide_data_readl(ps2_hdd,0); + } + break; + case ATA_R_ERROR: + if (sz!=1 && LOG_IRS) + { + emu_printf("ATA: Invalid ATA_R_ERROR size: register cannot be read w/o using 8 bit\n"); + } + //else + { + return ide_ioport_read(ps2_hdd,1); + } + break; + case ATA_R_NSECTOR: + if (sz!=1 && LOG_IRS) + { + emu_printf("ATA: Invalid ATA_R_NSECTOR size: register cannot be read w/o using 8 bit\n"); + } + //else + { + return ide_ioport_read(ps2_hdd,2); + } + break; + case ATA_R_SECTOR: + if (sz!=1 && LOG_IRS) + { + emu_printf("ATA: Invalid ATA_R_SECTOR size: register cannot be read w/o using 8 bit\n"); + } + //else + { + return ide_ioport_read(ps2_hdd,3); + } + break; + case ATA_R_LCYL: + if (sz!=1 && LOG_IRS) + { + emu_printf("ATA: Invalid ATA_R_LCYL size: register cannot be read w/o using 8 bit\n"); + } + //else + { + return ide_ioport_read(ps2_hdd,4); + } + break; + case ATA_R_HCYL: + if (sz!=1 && LOG_IRS) + { + emu_printf("ATA: Invalid ATA_R_HCYL size: register cannot be read w/o using 8 bit\n"); + } + //else + { + return ide_ioport_read(ps2_hdd,5); + } + break; + case ATA_R_SELECT: + if (sz!=1 && LOG_IRS) + { + emu_printf("ATA: Invalid ATA_R_SELECT size: register cannot be read w/o using 8 bit\n"); + } + //else + { + return ide_ioport_read(ps2_hdd,6); + } + break; + //command -> status + case ATA_R_STATUS: + if (sz!=1 && LOG_IRS) + { + emu_printf("ATA: Invalid ATA_R_STATUS size: register cannot be read w/o using 8 bit\n"); + } + //else + { + return ide_ioport_read(ps2_hdd,7); + } + break; + case ATA_R_CONTROL: + //ide_cmd -> seems to be control + if (sz!=1 && LOG_IRS) + { + emu_printf("ATA: Invalid ATA_R_STATUS size: register cannot be read w/o using 8 bit\n"); + } + //else + { + return ide_status_read(ps2_hdd,0); + } + break; + default: + DEV9_LOG("ATA: Unknown %d bit read @ %X,v=%X\n",sz*8,addr,dev9Ru8(addr)); + if (sz==1) + { + return dev9Ru8(addr); + } + else if (sz==2) + { + return dev9Ru16(addr); + } + else + { + return dev9Ru32(addr); + } + } + + DEV9_LOG("ATA: Unknown %d bit read @ %X,v=%X\n",sz*8,addr,0xdeadb33f); + return 0xdeadb33f; +} +#define LOG_IWS (value&~0xFF) +template +void CALLBACK ata_write(u32 addr, u32 value) +{ + //emu_printf("ata_write%d(0x%X,0x%X)\n",sz*8,addr,value); + switch(addr) + { + case ATA_R_DATA: + if (sz==1) + { + emu_printf("ATA: Invalid ATA_R_DATA size: register cannot be writen using 8 bit\n"); + } + else if (sz==2) + { + ide_data_writew(ps2_hdd,0,value); + } + else + { + ide_data_writel(ps2_hdd,0,value); + } + break; + case ATA_R_ERROR: + if (sz!=1 && LOG_IWS) + { + emu_printf("ATA: Invalid ATA_R_ERROR(feature) size: register cannot be writen w/o using 8 bit\n"); + } + //else + { + ide_ioport_write(ps2_hdd,1,value); + } + break; + case ATA_R_NSECTOR: + if (sz!=1 && LOG_IWS) + { + emu_printf("ATA: Invalid ATA_R_NSECTOR size: register cannot be writen w/o using 8 bit\n"); + } + //else + { + ide_ioport_write(ps2_hdd,2,value); + } + break; + case ATA_R_SECTOR: + if (sz!=1 && LOG_IWS) + { + emu_printf("ATA: Invalid ATA_R_SECTOR size: register cannot be writen w/o using 8 bit\n"); + } + //else + { + ide_ioport_write(ps2_hdd,3,value); + } + break; + case ATA_R_LCYL: + if (sz!=1 && LOG_IWS) + { + emu_printf("ATA: Invalid ATA_R_LCYL size: register cannot be writen w/o using 8 bit\n"); + } + //else + { + ide_ioport_write(ps2_hdd,4,value); + } + break; + case ATA_R_HCYL: + if (sz!=1 && LOG_IWS) + { + emu_printf("ATA: Invalid ATA_R_HCYL size: register cannot be writen w/o using 8 bit\n"); + } + //else + { + ide_ioport_write(ps2_hdd,5,value); + } + break; + case ATA_R_SELECT: + if (sz!=1 && LOG_IWS) + { + emu_printf("ATA: Invalid ATA_R_SELECT size: register cannot be writen w/o using 8 bit\n"); + } + //else + { + ide_ioport_write(ps2_hdd,6,value); + } + break; + //command -> status + case ATA_R_STATUS: + if (sz!=1 && LOG_IWS) + { + emu_printf("ATA: Invalid ATA_R_STATUS(command) size: register cannot be writen w/o using 8 bit\n"); + } + //else + { + ide_ioport_write(ps2_hdd,7,value); + } + break; + case ATA_R_CONTROL: + //ide_cmd -> seems to be control + if (sz!=1 && LOG_IWS) + { + emu_printf("ATA: Invalid ATA_R_CONTROL size: register cannot be writen w/o using 8 bit\n"); + } + // else + { + ide_cmd_write(ps2_hdd,7,value); + } + break; + default: + DEV9_LOG("ATA: Unknown %d bit write @ %X,v=%X\n",addr,value); + if (sz==1) + { + dev9Ru8(addr)=value; + } + else if (sz==2) + { + dev9Ru16(addr)=value; + } + else + { + dev9Ru32(addr)=value; + } + } +} + +u8* pMem_dma; +void do_dma(int size) +{ + BMDMAState* bm=ps2_hdd->bmdma; + bm->addr=0; + bm->cur_prd_addr = 0; + bm->cur_prd_len = size; + + if (!(bm->status & BM_STATUS_DMAING)) + { + bm->status |= BM_STATUS_DMAING; + /* start dma transfer if possible */ + if (bm->dma_cb) + bm->dma_cb(bm, 0); + else + emu_printf("DMA ERROR 2 !!!!@#!@#!@#!#!@#!@#$####################################################^#^\n"); + //bm->status&=~BM_STATUS_DMAING; + } + else + { + emu_printf("DMA ERROR 1 !!!!@#!@#!@#!#!@#!@#$####################################################^#^\n"); + } + + _DEV9irq(ATA_DEV9_INT_DMA,0); +} +void CALLBACK ata_readDMA8Mem(u32 *pMem, int size) +{ + size>>=1; + //#define SPD_R_IF_CTRL (SPD_REGBASE + 0x64) + //#define SPD_IF_ATA_RESET 0x80 + //#define SPD_IF_DMA_ENABLE 0x04 + pMem_dma=(u8*)pMem; + if (dev9Ru8(SPD_R_IF_CTRL)&SPD_IF_DMA_ENABLE) + { + emu_printf("ATA: ata_readDMA8Mem(0x%X,%d) :D\n",pMem,size); + do_dma(size); + //bm->cmd = val & 0x09; + } + else + { + emu_printf("ATA: ata_readDMA8Mem & SPD_IF_DMA_ENABLE disabled\n"); + } +} +void CALLBACK ata_writeDMA8Mem(u32 *pMem, int size) +{ + size>>=1; + pMem_dma=(u8*)pMem; + if (dev9Ru8(SPD_R_IF_CTRL)&SPD_IF_DMA_ENABLE) + { + emu_printf("ATA: ata_writeDMA8Mem(0x%X,%d) :D\n",pMem,size); + do_dma(size); + //bm->cmd = val & 0x09; + } + else + { + emu_printf("ATA: ata_writeDMA8Mem & SPD_IF_DMA_ENABLE disabled\n"); + } +} +void _template_hack_() +{ + ata_read<1>(0); + ata_read<2>(0); + ata_read<4>(0); + + ata_write<1>(0,0); + ata_write<2>(0,0); + ata_write<4>(0,0); +} +#define printme emu_printf("Called stub:" __FUNCTION__ "\n"); + +//memory access +void __cdecl cpu_physical_memory_write(u32 addr,void* ptr,u32 sz) +{ + printf("cpu_physical_memory_write(0x%X,0x%X,%d)\n",addr,ptr,sz); + //return; + memcpy(pMem_dma+addr,ptr,sz); +} +void __cdecl cpu_physical_memory_read(u32 addr,void* ptr,u32 sz) +{ + printf("cpu_physical_memory_read(0x%X,0x%X,%d)\n",addr,ptr,sz); + //return; + memcpy(ptr,pMem_dma+addr,sz); +} + +//IMAGE IO + + +//Async io emulation =) +BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, + int64_t sector_num, uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) +{ + //printme + int ret; + ret = bdrv_read(bs, sector_num, buf, nb_sectors); + cb(opaque, ret); + return 0; +} +BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, + int64_t sector_num, const uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) +{ + //printme + int ret; + ret = bdrv_write(bs, sector_num, buf, nb_sectors); + cb(opaque, ret); + return 0; +} + +void bdrv_flush(BlockDriverState *bs) +{ + printme; + //return; + FlushFileBuffers(HddFile); +} +int bdrv_read(BlockDriverState *bs, int64_t sector_num, + uint8_t *buf, int nb_sectors) +{ + //printme; + //return 0; + if ((sector_num+nb_sectors)>bs->total_sectors) + { + emu_printf("ATA: ERROR , ((sector_num+nb_sectors)>bs->total_sectors)\n"); + return -1; + } + DWORD rv; + LARGE_INTEGER sp; + sp.QuadPart=sector_num*512; + + BOOL sfp=SetFilePointerEx(HddFile,sp,0,FILE_BEGIN); + if (!sfp) + { + emu_printf("SetFilePointerEx file failed\n"); + return -1; + } + + BOOL ss=ReadFile(HddFile,buf,nb_sectors*512,&rv,0); + if (!ss) + { + emu_printf("ReadFile file failed - %d\n",GetLastError()); + return -1; + } + emu_printf("Readed %d bytes from %d:%d@file\n",rv,sp.HighPart,sp.LowPart); + return 0; +} +int bdrv_write(BlockDriverState *bs, int64_t sector_num, + const uint8_t *buf, int nb_sectors) +{ + //printme; + //return 0; + if ((sector_num+nb_sectors)>bs->total_sectors) + { + emu_printf("ATA: ERROR , ((sector_num+nb_sectors)>bs->total_sectors)\n"); + return -1; + } + DWORD rv; + LARGE_INTEGER sp; + sp.QuadPart=sector_num*512; + + BOOL sfp=SetFilePointerEx(HddFile,sp,0,FILE_BEGIN); + if (!sfp) + { + emu_printf("SetFilePointerEx file failed\n"); + return -1; + } + + BOOL ss=WriteFile(HddFile,buf,nb_sectors*512,&rv,0); + if (!ss) + { + emu_printf("WriteFile file failed - %d\n",GetLastError()); + return -1; + } + emu_printf("Writen %d bytes to %d:%d@file\n",rv,sp.HighPart,sp.LowPart); + return 0; +} + +void __cdecl bdrv_eject(struct BlockDriverState *,int) +{ + printme; +} +void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr) +{ + printme; + //return; + *nb_sectors_ptr=bs->total_sectors; +} +void bdrv_set_locked(BlockDriverState *bs, int locked) +{ + printme; + //return; + bs->locked = locked; +} + +int __cdecl bdrv_is_locked(struct BlockDriverState *bs) +{ + printme; + return bs->locked; +} +int __cdecl bdrv_is_inserted(struct BlockDriverState *) +{ + printme; + return 1; +} + +void __cdecl bdrv_set_change_cb(struct BlockDriverState *,void (__cdecl*)(void *),void *) +{ + printme +} +int __cdecl bdrv_get_type_hint(struct BlockDriverState *) +{ + printme; + return BDRV_TYPE_HD; +} +void bdrv_set_geometry_hint(BlockDriverState *bs, + int cyls, int heads, int secs) +{ + printme; + //return; + bs->cyls = cyls; + bs->heads = heads; + bs->secs = secs; +} +void bdrv_set_translation_hint(BlockDriverState *bs, int translation) +{ + printme; + bs->translation = translation; +} +int bdrv_get_translation_hint(BlockDriverState *bs) +{ + printme; + //return 0; + return bs->translation; +} + +void bdrv_get_geometry_hint(BlockDriverState *bs, + int *pcyls, int *pheads, int *psecs) +{ + printme; + //return; + *pcyls = bs->cyls; + *pheads = bs->heads; + *psecs = bs->secs; +} \ No newline at end of file diff --git a/plugins/dev9ghzdrk/Win32/ata.h b/plugins/dev9ghzdrk/Win32/ata.h new file mode 100644 index 000000000..32e2d213c --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/ata.h @@ -0,0 +1,13 @@ +#pragma once +#include "dev9.h" + +void ata_init(); +void ata_term(); + +template +void CALLBACK ata_write(u32 addr, u32 value); +template +u8 CALLBACK ata_read(u32 addr); + +void CALLBACK ata_readDMA8Mem(u32 *pMem, int size); +void CALLBACK ata_writeDMA8Mem(u32 *pMem, int size); \ No newline at end of file diff --git a/plugins/dev9ghzdrk/Win32/icmp.cpp b/plugins/dev9ghzdrk/Win32/icmp.cpp new file mode 100644 index 000000000..18f71d83f --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/icmp.cpp @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include +#include + +#include + +struct pending_icmp_request +{ + char ipaddress[4]; + HANDLE hEvent; + DWORD sTick; + DWORD timeOut; //ttl in ms + DWORD replyBufferSize; + char *replyBuffer; + char *requestData; + void *userdata; + + pending_icmp_request() + { + memset(this,0,sizeof(pending_icmp_request)); + } + + pending_icmp_request(pending_icmp_request&p) + { + memcpy(this,&p,sizeof(p)); + } +}; + +typedef std::list request_list; + +request_list ping_list; + +HANDLE hIP; + +int icmp_init() +{ + hIP = IcmpCreateFile(); + + if(hIP==INVALID_HANDLE_VALUE) + return -1; + + return 0; +} + +void icmp_start(unsigned char *ipaddr, int ttl, void *data, int datasize, void *udata) +{ + pending_icmp_request req; + + req.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); + req.sTick = GetTickCount(); + req.timeOut = ttl; + + req.requestData = (char*)malloc(datasize); + memcpy(req.requestData,data,datasize); + + memcpy(req.ipaddress,ipaddr,4); + + req.replyBufferSize = (sizeof(ICMP_ECHO_REPLY) + sizeof(datasize)); + req.replyBuffer = (char*)malloc(replyBufferSize); + + req.userdata=udata; + + ping_list.push_back(req); + + IcmpSendEcho2(hIP,req.hEvent,NULL,NULL,*(DWORD*)ipaddr,req.requestData,58, + NULL,req.replyBuffer,replyBufferSize,ttl); + +} + +int icmp_check_replies(char *ipaddress, void **udata) +{ + for(request_list::iterator rit=ping_list.begin();rit!=ping_list.end();rit++) + { + if(WaitForSingleObject(rit->hEvent,0)==0) //handle is signaled, reply received. + { + if(IcmpParseReplies(rit->replyBuffer,rit->replyBufferSize)>0) + { + memcpy(ipaddress,rit->ipaddress,4); + + ping_list.remove(rit); + + return 1; //reply received + } + ResetEvent(rit->hEvent); + } + if(GetTickCount() >= (rit->sTick+rit->timeOut)) + { + memcpy(ipaddress,rit->ipaddress,4); + *udata = rit->userdata; + + ping_list.remove(rit); + + return 2; //timeout + } + } + return 0; +} + +void icmp_close() +{ + IcmpCloseHandle(hIP); +} \ No newline at end of file diff --git a/plugins/dev9ghzdrk/Win32/mtfifo.h b/plugins/dev9ghzdrk/Win32/mtfifo.h new file mode 100644 index 000000000..8e20c9720 --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/mtfifo.h @@ -0,0 +1,70 @@ +#pragma once +#include +//a simple, mt-safe fifo template class +template +class mtfifo +{ + struct container + { + container(container* n,T d) + { + next=n; + data=d; + } + container* next;T data; + }; + container* start; + container* end; + + CRITICAL_SECTION cs; +public: + mtfifo() + { + InitializeCriticalSection(&cs); + } + ~mtfifo() + { + //no need to destroy the CS? i cant remember realy .. ;p + } + void put(T data) + { + EnterCriticalSection(&cs); + if (end==0) + { + end=start=new container(0,data); + } + else + { + end=end->next=new container(0,data); + } + LeaveCriticalSection(&cs); + } + //Note, this is partialy mt-safe, the get may fail even if that returned false + bool empty(){ return start==0;} + bool get(T& rvi) + { + container* rv; + EnterCriticalSection(&cs); + if (start==0) + { + rv=0; //error + + + } + else + { + rv=start; + start=rv->next; + if (!start) + end=0; //last item + } + LeaveCriticalSection(&cs); + + if(!rv) + return false; + rvi=rv->data; + delete rv; + + return true; + } +}; \ No newline at end of file diff --git a/plugins/dev9ghzdrk/Win32/net.cpp b/plugins/dev9ghzdrk/Win32/net.cpp new file mode 100644 index 000000000..c7acdad27 --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/net.cpp @@ -0,0 +1,51 @@ +#include "net.h" +#include "Dev9.h" + +//mtfifo rx_fifo; +//mtfifo tx_fifo; + +NetAdapter* nif; +HANDLE rx_thread; + +volatile bool RxRunning=false; +//rx thread +DWORD WINAPI NetRxThread(LPVOID lpThreadParameter) +{ + NetPacket tmp; + while(RxRunning) + { + while(rx_fifo_can_rx() && nif->recv(&tmp)) + { + rx_process(&tmp); + } + + Sleep(10); + } + + return 0; +} + +void tx_put(NetPacket* pkt) +{ + nif->send(pkt); + //pkt must be copied if its not processed by here, since it can be allocated on the callers stack +} +void InitNet(NetAdapter* ad) +{ + nif=ad; + RxRunning=true; + + rx_thread=CreateThread(0,0,NetRxThread,0,CREATE_SUSPENDED,0); + + SetThreadPriority(rx_thread,THREAD_PRIORITY_HIGHEST); + ResumeThread(rx_thread); +} +void TermNet() +{ + RxRunning=false; + emu_printf("Waiting for RX-net thread to terminate.."); + WaitForSingleObject(rx_thread,-1); + emu_printf(".done\n"); + + delete nif; +} \ No newline at end of file diff --git a/plugins/dev9ghzdrk/Win32/net.h b/plugins/dev9ghzdrk/Win32/net.h new file mode 100644 index 000000000..0b18e2ed5 --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/net.h @@ -0,0 +1,29 @@ +#pragma once +#include +#include //uh isnt memcpy @ stdlib ? + +struct NetPacket +{ + NetPacket() {size=0;} + NetPacket(void* ptr,int sz) {size=sz;memcpy(buffer,ptr,sz);} + + int size; + char buffer[2048-sizeof(int)];//1536 is realy needed, just pad up to 2048 bytes :) +}; +/* +extern mtfifo rx_fifo; +extern mtfifo tx_fifo; +*/ + +class NetAdapter +{ +public: + virtual bool blocks()=0; + virtual bool recv(NetPacket* pkt)=0; //gets a packet + virtual bool send(NetPacket* pkt)=0; //sends the packet and deletes it when done + virtual ~NetAdapter(){} +}; + +void tx_put(NetPacket* ptr); +void InitNet(NetAdapter* adapter); +void TermNet(); \ No newline at end of file diff --git a/plugins/dev9ghzdrk/Win32/packet32.h b/plugins/dev9ghzdrk/Win32/packet32.h new file mode 100644 index 000000000..d36b684d6 --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/packet32.h @@ -0,0 +1,450 @@ +/* + * Copyright (c) 1999 - 2003 + * NetGroup, Politecnico di Torino (Italy) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Politecnico di Torino nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** @ingroup packetapi + * @{ + */ + +/** @defgroup packet32h Packet.dll definitions and data structures + * Packet32.h contains the data structures and the definitions used by packet.dll. + * The file is used both by the Win9x and the WinNTx versions of packet.dll, and can be included + * by the applications that use the functions of this library + * @{ + */ + +#ifndef __PACKET32 +#define __PACKET32 + +#include +#include "devioctl.h" +#ifdef HAVE_DAG_API +#include +#endif /* HAVE_DAG_API */ + +// Working modes +#define PACKET_MODE_CAPT 0x0 ///< Capture mode +#define PACKET_MODE_STAT 0x1 ///< Statistical mode +#define PACKET_MODE_MON 0x2 ///< Monitoring mode +#define PACKET_MODE_DUMP 0x10 ///< Dump mode +#define PACKET_MODE_STAT_DUMP MODE_DUMP | MODE_STAT ///< Statistical dump Mode + +// ioctls +#define FILE_DEVICE_PROTOCOL 0x8000 + +#define IOCTL_PROTOCOL_STATISTICS CTL_CODE(FILE_DEVICE_PROTOCOL, 2 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_PROTOCOL_RESET CTL_CODE(FILE_DEVICE_PROTOCOL, 3 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_PROTOCOL_READ CTL_CODE(FILE_DEVICE_PROTOCOL, 4 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_PROTOCOL_WRITE CTL_CODE(FILE_DEVICE_PROTOCOL, 5 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_PROTOCOL_MACNAME CTL_CODE(FILE_DEVICE_PROTOCOL, 6 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_OPEN CTL_CODE(FILE_DEVICE_PROTOCOL, 7 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_CLOSE CTL_CODE(FILE_DEVICE_PROTOCOL, 8 , METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define pBIOCSETBUFFERSIZE 9592 ///< IOCTL code: set kernel buffer size. +#define pBIOCSETF 9030 ///< IOCTL code: set packet filtering program. +#define pBIOCGSTATS 9031 ///< IOCTL code: get the capture stats. +#define pBIOCSRTIMEOUT 7416 ///< IOCTL code: set the read timeout. +#define pBIOCSMODE 7412 ///< IOCTL code: set working mode. +#define pBIOCSWRITEREP 7413 ///< IOCTL code: set number of physical repetions of every packet written by the app. +#define pBIOCSMINTOCOPY 7414 ///< IOCTL code: set minimum amount of data in the kernel buffer that unlocks a read call. +#define pBIOCSETOID 2147483648 ///< IOCTL code: set an OID value. +#define pBIOCQUERYOID 2147483652 ///< IOCTL code: get an OID value. +#define pATTACHPROCESS 7117 ///< IOCTL code: attach a process to the driver. Used in Win9x only. +#define pDETACHPROCESS 7118 ///< IOCTL code: detach a process from the driver. Used in Win9x only. +#define pBIOCSETDUMPFILENAME 9029 ///< IOCTL code: set the name of a the file used by kernel dump mode. +#define pBIOCEVNAME 7415 ///< IOCTL code: get the name of the event that the driver signals when some data is present in the buffer. +#define pBIOCSENDPACKETSNOSYNC 9032 ///< IOCTL code: Send a buffer containing multiple packets to the network, ignoring the timestamps associated with the packets. +#define pBIOCSENDPACKETSSYNC 9033 ///< IOCTL code: Send a buffer containing multiple packets to the network, respecting the timestamps associated with the packets. +#define pBIOCSETDUMPLIMITS 9034 ///< IOCTL code: Set the dump file limits. See the PacketSetDumpLimits() function. +#define pBIOCISDUMPENDED 7411 ///< IOCTL code: Get the status of the kernel dump process. See the PacketIsDumpEnded() function. + +#define pBIOCSTIMEZONE 7471 ///< IOCTL code: set time zone. Used in Win9x only. + + +/// Alignment macro. Defines the alignment size. +#define Packet_ALIGNMENT sizeof(int) +/// Alignment macro. Rounds up to the next even multiple of Packet_ALIGNMENT. +#define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1)) + + +#define NdisMediumNull -1 // Custom linktype: NDIS doesn't provide an equivalent +#define NdisMediumCHDLC -2 // Custom linktype: NDIS doesn't provide an equivalent +#define NdisMediumPPPSerial -3 // Custom linktype: NDIS doesn't provide an equivalent + +/*! + \brief Network type structure. + + This structure is used by the PacketGetNetType() function to return information on the current adapter's type and speed. +*/ +typedef struct NetType +{ + UINT LinkType; ///< The MAC of the current network adapter (see function PacketGetNetType() for more information) + ULONGLONG LinkSpeed; ///< The speed of the network in bits per second +}NetType; + + +//some definitions stolen from libpcap + +#ifndef BPF_MAJOR_VERSION + +/*! + \brief A BPF pseudo-assembly program. + + The program will be injected in the kernel by the PacketSetBPF() function and applied to every incoming packet. +*/ +struct bpf_program +{ + UINT bf_len; ///< Indicates the number of instructions of the program, i.e. the number of struct bpf_insn that will follow. + struct bpf_insn *bf_insns; ///< A pointer to the first instruction of the program. +}; + +/*! + \brief A single BPF pseudo-instruction. + + bpf_insn contains a single instruction for the BPF register-machine. It is used to send a filter program to the driver. +*/ +struct bpf_insn +{ + USHORT code; ///< Instruction type and addressing mode. + UCHAR jt; ///< Jump if true + UCHAR jf; ///< Jump if false + int k; ///< Generic field used for various purposes. +}; + +/*! + \brief Structure that contains a couple of statistics values on the current capture. + + It is used by packet.dll to return statistics about a capture session. +*/ +struct bpf_stat +{ + UINT bs_recv; ///< Number of packets that the driver received from the network adapter + ///< from the beginning of the current capture. This value includes the packets + ///< lost by the driver. + UINT bs_drop; ///< number of packets that the driver lost from the beginning of a capture. + ///< Basically, a packet is lost when the the buffer of the driver is full. + ///< In this situation the packet cannot be stored and the driver rejects it. + UINT ps_ifdrop; ///< drops by interface. XXX not yet supported + UINT bs_capt; ///< number of packets that pass the filter, find place in the kernel buffer and + ///< thus reach the application. +}; + +/*! + \brief Packet header. + + This structure defines the header associated with every packet delivered to the application. +*/ +struct bpf_hdr +{ + struct timeval bh_tstamp; ///< The timestamp associated with the captured packet. + ///< It is stored in a TimeVal structure. + UINT bh_caplen; ///< Length of captured portion. The captured portion can be different + ///< from the original packet, because it is possible (with a proper filter) + ///< to instruct the driver to capture only a portion of the packets. + UINT bh_datalen; ///< Original length of packet + USHORT bh_hdrlen; ///< Length of bpf header (this struct plus alignment padding). In some cases, + ///< a padding could be added between the end of this structure and the packet + ///< data for performance reasons. This filed can be used to retrieve the actual data + ///< of the packet. +}; + +/*! + \brief Dump packet header. + + This structure defines the header associated with the packets in a buffer to be used with PacketSendPackets(). + It is simpler than the bpf_hdr, because it corresponds to the header associated by WinPcap and libpcap to a + packet in a dump file. This makes straightforward sending WinPcap dump files to the network. +*/ +struct dump_bpf_hdr{ + struct timeval ts; ///< Time stamp of the packet + UINT caplen; ///< Length of captured portion. The captured portion can smaller than the + ///< the original packet, because it is possible (with a proper filter) to + ///< instruct the driver to capture only a portion of the packets. + UINT len; ///< Length of the original packet (off wire). +}; + + +#endif + +#define DOSNAMEPREFIX TEXT("Packet_") ///< Prefix added to the adapters device names to create the WinPcap devices +#define MAX_LINK_NAME_LENGTH 64 //< Maximum length of the devices symbolic links +#define NMAX_PACKET 65535 + +/* + * Desired design of maximum size and alignment. + * These are implementation specific. + */ +#define _SS_MAXSIZE 128 // Maximum size. +#define _SS_ALIGNSIZE (sizeof(__int64)) // Desired alignment. + +/* + * Definitions used for sockaddr_storage structure paddings design. + */ +#define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof (short)) +#define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof (short) + _SS_PAD1SIZE \ + + _SS_ALIGNSIZE)) +/* +struct sockaddr_storage { + short ss_family; // Address family. + char __ss_pad1[_SS_PAD1SIZE]; // 6 byte pad, this is to make + // implementation specific pad up to + // alignment field that follows explicit + // in the data structure. + __int64 __ss_align; // Field to force desired structure. + char __ss_pad2[_SS_PAD2SIZE]; // 112 byte pad to achieve desired size; + // _SS_MAXSIZE value minus size of + // ss_family, __ss_pad1, and + // __ss_align fields is 112. +}; +*/ +/*! + \brief Addresses of a network adapter. + + This structure is used by the PacketGetNetInfoEx() function to return the IP addresses associated with + an adapter. +*/ +typedef struct npf_if_addr { + struct sockaddr_storage IPAddress; ///< IP address. + struct sockaddr_storage SubnetMask; ///< Netmask for that address. + struct sockaddr_storage Broadcast; ///< Broadcast address. +}npf_if_addr; + + +#define ADAPTER_NAME_LENGTH 256 + 12 ///< Maximum length for the name of an adapter. The value is the same used by the IP Helper API. +#define ADAPTER_DESC_LENGTH 128 ///< Maximum length for the description of an adapter. The value is the same used by the IP Helper API. +#define MAX_MAC_ADDR_LENGTH 8 ///< Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API. +#define MAX_NETWORK_ADDRESSES 16 ///< Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API. + + +typedef struct WAN_ADAPTER_INT WAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API +typedef WAN_ADAPTER *PWAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API + +#define INFO_FLAG_NDIS_ADAPTER 0 ///< Flag for ADAPTER_INFO: this is a traditional ndis adapter +#define INFO_FLAG_NDISWAN_ADAPTER 1 ///< Flag for ADAPTER_INFO: this is a NdisWan adapter +#define INFO_FLAG_DAG_CARD 2 ///< Flag for ADAPTER_INFO: this is a DAG card +#define INFO_FLAG_DAG_FILE 6 ///< Flag for ADAPTER_INFO: this is a DAG file +#define INFO_FLAG_DONT_EXPORT 8 ///< Flag for ADAPTER_INFO: when this flag is set, the adapter will not be listed or openend by winpcap. This allows to prevent exporting broken network adapters, like for example FireWire ones. + +/*! + \brief Contains comprehensive information about a network adapter. + + This structure is filled with all the accessory information that the user can need about an adapter installed + on his system. +*/ +typedef struct _ADAPTER_INFO +{ + struct _ADAPTER_INFO *Next; ///< Pointer to the next adapter in the list. + CHAR Name[ADAPTER_NAME_LENGTH + 1]; ///< Name of the device representing the adapter. + CHAR Description[ADAPTER_DESC_LENGTH + 1]; ///< Human understandable description of the adapter + UINT MacAddressLen; ///< Length of the link layer address. + UCHAR MacAddress[MAX_MAC_ADDR_LENGTH]; ///< Link layer address. + NetType LinkLayer; ///< Physical characteristics of this adapter. This NetType structure contains the link type and the speed of the adapter. + INT NNetworkAddresses; ///< Number of network layer addresses of this adapter. + npf_if_addr *NetworkAddresses; ///< Pointer to an array of npf_if_addr, each of which specifies a network address of this adapter. + UINT Flags; ///< Adapter's flags. Tell if this adapter must be treated in a different way, using the Netmon API or the dagc API. +} +ADAPTER_INFO, *PADAPTER_INFO; + +/*! + \brief Describes an opened network adapter. + + This structure is the most important for the functioning of packet.dll, but the great part of its fields + should be ignored by the user, since the library offers functions that avoid to cope with low-level parameters +*/ +typedef struct _ADAPTER { + HANDLE hFile; ///< \internal Handle to an open instance of the NPF driver. + CHAR SymbolicLink[MAX_LINK_NAME_LENGTH]; ///< \internal A string containing the name of the network adapter currently opened. + int NumWrites; ///< \internal Number of times a packets written on this adapter will be repeated + ///< on the wire. + HANDLE ReadEvent; ///< A notification event associated with the read calls on the adapter. + ///< It can be passed to standard Win32 functions (like WaitForSingleObject + ///< or WaitForMultipleObjects) to wait until the driver's buffer contains some + ///< data. It is particularly useful in GUI applications that need to wait + ///< concurrently on several events. In Windows NT/2000 the PacketSetMinToCopy() + ///< function can be used to define the minimum amount of data in the kernel buffer + ///< that will cause the event to be signalled. + + UINT ReadTimeOut; ///< \internal The amount of time after which a read on the driver will be released and + ///< ReadEvent will be signaled, also if no packets were captured + CHAR Name[ADAPTER_NAME_LENGTH]; + PWAN_ADAPTER pWanAdapter; + UINT Flags; ///< Adapter's flags. Tell if this adapter must be treated in a different way, using the Netmon API or the dagc API. +#ifdef HAVE_DAG_API + dagc_t *pDagCard; ///< Pointer to the dagc API adapter descriptor for this adapter + PCHAR DagBuffer; ///< Pointer to the buffer with the packets that is received from the DAG card + struct timeval DagReadTimeout; ///< Read timeout. The dagc API requires a timeval structure + unsigned DagFcsLen; ///< Length of the frame check sequence attached to any packet by the card. Obtained from the registry + DWORD DagFastProcess; ///< True if the user requests fast capture processing on this card. Higher level applications can use this value to provide a faster but possibly unprecise capture (for example, libpcap doesn't convert the timestamps). +#endif // HAVE_DAG_API +} ADAPTER, *LPADAPTER; + +/*! + \brief Structure that contains a group of packets coming from the driver. + + This structure defines the header associated with every packet delivered to the application. +*/ +typedef struct _PACKET { + HANDLE hEvent; ///< \deprecated Still present for compatibility with old applications. + OVERLAPPED OverLapped; ///< \deprecated Still present for compatibility with old applications. + PVOID Buffer; ///< Buffer with containing the packets. See the PacketReceivePacket() for + ///< details about the organization of the data in this buffer + UINT Length; ///< Length of the buffer + DWORD ulBytesReceived; ///< Number of valid bytes present in the buffer, i.e. amount of data + ///< received by the last call to PacketReceivePacket() + BOOLEAN bIoComplete; ///< \deprecated Still present for compatibility with old applications. +} PACKET, *LPPACKET; + +/*! + \brief Structure containing an OID request. + + It is used by the PacketRequest() function to send an OID to the interface card driver. + It can be used, for example, to retrieve the status of the error counters on the adapter, its MAC address, + the list of the multicast groups defined on it, and so on. +*/ +struct _PACKET_OID_DATA { + ULONG Oid; ///< OID code. See the Microsoft DDK documentation or the file ntddndis.h + ///< for a complete list of valid codes. + ULONG Length; ///< Length of the data field + UCHAR Data[1]; ///< variable-lenght field that contains the information passed to or received + ///< from the adapter. +}; +typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA; + + +#if _DBG +#define ODS(_x) OutputDebugString(TEXT(_x)) +#define ODSEx(_x, _y) +#else +#ifdef _DEBUG_TO_FILE +/*! + \brief Macro to print a debug string. The behavior differs depending on the debug level +*/ +#define ODS(_x) { \ + FILE *f; \ + f = fopen("winpcap_debug.txt", "a"); \ + fprintf(f, "%s", _x); \ + fclose(f); \ +} +/*! + \brief Macro to print debug data with the printf convention. The behavior differs depending on + the debug level +*/ +#define ODSEx(_x, _y) { \ + FILE *f; \ + f = fopen("winpcap_debug.txt", "a"); \ + fprintf(f, _x, _y); \ + fclose(f); \ +} + + + +LONG PacketDumpRegistryKey(PCHAR KeyName, PCHAR FileName); +#else +#define ODS(_x) +#define ODSEx(_x, _y) +#endif +#endif + +/* We load dinamically the dag library in order link it only when it's present on the system */ +#ifdef HAVE_DAG_API +typedef dagc_t* (*dagc_open_handler)(const char *source, unsigned flags, char *ebuf); ///< prototype used to dynamically load the dag dll +typedef void (*dagc_close_handler)(dagc_t *dagcfd); ///< prototype used to dynamically load the dag dll +typedef int (*dagc_getlinktype_handler)(dagc_t *dagcfd); ///< prototype used to dynamically load the dag dll +typedef int (*dagc_getlinkspeed_handler)(dagc_t *dagcfd); ///< prototype used to dynamically load the dag dll +typedef int (*dagc_setsnaplen_handler)(dagc_t *dagcfd, unsigned snaplen); ///< prototype used to dynamically load the dag dll +typedef unsigned (*dagc_getfcslen_handler)(dagc_t *dagcfd); ///< prototype used to dynamically load the dag dll +typedef int (*dagc_receive_handler)(dagc_t *dagcfd, u_char **buffer, u_int *bufsize); ///< prototype used to dynamically load the dag dll +typedef int (*dagc_stats_handler)(dagc_t *dagcfd, dagc_stats_t *ps); ///< prototype used to dynamically load the dag dll +typedef int (*dagc_wait_handler)(dagc_t *dagcfd, struct timeval *timeout); ///< prototype used to dynamically load the dag dll +typedef int (*dagc_finddevs_handler)(dagc_if_t **alldevsp, char *ebuf); ///< prototype used to dynamically load the dag dll +typedef int (*dagc_freedevs_handler)(dagc_if_t *alldevsp); ///< prototype used to dynamically load the dag dll +#endif // HAVE_DAG_API + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @} + */ + +// The following is used to check the adapter name in PacketOpenAdapterNPF and prevent +// opening of firewire adapters +#define FIREWIRE_SUBSTR L"1394" + +void PacketPopulateAdaptersInfoList(); +PWCHAR SChar2WChar(PCHAR string); +PCHAR WChar2SChar(PWCHAR string); +BOOL PacketGetFileVersion(LPTSTR FileName, PCHAR VersionBuff, UINT VersionBuffLen); +PADAPTER_INFO PacketFindAdInfo(PCHAR AdapterName); +BOOLEAN PacketUpdateAdInfo(PCHAR AdapterName); +BOOLEAN IsFireWire(TCHAR *AdapterDesc); + + +//--------------------------------------------------------------------------- +// EXPORTED FUNCTIONS +//--------------------------------------------------------------------------- + +PCHAR PacketGetVersion(); +PCHAR PacketGetDriverVersion(); +BOOLEAN PacketSetMinToCopy(LPADAPTER AdapterObject,int nbytes); +BOOLEAN PacketSetNumWrites(LPADAPTER AdapterObject,int nwrites); +BOOLEAN PacketSetMode(LPADAPTER AdapterObject,int mode); +BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout); +BOOLEAN PacketSetBpf(LPADAPTER AdapterObject,struct bpf_program *fp); +INT PacketSetSnapLen(LPADAPTER AdapterObject,int snaplen); +BOOLEAN PacketGetStats(LPADAPTER AdapterObject,struct bpf_stat *s); +BOOLEAN PacketGetStatsEx(LPADAPTER AdapterObject,struct bpf_stat *s); +BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim); +BOOLEAN PacketGetNetType (LPADAPTER AdapterObject,NetType *type); +LPADAPTER PacketOpenAdapter(PCHAR AdapterName); +BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET pPacket,BOOLEAN Sync); +INT PacketSendPackets(LPADAPTER AdapterObject,PVOID PacketBuff,ULONG Size, BOOLEAN Sync); +LPPACKET PacketAllocatePacket(void); +VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length); +VOID PacketFreePacket(LPPACKET lpPacket); +BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync); +BOOLEAN PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter); +BOOLEAN PacketGetAdapterNames(PTSTR pStr,PULONG BufferSize); +BOOLEAN PacketGetNetInfoEx(PCHAR AdapterName, npf_if_addr* buffer, PLONG NEntries); +BOOLEAN PacketRequest(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData); +HANDLE PacketGetReadEvent(LPADAPTER AdapterObject); +BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject, void *name, int len); +BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject, UINT maxfilesize, UINT maxnpacks); +BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject, BOOLEAN sync); +BOOL PacketStopDriver(); +VOID PacketCloseAdapter(LPADAPTER lpAdapter); + +#ifdef __cplusplus +} +#endif + +#endif //__PACKET32 diff --git a/plugins/dev9ghzdrk/Win32/pcap_io.h b/plugins/dev9ghzdrk/Win32/pcap_io.h new file mode 100644 index 000000000..c10788220 --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/pcap_io.h @@ -0,0 +1,161 @@ +#pragma once +#include "net.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#pragma pack(push,1) + +typedef struct _ip_address +{ + u_char bytes[4]; +} ip_address; + +typedef struct _mac_address +{ + u_char bytes[6]; +} mac_address; + +typedef struct _ethernet_header +{ + mac_address dst; + mac_address src; + u_short protocol; +} ethernet_header; + +typedef struct _arp_packet +{ + u_short hw_type; + u_short protocol; + u_char h_addr_len; + u_char p_addr_len; + u_short operation; + mac_address h_src; + ip_address p_src; + mac_address h_dst; + ip_address p_dst; +} arp_packet; + +typedef struct _ip_header { + u_char ver_hlen; /* version << 4 | header length >> 2 */ + u_char type; /* type of service */ + u_short len; /* total length */ + u_short id; /* identification */ + u_short offset; /* fragment offset field */ + u_char ttl; /* time to live */ + u_char proto; /* protocol */ + u_short hdr_csum; /* checksum */ + ip_address src; /* source and dest address */ + ip_address dst; +} ip_header; + +/* Internet Control Message Protocol Constants and Packet Format */ + +/* ic_type field */ +#define ICT_ECHORP 0 /* Echo reply */ +#define ICT_DESTUR 3 /* Destination unreachable */ +#define ICT_SRCQ 4 /* Source quench */ +#define ICT_REDIRECT 5 /* Redirect message type */ +#define ICT_ECHORQ 8 /* Echo request */ +#define ICT_TIMEX 11 /* Time exceeded */ +#define ICT_PARAMP 12 /* Parameter Problem */ +#define ICT_TIMERQ 13 /* Timestamp request */ +#define ICT_TIMERP 14 /* Timestamp reply */ +#define ICT_INFORQ 15 /* Information request */ +#define ICT_INFORP 16 /* Information reply */ +#define ICT_MASKRQ 17 /* Mask request */ +#define ICT_MASKRP 18 /* Mask reply */ + +/* ic_code field */ +#define ICC_NETUR 0 /* dest unreachable, net unreachable */ +#define ICC_HOSTUR 1 /* dest unreachable, host unreachable */ +#define ICC_PROTOUR 2 /* dest unreachable, proto unreachable */ +#define ICC_PORTUR 3 /* dest unreachable, port unreachable */ +#define ICC_FNADF 4 /* dest unr, frag needed & don't frag */ +#define ICC_SRCRT 5 /* dest unreachable, src route failed */ + +#define ICC_NETRD 0 /* redirect: net */ +#define ICC_HOSTRD 1 /* redirect: host */ +#define IC_TOSNRD 2 /* redirect: type of service, net */ +#define IC_TOSHRD 3 /* redirect: type of service, host */ + +#define ICC_TIMEX 0 /* time exceeded, ttl */ +#define ICC_FTIMEX 1 /* time exceeded, frag */ + +#define IC_HLEN 8 /* octets */ +#define IC_PADLEN 3 /* pad length (octets) */ + +#define IC_RDTTL 300 /* ttl for redirect routes */ + + +/* ICMP packet format (following the IP header) */ +typedef struct _icmp_header { /* ICMP packet */ + char type; /* type of message (ICT_* above)*/ + char code; /* code (ICC_* above) */ + short csum; /* checksum of ICMP header+data */ + + union { + struct { + int ic1_id:16; /* echo type, a message id */ + int ic1_seq:16;/* echo type, a seq. number */ + } ic1; + ip_address ic2_gw; /* for redirect, gateway */ + struct { + char ic3_ptr;/* pointer, for ICT_PARAMP */ + char ic3_pad[IC_PADLEN]; + } ic3; + int ic4_mbz; /* must be zero */ + } icu; +} icmp_header; + +/*typedef struct _udp_header { + u16 src_port; + u16 dst_port; + u16 len; + u16 csum; +} udp_header;*/ + +typedef struct _full_arp_packet +{ + ethernet_header header; + arp_packet arp; +} full_arp_packet; + +#pragma pack(pop) + +#define ARP_REQUEST 0x0100 //values are big-endian + +extern mac_address virtual_mac; +extern mac_address broadcast_mac; + +extern ip_address virtual_ip; + +#define mac_compare(a,b) (memcmp(&(a),&(b),6)) +#define ip_compare(a,b) (memcmp(&(a),&(b),4)) + +/* +int pcap_io_init(char *adapter); +int pcap_io_send(void* packet, int plen); +int pcap_io_recv(void* packet, int max_len); +void pcap_io_close(); +*/ +int pcap_io_get_dev_num(); +char* pcap_io_get_dev_desc(int num,int md); +char* pcap_io_get_dev_name(int num,int md); + +#ifdef __cplusplus +} +#endif + +class PCAPAdapter : public NetAdapter +{ +public: + PCAPAdapter(); + virtual bool blocks(); + //gets a packet.rv :true success + virtual bool recv(NetPacket* pkt); + //sends the packet and deletes it when done (if successful).rv :true success + virtual bool send(NetPacket* pkt); + virtual ~PCAPAdapter(); +}; \ No newline at end of file diff --git a/plugins/dev9ghzdrk/Win32/postBuild.cmd b/plugins/dev9ghzdrk/Win32/postBuild.cmd new file mode 100644 index 000000000..2d13fa707 --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/postBuild.cmd @@ -0,0 +1,50 @@ +::@echo off +:: +:: Usage: postBuild.cmd SourcePath DestFile DestExt {plugins} +:: +:: SourcePath - $(TargetPath) - Fully qualified path of the generated target file. +:: DestFile - Base filename of the target/dest, without extension! +:: DestExt - Extension of the target/dest! +:: plugins - optional parameter used to generate plugins into the /plugins folder +:: +:: The destination file is determined by the PCSX2_TARGET_DIR environment var. + +SETLOCAL ENABLEEXTENSIONS +if defined PCSX2_TARGET_COPY CALL :TestAndCopy "%PCSX2_TARGET_COPY%" %1 %2 %3 %4 +ENDLOCAL +exit 0 + + +:TestAndCopy +:: Subroutine. First parameter is our Target Dir. Since it's a parameter into +:: the subroutine, we can use tilda expansion to handle quotes correctly. :) + +if NOT EXIST "%~1" ( + md "%~1" +) + +:: Error checking. Try to change to the dir. If it fails, it means the dir is +:: actually a file, and we should cancel the script. + +set mycwd="%CD%" +cd "%~1" +if %ERRORLEVEL% NEQ 0 goto :eof +cd %mycwd% + +set pcsxoutdir=%~1\%~5 +set pcsxoutname=%pcsxoutdir%\%~3%4 +set pcsxnewname=%pcsxoutdir%\%~3-r0%4 + +IF NOT EXIST "%pcsxoutdir%" ( + md "%pcsxoutdir%" +) + +copy /Y "%~2" "%pcsxoutname%" +copy /Y "%~2" "%pcsxnewname%" +if %ERRORLEVEL% EQU 0 ( + echo Target copied to %pcsxnewname% +) + +goto :eof + +:quit diff --git a/plugins/dev9ghzdrk/Win32/resource.h b/plugins/dev9ghzdrk/Win32/resource.h new file mode 100644 index 000000000..c1a6c820e --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/resource.h @@ -0,0 +1,25 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by DEV9linuz.rc +// +#define IDD_CONFDLG 101 +#define IDD_CONFIG 101 +#define IDD_ABOUT 103 +#define IDC_NAME 1000 +#define IDC_COMBO1 1007 +#define IDC_ETHDEV 1007 +#define IDC_BAYTYPE 1008 +#define IDC_ETHENABLED 1009 +#define IDC_HDDFILE 1010 +#define IDC_HDDENABLED 1011 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 105 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1011 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/dev9ghzdrk/Win32/smap.cpp b/plugins/dev9ghzdrk/Win32/smap.cpp new file mode 100644 index 000000000..942582b7c --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/smap.cpp @@ -0,0 +1,874 @@ +#define WINVER 0x0600 +#define _WIN32_WINNT 0x0600 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "smap.h" +#include "net.h" +#include "pcap.h" +#include "pcap_io.h" +#include "tap.h" + +bool has_link=true; +/* +#define SMAP_BASE 0xb0000000 +#define SMAP_REG8(Offset) (*(u8 volatile*)(SMAP_BASE+(Offset))) +#define SMAP_REG16(Offset) (*(u16 volatile*)(SMAP_BASE+(Offset))) +#define SMAP_REG32(Offset) (*(u32 volatile*)(SMAP_BASE+(Offset))) + +u32 EMAC3REG_READ(u32 u32Offset) +{ + u32 hi=SMAP_REG16(u32Offset); + u32 lo=SMAP_REG16(u32Offset+2); + return (hi<<16)|lo; +} + + +void EMAC3REG_WRITE(u32 u32Offset,u32 u32V) +{ + SMAP_REG16(u32Offset)=((u32V>>16)&0xFFFF); + SMAP_REG16(u32Offset+2)=(u32V&0xFFFF); +} +#define SMAP_EMAC3_BASE 0x2000 +#define SMAP_EMAC3_STA_CTRL (SMAP_EMAC3_BASE+0x5C) +void test() +{ + printf ("EMAC3R 0x%08X raw read 0x%08X\n",EMAC3REG_READ(SMAP_EMAC3_STA_CTRL),SMAP_REG32(SMAP_EMAC3_STA_CTRL)); +}*/ + +//this can return a false positive, but its not problem since it may say it cant recv while it can (no harm done, just delay on packets) +bool rx_fifo_can_rx() +{ + //check if RX is on & stuff like that here + + //Check if there is space on RXBD + if (dev9Ru8(SMAP_R_RXFIFO_FRAME_CNT)==64) + return false; + + //Check if there is space on fifo + int rd_ptr = dev9Ru32(SMAP_R_RXFIFO_RD_PTR); + int space = sizeof(dev9.rxfifo) - + ((dev9.rxfifo_wr_ptr-rd_ptr)&16383); + + + if(space==0) + space = sizeof(dev9.rxfifo); + + if (space<1514) + return false; + + //we can recv a packet ! + return true; +} +void rx_process(NetPacket* pk) +{ + if (!rx_fifo_can_rx()) + { + emu_printf("ERROR : !rx_fifo_can_rx at rx_process\n"); + return; + } + smap_bd_t *pbd= ((smap_bd_t *)&dev9.dev9R[SMAP_BD_RX_BASE & 0xffff])+dev9.rxbdi; + + int bytes=(pk->size+3)&(~3); + + if (!(pbd->ctrl_stat & SMAP_BD_RX_EMPTY)) + { + emu_printf("ERROR : Discarding %d bytes (RX%d not ready)\n", bytes, dev9.rxbdi); + return; + } + + int pstart=(dev9.rxfifo_wr_ptr)&16383; + int i=0; + while(ibuffer[i++]); + dev9.rxfifo_wr_ptr&=16383; + } + + //increase RXBD + dev9.rxbdi++; + dev9.rxbdi&=(SMAP_BD_SIZE/8)-1; + + //Fill the BD with info ! + pbd->length = pk->size; + pbd->pointer = 0x4000 + pstart; + pbd->ctrl_stat&= ~SMAP_BD_RX_EMPTY; + + //increase frame count + u8* cntptr=&dev9Ru8(SMAP_R_RXFIFO_FRAME_CNT); + +#ifdef WIN_X64 + *cntptr++; //no asm inline in x64 +#else + __asm + { + //this is silly + mov eax,[cntptr]; + lock inc byte ptr [eax] + } +#endif + + //spams// emu_printf("Got packet, %d bytes (%d fifo)\n", pk->size,bytes); + _DEV9irq(SMAP_INTR_RXEND,0);//now ? or when the fifo is full ? i guess now atm + //note that this _is_ wrong since the IOP interrupt system is not thread safe.. but nothing i can do about that +} + +bool tx_p_first=false; +u32 wswap(u32 d) +{ + return (d>>16)|(d<<16); +} +void tx_process() +{ + //we loop based on count ? or just *use* it ? + u32 cnt=dev9Ru8(SMAP_R_TXFIFO_FRAME_CNT); + //spams// printf("tx_process : %d cnt frames !\n",cnt); + + // this hack worsens OPL performance. Is it really needed? OPL works fine without. (rama) + if (!tx_p_first) + { + dev9Ru8(SMAP_R_TXFIFO_FRAME_CNT)=0; + tx_p_first=true; + //THIS IS A HACK.without that the stack wont init, i guess its missing e3/emac emulation .. + emu_printf("WARN : First packet interrupt hack ..\n"); + _DEV9irq(SMAP_INTR_RXEND|SMAP_INTR_TXEND|SMAP_INTR_TXDNV,100); + return; + } + + NetPacket pk; + int fc=0; + for (fc=0;fcctrl_stat&SMAP_BD_TX_READY)) + { + emu_printf("ERROR : !pbd->ctrl_stat&SMAP_BD_TX_READY\n"); + break; + } + if (pbd->length&3) + { + //spams// emu_printf("WARN : pbd->length not alligned %d\n",pbd->length); + } + + if(pbd->length>1514) + { + emu_printf("ERROR : Trying to send packet too big.\n"); + } + else + { + u32 base=(pbd->pointer-0x1000)&16383; + DEV9_LOG("Sending Packet from base %x, size %d\n", base, pbd->length); + //spams// emu_printf("Sending Packet from base %x, size %d\n", base, pbd->length); + + pk.size=pbd->length; + + if (!(pbd->pointer>=0x1000)) + { + emu_printf("ERROR: odd , !pbd->pointer>0x1000 | 0x%X %d\n", pbd->pointer, pbd->length); + } + //increase fifo pointer(s) + //uh does that even exist on real h/w ? + /* + if(dev9.txfifo_rd_ptr+pbd->length >= 16383) + { + //warp around ! + //first part + u32 was=16384-dev9.txfifo_rd_ptr; + memcpy(pk.buffer,dev9.txfifo+dev9.txfifo_rd_ptr,was); + //warp + dev9.txfifo_rd_ptr+=pbd->length; + dev9.txfifo_rd_ptr&=16383; + if (pbd->length!=was+dev9.txfifo_rd_ptr) + { + emu_printf("ERROR ON TX FIFO HANDLING, %x\n", dev9.txfifo_rd_ptr); + } + //second part + memcpy(pk.buffer+was,dev9.txfifo,pbd->length-was); + } + else + { //no warp or 'perfect' warp (reads end, resets to start + memcpy(pk.buffer,dev9.txfifo+dev9.txfifo_rd_ptr,pbd->length); + dev9.txfifo_rd_ptr+=pbd->length; + if (dev9.txfifo_rd_ptr==16384) + dev9.txfifo_rd_ptr=0; + } + + + + if (dev9.txfifo_rd_ptr&(~16383)) + { + emu_printf("ERROR ON TX FIFO HANDLING, %x\n", dev9.txfifo_rd_ptr); + } + */ + + if(base+pbd->length > 16384) + { + u32 was=16384-base; + memcpy(pk.buffer,dev9.txfifo+base,was); + memcpy(pk.buffer,dev9.txfifo,pbd->length-was); + printf("Warped read, was=%d, sz=%d, sz-was=%d\n",was,pbd->length,pbd->length-was); + } + else + { + memcpy(pk.buffer,dev9.txfifo+base,pbd->length); + } + tx_put(&pk); + } + + + pbd->ctrl_stat&= ~SMAP_BD_TX_READY; + + //increase TXBD + dev9.txbdi++; + dev9.txbdi&=(SMAP_BD_SIZE/8)-1; + + //decrease frame count -- this is not thread safe + dev9Ru8(SMAP_R_TXFIFO_FRAME_CNT)--; + } + + //spams// emu_printf("processed %d frames, %d count, cnt = %d\n",fc,dev9Ru8(SMAP_R_TXFIFO_FRAME_CNT),cnt); + //if some error/early exit signal TXDNV + if (fc!=cnt || cnt==0) + { + printf("WARN : (fc!=cnt || cnt==0) but packet send request was made oO..\n"); + _DEV9irq(SMAP_INTR_TXDNV,0); + } + //if we actualy send something send TXEND + if(fc!=0) + _DEV9irq(SMAP_INTR_TXEND,100);//now ? or when the fifo is empty ? i guess now atm +} + + +void emac3_write(u32 addr) +{ + u32 value=wswap(dev9Ru32(addr)); + switch(addr) + { + case SMAP_R_EMAC3_MODE0_L: + DEV9_LOG("SMAP: SMAP_R_EMAC3_MODE0 write %x\n", value); + value = (value & (~SMAP_E3_SOFT_RESET)) | SMAP_E3_TXMAC_IDLE | SMAP_E3_RXMAC_IDLE; + dev9Ru16(SMAP_R_EMAC3_STA_CTRL_H)|= SMAP_E3_PHY_OP_COMP; + break; + case SMAP_R_EMAC3_TxMODE0_L: + DEV9_LOG("SMAP: SMAP_R_EMAC3_TxMODE0_L write %x\n", value); + //spams// emu_printf("SMAP: SMAP_R_EMAC3_TxMODE0_L write %x\n", value); + //Process TX here ? + if (!value&SMAP_E3_TX_GNP_0) + emu_printf("SMAP_R_EMAC3_TxMODE0_L: SMAP_E3_TX_GNP_0 not set\n"); + + tx_process(); + value = value& ~SMAP_E3_TX_GNP_0; + if (value) + emu_printf("SMAP_R_EMAC3_TxMODE0_L: extra bits set !\n"); + break; + + case SMAP_R_EMAC3_TxMODE1_L: + emu_printf("SMAP_R_EMAC3_TxMODE1_L 32bit write %x\n", value); + break; + + + case SMAP_R_EMAC3_STA_CTRL_L: + DEV9_LOG("SMAP: SMAP_R_EMAC3_STA_CTRL write %x\n", value); + { + if (value & (SMAP_E3_PHY_READ)) + { + value|= SMAP_E3_PHY_OP_COMP; + int reg = value & (SMAP_E3_PHY_REG_ADDR_MSK); + u16 val = dev9.phyregs[reg]; + switch (reg) + { + case SMAP_DsPHYTER_BMSR: + if (has_link) + val|= SMAP_PHY_BMSR_LINK | SMAP_PHY_BMSR_ANCP; + break; + case SMAP_DsPHYTER_PHYSTS: + if (has_link) + val|= SMAP_PHY_STS_LINK |SMAP_PHY_STS_100M | SMAP_PHY_STS_FDX | SMAP_PHY_STS_ANCP; + break; + } + DEV9_LOG("phy_read %d: %x\n", reg, val); + value=(value&0xFFFF)|(val<<16); + } + if (value & (SMAP_E3_PHY_WRITE)) + { + value|= SMAP_E3_PHY_OP_COMP; + int reg = value & (SMAP_E3_PHY_REG_ADDR_MSK); + u16 val = value>>16; + switch (reg) + { + case SMAP_DsPHYTER_BMCR: + val&= ~SMAP_PHY_BMCR_RST; + val|= 0x1; + break; + } + DEV9_LOG("phy_write %d: %x\n", reg, val); + dev9.phyregs[reg] = val; + } + } + break; + default: + DEV9_LOG("SMAP: emac3 write %x=%x\n",addr, value); + } + dev9Ru32(addr)=wswap(value); +} +u8 CALLBACK smap_read8(u32 addr) +{ + switch(addr) + { + case SMAP_R_TXFIFO_FRAME_CNT: + printf("SMAP_R_TXFIFO_FRAME_CNT read 8\n"); + break; + case SMAP_R_RXFIFO_FRAME_CNT: + printf("SMAP_R_RXFIFO_FRAME_CNT read 8\n"); + break; + + case SMAP_R_BD_MODE: + return dev9.bd_swap; + + default: + DEV9_LOG("SMAP : Unknown 8 bit read @ %X,v=%X\n",addr,dev9Ru8(addr)); + return dev9Ru8(addr); + } + + DEV9_LOG("SMAP : error , 8 bit read @ %X,v=%X\n",addr,dev9Ru8(addr)); + return dev9Ru8(addr); +} +u16 CALLBACK smap_read16(u32 addr) +{ + if (addr >= SMAP_BD_TX_BASE && addr < (SMAP_BD_TX_BASE + SMAP_BD_SIZE)) + { + int rv = dev9Ru16(addr); + if(dev9.bd_swap) + return (rv<<8)|(rv>>8); + return rv; + /* + switch (addr & 0x7) + { + case 0: // ctrl_stat + hard = dev9Ru16(addr); + //DEV9_LOG("TX_CTRL_STAT[%d]: read %x\n", (addr - SMAP_BD_TX_BASE) / 8, hard); + if(dev9.bd_swap) + return (hard<<8)|(hard>>8); + return hard; + case 2: // unknown + hard = dev9Ru16(addr); + //DEV9_LOG("TX_UNKNOWN[%d]: read %x\n", (addr - SMAP_BD_TX_BASE) / 8, hard); + if(dev9.bd_swap) + return (hard<<8)|(hard>>8); + return hard; + case 4: // length + hard = dev9Ru16(addr); + DEV9_LOG("TX_LENGTH[%d]: read %x\n", (addr - SMAP_BD_TX_BASE) / 8, hard); + if(dev9.bd_swap) + return (hard<<8)|(hard>>8); + return hard; + case 6: // pointer + hard = dev9Ru16(addr); + DEV9_LOG("TX_POINTER[%d]: read %x\n", (addr - SMAP_BD_TX_BASE) / 8, hard); + if(dev9.bd_swap) + return (hard<<8)|(hard>>8); + return hard; + } + */ + } + else if (addr >= SMAP_BD_RX_BASE && addr < (SMAP_BD_RX_BASE + SMAP_BD_SIZE)) + { + int rv = dev9Ru16(addr); + if(dev9.bd_swap) + return (rv<<8)|(rv>>8); + return rv; + /* + switch (addr & 0x7) + { + case 0: // ctrl_stat + hard = dev9Ru16(addr); + //DEV9_LOG("RX_CTRL_STAT[%d]: read %x\n", (addr - SMAP_BD_RX_BASE) / 8, hard); + if(dev9.bd_swap) + return (hard<<8)|(hard>>8); + return hard; + case 2: // unknown + hard = dev9Ru16(addr); + //DEV9_LOG("RX_UNKNOWN[%d]: read %x\n", (addr - SMAP_BD_RX_BASE) / 8, hard); + if(dev9.bd_swap) + return (hard<<8)|(hard>>8); + return hard; + case 4: // length + hard = dev9Ru16(addr); + DEV9_LOG("RX_LENGTH[%d]: read %x\n", (addr - SMAP_BD_RX_BASE) / 8, hard); + if(dev9.bd_swap) + return (hard<<8)|(hard>>8); + return hard; + case 6: // pointer + hard = dev9Ru16(addr); + DEV9_LOG("RX_POINTER[%d]: read %x\n", (addr - SMAP_BD_RX_BASE) / 8, hard); + if(dev9.bd_swap) + return (hard<<8)|(hard>>8); + return hard; + } + */ + } + + switch(addr) + { +#ifdef DEV9_LOG_ENABLE + case SMAP_R_TXFIFO_FRAME_CNT: + printf("SMAP_R_TXFIFO_FRAME_CNT read 16\n"); + return dev9Ru16(addr); + case SMAP_R_RXFIFO_FRAME_CNT: + printf("SMAP_R_RXFIFO_FRAME_CNT read 16\n"); + return dev9Ru16(addr); + case SMAP_R_EMAC3_MODE0_L: + DEV9_LOG("SMAP_R_EMAC3_MODE0_L 16bit read %x\n", dev9Ru16(addr)); + return dev9Ru16(addr); + + case SMAP_R_EMAC3_MODE0_H: + DEV9_LOG("SMAP_R_EMAC3_MODE0_H 16bit read %x\n", dev9Ru16(addr)); + return dev9Ru16(addr); + + case SMAP_R_EMAC3_MODE1_L: + DEV9_LOG("SMAP_R_EMAC3_MODE1_L 16bit read %x\n", dev9Ru16(addr)); + return dev9Ru16(addr); + + case SMAP_R_EMAC3_MODE1_H: + DEV9_LOG("SMAP_R_EMAC3_MODE1_H 16bit read %x\n", dev9Ru16(addr)); + return dev9Ru16(addr); + + case SMAP_R_EMAC3_RxMODE_L: + DEV9_LOG("SMAP_R_EMAC3_RxMODE_L 16bit read %x\n", dev9Ru16(addr)); + return dev9Ru16(addr); + + case SMAP_R_EMAC3_RxMODE_H: + DEV9_LOG("SMAP_R_EMAC3_RxMODE_H 16bit read %x\n", dev9Ru16(addr)); + return dev9Ru16(addr); + + case SMAP_R_EMAC3_INTR_STAT_L: + DEV9_LOG("SMAP_R_EMAC3_INTR_STAT_L 16bit read %x\n", dev9Ru16(addr)); + return dev9Ru16(addr); + + case SMAP_R_EMAC3_INTR_STAT_H: + DEV9_LOG("SMAP_R_EMAC3_INTR_STAT_H 16bit read %x\n", dev9Ru16(addr)); + return dev9Ru16(addr); + + case SMAP_R_EMAC3_INTR_ENABLE_L: + DEV9_LOG("SMAP_R_EMAC3_INTR_ENABLE_L 16bit read %x\n", dev9Ru16(addr)); + return dev9Ru16(addr); + + case SMAP_R_EMAC3_INTR_ENABLE_H: + DEV9_LOG("SMAP_R_EMAC3_INTR_ENABLE_H 16bit read %x\n", dev9Ru16(addr)); + return dev9Ru16(addr); + + case SMAP_R_EMAC3_TxMODE0_L: + DEV9_LOG("SMAP_R_EMAC3_TxMODE0_L 16bit read %x\n", dev9Ru16(addr)); + return dev9Ru16(addr); + + case SMAP_R_EMAC3_TxMODE0_H: + DEV9_LOG("SMAP_R_EMAC3_TxMODE0_H 16bit read %x\n", dev9Ru16(addr)); + return dev9Ru16(addr); + + case SMAP_R_EMAC3_TxMODE1_L: + DEV9_LOG("SMAP_R_EMAC3_TxMODE1_L 16bit read %x\n", dev9Ru16(addr)); + return dev9Ru16(addr); + + case SMAP_R_EMAC3_TxMODE1_H: + DEV9_LOG("SMAP_R_EMAC3_TxMODE1_H 16bit read %x\n", dev9Ru16(addr)); + return dev9Ru16(addr); + + case SMAP_R_EMAC3_STA_CTRL_L: + DEV9_LOG("SMAP_R_EMAC3_STA_CTRL_L 16bit read %x\n", dev9Ru16(addr)); + return dev9Ru16(addr); + + case SMAP_R_EMAC3_STA_CTRL_H: + DEV9_LOG("SMAP_R_EMAC3_STA_CTRL_H 16bit read %x\n", dev9Ru16(addr)); + return dev9Ru16(addr); +#endif + default: + DEV9_LOG("SMAP : Unknown 16 bit read @ %X,v=%X\n",addr,dev9Ru16(addr)); + return dev9Ru16(addr); + } + + DEV9_LOG("SMAP : error , 16 bit read @ %X,v=%X\n",addr,dev9Ru16(addr)); + return dev9Ru16(addr); + +} +u32 CALLBACK smap_read32(u32 addr) +{ + if (addr>=SMAP_EMAC3_REGBASE && addr>24)|((rv>>8)&0xFF00)|((rv<<8)&0xFF0000); + + DEV9_LOG("SMAP_R_RXFIFO_DATA 32bit read %x\n", rv); + return rv; + } + default: + DEV9_LOG("SMAP : Unknown 32 bit read @ %X,v=%X\n",addr,dev9Ru32(addr)); + return dev9Ru32(addr); + } + + DEV9_LOG("SMAP : error , 32 bit read @ %X,v=%X\n",addr,dev9Ru32(addr)); + return dev9Ru32(addr); +} +void CALLBACK smap_write8(u32 addr, u8 value) +{ + switch(addr) + { + case SMAP_R_TXFIFO_FRAME_INC: + DEV9_LOG("SMAP_R_TXFIFO_FRAME_INC 8bit write %x\n", value); + { + dev9Ru8(SMAP_R_TXFIFO_FRAME_CNT)++; + } + return; + + case SMAP_R_RXFIFO_FRAME_DEC: + DEV9_LOG("SMAP_R_RXFIFO_FRAME_DEC 8bit write %x\n", value); + dev9Ru8(addr) = value; + { + u8* cntptr=&dev9Ru8(SMAP_R_RXFIFO_FRAME_CNT); +#ifdef WIN_X64 + *cntptr--; //no asm inline in x64 +#else + __asm + { + //this is silly + mov eax,[cntptr]; + lock dec byte ptr [eax] + } +#endif + } + return; + + case SMAP_R_TXFIFO_CTRL: + DEV9_LOG("SMAP_R_TXFIFO_CTRL 8bit write %x\n", value); + if(value&SMAP_TXFIFO_RESET) + { + dev9.txbdi=0; + dev9.txfifo_rd_ptr=0; + dev9Ru8(SMAP_R_TXFIFO_FRAME_CNT)=0; //this actualy needs to be atomic (lock mov ...) + dev9Ru32(SMAP_R_TXFIFO_WR_PTR)=0; + dev9Ru32(SMAP_R_TXFIFO_SIZE)=16384; + } + value&= ~SMAP_TXFIFO_RESET; + dev9Ru8(addr) = value; + return; + + case SMAP_R_RXFIFO_CTRL: + DEV9_LOG("SMAP_R_RXFIFO_CTRL 8bit write %x\n", value); + if(value&SMAP_RXFIFO_RESET) + { + dev9.rxbdi=0; + dev9.rxfifo_wr_ptr=0; + dev9Ru8(SMAP_R_RXFIFO_FRAME_CNT)=0; + dev9Ru32(SMAP_R_RXFIFO_RD_PTR)=0; + dev9Ru32(SMAP_R_RXFIFO_SIZE)=16384; + } + value&= ~SMAP_RXFIFO_RESET; + dev9Ru8(addr) = value; + return; + + case SMAP_R_BD_MODE: + if(value&SMAP_BD_SWAP) + { + DEV9_LOG("SMAP_R_BD_MODE: byteswapped.\n"); + emu_printf("BD Byteswapping enabled.\n"); + dev9.bd_swap=1; + } + else + { + DEV9_LOG("SMAP_R_BD_MODE: NOT byteswapped.\n"); + emu_printf("BD Byteswapping disabled.\n"); + dev9.bd_swap=0; + } + return; + default : + DEV9_LOG("SMAP : Unknown 8 bit write @ %X,v=%X\n",addr,value); + dev9Ru8(addr) = value; + return; + } + + DEV9_LOG("SMAP : error , 8 bit write @ %X,v=%X\n",addr,value); + dev9Ru8(addr) = value; +} +void CALLBACK smap_write16(u32 addr, u16 value) +{ + if (addr >= SMAP_BD_TX_BASE && addr < (SMAP_BD_TX_BASE + SMAP_BD_SIZE)) { + if(dev9.bd_swap) + value = (value>>8)|(value<<8); + dev9Ru16(addr) = value; + /* + switch (addr & 0x7) + { + case 0: // ctrl_stat + DEV9_LOG("TX_CTRL_STAT[%d]: write %x\n", (addr - SMAP_BD_TX_BASE) / 8, value); + //hacky + dev9Ru16(addr) = value; + return; + case 2: // unknown + //DEV9_LOG("TX_UNKNOWN[%d]: write %x\n", (addr - SMAP_BD_TX_BASE) / 8, value); + dev9Ru16(addr) = value; + return; + case 4: // length + DEV9_LOG("TX_LENGTH[%d]: write %x\n", (addr - SMAP_BD_TX_BASE) / 8, value); + dev9Ru16(addr) = value; + return; + case 6: // pointer + DEV9_LOG("TX_POINTER[%d]: write %x\n", (addr - SMAP_BD_TX_BASE) / 8, value); + dev9Ru16(addr) = value; + return; + } + */ + return; + } + else if (addr >= SMAP_BD_RX_BASE && addr < (SMAP_BD_RX_BASE + SMAP_BD_SIZE)) + { + int rx_index=(addr - SMAP_BD_RX_BASE)>>3; + if(dev9.bd_swap) + value = (value>>8)|(value<<8); + dev9Ru16(addr) = value; +/* + switch (addr & 0x7) + { + case 0: // ctrl_stat + DEV9_LOG("RX_CTRL_STAT[%d]: write %x\n", rx_index, value); + dev9Ru16(addr) = value; + if(value&0x8000) + { + DEV9_LOG(" * * PACKET READ COMPLETE: rd_ptr=%d, wr_ptr=%d\n", dev9Ru32(SMAP_R_RXFIFO_RD_PTR), dev9.rxfifo_wr_ptr); + } + return; + case 2: // unknown + //DEV9_LOG("RX_UNKNOWN[%d]: write %x\n", rx_index, value); + dev9Ru16(addr) = value; + return; + case 4: // length + DEV9_LOG("RX_LENGTH[%d]: write %x\n", rx_index, value); + dev9Ru16(addr) = value; + return; + case 6: // pointer + DEV9_LOG("RX_POINTER[%d]: write %x\n", rx_index, value); + dev9Ru16(addr) = value; + return; + } + */ + return; + } + + switch(addr) + { + case SMAP_R_INTR_CLR: + DEV9_LOG("SMAP: SMAP_R_INTR_CLR 16bit write %x\n", value); + dev9.irqcause&= ~value; + return; + + case SMAP_R_TXFIFO_WR_PTR: + DEV9_LOG("SMAP: SMAP_R_TXFIFO_WR_PTR 16bit write %x\n", value); + dev9Ru16(addr) = value; + return; +#define EMAC3_L_WRITE(name) \ + case name: \ + DEV9_LOG("SMAP: " #name " 16 bit write %x\n", value); \ + dev9Ru16(addr) = value; \ + return; + //handle L writes + EMAC3_L_WRITE(SMAP_R_EMAC3_MODE0_L ) + EMAC3_L_WRITE( SMAP_R_EMAC3_MODE1_L ) + EMAC3_L_WRITE( SMAP_R_EMAC3_TxMODE0_L ) + EMAC3_L_WRITE( SMAP_R_EMAC3_TxMODE1_L ) + EMAC3_L_WRITE( SMAP_R_EMAC3_RxMODE_L ) + EMAC3_L_WRITE( SMAP_R_EMAC3_INTR_STAT_L ) + EMAC3_L_WRITE( SMAP_R_EMAC3_INTR_ENABLE_L ) + EMAC3_L_WRITE( SMAP_R_EMAC3_ADDR_HI_L ) + EMAC3_L_WRITE( SMAP_R_EMAC3_ADDR_LO_L ) + EMAC3_L_WRITE( SMAP_R_EMAC3_VLAN_TPID ) + EMAC3_L_WRITE( SMAP_R_EMAC3_PAUSE_TIMER_L ) + EMAC3_L_WRITE( SMAP_R_EMAC3_INDIVID_HASH1 ) + EMAC3_L_WRITE( SMAP_R_EMAC3_INDIVID_HASH2 ) + EMAC3_L_WRITE( SMAP_R_EMAC3_INDIVID_HASH3 ) + EMAC3_L_WRITE( SMAP_R_EMAC3_INDIVID_HASH4 ) + EMAC3_L_WRITE( SMAP_R_EMAC3_GROUP_HASH1 ) + EMAC3_L_WRITE( SMAP_R_EMAC3_GROUP_HASH2 ) + EMAC3_L_WRITE( SMAP_R_EMAC3_GROUP_HASH3 ) + EMAC3_L_WRITE( SMAP_R_EMAC3_GROUP_HASH4 ) + + EMAC3_L_WRITE( SMAP_R_EMAC3_LAST_SA_HI ) + EMAC3_L_WRITE( SMAP_R_EMAC3_LAST_SA_LO ) + EMAC3_L_WRITE( SMAP_R_EMAC3_INTER_FRAME_GAP_L ) + EMAC3_L_WRITE( SMAP_R_EMAC3_STA_CTRL_L ) + EMAC3_L_WRITE( SMAP_R_EMAC3_TX_THRESHOLD_L ) + EMAC3_L_WRITE( SMAP_R_EMAC3_RX_WATERMARK_L ) + EMAC3_L_WRITE( SMAP_R_EMAC3_TX_OCTETS ) + EMAC3_L_WRITE( SMAP_R_EMAC3_RX_OCTETS ) + +#define EMAC3_H_WRITE(name) \ + case name: \ + DEV9_LOG("SMAP: " #name " 16 bit write %x\n", value); \ + dev9Ru16(addr) = value; \ + emac3_write(addr-2); \ + return; + //handle H writes + EMAC3_H_WRITE(SMAP_R_EMAC3_MODE0_H ) + EMAC3_H_WRITE( SMAP_R_EMAC3_MODE1_H ) + EMAC3_H_WRITE( SMAP_R_EMAC3_TxMODE0_H ) + EMAC3_H_WRITE( SMAP_R_EMAC3_TxMODE1_H ) + EMAC3_H_WRITE( SMAP_R_EMAC3_RxMODE_H ) + EMAC3_H_WRITE( SMAP_R_EMAC3_INTR_STAT_H ) + EMAC3_H_WRITE( SMAP_R_EMAC3_INTR_ENABLE_H ) + EMAC3_H_WRITE( SMAP_R_EMAC3_ADDR_HI_H ) + EMAC3_H_WRITE( SMAP_R_EMAC3_ADDR_LO_H ) + EMAC3_H_WRITE( SMAP_R_EMAC3_VLAN_TPID+2 ) + EMAC3_H_WRITE( SMAP_R_EMAC3_PAUSE_TIMER_H ) + EMAC3_H_WRITE( SMAP_R_EMAC3_INDIVID_HASH1+2 ) + EMAC3_H_WRITE( SMAP_R_EMAC3_INDIVID_HASH2+2 ) + EMAC3_H_WRITE( SMAP_R_EMAC3_INDIVID_HASH3+2 ) + EMAC3_H_WRITE( SMAP_R_EMAC3_INDIVID_HASH4+2 ) + EMAC3_H_WRITE( SMAP_R_EMAC3_GROUP_HASH1+2 ) + EMAC3_H_WRITE( SMAP_R_EMAC3_GROUP_HASH2+2 ) + EMAC3_H_WRITE( SMAP_R_EMAC3_GROUP_HASH3+2 ) + EMAC3_H_WRITE( SMAP_R_EMAC3_GROUP_HASH4+2 ) + + EMAC3_H_WRITE( SMAP_R_EMAC3_LAST_SA_HI+2 ) + EMAC3_H_WRITE( SMAP_R_EMAC3_LAST_SA_LO+2 ) + EMAC3_H_WRITE( SMAP_R_EMAC3_INTER_FRAME_GAP_H ) + EMAC3_H_WRITE( SMAP_R_EMAC3_STA_CTRL_H ) + EMAC3_H_WRITE( SMAP_R_EMAC3_TX_THRESHOLD_H ) + EMAC3_H_WRITE( SMAP_R_EMAC3_RX_WATERMARK_H ) + EMAC3_H_WRITE( SMAP_R_EMAC3_TX_OCTETS+2 ) + EMAC3_H_WRITE( SMAP_R_EMAC3_RX_OCTETS+2 ) +/* + case SMAP_R_EMAC3_MODE0_L: + DEV9_LOG("SMAP: SMAP_R_EMAC3_MODE0 write %x\n", value); + dev9Ru16(addr) = value; + return; + case SMAP_R_EMAC3_TxMODE0_L: + DEV9_LOG("SMAP: SMAP_R_EMAC3_TxMODE0_L 16bit write %x\n", value); + dev9Ru16(addr) = value; + return; + case SMAP_R_EMAC3_TxMODE1_L: + emu_printf("SMAP: SMAP_R_EMAC3_TxMODE1_L 16bit write %x\n", value); + dev9Ru16(addr) = value; + return; + + case SMAP_R_EMAC3_TxMODE0_H: + emu_printf("SMAP: SMAP_R_EMAC3_TxMODE0_H 16bit write %x\n", value); + dev9Ru16(addr) = value; + return; + + case SMAP_R_EMAC3_TxMODE1_H: + emu_printf("SMAP: SMAP_R_EMAC3_TxMODE1_H 16bit write %x\n", value); + dev9Ru16(addr) = value; + return; + case SMAP_R_EMAC3_STA_CTRL_H: + DEV9_LOG("SMAP: SMAP_R_EMAC3_STA_CTRL_H 16bit write %x\n", value); + dev9Ru16(addr) = value; + return; + */ + + default : + DEV9_LOG("SMAP : Unknown 16 bit write @ %X,v=%X\n",addr,value); + dev9Ru16(addr) = value; + return; + } + + DEV9_LOG("SMAP : error , 16 bit write @ %X,v=%X\n",addr,value); + dev9Ru16(addr) = value; +} +void CALLBACK smap_write32(u32 addr, u32 value) +{ + if (addr>=SMAP_EMAC3_REGBASE && addr>16); + return; + } + switch(addr) + { + case SMAP_R_TXFIFO_DATA: + if(dev9.bd_swap) + value=(value<<24)|(value>>24)|((value>>8)&0xFF00)|((value<<8)&0xFF0000); + + DEV9_LOG("SMAP_R_TXFIFO_DATA 32bit write %x\n", value); + *((u32*)(dev9.txfifo+dev9Ru32(SMAP_R_TXFIFO_WR_PTR)))=value; + dev9Ru32(SMAP_R_TXFIFO_WR_PTR) = (dev9Ru32(SMAP_R_TXFIFO_WR_PTR)+4)&16383; + return; + default : + DEV9_LOG("SMAP : Unknown 32 bit write @ %X,v=%X\n",addr,value); + dev9Ru32(addr) = value; + return; + } + + DEV9_LOG("SMAP : error , 32 bit write @ %X,v=%X\n",addr,value); + dev9Ru32(addr) = value; +} +void CALLBACK smap_readDMA8Mem(u32 *pMem, int size) +{ + if(dev9Ru16(SMAP_R_RXFIFO_CTRL)&SMAP_RXFIFO_DMAEN) + { + dev9Ru32(SMAP_R_RXFIFO_RD_PTR)&=16383; + size>>=1; + DEV9_LOG(" * * SMAP DMA READ START: rd_ptr=%d, wr_ptr=%d\n", dev9Ru32(SMAP_R_RXFIFO_RD_PTR), dev9.rxfifo_wr_ptr); + while(size>0) + { + *pMem = *((u32*)(dev9.rxfifo+dev9Ru32(SMAP_R_RXFIFO_RD_PTR))); + pMem++; + dev9Ru32(SMAP_R_RXFIFO_RD_PTR) = (dev9Ru32(SMAP_R_RXFIFO_RD_PTR)+4)&16383; + + size-=4; + } + DEV9_LOG(" * * SMAP DMA READ END: rd_ptr=%d, wr_ptr=%d\n", dev9Ru32(SMAP_R_RXFIFO_RD_PTR), dev9.rxfifo_wr_ptr); + + dev9Ru16(SMAP_R_RXFIFO_CTRL) &= ~SMAP_RXFIFO_DMAEN; + } +} +void CALLBACK smap_writeDMA8Mem(u32* pMem, int size) +{ + if(dev9Ru16(SMAP_R_TXFIFO_CTRL)&SMAP_TXFIFO_DMAEN) + { + dev9Ru32(SMAP_R_TXFIFO_WR_PTR)&=16383; + size>>=1; + DEV9_LOG(" * * SMAP DMA WRITE START: wr_ptr=%d, rd_ptr=%d\n", dev9Ru32(SMAP_R_TXFIFO_WR_PTR), dev9.txfifo_rd_ptr); + while(size>0) + { + int value=*pMem; + // value=(value<<24)|(value>>24)|((value>>8)&0xFF00)|((value<<8)&0xFF0000); + pMem++; + + *((u32*)(dev9.txfifo+dev9Ru32(SMAP_R_TXFIFO_WR_PTR)))=value; + dev9Ru32(SMAP_R_TXFIFO_WR_PTR) = (dev9Ru32(SMAP_R_TXFIFO_WR_PTR)+4)&16383; + size-=4; + } + DEV9_LOG(" * * SMAP DMA WRITE END: wr_ptr=%d, rd_ptr=%d\n", dev9Ru32(SMAP_R_TXFIFO_WR_PTR), dev9.txfifo_rd_ptr); + + dev9Ru16(SMAP_R_TXFIFO_CTRL) &= ~SMAP_TXFIFO_DMAEN; + + } +} diff --git a/plugins/dev9ghzdrk/Win32/smap.h b/plugins/dev9ghzdrk/Win32/smap.h new file mode 100644 index 000000000..42ad1842a --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/smap.h @@ -0,0 +1,13 @@ +#pragma once +#include "dev9.h" + +u8 CALLBACK smap_read8(u32 addr); +u16 CALLBACK smap_read16(u32 addr); +u32 CALLBACK smap_read32(u32 addr); + +void CALLBACK smap_write8(u32 addr, u8 value); +void CALLBACK smap_write16(u32 addr, u16 value); +void CALLBACK smap_write32(u32 addr, u32 value); + +void CALLBACK smap_readDMA8Mem(u32 *pMem, int size); +void CALLBACK smap_writeDMA8Mem(u32 *pMem, int size); \ No newline at end of file diff --git a/plugins/dev9ghzdrk/Win32/socket_io.cpp b/plugins/dev9ghzdrk/Win32/socket_io.cpp new file mode 100644 index 000000000..78b557243 --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/socket_io.cpp @@ -0,0 +1,294 @@ +#include +#include + +#include +extern "C" { +#include "dev9.h" +} +#include + +#include "pcap_io.h" + +#include +#include +#include + +//extern "C" int emu_printf(const char *fmt, ...); + +mac_address gateway_mac = { 0x76, 0x6D, 0x61, 0x63, 0x30, 0x32 }; +mac_address virtual_mac = { 0x76, 0x6D, 0x61, 0x63, 0x30, 0x31 }; +mac_address broadcast_mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + +//mac_address host_mac = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +ip_address virtual_gway_ip = { 192, 168, 1, 1}; +ip_address virtual_host_ip = { 192, 168, 1, 2}; + +char namebuff[256]; + +FILE*packet_log; + +int pcap_io_running=0; + +class packet_info +{ +public: + int length; + s8 data[2048]; + + packet_info() + { + length=0; + memset(data,0,2048); + } + + packet_info(const packet_info& pkt) + { + length=pkt.length; + memcpy(data,pkt.data,length); + } + + packet_info(int l, void*d) + { + length=l; + memcpy(data,d,l); + } +}; + +std::queue recv_queue; + + +int ip_checksum(u16 *data, int length) +{ + int n=(length+1)>>1; + int s=0; + for(int i=0;i>16); + return s; +} + +// +int pcap_io_init(char *adapter) +{ + WSADATA wsaData; + + emu_printf(" * Socket IO: Initializing virtual gateway...",adapter); + + WSAStartup(0x0200,&wsaData); + + packet_log=fopen("logs/packet.log","w"); + + pcap_io_running=1; + + emu_printf("Ok.\n"); + return 0; +} + +int pcap_io_send(void* packet, int plen) +{ + emu_printf(" * Socket IO: Sending %d byte packet.\n",plen); + + if(packet_log) + { + int i=0; + int n=0; + + fprintf(packet_log,"PACKET SEND: %d BYTES\n",plen); + for(i=0,n=0;idst,broadcast_mac)==0) //broadcast packets + { + if(eth->protocol == 0x0608) //ARP + { + arp_packet *arp = (arp_packet*)((s8*)packet+sizeof(ethernet_header)); + if(arp->operation == 0x0100) //ARP request + { + if(ip_compare(arp->p_dst,virtual_gway_ip)==0) //it's trying to resolve the virtual gateway's mac addr + { + full_arp_packet p; + p.header.src = gateway_mac; + p.header.dst = eth->src; + p.header.protocol = 0x0608; + p.arp.h_addr_len=6; + p.arp.h_dst = eth->src; + p.arp.h_src = gateway_mac; + p.arp.p_addr_len = 4; + p.arp.p_dst = arp->p_src; + p.arp.p_src = virtual_gway_ip; + p.arp.protocol = 0x0008; + p.arp.operation = 0x0200; + + //packet_info pkt(sizeof(p),&p) + recv_queue.push(packet_info(sizeof(p),&p)); + } + } + } + } + else if(mac_compare(eth->dst,gateway_mac)==0) + { + if(eth->protocol == 0x0008) //IP + { + ip_header *ip = (ip_header*)((s8*)packet+sizeof(ethernet_header)); + + if((ip->proto == 0x11) && (ip->dst.bytes[0]!=192)) //UDP (non-local) + { + // + //if(ip-> + } + else + if(ip->proto == 0x01) //ICMP + { + if (ip_compare(ip->dst,virtual_gway_ip)==0) //PING to gateway + { + static u8 icmp_packet[1024]; + + memcpy(icmp_packet,packet,plen); + + ethernet_header *eh = (ethernet_header *)icmp_packet; + + eh->dst=eth->src; + eh->src=gateway_mac; + + ip_header *iph = (ip_header*)(eh+1); + + iph->dst = ip->src; + iph->src = virtual_gway_ip; + + iph->hdr_csum = 0; + + int sum = ip_checksum((u16*)iph,sizeof(ip_header)); + iph->hdr_csum = sum; + + icmp_header *ich = (icmp_header*)(iph+1); + + ich->type=0; + ich->code=0; + ich->csum=0; + + sum = ip_checksum((u16*)ich,iph->len-sizeof(ip_header)); + ich->csum = sum; + + recv_queue.push(packet_info(plen,&icmp_packet)); + + } + else if (ip->dst.bytes[0] != 192) //PING to external + { + static u8 icmp_packet[1024]; + + memcpy(icmp_packet,packet,plen); + + ethernet_header *eh = (ethernet_header *)icmp_packet; + + eh->dst=eth->src; + eh->src=gateway_mac; + + ip_header *iph = (ip_header*)(eh+1); + + iph->dst = ip->src; + iph->src = virtual_gway_ip; + + iph->hdr_csum = 0; + + int sum = ip_checksum((u16*)iph,sizeof(ip_header)); + iph->hdr_csum = sum; + + icmp_header *ich = (icmp_header*)(iph+1); + + ich->type=0; + ich->code=0; + ich->csum=0; + + sum = ip_checksum((u16*)ich,iph->len-sizeof(ip_header)); + ich->csum = sum; + + recv_queue.push(packet_info(plen,&icmp_packet)); + + } + } + } + } + + return 0; +} + +int pcap_io_recv(void* packet, int max_len) +{ + if(pcap_io_running<=0) + return -1; + + if(!recv_queue.empty()) + { + packet_info pkt(recv_queue.front()); + recv_queue.pop(); + + memcpy(packet,pkt.data,pkt.length); + + if(packet_log) + { + int i=0; + int n=0; + int plen=pkt.length; + + fprintf(packet_log,"PACKET RECV: %d BYTES\n",plen); + for(i=0,n=0;i +#include + +#include "packet32.h" +#include "ntddndis.h" + +#include "socks.h" +#include "DEV9.h" + +#define BUFFER_SIZE (2048) + +LPADAPTER lpAdapter; +LPPACKET lpSendPacket; +LPPACKET lpRecvPacket; +u8 buffer[BUFFER_SIZE]; +u8 *buf; +int lbytes; +int tbytes; +typedef struct { + char name[256]; + char desc[256]; +} _Adapter; + +_Adapter AdapterList[16]; + +long sockOpen(char *Device) { + lpAdapter = PacketOpenAdapter(Device); + if (lpAdapter == NULL) return -1; + +#ifdef DEV9_LOG + DEV9_LOG("PacketOpenAdapter %s: %p\n", Device, lpAdapter); +#endif + + if(PacketSetHwFilter(lpAdapter,NDIS_PACKET_TYPE_PROMISCUOUS)==FALSE){ + SysMessage("Warning: unable to set promiscuous mode!"); + } + + if(PacketSetBuff(lpAdapter,512000)==FALSE){ + SysMessage("Unable to set the kernel buffer!"); + return -1; + } + + if(PacketSetReadTimeout(lpAdapter,100)==FALSE){ + SysMessage("Warning: unable to set the read tiemout!"); + } + + if((lpRecvPacket = PacketAllocatePacket())==NULL){ + SysMessage("Error: failed to allocate the LPPACKET structure."); + return (-1); + } + if((lpSendPacket = PacketAllocatePacket())==NULL){ + SysMessage("Error: failed to allocate the LPPACKET structure."); + return (-1); + } + + lbytes=0; + tbytes=0; + + return 0; +} + +void sockClose() { + PacketCloseAdapter(lpAdapter); +} + +long sockSendData(void *pData, int Size) { + u8 *data = (u8*)pData; +// printf("_sendPacket %d (time=%d)\n", Size, timeGetTime()); + while (Size > 0) { + PacketInitPacket(lpSendPacket, data, Size > 1024 ? 1024 : Size); + if(PacketSendPacket(lpAdapter,lpSendPacket,FALSE)==FALSE){ + printf("Error: PacketSendPacket failed\n"); + return (-1); + } + data+= 1024; Size-= 1024; + PacketFreePacket(lpSendPacket); + } + + return 0; +} + +int _filterPacket(u8 *_buf) { +/* DEV9_LOG("%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", _buf[5], _buf[4], _buf[3], _buf[2], _buf[1], _buf[0]); + DEV9_LOG("%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", _buf[11], _buf[10], _buf[9], _buf[8], _buf[7], _buf[6]); + DEV9_LOG("%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", _buf[17], _buf[16], _buf[15], _buf[14], _buf[13], _buf[12]); + DEV9_LOG("%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", _buf[23], _buf[22], _buf[21], _buf[20], _buf[19], _buf[18]); +*/ + if (_buf[0] == 0xff && _buf[1] == 0xff && _buf[2] == 0xff && + _buf[3] == 0xff && _buf[4] == 0xff && _buf[5] == 0xff) { + return 1; + } else + if (_buf[0] == 0x00 && _buf[1] == 0x00 && _buf[2] == 0x00 && + _buf[3] == 0x00 && _buf[4] == 0x00 && _buf[5] == 0x00) { + return 1; + } else + if (*((u16*)&_buf[12]) == 0x0806) { + printf("ARP\n"); + return 1; + } + + return 0; +} + +int _recvPacket(void *pData) { + struct bpf_hdr *hdr; + u8 *data; + int ret=0; + int size; + + while (lbytes > 0) { + hdr = (struct bpf_hdr *)buf; +// DEV9_LOG("hdr %d,%d,%d\n", hdr->bh_hdrlen, hdr->bh_caplen, hdr->bh_datalen); +// DEV9_LOG("lbytes %d\n", lbytes); + data = buf+hdr->bh_hdrlen; + size = Packet_WORDALIGN(hdr->bh_hdrlen+hdr->bh_datalen); + buf+= size; lbytes-= size; + if (_filterPacket(data)) { + struct bpf_stat stat; + + ret = hdr->bh_datalen; + memcpy(pData, data, ret); + if(PacketGetStats(lpAdapter,&stat)==FALSE){ + printf("Warning: unable to get stats from the kernel!\n"); + } +// printf("_recvPacket %d (tbytes=%d, packets=%d, lost=%d, time=%d)\n", ret, tbytes, stat.bs_recv,stat.bs_drop, timeGetTime()); +// printf("%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", data[5], data[4], data[3], data[2], data[1], data[0]); + break; + } + } + + return ret; +} + +long sockRecvData(void *pData, int Size) { + int ret; + + ret = _recvPacket(pData); + if (ret > 0) return ret; + + PacketInitPacket(lpRecvPacket, buffer, BUFFER_SIZE); + if(PacketReceivePacket(lpAdapter,lpRecvPacket,TRUE)==FALSE){ + printf("Error: PacketReceivePacket failed"); + return (-1); + } + lbytes = lpRecvPacket->ulBytesReceived; + tbytes+= lbytes; +// DEV9_LOG("PacketReceivePacket %d:\n", lbytes); + if (lbytes == 0) return 0; + memcpy(buffer, lpRecvPacket->Buffer, lbytes); + buf = buffer; + PacketFreePacket(lpRecvPacket); + + return _recvPacket(pData); +} + +long sockGetDevicesNum() { + char AdapterName[8192]; // string that contains a list of the network adapters + ULONG AdapterLength; + char *temp,*temp1; + int i; + + AdapterLength = sizeof(AdapterName); + if(PacketGetAdapterNames(AdapterName,&AdapterLength)==FALSE){ + printf("Unable to retrieve the list of the adapters!\n"); + return -1; + } + temp=AdapterName; + temp1=AdapterName; + + i=0; + while (temp[0] != 0) { + strcpy(AdapterList[i++].name, temp); + temp+= strlen(temp)+1; + } + i=0; temp++; + while (temp[0] != 0) { + strcpy(AdapterList[i++].desc, temp); + temp+= strlen(temp)+1; + } + + return i; +} + +char *sockGetDevice(int index) { + return AdapterList[index].name; +} + +char *sockGetDeviceDesc(int index) { + return AdapterList[index].desc; +} + diff --git a/plugins/dev9ghzdrk/Win32/socks.h b/plugins/dev9ghzdrk/Win32/socks.h new file mode 100644 index 000000000..55e29ef24 --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/socks.h @@ -0,0 +1,12 @@ +#ifndef __SOCKS_H__ +#define __SOCKS_H__ + +long sockOpen(char *Device); +void sockClose(); +long sockSendData(void *pData, int Size); +long sockRecvData(void *pData, int Size); +long sockGetDevicesNum(); +char *sockGetDevice(int index); +char *sockGetDeviceDesc(int index); + +#endif /* __SOCKS_H__*/ diff --git a/plugins/dev9ghzdrk/Win32/svnrev.h b/plugins/dev9ghzdrk/Win32/svnrev.h new file mode 100644 index 000000000..b9fa556f9 --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/svnrev.h @@ -0,0 +1,33 @@ +/* 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 . +*/ + +// svnrev_template.h --> 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 0 +#define SVN_MODS 0 diff --git a/plugins/dev9ghzdrk/Win32/tap-win32.cpp b/plugins/dev9ghzdrk/Win32/tap-win32.cpp new file mode 100644 index 000000000..27afd4520 --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/tap-win32.cpp @@ -0,0 +1,1080 @@ +/* + * TAP-Win32 -- A kernel driver to provide virtual tap device functionality + * on Windows. Originally derived from the CIPE-Win32 + * project by Damion K. Wilson, with extensive modifications by + * James Yonan. + * + * All source code which derives from the CIPE-Win32 project is + * Copyright (C) Damion K. Wilson, 2003, and is released under the + * GPL version 2 (see below). + * + * All other source code is Copyright (C) James Yonan, 2003-2004, + * and is released under the GPL version 2 (see below). + * + * 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 (see the file COPYING included with this + * distribution); if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include "tap.h" +#include "dev9.h" +#include + +//============= +// TAP IOCTLs +//============= + +#define TAP_CONTROL_CODE(request,method) \ + CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS) + +#define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE (1, METHOD_BUFFERED) +#define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE (2, METHOD_BUFFERED) +#define TAP_IOCTL_GET_MTU TAP_CONTROL_CODE (3, METHOD_BUFFERED) +#define TAP_IOCTL_GET_INFO TAP_CONTROL_CODE (4, METHOD_BUFFERED) +#define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED) +#define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE (6, METHOD_BUFFERED) +#define TAP_IOCTL_CONFIG_DHCP_MASQ TAP_CONTROL_CODE (7, METHOD_BUFFERED) +#define TAP_IOCTL_GET_LOG_LINE TAP_CONTROL_CODE (8, METHOD_BUFFERED) +#define TAP_IOCTL_CONFIG_DHCP_SET_OPT TAP_CONTROL_CODE (9, METHOD_BUFFERED) + +//================= +// Registry keys +//================= + +#define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}" + +#define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}" + +//====================== +// Filesystem prefixes +//====================== + +#define USERMODEDEVICEDIR "\\\\.\\Global\\" +#define TAPSUFFIX ".tap" + +#ifdef WIN_X64 +#define TAP_COMPONENT_ID "tap0901" +#else +#define TAP_COMPONENT_ID "tap0801" +#endif + +vector* get_tap_reg () +{ + vector* names = new vector(); + HKEY adapter_key; + LONG status; + DWORD len; + + int i = 0; + + status = RegOpenKeyEx( + HKEY_LOCAL_MACHINE, + ADAPTER_KEY, + 0, + KEY_READ, + &adapter_key); + + if (status != ERROR_SUCCESS) + printf ( "Error opening registry key: %s", ADAPTER_KEY); + + while (true) + { + char enum_name[256]; + char unit_string[256]; + HKEY unit_key; + char component_id_string[] = "ComponentId"; + char component_id[256]; + char net_cfg_instance_id_string[] = "NetCfgInstanceId"; + char net_cfg_instance_id[256]; + DWORD data_type; + + len = sizeof (enum_name); + status = RegEnumKeyEx( + adapter_key, + i, + enum_name, + &len, + NULL, + NULL, + NULL, + NULL); + if (status == ERROR_NO_MORE_ITEMS) + break; + else if (status != ERROR_SUCCESS) + printf ( "Error enumerating registry subkeys of key: %s", + ADAPTER_KEY); + + _snprintf (unit_string, sizeof(unit_string), "%s\\%s", + ADAPTER_KEY, enum_name); + + status = RegOpenKeyEx( + HKEY_LOCAL_MACHINE, + unit_string, + 0, + KEY_READ, + &unit_key); + + if (status != ERROR_SUCCESS) + printf ( "Error opening registry key: %s", unit_string); + else + { + len = sizeof (component_id); + status = RegQueryValueEx( + unit_key, + component_id_string, + NULL, + &data_type, + (LPBYTE)component_id, + &len); + + if (status != ERROR_SUCCESS || data_type != REG_SZ) + printf ( "Error opening registry key: %s\\%s", + unit_string, component_id_string); + else + { + len = sizeof (net_cfg_instance_id); + status = RegQueryValueEx( + unit_key, + net_cfg_instance_id_string, + NULL, + &data_type, + (LPBYTE)net_cfg_instance_id, + &len); + + if (status == ERROR_SUCCESS && data_type == REG_SZ) + { + if(!memcmp(component_id, "tap",3)) + { + printf("*** Found possible tap adapter: %s\n",component_id); + + int version = atoi(component_id+3); + if(version>=800) + { + names->push_back(net_cfg_instance_id); + } + } + } + } + RegCloseKey (unit_key); + } + ++i; + } + + RegCloseKey (adapter_key); + return names; +} + +struct temp_11{string name;string guid;}; +vector* get_panel_reg () +{ + LONG status; + HKEY network_connections_key; + DWORD len; + vector* names = new vector(); + int i = 0; + + status = RegOpenKeyEx( + HKEY_LOCAL_MACHINE, + NETWORK_CONNECTIONS_KEY, + 0, + KEY_READ, + &network_connections_key); + + if (status != ERROR_SUCCESS) + printf ( "Error opening registry key: %s", NETWORK_CONNECTIONS_KEY); + + while (true) + { + char enum_name[256]; + char connection_string[256]; + HKEY connection_key; + char name_data[256]; + DWORD name_type; + const char name_string[] = "Name"; + + len = sizeof (enum_name); + status = RegEnumKeyEx( + network_connections_key, + i, + enum_name, + &len, + NULL, + NULL, + NULL, + NULL); + if (status == ERROR_NO_MORE_ITEMS) + break; + else if (status != ERROR_SUCCESS) + printf ( "Error enumerating registry subkeys of key: %s", + NETWORK_CONNECTIONS_KEY); + + _snprintf (connection_string, sizeof(connection_string), + "%s\\%s\\Connection", + NETWORK_CONNECTIONS_KEY, enum_name); + + status = RegOpenKeyEx( + HKEY_LOCAL_MACHINE, + connection_string, + 0, + KEY_READ, + &connection_key); + + if (status != ERROR_SUCCESS) + printf ( "Error opening registry key: %s", connection_string); + else + { + len = sizeof (name_data); + status = RegQueryValueEx( + connection_key, + name_string, + NULL, + &name_type, + (LPBYTE)name_data, + &len); + + if (status != ERROR_SUCCESS || name_type != REG_SZ) + printf ( "Error opening registry key: %s\\%s\\%s", + NETWORK_CONNECTIONS_KEY, connection_string, name_string); + else + { + temp_11 t = {name_data,enum_name}; + names->push_back(t); + + } + RegCloseKey (connection_key); + } + ++i; + } + + RegCloseKey (network_connections_key); + + return names; +} + + +vector* GetTapAdapters() +{ + vector* rv = new vector(); + int links; + + vector *tap_reg = get_tap_reg (); + vector *panel_reg = get_panel_reg (); + + printf ( "\nAvailable TAP-WIN32 adapters [name, GUID]:\n"); + + /* loop through each TAP-Win32 adapter registry entry */ + for (size_t i = 0; isize();i++) + { + links = 0; + + /* loop through each network connections entry in the control panel */ + for (size_t j = 0; jsize();j++) + { + if (!strcmp ((*tap_reg)[i].c_str(), (*panel_reg)[j].guid.c_str())) + { + //printf ("'%s' %s\n", (*panel_reg)[j].name.c_str(),(*tap_reg)[i].c_str()); + tap_adapter t = { (*panel_reg)[j].name,(*tap_reg)[i]}; + t.guid= string("tap:") + t.guid; + t.name=string("tap:") + t.name; + rv->push_back(t); + ++links; + } + } + + if (links > 1) + { + //warn_panel_dup = true; + } + else if (links == 0) + { + /* a TAP adapter exists without a link from the network + connections control panel */ +// warn_panel_null = true; + printf ("[NULL] %s\n",(*tap_reg)[i].c_str()); + } + } + delete tap_reg,panel_reg; + return rv; +} + +//Set the connection status +static int TAPSetStatus(HANDLE handle, int status) +{ + unsigned long len = 0; + + return DeviceIoControl(handle, TAP_IOCTL_SET_MEDIA_STATUS, + &status, sizeof (status), + &status, sizeof (status), &len, NULL); +} +//Open the TAP adapter and set the connection to enabled :) +HANDLE TAPOpen(const char *device_guid) +{ + char device_path[256]; + + struct { + unsigned long major; + unsigned long minor; + unsigned long debug; + } version; + LONG version_len; + + _snprintf (device_path, sizeof(device_path), "%s%s%s", + USERMODEDEVICEDIR, + device_guid, + TAPSUFFIX); + + HANDLE handle = CreateFile ( + device_path, + GENERIC_READ | GENERIC_WRITE, + 0, + 0, + OPEN_EXISTING, + FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, + 0 ); + + if (handle == INVALID_HANDLE_VALUE) { + return INVALID_HANDLE_VALUE; + } + + BOOL bret = DeviceIoControl(handle, TAP_IOCTL_GET_VERSION, + &version, sizeof (version), + &version, sizeof (version), (LPDWORD)&version_len, NULL); + + if (bret == FALSE) { + CloseHandle(handle); + return INVALID_HANDLE_VALUE; + } + + if (!TAPSetStatus(handle, TRUE)) { + return INVALID_HANDLE_VALUE; + } + + return handle; +} + + + +TAPAdapter::TAPAdapter() +{ + htap=TAPOpen(config.Eth+4); + + read.Offset = 0; + read.OffsetHigh = 0; + read.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + + write.Offset = 0; + write.OffsetHigh = 0; + write.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + + +} + +bool TAPAdapter::blocks() +{ + return true; //we use blocking io +} +u8 broadcast_adddrrrr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; +//gets a packet.rv :true success +bool TAPAdapter::recv(NetPacket* pkt) +{ + DWORD read_size; + BOOL result = ReadFile(htap, + pkt->buffer, + sizeof(pkt->buffer), + &read_size, + &read); + + if (!result) { + DWORD dwError = GetLastError(); + if (dwError == ERROR_IO_PENDING) + { + WaitForSingleObject(read.hEvent, INFINITE); + result = GetOverlappedResult( htap, &read, + &read_size, FALSE); + if (!result) + { + + } + } + else { + + } + } + + + if (result) + { + if((memcmp(pkt->buffer,dev9.eeprom,6)!=0)&&(memcmp(pkt->buffer,&broadcast_adddrrrr,6)!=0)) + { + //ignore strange packets + return false; + } + + if(memcmp(pkt->buffer+6,dev9.eeprom,6)==0) + { + //avoid pcap looping packets + return false; + } + pkt->size=read_size; + return true; + } + else + return false; +} +//sends the packet .rv :true success +bool TAPAdapter::send(NetPacket* pkt) +{ + DWORD writen; + BOOL result = WriteFile(htap, + pkt->buffer, + pkt->size, + &writen, + &write); + + if (!result) { + DWORD dwError = GetLastError(); + if (dwError == ERROR_IO_PENDING) + { + WaitForSingleObject(write.hEvent, INFINITE); + result = GetOverlappedResult( htap, &write, + &writen, FALSE); + if (!result) + { + + } + } + else { + + } + } + + if (result) + { + if (writen!=pkt->size) + return false; + + return true; + } + else + return false; +} +TAPAdapter::~TAPAdapter() +{ + CloseHandle(read.hEvent); + CloseHandle(write.hEvent); + TAPSetStatus(htap, FALSE); + CloseHandle(htap); +} + +//i leave these for reference, in case we need msth :p +#if 0==666 +//====================== +// Compile time configuration +//====================== + +//#define DEBUG_TAP_WIN32 1 + +#define TUN_ASYNCHRONOUS_WRITES 1 + +#define TUN_BUFFER_SIZE 1560 +#define TUN_MAX_BUFFER_COUNT 32 + +/* + * The data member "buffer" must be the first element in the tun_buffer + * structure. See the function, tap_win32_free_buffer. + */ +typedef struct tun_buffer_s { + unsigned char buffer [TUN_BUFFER_SIZE]; + unsigned long read_size; + struct tun_buffer_s* next; +} tun_buffer_t; + +typedef struct tap_win32_overlapped { + HANDLE handle; + HANDLE read_event; + HANDLE write_event; + HANDLE output_queue_semaphore; + HANDLE free_list_semaphore; + HANDLE tap_semaphore; + CRITICAL_SECTION output_queue_cs; + CRITICAL_SECTION free_list_cs; + OVERLAPPED read_overlapped; + OVERLAPPED write_overlapped; + tun_buffer_t buffers[TUN_MAX_BUFFER_COUNT]; + tun_buffer_t* free_list; + tun_buffer_t* output_queue_front; + tun_buffer_t* output_queue_back; +} tap_win32_overlapped_t; + +static tap_win32_overlapped_t tap_overlapped; + +static tun_buffer_t* get_buffer_from_free_list(tap_win32_overlapped_t* const overlapped) +{ + tun_buffer_t* buffer = NULL; + WaitForSingleObject(overlapped->free_list_semaphore, INFINITE); + EnterCriticalSection(&overlapped->free_list_cs); + buffer = overlapped->free_list; +// assert(buffer != NULL); + overlapped->free_list = buffer->next; + LeaveCriticalSection(&overlapped->free_list_cs); + buffer->next = NULL; + return buffer; +} + +static void put_buffer_on_free_list(tap_win32_overlapped_t* const overlapped, tun_buffer_t* const buffer) +{ + EnterCriticalSection(&overlapped->free_list_cs); + buffer->next = overlapped->free_list; + overlapped->free_list = buffer; + LeaveCriticalSection(&overlapped->free_list_cs); + ReleaseSemaphore(overlapped->free_list_semaphore, 1, NULL); +} + +static tun_buffer_t* get_buffer_from_output_queue(tap_win32_overlapped_t* const overlapped, const int block) +{ + tun_buffer_t* buffer = NULL; + DWORD result, timeout = block ? INFINITE : 0L; + + // Non-blocking call + result = WaitForSingleObject(overlapped->output_queue_semaphore, timeout); + + switch (result) + { + // The semaphore object was signaled. + case WAIT_OBJECT_0: + EnterCriticalSection(&overlapped->output_queue_cs); + + buffer = overlapped->output_queue_front; + overlapped->output_queue_front = buffer->next; + + if(overlapped->output_queue_front == NULL) { + overlapped->output_queue_back = NULL; + } + + LeaveCriticalSection(&overlapped->output_queue_cs); + break; + + // Semaphore was nonsignaled, so a time-out occurred. + case WAIT_TIMEOUT: + // Cannot open another window. + break; + } + + return buffer; +} + +static tun_buffer_t* get_buffer_from_output_queue_immediate (tap_win32_overlapped_t* const overlapped) +{ + return get_buffer_from_output_queue(overlapped, 0); +} + +static void put_buffer_on_output_queue(tap_win32_overlapped_t* const overlapped, tun_buffer_t* const buffer) +{ + EnterCriticalSection(&overlapped->output_queue_cs); + + if(overlapped->output_queue_front == NULL && overlapped->output_queue_back == NULL) { + overlapped->output_queue_front = overlapped->output_queue_back = buffer; + } else { + buffer->next = NULL; + overlapped->output_queue_back->next = buffer; + overlapped->output_queue_back = buffer; + } + + LeaveCriticalSection(&overlapped->output_queue_cs); + + ReleaseSemaphore(overlapped->output_queue_semaphore, 1, NULL); +} + + +static int is_tap_win32_dev(const char *guid) +{ + HKEY netcard_key; + LONG status; + DWORD len; + int i = 0; + + status = RegOpenKeyEx( + HKEY_LOCAL_MACHINE, + ADAPTER_KEY, + 0, + KEY_READ, + &netcard_key); + + if (status != ERROR_SUCCESS) { + return FALSE; + } + + for (;;) { + char enum_name[256]; + char unit_string[256]; + HKEY unit_key; + char component_id_string[] = "ComponentId"; + char component_id[256]; + char net_cfg_instance_id_string[] = "NetCfgInstanceId"; + char net_cfg_instance_id[256]; + DWORD data_type; + + len = sizeof (enum_name); + status = RegEnumKeyEx( + netcard_key, + i, + enum_name, + &len, + NULL, + NULL, + NULL, + NULL); + + if (status == ERROR_NO_MORE_ITEMS) + break; + else if (status != ERROR_SUCCESS) { + return FALSE; + } + + _snprintf(unit_string, sizeof(unit_string), "%s\\%s", + ADAPTER_KEY, enum_name); + + status = RegOpenKeyEx( + HKEY_LOCAL_MACHINE, + unit_string, + 0, + KEY_READ, + &unit_key); + + if (status != ERROR_SUCCESS) { + return FALSE; + } else { + len = sizeof (component_id); + status = RegQueryValueEx( + unit_key, + component_id_string, + NULL, + &data_type, + (LPBYTE)component_id, + &len); + + if (!(status != ERROR_SUCCESS || data_type != REG_SZ)) { + len = sizeof (net_cfg_instance_id); + status = RegQueryValueEx( + unit_key, + net_cfg_instance_id_string, + NULL, + &data_type, + (LPBYTE)net_cfg_instance_id, + &len); + + if (status == ERROR_SUCCESS && data_type == REG_SZ) { + if (/* !strcmp (component_id, TAP_COMPONENT_ID) &&*/ + !strcmp (net_cfg_instance_id, guid)) { + RegCloseKey (unit_key); + RegCloseKey (netcard_key); + return TRUE; + } + } + } + RegCloseKey (unit_key); + } + ++i; + } + + RegCloseKey (netcard_key); + return FALSE; +} + +static int get_device_guid( + char *name, + int name_size, + char *actual_name, + int actual_name_size) +{ + LONG status; + HKEY control_net_key; + DWORD len; + int i = 0; + int stop = 0; + + status = RegOpenKeyEx( + HKEY_LOCAL_MACHINE, + NETWORK_CONNECTIONS_KEY, + 0, + KEY_READ, + &control_net_key); + + if (status != ERROR_SUCCESS) { + return -1; + } + + while (!stop) + { + char enum_name[256]; + char connection_string[256]; + HKEY connection_key; + char name_data[256]; + DWORD name_type; + const char name_string[] = "Name"; + + len = sizeof (enum_name); + status = RegEnumKeyEx( + control_net_key, + i, + enum_name, + &len, + NULL, + NULL, + NULL, + NULL); + + if (status == ERROR_NO_MORE_ITEMS) + break; + else if (status != ERROR_SUCCESS) { + return -1; + } + + _snprintf(connection_string, + sizeof(connection_string), + "%s\\%s\\Connection", + NETWORK_CONNECTIONS_KEY, enum_name); + + status = RegOpenKeyEx( + HKEY_LOCAL_MACHINE, + connection_string, + 0, + KEY_READ, + &connection_key); + + if (status == ERROR_SUCCESS) { + len = sizeof (name_data); + status = RegQueryValueEx( + connection_key, + name_string, + NULL, + &name_type, + (LPBYTE)name_data, + &len); + + if (status != ERROR_SUCCESS || name_type != REG_SZ) { + return -1; + } + else { + if (is_tap_win32_dev(enum_name)) { + _snprintf(name, name_size, "%s", enum_name); + if (actual_name) { + if (strcmp(actual_name, "") != 0) { + if (strcmp(name_data, actual_name) != 0) { + RegCloseKey (connection_key); + ++i; + continue; + } + } + else { + _snprintf(actual_name, actual_name_size, "%s", name_data); + } + } + stop = 1; + } + } + + RegCloseKey (connection_key); + } + ++i; + } + + RegCloseKey (control_net_key); + + if (stop == 0) + return -1; + + return 0; +} + + + +static void tap_win32_overlapped_init(tap_win32_overlapped_t* const overlapped, const HANDLE handle) +{ + overlapped->handle = handle; + + overlapped->read_event = CreateEvent(NULL, FALSE, FALSE, NULL); + overlapped->write_event = CreateEvent(NULL, FALSE, FALSE, NULL); + + overlapped->read_overlapped.Offset = 0; + overlapped->read_overlapped.OffsetHigh = 0; + overlapped->read_overlapped.hEvent = overlapped->read_event; + + overlapped->write_overlapped.Offset = 0; + overlapped->write_overlapped.OffsetHigh = 0; + overlapped->write_overlapped.hEvent = overlapped->write_event; + + InitializeCriticalSection(&overlapped->output_queue_cs); + InitializeCriticalSection(&overlapped->free_list_cs); + + overlapped->output_queue_semaphore = CreateSemaphore( + NULL, // default security attributes + 0, // initial count + TUN_MAX_BUFFER_COUNT, // maximum count + NULL); // unnamed semaphore + + if(!overlapped->output_queue_semaphore) { + fprintf(stderr, "error creating output queue semaphore!\n"); + } + + overlapped->free_list_semaphore = CreateSemaphore( + NULL, // default security attributes + TUN_MAX_BUFFER_COUNT, // initial count + TUN_MAX_BUFFER_COUNT, // maximum count + NULL); // unnamed semaphore + + if(!overlapped->free_list_semaphore) { + fprintf(stderr, "error creating free list semaphore!\n"); + } + + overlapped->free_list = overlapped->output_queue_front = overlapped->output_queue_back = NULL; + + { + unsigned index; + for(index = 0; index < TUN_MAX_BUFFER_COUNT; index++) { + tun_buffer_t* element = &overlapped->buffers[index]; + element->next = overlapped->free_list; + overlapped->free_list = element; + } + } + /* To count buffers, initially no-signal. */ + overlapped->tap_semaphore = CreateSemaphore(NULL, 0, TUN_MAX_BUFFER_COUNT, NULL); + if(!overlapped->tap_semaphore) + fprintf(stderr, "error creating tap_semaphore.\n"); +} + +static int tap_win32_write(tap_win32_overlapped_t *overlapped, + const void *buffer, unsigned long size) +{ + unsigned long write_size; + BOOL result; + DWORD error; + + result = GetOverlappedResult( overlapped->handle, &overlapped->write_overlapped, + &write_size, FALSE); + + if (!result && GetLastError() == ERROR_IO_INCOMPLETE) + WaitForSingleObject(overlapped->write_event, INFINITE); + + result = WriteFile(overlapped->handle, buffer, size, + &write_size, &overlapped->write_overlapped); + + if (!result) { + switch (error = GetLastError()) + { + case ERROR_IO_PENDING: +#ifndef TUN_ASYNCHRONOUS_WRITES + WaitForSingleObject(overlapped->write_event, INFINITE); +#endif + break; + default: + return -1; + } + } + + return 0; +} + +static DWORD WINAPI tap_win32_thread_entry(LPVOID param) +{ + tap_win32_overlapped_t *overlapped = (tap_win32_overlapped_t*)param; + unsigned long read_size; + BOOL result; + DWORD dwError; + tun_buffer_t* buffer = get_buffer_from_free_list(overlapped); + + + for (;;) { + result = ReadFile(overlapped->handle, + buffer->buffer, + sizeof(buffer->buffer), + &read_size, + &overlapped->read_overlapped); + if (!result) { + dwError = GetLastError(); + if (dwError == ERROR_IO_PENDING) { + WaitForSingleObject(overlapped->read_event, INFINITE); + result = GetOverlappedResult( overlapped->handle, &overlapped->read_overlapped, + &read_size, FALSE); + if (!result) { +#if DEBUG_TAP_WIN32 + LPVOID lpBuffer; + dwError = GetLastError(); + FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) & lpBuffer, 0, NULL ); + fprintf(stderr, "Tap-Win32: Error GetOverlappedResult %d - %s\n", dwError, lpBuffer); + LocalFree( lpBuffer ); +#endif + } + } else { +#if DEBUG_TAP_WIN32 + LPVOID lpBuffer; + FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) & lpBuffer, 0, NULL ); + fprintf(stderr, "Tap-Win32: Error ReadFile %d - %s\n", dwError, lpBuffer); + LocalFree( lpBuffer ); +#endif + } + } + + if(read_size > 0) { + buffer->read_size = read_size; + put_buffer_on_output_queue(overlapped, buffer); + ReleaseSemaphore(overlapped->tap_semaphore, 1, NULL); + buffer = get_buffer_from_free_list(overlapped); + } + } + + return 0; +} + +typedef unsigned __int8 uint8_t; + +static int tap_win32_read(tap_win32_overlapped_t *overlapped, + uint8_t **pbuf, int max_size) +{ + int size = 0; + + tun_buffer_t* buffer = get_buffer_from_output_queue_immediate(overlapped); + + if(buffer != NULL) { + *pbuf = buffer->buffer; + size = (int)buffer->read_size; + if(size > max_size) { + size = max_size; + } + } + + return size; +} + +static void tap_win32_free_buffer(tap_win32_overlapped_t *overlapped, + char* pbuf) +{ + tun_buffer_t* buffer = (tun_buffer_t*)pbuf; + put_buffer_on_free_list(overlapped, buffer); +} + +static int tap_win32_open(tap_win32_overlapped_t **phandle, + const char *prefered_name) +{ + char device_path[256]; + char device_guid[0x100]; + int rc; + HANDLE handle; + BOOL bret; + char name_buffer[0x100] = {0, }; + struct { + unsigned long major; + unsigned long minor; + unsigned long debug; + } version; + LONG version_len; + DWORD idThread; + HANDLE hThread; + + if (prefered_name != NULL) + _snprintf(name_buffer, sizeof(name_buffer), "%s", prefered_name); + + rc = get_device_guid(device_guid, sizeof(device_guid), name_buffer, sizeof(name_buffer)); + if (rc) + return -1; + + _snprintf (device_path, sizeof(device_path), "%s%s%s", + USERMODEDEVICEDIR, + device_guid, + TAPSUFFIX); + + handle = CreateFile ( + device_path, + GENERIC_READ | GENERIC_WRITE, + 0, + 0, + OPEN_EXISTING, + FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, + 0 ); + + if (handle == INVALID_HANDLE_VALUE) { + return -1; + } + + bret = DeviceIoControl(handle, TAP_IOCTL_GET_VERSION, + &version, sizeof (version), + &version, sizeof (version), (LPDWORD)&version_len, NULL); + + if (bret == FALSE) { + CloseHandle(handle); + return -1; + } + + if (!tap_win32_set_status(handle, TRUE)) { + return -1; + } + + tap_win32_overlapped_init(&tap_overlapped, handle); + + *phandle = &tap_overlapped; + + hThread = CreateThread(NULL, 0, tap_win32_thread_entry, + (LPVOID)&tap_overlapped, 0, &idThread); + return 0; +} + +/********************************************/ + + typedef struct TAPState { + tap_win32_overlapped_t *handle; + } TAPState; + +static void tap_receive(void *opaque, const uint8_t *buf, int size) +{ + TAPState *s = (TAPState *)opaque; + + tap_win32_write(s->handle, buf, size); +} + +static void tap_win32_send(void *opaque) +{ + TAPState *s = (TAPState *)opaque; + uint8_t *buf; + int max_size = 4096; + int size; + + size = tap_win32_read(s->handle, &buf, max_size); + if (size > 0) { + //qemu_send_packet(s->vc, buf, size); + tap_win32_free_buffer(s->handle, (char*)buf); + } +} + +int tap_win32_init(const char *ifname) +{ + TAPState *s = (TAPState *)malloc(sizeof(TAPState)); + if (!s) + return -1; + + memset(s,0,sizeof(TAPState)); + + if (tap_win32_open(&s->handle, ifname) < 0) { + printf("tap: Could not open '%s'\n", ifname); + return -1; + } + + return 0; +} + +#endif diff --git a/plugins/dev9ghzdrk/Win32/tap.h b/plugins/dev9ghzdrk/Win32/tap.h new file mode 100644 index 000000000..82c3c4f41 --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/tap.h @@ -0,0 +1,24 @@ +#pragma once +#include +#include "net.h" +using namespace std; + +struct tap_adapter +{ + string name; + string guid; +}; +vector* GetTapAdapters(); +class TAPAdapter : public NetAdapter +{ + HANDLE htap; + OVERLAPPED read,write; +public: + TAPAdapter(); + virtual bool blocks(); + //gets a packet.rv :true success + virtual bool recv(NetPacket* pkt); + //sends the packet and deletes it when done (if successful).rv :true success + virtual bool send(NetPacket* pkt); + virtual ~TAPAdapter(); +}; \ No newline at end of file diff --git a/plugins/dev9ghzdrk/Win32/vl.h b/plugins/dev9ghzdrk/Win32/vl.h new file mode 100644 index 000000000..618519fca --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/vl.h @@ -0,0 +1,1419 @@ +/* + * QEMU System Emulator header + * + * Copyright (c) 2003 Fabrice Bellard + * + * 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. + */ +#ifndef VL_H +#define VL_H + +/* we put basic includes here to avoid repeating them in device drivers */ +#include +#include +#include +#include +//#include +typedef signed char int8_t; +typedef signed short int16_t; +typedef signed int int32_t; + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; + +//typedef signed long int intptr_t; +//typedef unsigned long int uintptr_t; + +typedef signed long long int64_t; +typedef unsigned long long uint64_t; +typedef signed long long int intmax_t; +typedef unsigned long long int uintmax_t; + + +#include +#include +#include +#include +//#include +#include +#include + +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +#ifndef ENOMEDIUM +#define ENOMEDIUM ENODEV +#endif + +#ifdef _WIN32 +#include +#define fsync _commit +#define lseek _lseeki64 +#define ENOTSUP 4096 +extern int qemu_ftruncate64(int, int64_t); +#define ftruncate qemu_ftruncate64 + + +static inline char *realpath(const char *path, char *resolved_path) +{ + _fullpath(resolved_path, path, _MAX_PATH); + return resolved_path; +} + +#define PRId64 "I64d" +#define PRIx64 "I64x" +#define PRIu64 "I64u" +#define PRIo64 "I64o" +#endif + +#ifdef QEMU_TOOL + +/* we use QEMU_TOOL in the command line tools which do not depend on + the target CPU type */ +#include "config-host.h" +#include +#include "osdep.h" +#include "bswap.h" + +#else + +//#include "audio/audio.h" +//#include "cpu.h" + +#endif /* !defined(QEMU_TOOL) */ + +#ifndef glue +#define xglue(x, y) x ## y +#define glue(x, y) xglue(x, y) +#define stringify(s) tostring(s) +#define tostring(s) #s +#endif + +#ifndef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif +#ifndef MAX +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif + +/* cutils.c */ +void pstrcpy(char *buf, int buf_size, const char *str); +char *pstrcat(char *buf, int buf_size, const char *s); +int strstart(const char *str, const char *val, const char **ptr); +int stristart(const char *str, const char *val, const char **ptr); + +/* vl.c */ +uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c); + +void hw_error(const char *fmt, ...); + +extern const char *bios_dir; + +extern int vm_running; + +typedef struct vm_change_state_entry VMChangeStateEntry; +typedef void VMChangeStateHandler(void *opaque, int running); +typedef void VMStopHandler(void *opaque, int reason); + +VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb, + void *opaque); +void qemu_del_vm_change_state_handler(VMChangeStateEntry *e); + +int qemu_add_vm_stop_handler(VMStopHandler *cb, void *opaque); +void qemu_del_vm_stop_handler(VMStopHandler *cb, void *opaque); + +void vm_start(void); +void vm_stop(int reason); + +typedef void QEMUResetHandler(void *opaque); + +void qemu_register_reset(QEMUResetHandler *func, void *opaque); +void qemu_system_reset_request(void); +void qemu_system_shutdown_request(void); +void qemu_system_powerdown_request(void); +#if !defined(TARGET_SPARC) +// Please implement a power failure function to signal the OS +#define qemu_system_powerdown() do{}while(0) +#else +void qemu_system_powerdown(void); +#endif + +void main_loop_wait(int timeout); + +extern int ram_size; +extern int bios_size; +extern int rtc_utc; +extern int cirrus_vga_enabled; +extern int graphic_width; +extern int graphic_height; +extern int graphic_depth; +extern const char *keyboard_layout; +extern int kqemu_allowed; +extern int win2k_install_hack; +extern int usb_enabled; +extern int smp_cpus; +extern int no_quit; +extern int semihosting_enabled; +extern int autostart; + +#define MAX_OPTION_ROMS 16 +extern const char *option_rom[MAX_OPTION_ROMS]; +extern int nb_option_roms; + +/* XXX: make it dynamic */ +#if defined (TARGET_PPC) || defined (TARGET_SPARC64) +#define BIOS_SIZE ((512 + 32) * 1024) +#elif defined(TARGET_MIPS) +#define BIOS_SIZE (4 * 1024 * 1024) +#else +#define BIOS_SIZE ((256 + 64) * 1024) +#endif + +/* keyboard/mouse support */ + +#define MOUSE_EVENT_LBUTTON 0x01 +#define MOUSE_EVENT_RBUTTON 0x02 +#define MOUSE_EVENT_MBUTTON 0x04 + +typedef void QEMUPutKBDEvent(void *opaque, int keycode); +typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, int buttons_state); + +typedef struct QEMUPutMouseEntry { + QEMUPutMouseEvent *qemu_put_mouse_event; + void *qemu_put_mouse_event_opaque; + int qemu_put_mouse_event_absolute; + char *qemu_put_mouse_event_name; + + /* used internally by qemu for handling mice */ + struct QEMUPutMouseEntry *next; +} QEMUPutMouseEntry; + +void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque); +QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, + void *opaque, int absolute, + const char *name); +void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry); + +void kbd_put_keycode(int keycode); +void kbd_mouse_event(int dx, int dy, int dz, int buttons_state); +int kbd_mouse_is_absolute(void); + +void do_info_mice(void); +void do_mouse_set(int index); + +/* keysym is a unicode code except for special keys (see QEMU_KEY_xxx + constants) */ +#define QEMU_KEY_ESC1(c) ((c) | 0xe100) +#define QEMU_KEY_BACKSPACE 0x007f +#define QEMU_KEY_UP QEMU_KEY_ESC1('A') +#define QEMU_KEY_DOWN QEMU_KEY_ESC1('B') +#define QEMU_KEY_RIGHT QEMU_KEY_ESC1('C') +#define QEMU_KEY_LEFT QEMU_KEY_ESC1('D') +#define QEMU_KEY_HOME QEMU_KEY_ESC1(1) +#define QEMU_KEY_END QEMU_KEY_ESC1(4) +#define QEMU_KEY_PAGEUP QEMU_KEY_ESC1(5) +#define QEMU_KEY_PAGEDOWN QEMU_KEY_ESC1(6) +#define QEMU_KEY_DELETE QEMU_KEY_ESC1(3) + +#define QEMU_KEY_CTRL_UP 0xe400 +#define QEMU_KEY_CTRL_DOWN 0xe401 +#define QEMU_KEY_CTRL_LEFT 0xe402 +#define QEMU_KEY_CTRL_RIGHT 0xe403 +#define QEMU_KEY_CTRL_HOME 0xe404 +#define QEMU_KEY_CTRL_END 0xe405 +#define QEMU_KEY_CTRL_PAGEUP 0xe406 +#define QEMU_KEY_CTRL_PAGEDOWN 0xe407 + +void kbd_put_keysym(int keysym); + +/* async I/O support */ + +typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size); +typedef int IOCanRWHandler(void *opaque); +typedef void IOHandler(void *opaque); + +int qemu_set_fd_handler2(int fd, + IOCanRWHandler *fd_read_poll, + IOHandler *fd_read, + IOHandler *fd_write, + void *opaque); +int qemu_set_fd_handler(int fd, + IOHandler *fd_read, + IOHandler *fd_write, + void *opaque); + +/* Polling handling */ + +/* return TRUE if no sleep should be done afterwards */ +typedef int PollingFunc(void *opaque); + +int qemu_add_polling_cb(PollingFunc *func, void *opaque); +void qemu_del_polling_cb(PollingFunc *func, void *opaque); + +#ifdef _WIN32 +/* Wait objects handling */ +typedef void WaitObjectFunc(void *opaque); + +int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque); +void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque); +#endif + +typedef struct QEMUBH QEMUBH; + +/* character device */ + +#define CHR_EVENT_BREAK 0 /* serial break char */ +#define CHR_EVENT_FOCUS 1 /* focus to this terminal (modal input needed) */ +#define CHR_EVENT_RESET 2 /* new connection established */ + + +#define CHR_IOCTL_SERIAL_SET_PARAMS 1 +typedef struct { + int speed; + int parity; + int data_bits; + int stop_bits; +} QEMUSerialSetParams; + +#define CHR_IOCTL_SERIAL_SET_BREAK 2 + +#define CHR_IOCTL_PP_READ_DATA 3 +#define CHR_IOCTL_PP_WRITE_DATA 4 +#define CHR_IOCTL_PP_READ_CONTROL 5 +#define CHR_IOCTL_PP_WRITE_CONTROL 6 +#define CHR_IOCTL_PP_READ_STATUS 7 + +typedef void IOEventHandler(void *opaque, int event); + +typedef struct CharDriverState { + int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len); + void (*chr_update_read_handler)(struct CharDriverState *s); + int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg); + IOEventHandler *chr_event; + IOCanRWHandler *chr_can_read; + IOReadHandler *chr_read; + void *handler_opaque; + void (*chr_send_event)(struct CharDriverState *chr, int event); + void (*chr_close)(struct CharDriverState *chr); + void *opaque; + QEMUBH *bh; +} CharDriverState; + +CharDriverState *qemu_chr_open(const char *filename); +void qemu_chr_printf(CharDriverState *s, const char *fmt, ...); +int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len); +void qemu_chr_send_event(CharDriverState *s, int event); +void qemu_chr_add_handlers(CharDriverState *s, + IOCanRWHandler *fd_can_read, + IOReadHandler *fd_read, + IOEventHandler *fd_event, + void *opaque); +int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg); +void qemu_chr_reset(CharDriverState *s); +int qemu_chr_can_read(CharDriverState *s); +void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len); + +/* consoles */ + +typedef struct DisplayState DisplayState; +typedef struct TextConsole TextConsole; + +typedef void (*vga_hw_update_ptr)(void *); +typedef void (*vga_hw_invalidate_ptr)(void *); +typedef void (*vga_hw_screen_dump_ptr)(void *, const char *); + +TextConsole *graphic_console_init(DisplayState *ds, vga_hw_update_ptr update, + vga_hw_invalidate_ptr invalidate, + vga_hw_screen_dump_ptr screen_dump, + void *opaque); +void vga_hw_update(void); +void vga_hw_invalidate(void); +void vga_hw_screen_dump(const char *filename); + +int is_graphic_console(void); +CharDriverState *text_console_init(DisplayState *ds); +void console_select(unsigned int index); + +/* serial ports */ + +#define MAX_SERIAL_PORTS 4 + +extern CharDriverState *serial_hds[MAX_SERIAL_PORTS]; + +/* parallel ports */ + +#define MAX_PARALLEL_PORTS 3 + +extern CharDriverState *parallel_hds[MAX_PARALLEL_PORTS]; + +/* VLANs support */ + +typedef struct VLANClientState VLANClientState; + +struct VLANClientState { + IOReadHandler *fd_read; + /* Packets may still be sent if this returns zero. It's used to + rate-limit the slirp code. */ + IOCanRWHandler *fd_can_read; + void *opaque; + struct VLANClientState *next; + struct VLANState *vlan; + char info_str[256]; +}; + +typedef struct VLANState { + int id; + VLANClientState *first_client; + struct VLANState *next; +} VLANState; + +VLANState *qemu_find_vlan(int id); +VLANClientState *qemu_new_vlan_client(VLANState *vlan, + IOReadHandler *fd_read, + IOCanRWHandler *fd_can_read, + void *opaque); +int qemu_can_send_packet(VLANClientState *vc); +void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size); +void qemu_handler_true(void *opaque); + +void do_info_network(void); + +/* TAP win32 */ +int tap_win32_init(VLANState *vlan, const char *ifname); + +/* NIC info */ + +#define MAX_NICS 8 + +typedef struct NICInfo { + uint8_t macaddr[6]; + const char *model; + VLANState *vlan; +} NICInfo; + +extern int nb_nics; +extern NICInfo nd_table[MAX_NICS]; + +/* timers */ + +typedef struct QEMUClock QEMUClock; +typedef struct QEMUTimer QEMUTimer; +typedef void QEMUTimerCB(void *opaque); + +/* The real time clock should be used only for stuff which does not + change the virtual machine state, as it is run even if the virtual + machine is stopped. The real time clock has a frequency of 1000 + Hz. */ +extern QEMUClock *rt_clock; + +/* The virtual clock is only run during the emulation. It is stopped + when the virtual machine is stopped. Virtual timers use a high + precision clock, usually cpu cycles (use ticks_per_sec). */ +extern QEMUClock *vm_clock; + +int64_t qemu_get_clock(QEMUClock *clock); + +QEMUTimer *qemu_new_timer(QEMUClock *clock, QEMUTimerCB *cb, void *opaque); +void qemu_free_timer(QEMUTimer *ts); +void qemu_del_timer(QEMUTimer *ts); +void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time); +int qemu_timer_pending(QEMUTimer *ts); + +extern int64_t ticks_per_sec; +extern int pit_min_timer_count; + +int64_t cpu_get_ticks(void); +void cpu_enable_ticks(void); +void cpu_disable_ticks(void); + +/* VM Load/Save */ + +typedef struct QEMUFile QEMUFile; + +QEMUFile *qemu_fopen(const char *filename, const char *mode); +void qemu_fflush(QEMUFile *f); +void qemu_fclose(QEMUFile *f); +void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size); +void qemu_put_byte(QEMUFile *f, int v); +void qemu_put_be16(QEMUFile *f, unsigned int v); +void qemu_put_be32(QEMUFile *f, unsigned int v); +void qemu_put_be64(QEMUFile *f, uint64_t v); +int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size); +int qemu_get_byte(QEMUFile *f); +unsigned int qemu_get_be16(QEMUFile *f); +unsigned int qemu_get_be32(QEMUFile *f); +uint64_t qemu_get_be64(QEMUFile *f); + +static inline void qemu_put_be64s(QEMUFile *f, const uint64_t *pv) +{ + qemu_put_be64(f, *pv); +} + +static inline void qemu_put_be32s(QEMUFile *f, const uint32_t *pv) +{ + qemu_put_be32(f, *pv); +} + +static inline void qemu_put_be16s(QEMUFile *f, const uint16_t *pv) +{ + qemu_put_be16(f, *pv); +} + +static inline void qemu_put_8s(QEMUFile *f, const uint8_t *pv) +{ + qemu_put_byte(f, *pv); +} + +static inline void qemu_get_be64s(QEMUFile *f, uint64_t *pv) +{ + *pv = qemu_get_be64(f); +} + +static inline void qemu_get_be32s(QEMUFile *f, uint32_t *pv) +{ + *pv = qemu_get_be32(f); +} + +static inline void qemu_get_be16s(QEMUFile *f, uint16_t *pv) +{ + *pv = qemu_get_be16(f); +} + +static inline void qemu_get_8s(QEMUFile *f, uint8_t *pv) +{ + *pv = qemu_get_byte(f); +} + +#if TARGET_LONG_BITS == 64 +#define qemu_put_betl qemu_put_be64 +#define qemu_get_betl qemu_get_be64 +#define qemu_put_betls qemu_put_be64s +#define qemu_get_betls qemu_get_be64s +#else +#define qemu_put_betl qemu_put_be32 +#define qemu_get_betl qemu_get_be32 +#define qemu_put_betls qemu_put_be32s +#define qemu_get_betls qemu_get_be32s +#endif + +int64_t qemu_ftell(QEMUFile *f); +int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence); + +typedef void SaveStateHandler(QEMUFile *f, void *opaque); +typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id); + +int register_savevm(const char *idstr, + int instance_id, + int version_id, + SaveStateHandler *save_state, + LoadStateHandler *load_state, + void *opaque); +void qemu_get_timer(QEMUFile *f, QEMUTimer *ts); +void qemu_put_timer(QEMUFile *f, QEMUTimer *ts); + +void cpu_save(QEMUFile *f, void *opaque); +int cpu_load(QEMUFile *f, void *opaque, int version_id); + +void do_savevm(const char *name); +void do_loadvm(const char *name); +void do_delvm(const char *name); +void do_info_snapshots(void); + +/* bottom halves */ +typedef void QEMUBHFunc(void *opaque); + +QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque); +void qemu_bh_schedule(QEMUBH *bh); +void qemu_bh_cancel(QEMUBH *bh); +void qemu_bh_delete(QEMUBH *bh); +int qemu_bh_poll(void); + +/* block.c */ +typedef struct BlockDriverState BlockDriverState; +typedef struct BlockDriver BlockDriver; + +extern BlockDriver bdrv_raw; +extern BlockDriver bdrv_host_device; +extern BlockDriver bdrv_cow; +extern BlockDriver bdrv_qcow; +extern BlockDriver bdrv_vmdk; +extern BlockDriver bdrv_cloop; +extern BlockDriver bdrv_dmg; +extern BlockDriver bdrv_bochs; +extern BlockDriver bdrv_vpc; +extern BlockDriver bdrv_vvfat; +extern BlockDriver bdrv_qcow2; + +typedef struct BlockDriverInfo { + /* in bytes, 0 if irrelevant */ + int cluster_size; + /* offset at which the VM state can be saved (0 if not possible) */ + int64_t vm_state_offset; +} BlockDriverInfo; + +typedef struct QEMUSnapshotInfo { + char id_str[128]; /* unique snapshot id */ + /* the following fields are informative. They are not needed for + the consistency of the snapshot */ + char name[256]; /* user choosen name */ + uint32_t vm_state_size; /* VM state info size */ + uint32_t date_sec; /* UTC date of the snapshot */ + uint32_t date_nsec; + uint64_t vm_clock_nsec; /* VM clock relative to boot */ +} QEMUSnapshotInfo; + +#define BDRV_O_RDONLY 0x0000 +#define BDRV_O_RDWR 0x0002 +#define BDRV_O_ACCESS 0x0003 +#define BDRV_O_CREAT 0x0004 /* create an empty file */ +#define BDRV_O_SNAPSHOT 0x0008 /* open the file read only and save writes in a snapshot */ +#define BDRV_O_FILE 0x0010 /* open as a raw file (do not try to + use a disk image format on top of + it (default for + bdrv_file_open()) */ + +void bdrv_init(void); +BlockDriver *bdrv_find_format(const char *format_name); +int bdrv_create(BlockDriver *drv, + const char *filename, int64_t size_in_sectors, + const char *backing_file, int flags); +BlockDriverState *bdrv_new(const char *device_name); +void bdrv_delete(BlockDriverState *bs); +int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags); +int bdrv_open(BlockDriverState *bs, const char *filename, int flags); +int bdrv_open2(BlockDriverState *bs, const char *filename, int flags, + BlockDriver *drv); +void bdrv_close(BlockDriverState *bs); +int bdrv_read(BlockDriverState *bs, int64_t sector_num, + uint8_t *buf, int nb_sectors); +int bdrv_write(BlockDriverState *bs, int64_t sector_num, + const uint8_t *buf, int nb_sectors); +int bdrv_pread(BlockDriverState *bs, int64_t offset, + void *buf, int count); +int bdrv_pwrite(BlockDriverState *bs, int64_t offset, + const void *buf, int count); +int bdrv_truncate(BlockDriverState *bs, int64_t offset); +int64_t bdrv_getlength(BlockDriverState *bs); +void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr); +int bdrv_commit(BlockDriverState *bs); +void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size); +/* async block I/O */ +typedef struct BlockDriverAIOCB BlockDriverAIOCB; +typedef void BlockDriverCompletionFunc(void *opaque, int ret); + +BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num, + uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque); +BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num, + const uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque); +void bdrv_aio_cancel(BlockDriverAIOCB *acb); + +void qemu_aio_init(void); +void qemu_aio_poll(void); +void qemu_aio_flush(void); +void qemu_aio_wait_start(void); +void qemu_aio_wait(void); +void qemu_aio_wait_end(void); + +/* Ensure contents are flushed to disk. */ +void bdrv_flush(BlockDriverState *bs); + +#define BDRV_TYPE_HD 0 +#define BDRV_TYPE_CDROM 1 +#define BDRV_TYPE_FLOPPY 2 +#define BIOS_ATA_TRANSLATION_AUTO 0 +#define BIOS_ATA_TRANSLATION_NONE 1 +#define BIOS_ATA_TRANSLATION_LBA 2 +#define BIOS_ATA_TRANSLATION_LARGE 3 +#define BIOS_ATA_TRANSLATION_RECHS 4 + +void bdrv_set_geometry_hint(BlockDriverState *bs, + int cyls, int heads, int secs); +void bdrv_set_type_hint(BlockDriverState *bs, int type); +void bdrv_set_translation_hint(BlockDriverState *bs, int translation); +void bdrv_get_geometry_hint(BlockDriverState *bs, + int *pcyls, int *pheads, int *psecs); +int bdrv_get_type_hint(BlockDriverState *bs); +int bdrv_get_translation_hint(BlockDriverState *bs); +int bdrv_is_removable(BlockDriverState *bs); +int bdrv_is_read_only(BlockDriverState *bs); +int bdrv_is_inserted(BlockDriverState *bs); +int bdrv_media_changed(BlockDriverState *bs); +int bdrv_is_locked(BlockDriverState *bs); +void bdrv_set_locked(BlockDriverState *bs, int locked); +void bdrv_eject(BlockDriverState *bs, int eject_flag); +void bdrv_set_change_cb(BlockDriverState *bs, + void (*change_cb)(void *opaque), void *opaque); +void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size); +void bdrv_info(void); +BlockDriverState *bdrv_find(const char *name); +void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque); +int bdrv_is_encrypted(BlockDriverState *bs); +int bdrv_set_key(BlockDriverState *bs, const char *key); +void bdrv_iterate_format(void (*it)(void *opaque, const char *name), + void *opaque); +const char *bdrv_get_device_name(BlockDriverState *bs); +int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num, + const uint8_t *buf, int nb_sectors); +int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi); + +void bdrv_get_backing_filename(BlockDriverState *bs, + char *filename, int filename_size); +int bdrv_snapshot_create(BlockDriverState *bs, + QEMUSnapshotInfo *sn_info); +int bdrv_snapshot_goto(BlockDriverState *bs, + const char *snapshot_id); +int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id); +int bdrv_snapshot_list(BlockDriverState *bs, + QEMUSnapshotInfo **psn_info); +char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn); + +char *get_human_readable_size(char *buf, int buf_size, int64_t size); +int path_is_absolute(const char *path); +void path_combine(char *dest, int dest_size, + const char *base_path, + const char *filename); + +#ifndef QEMU_TOOL + +typedef void QEMUMachineInitFunc(int ram_size, int vga_ram_size, + int boot_device, + DisplayState *ds, const char **fd_filename, int snapshot, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename); + +typedef struct QEMUMachine { + const char *name; + const char *desc; + QEMUMachineInitFunc *init; + struct QEMUMachine *next; +} QEMUMachine; + +int qemu_register_machine(QEMUMachine *m); + +typedef void SetIRQFunc(void *opaque, int irq_num, int level); +typedef void IRQRequestFunc(void *opaque, int level); + +#ifdef ASDDasdasda0011 +/* ISA bus */ + +extern target_phys_addr_t isa_mem_base; + +typedef void (IOPortWriteFunc)(void *opaque, uint32_t address, uint32_t data); +typedef uint32_t (IOPortReadFunc)(void *opaque, uint32_t address); + +int register_ioport_read(int start, int length, int size, + IOPortReadFunc *func, void *opaque); +int register_ioport_write(int start, int length, int size, + IOPortWriteFunc *func, void *opaque); +void isa_unassign_ioport(int start, int length); + +void isa_mmio_init(target_phys_addr_t base, target_phys_addr_t size); + +/* PCI bus */ + +extern target_phys_addr_t pci_mem_base; + +typedef struct PCIBus PCIBus; +typedef struct PCIDevice PCIDevice; + +typedef void PCIConfigWriteFunc(PCIDevice *pci_dev, + uint32_t address, uint32_t data, int len); +typedef uint32_t PCIConfigReadFunc(PCIDevice *pci_dev, + uint32_t address, int len); +typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num, + uint32_t addr, uint32_t size, int type); + +#define PCI_ADDRESS_SPACE_MEM 0x00 +#define PCI_ADDRESS_SPACE_IO 0x01 +#define PCI_ADDRESS_SPACE_MEM_PREFETCH 0x08 + +typedef struct PCIIORegion { + uint32_t addr; /* current PCI mapping address. -1 means not mapped */ + uint32_t size; + uint8_t type; + PCIMapIORegionFunc *map_func; +} PCIIORegion; + +#define PCI_ROM_SLOT 6 +#define PCI_NUM_REGIONS 7 + +#define PCI_DEVICES_MAX 64 + +#define PCI_VENDOR_ID 0x00 /* 16 bits */ +#define PCI_DEVICE_ID 0x02 /* 16 bits */ +#define PCI_COMMAND 0x04 /* 16 bits */ +#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */ +#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */ +#define PCI_CLASS_DEVICE 0x0a /* Device class */ +#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */ +#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */ +#define PCI_MIN_GNT 0x3e /* 8 bits */ +#define PCI_MAX_LAT 0x3f /* 8 bits */ + +struct PCIDevice { + /* PCI config space */ + uint8_t config[256]; + + /* the following fields are read only */ + PCIBus *bus; + int devfn; + char name[64]; + PCIIORegion io_regions[PCI_NUM_REGIONS]; + + /* do not access the following fields */ + PCIConfigReadFunc *config_read; + PCIConfigWriteFunc *config_write; + /* ??? This is a PC-specific hack, and should be removed. */ + int irq_index; + + /* Current IRQ levels. Used internally by the generic PCI code. */ + int irq_state[4]; +}; + +PCIDevice *pci_register_device(PCIBus *bus, const char *name, + int instance_size, int devfn, + PCIConfigReadFunc *config_read, + PCIConfigWriteFunc *config_write); + +void pci_register_io_region(PCIDevice *pci_dev, int region_num, + uint32_t size, int type, + PCIMapIORegionFunc *map_func); + +void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level); + +uint32_t pci_default_read_config(PCIDevice *d, + uint32_t address, int len); +void pci_default_write_config(PCIDevice *d, + uint32_t address, uint32_t val, int len); +void pci_device_save(PCIDevice *s, QEMUFile *f); +int pci_device_load(PCIDevice *s, QEMUFile *f); + +typedef void (*pci_set_irq_fn)(void *pic, int irq_num, int level); +typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num); +PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, + void *pic, int devfn_min, int nirq); + +void pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn); +void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len); +uint32_t pci_data_read(void *opaque, uint32_t addr, int len); +int pci_bus_num(PCIBus *s); +void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d)); + +void pci_info(void); +PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id, + pci_map_irq_fn map_irq, const char *name); + +/* prep_pci.c */ +PCIBus *pci_prep_init(void); + +/* grackle_pci.c */ +PCIBus *pci_grackle_init(uint32_t base, void *pic); + +/* unin_pci.c */ +PCIBus *pci_pmac_init(void *pic); + +/* apb_pci.c */ +PCIBus *pci_apb_init(target_ulong special_base, target_ulong mem_base, + void *pic); + +PCIBus *pci_vpb_init(void *pic, int irq, int realview); + +/* piix_pci.c */ +PCIBus *i440fx_init(PCIDevice **pi440fx_state); +void i440fx_set_smm(PCIDevice *d, int val); +int piix3_init(PCIBus *bus, int devfn); +void i440fx_init_memory_mappings(PCIDevice *d); + +int piix4_init(PCIBus *bus, int devfn); + +/* openpic.c */ +typedef struct openpic_t openpic_t; +void openpic_set_irq(void *opaque, int n_IRQ, int level); +openpic_t *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus, + CPUState **envp); + +/* heathrow_pic.c */ +typedef struct HeathrowPICS HeathrowPICS; +void heathrow_pic_set_irq(void *opaque, int num, int level); +HeathrowPICS *heathrow_pic_init(int *pmem_index); + +/* gt64xxx.c */ +PCIBus *pci_gt64120_init(void *pic); + +#ifdef HAS_AUDIO +struct soundhw { + const char *name; + const char *descr; + int enabled; + int isa; + union { + int (*init_isa) (AudioState *s); + int (*init_pci) (PCIBus *bus, AudioState *s); + } init; +}; + +extern struct soundhw soundhw[]; +#endif + +/* vga.c */ + +#define VGA_RAM_SIZE (8192 * 1024) + +struct DisplayState { + uint8_t *data; + int linesize; + int depth; + int bgr; /* BGR color order instead of RGB. Only valid for depth == 32 */ + int width; + int height; + void *opaque; + + void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h); + void (*dpy_resize)(struct DisplayState *s, int w, int h); + void (*dpy_refresh)(struct DisplayState *s); + void (*dpy_copy)(struct DisplayState *s, int src_x, int src_y, int dst_x, int dst_y, int w, int h); +}; + +static inline void dpy_update(DisplayState *s, int x, int y, int w, int h) +{ + s->dpy_update(s, x, y, w, h); +} + +static inline void dpy_resize(DisplayState *s, int w, int h) +{ + s->dpy_resize(s, w, h); +} + +int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base, + unsigned long vga_ram_offset, int vga_ram_size); +int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, + unsigned long vga_ram_offset, int vga_ram_size, + unsigned long vga_bios_offset, int vga_bios_size); + +/* cirrus_vga.c */ +void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, + unsigned long vga_ram_offset, int vga_ram_size); +void isa_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base, + unsigned long vga_ram_offset, int vga_ram_size); + +/* sdl.c */ +void sdl_display_init(DisplayState *ds, int full_screen); + +/* cocoa.m */ +void cocoa_display_init(DisplayState *ds, int full_screen); + +/* vnc.c */ +void vnc_display_init(DisplayState *ds, const char *display); +void do_info_vnc(void); + +/* x_keymap.c */ +extern uint8_t _translate_keycode(const int key); + +/* ide.c */ +#define MAX_DISKS 4 + +extern BlockDriverState *bs_table[MAX_DISKS + 1]; + +void isa_ide_init(int iobase, int iobase2, int irq, + BlockDriverState *hd0, BlockDriverState *hd1); +void pci_cmd646_ide_init(PCIBus *bus, BlockDriverState **hd_table, + int secondary_ide_enabled); +void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn); +int pmac_ide_init (BlockDriverState **hd_table, + SetIRQFunc *set_irq, void *irq_opaque, int irq); + +/* cdrom.c */ +int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track); +int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num); + +/* es1370.c */ +int es1370_init (PCIBus *bus, AudioState *s); + +/* sb16.c */ +int SB16_init (AudioState *s); + +/* adlib.c */ +int Adlib_init (AudioState *s); + +/* gus.c */ +int GUS_init (AudioState *s); + +/* dma.c */ +typedef int (*DMA_transfer_handler) (void *opaque, int nchan, int pos, int size); +int DMA_get_channel_mode (int nchan); +int DMA_read_memory (int nchan, void *buf, int pos, int size); +int DMA_write_memory (int nchan, void *buf, int pos, int size); +void DMA_hold_DREQ (int nchan); +void DMA_release_DREQ (int nchan); +void DMA_schedule(int nchan); +void DMA_run (void); +void DMA_init (int high_page_enable); +void DMA_register_channel (int nchan, + DMA_transfer_handler transfer_handler, + void *opaque); +/* fdc.c */ +#define MAX_FD 2 +extern BlockDriverState *fd_table[MAX_FD]; + +typedef struct fdctrl_t fdctrl_t; + +fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped, + uint32_t io_base, + BlockDriverState **fds); +int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num); + +/* ne2000.c */ + +void isa_ne2000_init(int base, int irq, NICInfo *nd); +void pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn); + +/* rtl8139.c */ + +void pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn); + +/* pcnet.c */ + +void pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn); +void pcnet_h_reset(void *opaque); +void *lance_init(NICInfo *nd, uint32_t leaddr, void *dma_opaque); + + +/* pckbd.c */ + +void kbd_init(void); + +/* mc146818rtc.c */ + +typedef struct RTCState RTCState; + +RTCState *rtc_init(int base, int irq); +void rtc_set_memory(RTCState *s, int addr, int val); +void rtc_set_date(RTCState *s, const struct tm *tm); + +/* serial.c */ + +typedef struct SerialState SerialState; +SerialState *serial_init(SetIRQFunc *set_irq, void *opaque, + int base, int irq, CharDriverState *chr); +SerialState *serial_mm_init (SetIRQFunc *set_irq, void *opaque, + target_ulong base, int it_shift, + int irq, CharDriverState *chr); + +/* parallel.c */ + +typedef struct ParallelState ParallelState; +ParallelState *parallel_init(int base, int irq, CharDriverState *chr); + +/* i8259.c */ + +typedef struct PicState2 PicState2; +extern PicState2 *isa_pic; +void pic_set_irq(int irq, int level); +void pic_set_irq_new(void *opaque, int irq, int level); +PicState2 *pic_init(IRQRequestFunc *irq_request, void *irq_request_opaque); +void pic_set_alt_irq_func(PicState2 *s, SetIRQFunc *alt_irq_func, + void *alt_irq_opaque); +int pic_read_irq(PicState2 *s); +void pic_update_irq(PicState2 *s); +uint32_t pic_intack_read(PicState2 *s); +void pic_info(void); +void irq_info(void); + +/* APIC */ +typedef struct IOAPICState IOAPICState; + +int apic_init(CPUState *env); +int apic_get_interrupt(CPUState *env); +IOAPICState *ioapic_init(void); +void ioapic_set_irq(void *opaque, int vector, int level); + +/* i8254.c */ + +#define PIT_FREQ 1193182 + +typedef struct PITState PITState; + +PITState *pit_init(int base, int irq); +void pit_set_gate(PITState *pit, int channel, int val); +int pit_get_gate(PITState *pit, int channel); +int pit_get_initial_count(PITState *pit, int channel); +int pit_get_mode(PITState *pit, int channel); +int pit_get_out(PITState *pit, int channel, int64_t current_time); + +/* pcspk.c */ +void pcspk_init(PITState *); +int pcspk_audio_init(AudioState *); + +#include "hw/smbus.h" + +/* acpi.c */ +extern int acpi_enabled; +void piix4_pm_init(PCIBus *bus, int devfn); +void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr); +void acpi_bios_init(void); + +/* smbus_eeprom.c */ +SMBusDevice *smbus_eeprom_device_init(uint8_t addr, uint8_t *buf); + +/* pc.c */ +extern QEMUMachine pc_machine; +extern QEMUMachine isapc_machine; +extern int fd_bootchk; + +void ioport_set_a20(int enable); +int ioport_get_a20(void); + +/* ppc.c */ +extern QEMUMachine prep_machine; +extern QEMUMachine core99_machine; +extern QEMUMachine heathrow_machine; + +/* mips_r4k.c */ +extern QEMUMachine mips_machine; + +/* mips_malta.c */ +extern QEMUMachine mips_malta_machine; + +/* mips_int */ +extern void cpu_mips_irq_request(void *opaque, int irq, int level); + +/* mips_timer.c */ +extern void cpu_mips_clock_init(CPUState *); +extern void cpu_mips_irqctrl_init (void); + +/* shix.c */ +extern QEMUMachine shix_machine; + +#ifdef TARGET_PPC +ppc_tb_t *cpu_ppc_tb_init (CPUState *env, uint32_t freq); +#endif +void PREP_debug_write (void *opaque, uint32_t addr, uint32_t val); + +extern CPUWriteMemoryFunc *PPC_io_write[]; +extern CPUReadMemoryFunc *PPC_io_read[]; +void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val); + +/* sun4m.c */ +extern QEMUMachine sun4m_machine; +void pic_set_irq_cpu(int irq, int level, unsigned int cpu); + +/* iommu.c */ +void *iommu_init(uint32_t addr); +void sparc_iommu_memory_rw(void *opaque, target_phys_addr_t addr, + uint8_t *buf, int len, int is_write); +static inline void sparc_iommu_memory_read(void *opaque, + target_phys_addr_t addr, + uint8_t *buf, int len) +{ + sparc_iommu_memory_rw(opaque, addr, buf, len, 0); +} + +static inline void sparc_iommu_memory_write(void *opaque, + target_phys_addr_t addr, + uint8_t *buf, int len) +{ + sparc_iommu_memory_rw(opaque, addr, buf, len, 1); +} + +/* tcx.c */ +void tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base, + unsigned long vram_offset, int vram_size, int width, int height); + +/* slavio_intctl.c */ +void *slavio_intctl_init(); +void slavio_intctl_set_cpu(void *opaque, unsigned int cpu, CPUState *env); +void slavio_pic_info(void *opaque); +void slavio_irq_info(void *opaque); +void slavio_pic_set_irq(void *opaque, int irq, int level); +void slavio_pic_set_irq_cpu(void *opaque, int irq, int level, unsigned int cpu); + +/* loader.c */ +int get_image_size(const char *filename); +int load_image(const char *filename, uint8_t *addr); +int load_elf(const char *filename, int64_t virt_to_phys_addend, uint64_t *pentry); +int load_aout(const char *filename, uint8_t *addr); + +/* slavio_timer.c */ +void slavio_timer_init(uint32_t addr, int irq, int mode, unsigned int cpu); + +/* slavio_serial.c */ +SerialState *slavio_serial_init(int base, int irq, CharDriverState *chr1, CharDriverState *chr2); +void slavio_serial_ms_kbd_init(int base, int irq); + +/* slavio_misc.c */ +void *slavio_misc_init(uint32_t base, int irq); +void slavio_set_power_fail(void *opaque, int power_failing); + +/* esp.c */ +void esp_scsi_attach(void *opaque, BlockDriverState *bd, int id); +void *esp_init(BlockDriverState **bd, uint32_t espaddr, void *dma_opaque); +void esp_reset(void *opaque); + +/* sparc32_dma.c */ +void *sparc32_dma_init(uint32_t daddr, int espirq, int leirq, void *iommu, + void *intctl); +void ledma_set_irq(void *opaque, int isr); +void ledma_memory_read(void *opaque, target_phys_addr_t addr, + uint8_t *buf, int len, int do_bswap); +void ledma_memory_write(void *opaque, target_phys_addr_t addr, + uint8_t *buf, int len, int do_bswap); +void espdma_raise_irq(void *opaque); +void espdma_clear_irq(void *opaque); +void espdma_memory_read(void *opaque, uint8_t *buf, int len); +void espdma_memory_write(void *opaque, uint8_t *buf, int len); +void sparc32_dma_set_reset_data(void *opaque, void *esp_opaque, + void *lance_opaque); + +/* cs4231.c */ +void cs_init(target_phys_addr_t base, int irq, void *intctl); + +/* sun4u.c */ +extern QEMUMachine sun4u_machine; + +/* NVRAM helpers */ +#include "hw/m48t59.h" + +void NVRAM_set_byte (m48t59_t *nvram, uint32_t addr, uint8_t value); +uint8_t NVRAM_get_byte (m48t59_t *nvram, uint32_t addr); +void NVRAM_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value); +uint16_t NVRAM_get_word (m48t59_t *nvram, uint32_t addr); +void NVRAM_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value); +uint32_t NVRAM_get_lword (m48t59_t *nvram, uint32_t addr); +void NVRAM_set_string (m48t59_t *nvram, uint32_t addr, + const unsigned char *str, uint32_t max); +int NVRAM_get_string (m48t59_t *nvram, uint8_t *dst, uint16_t addr, int max); +void NVRAM_set_crc (m48t59_t *nvram, uint32_t addr, + uint32_t start, uint32_t count); +int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size, + const unsigned char *arch, + uint32_t RAM_size, int boot_device, + uint32_t kernel_image, uint32_t kernel_size, + const char *cmdline, + uint32_t initrd_image, uint32_t initrd_size, + uint32_t NVRAM_image, + int width, int height, int depth); + +/* adb.c */ + +#define MAX_ADB_DEVICES 16 + +#define ADB_MAX_OUT_LEN 16 + +typedef struct ADBDevice ADBDevice; + +/* buf = NULL means polling */ +typedef int ADBDeviceRequest(ADBDevice *d, uint8_t *buf_out, + const uint8_t *buf, int len); +typedef int ADBDeviceReset(ADBDevice *d); + +struct ADBDevice { + struct ADBBusState *bus; + int devaddr; + int handler; + ADBDeviceRequest *devreq; + ADBDeviceReset *devreset; + void *opaque; +}; + +typedef struct ADBBusState { + ADBDevice devices[MAX_ADB_DEVICES]; + int nb_devices; + int poll_index; +} ADBBusState; + +int adb_request(ADBBusState *s, uint8_t *buf_out, + const uint8_t *buf, int len); +int adb_poll(ADBBusState *s, uint8_t *buf_out); + +ADBDevice *adb_register_device(ADBBusState *s, int devaddr, + ADBDeviceRequest *devreq, + ADBDeviceReset *devreset, + void *opaque); +void adb_kbd_init(ADBBusState *bus); +void adb_mouse_init(ADBBusState *bus); + +/* cuda.c */ + +extern ADBBusState adb_bus; +int cuda_init(SetIRQFunc *set_irq, void *irq_opaque, int irq); + +#include "hw/usb.h" + +/* usb ports of the VM */ + +void qemu_register_usb_port(USBPort *port, void *opaque, int index, + usb_attachfn attach); + +#define VM_USB_HUB_SIZE 8 + +void do_usb_add(const char *devname); +void do_usb_del(const char *devname); +void usb_info(void); + +/* scsi-disk.c */ +enum scsi_reason { + SCSI_REASON_DONE, /* Command complete. */ + SCSI_REASON_DATA /* Transfer complete, more data required. */ +}; + +typedef struct SCSIDevice SCSIDevice; +typedef void (*scsi_completionfn)(void *opaque, int reason, uint32_t tag, + uint32_t arg); + +SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, + int tcq, + scsi_completionfn completion, + void *opaque); +void scsi_disk_destroy(SCSIDevice *s); + +int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun); +/* SCSI data transfers are asynchrnonous. However, unlike the block IO + layer the completion routine may be called directly by + scsi_{read,write}_data. */ +void scsi_read_data(SCSIDevice *s, uint32_t tag); +int scsi_write_data(SCSIDevice *s, uint32_t tag); +void scsi_cancel_io(SCSIDevice *s, uint32_t tag); +uint8_t *scsi_get_buf(SCSIDevice *s, uint32_t tag); + +/* lsi53c895a.c */ +void lsi_scsi_attach(void *opaque, BlockDriverState *bd, int id); +void *lsi_scsi_init(PCIBus *bus, int devfn); + +/* integratorcp.c */ +extern QEMUMachine integratorcp926_machine; +extern QEMUMachine integratorcp1026_machine; + +/* versatilepb.c */ +extern QEMUMachine versatilepb_machine; +extern QEMUMachine versatileab_machine; + +/* realview.c */ +extern QEMUMachine realview_machine; + +/* ps2.c */ +void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg); +void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg); +void ps2_write_mouse(void *, int val); +void ps2_write_keyboard(void *, int val); +uint32_t ps2_read_data(void *); +void ps2_queue(void *, int b); +void ps2_keyboard_set_translation(void *opaque, int mode); + +/* smc91c111.c */ +void smc91c111_init(NICInfo *, uint32_t, void *, int); + +/* pl110.c */ +void *pl110_init(DisplayState *ds, uint32_t base, void *pic, int irq, int); + +/* pl011.c */ +void pl011_init(uint32_t base, void *pic, int irq, CharDriverState *chr); + +/* pl050.c */ +void pl050_init(uint32_t base, void *pic, int irq, int is_mouse); + +/* pl080.c */ +void *pl080_init(uint32_t base, void *pic, int irq, int nchannels); + +/* pl190.c */ +void *pl190_init(uint32_t base, void *parent, int irq, int fiq); + +/* arm-timer.c */ +void sp804_init(uint32_t base, void *pic, int irq); +void icp_pit_init(uint32_t base, void *pic, int irq); + +/* arm_sysctl.c */ +void arm_sysctl_init(uint32_t base, uint32_t sys_id); + +/* arm_gic.c */ +void *arm_gic_init(uint32_t base, void *parent, int parent_irq); + +/* arm_boot.c */ + +void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename, + const char *kernel_cmdline, const char *initrd_filename, + int board_id); + +/* sh7750.c */ +struct SH7750State; + +struct SH7750State *sh7750_init(CPUState * cpu); + +typedef struct { + /* The callback will be triggered if any of the designated lines change */ + uint16_t portamask_trigger; + uint16_t portbmask_trigger; + /* Return 0 if no action was taken */ + int (*port_change_cb) (uint16_t porta, uint16_t portb, + uint16_t * periph_pdtra, + uint16_t * periph_portdira, + uint16_t * periph_pdtrb, + uint16_t * periph_portdirb); +} sh7750_io_device; + +int sh7750_register_io_device(struct SH7750State *s, + sh7750_io_device * device); +/* tc58128.c */ +int tc58128_init(struct SH7750State *s, char *zone1, char *zone2); + +/* NOR flash devices */ +typedef struct pflash_t pflash_t; + +pflash_t *pflash_register (target_ulong base, ram_addr_t off, + BlockDriverState *bs, + target_ulong sector_len, int nb_blocs, int width, + uint16_t id0, uint16_t id1, + uint16_t id2, uint16_t id3); + +#include "gdbstub.h" + +#endif /* defined(QEMU_TOOL) */ + +/* monitor.c */ +void monitor_init(CharDriverState *hd, int show_banner); +void term_puts(const char *str); +void term_vprintf(const char *fmt, va_list ap); +void term_printf(const char *fmt, ...); +void term_print_filename(const char *filename); +void term_flush(void); +void term_print_help(void); +void monitor_readline(const char *prompt, int is_password, + char *buf, int buf_size); + +/* readline.c */ +typedef void ReadLineFunc(void *opaque, const char *str); + +extern int completion_index; +void add_completion(const char *str); +void readline_handle_byte(int ch); +void readline_find_completion(const char *cmdline); +const char *readline_get_history(unsigned int index); +void readline_start(const char *prompt, int is_password, + ReadLineFunc *readline_func, void *opaque); + +void kqemu_record_dump(void); +#endif + +#endif /* VL_H */ diff --git a/plugins/dev9ghzdrk/bittypes.h b/plugins/dev9ghzdrk/bittypes.h new file mode 100644 index 000000000..558a0b5c0 --- /dev/null +++ b/plugins/dev9ghzdrk/bittypes.h @@ -0,0 +1,137 @@ +/* + * Copyright (C) 1999 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _BITTYPES_H +#define _BITTYPES_H + +#ifndef HAVE_U_INT8_T + +#if SIZEOF_CHAR == 1 +typedef unsigned char u_int8_t; +typedef signed char int8_t; +#elif SIZEOF_INT == 1 +typedef unsigned int u_int8_t; +typedef signed int int8_t; +#else /* XXX */ +#error "there's no appropriate type for u_int8_t" +#endif +#define HAVE_U_INT8_T 1 +#define HAVE_INT8_T 1 + +#endif /* HAVE_U_INT8_T */ + +#ifndef HAVE_U_INT16_T + +#if SIZEOF_SHORT == 2 +typedef unsigned short u_int16_t; +typedef signed short int16_t; +#elif SIZEOF_INT == 2 +typedef unsigned int u_int16_t; +typedef signed int int16_t; +#elif SIZEOF_CHAR == 2 +typedef unsigned char u_int16_t; +typedef signed char int16_t; +#else /* XXX */ +#error "there's no appropriate type for u_int16_t" +#endif +#define HAVE_U_INT16_T 1 +#define HAVE_INT16_T 1 + +#endif /* HAVE_U_INT16_T */ + +#ifndef HAVE_U_INT32_T + +#if SIZEOF_INT == 4 +typedef unsigned int u_int32_t; +typedef signed int int32_t; +#elif SIZEOF_LONG == 4 +typedef unsigned long u_int32_t; +typedef signed long int32_t; +#elif SIZEOF_SHORT == 4 +typedef unsigned short u_int32_t; +typedef signed short int32_t; +#else /* XXX */ +#error "there's no appropriate type for u_int32_t" +#endif +#define HAVE_U_INT32_T 1 +#define HAVE_INT32_T 1 + +#endif /* HAVE_U_INT32_T */ + +#ifndef HAVE_U_INT64_T +#if SIZEOF_LONG_LONG == 8 +typedef unsigned long long u_int64_t; +typedef long long int64_t; +#elif defined(_MSC_EXTENSIONS) +typedef unsigned _int64 u_int64_t; +typedef _int64 int64_t; +#elif SIZEOF_INT == 8 +typedef unsigned int u_int64_t; +#elif SIZEOF_LONG == 8 +typedef unsigned long u_int64_t; +#elif SIZEOF_SHORT == 8 +typedef unsigned short u_int64_t; +#else /* XXX */ +#error "there's no appropriate type for u_int64_t" +#endif + +#endif /* HAVE_U_INT64_T */ + +#ifndef PRId64 +#ifdef _MSC_EXTENSIONS +#define PRId64 "I64d" +#else /* _MSC_EXTENSIONS */ +#define PRId64 "lld" +#endif /* _MSC_EXTENSIONS */ +#endif /* PRId64 */ + +#ifndef PRIo64 +#ifdef _MSC_EXTENSIONS +#define PRIo64 "I64o" +#else /* _MSC_EXTENSIONS */ +#define PRIo64 "llo" +#endif /* _MSC_EXTENSIONS */ +#endif /* PRIo64 */ + +#ifndef PRIx64 +#ifdef _MSC_EXTENSIONS +#define PRIx64 "I64x" +#else /* _MSC_EXTENSIONS */ +#define PRIx64 "llx" +#endif /* _MSC_EXTENSIONS */ +#endif /* PRIx64 */ + +#ifndef PRIu64 +#ifdef _MSC_EXTENSIONS +#define PRIu64 "I64u" +#else /* _MSC_EXTENSIONS */ +#define PRIu64 "llu" +#endif /* _MSC_EXTENSIONS */ +#endif /* PRIu64 */ + +#endif /* _BITTYPES_H */ diff --git a/plugins/dev9ghzdrk/flash.cpp b/plugins/dev9ghzdrk/flash.cpp new file mode 100644 index 000000000..0a4f2a2f2 --- /dev/null +++ b/plugins/dev9ghzdrk/flash.cpp @@ -0,0 +1,249 @@ +// The code has been designed for 64Mb flash and uses as file support the second memory card +#include +#include +#include "DEV9.h" + +#define PAGE_SIZE_BITS 9 +#define PAGE_SIZE (1<>2), page+PAGE_SIZE+0*3);//(ECC_SIZE>>2)); + xfromman_call20_calculateXors(page + 1*(PAGE_SIZE>>2), page+PAGE_SIZE+1*3);//(ECC_SIZE>>2)); + xfromman_call20_calculateXors(page + 2*(PAGE_SIZE>>2), page+PAGE_SIZE+2*3);//(ECC_SIZE>>2)); + xfromman_call20_calculateXors(page + 3*(PAGE_SIZE>>2), page+PAGE_SIZE+3*3);//(ECC_SIZE>>2)); +} + +static char* getCmdName(u32 cmd){ + switch(cmd) { + case SM_CMD_READ1: return "READ1"; + case SM_CMD_READ2: return "READ2"; + case SM_CMD_READ3: return "READ3"; + case SM_CMD_RESET: return "RESET"; + case SM_CMD_WRITEDATA: return "WRITEDATA"; + case SM_CMD_PROGRAMPAGE: return "PROGRAMPAGE"; + case SM_CMD_ERASEBLOCK: return "ERASEBLOCK"; + case SM_CMD_ERASECONFIRM: return "ERASECONFIRM"; + case SM_CMD_GETSTATUS: return "GETSTATUS"; + case SM_CMD_READID: return "READID"; + default: return "unknown"; + } +} + +void CALLBACK FLASHinit(){ + FILE *fd; + + id= FLASH_ID_64MBIT; + counter= 0; + addrbyte= 0; + + address = 0; + memset(data, 0xFF, PAGE_SIZE); + calculateECC(data); + ctrl = FLASH_PP_READY; + + if (fd=fopen("flash.dat", "rb")){ + fread(file, 1, CARD_SIZE_ECC, fd); + fclose(fd); + }else + memset(file, 0xFF, CARD_SIZE_ECC); +} + +u32 CALLBACK FLASHread32(u32 addr, int size) { + u32 value, refill= 0; + + switch(addr) { + case FLASH_R_DATA: + memcpy(&value, &data[counter], size); + counter += size; + DEV9_LOG("*FLASH DATA %dbit read 0x%08lX %s\n", size*8, value, (ctrl & FLASH_PP_READ) ? "READ_ENABLE" : "READ_DISABLE"); + if (cmd == SM_CMD_READ3){ + if (counter >= PAGE_SIZE_ECC){ + counter= PAGE_SIZE; + refill= 1; + } + }else{ + if ( (ctrl & FLASH_PP_NOECC) && (counter >= PAGE_SIZE)){ + counter %= PAGE_SIZE; + refill= 1; + }else + if (!(ctrl & FLASH_PP_NOECC) && (counter >= PAGE_SIZE_ECC)){ + counter %= PAGE_SIZE_ECC; + refill= 1; + } + } + + if (refill){ + ctrl &= ~FLASH_PP_READY; + address += PAGE_SIZE; + address %= CARD_SIZE; + memcpy(data, file+(address>>PAGE_SIZE_BITS)*PAGE_SIZE_ECC, PAGE_SIZE); + calculateECC(data); // calculate ECC; should be in the file already + ctrl |= FLASH_PP_READY; + } + + return value; + + case FLASH_R_CMD: + DEV9_LOG("*FLASH CMD %dbit read %s DENIED\n", size*8, getCmdName(cmd)); + return cmd; + + case FLASH_R_ADDR: + DEV9_LOG("*FLASH ADDR %dbit read DENIED\n", size*8); + return 0; + + case FLASH_R_CTRL: + DEV9_LOG("*FLASH CTRL %dbit read 0x%08lX\n", size*8, ctrl); + return ctrl; + + case FLASH_R_ID: + if (cmd == SM_CMD_READID){ + DEV9_LOG("*FLASH ID %dbit read 0x%08lX\n", size*8, id); + return id;//0x98=Toshiba/0xEC=Samsung maker code should be returned first + }else + if (cmd == SM_CMD_GETSTATUS){ + value= 0x80 | ((ctrl & 1) << 6); // 0:0=pass, 6:ready/busy, 7:1=not protected + DEV9_LOG("*FLASH STATUS %dbit read 0x%08lX\n", size*8, value); + return value; + }//else fall off + + default: + DEV9_LOG("*FLASH Unkwnown %dbit read at address %lx\n", size*8, addr); + return 0; + } +} + +void CALLBACK FLASHwrite32(u32 addr, u32 value, int size) { + + switch(addr & 0x1FFFFFFF) { + case FLASH_R_DATA: + + DEV9_LOG("*FLASH DATA %dbit write 0x%08lX %s\n", size*8, value, (ctrl & FLASH_PP_WRITE) ? "WRITE_ENABLE" : "WRITE_DISABLE"); + memcpy(&data[counter], &value, size); + counter += size; + counter %= PAGE_SIZE_ECC;//should not get past the last byte, but at the end + break; + + case FLASH_R_CMD: + if (!(ctrl & FLASH_PP_READY)){ + if ((value != SM_CMD_GETSTATUS) && (value != SM_CMD_RESET)){ + DEV9_LOG("*FLASH CMD %dbit write %s ILLEGAL in busy mode - IGNORED\n", size*8, getCmdName(value)); + break; + } + } + if (cmd == SM_CMD_WRITEDATA){ + if ((value != SM_CMD_PROGRAMPAGE) && (value != SM_CMD_RESET)){ + DEV9_LOG("*FLASH CMD %dbit write %s ILLEGAL after WRITEDATA cmd - IGNORED\n", size*8, getCmdName(value)); + ctrl &= ~FLASH_PP_READY;//go busy, reset is needed + break; + } + } + DEV9_LOG("*FLASH CMD %dbit write %s\n", size*8, getCmdName(value)); + switch (value){ // A8 bit is encoded in READ cmd;) + case SM_CMD_READ1: counter= 0; if (cmd != SM_CMD_GETSTATUS) address= counter; addrbyte= 0; break; + case SM_CMD_READ2: counter= PAGE_SIZE/2; if (cmd != SM_CMD_GETSTATUS) address= counter; addrbyte= 0; break; + case SM_CMD_READ3: counter= PAGE_SIZE; if (cmd != SM_CMD_GETSTATUS) address= counter; addrbyte= 0; break; + case SM_CMD_RESET: FLASHinit(); break; + case SM_CMD_WRITEDATA: counter= 0; address= counter; addrbyte= 0; break; + case SM_CMD_ERASEBLOCK: counter= 0; memset(data, 0xFF, PAGE_SIZE); address= counter; addrbyte= 1; break; + case SM_CMD_PROGRAMPAGE: //fall + case SM_CMD_ERASECONFIRM: + ctrl &= ~FLASH_PP_READY; + calculateECC(data); + memcpy(file+(address/PAGE_SIZE)*PAGE_SIZE_ECC, data, PAGE_SIZE_ECC); + /*write2file*/ + ctrl |= FLASH_PP_READY; break; + case SM_CMD_GETSTATUS: break; + case SM_CMD_READID: counter= 0; address= counter; addrbyte= 0; break; + default: + ctrl &= ~FLASH_PP_READY; + return;//ignore any other command; go busy, reset is needed + } + cmd= value; + break; + + case FLASH_R_ADDR: + DEV9_LOG("*FLASH ADDR %dbit write 0x%08lX\n", size*8, value); + address |= (value & 0xFF) << (addrbyte == 0 ? 0 : (1 + 8 * addrbyte)); + addrbyte++; + DEV9_LOG("*FLASH ADDR = 0x%08lX (addrbyte=%d)\n", address, addrbyte); + if (!(value & 0x100)){ // address is complete + if ((cmd == SM_CMD_READ1) || (cmd == SM_CMD_READ2) || (cmd == SM_CMD_READ3)) { + ctrl &= ~FLASH_PP_READY; + memcpy(data, file+(address>>PAGE_SIZE_BITS)*PAGE_SIZE_ECC, PAGE_SIZE); + calculateECC(data); // calculate ECC; should be in the file already + ctrl |= FLASH_PP_READY; + } + addrbyte= 0; // address reset + { + u32 bytes, pages, blocks; + + blocks = address / BLOCK_SIZE; + pages = address-(blocks*BLOCK_SIZE); + bytes = pages % PAGE_SIZE; + pages = pages / PAGE_SIZE; + DEV9_LOG("*FLASH ADDR = 0x%08lX (%d:%d:%d) (addrbyte=%d) FINAL\n", address, blocks, pages, bytes, addrbyte); + } + } + break; + + case FLASH_R_CTRL: + DEV9_LOG("*FLASH CTRL %dbit write 0x%08lX\n", size*8, value); + ctrl = (ctrl & FLASH_PP_READY) | (value & ~FLASH_PP_READY); + break; + + case FLASH_R_ID: + DEV9_LOG("*FLASH ID %dbit write 0x%08lX DENIED :P\n", size*8, value); + break; + + default: + DEV9_LOG("*FLASH Unkwnown %dbit write at address 0x%08lX= 0x%08lX IGNORED\n", size*8, addr, value); + break; + } +} + +static unsigned char xor_table[256]={ + 0x00, 0x87, 0x96, 0x11, 0xA5, 0x22, 0x33, 0xB4, 0xB4, 0x33, 0x22, 0xA5, 0x11, 0x96, 0x87, 0x00, + 0xC3, 0x44, 0x55, 0xD2, 0x66, 0xE1, 0xF0, 0x77, 0x77, 0xF0, 0xE1, 0x66, 0xD2, 0x55, 0x44, 0xC3, + 0xD2, 0x55, 0x44, 0xC3, 0x77, 0xF0, 0xE1, 0x66, 0x66, 0xE1, 0xF0, 0x77, 0xC3, 0x44, 0x55, 0xD2, + 0x11, 0x96, 0x87, 0x00, 0xB4, 0x33, 0x22, 0xA5, 0xA5, 0x22, 0x33, 0xB4, 0x00, 0x87, 0x96, 0x11, + 0xE1, 0x66, 0x77, 0xF0, 0x44, 0xC3, 0xD2, 0x55, 0x55, 0xD2, 0xC3, 0x44, 0xF0, 0x77, 0x66, 0xE1, + 0x22, 0xA5, 0xB4, 0x33, 0x87, 0x00, 0x11, 0x96, 0x96, 0x11, 0x00, 0x87, 0x33, 0xB4, 0xA5, 0x22, + 0x33, 0xB4, 0xA5, 0x22, 0x96, 0x11, 0x00, 0x87, 0x87, 0x00, 0x11, 0x96, 0x22, 0xA5, 0xB4, 0x33, + 0xF0, 0x77, 0x66, 0xE1, 0x55, 0xD2, 0xC3, 0x44, 0x44, 0xC3, 0xD2, 0x55, 0xE1, 0x66, 0x77, 0xF0, + 0xF0, 0x77, 0x66, 0xE1, 0x55, 0xD2, 0xC3, 0x44, 0x44, 0xC3, 0xD2, 0x55, 0xE1, 0x66, 0x77, 0xF0, + 0x33, 0xB4, 0xA5, 0x22, 0x96, 0x11, 0x00, 0x87, 0x87, 0x00, 0x11, 0x96, 0x22, 0xA5, 0xB4, 0x33, + 0x22, 0xA5, 0xB4, 0x33, 0x87, 0x00, 0x11, 0x96, 0x96, 0x11, 0x00, 0x87, 0x33, 0xB4, 0xA5, 0x22, + 0xE1, 0x66, 0x77, 0xF0, 0x44, 0xC3, 0xD2, 0x55, 0x55, 0xD2, 0xC3, 0x44, 0xF0, 0x77, 0x66, 0xE1, + 0x11, 0x96, 0x87, 0x00, 0xB4, 0x33, 0x22, 0xA5, 0xA5, 0x22, 0x33, 0xB4, 0x00, 0x87, 0x96, 0x11, + 0xD2, 0x55, 0x44, 0xC3, 0x77, 0xF0, 0xE1, 0x66, 0x66, 0xE1, 0xF0, 0x77, 0xC3, 0x44, 0x55, 0xD2, + 0xC3, 0x44, 0x55, 0xD2, 0x66, 0xE1, 0xF0, 0x77, 0x77, 0xF0, 0xE1, 0x66, 0xD2, 0x55, 0x44, 0xC3, + 0x00, 0x87, 0x96, 0x11, 0xA5, 0x22, 0x33, 0xB4, 0xB4, 0x33, 0x22, 0xA5, 0x11, 0x96, 0x87, 0x00}; + +static void xfromman_call20_calculateXors(unsigned char buffer[128], unsigned char xor[4]){ + register unsigned char a=0, b=0, c=0, i; + + for (i=0; i<128; i++){ + a ^= xor_table[buffer[i]]; + if (xor_table[buffer[i]] & 0x80){ + b ^= ~i; + c ^= i; + } + } + + xor[0]=(~a) & 0x77; + xor[1]=(~b) & 0x7F; + xor[2]=(~c) & 0x7F; +} diff --git a/plugins/dev9ghzdrk/ip6_misc.h b/plugins/dev9ghzdrk/ip6_misc.h new file mode 100644 index 000000000..562fa6184 --- /dev/null +++ b/plugins/dev9ghzdrk/ip6_misc.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 1993, 1994, 1997 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header: /tcpdump/master/libpcap/Win32/Include/ip6_misc.h,v 1.5 2006-01-22 18:02:18 gianluca Exp $ (LBL) + */ + +/* + * This file contains a collage of declarations for IPv6 from FreeBSD not present in Windows + */ + +#include + +#include + +#ifndef __MINGW32__ +#define IN_MULTICAST(a) IN_CLASSD(a) +#endif + +#define IN_EXPERIMENTAL(a) ((((u_int32_t) (a)) & 0xf0000000) == 0xf0000000) + +#define IN_LOOPBACKNET 127 + +#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF) +/* IPv6 address */ +struct in6_addr + { + union + { + u_int8_t u6_addr8[16]; + u_int16_t u6_addr16[8]; + u_int32_t u6_addr32[4]; + } in6_u; +#define s6_addr in6_u.u6_addr8 +#define s6_addr16 in6_u.u6_addr16 +#define s6_addr32 in6_u.u6_addr32 +#define s6_addr64 in6_u.u6_addr64 + }; + +#define IN6ADDR_ANY_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } +#define IN6ADDR_LOOPBACK_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } +#endif /* __MINGW32__ */ + + +#if (defined _MSC_VER) || (defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)) +typedef unsigned short sa_family_t; +#endif + + +#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF) + +#define __SOCKADDR_COMMON(sa_prefix) \ + sa_family_t sa_prefix##family + +/* Ditto, for IPv6. */ +struct sockaddr_in6 + { + __SOCKADDR_COMMON (sin6_); + u_int16_t sin6_port; /* Transport layer port # */ + u_int32_t sin6_flowinfo; /* IPv6 flow information */ + struct in6_addr sin6_addr; /* IPv6 address */ + }; + +#define IN6_IS_ADDR_V4MAPPED(a) \ + ((((u_int32_t *) (a))[0] == 0) && (((u_int32_t *) (a))[1] == 0) && \ + (((u_int32_t *) (a))[2] == htonl (0xffff))) + +#define IN6_IS_ADDR_MULTICAST(a) (((u_int8_t *) (a))[0] == 0xff) + +#define IN6_IS_ADDR_LINKLOCAL(a) \ + ((((u_int32_t *) (a))[0] & htonl (0xffc00000)) == htonl (0xfe800000)) + +#define IN6_IS_ADDR_LOOPBACK(a) \ + (((u_int32_t *) (a))[0] == 0 && ((u_int32_t *) (a))[1] == 0 && \ + ((u_int32_t *) (a))[2] == 0 && ((u_int32_t *) (a))[3] == htonl (1)) +#endif /* __MINGW32__ */ + +#define ip6_vfc ip6_ctlun.ip6_un2_vfc +#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow +#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen +#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt +#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim +#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim + +#define nd_rd_type nd_rd_hdr.icmp6_type +#define nd_rd_code nd_rd_hdr.icmp6_code +#define nd_rd_cksum nd_rd_hdr.icmp6_cksum +#define nd_rd_reserved nd_rd_hdr.icmp6_data32[0] + +/* + * IPV6 extension headers + */ +#define IPPROTO_HOPOPTS 0 /* IPv6 hop-by-hop options */ +#define IPPROTO_IPV6 41 /* IPv6 header. */ +#define IPPROTO_ROUTING 43 /* IPv6 routing header */ +#define IPPROTO_FRAGMENT 44 /* IPv6 fragmentation header */ +#define IPPROTO_ESP 50 /* encapsulating security payload */ +#define IPPROTO_AH 51 /* authentication header */ +#define IPPROTO_ICMPV6 58 /* ICMPv6 */ +#define IPPROTO_NONE 59 /* IPv6 no next header */ +#define IPPROTO_DSTOPTS 60 /* IPv6 destination options */ +#define IPPROTO_PIM 103 /* Protocol Independent Multicast. */ + +#define IPV6_RTHDR_TYPE_0 0 + +/* Option types and related macros */ +#define IP6OPT_PAD1 0x00 /* 00 0 00000 */ +#define IP6OPT_PADN 0x01 /* 00 0 00001 */ +#define IP6OPT_JUMBO 0xC2 /* 11 0 00010 = 194 */ +#define IP6OPT_JUMBO_LEN 6 +#define IP6OPT_ROUTER_ALERT 0x05 /* 00 0 00101 */ + +#define IP6OPT_RTALERT_LEN 4 +#define IP6OPT_RTALERT_MLD 0 /* Datagram contains an MLD message */ +#define IP6OPT_RTALERT_RSVP 1 /* Datagram contains an RSVP message */ +#define IP6OPT_RTALERT_ACTNET 2 /* contains an Active Networks msg */ +#define IP6OPT_MINLEN 2 + +#define IP6OPT_BINDING_UPDATE 0xc6 /* 11 0 00110 */ +#define IP6OPT_BINDING_ACK 0x07 /* 00 0 00111 */ +#define IP6OPT_BINDING_REQ 0x08 /* 00 0 01000 */ +#define IP6OPT_HOME_ADDRESS 0xc9 /* 11 0 01001 */ +#define IP6OPT_EID 0x8a /* 10 0 01010 */ + +#define IP6OPT_TYPE(o) ((o) & 0xC0) +#define IP6OPT_TYPE_SKIP 0x00 +#define IP6OPT_TYPE_DISCARD 0x40 +#define IP6OPT_TYPE_FORCEICMP 0x80 +#define IP6OPT_TYPE_ICMP 0xC0 + +#define IP6OPT_MUTABLE 0x20 + + +#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF) +#ifndef EAI_ADDRFAMILY +struct addrinfo { + int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* length of ai_addr */ + char *ai_canonname; /* canonical name for hostname */ + struct sockaddr *ai_addr; /* binary address */ + struct addrinfo *ai_next; /* next structure in linked list */ +}; +#endif +#endif /* __MINGW32__ */ diff --git a/plugins/dev9ghzdrk/pcap-bpf.h b/plugins/dev9ghzdrk/pcap-bpf.h new file mode 100644 index 000000000..5fe129dbb --- /dev/null +++ b/plugins/dev9ghzdrk/pcap-bpf.h @@ -0,0 +1,47 @@ +/*- + * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from the Stanford/CMU enet packet filter, + * (net/enet.c) distributed as part of 4.3BSD, and code contributed + * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence + * Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) $Header: /tcpdump/master/libpcap/pcap-bpf.h,v 1.50 2007/04/01 21:43:55 guy Exp $ (LBL) + */ + +/* + * For backwards compatibility. + * + * Note to OS vendors: do NOT get rid of this file! Some applications + * might expect to be able to include . + */ +#include diff --git a/plugins/dev9ghzdrk/pcap-namedb.h b/plugins/dev9ghzdrk/pcap-namedb.h new file mode 100644 index 000000000..80a2f0040 --- /dev/null +++ b/plugins/dev9ghzdrk/pcap-namedb.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 1994, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Computer Systems + * Engineering Group at Lawrence Berkeley Laboratory. + * 4. Neither the name of the University nor of the Laboratory may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) $Header: /tcpdump/master/libpcap/pcap-namedb.h,v 1.13 2006/10/04 18:13:32 guy Exp $ (LBL) + */ + +/* + * For backwards compatibility. + * + * Note to OS vendors: do NOT get rid of this file! Some applications + * might expect to be able to include . + */ +#include diff --git a/plugins/dev9ghzdrk/pcap-stdinc.h b/plugins/dev9ghzdrk/pcap-stdinc.h new file mode 100644 index 000000000..417604177 --- /dev/null +++ b/plugins/dev9ghzdrk/pcap-stdinc.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy) + * Copyright (c) 2005 - 2009 CACE Technologies, Inc. Davis (California) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Politecnico di Torino nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @(#) $Header: /tcpdump/master/libpcap/pcap-stdinc.h,v 1.10.2.1 2008-10-06 15:38:39 gianluca Exp $ (LBL) + */ + +#define SIZEOF_CHAR 1 +#define SIZEOF_SHORT 2 +#define SIZEOF_INT 4 +#ifndef _MSC_EXTENSIONS +#define SIZEOF_LONG_LONG 8 +#endif + +/* + * Avoids a compiler warning in case this was already defined + * (someone defined _WINSOCKAPI_ when including 'windows.h', in order + * to prevent it from including 'winsock.h') + */ +#ifdef _WINSOCKAPI_ +#undef _WINSOCKAPI_ +#endif +#include + +#include + +#include "bittypes.h" +#include +#include + +#ifndef __MINGW32__ +#include "IP6_misc.h" +#endif + +#define caddr_t char* + +#if _MSC_VER < 1500 +#define snprintf _snprintf +#define vsnprintf _vsnprintf +#define strdup _strdup +#endif + +#define inline __inline + +#ifdef __MINGW32__ +#include +#else /*__MINGW32__*/ +/* MSVC compiler */ +#ifndef _UINTPTR_T_DEFINED +#ifdef _WIN64 +typedef unsigned __int64 uintptr_t; +#else +typedef _W64 unsigned int uintptr_t; +#endif +#define _UINTPTR_T_DEFINED +#endif + +#ifndef _INTPTR_T_DEFINED +#ifdef _WIN64 +typedef __int64 intptr_t; +#else +typedef _W64 int intptr_t; +#endif +#define _INTPTR_T_DEFINED +#endif + +#endif /*__MINGW32__*/ diff --git a/plugins/dev9ghzdrk/pcap.h b/plugins/dev9ghzdrk/pcap.h new file mode 100644 index 000000000..935f9494c --- /dev/null +++ b/plugins/dev9ghzdrk/pcap.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 1993, 1994, 1995, 1996, 1997 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Computer Systems + * Engineering Group at Lawrence Berkeley Laboratory. + * 4. Neither the name of the University nor of the Laboratory may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.59 2006/10/04 18:09:22 guy Exp $ (LBL) + */ + +/* + * For backwards compatibility. + * + * Note to OS vendors: do NOT get rid of this file! Many applications + * expect to be able to include , and at least some of them + * go through contortions in their configure scripts to try to detect + * OSes that have "helpfully" moved pcap.h to without + * leaving behind a file. + */ +#include diff --git a/plugins/dev9ghzdrk/pcap/bluetooth.h b/plugins/dev9ghzdrk/pcap/bluetooth.h new file mode 100644 index 000000000..7bf65df03 --- /dev/null +++ b/plugins/dev9ghzdrk/pcap/bluetooth.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2006 Paolo Abeni (Italy) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * bluetooth data struct + * By Paolo Abeni + * + * @(#) $Header: /tcpdump/master/libpcap/pcap/bluetooth.h,v 1.1 2007/09/22 02:10:17 guy Exp $ + */ + +#ifndef _PCAP_BLUETOOTH_STRUCTS_H__ +#define _PCAP_BLUETOOTH_STRUCTS_H__ + +/* + * Header prepended libpcap to each bluetooth h:4 frame. + * fields are in network byte order + */ +typedef struct _pcap_bluetooth_h4_header { + u_int32_t direction; /* if first bit is set direction is incoming */ +} pcap_bluetooth_h4_header; + + +#endif diff --git a/plugins/dev9ghzdrk/pcap/bpf.h b/plugins/dev9ghzdrk/pcap/bpf.h new file mode 100644 index 000000000..9f4ca33e3 --- /dev/null +++ b/plugins/dev9ghzdrk/pcap/bpf.h @@ -0,0 +1,934 @@ +/*- + * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from the Stanford/CMU enet packet filter, + * (net/enet.c) distributed as part of 4.3BSD, and code contributed + * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence + * Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)bpf.h 7.1 (Berkeley) 5/7/91 + * + * @(#) $Header: /tcpdump/master/libpcap/pcap/bpf.h,v 1.19.2.8 2008-09-22 20:16:01 guy Exp $ (LBL) + */ + +/* + * This is libpcap's cut-down version of bpf.h; it includes only + * the stuff needed for the code generator and the userland BPF + * interpreter, and the libpcap APIs for setting filters, etc.. + * + * "pcap-bpf.c" will include the native OS version, as it deals with + * the OS's BPF implementation. + * + * XXX - should this all just be moved to "pcap.h"? + */ + +#ifndef BPF_MAJOR_VERSION + +#ifdef __cplusplus +extern "C" { +#endif + +/* BSD style release date */ +#define BPF_RELEASE 199606 + +#ifdef MSDOS /* must be 32-bit */ +typedef long bpf_int32; +typedef unsigned long bpf_u_int32; +#else +typedef int bpf_int32; +typedef u_int bpf_u_int32; +#endif + +/* + * Alignment macros. BPF_WORDALIGN rounds up to the next + * even multiple of BPF_ALIGNMENT. + */ +#ifndef __NetBSD__ +#define BPF_ALIGNMENT sizeof(bpf_int32) +#else +#define BPF_ALIGNMENT sizeof(long) +#endif +#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1)) + +#define BPF_MAXBUFSIZE 0x8000 +#define BPF_MINBUFSIZE 32 + +/* + * Structure for "pcap_compile()", "pcap_setfilter()", etc.. + */ +struct bpf_program { + u_int bf_len; + struct bpf_insn *bf_insns; +}; + +/* + * Struct return by BIOCVERSION. This represents the version number of + * the filter language described by the instruction encodings below. + * bpf understands a program iff kernel_major == filter_major && + * kernel_minor >= filter_minor, that is, if the value returned by the + * running kernel has the same major number and a minor number equal + * equal to or less than the filter being downloaded. Otherwise, the + * results are undefined, meaning an error may be returned or packets + * may be accepted haphazardly. + * It has nothing to do with the source code version. + */ +struct bpf_version { + u_short bv_major; + u_short bv_minor; +}; +/* Current version number of filter architecture. */ +#define BPF_MAJOR_VERSION 1 +#define BPF_MINOR_VERSION 1 + +/* + * Data-link level type codes. + * + * Do *NOT* add new values to this list without asking + * "tcpdump-workers@lists.tcpdump.org" for a value. Otherwise, you run + * the risk of using a value that's already being used for some other + * purpose, and of having tools that read libpcap-format captures not + * being able to handle captures with your new DLT_ value, with no hope + * that they will ever be changed to do so (as that would destroy their + * ability to read captures using that value for that other purpose). + */ + +/* + * These are the types that are the same on all platforms, and that + * have been defined by for ages. + */ +#define DLT_NULL 0 /* BSD loopback encapsulation */ +#define DLT_EN10MB 1 /* Ethernet (10Mb) */ +#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */ +#define DLT_AX25 3 /* Amateur Radio AX.25 */ +#define DLT_PRONET 4 /* Proteon ProNET Token Ring */ +#define DLT_CHAOS 5 /* Chaos */ +#define DLT_IEEE802 6 /* 802.5 Token Ring */ +#define DLT_ARCNET 7 /* ARCNET, with BSD-style header */ +#define DLT_SLIP 8 /* Serial Line IP */ +#define DLT_PPP 9 /* Point-to-point Protocol */ +#define DLT_FDDI 10 /* FDDI */ + +/* + * These are types that are different on some platforms, and that + * have been defined by for ages. We use #ifdefs to + * detect the BSDs that define them differently from the traditional + * libpcap + * + * XXX - DLT_ATM_RFC1483 is 13 in BSD/OS, and DLT_RAW is 14 in BSD/OS, + * but I don't know what the right #define is for BSD/OS. + */ +#define DLT_ATM_RFC1483 11 /* LLC-encapsulated ATM */ + +#ifdef __OpenBSD__ +#define DLT_RAW 14 /* raw IP */ +#else +#define DLT_RAW 12 /* raw IP */ +#endif + +/* + * Given that the only OS that currently generates BSD/OS SLIP or PPP + * is, well, BSD/OS, arguably everybody should have chosen its values + * for DLT_SLIP_BSDOS and DLT_PPP_BSDOS, which are 15 and 16, but they + * didn't. So it goes. + */ +#if defined(__NetBSD__) || defined(__FreeBSD__) +#ifndef DLT_SLIP_BSDOS +#define DLT_SLIP_BSDOS 13 /* BSD/OS Serial Line IP */ +#define DLT_PPP_BSDOS 14 /* BSD/OS Point-to-point Protocol */ +#endif +#else +#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */ +#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */ +#endif + +/* + * 17 is used for DLT_OLD_PFLOG in OpenBSD; + * OBSOLETE: DLT_PFLOG is 117 in OpenBSD now as well. See below. + * 18 is used for DLT_PFSYNC in OpenBSD; don't use it for anything else. + */ + +#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */ + +/* + * Apparently Redback uses this for its SmartEdge 400/800. I hope + * nobody else decided to use it, too. + */ +#define DLT_REDBACK_SMARTEDGE 32 + +/* + * These values are defined by NetBSD; other platforms should refrain from + * using them for other purposes, so that NetBSD savefiles with link + * types of 50 or 51 can be read as this type on all platforms. + */ +#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */ +#define DLT_PPP_ETHER 51 /* PPP over Ethernet */ + +/* + * The Axent Raptor firewall - now the Symantec Enterprise Firewall - uses + * a link-layer type of 99 for the tcpdump it supplies. The link-layer + * header has 6 bytes of unknown data, something that appears to be an + * Ethernet type, and 36 bytes that appear to be 0 in at least one capture + * I've seen. + */ +#define DLT_SYMANTEC_FIREWALL 99 + +/* + * Values between 100 and 103 are used in capture file headers as + * link-layer types corresponding to DLT_ types that differ + * between platforms; don't use those values for new DLT_ new types. + */ + +/* + * This value was defined by libpcap 0.5; platforms that have defined + * it with a different value should define it here with that value - + * a link type of 104 in a save file will be mapped to DLT_C_HDLC, + * whatever value that happens to be, so programs will correctly + * handle files with that link type regardless of the value of + * DLT_C_HDLC. + * + * The name DLT_C_HDLC was used by BSD/OS; we use that name for source + * compatibility with programs written for BSD/OS. + * + * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well, + * for source compatibility with programs written for libpcap 0.5. + */ +#define DLT_C_HDLC 104 /* Cisco HDLC */ +#define DLT_CHDLC DLT_C_HDLC + +#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */ + +/* + * 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW, + * except when it isn't. (I.e., sometimes it's just raw IP, and + * sometimes it isn't.) We currently handle it as DLT_LINUX_SLL, + * so that we don't have to worry about the link-layer header.) + */ + +/* + * Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides + * with other values. + * DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header + * (DLCI, etc.). + */ +#define DLT_FRELAY 107 + +/* + * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except + * that the AF_ type in the link-layer header is in network byte order. + * + * DLT_LOOP is 12 in OpenBSD, but that's DLT_RAW in other OSes, so + * we don't use 12 for it in OSes other than OpenBSD. + */ +#ifdef __OpenBSD__ +#define DLT_LOOP 12 +#else +#define DLT_LOOP 108 +#endif + +/* + * Encapsulated packets for IPsec; DLT_ENC is 13 in OpenBSD, but that's + * DLT_SLIP_BSDOS in NetBSD, so we don't use 13 for it in OSes other + * than OpenBSD. + */ +#ifdef __OpenBSD__ +#define DLT_ENC 13 +#else +#define DLT_ENC 109 +#endif + +/* + * Values between 110 and 112 are reserved for use in capture file headers + * as link-layer types corresponding to DLT_ types that might differ + * between platforms; don't use those values for new DLT_ types + * other than the corresponding DLT_ types. + */ + +/* + * This is for Linux cooked sockets. + */ +#define DLT_LINUX_SLL 113 + +/* + * Apple LocalTalk hardware. + */ +#define DLT_LTALK 114 + +/* + * Acorn Econet. + */ +#define DLT_ECONET 115 + +/* + * Reserved for use with OpenBSD ipfilter. + */ +#define DLT_IPFILTER 116 + +/* + * OpenBSD DLT_PFLOG; DLT_PFLOG is 17 in OpenBSD, but that's DLT_LANE8023 + * in SuSE 6.3, so we can't use 17 for it in capture-file headers. + * + * XXX: is there a conflict with DLT_PFSYNC 18 as well? + */ +#ifdef __OpenBSD__ +#define DLT_OLD_PFLOG 17 +#define DLT_PFSYNC 18 +#endif +#define DLT_PFLOG 117 + +/* + * Registered for Cisco-internal use. + */ +#define DLT_CISCO_IOS 118 + +/* + * For 802.11 cards using the Prism II chips, with a link-layer + * header including Prism monitor mode information plus an 802.11 + * header. + */ +#define DLT_PRISM_HEADER 119 + +/* + * Reserved for Aironet 802.11 cards, with an Aironet link-layer header + * (see Doug Ambrisko's FreeBSD patches). + */ +#define DLT_AIRONET_HEADER 120 + +/* + * Reserved for Siemens HiPath HDLC. + */ +#define DLT_HHDLC 121 + +/* + * This is for RFC 2625 IP-over-Fibre Channel. + * + * This is not for use with raw Fibre Channel, where the link-layer + * header starts with a Fibre Channel frame header; it's for IP-over-FC, + * where the link-layer header starts with an RFC 2625 Network_Header + * field. + */ +#define DLT_IP_OVER_FC 122 + +/* + * This is for Full Frontal ATM on Solaris with SunATM, with a + * pseudo-header followed by an AALn PDU. + * + * There may be other forms of Full Frontal ATM on other OSes, + * with different pseudo-headers. + * + * If ATM software returns a pseudo-header with VPI/VCI information + * (and, ideally, packet type information, e.g. signalling, ILMI, + * LANE, LLC-multiplexed traffic, etc.), it should not use + * DLT_ATM_RFC1483, but should get a new DLT_ value, so tcpdump + * and the like don't have to infer the presence or absence of a + * pseudo-header and the form of the pseudo-header. + */ +#define DLT_SUNATM 123 /* Solaris+SunATM */ + +/* + * Reserved as per request from Kent Dahlgren + * for private use. + */ +#define DLT_RIO 124 /* RapidIO */ +#define DLT_PCI_EXP 125 /* PCI Express */ +#define DLT_AURORA 126 /* Xilinx Aurora link layer */ + +/* + * Header for 802.11 plus a number of bits of link-layer information + * including radio information, used by some recent BSD drivers as + * well as the madwifi Atheros driver for Linux. + */ +#define DLT_IEEE802_11_RADIO 127 /* 802.11 plus radiotap radio header */ + +/* + * Reserved for the TZSP encapsulation, as per request from + * Chris Waters + * TZSP is a generic encapsulation for any other link type, + * which includes a means to include meta-information + * with the packet, e.g. signal strength and channel + * for 802.11 packets. + */ +#define DLT_TZSP 128 /* Tazmen Sniffer Protocol */ + +/* + * BSD's ARCNET headers have the source host, destination host, + * and type at the beginning of the packet; that's what's handed + * up to userland via BPF. + * + * Linux's ARCNET headers, however, have a 2-byte offset field + * between the host IDs and the type; that's what's handed up + * to userland via PF_PACKET sockets. + * + * We therefore have to have separate DLT_ values for them. + */ +#define DLT_ARCNET_LINUX 129 /* ARCNET */ + +/* + * Juniper-private data link types, as per request from + * Hannes Gredler . The DLT_s are used + * for passing on chassis-internal metainformation such as + * QOS profiles, etc.. + */ +#define DLT_JUNIPER_MLPPP 130 +#define DLT_JUNIPER_MLFR 131 +#define DLT_JUNIPER_ES 132 +#define DLT_JUNIPER_GGSN 133 +#define DLT_JUNIPER_MFR 134 +#define DLT_JUNIPER_ATM2 135 +#define DLT_JUNIPER_SERVICES 136 +#define DLT_JUNIPER_ATM1 137 + +/* + * Apple IP-over-IEEE 1394, as per a request from Dieter Siegmund + * . The header that's presented is an Ethernet-like + * header: + * + * #define FIREWIRE_EUI64_LEN 8 + * struct firewire_header { + * u_char firewire_dhost[FIREWIRE_EUI64_LEN]; + * u_char firewire_shost[FIREWIRE_EUI64_LEN]; + * u_short firewire_type; + * }; + * + * with "firewire_type" being an Ethernet type value, rather than, + * for example, raw GASP frames being handed up. + */ +#define DLT_APPLE_IP_OVER_IEEE1394 138 + +/* + * Various SS7 encapsulations, as per a request from Jeff Morriss + * and subsequent discussions. + */ +#define DLT_MTP2_WITH_PHDR 139 /* pseudo-header with various info, followed by MTP2 */ +#define DLT_MTP2 140 /* MTP2, without pseudo-header */ +#define DLT_MTP3 141 /* MTP3, without pseudo-header or MTP2 */ +#define DLT_SCCP 142 /* SCCP, without pseudo-header or MTP2 or MTP3 */ + +/* + * DOCSIS MAC frames. + */ +#define DLT_DOCSIS 143 + +/* + * Linux-IrDA packets. Protocol defined at http://www.irda.org. + * Those packets include IrLAP headers and above (IrLMP...), but + * don't include Phy framing (SOF/EOF/CRC & byte stuffing), because Phy + * framing can be handled by the hardware and depend on the bitrate. + * This is exactly the format you would get capturing on a Linux-IrDA + * interface (irdaX), but not on a raw serial port. + * Note the capture is done in "Linux-cooked" mode, so each packet include + * a fake packet header (struct sll_header). This is because IrDA packet + * decoding is dependant on the direction of the packet (incomming or + * outgoing). + * When/if other platform implement IrDA capture, we may revisit the + * issue and define a real DLT_IRDA... + * Jean II + */ +#define DLT_LINUX_IRDA 144 + +/* + * Reserved for IBM SP switch and IBM Next Federation switch. + */ +#define DLT_IBM_SP 145 +#define DLT_IBM_SN 146 + +/* + * Reserved for private use. If you have some link-layer header type + * that you want to use within your organization, with the capture files + * using that link-layer header type not ever be sent outside your + * organization, you can use these values. + * + * No libpcap release will use these for any purpose, nor will any + * tcpdump release use them, either. + * + * Do *NOT* use these in capture files that you expect anybody not using + * your private versions of capture-file-reading tools to read; in + * particular, do *NOT* use them in products, otherwise you may find that + * people won't be able to use tcpdump, or snort, or Ethereal, or... to + * read capture files from your firewall/intrusion detection/traffic + * monitoring/etc. appliance, or whatever product uses that DLT_ value, + * and you may also find that the developers of those applications will + * not accept patches to let them read those files. + * + * Also, do not use them if somebody might send you a capture using them + * for *their* private type and tools using them for *your* private type + * would have to read them. + * + * Instead, ask "tcpdump-workers@lists.tcpdump.org" for a new DLT_ value, + * as per the comment above, and use the type you're given. + */ +#define DLT_USER0 147 +#define DLT_USER1 148 +#define DLT_USER2 149 +#define DLT_USER3 150 +#define DLT_USER4 151 +#define DLT_USER5 152 +#define DLT_USER6 153 +#define DLT_USER7 154 +#define DLT_USER8 155 +#define DLT_USER9 156 +#define DLT_USER10 157 +#define DLT_USER11 158 +#define DLT_USER12 159 +#define DLT_USER13 160 +#define DLT_USER14 161 +#define DLT_USER15 162 + +/* + * For future use with 802.11 captures - defined by AbsoluteValue + * Systems to store a number of bits of link-layer information + * including radio information: + * + * http://www.shaftnet.org/~pizza/software/capturefrm.txt + * + * but it might be used by some non-AVS drivers now or in the + * future. + */ +#define DLT_IEEE802_11_RADIO_AVS 163 /* 802.11 plus AVS radio header */ + +/* + * Juniper-private data link type, as per request from + * Hannes Gredler . The DLT_s are used + * for passing on chassis-internal metainformation such as + * QOS profiles, etc.. + */ +#define DLT_JUNIPER_MONITOR 164 + +/* + * Reserved for BACnet MS/TP. + */ +#define DLT_BACNET_MS_TP 165 + +/* + * Another PPP variant as per request from Karsten Keil . + * + * This is used in some OSes to allow a kernel socket filter to distinguish + * between incoming and outgoing packets, on a socket intended to + * supply pppd with outgoing packets so it can do dial-on-demand and + * hangup-on-lack-of-demand; incoming packets are filtered out so they + * don't cause pppd to hold the connection up (you don't want random + * input packets such as port scans, packets from old lost connections, + * etc. to force the connection to stay up). + * + * The first byte of the PPP header (0xff03) is modified to accomodate + * the direction - 0x00 = IN, 0x01 = OUT. + */ +#define DLT_PPP_PPPD 166 + +/* + * Names for backwards compatibility with older versions of some PPP + * software; new software should use DLT_PPP_PPPD. + */ +#define DLT_PPP_WITH_DIRECTION DLT_PPP_PPPD +#define DLT_LINUX_PPP_WITHDIRECTION DLT_PPP_PPPD + +/* + * Juniper-private data link type, as per request from + * Hannes Gredler . The DLT_s are used + * for passing on chassis-internal metainformation such as + * QOS profiles, cookies, etc.. + */ +#define DLT_JUNIPER_PPPOE 167 +#define DLT_JUNIPER_PPPOE_ATM 168 + +#define DLT_GPRS_LLC 169 /* GPRS LLC */ +#define DLT_GPF_T 170 /* GPF-T (ITU-T G.7041/Y.1303) */ +#define DLT_GPF_F 171 /* GPF-F (ITU-T G.7041/Y.1303) */ + +/* + * Requested by Oolan Zimmer for use in Gcom's T1/E1 line + * monitoring equipment. + */ +#define DLT_GCOM_T1E1 172 +#define DLT_GCOM_SERIAL 173 + +/* + * Juniper-private data link type, as per request from + * Hannes Gredler . The DLT_ is used + * for internal communication to Physical Interface Cards (PIC) + */ +#define DLT_JUNIPER_PIC_PEER 174 + +/* + * Link types requested by Gregor Maier of Endace + * Measurement Systems. They add an ERF header (see + * http://www.endace.com/support/EndaceRecordFormat.pdf) in front of + * the link-layer header. + */ +#define DLT_ERF_ETH 175 /* Ethernet */ +#define DLT_ERF_POS 176 /* Packet-over-SONET */ + +/* + * Requested by Daniele Orlandi for raw LAPD + * for vISDN (http://www.orlandi.com/visdn/). Its link-layer header + * includes additional information before the LAPD header, so it's + * not necessarily a generic LAPD header. + */ +#define DLT_LINUX_LAPD 177 + +/* + * Juniper-private data link type, as per request from + * Hannes Gredler . + * The DLT_ are used for prepending meta-information + * like interface index, interface name + * before standard Ethernet, PPP, Frelay & C-HDLC Frames + */ +#define DLT_JUNIPER_ETHER 178 +#define DLT_JUNIPER_PPP 179 +#define DLT_JUNIPER_FRELAY 180 +#define DLT_JUNIPER_CHDLC 181 + +/* + * Multi Link Frame Relay (FRF.16) + */ +#define DLT_MFR 182 + +/* + * Juniper-private data link type, as per request from + * Hannes Gredler . + * The DLT_ is used for internal communication with a + * voice Adapter Card (PIC) + */ +#define DLT_JUNIPER_VP 183 + +/* + * Arinc 429 frames. + * DLT_ requested by Gianluca Varenni . + * Every frame contains a 32bit A429 label. + * More documentation on Arinc 429 can be found at + * http://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf + */ +#define DLT_A429 184 + +/* + * Arinc 653 Interpartition Communication messages. + * DLT_ requested by Gianluca Varenni . + * Please refer to the A653-1 standard for more information. + */ +#define DLT_A653_ICM 185 + +/* + * USB packets, beginning with a USB setup header; requested by + * Paolo Abeni . + */ +#define DLT_USB 186 + +/* + * Bluetooth HCI UART transport layer (part H:4); requested by + * Paolo Abeni. + */ +#define DLT_BLUETOOTH_HCI_H4 187 + +/* + * IEEE 802.16 MAC Common Part Sublayer; requested by Maria Cruz + * . + */ +#define DLT_IEEE802_16_MAC_CPS 188 + +/* + * USB packets, beginning with a Linux USB header; requested by + * Paolo Abeni . + */ +#define DLT_USB_LINUX 189 + +/* + * Controller Area Network (CAN) v. 2.0B packets. + * DLT_ requested by Gianluca Varenni . + * Used to dump CAN packets coming from a CAN Vector board. + * More documentation on the CAN v2.0B frames can be found at + * http://www.can-cia.org/downloads/?269 + */ +#define DLT_CAN20B 190 + +/* + * IEEE 802.15.4, with address fields padded, as is done by Linux + * drivers; requested by Juergen Schimmer. + */ +#define DLT_IEEE802_15_4_LINUX 191 + +/* + * Per Packet Information encapsulated packets. + * DLT_ requested by Gianluca Varenni . + */ +#define DLT_PPI 192 + +/* + * Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header; + * requested by Charles Clancy. + */ +#define DLT_IEEE802_16_MAC_CPS_RADIO 193 + +/* + * Juniper-private data link type, as per request from + * Hannes Gredler . + * The DLT_ is used for internal communication with a + * integrated service module (ISM). + */ +#define DLT_JUNIPER_ISM 194 + +/* + * IEEE 802.15.4, exactly as it appears in the spec (no padding, no + * nothing); requested by Mikko Saarnivala . + */ +#define DLT_IEEE802_15_4 195 + +/* + * Various link-layer types, with a pseudo-header, for SITA + * (http://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com). + */ +#define DLT_SITA 196 + +/* + * Various link-layer types, with a pseudo-header, for Endace DAG cards; + * encapsulates Endace ERF records. Requested by Stephen Donnelly + * . + */ +#define DLT_ERF 197 + +/* + * Special header prepended to Ethernet packets when capturing from a + * u10 Networks board. Requested by Phil Mulholland + * . + */ +#define DLT_RAIF1 198 + +/* + * IPMB packet for IPMI, beginning with the I2C slave address, followed + * by the netFn and LUN, etc.. Requested by Chanthy Toeung + * . + */ +#define DLT_IPMB 199 + +/* + * Juniper-private data link type, as per request from + * Hannes Gredler . + * The DLT_ is used for capturing data on a secure tunnel interface. + */ +#define DLT_JUNIPER_ST 200 + +/* + * Bluetooth HCI UART transport layer (part H:4), with pseudo-header + * that includes direction information; requested by Paolo Abeni. + */ +#define DLT_BLUETOOTH_HCI_H4_WITH_PHDR 201 + +/* + * AX.25 packet with a 1-byte KISS header; see + * + * http://www.ax25.net/kiss.htm + * + * as per Richard Stearn . + */ +#define DLT_AX25_KISS 202 + +/* + * LAPD packets from an ISDN channel, starting with the address field, + * with no pseudo-header. + * Requested by Varuna De Silva . + */ +#define DLT_LAPD 203 + +/* + * Variants of various link-layer headers, with a one-byte direction + * pseudo-header prepended - zero means "received by this host", + * non-zero (any non-zero value) means "sent by this host" - as per + * Will Barker . + */ +#define DLT_PPP_WITH_DIR 204 /* PPP - don't confuse with DLT_PPP_WITH_DIRECTION */ +#define DLT_C_HDLC_WITH_DIR 205 /* Cisco HDLC */ +#define DLT_FRELAY_WITH_DIR 206 /* Frame Relay */ +#define DLT_LAPB_WITH_DIR 207 /* LAPB */ + +/* + * 208 is reserved for an as-yet-unspecified proprietary link-layer + * type, as requested by Will Barker. + */ + +/* + * IPMB with a Linux-specific pseudo-header; as requested by Alexey Neyman + * . + */ +#define DLT_IPMB_LINUX 209 + +/* + * FlexRay automotive bus - http://www.flexray.com/ - as requested + * by Hannes Kaelber . + */ +#define DLT_FLEXRAY 210 + +/* + * Media Oriented Systems Transport (MOST) bus for multimedia + * transport - http://www.mostcooperation.com/ - as requested + * by Hannes Kaelber . + */ +#define DLT_MOST 211 + +/* + * Local Interconnect Network (LIN) bus for vehicle networks - + * http://www.lin-subbus.org/ - as requested by Hannes Kaelber + * . + */ +#define DLT_LIN 212 + +/* + * X2E-private data link type used for serial line capture, + * as requested by Hannes Kaelber . + */ +#define DLT_X2E_SERIAL 213 + +/* + * X2E-private data link type used for the Xoraya data logger + * family, as requested by Hannes Kaelber . + */ +#define DLT_X2E_XORAYA 214 + +/* + * IEEE 802.15.4, exactly as it appears in the spec (no padding, no + * nothing), but with the PHY-level data for non-ASK PHYs (4 octets + * of 0 as preamble, one octet of SFD, one octet of frame length+ + * reserved bit, and then the MAC-layer data, starting with the + * frame control field). + * + * Requested by Max Filippov . + */ +#define DLT_IEEE802_15_4_NONASK_PHY 215 + + +/* + * DLT and savefile link type values are split into a class and + * a member of that class. A class value of 0 indicates a regular + * DLT_/LINKTYPE_ value. + */ +#define DLT_CLASS(x) ((x) & 0x03ff0000) + +/* + * NetBSD-specific generic "raw" link type. The class value indicates + * that this is the generic raw type, and the lower 16 bits are the + * address family we're dealing with. Those values are NetBSD-specific; + * do not assume that they correspond to AF_ values for your operating + * system. + */ +#define DLT_CLASS_NETBSD_RAWAF 0x02240000 +#define DLT_NETBSD_RAWAF(af) (DLT_CLASS_NETBSD_RAWAF | (af)) +#define DLT_NETBSD_RAWAF_AF(x) ((x) & 0x0000ffff) +#define DLT_IS_NETBSD_RAWAF(x) (DLT_CLASS(x) == DLT_CLASS_NETBSD_RAWAF) + + +/* + * The instruction encodings. + */ +/* instruction classes */ +#define BPF_CLASS(code) ((code) & 0x07) +#define BPF_LD 0x00 +#define BPF_LDX 0x01 +#define BPF_ST 0x02 +#define BPF_STX 0x03 +#define BPF_ALU 0x04 +#define BPF_JMP 0x05 +#define BPF_RET 0x06 +#define BPF_MISC 0x07 + +/* ld/ldx fields */ +#define BPF_SIZE(code) ((code) & 0x18) +#define BPF_W 0x00 +#define BPF_H 0x08 +#define BPF_B 0x10 +#define BPF_MODE(code) ((code) & 0xe0) +#define BPF_IMM 0x00 +#define BPF_ABS 0x20 +#define BPF_IND 0x40 +#define BPF_MEM 0x60 +#define BPF_LEN 0x80 +#define BPF_MSH 0xa0 + +/* alu/jmp fields */ +#define BPF_OP(code) ((code) & 0xf0) +#define BPF_ADD 0x00 +#define BPF_SUB 0x10 +#define BPF_MUL 0x20 +#define BPF_DIV 0x30 +#define BPF_OR 0x40 +#define BPF_AND 0x50 +#define BPF_LSH 0x60 +#define BPF_RSH 0x70 +#define BPF_NEG 0x80 +#define BPF_JA 0x00 +#define BPF_JEQ 0x10 +#define BPF_JGT 0x20 +#define BPF_JGE 0x30 +#define BPF_JSET 0x40 +#define BPF_SRC(code) ((code) & 0x08) +#define BPF_K 0x00 +#define BPF_X 0x08 + +/* ret - BPF_K and BPF_X also apply */ +#define BPF_RVAL(code) ((code) & 0x18) +#define BPF_A 0x10 + +/* misc */ +#define BPF_MISCOP(code) ((code) & 0xf8) +#define BPF_TAX 0x00 +#define BPF_TXA 0x80 + +/* + * The instruction data structure. + */ +struct bpf_insn { + u_short code; + u_char jt; + u_char jf; + bpf_u_int32 k; +}; + +/* + * Macros for insn array initializers. + */ +#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k } +#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k } + +#if __STDC__ || defined(__cplusplus) +extern int bpf_validate(const struct bpf_insn *, int); +extern u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int); +#else +extern int bpf_validate(); +extern u_int bpf_filter(); +#endif + +/* + * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST). + */ +#define BPF_MEMWORDS 16 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/plugins/dev9ghzdrk/pcap/namedb.h b/plugins/dev9ghzdrk/pcap/namedb.h new file mode 100644 index 000000000..9002c7509 --- /dev/null +++ b/plugins/dev9ghzdrk/pcap/namedb.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 1994, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Computer Systems + * Engineering Group at Lawrence Berkeley Laboratory. + * 4. Neither the name of the University nor of the Laboratory may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) $Header: /tcpdump/master/libpcap/pcap/namedb.h,v 1.1 2006/10/04 18:09:22 guy Exp $ (LBL) + */ + +#ifndef lib_pcap_namedb_h +#define lib_pcap_namedb_h + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * As returned by the pcap_next_etherent() + * XXX this stuff doesn't belong in this interface, but this + * library already must do name to address translation, so + * on systems that don't have support for /etc/ethers, we + * export these hooks since they'll + */ +struct pcap_etherent { + u_char addr[6]; + char name[122]; +}; +#ifndef PCAP_ETHERS_FILE +#define PCAP_ETHERS_FILE "/etc/ethers" +#endif +struct pcap_etherent *pcap_next_etherent(FILE *); +u_char *pcap_ether_hostton(const char*); +u_char *pcap_ether_aton(const char *); + +bpf_u_int32 **pcap_nametoaddr(const char *); +#ifdef INET6 +struct addrinfo *pcap_nametoaddrinfo(const char *); +#endif +bpf_u_int32 pcap_nametonetaddr(const char *); + +int pcap_nametoport(const char *, int *, int *); +int pcap_nametoportrange(const char *, int *, int *, int *); +int pcap_nametoproto(const char *); +int pcap_nametoeproto(const char *); +int pcap_nametollc(const char *); +/* + * If a protocol is unknown, PROTO_UNDEF is returned. + * Also, pcap_nametoport() returns the protocol along with the port number. + * If there are ambiguous entried in /etc/services (i.e. domain + * can be either tcp or udp) PROTO_UNDEF is returned. + */ +#define PROTO_UNDEF -1 + +/* XXX move these to pcap-int.h? */ +int __pcap_atodn(const char *, bpf_u_int32 *); +int __pcap_atoin(const char *, bpf_u_int32 *); +u_short __pcap_nametodnaddr(const char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/plugins/dev9ghzdrk/pcap/pcap.h b/plugins/dev9ghzdrk/pcap/pcap.h new file mode 100644 index 000000000..ad8fc40ac --- /dev/null +++ b/plugins/dev9ghzdrk/pcap/pcap.h @@ -0,0 +1,407 @@ +/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ +/* + * Copyright (c) 1993, 1994, 1995, 1996, 1997 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Computer Systems + * Engineering Group at Lawrence Berkeley Laboratory. + * 4. Neither the name of the University nor of the Laboratory may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) $Header: /tcpdump/master/libpcap/pcap/pcap.h,v 1.4.2.11 2008-10-06 15:38:39 gianluca Exp $ (LBL) + */ + +#ifndef lib_pcap_pcap_h +#define lib_pcap_pcap_h + +#if defined(WIN32) + #include +#elif defined(MSDOS) + #include + #include /* u_int, u_char etc. */ +#else /* UN*X */ + #include + #include +#endif /* WIN32/MSDOS/UN*X */ + +#ifndef PCAP_DONT_INCLUDE_PCAP_BPF_H +#include +#endif + +#include + +#ifdef HAVE_REMOTE + // We have to define the SOCKET here, although it has been defined in sockutils.h + // This is to avoid the distribution of the 'sockutils.h' file around + // (for example in the WinPcap developer's pack) + #ifndef SOCKET + #ifdef WIN32 + #define SOCKET unsigned int + #else + #define SOCKET int + #endif + #endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define PCAP_VERSION_MAJOR 2 +#define PCAP_VERSION_MINOR 4 + +#define PCAP_ERRBUF_SIZE 256 + +/* + * Compatibility for systems that have a bpf.h that + * predates the bpf typedefs for 64-bit support. + */ +#if BPF_RELEASE - 0 < 199406 +typedef int bpf_int32; +typedef u_int bpf_u_int32; +#endif + +typedef struct pcap pcap_t; +typedef struct pcap_dumper pcap_dumper_t; +typedef struct pcap_if pcap_if_t; +typedef struct pcap_addr pcap_addr_t; + +/* + * The first record in the file contains saved values for some + * of the flags used in the printout phases of tcpdump. + * Many fields here are 32 bit ints so compilers won't insert unwanted + * padding; these files need to be interchangeable across architectures. + * + * Do not change the layout of this structure, in any way (this includes + * changes that only affect the length of fields in this structure). + * + * Also, do not change the interpretation of any of the members of this + * structure, in any way (this includes using values other than + * LINKTYPE_ values, as defined in "savefile.c", in the "linktype" + * field). + * + * Instead: + * + * introduce a new structure for the new format, if the layout + * of the structure changed; + * + * send mail to "tcpdump-workers@lists.tcpdump.org", requesting + * a new magic number for your new capture file format, and, when + * you get the new magic number, put it in "savefile.c"; + * + * use that magic number for save files with the changed file + * header; + * + * make the code in "savefile.c" capable of reading files with + * the old file header as well as files with the new file header + * (using the magic number to determine the header format). + * + * Then supply the changes as a patch at + * + * http://sourceforge.net/projects/libpcap/ + * + * so that future versions of libpcap and programs that use it (such as + * tcpdump) will be able to read your new capture file format. + */ +struct pcap_file_header { + bpf_u_int32 magic; + u_short version_major; + u_short version_minor; + bpf_int32 thiszone; /* gmt to local correction */ + bpf_u_int32 sigfigs; /* accuracy of timestamps */ + bpf_u_int32 snaplen; /* max length saved portion of each pkt */ + bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */ +}; + +/* + * Macros for the value returned by pcap_datalink_ext(). + * + * If LT_FCS_LENGTH_PRESENT(x) is true, the LT_FCS_LENGTH(x) macro + * gives the FCS length of packets in the capture. + */ +#define LT_FCS_LENGTH_PRESENT(x) ((x) & 0x04000000) +#define LT_FCS_LENGTH(x) (((x) & 0xF0000000) >> 28) +#define LT_FCS_DATALINK_EXT(x) ((((x) & 0xF) << 28) | 0x04000000) + +typedef enum { + PCAP_D_INOUT = 0, + PCAP_D_IN, + PCAP_D_OUT +} pcap_direction_t; + +/* + * Generic per-packet information, as supplied by libpcap. + * + * The time stamp can and should be a "struct timeval", regardless of + * whether your system supports 32-bit tv_sec in "struct timeval", + * 64-bit tv_sec in "struct timeval", or both if it supports both 32-bit + * and 64-bit applications. The on-disk format of savefiles uses 32-bit + * tv_sec (and tv_usec); this structure is irrelevant to that. 32-bit + * and 64-bit versions of libpcap, even if they're on the same platform, + * should supply the appropriate version of "struct timeval", even if + * that's not what the underlying packet capture mechanism supplies. + */ +struct pcap_pkthdr { + struct timeval ts; /* time stamp */ + bpf_u_int32 caplen; /* length of portion present */ + bpf_u_int32 len; /* length this packet (off wire) */ +}; + +/* + * As returned by the pcap_stats() + */ +struct pcap_stat { + u_int ps_recv; /* number of packets received */ + u_int ps_drop; /* number of packets dropped */ + u_int ps_ifdrop; /* drops by interface XXX not yet supported */ +#ifdef HAVE_REMOTE + u_int ps_capt; /* number of packets that are received by the application; please get rid off the Win32 ifdef */ + u_int ps_sent; /* number of packets sent by the server on the network */ + u_int ps_netdrop; /* number of packets lost on the network */ +#endif /* HAVE_REMOTE */ +}; + +#ifdef MSDOS +/* + * As returned by the pcap_stats_ex() + */ +struct pcap_stat_ex { + u_long rx_packets; /* total packets received */ + u_long tx_packets; /* total packets transmitted */ + u_long rx_bytes; /* total bytes received */ + u_long tx_bytes; /* total bytes transmitted */ + u_long rx_errors; /* bad packets received */ + u_long tx_errors; /* packet transmit problems */ + u_long rx_dropped; /* no space in Rx buffers */ + u_long tx_dropped; /* no space available for Tx */ + u_long multicast; /* multicast packets received */ + u_long collisions; + + /* detailed rx_errors: */ + u_long rx_length_errors; + u_long rx_over_errors; /* receiver ring buff overflow */ + u_long rx_crc_errors; /* recv'd pkt with crc error */ + u_long rx_frame_errors; /* recv'd frame alignment error */ + u_long rx_fifo_errors; /* recv'r fifo overrun */ + u_long rx_missed_errors; /* recv'r missed packet */ + + /* detailed tx_errors */ + u_long tx_aborted_errors; + u_long tx_carrier_errors; + u_long tx_fifo_errors; + u_long tx_heartbeat_errors; + u_long tx_window_errors; + }; +#endif + +/* + * Item in a list of interfaces. + */ +struct pcap_if { + struct pcap_if *next; + char *name; /* name to hand to "pcap_open_live()" */ + char *description; /* textual description of interface, or NULL */ + struct pcap_addr *addresses; + bpf_u_int32 flags; /* PCAP_IF_ interface flags */ +}; + +#define PCAP_IF_LOOPBACK 0x00000001 /* interface is loopback */ + +/* + * Representation of an interface address. + */ +struct pcap_addr { + struct pcap_addr *next; + struct sockaddr *addr; /* address */ + struct sockaddr *netmask; /* netmask for that address */ + struct sockaddr *broadaddr; /* broadcast address for that address */ + struct sockaddr *dstaddr; /* P2P destination address for that address */ +}; + +typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, + const u_char *); + +/* + * Error codes for the pcap API. + * These will all be negative, so you can check for the success or + * failure of a call that returns these codes by checking for a + * negative value. + */ +#define PCAP_ERROR -1 /* generic error code */ +#define PCAP_ERROR_BREAK -2 /* loop terminated by pcap_breakloop */ +#define PCAP_ERROR_NOT_ACTIVATED -3 /* the capture needs to be activated */ +#define PCAP_ERROR_ACTIVATED -4 /* the operation can't be performed on already activated captures */ +#define PCAP_ERROR_NO_SUCH_DEVICE -5 /* no such device exists */ +#define PCAP_ERROR_RFMON_NOTSUP -6 /* this device doesn't support rfmon (monitor) mode */ +#define PCAP_ERROR_NOT_RFMON -7 /* operation supported only in monitor mode */ +#define PCAP_ERROR_PERM_DENIED -8 /* no permission to open the device */ +#define PCAP_ERROR_IFACE_NOT_UP -9 /* interface isn't up */ + +/* + * Warning codes for the pcap API. + * These will all be positive and non-zero, so they won't look like + * errors. + */ +#define PCAP_WARNING 1 /* generic warning code */ +#define PCAP_WARNING_PROMISC_NOTSUP 2 /* this device doesn't support promiscuous mode */ + +char *pcap_lookupdev(char *); +int pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *); + +pcap_t *pcap_create(const char *, char *); +int pcap_set_snaplen(pcap_t *, int); +int pcap_set_promisc(pcap_t *, int); +int pcap_can_set_rfmon(pcap_t *); +int pcap_set_rfmon(pcap_t *, int); +int pcap_set_timeout(pcap_t *, int); +int pcap_set_buffer_size(pcap_t *, int); +int pcap_activate(pcap_t *); + +pcap_t *pcap_open_live(const char *, int, int, int, char *); +pcap_t *pcap_open_dead(int, int); +pcap_t *pcap_open_offline(const char *, char *); +#if defined(WIN32) +pcap_t *pcap_hopen_offline(intptr_t, char *); +#if !defined(LIBPCAP_EXPORTS) +#define pcap_fopen_offline(f,b) \ + pcap_hopen_offline(_get_osfhandle(_fileno(f)), b) +#else /*LIBPCAP_EXPORTS*/ +static pcap_t *pcap_fopen_offline(FILE *, char *); +#endif +#else /*WIN32*/ +pcap_t *pcap_fopen_offline(FILE *, char *); +#endif /*WIN32*/ + +void pcap_close(pcap_t *); +int pcap_loop(pcap_t *, int, pcap_handler, u_char *); +int pcap_dispatch(pcap_t *, int, pcap_handler, u_char *); +const u_char* + pcap_next(pcap_t *, struct pcap_pkthdr *); +int pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **); +void pcap_breakloop(pcap_t *); +int pcap_stats(pcap_t *, struct pcap_stat *); +int pcap_setfilter(pcap_t *, struct bpf_program *); +int pcap_setdirection(pcap_t *, pcap_direction_t); +int pcap_getnonblock(pcap_t *, char *); +int pcap_setnonblock(pcap_t *, int, char *); +int pcap_inject(pcap_t *, const void *, size_t); +int pcap_sendpacket(pcap_t *, const u_char *, int); +const char *pcap_statustostr(int); +const char *pcap_strerror(int); +char *pcap_geterr(pcap_t *); +void pcap_perror(pcap_t *, char *); +int pcap_compile(pcap_t *, struct bpf_program *, const char *, int, + bpf_u_int32); +int pcap_compile_nopcap(int, int, struct bpf_program *, + const char *, int, bpf_u_int32); +void pcap_freecode(struct bpf_program *); +int pcap_offline_filter(struct bpf_program *, const struct pcap_pkthdr *, + const u_char *); +int pcap_datalink(pcap_t *); +int pcap_datalink_ext(pcap_t *); +int pcap_list_datalinks(pcap_t *, int **); +int pcap_set_datalink(pcap_t *, int); +void pcap_free_datalinks(int *); +int pcap_datalink_name_to_val(const char *); +const char *pcap_datalink_val_to_name(int); +const char *pcap_datalink_val_to_description(int); +int pcap_snapshot(pcap_t *); +int pcap_is_swapped(pcap_t *); +int pcap_major_version(pcap_t *); +int pcap_minor_version(pcap_t *); + +/* XXX */ +FILE *pcap_file(pcap_t *); +int pcap_fileno(pcap_t *); + +pcap_dumper_t *pcap_dump_open(pcap_t *, const char *); +pcap_dumper_t *pcap_dump_fopen(pcap_t *, FILE *fp); +FILE *pcap_dump_file(pcap_dumper_t *); +long pcap_dump_ftell(pcap_dumper_t *); +int pcap_dump_flush(pcap_dumper_t *); +void pcap_dump_close(pcap_dumper_t *); +void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *); + +int pcap_findalldevs(pcap_if_t **, char *); +void pcap_freealldevs(pcap_if_t *); + +const char *pcap_lib_version(void); + +/* XXX this guy lives in the bpf tree */ +u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int); +int bpf_validate(const struct bpf_insn *f, int len); +char *bpf_image(const struct bpf_insn *, int); +void bpf_dump(const struct bpf_program *, int); + +#if defined(WIN32) + +/* + * Win32 definitions + */ + +int pcap_setbuff(pcap_t *p, int dim); +int pcap_setmode(pcap_t *p, int mode); +int pcap_setmintocopy(pcap_t *p, int size); + +#ifdef WPCAP +/* Include file with the wpcap-specific extensions */ +#include +#endif /* WPCAP */ + +#define MODE_CAPT 0 +#define MODE_STAT 1 +#define MODE_MON 2 + +#elif defined(MSDOS) + +/* + * MS-DOS definitions + */ + +int pcap_stats_ex (pcap_t *, struct pcap_stat_ex *); +void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait); +u_long pcap_mac_packets (void); + +#else /* UN*X */ + +/* + * UN*X definitions + */ + +int pcap_get_selectable_fd(pcap_t *); + +#endif /* WIN32/MSDOS/UN*X */ + +#ifdef HAVE_REMOTE +/* Includes most of the public stuff that is needed for the remote capture */ +#include +#endif /* HAVE_REMOTE */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/plugins/dev9ghzdrk/pcap/sll.h b/plugins/dev9ghzdrk/pcap/sll.h new file mode 100644 index 000000000..e9d5452af --- /dev/null +++ b/plugins/dev9ghzdrk/pcap/sll.h @@ -0,0 +1,129 @@ +/*- + * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from the Stanford/CMU enet packet filter, + * (net/enet.c) distributed as part of 4.3BSD, and code contributed + * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence + * Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) $Header: /tcpdump/master/libpcap/pcap/sll.h,v 1.2.2.1 2008-05-30 01:36:06 guy Exp $ (LBL) + */ + +/* + * For captures on Linux cooked sockets, we construct a fake header + * that includes: + * + * a 2-byte "packet type" which is one of: + * + * LINUX_SLL_HOST packet was sent to us + * LINUX_SLL_BROADCAST packet was broadcast + * LINUX_SLL_MULTICAST packet was multicast + * LINUX_SLL_OTHERHOST packet was sent to somebody else + * LINUX_SLL_OUTGOING packet was sent *by* us; + * + * a 2-byte Ethernet protocol field; + * + * a 2-byte link-layer type; + * + * a 2-byte link-layer address length; + * + * an 8-byte source link-layer address, whose actual length is + * specified by the previous value. + * + * All fields except for the link-layer address are in network byte order. + * + * DO NOT change the layout of this structure, or change any of the + * LINUX_SLL_ values below. If you must change the link-layer header + * for a "cooked" Linux capture, introduce a new DLT_ type (ask + * "tcpdump-workers@lists.tcpdump.org" for one, so that you don't give it + * a value that collides with a value already being used), and use the + * new header in captures of that type, so that programs that can + * handle DLT_LINUX_SLL captures will continue to handle them correctly + * without any change, and so that capture files with different headers + * can be told apart and programs that read them can dissect the + * packets in them. + */ + +#ifndef lib_pcap_sll_h +#define lib_pcap_sll_h + +/* + * A DLT_LINUX_SLL fake link-layer header. + */ +#define SLL_HDR_LEN 16 /* total header length */ +#define SLL_ADDRLEN 8 /* length of address field */ + +struct sll_header { + u_int16_t sll_pkttype; /* packet type */ + u_int16_t sll_hatype; /* link-layer address type */ + u_int16_t sll_halen; /* link-layer address length */ + u_int8_t sll_addr[SLL_ADDRLEN]; /* link-layer address */ + u_int16_t sll_protocol; /* protocol */ +}; + +/* + * The LINUX_SLL_ values for "sll_pkttype"; these correspond to the + * PACKET_ values on Linux, but are defined here so that they're + * available even on systems other than Linux, and so that they + * don't change even if the PACKET_ values change. + */ +#define LINUX_SLL_HOST 0 +#define LINUX_SLL_BROADCAST 1 +#define LINUX_SLL_MULTICAST 2 +#define LINUX_SLL_OTHERHOST 3 +#define LINUX_SLL_OUTGOING 4 + +/* + * The LINUX_SLL_ values for "sll_protocol"; these correspond to the + * ETH_P_ values on Linux, but are defined here so that they're + * available even on systems other than Linux. We assume, for now, + * that the ETH_P_ values won't change in Linux; if they do, then: + * + * if we don't translate them in "pcap-linux.c", capture files + * won't necessarily be readable if captured on a system that + * defines ETH_P_ values that don't match these values; + * + * if we do translate them in "pcap-linux.c", that makes life + * unpleasant for the BPF code generator, as the values you test + * for in the kernel aren't the values that you test for when + * reading a capture file, so the fixup code run on BPF programs + * handed to the kernel ends up having to do more work. + * + * Add other values here as necessary, for handling packet types that + * might show up on non-Ethernet, non-802.x networks. (Not all the ones + * in the Linux "if_ether.h" will, I suspect, actually show up in + * captures.) + */ +#define LINUX_SLL_P_802_3 0x0001 /* Novell 802.3 frames without 802.2 LLC header */ +#define LINUX_SLL_P_802_2 0x0004 /* 802.2 frames (not D/I/X Ethernet) */ + +#endif diff --git a/plugins/dev9ghzdrk/pcap/usb.h b/plugins/dev9ghzdrk/pcap/usb.h new file mode 100644 index 000000000..adcd19c05 --- /dev/null +++ b/plugins/dev9ghzdrk/pcap/usb.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2006 Paolo Abeni (Italy) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Basic USB data struct + * By Paolo Abeni + * + * @(#) $Header: /tcpdump/master/libpcap/pcap/usb.h,v 1.6 2007/09/22 02:06:08 guy Exp $ + */ + +#ifndef _PCAP_USB_STRUCTS_H__ +#define _PCAP_USB_STRUCTS_H__ + +/* + * possible transfer mode + */ +#define URB_TRANSFER_IN 0x80 +#define URB_ISOCHRONOUS 0x0 +#define URB_INTERRUPT 0x1 +#define URB_CONTROL 0x2 +#define URB_BULK 0x3 + +/* + * possible event type + */ +#define URB_SUBMIT 'S' +#define URB_COMPLETE 'C' +#define URB_ERROR 'E' + +/* + * USB setup header as defined in USB specification. + * Appears at the front of each packet in DLT_USB captures. + */ +typedef struct _usb_setup { + u_int8_t bmRequestType; + u_int8_t bRequest; + u_int16_t wValue; + u_int16_t wIndex; + u_int16_t wLength; +} pcap_usb_setup; + + +/* + * Header prepended by linux kernel to each event. + * Appears at the front of each packet in DLT_USB_LINUX captures. + */ +typedef struct _usb_header { + u_int64_t id; + u_int8_t event_type; + u_int8_t transfer_type; + u_int8_t endpoint_number; + u_int8_t device_address; + u_int16_t bus_id; + char setup_flag;/*if !=0 the urb setup header is not present*/ + char data_flag; /*if !=0 no urb data is present*/ + int64_t ts_sec; + int32_t ts_usec; + int32_t status; + u_int32_t urb_len; + u_int32_t data_len; /* amount of urb data really present in this event*/ + pcap_usb_setup setup; +} pcap_usb_header; + + +#endif diff --git a/plugins/dev9ghzdrk/pcap/vlan.h b/plugins/dev9ghzdrk/pcap/vlan.h new file mode 100644 index 000000000..b0cb7949b --- /dev/null +++ b/plugins/dev9ghzdrk/pcap/vlan.h @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) $Header: /tcpdump/master/libpcap/pcap/vlan.h,v 1.1.2.2 2008-08-06 07:45:59 guy Exp $ + */ + +#ifndef lib_pcap_vlan_h +#define lib_pcap_vlan_h + +struct vlan_tag { + u_int16_t vlan_tpid; /* ETH_P_8021Q */ + u_int16_t vlan_tci; /* VLAN TCI */ +}; + +#define VLAN_TAG_LEN 4 + +#endif diff --git a/plugins/dev9ghzdrk/pcap/wpcap_32/Packet.dll b/plugins/dev9ghzdrk/pcap/wpcap_32/Packet.dll new file mode 100644 index 0000000000000000000000000000000000000000..26a4a65d779e861a65e1221cfbb268e10d7a147a GIT binary patch literal 88696 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 literal 0 HcmV?d00001 diff --git a/plugins/dev9ghzdrk/pcap/wpcap_32/Packet.lib b/plugins/dev9ghzdrk/pcap/wpcap_32/Packet.lib new file mode 100644 index 0000000000000000000000000000000000000000..bc9dba853308409bd98da2d296a919d44cb00585 GIT binary patch literal 8674 zcmcIp&2JM|5FaNYfj~nD`Tleus_2E1V3QzKRlZBW36X8uqgm`tS=IJ#?F}tldPS%Q z4*UzfQHcYWa-tH~9xA00w^kLm{sV{u>AZdWKKFTXaAIk)yEF6V_daIc%zK&s!m1VT ze%bwbQvJ=&F3hFU3+bzKD*saWIXk})zTWNzfE9qA8o-$c0DaE@Mkgr^?*R}RT%a`i z82LzJuPKeM0}$$OqcpM%K&bx>rP24OkJRr|n%n^(G?1k{5hrRP5?qf z?kb=i4>4 zJBonn=Im;TzNxA*U)QWRQbhsPT`HH|qUGBr%esu}Y*ZcJq%HHQe7$BH?aF+rnYD{H zPM*oECZZ}UWw&k{Cr*`6?VRmj`(fQFM`l?OP+eTv(C(I1v9OhqES0LfgLU(a_f{OMKpo)!m9m z+)h)qeIZbEGfu_Pml(TDw3&$NZ`28Ity;26s%=HUZD(B9yMtTivVGUO=eXM5ga}au z+Li=}Q`;_D-ZiUQDr*CYNDrPbukw6(9usD*2jIaOfMoI_J z%v5dt0Lvo)Z}9mZ`93~(Fw12J0IH}nIRWq-^*W~k-VLD)ZH(jdNfO}26u=BVpQ6p{ z`2Gm_KI*;2HV=`Wq1`>S^$Kla@`i5cfm6^6=b;nEU%lXFihGrtc zMtO82;jJTKgIWzYD&C5xTFQwgAcJ@7H2`gDNVmqk6WP>7N~VTHGUgc;!)007!L=&UK&D(2l;%Pl!+?}}DoAFR@pG^u;3oI+J! zl_j#r%KV7m>cZH~N%LW?t>np3i7_!sUahr=NzI0Y#r<5iB73{SZ?x6xo-a32{9hJm zQJ{(pRgdt0HO~mXR*|631<@f}COlKEBu9#-PejJd*|6}7#*SuEiXdHLDpsUu($tlh z(qufc6uyYBMkg9CIM7@ymCH1Te(0n*KbsEEoVU9(iFWws-v{geB>=M#z&`+qlLsCR|wox+#DB|XAlgyc({GR*lW$R~7*MY{lJd%KWDrwoe^ zeBV#@Z92u8TX%Q-yLTBU7#zWAXPgw#K?ZQ0wBQgv)=2zEtYbOGzX{ehejVn)UYgS8 z;$SY#?p{b7v;}eS8+M9z77`{uDM>>huaci!W+LJzzp#(+N&JM^J@oZ&W>v8|#hGq! zPa<5T$yuA9kL(_QAwb-${T$8$dq}gEW<27Ef3T16DMeR`iHP2x>_gH!wApQDM)8c$ z@Pg^Uewe--PH2+c{E^ViB*>mT9gOaHgBo6}o4lDcw}$CiGa?Du1m=P8oUhbet>C4u zn(>HZwh26`l4}Jmoid}HL$r2*rq_oOq}~}uE-H>IXrh>J1uw-mQq61dA_A)f9)XzI~ZfJk229A4^*IXB>CU~nH7 zWQev! literal 0 HcmV?d00001 diff --git a/plugins/dev9ghzdrk/pcap/wpcap_32/wpcap.dll b/plugins/dev9ghzdrk/pcap/wpcap_32/wpcap.dll new file mode 100644 index 0000000000000000000000000000000000000000..1dd1f69709e730b8fc56c5288e9d6b55e6735163 GIT binary patch literal 244336 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 b)KiE$;pThSdo}Q04ZK$a@72J6OAY*AStsGh literal 0 HcmV?d00001 diff --git a/plugins/dev9ghzdrk/pcap/wpcap_64/wpcap.lib b/plugins/dev9ghzdrk/pcap/wpcap_64/wpcap.lib new file mode 100644 index 0000000000000000000000000000000000000000..abacd5d3652d38e0116fced9b25df4f75fc667db GIT binary patch literal 17046 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 +#include +#include "pcap.h" +#include "pcap_io.h" + +#include "dev9.h" +#include "net.h" + +#include + +enum pcap_m_e +{ + switched, + bridged +}; +pcap_m_e pcap_mode=switched; +mac_address virtual_mac = { 0x76, 0x6D, 0x61, 0x63, 0x30, 0x31 }; +//mac_address virtual_mac = { 0x6D, 0x76, 0x63, 0x61, 0x31, 0x30 }; +mac_address broadcast_mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + +ip_address virtual_ip = { 192, 168, 1, 4}; + +pcap_t *adhandle; +int pcap_io_running=0; + +char errbuf[PCAP_ERRBUF_SIZE]; + +char namebuff[256]; + +FILE*packet_log; + +pcap_dumper_t *dump_pcap; + +mac_address host_mac = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +// Fetches the MAC address and prints it +int GetMACAddress(char *adapter, mac_address* addr) +{ + static IP_ADAPTER_INFO AdapterInfo[128]; // Allocate information + // for up to 128 NICs + static PIP_ADAPTER_INFO pAdapterInfo; + ULONG dwBufLen = sizeof(AdapterInfo); // Save memory size of buffer + + DWORD dwStatus = GetAdaptersInfo( // Call GetAdapterInfo + AdapterInfo, // [out] buffer to receive data + &dwBufLen); // [in] size of receive data buffer + if(dwStatus != ERROR_SUCCESS) // Verify return value is + return 0; // valid, no buffer overflow + + pAdapterInfo = AdapterInfo; // Contains pointer to + // current adapter info + do { + if(strcmp(pAdapterInfo->AdapterName,adapter+12)==0) + { + memcpy(addr,pAdapterInfo->Address,6); + return 1; + } + + pAdapterInfo = pAdapterInfo->Next; // Progress through + } + while(pAdapterInfo); // Terminate if last adapter + return 0; +} + +int pcap_io_init(char *adapter) +{ + int dlt; + char *dlt_name; + emu_printf("Opening adapter '%s'...",adapter); + + GetMACAddress(adapter,&host_mac); + + /* Open the adapter */ + if ((adhandle= pcap_open_live(adapter, // name of the device + 65536, // portion of the packet to capture. + // 65536 grants that the whole packet will be captured on all the MACs. + pcap_mode==switched?1:0, // promiscuous mode (nonzero means promiscuous) + 1, // read timeout + errbuf // error buffer + )) == NULL) + { + fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", adapter); + return -1; + } + + dlt = pcap_datalink(adhandle); + dlt_name = (char*)pcap_datalink_val_to_name(dlt); + + fprintf(stderr,"Device uses DLT %d: %s\n",dlt,dlt_name); + switch(dlt) + { + case DLT_EN10MB : + //case DLT_IEEE802_11: + break; + default: + SysMessage("ERROR: Unsupported DataLink Type (%d): %s",dlt,dlt_name); + pcap_close(adhandle); + return -1; + } + + if(pcap_setnonblock(adhandle,1,errbuf)==-1) + { + fprintf(stderr,"WARNING: Error setting non-blocking mode. Default mode will be used.\n"); + } + + packet_log=fopen("logs/packet.log","w"); + + dump_pcap = pcap_dump_open(adhandle,"logs/pkt_log.pcap"); + + pcap_io_running=1; + emu_printf("Ok.\n"); + return 0; +} + +int gettimeofday (struct timeval *tv, void* tz) +{ + unsigned __int64 ns100; /*time since 1 Jan 1601 in 100ns units */ + + GetSystemTimeAsFileTime((LPFILETIME)&ns100); + tv->tv_usec = (long) ((ns100 / 10L) % 1000000L); + tv->tv_sec = (long) ((ns100 - 116444736000000000L) / 10000000L); + return (0); +} + +int pcap_io_send(void* packet, int plen) +{ + struct pcap_pkthdr ph; + + if(pcap_io_running<=0) + return -1; + emu_printf(" * pcap io: Sending %d byte packet.\n",plen); + + if (pcap_mode==bridged) + { + if(((ethernet_header*)packet)->protocol == 0x0008) //IP + { +#ifndef PLOT_VERSION + virtual_ip = ((ip_header*)((u8*)packet+sizeof(ethernet_header)))->src; +#endif + virtual_mac = ((ethernet_header*)packet)->src; + } + if(((ethernet_header*)packet)->protocol == 0x0608) //ARP + { +#ifndef PLOT_VERSION + virtual_ip = ((arp_packet*)((u8*)packet+sizeof(ethernet_header)))->p_src; +#endif + virtual_mac = ((ethernet_header*)packet)->src; + + ((arp_packet*)((u8*)packet+sizeof(ethernet_header)))->h_src = host_mac; + } + ((ethernet_header*)packet)->src = host_mac; + } + + if(dump_pcap) + { + gettimeofday(&ph.ts,NULL); + ph.caplen=plen; + ph.len=plen; + pcap_dump((u_char*)dump_pcap,&ph,(u_char*)packet); + } + + if(packet_log) + { + int i=0; + int n=0; + + fprintf(packet_log,"PACKET SEND: %d BYTES\n",plen); + for(i=0,n=0;idst,broadcast_mac)==0) + { + static char pack[65536]; + memcpy(pack,packet,plen); + + ((ethernet_header*)packet)->dst=host_mac; + pcap_sendpacket(adhandle, (u_char*)pack, plen); + } + } + + return pcap_sendpacket(adhandle, (u_char*)packet, plen); +} + +int pcap_io_recv(void* packet, int max_len) +{ + int res; + struct pcap_pkthdr *header; + const u_char *pkt_data1; + static u_char pkt_data[32768]; + + if(pcap_io_running<=0) + return -1; + + if((res = pcap_next_ex(adhandle, &header, &pkt_data1)) > 0) + { + ethernet_header *ph=(ethernet_header*)pkt_data; + + memcpy(pkt_data,pkt_data1,header->len); + + if (pcap_mode==bridged) + { + if(((ethernet_header*)pkt_data)->protocol == 0x0008) + { + ip_header *iph=((ip_header*)((u8*)pkt_data+sizeof(ethernet_header))); + if(ip_compare(iph->dst,virtual_ip)==0) + { + ((ethernet_header*)pkt_data)->dst = virtual_mac; + } + } + if(((ethernet_header*)pkt_data)->protocol == 0x0608) + { + arp_packet *aph=((arp_packet*)((u8*)pkt_data+sizeof(ethernet_header))); + if(ip_compare(aph->p_dst,virtual_ip)==0) + { + ((ethernet_header*)pkt_data)->dst = virtual_mac; + ((arp_packet*)((u8*)packet+sizeof(ethernet_header)))->h_dst = virtual_mac; + } + } + } + + if((memcmp(pkt_data,dev9.eeprom,6)!=0)&&(memcmp(pkt_data,&broadcast_mac,6)!=0)) + { + //ignore strange packets + return 0; + } + + if(memcmp(pkt_data+6,dev9.eeprom,6)==0) + { + //avoid pcap looping packets + return 0; + } + + memcpy(packet,pkt_data,header->len); + + if(dump_pcap) + pcap_dump((u_char*)dump_pcap,header,(u_char*)packet); + + + if(packet_log) + { + int i=0; + int n=0; + int plen=header->len; + + fprintf(packet_log,"PACKET RECV: %d BYTES\n",plen); + for(i=0,n=0;ilen; + } + + return -1; +} + +void pcap_io_close() +{ + if(packet_log) + fclose(packet_log); + if(dump_pcap) + pcap_dump_close(dump_pcap); + pcap_close(adhandle); + pcap_io_running=0; +} + + +int pcap_io_get_dev_num() +{ + pcap_if_t *alldevs; + pcap_if_t *d; + int i=0; + + if(pcap_findalldevs(&alldevs, errbuf) == -1) + { + return 0; + } + + d=alldevs; + while(d!=NULL) {d=d->next; i++;} + + pcap_freealldevs(alldevs); + + return i; +} + +char* pcap_io_get_dev_name(int num,int md) +{ + pcap_if_t *alldevs; + pcap_if_t *d; + int i=0; + + if(pcap_findalldevs(&alldevs, errbuf) == -1) + { + return NULL; + } + + d=alldevs; + while(d!=NULL) { + if(num==i) + { + if (!md) + strcpy(namebuff,"pcap switch:"); + else + strcpy(namebuff,"pcap bridge:"); + strcat(namebuff,d->name); + pcap_freealldevs(alldevs); + return namebuff; + } + d=d->next; i++; + } + + pcap_freealldevs(alldevs); + + return NULL; +} + +char* pcap_io_get_dev_desc(int num,int md) +{ + pcap_if_t *alldevs; + pcap_if_t *d; + int i=0; + + if(pcap_findalldevs(&alldevs, errbuf) == -1) + { + return NULL; + } + + d=alldevs; + while(d!=NULL) { + if(num==i) + { + if (!md) + strcpy(namebuff,"pcap switch:"); + else + strcpy(namebuff,"pcap bridge:"); + strcat(namebuff,d->description); + pcap_freealldevs(alldevs); + return namebuff; + } + d=d->next; i++; + } + + pcap_freealldevs(alldevs); + + return NULL; +} + + +PCAPAdapter::PCAPAdapter() +{ + //if (config.ethEnable == 0) return; //whut? nada! + if (config.Eth[5]=='s') + pcap_mode=switched; + else + pcap_mode=bridged; + + if (pcap_io_init(config.Eth+12) == -1) { + SysMessage("Can't open Device '%s'\n", config.Eth); + } +} +bool PCAPAdapter::blocks() +{ + return false; +} +//gets a packet.rv :true success +bool PCAPAdapter::recv(NetPacket* pkt) +{ + int size=pcap_io_recv(pkt->buffer,sizeof(pkt->buffer)); + if(size<=0) + { + return false; + } + else + { + pkt->size=size; + return true; + } +} +//sends the packet .rv :true success +bool PCAPAdapter::send(NetPacket* pkt) +{ + if(pcap_io_send(pkt->buffer,pkt->size)) + { + return false; + } + else + { + return true; + } +} +PCAPAdapter::~PCAPAdapter() +{ + pcap_io_close(); +} diff --git a/plugins/dev9ghzdrk/remote-ext.h b/plugins/dev9ghzdrk/remote-ext.h new file mode 100644 index 000000000..35a2fff6c --- /dev/null +++ b/plugins/dev9ghzdrk/remote-ext.h @@ -0,0 +1,444 @@ +/* + * Copyright (c) 2002 - 2003 + * NetGroup, Politecnico di Torino (Italy) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Politecnico di Torino nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#ifndef __REMOTE_EXT_H__ +#define __REMOTE_EXT_H__ + + +#ifndef HAVE_REMOTE +#error Please do not include this file directly. Just define HAVE_REMOTE and then include pcap.h +#endif + +// Definition for Microsoft Visual Studio +#if _MSC_VER > 1000 +#pragma once +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + \file remote-ext.h + + The goal of this file it to include most of the new definitions that should be + placed into the pcap.h file. + + It includes all new definitions (structures and functions like pcap_open(). + Some of the functions are not really a remote feature, but, right now, + they are placed here. +*/ + + + +// All this stuff is public +/*! \addtogroup remote_struct + \{ +*/ + + + + +/*! + \brief Defines the maximum buffer size in which address, port, interface names are kept. + + In case the adapter name or such is larger than this value, it is truncated. + This is not used by the user; however it must be aware that an hostname / interface + name longer than this value will be truncated. +*/ +#define PCAP_BUF_SIZE 1024 + + +/*! \addtogroup remote_source_ID + \{ +*/ + + +/*! + \brief Internal representation of the type of source in use (file, + remote/local interface). + + This indicates a file, i.e. the user want to open a capture from a local file. +*/ +#define PCAP_SRC_FILE 2 +/*! + \brief Internal representation of the type of source in use (file, + remote/local interface). + + This indicates a local interface, i.e. the user want to open a capture from + a local interface. This does not involve the RPCAP protocol. +*/ +#define PCAP_SRC_IFLOCAL 3 +/*! + \brief Internal representation of the type of source in use (file, + remote/local interface). + + This indicates a remote interface, i.e. the user want to open a capture from + an interface on a remote host. This does involve the RPCAP protocol. +*/ +#define PCAP_SRC_IFREMOTE 4 + +/*! + \} +*/ + + + +/*! \addtogroup remote_source_string + + The formats allowed by the pcap_open() are the following: + - file://path_and_filename [opens a local file] + - rpcap://devicename [opens the selected device devices available on the local host, without using the RPCAP protocol] + - rpcap://host/devicename [opens the selected device available on a remote host] + - rpcap://host:port/devicename [opens the selected device available on a remote host, using a non-standard port for RPCAP] + - adaptername [to open a local adapter; kept for compability, but it is strongly discouraged] + - (NULL) [to open the first local adapter; kept for compability, but it is strongly discouraged] + + The formats allowed by the pcap_findalldevs_ex() are the following: + - file://folder/ [lists all the files in the given folder] + - rpcap:// [lists all local adapters] + - rpcap://host:port/ [lists the devices available on a remote host] + + Referring to the 'host' and 'port' paramters, they can be either numeric or literal. Since + IPv6 is fully supported, these are the allowed formats: + + - host (literal): e.g. host.foo.bar + - host (numeric IPv4): e.g. 10.11.12.13 + - host (numeric IPv4, IPv6 style): e.g. [10.11.12.13] + - host (numeric IPv6): e.g. [1:2:3::4] + - port: can be either numeric (e.g. '80') or literal (e.g. 'http') + + Here you find some allowed examples: + - rpcap://host.foo.bar/devicename [everything literal, no port number] + - rpcap://host.foo.bar:1234/devicename [everything literal, with port number] + - rpcap://10.11.12.13/devicename [IPv4 numeric, no port number] + - rpcap://10.11.12.13:1234/devicename [IPv4 numeric, with port number] + - rpcap://[10.11.12.13]:1234/devicename [IPv4 numeric with IPv6 format, with port number] + - rpcap://[1:2:3::4]/devicename [IPv6 numeric, no port number] + - rpcap://[1:2:3::4]:1234/devicename [IPv6 numeric, with port number] + - rpcap://[1:2:3::4]:http/devicename [IPv6 numeric, with literal port number] + + \{ +*/ + + +/*! + \brief String that will be used to determine the type of source in use (file, + remote/local interface). + + This string will be prepended to the interface name in order to create a string + that contains all the information required to open the source. + + This string indicates that the user wants to open a capture from a local file. +*/ +#define PCAP_SRC_FILE_STRING "file://" +/*! + \brief String that will be used to determine the type of source in use (file, + remote/local interface). + + This string will be prepended to the interface name in order to create a string + that contains all the information required to open the source. + + This string indicates that the user wants to open a capture from a network interface. + This string does not necessarily involve the use of the RPCAP protocol. If the + interface required resides on the local host, the RPCAP protocol is not involved + and the local functions are used. +*/ +#define PCAP_SRC_IF_STRING "rpcap://" + +/*! + \} +*/ + + + + + +/*! + \addtogroup remote_open_flags + \{ +*/ + +/*! + \brief Defines if the adapter has to go in promiscuous mode. + + It is '1' if you have to open the adapter in promiscuous mode, '0' otherwise. + Note that even if this parameter is false, the interface could well be in promiscuous + mode for some other reason (for example because another capture process with + promiscuous mode enabled is currently using that interface). + On on Linux systems with 2.2 or later kernels (that have the "any" device), this + flag does not work on the "any" device; if an argument of "any" is supplied, + the 'promisc' flag is ignored. +*/ +#define PCAP_OPENFLAG_PROMISCUOUS 1 + +/*! + \brief Defines if the data trasfer (in case of a remote + capture) has to be done with UDP protocol. + + If it is '1' if you want a UDP data connection, '0' if you want + a TCP data connection; control connection is always TCP-based. + A UDP connection is much lighter, but it does not guarantee that all + the captured packets arrive to the client workstation. Moreover, + it could be harmful in case of network congestion. + This flag is meaningless if the source is not a remote interface. + In that case, it is simply ignored. +*/ +#define PCAP_OPENFLAG_DATATX_UDP 2 + + +/*! + \brief Defines if the remote probe will capture its own generated traffic. + + In case the remote probe uses the same interface to capture traffic and to send + data back to the caller, the captured traffic includes the RPCAP traffic as well. + If this flag is turned on, the RPCAP traffic is excluded from the capture, so that + the trace returned back to the collector is does not include this traffic. +*/ +#define PCAP_OPENFLAG_NOCAPTURE_RPCAP 4 + +/*! + \brief Defines if the local adapter will capture its own generated traffic. + + This flag tells the underlying capture driver to drop the packets that were sent by itself. + This is usefult when building applications like bridges, that should ignore the traffic + they just sent. +*/ +#define PCAP_OPENFLAG_NOCAPTURE_LOCAL 8 + +/*! + \brief This flag configures the adapter for maximum responsiveness. + + In presence of a large value for nbytes, WinPcap waits for the arrival of several packets before + copying the data to the user. This guarantees a low number of system calls, i.e. lower processor usage, + i.e. better performance, which is good for applications like sniffers. If the user sets the + PCAP_OPENFLAG_MAX_RESPONSIVENESS flag, the capture driver will copy the packets as soon as the application + is ready to receive them. This is suggested for real time applications (like, for example, a bridge) + that need the best responsiveness.*/ +#define PCAP_OPENFLAG_MAX_RESPONSIVENESS 16 + +/*! + \} +*/ + + +/*! + \addtogroup remote_samp_methods + \{ +*/ + +/*! + \brief No sampling has to be done on the current capture. + + In this case, no sampling algorithms are applied to the current capture. +*/ +#define PCAP_SAMP_NOSAMP 0 + +/*! + \brief It defines that only 1 out of N packets must be returned to the user. + + In this case, the 'value' field of the 'pcap_samp' structure indicates the + number of packets (minus 1) that must be discarded before one packet got accepted. + In other words, if 'value = 10', the first packet is returned to the caller, while + the following 9 are discarded. +*/ +#define PCAP_SAMP_1_EVERY_N 1 + +/*! + \brief It defines that we have to return 1 packet every N milliseconds. + + In this case, the 'value' field of the 'pcap_samp' structure indicates the 'waiting + time' in milliseconds before one packet got accepted. + In other words, if 'value = 10', the first packet is returned to the caller; the next + returned one will be the first packet that arrives when 10ms have elapsed. +*/ +#define PCAP_SAMP_FIRST_AFTER_N_MS 2 + +/*! + \} +*/ + + +/*! + \addtogroup remote_auth_methods + \{ +*/ + +/*! + \brief It defines the NULL authentication. + + This value has to be used within the 'type' member of the pcap_rmtauth structure. + The 'NULL' authentication has to be equal to 'zero', so that old applications + can just put every field of struct pcap_rmtauth to zero, and it does work. +*/ +#define RPCAP_RMTAUTH_NULL 0 +/*! + \brief It defines the username/password authentication. + + With this type of authentication, the RPCAP protocol will use the username/ + password provided to authenticate the user on the remote machine. If the + authentication is successful (and the user has the right to open network devices) + the RPCAP connection will continue; otherwise it will be dropped. + + This value has to be used within the 'type' member of the pcap_rmtauth structure. +*/ +#define RPCAP_RMTAUTH_PWD 1 + +/*! + \} +*/ + + + + +/*! + + \brief This structure keeps the information needed to autheticate + the user on a remote machine. + + The remote machine can either grant or refuse the access according + to the information provided. + In case the NULL authentication is required, both 'username' and + 'password' can be NULL pointers. + + This structure is meaningless if the source is not a remote interface; + in that case, the functions which requires such a structure can accept + a NULL pointer as well. +*/ +struct pcap_rmtauth +{ + /*! + \brief Type of the authentication required. + + In order to provide maximum flexibility, we can support different types + of authentication based on the value of this 'type' variable. The currently + supported authentication methods are defined into the + \link remote_auth_methods Remote Authentication Methods Section\endlink. + + */ + int type; + /*! + \brief Zero-terminated string containing the username that has to be + used on the remote machine for authentication. + + This field is meaningless in case of the RPCAP_RMTAUTH_NULL authentication + and it can be NULL. + */ + char *username; + /*! + \brief Zero-terminated string containing the password that has to be + used on the remote machine for authentication. + + This field is meaningless in case of the RPCAP_RMTAUTH_NULL authentication + and it can be NULL. + */ + char *password; +}; + + +/*! + \brief This structure defines the information related to sampling. + + In case the sampling is requested, the capturing device should read + only a subset of the packets coming from the source. The returned packets depend + on the sampling parameters. + + \warning The sampling process is applied after the filtering process. + In other words, packets are filtered first, then the sampling process selects a + subset of the 'filtered' packets and it returns them to the caller. +*/ +struct pcap_samp +{ + /*! + Method used for sampling. Currently, the supported methods are listed in the + \link remote_samp_methods Sampling Methods Section\endlink. + */ + int method; + + /*! + This value depends on the sampling method defined. For its meaning, please check + at the \link remote_samp_methods Sampling Methods Section\endlink. + */ + int value; +}; + + + + +//! Maximum lenght of an host name (needed for the RPCAP active mode) +#define RPCAP_HOSTLIST_SIZE 1024 + + +/*! + \} +*/ // end of public documentation + + +// Exported functions + + + +/** \name New WinPcap functions + + This section lists the new functions that are able to help considerably in writing + WinPcap programs because of their easiness of use. + */ +//\{ +pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf); +int pcap_createsrcstr(char *source, int type, const char *host, const char *port, const char *name, char *errbuf); +int pcap_parsesrcstr(const char *source, int *type, char *host, char *port, char *name, char *errbuf); +int pcap_findalldevs_ex(char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf); +struct pcap_samp *pcap_setsampling(pcap_t *p); + +//\} +// End of new winpcap functions + + + +/** \name Remote Capture functions + */ +//\{ +SOCKET pcap_remoteact_accept(const char *address, const char *port, const char *hostlist, char *connectinghost, struct pcap_rmtauth *auth, char *errbuf); +int pcap_remoteact_list(char *hostlist, char sep, int size, char *errbuf); +int pcap_remoteact_close(const char *host, char *errbuf); +void pcap_remoteact_cleanup(); +//\} +// End of remote capture functions + +#ifdef __cplusplus +} +#endif + + +#endif + From 6ac678d34f0cd08e9ab38a39677f25aab196045f Mon Sep 17 00:00:00 2001 From: "ramapcsx2.code" Date: Tue, 19 Mar 2013 22:21:48 +0000 Subject: [PATCH 46/81] DEV9ghzdrk: These files aren't needed. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5596 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/dev9ghzdrk/Win32/DEV9ghzdrk.def | 2 +- plugins/dev9ghzdrk/Win32/postBuild.cmd | 50 -------------------- plugins/dev9ghzdrk/Win32/svnrev.h | 33 ------------- plugins/dev9ghzdrk/pcap/wpcap_64/Packet.dll | Bin 80384 -> 0 bytes plugins/dev9ghzdrk/pcap/wpcap_64/Packet.lib | Bin 8286 -> 0 bytes plugins/dev9ghzdrk/pcap/wpcap_64/wpcap.dll | Bin 252416 -> 0 bytes plugins/dev9ghzdrk/pcap/wpcap_64/wpcap.lib | Bin 17046 -> 0 bytes 7 files changed, 1 insertion(+), 84 deletions(-) delete mode 100644 plugins/dev9ghzdrk/Win32/postBuild.cmd delete mode 100644 plugins/dev9ghzdrk/Win32/svnrev.h delete mode 100644 plugins/dev9ghzdrk/pcap/wpcap_64/Packet.dll delete mode 100644 plugins/dev9ghzdrk/pcap/wpcap_64/Packet.lib delete mode 100644 plugins/dev9ghzdrk/pcap/wpcap_64/wpcap.dll delete mode 100644 plugins/dev9ghzdrk/pcap/wpcap_64/wpcap.lib diff --git a/plugins/dev9ghzdrk/Win32/DEV9ghzdrk.def b/plugins/dev9ghzdrk/Win32/DEV9ghzdrk.def index 1bde44b8a..22ac653bf 100644 --- a/plugins/dev9ghzdrk/Win32/DEV9ghzdrk.def +++ b/plugins/dev9ghzdrk/Win32/DEV9ghzdrk.def @@ -1,4 +1,4 @@ -; DEV9null.def : Declares the module parameters for the DLL. +; DEV9ghzdrk.def : Declares the module parameters for the DLL. EXPORTS diff --git a/plugins/dev9ghzdrk/Win32/postBuild.cmd b/plugins/dev9ghzdrk/Win32/postBuild.cmd deleted file mode 100644 index 2d13fa707..000000000 --- a/plugins/dev9ghzdrk/Win32/postBuild.cmd +++ /dev/null @@ -1,50 +0,0 @@ -::@echo off -:: -:: Usage: postBuild.cmd SourcePath DestFile DestExt {plugins} -:: -:: SourcePath - $(TargetPath) - Fully qualified path of the generated target file. -:: DestFile - Base filename of the target/dest, without extension! -:: DestExt - Extension of the target/dest! -:: plugins - optional parameter used to generate plugins into the /plugins folder -:: -:: The destination file is determined by the PCSX2_TARGET_DIR environment var. - -SETLOCAL ENABLEEXTENSIONS -if defined PCSX2_TARGET_COPY CALL :TestAndCopy "%PCSX2_TARGET_COPY%" %1 %2 %3 %4 -ENDLOCAL -exit 0 - - -:TestAndCopy -:: Subroutine. First parameter is our Target Dir. Since it's a parameter into -:: the subroutine, we can use tilda expansion to handle quotes correctly. :) - -if NOT EXIST "%~1" ( - md "%~1" -) - -:: Error checking. Try to change to the dir. If it fails, it means the dir is -:: actually a file, and we should cancel the script. - -set mycwd="%CD%" -cd "%~1" -if %ERRORLEVEL% NEQ 0 goto :eof -cd %mycwd% - -set pcsxoutdir=%~1\%~5 -set pcsxoutname=%pcsxoutdir%\%~3%4 -set pcsxnewname=%pcsxoutdir%\%~3-r0%4 - -IF NOT EXIST "%pcsxoutdir%" ( - md "%pcsxoutdir%" -) - -copy /Y "%~2" "%pcsxoutname%" -copy /Y "%~2" "%pcsxnewname%" -if %ERRORLEVEL% EQU 0 ( - echo Target copied to %pcsxnewname% -) - -goto :eof - -:quit diff --git a/plugins/dev9ghzdrk/Win32/svnrev.h b/plugins/dev9ghzdrk/Win32/svnrev.h deleted file mode 100644 index b9fa556f9..000000000 --- a/plugins/dev9ghzdrk/Win32/svnrev.h +++ /dev/null @@ -1,33 +0,0 @@ -/* 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 . -*/ - -// svnrev_template.h --> 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 0 -#define SVN_MODS 0 diff --git a/plugins/dev9ghzdrk/pcap/wpcap_64/Packet.dll b/plugins/dev9ghzdrk/pcap/wpcap_64/Packet.dll deleted file mode 100644 index 102954e96abc488efff5373e45f66a9c7673c4eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 80384 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 diff --git a/plugins/dev9ghzdrk/pcap/wpcap_64/Packet.lib b/plugins/dev9ghzdrk/pcap/wpcap_64/Packet.lib deleted file mode 100644 index 8529e0f0a7f75a55372eec44ae50c2e639b111a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8286 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 b)KiE$;pThSdo}Q04ZK$a@72J6OAY*AStsGh diff --git a/plugins/dev9ghzdrk/pcap/wpcap_64/wpcap.lib b/plugins/dev9ghzdrk/pcap/wpcap_64/wpcap.lib deleted file mode 100644 index abacd5d3652d38e0116fced9b25df4f75fc667db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17046 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 Date: Tue, 19 Mar 2013 23:08:29 +0000 Subject: [PATCH 47/81] DEV9ghzdrk: Either be thread safe in the whole plugin or don't try to at all. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5597 96395faa-99c1-11dd-bbfe-3dabce05a288 --- .../Win32/DEV9ghzdrk.vcxproj.filters | 10 ++--- plugins/dev9ghzdrk/Win32/smap.cpp | 44 +++++-------------- plugins/dev9ghzdrk/Win32/tap-win32.cpp | 4 -- 3 files changed, 16 insertions(+), 42 deletions(-) diff --git a/plugins/dev9ghzdrk/Win32/DEV9ghzdrk.vcxproj.filters b/plugins/dev9ghzdrk/Win32/DEV9ghzdrk.vcxproj.filters index 4225c129d..3a59b7752 100644 --- a/plugins/dev9ghzdrk/Win32/DEV9ghzdrk.vcxproj.filters +++ b/plugins/dev9ghzdrk/Win32/DEV9ghzdrk.vcxproj.filters @@ -61,11 +61,6 @@ Source Files\ethernet i/o\pcap - - - Source Files - - Source Files @@ -94,4 +89,9 @@ Resource Files + + + Resource Files + + \ No newline at end of file diff --git a/plugins/dev9ghzdrk/Win32/smap.cpp b/plugins/dev9ghzdrk/Win32/smap.cpp index 942582b7c..54d274f39 100644 --- a/plugins/dev9ghzdrk/Win32/smap.cpp +++ b/plugins/dev9ghzdrk/Win32/smap.cpp @@ -101,19 +101,7 @@ void rx_process(NetPacket* pk) pbd->ctrl_stat&= ~SMAP_BD_RX_EMPTY; //increase frame count - u8* cntptr=&dev9Ru8(SMAP_R_RXFIFO_FRAME_CNT); - -#ifdef WIN_X64 - *cntptr++; //no asm inline in x64 -#else - __asm - { - //this is silly - mov eax,[cntptr]; - lock inc byte ptr [eax] - } -#endif - + dev9Ru8(SMAP_R_RXFIFO_FRAME_CNT)++; //spams// emu_printf("Got packet, %d bytes (%d fifo)\n", pk->size,bytes); _DEV9irq(SMAP_INTR_RXEND,0);//now ? or when the fifo is full ? i guess now atm //note that this _is_ wrong since the IOP interrupt system is not thread safe.. but nothing i can do about that @@ -131,15 +119,15 @@ void tx_process() //spams// printf("tx_process : %d cnt frames !\n",cnt); // this hack worsens OPL performance. Is it really needed? OPL works fine without. (rama) - if (!tx_p_first) - { - dev9Ru8(SMAP_R_TXFIFO_FRAME_CNT)=0; - tx_p_first=true; - //THIS IS A HACK.without that the stack wont init, i guess its missing e3/emac emulation .. - emu_printf("WARN : First packet interrupt hack ..\n"); - _DEV9irq(SMAP_INTR_RXEND|SMAP_INTR_TXEND|SMAP_INTR_TXDNV,100); - return; - } + //if (!tx_p_first) + //{ + // dev9Ru8(SMAP_R_TXFIFO_FRAME_CNT)=0; + // tx_p_first=true; + // //THIS IS A HACK.without that the stack wont init, i guess its missing e3/emac emulation .. + // emu_printf("WARN : First packet interrupt hack ..\n"); + // _DEV9irq(SMAP_INTR_RXEND|SMAP_INTR_TXEND|SMAP_INTR_TXDNV,100); + // return; + //} NetPacket pk; int fc=0; @@ -554,17 +542,7 @@ void CALLBACK smap_write8(u32 addr, u8 value) DEV9_LOG("SMAP_R_RXFIFO_FRAME_DEC 8bit write %x\n", value); dev9Ru8(addr) = value; { - u8* cntptr=&dev9Ru8(SMAP_R_RXFIFO_FRAME_CNT); -#ifdef WIN_X64 - *cntptr--; //no asm inline in x64 -#else - __asm - { - //this is silly - mov eax,[cntptr]; - lock dec byte ptr [eax] - } -#endif + dev9Ru8(SMAP_R_RXFIFO_FRAME_CNT)--; } return; diff --git a/plugins/dev9ghzdrk/Win32/tap-win32.cpp b/plugins/dev9ghzdrk/Win32/tap-win32.cpp index 27afd4520..9c4ceb435 100644 --- a/plugins/dev9ghzdrk/Win32/tap-win32.cpp +++ b/plugins/dev9ghzdrk/Win32/tap-win32.cpp @@ -64,11 +64,7 @@ #define USERMODEDEVICEDIR "\\\\.\\Global\\" #define TAPSUFFIX ".tap" -#ifdef WIN_X64 -#define TAP_COMPONENT_ID "tap0901" -#else #define TAP_COMPONENT_ID "tap0801" -#endif vector* get_tap_reg () { From 7a00d19b55a1c4ebddc655e031f21b5823843200 Mon Sep 17 00:00:00 2001 From: "ramapcsx2.code" Date: Tue, 19 Mar 2013 23:43:16 +0000 Subject: [PATCH 48/81] DEV9ghzdrk: Fixed the bad slowness. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5598 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/dev9ghzdrk/DEV9.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/dev9ghzdrk/DEV9.cpp b/plugins/dev9ghzdrk/DEV9.cpp index 7c4a08acf..992d83043 100644 --- a/plugins/dev9ghzdrk/DEV9.cpp +++ b/plugins/dev9ghzdrk/DEV9.cpp @@ -37,9 +37,6 @@ u8 eeprom[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; - -int Log = 1; - u32 *iopPC; const unsigned char version = PS2E_DEV9_VERSION; @@ -68,7 +65,11 @@ u32 CALLBACK PS2EgetLibVersion2(u32 type) { return (version<<16) | (revision<<8) | build; } +// Warning: The below log function is SLOW. Better fix it before attempting to use it. +int Log = 0; + void __Log(char *fmt, ...) { + if (!Log) return; va_list list; static int ticks=-1; @@ -76,7 +77,6 @@ void __Log(char *fmt, ...) { if(ticks==-1) ticks=nticks; -// if (!Log) return; if(iopPC!=NULL) { fprintf(dev9Log,"[%10d + %4d, IOP PC = %08x] ",nticks,nticks-ticks,*iopPC); From e32a18dac4c2a01c5ba7d0bb0a924610abf93402 Mon Sep 17 00:00:00 2001 From: "ramapcsx2.code" Date: Wed, 20 Mar 2013 13:58:00 +0000 Subject: [PATCH 49/81] Added WinPcap to the library of 3rd party includes and made DEV9ghzdrk use them. WinPcap version is 4.1.2 and only the /include and /lib folders of their developer pack are included. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5599 96395faa-99c1-11dd-bbfe-3dabce05a288 --- .../winpcap/include}/Packet32.h | 718 +++++++------- .../winpcap/include}/Win32-Extensions.h | 226 ++--- .../winpcap/include}/bittypes.h | 0 .../winpcap/include}/ip6_misc.h | 0 .../winpcap/include}/pcap-bpf.h | 0 .../winpcap/include}/pcap-namedb.h | 0 .../winpcap/include}/pcap-stdinc.h | 0 .../winpcap/include}/pcap.h | 0 .../winpcap/include}/pcap/bluetooth.h | 0 .../winpcap/include}/pcap/bpf.h | 0 .../winpcap/include}/pcap/namedb.h | 0 .../winpcap/include}/pcap/pcap.h | 0 .../winpcap/include}/pcap/sll.h | 0 .../winpcap/include}/pcap/usb.h | 0 .../winpcap/include}/pcap/vlan.h | 0 .../winpcap/include}/remote-ext.h | 888 +++++++++--------- 3rdparty/winpcap/lib/Packet.lib | Bin 0 -> 8450 bytes 3rdparty/winpcap/lib/wpcap.lib | Bin 0 -> 19320 bytes 3rdparty/winpcap/lib/x64/Packet.lib | Bin 0 -> 8290 bytes 3rdparty/winpcap/lib/x64/wpcap.lib | Bin 0 -> 18892 bytes 3rdparty/winpcap/readme.txt | 3 + plugins/dev9ghzdrk/Win32/Config.cpp | 2 +- plugins/dev9ghzdrk/Win32/DEV9ghzdrk.vcxproj | 8 +- plugins/dev9ghzdrk/Win32/Win32.cpp | 2 +- plugins/dev9ghzdrk/Win32/net.cpp | 2 +- plugins/dev9ghzdrk/Win32/smap.h | 2 +- plugins/dev9ghzdrk/Win32/tap-win32.cpp | 2 +- plugins/dev9ghzdrk/pcap/wpcap_32/Packet.dll | Bin 88696 -> 0 bytes plugins/dev9ghzdrk/pcap/wpcap_32/Packet.lib | Bin 8674 -> 0 bytes plugins/dev9ghzdrk/pcap/wpcap_32/wpcap.dll | Bin 244336 -> 0 bytes plugins/dev9ghzdrk/pcap/wpcap_32/wpcap.lib | Bin 17658 -> 0 bytes 31 files changed, 928 insertions(+), 925 deletions(-) rename {plugins/dev9ghzdrk => 3rdparty/winpcap/include}/Packet32.h (97%) rename {plugins/dev9ghzdrk => 3rdparty/winpcap/include}/Win32-Extensions.h (97%) rename {plugins/dev9ghzdrk => 3rdparty/winpcap/include}/bittypes.h (100%) rename {plugins/dev9ghzdrk => 3rdparty/winpcap/include}/ip6_misc.h (100%) rename {plugins/dev9ghzdrk => 3rdparty/winpcap/include}/pcap-bpf.h (100%) rename {plugins/dev9ghzdrk => 3rdparty/winpcap/include}/pcap-namedb.h (100%) rename {plugins/dev9ghzdrk => 3rdparty/winpcap/include}/pcap-stdinc.h (100%) rename {plugins/dev9ghzdrk => 3rdparty/winpcap/include}/pcap.h (100%) rename {plugins/dev9ghzdrk => 3rdparty/winpcap/include}/pcap/bluetooth.h (100%) rename {plugins/dev9ghzdrk => 3rdparty/winpcap/include}/pcap/bpf.h (100%) rename {plugins/dev9ghzdrk => 3rdparty/winpcap/include}/pcap/namedb.h (100%) rename {plugins/dev9ghzdrk => 3rdparty/winpcap/include}/pcap/pcap.h (100%) rename {plugins/dev9ghzdrk => 3rdparty/winpcap/include}/pcap/sll.h (100%) rename {plugins/dev9ghzdrk => 3rdparty/winpcap/include}/pcap/usb.h (100%) rename {plugins/dev9ghzdrk => 3rdparty/winpcap/include}/pcap/vlan.h (100%) rename {plugins/dev9ghzdrk => 3rdparty/winpcap/include}/remote-ext.h (97%) create mode 100644 3rdparty/winpcap/lib/Packet.lib create mode 100644 3rdparty/winpcap/lib/wpcap.lib create mode 100644 3rdparty/winpcap/lib/x64/Packet.lib create mode 100644 3rdparty/winpcap/lib/x64/wpcap.lib create mode 100644 3rdparty/winpcap/readme.txt delete mode 100644 plugins/dev9ghzdrk/pcap/wpcap_32/Packet.dll delete mode 100644 plugins/dev9ghzdrk/pcap/wpcap_32/Packet.lib delete mode 100644 plugins/dev9ghzdrk/pcap/wpcap_32/wpcap.dll delete mode 100644 plugins/dev9ghzdrk/pcap/wpcap_32/wpcap.lib diff --git a/plugins/dev9ghzdrk/Packet32.h b/3rdparty/winpcap/include/Packet32.h similarity index 97% rename from plugins/dev9ghzdrk/Packet32.h rename to 3rdparty/winpcap/include/Packet32.h index 64be055d9..1e0eacd77 100644 --- a/plugins/dev9ghzdrk/Packet32.h +++ b/3rdparty/winpcap/include/Packet32.h @@ -1,359 +1,359 @@ -/* - * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy) - * Copyright (c) 2005 - 2007 CACE Technologies, Davis (California) - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Politecnico di Torino, CACE Technologies - * nor the names of its contributors may be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** @ingroup packetapi - * @{ - */ - -/** @defgroup packet32h Packet.dll definitions and data structures - * Packet32.h contains the data structures and the definitions used by packet.dll. - * The file is used both by the Win9x and the WinNTx versions of packet.dll, and can be included - * by the applications that use the functions of this library - * @{ - */ - -#ifndef __PACKET32 -#define __PACKET32 - -#include - -#ifdef HAVE_AIRPCAP_API -#include -#else -#if !defined(AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_) -#define AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_ -typedef struct _AirpcapHandle *PAirpcapHandle; -#endif /* AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_ */ -#endif /* HAVE_AIRPCAP_API */ - -#ifdef HAVE_DAG_API -#include -#endif /* HAVE_DAG_API */ - -// Working modes -#define PACKET_MODE_CAPT 0x0 ///< Capture mode -#define PACKET_MODE_STAT 0x1 ///< Statistical mode -#define PACKET_MODE_MON 0x2 ///< Monitoring mode -#define PACKET_MODE_DUMP 0x10 ///< Dump mode -#define PACKET_MODE_STAT_DUMP MODE_DUMP | MODE_STAT ///< Statistical dump Mode - - -/// Alignment macro. Defines the alignment size. -#define Packet_ALIGNMENT sizeof(int) -/// Alignment macro. Rounds up to the next even multiple of Packet_ALIGNMENT. -#define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1)) - -#define NdisMediumNull -1 ///< Custom linktype: NDIS doesn't provide an equivalent -#define NdisMediumCHDLC -2 ///< Custom linktype: NDIS doesn't provide an equivalent -#define NdisMediumPPPSerial -3 ///< Custom linktype: NDIS doesn't provide an equivalent -#define NdisMediumBare80211 -4 ///< Custom linktype: NDIS doesn't provide an equivalent -#define NdisMediumRadio80211 -5 ///< Custom linktype: NDIS doesn't provide an equivalent -#define NdisMediumPpi -6 ///< Custom linktype: NDIS doesn't provide an equivalent - -// Loopback behaviour definitions -#define NPF_DISABLE_LOOPBACK 1 ///< Drop the packets sent by the NPF driver -#define NPF_ENABLE_LOOPBACK 2 ///< Capture the packets sent by the NPF driver - -/*! - \brief Network type structure. - - This structure is used by the PacketGetNetType() function to return information on the current adapter's type and speed. -*/ -typedef struct NetType -{ - UINT LinkType; ///< The MAC of the current network adapter (see function PacketGetNetType() for more information) - ULONGLONG LinkSpeed; ///< The speed of the network in bits per second -}NetType; - - -//some definitions stolen from libpcap - -#ifndef BPF_MAJOR_VERSION - -/*! - \brief A BPF pseudo-assembly program. - - The program will be injected in the kernel by the PacketSetBPF() function and applied to every incoming packet. -*/ -struct bpf_program -{ - UINT bf_len; ///< Indicates the number of instructions of the program, i.e. the number of struct bpf_insn that will follow. - struct bpf_insn *bf_insns; ///< A pointer to the first instruction of the program. -}; - -/*! - \brief A single BPF pseudo-instruction. - - bpf_insn contains a single instruction for the BPF register-machine. It is used to send a filter program to the driver. -*/ -struct bpf_insn -{ - USHORT code; ///< Instruction type and addressing mode. - UCHAR jt; ///< Jump if true - UCHAR jf; ///< Jump if false - int k; ///< Generic field used for various purposes. -}; - -/*! - \brief Structure that contains a couple of statistics values on the current capture. - - It is used by packet.dll to return statistics about a capture session. -*/ -struct bpf_stat -{ - UINT bs_recv; ///< Number of packets that the driver received from the network adapter - ///< from the beginning of the current capture. This value includes the packets - ///< lost by the driver. - UINT bs_drop; ///< number of packets that the driver lost from the beginning of a capture. - ///< Basically, a packet is lost when the the buffer of the driver is full. - ///< In this situation the packet cannot be stored and the driver rejects it. - UINT ps_ifdrop; ///< drops by interface. XXX not yet supported - UINT bs_capt; ///< number of packets that pass the filter, find place in the kernel buffer and - ///< thus reach the application. -}; - -/*! - \brief Packet header. - - This structure defines the header associated with every packet delivered to the application. -*/ -struct bpf_hdr -{ - struct timeval bh_tstamp; ///< The timestamp associated with the captured packet. - ///< It is stored in a TimeVal structure. - UINT bh_caplen; ///< Length of captured portion. The captured portion can be different - ///< from the original packet, because it is possible (with a proper filter) - ///< to instruct the driver to capture only a portion of the packets. - UINT bh_datalen; ///< Original length of packet - USHORT bh_hdrlen; ///< Length of bpf header (this struct plus alignment padding). In some cases, - ///< a padding could be added between the end of this structure and the packet - ///< data for performance reasons. This filed can be used to retrieve the actual data - ///< of the packet. -}; - -/*! - \brief Dump packet header. - - This structure defines the header associated with the packets in a buffer to be used with PacketSendPackets(). - It is simpler than the bpf_hdr, because it corresponds to the header associated by WinPcap and libpcap to a - packet in a dump file. This makes straightforward sending WinPcap dump files to the network. -*/ -struct dump_bpf_hdr{ - struct timeval ts; ///< Time stamp of the packet - UINT caplen; ///< Length of captured portion. The captured portion can smaller than the - ///< the original packet, because it is possible (with a proper filter) to - ///< instruct the driver to capture only a portion of the packets. - UINT len; ///< Length of the original packet (off wire). -}; - - -#endif - -struct bpf_stat; - -#define DOSNAMEPREFIX TEXT("Packet_") ///< Prefix added to the adapters device names to create the WinPcap devices -#define MAX_LINK_NAME_LENGTH 64 //< Maximum length of the devices symbolic links -#define NMAX_PACKET 65535 - -/*! - \brief Addresses of a network adapter. - - This structure is used by the PacketGetNetInfoEx() function to return the IP addresses associated with - an adapter. -*/ -typedef struct npf_if_addr { - struct sockaddr_storage IPAddress; ///< IP address. - struct sockaddr_storage SubnetMask; ///< Netmask for that address. - struct sockaddr_storage Broadcast; ///< Broadcast address. -}npf_if_addr; - - -#define ADAPTER_NAME_LENGTH 256 + 12 ///< Maximum length for the name of an adapter. The value is the same used by the IP Helper API. -#define ADAPTER_DESC_LENGTH 128 ///< Maximum length for the description of an adapter. The value is the same used by the IP Helper API. -#define MAX_MAC_ADDR_LENGTH 8 ///< Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API. -#define MAX_NETWORK_ADDRESSES 16 ///< Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API. - - -typedef struct WAN_ADAPTER_INT WAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API -typedef WAN_ADAPTER *PWAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API - -#define INFO_FLAG_NDIS_ADAPTER 0 ///< Flag for ADAPTER_INFO: this is a traditional ndis adapter -#define INFO_FLAG_NDISWAN_ADAPTER 1 ///< Flag for ADAPTER_INFO: this is a NdisWan adapter, and it's managed by WANPACKET -#define INFO_FLAG_DAG_CARD 2 ///< Flag for ADAPTER_INFO: this is a DAG card -#define INFO_FLAG_DAG_FILE 6 ///< Flag for ADAPTER_INFO: this is a DAG file -#define INFO_FLAG_DONT_EXPORT 8 ///< Flag for ADAPTER_INFO: when this flag is set, the adapter will not be listed or openend by winpcap. This allows to prevent exporting broken network adapters, like for example FireWire ones. -#define INFO_FLAG_AIRPCAP_CARD 16 ///< Flag for ADAPTER_INFO: this is an airpcap card -#define INFO_FLAG_NPFIM_DEVICE 32 - -/*! - \brief Describes an opened network adapter. - - This structure is the most important for the functioning of packet.dll, but the great part of its fields - should be ignored by the user, since the library offers functions that avoid to cope with low-level parameters -*/ -typedef struct _ADAPTER { - HANDLE hFile; ///< \internal Handle to an open instance of the NPF driver. - CHAR SymbolicLink[MAX_LINK_NAME_LENGTH]; ///< \internal A string containing the name of the network adapter currently opened. - int NumWrites; ///< \internal Number of times a packets written on this adapter will be repeated - ///< on the wire. - HANDLE ReadEvent; ///< A notification event associated with the read calls on the adapter. - ///< It can be passed to standard Win32 functions (like WaitForSingleObject - ///< or WaitForMultipleObjects) to wait until the driver's buffer contains some - ///< data. It is particularly useful in GUI applications that need to wait - ///< concurrently on several events. In Windows NT/2000 the PacketSetMinToCopy() - ///< function can be used to define the minimum amount of data in the kernel buffer - ///< that will cause the event to be signalled. - - UINT ReadTimeOut; ///< \internal The amount of time after which a read on the driver will be released and - ///< ReadEvent will be signaled, also if no packets were captured - CHAR Name[ADAPTER_NAME_LENGTH]; - PWAN_ADAPTER pWanAdapter; - UINT Flags; ///< Adapter's flags. Tell if this adapter must be treated in a different way, using the Netmon API or the dagc API. - -#ifdef HAVE_AIRPCAP_API - PAirpcapHandle AirpcapAd; -#endif // HAVE_AIRPCAP_API - -#ifdef HAVE_NPFIM_API - void* NpfImHandle; -#endif // HAVE_NPFIM_API - -#ifdef HAVE_DAG_API - dagc_t *pDagCard; ///< Pointer to the dagc API adapter descriptor for this adapter - PCHAR DagBuffer; ///< Pointer to the buffer with the packets that is received from the DAG card - struct timeval DagReadTimeout; ///< Read timeout. The dagc API requires a timeval structure - unsigned DagFcsLen; ///< Length of the frame check sequence attached to any packet by the card. Obtained from the registry - DWORD DagFastProcess; ///< True if the user requests fast capture processing on this card. Higher level applications can use this value to provide a faster but possibly unprecise capture (for example, libpcap doesn't convert the timestamps). -#endif // HAVE_DAG_API -} ADAPTER, *LPADAPTER; - -/*! - \brief Structure that contains a group of packets coming from the driver. - - This structure defines the header associated with every packet delivered to the application. -*/ -typedef struct _PACKET { - HANDLE hEvent; ///< \deprecated Still present for compatibility with old applications. - OVERLAPPED OverLapped; ///< \deprecated Still present for compatibility with old applications. - PVOID Buffer; ///< Buffer with containing the packets. See the PacketReceivePacket() for - ///< details about the organization of the data in this buffer - UINT Length; ///< Length of the buffer - DWORD ulBytesReceived; ///< Number of valid bytes present in the buffer, i.e. amount of data - ///< received by the last call to PacketReceivePacket() - BOOLEAN bIoComplete; ///< \deprecated Still present for compatibility with old applications. -} PACKET, *LPPACKET; - -/*! - \brief Structure containing an OID request. - - It is used by the PacketRequest() function to send an OID to the interface card driver. - It can be used, for example, to retrieve the status of the error counters on the adapter, its MAC address, - the list of the multicast groups defined on it, and so on. -*/ -struct _PACKET_OID_DATA { - ULONG Oid; ///< OID code. See the Microsoft DDK documentation or the file ntddndis.h - ///< for a complete list of valid codes. - ULONG Length; ///< Length of the data field - UCHAR Data[1]; ///< variable-lenght field that contains the information passed to or received - ///< from the adapter. -}; -typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @} - */ - -/* -BOOLEAN QueryWinPcapRegistryStringA(CHAR *SubKeyName, - CHAR *Value, - UINT *pValueLen, - CHAR *DefaultVal); - -BOOLEAN QueryWinPcapRegistryStringW(WCHAR *SubKeyName, - WCHAR *Value, - UINT *pValueLen, - WCHAR *DefaultVal); -*/ - -//--------------------------------------------------------------------------- -// EXPORTED FUNCTIONS -//--------------------------------------------------------------------------- - -PCHAR PacketGetVersion(); -PCHAR PacketGetDriverVersion(); -BOOLEAN PacketSetMinToCopy(LPADAPTER AdapterObject,int nbytes); -BOOLEAN PacketSetNumWrites(LPADAPTER AdapterObject,int nwrites); -BOOLEAN PacketSetMode(LPADAPTER AdapterObject,int mode); -BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout); -BOOLEAN PacketSetBpf(LPADAPTER AdapterObject,struct bpf_program *fp); -BOOLEAN PacketSetLoopbackBehavior(LPADAPTER AdapterObject, UINT LoopbackBehavior); -INT PacketSetSnapLen(LPADAPTER AdapterObject,int snaplen); -BOOLEAN PacketGetStats(LPADAPTER AdapterObject,struct bpf_stat *s); -BOOLEAN PacketGetStatsEx(LPADAPTER AdapterObject,struct bpf_stat *s); -BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim); -BOOLEAN PacketGetNetType (LPADAPTER AdapterObject,NetType *type); -LPADAPTER PacketOpenAdapter(PCHAR AdapterName); -BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET pPacket,BOOLEAN Sync); -INT PacketSendPackets(LPADAPTER AdapterObject,PVOID PacketBuff,ULONG Size, BOOLEAN Sync); -LPPACKET PacketAllocatePacket(void); -VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length); -VOID PacketFreePacket(LPPACKET lpPacket); -BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync); -BOOLEAN PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter); -BOOLEAN PacketGetAdapterNames(PTSTR pStr,PULONG BufferSize); -BOOLEAN PacketGetNetInfoEx(PCHAR AdapterName, npf_if_addr* buffer, PLONG NEntries); -BOOLEAN PacketRequest(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData); -HANDLE PacketGetReadEvent(LPADAPTER AdapterObject); -BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject, void *name, int len); -BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject, UINT maxfilesize, UINT maxnpacks); -BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject, BOOLEAN sync); -BOOL PacketStopDriver(); -VOID PacketCloseAdapter(LPADAPTER lpAdapter); -BOOLEAN PacketStartOem(PCHAR errorString, UINT errorStringLength); -BOOLEAN PacketStartOemEx(PCHAR errorString, UINT errorStringLength, ULONG flags); -PAirpcapHandle PacketGetAirPcapHandle(LPADAPTER AdapterObject); - -// -// Used by PacketStartOemEx -// -#define PACKET_START_OEM_NO_NETMON 0x00000001 - -#ifdef __cplusplus -} -#endif - -#endif //__PACKET32 +/* + * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy) + * Copyright (c) 2005 - 2007 CACE Technologies, Davis (California) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Politecnico di Torino, CACE Technologies + * nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** @ingroup packetapi + * @{ + */ + +/** @defgroup packet32h Packet.dll definitions and data structures + * Packet32.h contains the data structures and the definitions used by packet.dll. + * The file is used both by the Win9x and the WinNTx versions of packet.dll, and can be included + * by the applications that use the functions of this library + * @{ + */ + +#ifndef __PACKET32 +#define __PACKET32 + +#include + +#ifdef HAVE_AIRPCAP_API +#include +#else +#if !defined(AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_) +#define AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_ +typedef struct _AirpcapHandle *PAirpcapHandle; +#endif /* AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_ */ +#endif /* HAVE_AIRPCAP_API */ + +#ifdef HAVE_DAG_API +#include +#endif /* HAVE_DAG_API */ + +// Working modes +#define PACKET_MODE_CAPT 0x0 ///< Capture mode +#define PACKET_MODE_STAT 0x1 ///< Statistical mode +#define PACKET_MODE_MON 0x2 ///< Monitoring mode +#define PACKET_MODE_DUMP 0x10 ///< Dump mode +#define PACKET_MODE_STAT_DUMP MODE_DUMP | MODE_STAT ///< Statistical dump Mode + + +/// Alignment macro. Defines the alignment size. +#define Packet_ALIGNMENT sizeof(int) +/// Alignment macro. Rounds up to the next even multiple of Packet_ALIGNMENT. +#define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1)) + +#define NdisMediumNull -1 ///< Custom linktype: NDIS doesn't provide an equivalent +#define NdisMediumCHDLC -2 ///< Custom linktype: NDIS doesn't provide an equivalent +#define NdisMediumPPPSerial -3 ///< Custom linktype: NDIS doesn't provide an equivalent +#define NdisMediumBare80211 -4 ///< Custom linktype: NDIS doesn't provide an equivalent +#define NdisMediumRadio80211 -5 ///< Custom linktype: NDIS doesn't provide an equivalent +#define NdisMediumPpi -6 ///< Custom linktype: NDIS doesn't provide an equivalent + +// Loopback behaviour definitions +#define NPF_DISABLE_LOOPBACK 1 ///< Drop the packets sent by the NPF driver +#define NPF_ENABLE_LOOPBACK 2 ///< Capture the packets sent by the NPF driver + +/*! + \brief Network type structure. + + This structure is used by the PacketGetNetType() function to return information on the current adapter's type and speed. +*/ +typedef struct NetType +{ + UINT LinkType; ///< The MAC of the current network adapter (see function PacketGetNetType() for more information) + ULONGLONG LinkSpeed; ///< The speed of the network in bits per second +}NetType; + + +//some definitions stolen from libpcap + +#ifndef BPF_MAJOR_VERSION + +/*! + \brief A BPF pseudo-assembly program. + + The program will be injected in the kernel by the PacketSetBPF() function and applied to every incoming packet. +*/ +struct bpf_program +{ + UINT bf_len; ///< Indicates the number of instructions of the program, i.e. the number of struct bpf_insn that will follow. + struct bpf_insn *bf_insns; ///< A pointer to the first instruction of the program. +}; + +/*! + \brief A single BPF pseudo-instruction. + + bpf_insn contains a single instruction for the BPF register-machine. It is used to send a filter program to the driver. +*/ +struct bpf_insn +{ + USHORT code; ///< Instruction type and addressing mode. + UCHAR jt; ///< Jump if true + UCHAR jf; ///< Jump if false + int k; ///< Generic field used for various purposes. +}; + +/*! + \brief Structure that contains a couple of statistics values on the current capture. + + It is used by packet.dll to return statistics about a capture session. +*/ +struct bpf_stat +{ + UINT bs_recv; ///< Number of packets that the driver received from the network adapter + ///< from the beginning of the current capture. This value includes the packets + ///< lost by the driver. + UINT bs_drop; ///< number of packets that the driver lost from the beginning of a capture. + ///< Basically, a packet is lost when the the buffer of the driver is full. + ///< In this situation the packet cannot be stored and the driver rejects it. + UINT ps_ifdrop; ///< drops by interface. XXX not yet supported + UINT bs_capt; ///< number of packets that pass the filter, find place in the kernel buffer and + ///< thus reach the application. +}; + +/*! + \brief Packet header. + + This structure defines the header associated with every packet delivered to the application. +*/ +struct bpf_hdr +{ + struct timeval bh_tstamp; ///< The timestamp associated with the captured packet. + ///< It is stored in a TimeVal structure. + UINT bh_caplen; ///< Length of captured portion. The captured portion can be different + ///< from the original packet, because it is possible (with a proper filter) + ///< to instruct the driver to capture only a portion of the packets. + UINT bh_datalen; ///< Original length of packet + USHORT bh_hdrlen; ///< Length of bpf header (this struct plus alignment padding). In some cases, + ///< a padding could be added between the end of this structure and the packet + ///< data for performance reasons. This filed can be used to retrieve the actual data + ///< of the packet. +}; + +/*! + \brief Dump packet header. + + This structure defines the header associated with the packets in a buffer to be used with PacketSendPackets(). + It is simpler than the bpf_hdr, because it corresponds to the header associated by WinPcap and libpcap to a + packet in a dump file. This makes straightforward sending WinPcap dump files to the network. +*/ +struct dump_bpf_hdr{ + struct timeval ts; ///< Time stamp of the packet + UINT caplen; ///< Length of captured portion. The captured portion can smaller than the + ///< the original packet, because it is possible (with a proper filter) to + ///< instruct the driver to capture only a portion of the packets. + UINT len; ///< Length of the original packet (off wire). +}; + + +#endif + +struct bpf_stat; + +#define DOSNAMEPREFIX TEXT("Packet_") ///< Prefix added to the adapters device names to create the WinPcap devices +#define MAX_LINK_NAME_LENGTH 64 //< Maximum length of the devices symbolic links +#define NMAX_PACKET 65535 + +/*! + \brief Addresses of a network adapter. + + This structure is used by the PacketGetNetInfoEx() function to return the IP addresses associated with + an adapter. +*/ +typedef struct npf_if_addr { + struct sockaddr_storage IPAddress; ///< IP address. + struct sockaddr_storage SubnetMask; ///< Netmask for that address. + struct sockaddr_storage Broadcast; ///< Broadcast address. +}npf_if_addr; + + +#define ADAPTER_NAME_LENGTH 256 + 12 ///< Maximum length for the name of an adapter. The value is the same used by the IP Helper API. +#define ADAPTER_DESC_LENGTH 128 ///< Maximum length for the description of an adapter. The value is the same used by the IP Helper API. +#define MAX_MAC_ADDR_LENGTH 8 ///< Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API. +#define MAX_NETWORK_ADDRESSES 16 ///< Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API. + + +typedef struct WAN_ADAPTER_INT WAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API +typedef WAN_ADAPTER *PWAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API + +#define INFO_FLAG_NDIS_ADAPTER 0 ///< Flag for ADAPTER_INFO: this is a traditional ndis adapter +#define INFO_FLAG_NDISWAN_ADAPTER 1 ///< Flag for ADAPTER_INFO: this is a NdisWan adapter, and it's managed by WANPACKET +#define INFO_FLAG_DAG_CARD 2 ///< Flag for ADAPTER_INFO: this is a DAG card +#define INFO_FLAG_DAG_FILE 6 ///< Flag for ADAPTER_INFO: this is a DAG file +#define INFO_FLAG_DONT_EXPORT 8 ///< Flag for ADAPTER_INFO: when this flag is set, the adapter will not be listed or openend by winpcap. This allows to prevent exporting broken network adapters, like for example FireWire ones. +#define INFO_FLAG_AIRPCAP_CARD 16 ///< Flag for ADAPTER_INFO: this is an airpcap card +#define INFO_FLAG_NPFIM_DEVICE 32 + +/*! + \brief Describes an opened network adapter. + + This structure is the most important for the functioning of packet.dll, but the great part of its fields + should be ignored by the user, since the library offers functions that avoid to cope with low-level parameters +*/ +typedef struct _ADAPTER { + HANDLE hFile; ///< \internal Handle to an open instance of the NPF driver. + CHAR SymbolicLink[MAX_LINK_NAME_LENGTH]; ///< \internal A string containing the name of the network adapter currently opened. + int NumWrites; ///< \internal Number of times a packets written on this adapter will be repeated + ///< on the wire. + HANDLE ReadEvent; ///< A notification event associated with the read calls on the adapter. + ///< It can be passed to standard Win32 functions (like WaitForSingleObject + ///< or WaitForMultipleObjects) to wait until the driver's buffer contains some + ///< data. It is particularly useful in GUI applications that need to wait + ///< concurrently on several events. In Windows NT/2000 the PacketSetMinToCopy() + ///< function can be used to define the minimum amount of data in the kernel buffer + ///< that will cause the event to be signalled. + + UINT ReadTimeOut; ///< \internal The amount of time after which a read on the driver will be released and + ///< ReadEvent will be signaled, also if no packets were captured + CHAR Name[ADAPTER_NAME_LENGTH]; + PWAN_ADAPTER pWanAdapter; + UINT Flags; ///< Adapter's flags. Tell if this adapter must be treated in a different way, using the Netmon API or the dagc API. + +#ifdef HAVE_AIRPCAP_API + PAirpcapHandle AirpcapAd; +#endif // HAVE_AIRPCAP_API + +#ifdef HAVE_NPFIM_API + void* NpfImHandle; +#endif // HAVE_NPFIM_API + +#ifdef HAVE_DAG_API + dagc_t *pDagCard; ///< Pointer to the dagc API adapter descriptor for this adapter + PCHAR DagBuffer; ///< Pointer to the buffer with the packets that is received from the DAG card + struct timeval DagReadTimeout; ///< Read timeout. The dagc API requires a timeval structure + unsigned DagFcsLen; ///< Length of the frame check sequence attached to any packet by the card. Obtained from the registry + DWORD DagFastProcess; ///< True if the user requests fast capture processing on this card. Higher level applications can use this value to provide a faster but possibly unprecise capture (for example, libpcap doesn't convert the timestamps). +#endif // HAVE_DAG_API +} ADAPTER, *LPADAPTER; + +/*! + \brief Structure that contains a group of packets coming from the driver. + + This structure defines the header associated with every packet delivered to the application. +*/ +typedef struct _PACKET { + HANDLE hEvent; ///< \deprecated Still present for compatibility with old applications. + OVERLAPPED OverLapped; ///< \deprecated Still present for compatibility with old applications. + PVOID Buffer; ///< Buffer with containing the packets. See the PacketReceivePacket() for + ///< details about the organization of the data in this buffer + UINT Length; ///< Length of the buffer + DWORD ulBytesReceived; ///< Number of valid bytes present in the buffer, i.e. amount of data + ///< received by the last call to PacketReceivePacket() + BOOLEAN bIoComplete; ///< \deprecated Still present for compatibility with old applications. +} PACKET, *LPPACKET; + +/*! + \brief Structure containing an OID request. + + It is used by the PacketRequest() function to send an OID to the interface card driver. + It can be used, for example, to retrieve the status of the error counters on the adapter, its MAC address, + the list of the multicast groups defined on it, and so on. +*/ +struct _PACKET_OID_DATA { + ULONG Oid; ///< OID code. See the Microsoft DDK documentation or the file ntddndis.h + ///< for a complete list of valid codes. + ULONG Length; ///< Length of the data field + UCHAR Data[1]; ///< variable-lenght field that contains the information passed to or received + ///< from the adapter. +}; +typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @} + */ + +/* +BOOLEAN QueryWinPcapRegistryStringA(CHAR *SubKeyName, + CHAR *Value, + UINT *pValueLen, + CHAR *DefaultVal); + +BOOLEAN QueryWinPcapRegistryStringW(WCHAR *SubKeyName, + WCHAR *Value, + UINT *pValueLen, + WCHAR *DefaultVal); +*/ + +//--------------------------------------------------------------------------- +// EXPORTED FUNCTIONS +//--------------------------------------------------------------------------- + +PCHAR PacketGetVersion(); +PCHAR PacketGetDriverVersion(); +BOOLEAN PacketSetMinToCopy(LPADAPTER AdapterObject,int nbytes); +BOOLEAN PacketSetNumWrites(LPADAPTER AdapterObject,int nwrites); +BOOLEAN PacketSetMode(LPADAPTER AdapterObject,int mode); +BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout); +BOOLEAN PacketSetBpf(LPADAPTER AdapterObject,struct bpf_program *fp); +BOOLEAN PacketSetLoopbackBehavior(LPADAPTER AdapterObject, UINT LoopbackBehavior); +INT PacketSetSnapLen(LPADAPTER AdapterObject,int snaplen); +BOOLEAN PacketGetStats(LPADAPTER AdapterObject,struct bpf_stat *s); +BOOLEAN PacketGetStatsEx(LPADAPTER AdapterObject,struct bpf_stat *s); +BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim); +BOOLEAN PacketGetNetType (LPADAPTER AdapterObject,NetType *type); +LPADAPTER PacketOpenAdapter(PCHAR AdapterName); +BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET pPacket,BOOLEAN Sync); +INT PacketSendPackets(LPADAPTER AdapterObject,PVOID PacketBuff,ULONG Size, BOOLEAN Sync); +LPPACKET PacketAllocatePacket(void); +VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length); +VOID PacketFreePacket(LPPACKET lpPacket); +BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync); +BOOLEAN PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter); +BOOLEAN PacketGetAdapterNames(PTSTR pStr,PULONG BufferSize); +BOOLEAN PacketGetNetInfoEx(PCHAR AdapterName, npf_if_addr* buffer, PLONG NEntries); +BOOLEAN PacketRequest(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData); +HANDLE PacketGetReadEvent(LPADAPTER AdapterObject); +BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject, void *name, int len); +BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject, UINT maxfilesize, UINT maxnpacks); +BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject, BOOLEAN sync); +BOOL PacketStopDriver(); +VOID PacketCloseAdapter(LPADAPTER lpAdapter); +BOOLEAN PacketStartOem(PCHAR errorString, UINT errorStringLength); +BOOLEAN PacketStartOemEx(PCHAR errorString, UINT errorStringLength, ULONG flags); +PAirpcapHandle PacketGetAirPcapHandle(LPADAPTER AdapterObject); + +// +// Used by PacketStartOemEx +// +#define PACKET_START_OEM_NO_NETMON 0x00000001 + +#ifdef __cplusplus +} +#endif + +#endif //__PACKET32 diff --git a/plugins/dev9ghzdrk/Win32-Extensions.h b/3rdparty/winpcap/include/Win32-Extensions.h similarity index 97% rename from plugins/dev9ghzdrk/Win32-Extensions.h rename to 3rdparty/winpcap/include/Win32-Extensions.h index ad3be25cf..d3b063b0f 100644 --- a/plugins/dev9ghzdrk/Win32-Extensions.h +++ b/3rdparty/winpcap/include/Win32-Extensions.h @@ -1,113 +1,113 @@ -/* - * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy) - * Copyright (c) 2005 - 2006 CACE Technologies, Davis (California) - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Politecnico di Torino, CACE Technologies - * nor the names of its contributors may be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef __WIN32_EXTENSIONS_H__ -#define __WIN32_EXTENSIONS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* Definitions */ - -/*! - \brief A queue of raw packets that will be sent to the network with pcap_sendqueue_transmit(). -*/ -struct pcap_send_queue -{ - u_int maxlen; ///< Maximum size of the the queue, in bytes. This variable contains the size of the buffer field. - u_int len; ///< Current size of the queue, in bytes. - char *buffer; ///< Buffer containing the packets to be sent. -}; - -typedef struct pcap_send_queue pcap_send_queue; - -/*! - \brief This typedef is a support for the pcap_get_airpcap_handle() function -*/ -#if !defined(AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_) -#define AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_ -typedef struct _AirpcapHandle *PAirpcapHandle; -#endif - -#define BPF_MEM_EX_IMM 0xc0 -#define BPF_MEM_EX_IND 0xe0 - -/*used for ST*/ -#define BPF_MEM_EX 0xc0 -#define BPF_TME 0x08 - -#define BPF_LOOKUP 0x90 -#define BPF_EXECUTE 0xa0 -#define BPF_INIT 0xb0 -#define BPF_VALIDATE 0xc0 -#define BPF_SET_ACTIVE 0xd0 -#define BPF_RESET 0xe0 -#define BPF_SET_MEMORY 0x80 -#define BPF_GET_REGISTER_VALUE 0x70 -#define BPF_SET_REGISTER_VALUE 0x60 -#define BPF_SET_WORKING 0x50 -#define BPF_SET_ACTIVE_READ 0x40 -#define BPF_SET_AUTODELETION 0x30 -#define BPF_SEPARATION 0xff - -/* Prototypes */ -pcap_send_queue* pcap_sendqueue_alloc(u_int memsize); - -void pcap_sendqueue_destroy(pcap_send_queue* queue); - -int pcap_sendqueue_queue(pcap_send_queue* queue, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data); - -u_int pcap_sendqueue_transmit(pcap_t *p, pcap_send_queue* queue, int sync); - -HANDLE pcap_getevent(pcap_t *p); - -struct pcap_stat *pcap_stats_ex(pcap_t *p, int *pcap_stat_size); - -int pcap_setuserbuffer(pcap_t *p, int size); - -int pcap_live_dump(pcap_t *p, char *filename, int maxsize, int maxpacks); - -int pcap_live_dump_ended(pcap_t *p, int sync); - -int pcap_offline_filter(struct bpf_program *prog, const struct pcap_pkthdr *header, const u_char *pkt_data); - -int pcap_start_oem(char* err_str, int flags); - -PAirpcapHandle pcap_get_airpcap_handle(pcap_t *p); - -#ifdef __cplusplus -} -#endif - -#endif //__WIN32_EXTENSIONS_H__ +/* + * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy) + * Copyright (c) 2005 - 2006 CACE Technologies, Davis (California) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Politecnico di Torino, CACE Technologies + * nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __WIN32_EXTENSIONS_H__ +#define __WIN32_EXTENSIONS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Definitions */ + +/*! + \brief A queue of raw packets that will be sent to the network with pcap_sendqueue_transmit(). +*/ +struct pcap_send_queue +{ + u_int maxlen; ///< Maximum size of the the queue, in bytes. This variable contains the size of the buffer field. + u_int len; ///< Current size of the queue, in bytes. + char *buffer; ///< Buffer containing the packets to be sent. +}; + +typedef struct pcap_send_queue pcap_send_queue; + +/*! + \brief This typedef is a support for the pcap_get_airpcap_handle() function +*/ +#if !defined(AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_) +#define AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_ +typedef struct _AirpcapHandle *PAirpcapHandle; +#endif + +#define BPF_MEM_EX_IMM 0xc0 +#define BPF_MEM_EX_IND 0xe0 + +/*used for ST*/ +#define BPF_MEM_EX 0xc0 +#define BPF_TME 0x08 + +#define BPF_LOOKUP 0x90 +#define BPF_EXECUTE 0xa0 +#define BPF_INIT 0xb0 +#define BPF_VALIDATE 0xc0 +#define BPF_SET_ACTIVE 0xd0 +#define BPF_RESET 0xe0 +#define BPF_SET_MEMORY 0x80 +#define BPF_GET_REGISTER_VALUE 0x70 +#define BPF_SET_REGISTER_VALUE 0x60 +#define BPF_SET_WORKING 0x50 +#define BPF_SET_ACTIVE_READ 0x40 +#define BPF_SET_AUTODELETION 0x30 +#define BPF_SEPARATION 0xff + +/* Prototypes */ +pcap_send_queue* pcap_sendqueue_alloc(u_int memsize); + +void pcap_sendqueue_destroy(pcap_send_queue* queue); + +int pcap_sendqueue_queue(pcap_send_queue* queue, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data); + +u_int pcap_sendqueue_transmit(pcap_t *p, pcap_send_queue* queue, int sync); + +HANDLE pcap_getevent(pcap_t *p); + +struct pcap_stat *pcap_stats_ex(pcap_t *p, int *pcap_stat_size); + +int pcap_setuserbuffer(pcap_t *p, int size); + +int pcap_live_dump(pcap_t *p, char *filename, int maxsize, int maxpacks); + +int pcap_live_dump_ended(pcap_t *p, int sync); + +int pcap_offline_filter(struct bpf_program *prog, const struct pcap_pkthdr *header, const u_char *pkt_data); + +int pcap_start_oem(char* err_str, int flags); + +PAirpcapHandle pcap_get_airpcap_handle(pcap_t *p); + +#ifdef __cplusplus +} +#endif + +#endif //__WIN32_EXTENSIONS_H__ diff --git a/plugins/dev9ghzdrk/bittypes.h b/3rdparty/winpcap/include/bittypes.h similarity index 100% rename from plugins/dev9ghzdrk/bittypes.h rename to 3rdparty/winpcap/include/bittypes.h diff --git a/plugins/dev9ghzdrk/ip6_misc.h b/3rdparty/winpcap/include/ip6_misc.h similarity index 100% rename from plugins/dev9ghzdrk/ip6_misc.h rename to 3rdparty/winpcap/include/ip6_misc.h diff --git a/plugins/dev9ghzdrk/pcap-bpf.h b/3rdparty/winpcap/include/pcap-bpf.h similarity index 100% rename from plugins/dev9ghzdrk/pcap-bpf.h rename to 3rdparty/winpcap/include/pcap-bpf.h diff --git a/plugins/dev9ghzdrk/pcap-namedb.h b/3rdparty/winpcap/include/pcap-namedb.h similarity index 100% rename from plugins/dev9ghzdrk/pcap-namedb.h rename to 3rdparty/winpcap/include/pcap-namedb.h diff --git a/plugins/dev9ghzdrk/pcap-stdinc.h b/3rdparty/winpcap/include/pcap-stdinc.h similarity index 100% rename from plugins/dev9ghzdrk/pcap-stdinc.h rename to 3rdparty/winpcap/include/pcap-stdinc.h diff --git a/plugins/dev9ghzdrk/pcap.h b/3rdparty/winpcap/include/pcap.h similarity index 100% rename from plugins/dev9ghzdrk/pcap.h rename to 3rdparty/winpcap/include/pcap.h diff --git a/plugins/dev9ghzdrk/pcap/bluetooth.h b/3rdparty/winpcap/include/pcap/bluetooth.h similarity index 100% rename from plugins/dev9ghzdrk/pcap/bluetooth.h rename to 3rdparty/winpcap/include/pcap/bluetooth.h diff --git a/plugins/dev9ghzdrk/pcap/bpf.h b/3rdparty/winpcap/include/pcap/bpf.h similarity index 100% rename from plugins/dev9ghzdrk/pcap/bpf.h rename to 3rdparty/winpcap/include/pcap/bpf.h diff --git a/plugins/dev9ghzdrk/pcap/namedb.h b/3rdparty/winpcap/include/pcap/namedb.h similarity index 100% rename from plugins/dev9ghzdrk/pcap/namedb.h rename to 3rdparty/winpcap/include/pcap/namedb.h diff --git a/plugins/dev9ghzdrk/pcap/pcap.h b/3rdparty/winpcap/include/pcap/pcap.h similarity index 100% rename from plugins/dev9ghzdrk/pcap/pcap.h rename to 3rdparty/winpcap/include/pcap/pcap.h diff --git a/plugins/dev9ghzdrk/pcap/sll.h b/3rdparty/winpcap/include/pcap/sll.h similarity index 100% rename from plugins/dev9ghzdrk/pcap/sll.h rename to 3rdparty/winpcap/include/pcap/sll.h diff --git a/plugins/dev9ghzdrk/pcap/usb.h b/3rdparty/winpcap/include/pcap/usb.h similarity index 100% rename from plugins/dev9ghzdrk/pcap/usb.h rename to 3rdparty/winpcap/include/pcap/usb.h diff --git a/plugins/dev9ghzdrk/pcap/vlan.h b/3rdparty/winpcap/include/pcap/vlan.h similarity index 100% rename from plugins/dev9ghzdrk/pcap/vlan.h rename to 3rdparty/winpcap/include/pcap/vlan.h diff --git a/plugins/dev9ghzdrk/remote-ext.h b/3rdparty/winpcap/include/remote-ext.h similarity index 97% rename from plugins/dev9ghzdrk/remote-ext.h rename to 3rdparty/winpcap/include/remote-ext.h index 35a2fff6c..9f54d6974 100644 --- a/plugins/dev9ghzdrk/remote-ext.h +++ b/3rdparty/winpcap/include/remote-ext.h @@ -1,444 +1,444 @@ -/* - * Copyright (c) 2002 - 2003 - * NetGroup, Politecnico di Torino (Italy) - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Politecnico di Torino nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - - -#ifndef __REMOTE_EXT_H__ -#define __REMOTE_EXT_H__ - - -#ifndef HAVE_REMOTE -#error Please do not include this file directly. Just define HAVE_REMOTE and then include pcap.h -#endif - -// Definition for Microsoft Visual Studio -#if _MSC_VER > 1000 -#pragma once -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/*! - \file remote-ext.h - - The goal of this file it to include most of the new definitions that should be - placed into the pcap.h file. - - It includes all new definitions (structures and functions like pcap_open(). - Some of the functions are not really a remote feature, but, right now, - they are placed here. -*/ - - - -// All this stuff is public -/*! \addtogroup remote_struct - \{ -*/ - - - - -/*! - \brief Defines the maximum buffer size in which address, port, interface names are kept. - - In case the adapter name or such is larger than this value, it is truncated. - This is not used by the user; however it must be aware that an hostname / interface - name longer than this value will be truncated. -*/ -#define PCAP_BUF_SIZE 1024 - - -/*! \addtogroup remote_source_ID - \{ -*/ - - -/*! - \brief Internal representation of the type of source in use (file, - remote/local interface). - - This indicates a file, i.e. the user want to open a capture from a local file. -*/ -#define PCAP_SRC_FILE 2 -/*! - \brief Internal representation of the type of source in use (file, - remote/local interface). - - This indicates a local interface, i.e. the user want to open a capture from - a local interface. This does not involve the RPCAP protocol. -*/ -#define PCAP_SRC_IFLOCAL 3 -/*! - \brief Internal representation of the type of source in use (file, - remote/local interface). - - This indicates a remote interface, i.e. the user want to open a capture from - an interface on a remote host. This does involve the RPCAP protocol. -*/ -#define PCAP_SRC_IFREMOTE 4 - -/*! - \} -*/ - - - -/*! \addtogroup remote_source_string - - The formats allowed by the pcap_open() are the following: - - file://path_and_filename [opens a local file] - - rpcap://devicename [opens the selected device devices available on the local host, without using the RPCAP protocol] - - rpcap://host/devicename [opens the selected device available on a remote host] - - rpcap://host:port/devicename [opens the selected device available on a remote host, using a non-standard port for RPCAP] - - adaptername [to open a local adapter; kept for compability, but it is strongly discouraged] - - (NULL) [to open the first local adapter; kept for compability, but it is strongly discouraged] - - The formats allowed by the pcap_findalldevs_ex() are the following: - - file://folder/ [lists all the files in the given folder] - - rpcap:// [lists all local adapters] - - rpcap://host:port/ [lists the devices available on a remote host] - - Referring to the 'host' and 'port' paramters, they can be either numeric or literal. Since - IPv6 is fully supported, these are the allowed formats: - - - host (literal): e.g. host.foo.bar - - host (numeric IPv4): e.g. 10.11.12.13 - - host (numeric IPv4, IPv6 style): e.g. [10.11.12.13] - - host (numeric IPv6): e.g. [1:2:3::4] - - port: can be either numeric (e.g. '80') or literal (e.g. 'http') - - Here you find some allowed examples: - - rpcap://host.foo.bar/devicename [everything literal, no port number] - - rpcap://host.foo.bar:1234/devicename [everything literal, with port number] - - rpcap://10.11.12.13/devicename [IPv4 numeric, no port number] - - rpcap://10.11.12.13:1234/devicename [IPv4 numeric, with port number] - - rpcap://[10.11.12.13]:1234/devicename [IPv4 numeric with IPv6 format, with port number] - - rpcap://[1:2:3::4]/devicename [IPv6 numeric, no port number] - - rpcap://[1:2:3::4]:1234/devicename [IPv6 numeric, with port number] - - rpcap://[1:2:3::4]:http/devicename [IPv6 numeric, with literal port number] - - \{ -*/ - - -/*! - \brief String that will be used to determine the type of source in use (file, - remote/local interface). - - This string will be prepended to the interface name in order to create a string - that contains all the information required to open the source. - - This string indicates that the user wants to open a capture from a local file. -*/ -#define PCAP_SRC_FILE_STRING "file://" -/*! - \brief String that will be used to determine the type of source in use (file, - remote/local interface). - - This string will be prepended to the interface name in order to create a string - that contains all the information required to open the source. - - This string indicates that the user wants to open a capture from a network interface. - This string does not necessarily involve the use of the RPCAP protocol. If the - interface required resides on the local host, the RPCAP protocol is not involved - and the local functions are used. -*/ -#define PCAP_SRC_IF_STRING "rpcap://" - -/*! - \} -*/ - - - - - -/*! - \addtogroup remote_open_flags - \{ -*/ - -/*! - \brief Defines if the adapter has to go in promiscuous mode. - - It is '1' if you have to open the adapter in promiscuous mode, '0' otherwise. - Note that even if this parameter is false, the interface could well be in promiscuous - mode for some other reason (for example because another capture process with - promiscuous mode enabled is currently using that interface). - On on Linux systems with 2.2 or later kernels (that have the "any" device), this - flag does not work on the "any" device; if an argument of "any" is supplied, - the 'promisc' flag is ignored. -*/ -#define PCAP_OPENFLAG_PROMISCUOUS 1 - -/*! - \brief Defines if the data trasfer (in case of a remote - capture) has to be done with UDP protocol. - - If it is '1' if you want a UDP data connection, '0' if you want - a TCP data connection; control connection is always TCP-based. - A UDP connection is much lighter, but it does not guarantee that all - the captured packets arrive to the client workstation. Moreover, - it could be harmful in case of network congestion. - This flag is meaningless if the source is not a remote interface. - In that case, it is simply ignored. -*/ -#define PCAP_OPENFLAG_DATATX_UDP 2 - - -/*! - \brief Defines if the remote probe will capture its own generated traffic. - - In case the remote probe uses the same interface to capture traffic and to send - data back to the caller, the captured traffic includes the RPCAP traffic as well. - If this flag is turned on, the RPCAP traffic is excluded from the capture, so that - the trace returned back to the collector is does not include this traffic. -*/ -#define PCAP_OPENFLAG_NOCAPTURE_RPCAP 4 - -/*! - \brief Defines if the local adapter will capture its own generated traffic. - - This flag tells the underlying capture driver to drop the packets that were sent by itself. - This is usefult when building applications like bridges, that should ignore the traffic - they just sent. -*/ -#define PCAP_OPENFLAG_NOCAPTURE_LOCAL 8 - -/*! - \brief This flag configures the adapter for maximum responsiveness. - - In presence of a large value for nbytes, WinPcap waits for the arrival of several packets before - copying the data to the user. This guarantees a low number of system calls, i.e. lower processor usage, - i.e. better performance, which is good for applications like sniffers. If the user sets the - PCAP_OPENFLAG_MAX_RESPONSIVENESS flag, the capture driver will copy the packets as soon as the application - is ready to receive them. This is suggested for real time applications (like, for example, a bridge) - that need the best responsiveness.*/ -#define PCAP_OPENFLAG_MAX_RESPONSIVENESS 16 - -/*! - \} -*/ - - -/*! - \addtogroup remote_samp_methods - \{ -*/ - -/*! - \brief No sampling has to be done on the current capture. - - In this case, no sampling algorithms are applied to the current capture. -*/ -#define PCAP_SAMP_NOSAMP 0 - -/*! - \brief It defines that only 1 out of N packets must be returned to the user. - - In this case, the 'value' field of the 'pcap_samp' structure indicates the - number of packets (minus 1) that must be discarded before one packet got accepted. - In other words, if 'value = 10', the first packet is returned to the caller, while - the following 9 are discarded. -*/ -#define PCAP_SAMP_1_EVERY_N 1 - -/*! - \brief It defines that we have to return 1 packet every N milliseconds. - - In this case, the 'value' field of the 'pcap_samp' structure indicates the 'waiting - time' in milliseconds before one packet got accepted. - In other words, if 'value = 10', the first packet is returned to the caller; the next - returned one will be the first packet that arrives when 10ms have elapsed. -*/ -#define PCAP_SAMP_FIRST_AFTER_N_MS 2 - -/*! - \} -*/ - - -/*! - \addtogroup remote_auth_methods - \{ -*/ - -/*! - \brief It defines the NULL authentication. - - This value has to be used within the 'type' member of the pcap_rmtauth structure. - The 'NULL' authentication has to be equal to 'zero', so that old applications - can just put every field of struct pcap_rmtauth to zero, and it does work. -*/ -#define RPCAP_RMTAUTH_NULL 0 -/*! - \brief It defines the username/password authentication. - - With this type of authentication, the RPCAP protocol will use the username/ - password provided to authenticate the user on the remote machine. If the - authentication is successful (and the user has the right to open network devices) - the RPCAP connection will continue; otherwise it will be dropped. - - This value has to be used within the 'type' member of the pcap_rmtauth structure. -*/ -#define RPCAP_RMTAUTH_PWD 1 - -/*! - \} -*/ - - - - -/*! - - \brief This structure keeps the information needed to autheticate - the user on a remote machine. - - The remote machine can either grant or refuse the access according - to the information provided. - In case the NULL authentication is required, both 'username' and - 'password' can be NULL pointers. - - This structure is meaningless if the source is not a remote interface; - in that case, the functions which requires such a structure can accept - a NULL pointer as well. -*/ -struct pcap_rmtauth -{ - /*! - \brief Type of the authentication required. - - In order to provide maximum flexibility, we can support different types - of authentication based on the value of this 'type' variable. The currently - supported authentication methods are defined into the - \link remote_auth_methods Remote Authentication Methods Section\endlink. - - */ - int type; - /*! - \brief Zero-terminated string containing the username that has to be - used on the remote machine for authentication. - - This field is meaningless in case of the RPCAP_RMTAUTH_NULL authentication - and it can be NULL. - */ - char *username; - /*! - \brief Zero-terminated string containing the password that has to be - used on the remote machine for authentication. - - This field is meaningless in case of the RPCAP_RMTAUTH_NULL authentication - and it can be NULL. - */ - char *password; -}; - - -/*! - \brief This structure defines the information related to sampling. - - In case the sampling is requested, the capturing device should read - only a subset of the packets coming from the source. The returned packets depend - on the sampling parameters. - - \warning The sampling process is applied after the filtering process. - In other words, packets are filtered first, then the sampling process selects a - subset of the 'filtered' packets and it returns them to the caller. -*/ -struct pcap_samp -{ - /*! - Method used for sampling. Currently, the supported methods are listed in the - \link remote_samp_methods Sampling Methods Section\endlink. - */ - int method; - - /*! - This value depends on the sampling method defined. For its meaning, please check - at the \link remote_samp_methods Sampling Methods Section\endlink. - */ - int value; -}; - - - - -//! Maximum lenght of an host name (needed for the RPCAP active mode) -#define RPCAP_HOSTLIST_SIZE 1024 - - -/*! - \} -*/ // end of public documentation - - -// Exported functions - - - -/** \name New WinPcap functions - - This section lists the new functions that are able to help considerably in writing - WinPcap programs because of their easiness of use. - */ -//\{ -pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf); -int pcap_createsrcstr(char *source, int type, const char *host, const char *port, const char *name, char *errbuf); -int pcap_parsesrcstr(const char *source, int *type, char *host, char *port, char *name, char *errbuf); -int pcap_findalldevs_ex(char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf); -struct pcap_samp *pcap_setsampling(pcap_t *p); - -//\} -// End of new winpcap functions - - - -/** \name Remote Capture functions - */ -//\{ -SOCKET pcap_remoteact_accept(const char *address, const char *port, const char *hostlist, char *connectinghost, struct pcap_rmtauth *auth, char *errbuf); -int pcap_remoteact_list(char *hostlist, char sep, int size, char *errbuf); -int pcap_remoteact_close(const char *host, char *errbuf); -void pcap_remoteact_cleanup(); -//\} -// End of remote capture functions - -#ifdef __cplusplus -} -#endif - - -#endif - +/* + * Copyright (c) 2002 - 2003 + * NetGroup, Politecnico di Torino (Italy) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Politecnico di Torino nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#ifndef __REMOTE_EXT_H__ +#define __REMOTE_EXT_H__ + + +#ifndef HAVE_REMOTE +#error Please do not include this file directly. Just define HAVE_REMOTE and then include pcap.h +#endif + +// Definition for Microsoft Visual Studio +#if _MSC_VER > 1000 +#pragma once +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + \file remote-ext.h + + The goal of this file it to include most of the new definitions that should be + placed into the pcap.h file. + + It includes all new definitions (structures and functions like pcap_open(). + Some of the functions are not really a remote feature, but, right now, + they are placed here. +*/ + + + +// All this stuff is public +/*! \addtogroup remote_struct + \{ +*/ + + + + +/*! + \brief Defines the maximum buffer size in which address, port, interface names are kept. + + In case the adapter name or such is larger than this value, it is truncated. + This is not used by the user; however it must be aware that an hostname / interface + name longer than this value will be truncated. +*/ +#define PCAP_BUF_SIZE 1024 + + +/*! \addtogroup remote_source_ID + \{ +*/ + + +/*! + \brief Internal representation of the type of source in use (file, + remote/local interface). + + This indicates a file, i.e. the user want to open a capture from a local file. +*/ +#define PCAP_SRC_FILE 2 +/*! + \brief Internal representation of the type of source in use (file, + remote/local interface). + + This indicates a local interface, i.e. the user want to open a capture from + a local interface. This does not involve the RPCAP protocol. +*/ +#define PCAP_SRC_IFLOCAL 3 +/*! + \brief Internal representation of the type of source in use (file, + remote/local interface). + + This indicates a remote interface, i.e. the user want to open a capture from + an interface on a remote host. This does involve the RPCAP protocol. +*/ +#define PCAP_SRC_IFREMOTE 4 + +/*! + \} +*/ + + + +/*! \addtogroup remote_source_string + + The formats allowed by the pcap_open() are the following: + - file://path_and_filename [opens a local file] + - rpcap://devicename [opens the selected device devices available on the local host, without using the RPCAP protocol] + - rpcap://host/devicename [opens the selected device available on a remote host] + - rpcap://host:port/devicename [opens the selected device available on a remote host, using a non-standard port for RPCAP] + - adaptername [to open a local adapter; kept for compability, but it is strongly discouraged] + - (NULL) [to open the first local adapter; kept for compability, but it is strongly discouraged] + + The formats allowed by the pcap_findalldevs_ex() are the following: + - file://folder/ [lists all the files in the given folder] + - rpcap:// [lists all local adapters] + - rpcap://host:port/ [lists the devices available on a remote host] + + Referring to the 'host' and 'port' paramters, they can be either numeric or literal. Since + IPv6 is fully supported, these are the allowed formats: + + - host (literal): e.g. host.foo.bar + - host (numeric IPv4): e.g. 10.11.12.13 + - host (numeric IPv4, IPv6 style): e.g. [10.11.12.13] + - host (numeric IPv6): e.g. [1:2:3::4] + - port: can be either numeric (e.g. '80') or literal (e.g. 'http') + + Here you find some allowed examples: + - rpcap://host.foo.bar/devicename [everything literal, no port number] + - rpcap://host.foo.bar:1234/devicename [everything literal, with port number] + - rpcap://10.11.12.13/devicename [IPv4 numeric, no port number] + - rpcap://10.11.12.13:1234/devicename [IPv4 numeric, with port number] + - rpcap://[10.11.12.13]:1234/devicename [IPv4 numeric with IPv6 format, with port number] + - rpcap://[1:2:3::4]/devicename [IPv6 numeric, no port number] + - rpcap://[1:2:3::4]:1234/devicename [IPv6 numeric, with port number] + - rpcap://[1:2:3::4]:http/devicename [IPv6 numeric, with literal port number] + + \{ +*/ + + +/*! + \brief String that will be used to determine the type of source in use (file, + remote/local interface). + + This string will be prepended to the interface name in order to create a string + that contains all the information required to open the source. + + This string indicates that the user wants to open a capture from a local file. +*/ +#define PCAP_SRC_FILE_STRING "file://" +/*! + \brief String that will be used to determine the type of source in use (file, + remote/local interface). + + This string will be prepended to the interface name in order to create a string + that contains all the information required to open the source. + + This string indicates that the user wants to open a capture from a network interface. + This string does not necessarily involve the use of the RPCAP protocol. If the + interface required resides on the local host, the RPCAP protocol is not involved + and the local functions are used. +*/ +#define PCAP_SRC_IF_STRING "rpcap://" + +/*! + \} +*/ + + + + + +/*! + \addtogroup remote_open_flags + \{ +*/ + +/*! + \brief Defines if the adapter has to go in promiscuous mode. + + It is '1' if you have to open the adapter in promiscuous mode, '0' otherwise. + Note that even if this parameter is false, the interface could well be in promiscuous + mode for some other reason (for example because another capture process with + promiscuous mode enabled is currently using that interface). + On on Linux systems with 2.2 or later kernels (that have the "any" device), this + flag does not work on the "any" device; if an argument of "any" is supplied, + the 'promisc' flag is ignored. +*/ +#define PCAP_OPENFLAG_PROMISCUOUS 1 + +/*! + \brief Defines if the data trasfer (in case of a remote + capture) has to be done with UDP protocol. + + If it is '1' if you want a UDP data connection, '0' if you want + a TCP data connection; control connection is always TCP-based. + A UDP connection is much lighter, but it does not guarantee that all + the captured packets arrive to the client workstation. Moreover, + it could be harmful in case of network congestion. + This flag is meaningless if the source is not a remote interface. + In that case, it is simply ignored. +*/ +#define PCAP_OPENFLAG_DATATX_UDP 2 + + +/*! + \brief Defines if the remote probe will capture its own generated traffic. + + In case the remote probe uses the same interface to capture traffic and to send + data back to the caller, the captured traffic includes the RPCAP traffic as well. + If this flag is turned on, the RPCAP traffic is excluded from the capture, so that + the trace returned back to the collector is does not include this traffic. +*/ +#define PCAP_OPENFLAG_NOCAPTURE_RPCAP 4 + +/*! + \brief Defines if the local adapter will capture its own generated traffic. + + This flag tells the underlying capture driver to drop the packets that were sent by itself. + This is usefult when building applications like bridges, that should ignore the traffic + they just sent. +*/ +#define PCAP_OPENFLAG_NOCAPTURE_LOCAL 8 + +/*! + \brief This flag configures the adapter for maximum responsiveness. + + In presence of a large value for nbytes, WinPcap waits for the arrival of several packets before + copying the data to the user. This guarantees a low number of system calls, i.e. lower processor usage, + i.e. better performance, which is good for applications like sniffers. If the user sets the + PCAP_OPENFLAG_MAX_RESPONSIVENESS flag, the capture driver will copy the packets as soon as the application + is ready to receive them. This is suggested for real time applications (like, for example, a bridge) + that need the best responsiveness.*/ +#define PCAP_OPENFLAG_MAX_RESPONSIVENESS 16 + +/*! + \} +*/ + + +/*! + \addtogroup remote_samp_methods + \{ +*/ + +/*! + \brief No sampling has to be done on the current capture. + + In this case, no sampling algorithms are applied to the current capture. +*/ +#define PCAP_SAMP_NOSAMP 0 + +/*! + \brief It defines that only 1 out of N packets must be returned to the user. + + In this case, the 'value' field of the 'pcap_samp' structure indicates the + number of packets (minus 1) that must be discarded before one packet got accepted. + In other words, if 'value = 10', the first packet is returned to the caller, while + the following 9 are discarded. +*/ +#define PCAP_SAMP_1_EVERY_N 1 + +/*! + \brief It defines that we have to return 1 packet every N milliseconds. + + In this case, the 'value' field of the 'pcap_samp' structure indicates the 'waiting + time' in milliseconds before one packet got accepted. + In other words, if 'value = 10', the first packet is returned to the caller; the next + returned one will be the first packet that arrives when 10ms have elapsed. +*/ +#define PCAP_SAMP_FIRST_AFTER_N_MS 2 + +/*! + \} +*/ + + +/*! + \addtogroup remote_auth_methods + \{ +*/ + +/*! + \brief It defines the NULL authentication. + + This value has to be used within the 'type' member of the pcap_rmtauth structure. + The 'NULL' authentication has to be equal to 'zero', so that old applications + can just put every field of struct pcap_rmtauth to zero, and it does work. +*/ +#define RPCAP_RMTAUTH_NULL 0 +/*! + \brief It defines the username/password authentication. + + With this type of authentication, the RPCAP protocol will use the username/ + password provided to authenticate the user on the remote machine. If the + authentication is successful (and the user has the right to open network devices) + the RPCAP connection will continue; otherwise it will be dropped. + + This value has to be used within the 'type' member of the pcap_rmtauth structure. +*/ +#define RPCAP_RMTAUTH_PWD 1 + +/*! + \} +*/ + + + + +/*! + + \brief This structure keeps the information needed to autheticate + the user on a remote machine. + + The remote machine can either grant or refuse the access according + to the information provided. + In case the NULL authentication is required, both 'username' and + 'password' can be NULL pointers. + + This structure is meaningless if the source is not a remote interface; + in that case, the functions which requires such a structure can accept + a NULL pointer as well. +*/ +struct pcap_rmtauth +{ + /*! + \brief Type of the authentication required. + + In order to provide maximum flexibility, we can support different types + of authentication based on the value of this 'type' variable. The currently + supported authentication methods are defined into the + \link remote_auth_methods Remote Authentication Methods Section\endlink. + + */ + int type; + /*! + \brief Zero-terminated string containing the username that has to be + used on the remote machine for authentication. + + This field is meaningless in case of the RPCAP_RMTAUTH_NULL authentication + and it can be NULL. + */ + char *username; + /*! + \brief Zero-terminated string containing the password that has to be + used on the remote machine for authentication. + + This field is meaningless in case of the RPCAP_RMTAUTH_NULL authentication + and it can be NULL. + */ + char *password; +}; + + +/*! + \brief This structure defines the information related to sampling. + + In case the sampling is requested, the capturing device should read + only a subset of the packets coming from the source. The returned packets depend + on the sampling parameters. + + \warning The sampling process is applied after the filtering process. + In other words, packets are filtered first, then the sampling process selects a + subset of the 'filtered' packets and it returns them to the caller. +*/ +struct pcap_samp +{ + /*! + Method used for sampling. Currently, the supported methods are listed in the + \link remote_samp_methods Sampling Methods Section\endlink. + */ + int method; + + /*! + This value depends on the sampling method defined. For its meaning, please check + at the \link remote_samp_methods Sampling Methods Section\endlink. + */ + int value; +}; + + + + +//! Maximum lenght of an host name (needed for the RPCAP active mode) +#define RPCAP_HOSTLIST_SIZE 1024 + + +/*! + \} +*/ // end of public documentation + + +// Exported functions + + + +/** \name New WinPcap functions + + This section lists the new functions that are able to help considerably in writing + WinPcap programs because of their easiness of use. + */ +//\{ +pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf); +int pcap_createsrcstr(char *source, int type, const char *host, const char *port, const char *name, char *errbuf); +int pcap_parsesrcstr(const char *source, int *type, char *host, char *port, char *name, char *errbuf); +int pcap_findalldevs_ex(char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf); +struct pcap_samp *pcap_setsampling(pcap_t *p); + +//\} +// End of new winpcap functions + + + +/** \name Remote Capture functions + */ +//\{ +SOCKET pcap_remoteact_accept(const char *address, const char *port, const char *hostlist, char *connectinghost, struct pcap_rmtauth *auth, char *errbuf); +int pcap_remoteact_list(char *hostlist, char sep, int size, char *errbuf); +int pcap_remoteact_close(const char *host, char *errbuf); +void pcap_remoteact_cleanup(); +//\} +// End of remote capture functions + +#ifdef __cplusplus +} +#endif + + +#endif + diff --git a/3rdparty/winpcap/lib/Packet.lib b/3rdparty/winpcap/lib/Packet.lib new file mode 100644 index 0000000000000000000000000000000000000000..81618bc8ca221dd99e52b0289ae4692a01f63d0b GIT binary patch literal 8450 zcmcIp&2JM|5TAVT(Lh5&zQ0XCKra-6O@f4?d{QEu5ZR{XW;XVwEVaE`+o450^v0>; z#EE+)#EAo!-Z*ih5|!wsQV*5*6LR22XZG#BuYFz|oUAnQ?##UTy^onU^IlF}v#N!A z^Icyj)aTO7>}+x_nY?^a<%ge_X6J&}yIlaV4A5N#=y?jz`xanip3%@Q0MWo5Mk6nf zk2Ly$(bzTsQQtJ9;Vl57{!T`tlcDC1hSB7G!G_lL5|2_8W zeLlaozIiK?%df0vmosadxm%gMXBB?1>yXcH+)k&Xa`=@gFmdk2?TwrHmBrj5 zX=kfyRUdw9S8I-2K{HO-%Quj*7T?%)qqfZFnk!Z3fn9B+uSr>}Tb^B6ELvXOuBzQp z1WY$;SBmUSRh9X=X04Gb3YhLQ%ui8etGM{N??1GJx zXELjan96d=t=YzjQzcA0Yu9i5bloXMW?2z1U0m6~?uJ#iwfTz(S(}XgeTf`K}AU-_jawa z?HWdg{S77D_PSHaxy!EiP#qn0LP)r68pG-XyP}N_XHAj>w(G9PLSM5i@p&&+cFG>P zou+Eng+S3wJ7q^-V(c<$ha#rGRwLeOrDzvb+lqkOPP?wRghE*w+w1GsVd(W3wdA>Z23A5S_@U#cuZ7;z52*BRG<^~oGiSrXFB&_VNhyMKiK$qTqDfO% zVoHIo z{sJUkwc~FuW<+|r#GuYYU(XR_kvV#(o9AAiTz3jpx8`ow6X!EuCDLmfH+`x8hrp;M zS-`~azhRYtiI{i-1-npi%O3Xi-0NT9BleHsQ44ygbL|igc>%!h?!A!X4~|-Ngq$Sl zAOpBgN^ppewFH02I=~$NCag{T+RuZpG^Ne?$xJG|n;<`F_x=f%P82zLu4S`-I zKe-%=$WML`KZ0NK6SBMS>)*_(V%3H--QXTUxJZ+;Hai=MuD=l=Zq{O=D-}$T@46IS z@*_o8GUSuP{uO=%zxz77&CDp)!woNB_UwnL%i)a~-HcIarrT)GI^~bMx=Ql@mJijb$1uZTrjw)!P z*lh(b8E&Ln6ygCLs{|f}{CLp<_qsWT0x45xRYXJ;;<-I9rxnDwN^ep@3~!MR3T;Y46L(WG+W!N((TxBA literal 0 HcmV?d00001 diff --git a/3rdparty/winpcap/lib/wpcap.lib b/3rdparty/winpcap/lib/wpcap.lib new file mode 100644 index 0000000000000000000000000000000000000000..f832e0445b5c7dafe5a0f887262064265ba2b293 GIT binary patch literal 19320 zcmdU0O>9(05-uRW4k3h)gbS|j4}Uz#t>t&Y%Y)S%rl;4JTp5pCTuoh zr6{Lp73IKQa^QrbD7U>tdx#=VoK`4`_7Fwch+_^p| zS6BDfKh<5`)$NUA`Fde~ylZ#2`x_V>8Oe?2azi67zdwrRhWbZ!@NyRb{1af)Ai(As zfGr;YjQ*f$?=%3>0gMxkW0+_MhKYuM)O4~3fN1X*n)>bm5FNa!=@dc`jeVwR->(2f zr@qm2dK`f0IF?CtuvgRRPmzx_yk67JDF8*E;}+y2(SaM92H(eeAPs$`X>=9#JJEGb+ptfFdaw>e+iq*x`Yiy_8LSsk zPhHb?lqKrHekD4vPE+rP*gr_)Sa+hqpEMo(8T%RO(3GZ$?*SB*@r$$_@rd?+t!Zo@ zjvvxV99NR-y@~cP&F-(99u}FD=x9fbs_AYW3=3tr%W|L_8r?37d|TiVLY~ zEvy9P(zP&>67jfHb#AU)syKqo60(JIwPA#!ut>cUHY?T2Y`I#v8X-CyA=yYsIvgR1 z{ec~7x`z7J_EoXesO6i5`6%5+g-kun7o&6?6lsXL*a+*hi*s{fJrauXgmly&fhf^s z3E4_`-3*NminK;E-)tB(9ge34;dLpXqEaSo&XvkdS!WX$Qnj#NubO6=h)8cV>r%o- zg$#}#%0zWB5s_Y~F4Rh8)(8_zN(7avo*HT-qioC+@^ketEL4l8NE;P0#e6f5+G>={ zMukkHlCL%9t7a5zRLGPXLF4Uwtri*$kqjZXkpEM)9$X9SjZ(D|bw-RQrAw8hw96CH zIB?un6^x}-su3UwQbeQ|7jfC3NgauZcw9Wn7pTvr=@psX2-v zPKxSZ5_y=PnoE_N$P;l>b2RJuN@JnKx{58)m9q&VA1x?B*qjgRVZ~&L@q{!@+G|$O zMuiOZZ>iF(7OFMdSjiHy%7zr}qAKD-YOYi%Vt=CNK_NilssaMOp#PS~G0a z3#jr@2fHjGTg%rQuBgKil48`YO^Y*yd_7#KHp6_O8RQFvux8Xd$xh8vE;W)lG&5CR zE{YZ+xiZSMFke|T8koY@IHd|2`Ept5435N=dVT?dRHmqxp2NoQb4*B>?S@fVJ*ax; z#(FH|ab7p_3pF&AS9m=V93eT2qkmOwwM1MS~zh^OYj+6w(qzK0R@x9xxG+j`OQ@O)YAwXd4wWGVhD0>`FwwU%QhSy`Bsht3yBaP(% ze(43MpxoU(=zYOFA0d4{0I&g1$&>iKwHu(>kDdVhcHwsomUZU@z?X;clzbTAW2BWw z0NzC^?gw}e%b&*d8(7cxv5c>V09Ik$uOp3b!!mjRZsYgctytC>fI7y0LnY-36{Zf7=>XNfjzJf#$Z1jgA3T1 zPr!??4yIuo*25%B!C6=dn_&}df!E4q}7h2Vp-SXex#;FLwXebxMB`=5C9I^9PV8s(AynihM(q47Hlj}F34Yx5 z5?lA>X`GVyBqM>5uRR)q`2Y)!$;$8I=7z=ffJr=%AQ6tTb`!4lnRETAExQINoiFRt&`kb6)zb#5OTk(WXF`3LzuyeV>Hxo-xE;5&wx*TA8>_O0# zmkw~5!tPVa^mwZsG2>X)OyT6P_FY#r`5rUt)woR?W2mOSw@rK-bJ`>O{@4yI%WYCPuf1kaI9X$ zNp*3w@H`qDr?aNs+&Oo2#&Hz0Why()^2D`)wqGhaX1N5xvM@q!8M4BUSkpzx4EynIBam!|lli=G+Mk}qYj1rahg&EpnNTMnkZ z6X;YS&b;BMmJ!Md!^x2hGOWz7`V;-AEPO=~#ptsfeItO|rMA!b4@pA?b9;q` zELR%xFI6w99i(bVQ6qBcEkNU%@)Gd`Z&9+L3Wy4UP

ii zt(#u7(X5F2?uWKuz$0Zt8OJO)7!6qr;{`-mW-ub#&;iOoI?D5ivfQBP z?YRYMzrS+nDC-bqg+bw+zXjsZL+Gm53p&N2Dhi z$sPL*kF_J!=aoO!_oo5a`Wl^G6SWCz8X~fDnjyWbFWEo#2>_LrfpY(yof(M2GuM&^&tn45RTGq64I1es%5IBD_q*{iK;u2FYa$7I6mN$G=TOG^=4LlDoZVf8Mpw z8`>v5@1R6iH=VS|vlhSLVkx(ih2l^~-N<=b^b_Mk`m)-zIUnA+Dq&#M2jgMyAnZo(4AD0*qp9b5G`pq6hCIM%0W!8nw$ z=X{p)l{75!sW3?UZSYVll0YzKHbPhY;~;29sU1>;c0zRY>-XSai;ZdbYZCG=to zq}NeHHZoF*W4Z&(oJadNNlfy2cY@QRZM55d-N8}r^iGgGy0KXzv2)UbaVVp147WIa zljmv+W4U(#jA6SoBbv{mY-KcYyI`T(Ull#QxQ(&o#f1gqP{wxoR*xQmS-4#qq68LyTjtHxo|KwtJB;6=J(Y@(tt?ceEx_3CTXEKlvOJ{NFy#1JrL^z$>YNrb&<@)H8*An#mck^5f7vwn&$@= zl0z9sY}m8Q7*9o{hYgHkLs{`!j2wCD52oO$CleN~{Wa0!-I!oJ@fxE8EMH$9a z4-3eltbOUxmcuD{<_QVov_E zH5QOV8As7)wU0Y^#`|rDZ3!!<#~Pe)(9AO+ZjXh{+AKB$jT}9S zHBXm1z-lq?X#aRxVyQ<_9pHHO31=jZeQssJ+SYsD$#znrB{r%InpH16?K&%w>>DwL zSc1lTMr+DJqo>Fgh(lRh<ClhvL%JxCqKEC=kR{Bh7JE3l N*?W_a?2Af)@;}RMSJ?mn literal 0 HcmV?d00001 diff --git a/3rdparty/winpcap/lib/x64/Packet.lib b/3rdparty/winpcap/lib/x64/Packet.lib new file mode 100644 index 0000000000000000000000000000000000000000..30c15405037e32d45233593bb67ac27f66c5f3de GIT binary patch literal 8290 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 #include -#include "DEV9.h" +#include "..\DEV9.h" #define GetKeyV(name, var, s, t) \ size = s; type = t; \ diff --git a/plugins/dev9ghzdrk/Win32/DEV9ghzdrk.vcxproj b/plugins/dev9ghzdrk/Win32/DEV9ghzdrk.vcxproj index a2103b905..e9a5cb30c 100644 --- a/plugins/dev9ghzdrk/Win32/DEV9ghzdrk.vcxproj +++ b/plugins/dev9ghzdrk/Win32/DEV9ghzdrk.vcxproj @@ -60,7 +60,7 @@ MultiThreadedDebug - $(ProjectDir)\..;%(AdditionalIncludeDirectories) + $(SvnRootDir)\common\include;$(SvnRootDir)\3rdparty\winpcap\include;%(AdditionalIncludeDirectories) NDEBUG;%(PreprocessorDefinitions) @@ -74,14 +74,14 @@ MachineX86 ws2_32.lib;iphlpapi.lib;wpcap.lib;packet.lib;%(AdditionalDependencies) - $(ProjectDir)../pcap/wpcap_32;%(AdditionalLibraryDirectories) + $(SolutionDir)3rdparty\winpcap\lib;%(AdditionalLibraryDirectories) - $(ProjectDir)\..;%(AdditionalIncludeDirectories) + $(SvnRootDir)\common\include;$(SvnRootDir)\3rdparty\winpcap\include;%(AdditionalIncludeDirectories) NDEBUG;%(PreprocessorDefinitions) @@ -93,7 +93,7 @@ MachineX86 - $(ProjectDir)../pcap/wpcap_32;%(AdditionalLibraryDirectories) + $(SolutionDir)3rdparty\winpcap\lib;%(AdditionalLibraryDirectories) ws2_32.lib;iphlpapi.lib;wpcap.lib;packet.lib;%(AdditionalDependencies) diff --git a/plugins/dev9ghzdrk/Win32/Win32.cpp b/plugins/dev9ghzdrk/Win32/Win32.cpp index 31224e87b..3d65280e4 100644 --- a/plugins/dev9ghzdrk/Win32/Win32.cpp +++ b/plugins/dev9ghzdrk/Win32/Win32.cpp @@ -5,7 +5,7 @@ #include "Config.h" #include "resource.h" -#include "DEV9.h" +#include "..\DEV9.h" #include "pcap.h" #include "pcap_io.h" #include "net.h" diff --git a/plugins/dev9ghzdrk/Win32/net.cpp b/plugins/dev9ghzdrk/Win32/net.cpp index c7acdad27..57edb104b 100644 --- a/plugins/dev9ghzdrk/Win32/net.cpp +++ b/plugins/dev9ghzdrk/Win32/net.cpp @@ -1,5 +1,5 @@ #include "net.h" -#include "Dev9.h" +#include "..\Dev9.h" //mtfifo rx_fifo; //mtfifo tx_fifo; diff --git a/plugins/dev9ghzdrk/Win32/smap.h b/plugins/dev9ghzdrk/Win32/smap.h index 42ad1842a..4247bc19f 100644 --- a/plugins/dev9ghzdrk/Win32/smap.h +++ b/plugins/dev9ghzdrk/Win32/smap.h @@ -1,5 +1,5 @@ #pragma once -#include "dev9.h" +#include "..\dev9.h" u8 CALLBACK smap_read8(u32 addr); u16 CALLBACK smap_read16(u32 addr); diff --git a/plugins/dev9ghzdrk/Win32/tap-win32.cpp b/plugins/dev9ghzdrk/Win32/tap-win32.cpp index 9c4ceb435..1223ec1de 100644 --- a/plugins/dev9ghzdrk/Win32/tap-win32.cpp +++ b/plugins/dev9ghzdrk/Win32/tap-win32.cpp @@ -29,7 +29,7 @@ #include #include #include "tap.h" -#include "dev9.h" +#include "..\dev9.h" #include //============= diff --git a/plugins/dev9ghzdrk/pcap/wpcap_32/Packet.dll b/plugins/dev9ghzdrk/pcap/wpcap_32/Packet.dll deleted file mode 100644 index 26a4a65d779e861a65e1221cfbb268e10d7a147a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 88696 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 diff --git a/plugins/dev9ghzdrk/pcap/wpcap_32/Packet.lib b/plugins/dev9ghzdrk/pcap/wpcap_32/Packet.lib deleted file mode 100644 index bc9dba853308409bd98da2d296a919d44cb00585..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8674 zcmcIp&2JM|5FaNYfj~nD`Tleus_2E1V3QzKRlZBW36X8uqgm`tS=IJ#?F}tldPS%Q z4*UzfQHcYWa-tH~9xA00w^kLm{sV{u>AZdWKKFTXaAIk)yEF6V_daIc%zK&s!m1VT ze%bwbQvJ=&F3hFU3+bzKD*saWIXk})zTWNzfE9qA8o-$c0DaE@Mkgr^?*R}RT%a`i z82LzJuPKeM0}$$OqcpM%K&bx>rP24OkJRr|n%n^(G?1k{5hrRP5?qf z?kb=i4>4 zJBonn=Im;TzNxA*U)QWRQbhsPT`HH|qUGBr%esu}Y*ZcJq%HHQe7$BH?aF+rnYD{H zPM*oECZZ}UWw&k{Cr*`6?VRmj`(fQFM`l?OP+eTv(C(I1v9OhqES0LfgLU(a_f{OMKpo)!m9m z+)h)qeIZbEGfu_Pml(TDw3&$NZ`28Ity;26s%=HUZD(B9yMtTivVGUO=eXM5ga}au z+Li=}Q`;_D-ZiUQDr*CYNDrPbukw6(9usD*2jIaOfMoI_J z%v5dt0Lvo)Z}9mZ`93~(Fw12J0IH}nIRWq-^*W~k-VLD)ZH(jdNfO}26u=BVpQ6p{ z`2Gm_KI*;2HV=`Wq1`>S^$Kla@`i5cfm6^6=b;nEU%lXFihGrtc zMtO82;jJTKgIWzYD&C5xTFQwgAcJ@7H2`gDNVmqk6WP>7N~VTHGUgc;!)007!L=&UK&D(2l;%Pl!+?}}DoAFR@pG^u;3oI+J! zl_j#r%KV7m>cZH~N%LW?t>np3i7_!sUahr=NzI0Y#r<5iB73{SZ?x6xo-a32{9hJm zQJ{(pRgdt0HO~mXR*|631<@f}COlKEBu9#-PejJd*|6}7#*SuEiXdHLDpsUu($tlh z(qufc6uyYBMkg9CIM7@ymCH1Te(0n*KbsEEoVU9(iFWws-v{geB>=M#z&`+qlLsCR|wox+#DB|XAlgyc({GR*lW$R~7*MY{lJd%KWDrwoe^ zeBV#@Z92u8TX%Q-yLTBU7#zWAXPgw#K?ZQ0wBQgv)=2zEtYbOGzX{ehejVn)UYgS8 z;$SY#?p{b7v;}eS8+M9z77`{uDM>>huaci!W+LJzzp#(+N&JM^J@oZ&W>v8|#hGq! zPa<5T$yuA9kL(_QAwb-${T$8$dq}gEW<27Ef3T16DMeR`iHP2x>_gH!wApQDM)8c$ z@Pg^Uewe--PH2+c{E^ViB*>mT9gOaHgBo6}o4lDcw}$CiGa?Du1m=P8oUhbet>C4u zn(>HZwh26`l4}Jmoid}HL$r2*rq_oOq}~}uE-H>IXrh>J1uw-mQq61dA_A)f9)XzI~ZfJk229A4^*IXB>CU~nH7 zWQev! diff --git a/plugins/dev9ghzdrk/pcap/wpcap_32/wpcap.dll b/plugins/dev9ghzdrk/pcap/wpcap_32/wpcap.dll deleted file mode 100644 index 1dd1f69709e730b8fc56c5288e9d6b55e6735163..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 244336 zcmeEveSB2K)&C}0!U7As;09NTy6CD=5{)KWFrWcLhzht#$Sy4is5D(uw5YpC+lYy~ z3*20`(w17=+CK7VTU-0IwzVz36cd6(Y-{nIK4^@f#R$I5y$Qf7SB$qyH!*k2&d~F^&gD z{9)pzyxD)4I4^q5je+GieBpC9TzPHa>MO6i?hCQNRi6#q5Wg;P&2@pA%NqmNeqrfn z&l){?WY9vr@to?*UJIS&w}0Q8eX{>myg#$zRCzYf4){O7d-MDo{ksM3Z2#4g9`s*{ z=gHv`fjfTrnf|}wz2Taxqr^3o^3Y6&V|Ly!$I`!ksn$;0?HDt0R9>OO;my}SB&5HQ zhcE&G#4*G$e&i4T*-u9~LWtk|3#UUM`9j#tQ@;jY%6F8w9FF=_IiS@JNA+16%(1K=3H^XuZaoLXb)I#@jW=A4IH@b@EM+gDq-FnA z6W$H7Uqx%x%SK2x1BcUW~+ItaLUQMWlJy{bA=uY!`*H8n35RIhx|;Rr>S1AY58 zDanD1Vbv=j-il6U>%ku>Ci5p8X>qFoP-FH3b!uO{fN-rrcSQ9HjZUN11@gy)RllZF zFc}y2)XFT|+%_1c&~DbcLaGbkVfC=4FjFk*=QQV`juErYY2M&6C#Pd$yjA;G6fRCY zK7gW^yBZ7LGM_M~7#EsfbQ-Ii<`-SYDwlbQ+nDQSo|P`J$Dio(8hH7Wd8w=5J@Zdp zz4?2;Z~ksU;^l(9_m~YX02Vy47!VbmnWCl6P3E$o%bW?0#*b@%O!#y!Sk|PzaFetM zh`6E~jpl7+O?>rc*lEsnHPnaH<`rPlPP5jT*y^p?8T)i(pvW1>_ojbEBrT4pu)D<( zV$cg`PZ6g1Uh`05`#?qKKYzOasY@0o4(7LxS(`lLQDnelGaljSI+U*Sstbh#ui3q5 z!4-Bh2^sE4;zCD!c+~w?zPImFXdPc_AactDtDWBlhOqh>$V+T>gZ{;f7Idpp@ZH?W zCfyaE5Z#%Pim+NOfG!KrT-^pTLh2ZlZO(N@8taYkF~(Tcs-BJ$rHIY~n;zZ1g<#+C zXdB77u*Dlv4+*3z$=E1kOVGydi21Hnd$SPruWtw`Qvlt`&c*TLqBVfjb%1bb3|a@R)4w|Nb1$kGuhdAE;Lt}jyV-RH-}BU?q5y_M{0X)0=t?S za+%fc29_3Ts8_4dhfw2g^h>LUWXiMquP$%8#xDJLdn~8_Zd!Sg!=YB7>ohin%?E;O z@fxwDpkkNEfw3^?Z9hm~3__(VO3Y;N4nReddo4)_sY+dEX`?F^v~MNSZu2Jsm!2Ig zX=-e2tPiV;JS5kjI56Nz?imJUQ4=gl94PRlo<-MhYD{kkt{dfWG^T5Ul?|b=^5%g5 zmf#NrHvn-{cv~{q1~;8U%{7S7B?!L*h^oDwki7 zY21t042>>N^6wySD2?f)&|DvCQ0u4_&L@d`J*mGO8bI&6qN3AoGS$FjSG{@+KEhD6 z#%|#z)c`^gTYZCDII8|>i9nM&M*wtx&WgY~X|cqC{3hc#PwI=L4J|Pok7RJ&G2j8X z$2Je8=LIY48^WqMr**c&?T4x)0iJ1;OU$?09;r+qYGG{bwqzv}7vh=1(@_hoi~!QL z6Ig*)g+B1QUVZh3JV!^e^6N-OkC}RA%xmR7)6NYNR$2%eLIXvCK)x4(Wz+=y@iQ!p z_0jvYHNFTKfod>IpoD{{;ysjj<{QSgtty(c;84>V1*0K{?tBC@=`RR`D8^W*-B(aUV|~+ zX-sz+)7_zvG2Kfl!1k8>kP3{Mp4m22y9L)04cNRoNf{ z6oGoXjPf?ui5RI4<+~wz7r7$xoeXY3X;RD3Hs=(FI_`SuS$85f+lc8e=0(&LDW*im z>sU4TLt-N44)mnIp^}Yi$&J!hW^2$7m9R2|5v&-E0^{PO-aAllbq~NyZ$s~#5AgC$ zzBod?)p!A zf>T>u=mt$o2%t6PqX1|`8qh^=1@=(5Nqqx2kv@&@p5(h^?tu?lM^tsUB2QlInCSYf zoPP5QlvDQTL!Tgc3Aa0jw$cl`&kDB*w{wFc)?mcXgK_obeO#t-1P5H(xE zn#F26AWuk4cE+lNYLFFdLdBMZC=y7iZ-B_%!9J}{l7d)^_^E?S(^+RT>%8ES`iAIQ z(A&4ooE;2kUSPaXou4LCsdWwwkfomF1JL>#i$7D~HRlBbRo%wCpx=}FEePA_M0)5npFuK1F@7dzV?l<4%ySC;YujmwW?$K(X1gr(MA4VVTihusp{N3f2-DjTQ z1$sb(dn@Aiy*V}^O7g=4MQ&YqDgl<`)rHrONyFqJG`wp*rD=G=qTvY^4GKbg z@3Bf>G`RHm2&?42ndWHs$@$)jU8(J>PJw__o0q>|pP|wi9(!H`T%71}RsE^;<%&)K zqKURv8@|V8gOKW~uGW6xG;P$LVQeh0)lsqQZfVTfL4Ws*mi z_L0=j-X9pC3L(P(|y+`hi7j`UOX7l%HE!Q3>i} zoiBu9X}d*BAZ_*Al0M>aXtT?YC{*kYP^HZ-wYo)yq`MBU&ksINk^{!Ym_mAz6M!VA zKK0UsZqQxbfVmVz!nhcdjpiv30tiDfetysD*%0h(wa`YOle9R143%odu!7_vlEyhR z@U8@2idyrue1|9XS7Zb4id%e`y^K{OL7UEr;oS|9I*4jeqzVyRZ1zu2?St4Bdy-(g zBVFsHW^D~M^w3atsCnpF>^U^OHGr!r1ll+Y45{;TQbWwX$la6%OA&+~_UELY%hXlg zCUEq91S1XV-4nBzeTafh3wqChA&ke#i7H3@1X?lvuv&Z#YETmlfar>S7^dP*X!T;m z_)&wJYAu~rUBbt8n`qdu@1k2Fc^-5K5+-}rRX`U|ja2MHbR{}ITLLzMx9Wf=nNI>> zO6s0&HPfUXOeTIQssk2Xo+tGpI5KoRf|Te?>T^+%+rCRx4O#98^_?Ewjai$OTxTUu zQl~Q6Ro~}Q6BzO~sIOcDZswZJ69m|YN>rNXkPir`sO+!#BkItF3|Fu7-F`@Fq zp5$ckvd)tn#YgM}lpBc7f7@b1NKMB)ORHi`-_ag!>0Hs-fC#J8Aev}Aw6vQh?S0^P zTb09;{7(cTQ9ocB)m6|P<__~cQ7N#rWUeVls-B9MMty>4G#D#!Q2u##IO>(Ow?zJf zeIt?fnuOh8ZEO={Q#7ae?Ry-Uvo@M{2EBMTg;TpC+iHSd2Zk~)(8-gQT&w`YioMoHnRtC9=)QS3*9>*|0r`Gz<3x+i(Yz`#HU7?}k9 z_mX}nlw1r?!Pfgg7x;t}2p+(677oCY;`EMn4WZ7gE9&Bux;%u2*LC%zCZUX$v%~6u z#DP_@W9_WS5~`0LfH3yH55?DZp#wHN zj$Ie0Pd$iy+sWy$&YFfY*_HdLM+`O3rVpm5W0eyXQ z(ZMcY2Rko=E7GJYhv4!gU%)(U@gglSIpUJVcTBVu_(V&E)IYBxpR#ijVJzfb`9w#`L3oPbr!SL`=n_ zu?c;G0eZgpj8qI%?5f&tpz-nZ!%hp}S%RMrzf$~y_!S$IyjPQuG>4S?Pn9O9Gg&{7wSJp41iuOxM1ye2m=w*!Zgb8s}-J z55igJtomc@Sa@S&QsPB}Q|G&?{z5`y6BF;{#flT}^(9b}=s58#Dt zcyBNp&I=$f`tC506Zc1Fqc1cKJdf6LH=ETi8=(fsi~FK=830!^JmzG0a{_;0Jeb{! z_wSt0x#-j+2L3CC4dyqz#ih;WUz+#tny@R;o!^`q5LS4Zx!8eeUy#(sT?`>W7h*Nq z2esPoNyZ@T9fcK7Cp*n2V<%5NE1ox_V|w0nc!l>S-Ytl8B36uQ$PDCa!0v;k;*5<3 zE-$I*y%fE$qbPvM4CpO?kfxMOpwC+i3uNzo5&_*c1>JbZH1(G50_fwFcqOT`K`Q1Eq_`gHT$^%mZGb3KQEUAHaLtLEUHS28c#L$$ z&o^&&o5R89GSiD;%!gJjp|>~~f>&id=uLGRg`Ol0phS-|y}X#f@n^8Wpp` z&@dlmLL4ggZA(xMIbgzhQXM2q57;tV$Koi%Ywqpvc06&x_;@iCjISenGipvk=E&fZZ_kC=C(a>Ir{H!uLl z@J+)9f~f&1eK!>IL}vx<${V&kS_a~13oPx8yi z+Q&6Be=u(!gc|eJfwp0YyanCOi<%1&2h{j14Y5n4e5YN0d~{fiUnKgkVqYJGUoSqC zG*fps8+G}{N+;I3NSd+8WrTC7NlL}RmvT=s1psI($`%>3i(|LnXMF*ovPDROtWf*!aCd7xy zaAN^9=DL3}tk4U7Im1$zEv`-@7HxgSor^GzNSk|QScA;PJz;gSt_F$lLi}J}K?Hql zaD?GK;3}nCgaC493joA1BLL<$=4{{N1P8>j!BX7=Vnt%TN4m3KL_)XcwDN=S4eUlHo~? zgY4JEmes|Me~|Ok&G%v)*!%tF?+*gr5M--G;1>M~mYB&WHwO2SIi#RiKtNT}+%-1@ zi}5gOz3h&+D-^+1-wfS%N-`>G0ZZ23MG`OPh3FJ6hBxJJH&FZe%>I4duGsnJm=<`& zzxQdffNO@QMq?mT3>SE@Kf`6?U%~y7u$CSz{_N}a#%j&+Esh3tMJDTc(NH$)Aw-AO zmk!SgD!h@93SC8{F0((Ed|NQBCj{O(tRGdh769A#?4&kK1{EG+-yA?79D)6x_3&11 zMh0kn{M~zB6FNmTVCc1;ieHUdd9jpBx9w&KC@9Yx)|d z!VLugP7p%s)LNnt&+q9p575u)X%;L)b43+c(zlh0Op=Oojgq8CNa!%{aYP~3(J3>1}9R~0dXxf7HBQoJVK8|WFv7yvlpr|1%*FQQ1*Hl0Me z1+7*Zx|ZNR1}Fc3o=jxz~0u|G{$Z{=qD>9n49= zNgwlbNA@wVLy=h@^T#LVC_K%Y2Fuy3$@rJf=GQG}bKpaq%`@q2?#*#F2XdXwu=ICy{+4`tQpED9hb%=K=!NbFGfE&hseM{jV&&1_Q(77>f+^r= z8P(LN_Mb07EKz+hgCbOtaY)F_-HN;+_1rAN!8W=1Gz-TsGdLa;9K}O$ ztP2tc)~?kTKP6(y?pR`FUXjV%sxxoGWQ$9=b{{j(TlzSJcVDauRLq0s^vxj>v0r|O z1~(6xzfR%_J^E+N=Zd0h@uGehmZ8#E!=%1(I`V5e@@_%c8Lv@i&BtJcKE5%Go}TOM zI;$zq=FoHJ*&Nz6oduT|?k8+Wv!iN;Ipac_JZ zENwPNAHW0s)X6cwks8PyPIX3_IhBH04gdW+>{ytxc|EuO1HtCR($w}iJ(1lT7Jy8uiL57$TTg3MzY-lqU~&V zAlz&&&&L=NKimAB`Fz{U-hF?XuwA>X+h69Ss2*BsGKCE@Ba@1?5H<4lox~1_Xj#t) zVL0$d`$dkv*eK&L{9Lwo0=2KiW|gWg&uSWyIVrM61w92O??-fbE~7zX39E)-f%Ky4 zp5#LeS36U$gM?tLAk_DTmV6Xl(&B`1TB(VgC`3-!*PUnf$099fh1DcIwt@6IAnUuB z+&M>^@ny8yV}*6GaTwyscbU6shVhlw{DKVsg3yfG*36h#s9UMjZADooPHLrVRFYdG zAcTF9MJ^Lk{hB*uw(nVpZpFPWWfbU0c2JzW_r8rK&<}6`baO_6-&78bV5$S_rs`zu zFS(ll&=g)s+vIv^5>6o-qM?0g$w8_kHrvuG(KeJK8YYaGfpM9QRvRR*PM(VVqHG$} zKkC`Q*-ZtcmhM$Jsbb~m&)72J4>hTomt?y0SJ~<-iqVr_C7k(^`CrnrUytvgFR#LB zEtz6yhyL-TCNRQUF7;GE3tkJAgk7mz8sbZLd<*!FGh_5}G{ftSE zNRl4S<^|^u8p`ngFUGNtUMQWf7fQ>xI4VQgvDSj+bF5Y$7?mByNZ`>@aTEhsO>n+7 zddWhqC%FZs<(7VJw)EZ~Ak1+Eax%H4uwMPB5)Jf#ENhvmHb|2+br>Rq%>XbqzlDLt zOlK47)eonN&P1O&Mt%MQaj-ytLbr=Fz-uzb{07_D_&WdgjWSbwiiXy!ob>6Fa_ z@U0>SGjAyENP1nc5`s6>lCILi$RxYhmkiN8)?o2(Zqg_js(awPMq`Bs!14GkS-tad zC^#y;QA!)Z9r=u1t7Yk^XySMtma)R zQV$zL>tWVUSK3;ikR2k;W+69&VDUbFU9&j`8%CPVaDKBwlnl{ z0vnw>jlB3IwHq4-xOCij8LVk=uQ+Q_ht!Lguw1?C5}W838!qhcrmqK%jXH#}WduH% zMcsDE$2#I)99ptDjqA=VojYBziDj-IJNrOf3w)D)^-EL@b0LeOd{8u(6v4jlx)fZa zBPUByy}C4)q6dewMGx%#K7C`|z~W_~2cl%NXZV zp;x{bUDmO`x9i?Q83LrC`z%7$}R=P6J}%tH-G7Y=cV$ zf4g=Uz)&qQQ?CLALgm#E$*HI+CrYPVd*vNSYl`-xCDqr?p=f0_7YXY|@1=`FT3sSK zQuG(4f7=PN?#&l51(iO$IU=!gGtI(4L{c{TMIG;=(J)>^J6qn4bAU}8CW1{9CmVH2 znUTZ&momWEP>e|P8y3!WvRKhFyuKl#epO10aDNPsVVB?sp5!k9>G?`MgcQb3`jQ-B zm4fyO+4=FaG=)NUL^hvLBenQIWPYYxPBA>mD_Qo2U^yQrP(&KA4{T0rqSK4H#2Sfy zAXow>X`=<8rFg+^6ERh&sF4%L8bZcMWE_JnrvPDT#DiBiUQ05sdCZ@Ao9;B{tkkTY z4rlY6m9a*1JW#TPG?wB3h=UU5Wb>(96CVKFlfd0_b5>S89=pZdv3Sx`=A2l;6UNMy z#+(@D6iDZCoaTO^MYLvzi5`;=Po8EGIMR<SYoW$SGB*@nHsqH zY<9vlrfZP%Vy@O~!EzVn6|3aOKraN)6%pS!@Ejs*`?k|3c*TP5jhw|K_PClVUZ*O8 zg&&Fe&9BgnGi7ZXm;v{tOs65~Z-`Y2X>KXR0SZjM%-acP*{VV8Ol?qZsPn|uVBd`y z*pZ>%vXbhRGme;H7p+?8>sM2h$eiB=`XAa{APce82Nlhf#0DCMN z0+SwdHG2YpjuilPm+rAW5)Bftbs=74t|rX@8r9SkQa5W5bM*m4_DGTd!g3C&H*44i z&K^l*v^w!@ZA@=<*+Uk{;oRQ|g6b7gk-^R7#{E0%1O(|$^rO0JY-pnk5y^H|v3e4F z{G3ceiYi`@O!?^^kP$x*nJTLu!{2iFEx9rjbr~gSE$E1Dyt}QasLv=dqFyVZiM;c- zV0n9GiOuQs=1!EU#TRl>B29En1(K!5qMfJ$l*2DDCMX3ue7CGNoCD7ovs_5`qsL*t zI}Z;rEnv=F*wy9lk%MWvIXAVs@*L`X^mZBF*5eIUYBIR45CczoU2y$K zD6BO0Rbo)2!{AN;pq)(%aTeuo^|LL(w>7umxKIbc*iHg06N11SyMj(Ha=tWG$K zg~~cWP_r+WWXK?LVrx0J2FV8S9`IjF78U^-)T2@vE&`BHPm-1++L&Iy5}D{$ZS$l! zGTQTv$u!EVwxLQ>t@%c^HQ%VQ<{Nd^d}FruXDmZz5Szqf=$v8}ld$U*4|`7W|7+v- z$D!e|JHefrJG-dZmz_|^CUAR-TcS68Z-5A+ReenjA&6SBG6Iwty;b#G zNRgIqXe=l|vAF8PEv~TIBBB+b0(1ikO~pQkrs8zq63YD;NMM*pzD_^I#uA3KO%^0* z^`8I$OMZ_8d8|OU@dgPC1`LLarHFDC!9{-%S{$_N{Tx< z%B{_=0P*+wSx`n1H>sab(~6j7=Mb<^2q?@Dz`R)PM?ul|0jVCi5X{Gls#A7L1mdTu z%d55dzvV&@mo@#H)a6owulIY%{NOG4Q_*Q2+It@e3+X`~a|)xDCn4uytjFACWS&5OspU6# zhLz&5V0kS13U%_w)N@01%;D>gN2JB}UVw`1;S$?>!Sz0RFDxAc7#u9IycgD5U)Fmu zNWXlPcF~5$SO|o+0n}_61>IIHay8fij*#WCGg0wni&4_2kc{P#(tn zTJ##aqu_B^ig%cP#xiUbTo$axFNmKXzuC%j9Q!q9`Z+tVnO|G&Rgc9^Hg97Gu`G4B zw$!U0i@(vwxp4qV4)dFY06+a{C>#VaHvsZtqzBuOK2S8HLxClKq(T zeoqvOySEIA%JV4B<{>{cm>)tuUzWG49`mH0Mx-s|K^Z_F1M(7U04=o!&~j@4t+WQv z$>OjZDeJ1e9Y6u{eCT^ahfyA>gLpB?Rty+!Vl4;fewTjVau9ax3;mI!7$LB;E`%-xcY3B|f#NdYE!GkCJ+ zUNl5wL(VEy)jP4lA|uP(pAS%G-M#OQf?PtVVjQOJtTI(;y|vIb&Q1P%KCkzf=u zjUKfSVzrz$op~E`KxUVU_rhy`z z%*r!7OZGAsmODQ}o@LvGbujR#r26nBFO++jARV>!VZ5(yaY6kph5EDB7N`xW0|#yLfey4qMYP|w6SSzjj~Ri58BLRYg(z}2NWW3WuW<~KlaAYMOWG8p{F4okp$j-r%qT-Y@}PR7?u>Jq5j_L{rCsd04it zG8I$fjwfu^S@R&^Gh;KXc^R7@1BHXMtxTwn%GUIxRv|N_B4cI#{~nc(Ft=Kd1~`0f z^*9=+wJJiNEWgg{*cgSaJC^!x2iU}G2@hYX_ zrdHiAp>P(0iaMOX%Lidm9x87%3PFloJUviUV;Km?rPmO-?yS*jPL{6M6qtqPXT{oARW!1>r;tc0t=JJ2+805gk9-@G&9ybbGcNt^MSzcrh8HK8` zjC#OntZ74WP|0VgH_k#g#2q_V!ub%2R-)+KiJMZBn8DZAimo2YuFPR`HoO>TfF6z! zvLJOE^_}=Jo|k?~2S{wD#UZV=ojAsUa>0^nC^&A>(k|fGiI(m~kFSP?rOj-)jpfn_ zDO(nfwFiY|^C-4e_6x|p3@wPl&99OQtY2#q00TW88waHp8!d#YKjB^)XhNiLNa9IS zj*(0=*D`Ot`i+Lb99%E2%N$u~RtrNA2R*|87kk!lfd&70=1dlC1vEQ7Uyr3QF0mD3 zO{RbgY{e+@bd*Jhn;&e8sBh1)^%Rc~aIqE@?@nXKA6!hq+@`Qb`X*#|wK!D0C^*z1 zHp-%u8C&x7kVl^Zmio<67)?1ei)3*mJ_hTsVle;@*0URcY4{N_nFZ#Toj6Tf@p`Ir zMMbkYJTsUUc3fVtc5XpOB!6u<-<-w$m@@hUdjT?FC-lrJb;BPtPe@djA)DM-qE@#< z2<5nkA8!#M4gB!xk!_ufgX3#MUF=nH_ZJE*YW01H8(@@Jj<7UaqWG3h`XphG`+A z=$S&MEHU7WiLAYAGOa~P(CLe&Kx3#rqOJge=v>qI9vjagz6N`;s|VMQGgx~?98{c5 znbyT})yZD8yh_TI-3EjCW1U?QBGx0X(_Blb#qQ!`p(l9P+u#2|DqPj}LL+(`ZI+NQ z%Ej1B3%2i>4C_VKmTC|PQ>)UDbm$d-^zZM`F#HBPk~AsyEW<+tsNyz2WxYd#cSKYk zfWm8ohD68A?B!xf-Fkw=4X2%PH;yJv`tN}O?NAsAE1?D&Bud2eDEuB}$_vl?)P?EI z&u*Ugq#mX@lNQ3TssrM1sT(?nJw+Q#khrVfj9PBN%rwcIVvC35lOk` z!{+s&oO%7}X=u|SekxD$Hz0b@%>Jd!7PCQH4RIi2HpDB(l*k;&XrW+jrR%T_$S7E| z?H3WO#-W0B742ZzjRBQ$xL{Qb+WRAdb-Q%?A(C$Ky7x+KrqNOlY+|UE4|a-vY(XnPkf9gCRobL zfk+=wP@e}fkQW1aiLJcpGlURWlo!TjSr@W8j>ewEi^$J^YHkhTIOoG%J{Xw7I*rNd zdZCM+2pK zlQk#TZ*rmyR4v3=?x4X7no(Z~U^k;ke=`mf=dBnfcOXEF*v#fz?SJEZ46Wl0hv?A1 z4RQ$?C`Y1@Mze07wa8D4l2+(0EM18UEXz%j&~0T9GgJhFjgB+Njp|2|V~}J>4oHIA z#3EIuG&Go>4d#~&zWqBFFPgx!t^#eHNfz8N1-Jihu*7&9NWJV8{Ar?|YIGE%rl9aTW>N!;}a8-vrx) zOpOXI$t!_yOi3@dquHI-(WU5xdU=Hw1S>E3@ussGZ=B9AcifRK@1bP;%N(U zxDet|9x`WQk7G!!`7p$!z??>BsNTF?h;7qO%z*KrC&0_y>ug(LJusH=ko%uxSYUr2 zLS_zIvAGhx_ZBHvx;j*YwNIF`Kn+XvAtx?Fkl|l}eRM@~B?x!Apr2oietr@A`32VG z6PsL_7427?*?s{U&d4Y{EcU&C>DNP2C=8pSMg z_?ip4aI6ZD9hW*2Tb#Hy>4{^C-pU0cvbTn%BtFZd*@$6T{nFHM2=1k6w z>7X?a2>06u*i=yctuvxfJr1z;UF=W;Ye5aC|8j740UDsaCl7XDizCvg)=Goo)WNpZ z%;Nx&fLzcWLGDL%ZjN|4*|#}Ah21bV9DwB-Z(c%9e!6*`6K@ssM(?qS4=D$Thqys6 zp|8DTxuU&d>w0A%g}1eg5}V~m8dulE;gxa zevcWPb#T!QZkKW&ViZ^oKe&kHkV~4x6v#QZ*fjXqB6A*gY_Z}vwuE(Tv3)CP>^7%y zZ!+s&^+D`Rpf2Xw#fUOw%)wFQ*!4KKSoKa^5ypHp33{tOh(BNT4la)Z@!~v&&kqZ` zp46j^uud)dGMg0q)+U8wYm-92+N2P)HYt?ICWYh0ZP|MhP?&4lPzoBzqOmc(F1Qf! zLw7A$2a1@a=Y#OY4Vnz%{a?%k4>!} zBz9Xs(YMhb0TUA#_h1-|T?@0w%ZYpvbUr?J@qnBts>l7}I{SH&-9I=xdRhjwA^NO_ z93_yx!H~A@<#S^xP8hfESr5TOCFg<}s0qK-I8ZbXY7Mo#faTx8^nI}tXhPpb`K>`^ zakt@pMPg}etGN)B9ViMR3zbOwRwC>cA`tF1K*I{5k=N7Y>|C1Q}lxL7~N* zJV+lu4oAf;U3)58p}!1&c8lw(quO<-leZf&WBZ;c_)S}p4tRKFFLs-kxy(jq1S9-F z(Na;>iGcxZ0P)7p1iRM(4Ekv;9+=}if@-OqIL-()ISO9`;XHx}c@;?;o}4V06oN*t zc`=MR$k7tbrb$2|xUdZafSBgoPh9IXu8hx1kR`tC!mXg(Q3K4A**&Lns@?-+|CK4 zW9Q^edJ5zCg5rXI;6BdO4H)S_1<&t+rQn6lRa~c5bi@RHi6z5(%7Oh)>;+5@2a2Ma z@27B_gN@(@b&r!t$Ln(}fM9ttq*-B(Y;xpY9~w<{h9iT|E4!!?WrfgfDSEG^=zW%= z_gjj-*xHT8+opT3L4)B!h-CJtXpRHsBaVvZZr;H(bYn-C}BQ9}WP_eiy>>`ayl@iC=}$hfcfA;rRXuFF(W$h{wjpp?gW*eX)z9 z0c7brEwR#-7oTBP`$KBcd(7?xqtDI4;d3&OLy#CEQDL>lo1-JOb}U6oH_t9wW!loM z&uh7Gl65&`m$L5Xq7oL8!V#Xt!XlRs=P1se)L(EQ8yDY$J`hA7zX5UhMLq!C_C8utk9Y5Z!l6r-ts(1I!&N4g$ma^D7a&Pd7Vj zsH}L}nm6#WoT@GOI~lN3p*t~aXiycM*;xaxJHgjkWXEQB&?*nkZR+pg&>D+?sDE|s z$piYHcDWUW*Pg)m+V9R9XuZb(2L%~zb2_FA;7bfKaMCn_daRjoz`u!ZBf0V9C4$=X z1h^|lIHAe!JaJOxJzb# zNh3_7>tWkkLhVUa@QMqFHs#@EG>5rU#DF5u^Y4p*C)M`hjgKo3xpeb!*jLy<@6>67Q0paq8Hs&m z+t5|QSm&S>!Vg)t$qGPrmr-L@0-#^1A)yy0K;=+pMtA6uz$PknR=28odB z94Qr-%?p@OvtYe^-^gyTIj0+l$3zV2qw|nY+}1s% zA6p0JI!H<_2MHT|usGsQ#X+6nlQZJ1UAz&myCMr#ir|>(N&hB1!tnPl8JjYzpg34AXCjVX>{| ztN{o78xsI20veqSiHfM}?5+e~39gx9GRp`@CnLF0U2Z2=3^*28ejJfHYGOp#LYV0d z*8T07kAfDPt7R)pXM9{({rm~i0%IMwgwxT-UI z9G?SA&&`|sZ3f~ec6h6kPsh%yc)DU&$Jh@4^p3AFe)8A(H}*=!(~COlA@>V9Iv7#$ zbO*eT9k(((sjFLRVwVR0=UQr-Fh0b9t~Lpc>)pf{+=1+9OmyN)ou8NK99Iu~=3IAT zn|qeI4Kv`~T8g{V?pr{<=}fOjF4RKsvCoBL$5CepwkaW3%wsNhCpz8uYErzPqkGzU z$s*I4VqqvJQ~!^ff1NHiQz0#{Ss$u?FUjE7@0CN|Cl7fK4t`(zB3cZS^5JINs|a<= zrJMyOzQywRKn7BiAo!tAhIK*+=#oRTM_pwFUiAe%?K%Ryz*_Ohuk|dn?7bpKxw}in zAMB>S(z+NxKM|nJB`LONpYuYHYW7F#VBEl0!U#-E;cb9n`6wgBj-U;32|qmSUfVtk zk!#y)1zxhL&CWc>gO@BQ@P;Qn9^HYeU^C^WLzHg+CZZVpZD(?T^~Z+@M^m=hs=4*K z^T_qd)c5`)r#sEIHl#oThvNgmDE-qpJk+P^7h&Cyx57J9_$G08#6B(mE{wbjHEsJyTk^bmT)KnTpco z3UYCt8&W^EaW-kBk7SV+WRd!TG{Zau5__t($q|C*Cq7EFCvS$S?uPDK0>ff{MQ6o8 z;tdzJbyRG}-E8d#e-1u*)?5j@3aap{>()EG1Ho@RdmCE5)|tk)UVi6Ua{&@fUkMgS zxR%|AVHhd-ObH;RStn(V`Sjh5bbN(0Q9zvAJKQB^SKn=rgoS+u2A_p}38WYFq(jcC zXFO~E%x>r`vDR*SmqMTFWL*FkTKm2$F+_PkUM-ZpQwTbj1SYV;@pRRnew+k_RDd5WkI{Ah-GRgm`W8yDnV%8%jRqKpBk%?JFn4T36W+JYY zh`vo#J@I=ok@K1FK!L_ zr}Xq5i^r&*UatT?v%7b=4yfKka90%6I(zrwISJ1<=)S-wrGK`i_pb;7#|mffpAb3) ziBI7<3eW8Xn(G9fN3D?R{S`v{clQ325eIsI$VX4_U3}E?4g--qJYgPC276by@*L}{ zzT)s+jNjGxeF47(khL%4`5>P6;WrMytMU5{;%1~B-s2GNN4OQ?&m+7V;oA`oAiN9V zUn9H%;qN1SCZ2ond>(OY5#EmQI|$D}I1j(!cyGhA3ct$`j^MW*;Y;xQHhvBGJpuR~ z_}zo>FYpTh=1DvqdHDs-VTHrX@Xy6R_%~wYD0#X^mz9k{$m1<58;j?-W6H{WcovPv zAN)JkUsiS;p2trpD=WtHgcHlkPQo*QAOB6n@8na;%7XG%R(7iOJk5HZj%UdkWo2iU zl})mu{`I4j^AGfSw-|kXOcG+8g*(j0nqkhvH#@vJad24tw0&Fp|%-wcTS^ScYS$X)F#f*(R zOL;?e8+82U#}QP=59eUXOSrt)KJdp%XS5 z7ew@N*=TYU#(&j)P{uWDi;m2~IGF*76pAG+@JqRHY5uIs}%(@w8{V zf3eX#5L+>=@(;h*7`w@Q+}zRrcbGo-cq#tiM1i+!w|CURQ9HWcbalPr8uf1b0JFr- zX&;arJoHr>b!Cft>>a6lSdAW19H(GCwI!6fdXo zaS5y#H$>JMb6c?uP>qN=D+c=9j~0=PVUJ?hC2mfs`oqnjsFm_(hFdZH!H4d3t+1P^ zc51vFBUnzuN7NG{I__<2WN%hjjTk~^;_n5MdSJpEtAWx1qOGq2*H(g@arz^p#$4Hs zCHLLpJ2WwG*$H4){PdpMa`LWkBC?HZo>t(v5p2^@W5_`|I~;ul#&zZTCZo_dc~cQh ztR1&!?lhX6hq${C=Rm6QQ%?7KR?~LAOJHaq>kw_f`z4OnR{+qm05-@cV2&gV!Mu{25`bF2H zYvkI;-~Xrd58B6K-%5{;J_0CxL_4HXTFAGprn%z)pv^bIwYhh2wh+Davp1?uzOKYQK|fAx?nl-FInAOai zcD7mn-CgYmt7mu|hQO>kV^iYK6E5bhz2mG~d(Ezb7akOdB4Ym5{)0vl(V4fiekhEr5z~>2t6uV~dkfZ4>h)XB>{Sfxicd5a1z@|_9wl$L*|oTC5%&~baY`5L z886mh`8^PZY#UtPzeyiUDU_erTpToKl{RvBxqL7Cyd2+k#fjcn)xL|N_WkPG zy&wtxpxti`3}}_#TaS(nK62B_I(LD$cRJol3b^1vc^Fq_m2jzvwmU>bJ`;kE*Y4DU zo4(%F)#n}c4Br1Loe1iDC%}p+zkhWx!Bj|Mzj@s|>Lt9qMmS?U6~6+cx2w<9^_nYP z?;iD%ar_`W@RckLjw70#2-XCT5!628xS>!r!DDTxrNQx|b{d~{Vh&Q;#~nH46rc2R zR~la#=WU+F#z_42;y!7#y;0{hXO-8*M%Bf=ILkb;s%wRdPh*UckLR-BWbD9PjUMBe z#{K&%g3%awWI2yGtBcY?M?J)d_IEdOz@JLo51~t%=M(p~ z*k3H%0pf-Y@%1e3;h}J}cnIxktdOm*^41&@5r%%CX28x59(Tg-^FlN1f;x6b=)E;- zaRifc-Qums0(}5+L3J5x7^Zzzi31bZ&VB(RuumQyu$+!zbr9SCI19^ScTsqEg4g&a zR{T`9JjDIgp@c?XCpLH{=>`O8zP1a?;uAY+X)GSUNtG6OH$RI!;ZS2leFYd%C?TUe z7^&u9s!U_CGyZ2a3=PVDwi1gDU zGxu^YzW<0-gs=+f+OUKfst&Trc76DDu?>qu4N?E-Ar+XWE1-*`ReTlhuLghhb?CUD zxtsPZ3Zf-cLW>Cv$c8KC=@BR?G_9+}UypS`FD<@i1bq04BOc?OJQh_9iX3S8pbEn~ zQAbsXV_6yHhbjYE)>&!2htz8EiCO+GbghFTAftVk@4;bru%%VI(Rl6b;`*61s zcqvzM{!|}Wh6J1gmqdWugT53yO`Wty29H1}x)iLDQMO){^odM}Cxilt65P1Say38o z7g9A~8K)D@szb8nGeE9H%kAt9s#l8AXJwcj#JI6(yfi~Wsk*oC2*v&!01@@RfazW) zh405cocM5&-dI6x-&-BS@lDdkCVcYsFR`VZEHv>$EdIs@b!(>eV`t`mrg*Ldf9rYK3m@#FxObEn~4skKgwL0%67mRfEH}pX>8T27+t_!;H;O-~BV*d6>Fo;0Kz6cJAfOedj zM_E#sn)_eUqbR}lS$N_TCPLQG-y4-ugmI%S?N2fa2%E{=Q3rbgfmJg}GNzT&($4Bg z*Y4rimc7AQj26TxL+4$nR=UP1huun9Ma~)rM7RHv5Jd-#mHW3m2PCSd*hYrO;#RS@hW8J$WkI#fJkLSst@zR zusUC=?3XUoZLE?NQFDeHILDYSd<)tM|K2`$uCOZT7F}bM%L6>tTgTC9u+l~2Rc{-o z;yCht@Af_X3MSxv>2yjYZZdhsI9H@dDc)+&HPP)JI* zqMK1W0FDJ8YzM$u>es!Rac3xw;=DISnAW6z{WrFcj9A>GELbu=fX2P|;TD!t1jK0+ zVqhu_tLN~luKYXktn1IFzx0}j06I-fogw*J$5TCprrg2Zr4=4Fyd`L5Pnsz7m0R8JL6so{qkg5x9nd;}E!o z0Rne2fH}Sp2d&2TN1e|w3tIvqb^WV0XKSK$S)RTk(eB^N4;6t zUt6$WCM+&-0DgKDRDlD1S&c+0PW3}Q_@l}mXPQ*Im8q7Q#wWkM1g!9+CgUy2oa#Gh zqKaMAP~F;-fUA)!(L1T9e)!rD39J-kzTSg$#LjJnXSY7opk~10H^-pHHJ~WU*--}G{hCM4#Nu@iN= z_D0;r#*urKm;4Bxhwt45rfKg4mhSL=kG$WDzxN}(XZ24I>XZs7fR<(PMJw38)vXG(-N(}|*OuULR=mpRSp0rPr)+Fb}c z&EI#7`O75AvR}DB!*5<3p!%bVt$NFoxCl=(!8y2joeKlofxKpOl{X$Vi=voU$aMT+ zPN_K^XH0Bly5{VH;QIyreZNXP%zXLr<*@yWmLsuhi)Y=pQ6TKsuybRKF*`i#SY0zg zB$y_ok1#bS;HpW7Pt6Mpc9>m;V3sMmOwI|+!7J_jR0ub>zz4`t3o#|>d1n{EK1jUs ze!)MhtGY0f!znO=PJyme=PlEE521?)3;}xIX7>RI^eVZ3ahCgrFm2M4h&4&OuoeTW z6%W(EkS3&rSZSC@^hg}Q1s?u%Y!I&7jXL8yaQI*ZN{YHYgS|b!K{5%}8y9Gyp&Gsj zPUd#~1sNCOoPA!{Jf=aF3!ooTa9UIim4fS$2Gf7TaV74u9Qbr?}}@&G+muIfUhG1z&y}8I;v1HH3MB90^ayA4@{bW zeCDtCj)BzAiLn%|Vu4N2U|96UCvKmr=%f$jKKa;MRo~tp8z(MUVFCUVngaOD3(-F& zePCQ@{&Df5g08`<>Fd`wnR|GJ8)|&B*SPt8^9onRzA3-tewWySeF@r$&RBy9{R+Li zjn>vkX%I{&ap&Cj0r^tg&0b8=z@@%nvicTQe*{c85;7#4G9aZI1A6+ln(_h6rNY8{ z04qiYQ~$ zbzg?VjUm8*eWP%6sxW@+l;ytoxaa{k`W)c30n&30paWN7Br@l?%_dCRUAX7L7_07h z5*#=NCCN54(w~*raL+J`5fUAnH*k!hQ49@v^)4YyYe)!O`yn5|T6Yij-mG6A-GQ8{ zmi7%g3&`xLc2TPu)k};ztO1C=LrNH<`g$}e!?0=@4u-&>0qjUgsb^IhX9#f6b z)V@NqZk`dEm)dT2#b3*Cob%n#2!NDcv6HJGu05@Sy?JG!h&Pz;o;8q53-@wjL z5NLSy`U>sazsr<)!NS?KlchdRMk}PVMXg)!-gd3*wKQOmElrv&oEYowOG`x({&Y@K0cGKE88=STwgD- ztOF~l*%HV=Qi6$zkku0V(U7{@8jEfQ(u3wBbD_sk07XNZj8bzq#buM`qm~v*)ZGF8 zVM!X3ZZKj(54M{rTfJO<=~yyAXVsNrRw~g&-MVp&A~M7%V!R!v;Wa5be$zNXLpq2s zx0p?(nWV#7tQ<)n()_(}PdTKzx}n%OQcuC15nUF~vU8J$R!q}INVdD(+FHg~IZ@=J zbwzYu-D8+00(w}QFAu&Jh{JFz>1AdEt;qXqy^K1CMf!{@Ve+IwUFCE?= z;XR1(2>c$#`!Df)0dZ3hejdMD@IDXEH}Q-h{&j>?4>-Kn;5QDx2k_gExV!Ls72&ba zIX?pIcM&ebZw`KIk@kB$Peqy|FNlA750xtz95FH&9L|^z|2J&Zho>De#m(4Zqk}HT z7z8{h#Ty(O430YnZ=-|0qN4G~7Wt1menPM~7(C$w0uTOo;z_|_fr)n934x-bqLWXt zK}SR7w@;%|??gkyF9^eRT#7YsY$D!)h@Qd#|JL&M57;BJ816Eb(_*0b!D8sCreEqB zIuh(*WFyff)Ge`N5^6dwvA}Q=QrJ;KtBG?KT+TlNZdsoykBnYO9@r z5~*sf472(2Bc0(~#Pv9sY>p;PSe~hKt93}kPCsyFTy7z8M9WM#;)MP4IRWw+H(`sQ z%?NAMJ-mKT>^)Nb9$;*?enmo)UB7Q4F;l;H8(DRg$YhZEy(+QDAoXjuGD!Wl>kJKu zJG_2BL87kTxw(aW1JT*~tr4Ij)=%t(x=7-{>7F%kvn z277)eSf2VNQZNTF`|Seq)m=lQMyT}AsL!b{AxiLn4*0Ld3#eT&6#sJ7n3FT=fEcQ= zs6M1zN{kjVhKurWNz|a#ypZ6Q?LXvKhBLA&X_xL zW1Ngxog0(Km{@L1K4Y%Rjd^J`VnR7F!hs9awI>YWVukt)q9nBf{F#Fn@Fy(FA*Y$n zRTVbaxd1y&gPolN7Cq!ZkuO19Z4LpcKYA-;_hVf)r|taF1Y=(w9D96=M?HxsWIG5<5=)7vezQuk9GW`i@|!M&w32@_4mcgWZN0OcrdRJif)NmLVlm z!eYEg3C(s^pSnzEooB}!r=}nVT?!>!WJgX=Txv#4+0YU^Y9vym1o#Hj2Qa>*1gD*K ztm;J^vi=kOGqJTYOWZj1N2D;Td7#DDw^ES!)k9Wf%W=T>Up7AK7Xdh4eM{r}PdjFU zT7wu(aasy-Wef4E77HH=Ij-**3rABna)PSEix7Rer}aL@k`=&1Ae#TcQ1YqA)h~~YoYTl87<0rGlW{c$6vHhOV(!GDiLv2{ zLy=g0Ur|fGiX9_dfwF2p#LkFszb+hydKY7R1UtxRj;rklJHZ&wntjkTm>aeKq+8}j zOYjJ*aac?OB-Pzmb!rYecC`4g&4=(bWtxM}d)DLT@s}~Vz%&sV!YYpGfzBLO4|?tJ zMo#ZATRuC=-Bh?P6rXBVKSnl;RO%N{Tw!%5R<@+=pXn!|nYQ;rrJtw9Tm{jE7&Zf? zK>e3M=^kd^*GQ5zUt(oea+`@8B>{MbI-+pK}qCKhQz_NJ~g1yZQox{*VhE8Fq0U;0q1Kg9UW$dYpor;ht zv&WW+xUv$}S%9`Q4{YRwqooX&h9attQB-6D*z=^DtmSOoW@Q46+v* z;P5_pZG4(Jx&+jk^}*EBSY@m)!Q*6ehiq!~V8b3nr3>5ccF4xMG2G?41N&RI;6MyN zst`gWvKg-iC$#iwBI3tDVsQMG_0LJtHJOTOWXrKu@)sUGrAkg$J9_KtXoo5{|7&qttzgBzO6nA5u61*k8ePErREyT4zA;X{E}qWH z<8LZTn3lUr{YVO_52#m~6d1eWfUc>5saCm;PRRUEaU}mw5Fm{?m85?|u$s94`M%Ju zcxa8ksW133g8e^^!?f#PNl2(KWS6;;5QJG{PNw5RrX{NXDm6B99;cITM7Dn?Pnm92 zf}g02R9hY+z1?XXJ>awaJ<{bLZvk6W|E~chZ#jOG9{Gl{p(m3PJW`R7o@~`m+HLMx z&)VE=xal1>_mS&u?)kU}a90y{CvMIL`f%V9evbg>5yHO1KZ<@d8+Rt|Je)0MDF0-A zmzruHI@F#4AR&kUm!5w3xWmU}I)<_)B7WeYp+lXLM`{+3V`$o7>z_*Navw}0b@0&i z!GmMrLj-+j9CR=OF+cBrpC8G)8+ye`??kE?vz`7677Jfq8FqRB#CWQ^iiMj;EIEtr zqJI)W5sfAIcD4X8qIW$wC{6R2z_Gu@y^Nz-t-Ok5YHxj)jb)83ywGWmog##sS{uEV zNG>3Aa0@E=oX_5xP9+G>ki)as#tJW*$C0D3&%>IsCzn2`rvQ`o=9!#Q15LHoz7ZEH zc3-F`!?kP(m4eks^JZ2f9Ml=Gpjxkh)`!7+Me7eR@L?~~C2WwX(Z;XJjF z?YTKHVnREi@|ejLfgz!u#R2Dp)e?{%xo#(4D&H?O+p&&l9;+&%N>8A(O|&KC>Q38$ zroXL^xQY}#O+2!>FVYk<6b&Ax&A;XxgfQ(5Z7ub2mRM=9j4V;irEP;ocG@;sqnhPP zn8s$l1y&SGN}p2QTAPwzZRYpUj%<2~$-pL?`*vIemw|Xj;^yLh4~#uyItp2TW8Gq; zIYM)wPDsH7Yhsa^xu`Ek^J|Vx$Y;nmAyz3lM~ufgu-CtSh4y&FL|Rw6>;xe#n|VI@ z6@J3-;wj$L;0YXQ{vLu*>9To=mhJJd-x(ck{#5c&dI3omzRGDXRfvu*TR|V9ykSLg zUna=A&=91-sjX|W))UN(lTe|SW@EgBGK22QRH0LxOG#pmB(%Xp_G7~NU8Q-g+eN^lnjGP)ll_Cw5&vwaIF4s{* ztf=`qib`rTuhdary{l6xpN~j0+-S|T7%u8gHdHieGP!njs9McbVq^da?!{E;(MrIH* z=w%uP`_FDdmNsP%gN568>3a0c;jMHTd1X|ug_F?6X)=+%f_T#Yl%}S0Rms)Bb}odW zu#c$F#=OLdiKZkI6O0t8`S=NtQR$7>WX|;(d{^t?u?OpjioMenoiUou=2O)KWoF2n z6*#}?fDpWSjP-qe)c=44gvpK45vY&wg*G6N>gWS1GiwCCQyE~C5m-~G@%NFqLP+eY z;ZBBpg-6d)8wLlRO6S2Fln#!s`9<4-%$`=W9Vc1VsP=8;sfBhrxo{}Uq#4Rmqf6!# zeO^n{)>RY0$LebSiiu@#< zY&UTt2hpMRr<;+$im|z4w`0&|IP&T>L_}_53O~6jy*1ypszZfThly5oIH5n)$0VU% zs`zxPh(4xyvsRS1Dy5#P1?n?vSTL&EzDP&tqBnL0hp4ZG2GjNL zOAm7vXGOYf-vdYMeq|8TBUc~(ZxZk`4v)Xb@z_I~%h(lI&KY4`3N@00-^LcXs}yk) zk}h?0IrF9E)AG_dV9t#+LNf{V&|o_vQUiz@Zn~8O`WrB+($)}iI68U2UVqKCq>@u* zd97m#C}=aawQ=wP2CZDIBJ5o8g99s$TroxN_Rma_O0c1|?pyiokeOXh1FzheZz+|W zm@;x>GiNZ501T9)SM2f2JV-8C<%T}Bhd#51KCxE{;oxsW2U4%8B+s1IF=r5;SGW@( zdqtq&z>3;}UKV<-;?*+ z;MEOG_2eHZEu6b^g3R{QiClzLaEIfP=`c^T1;msh}PDSfhIju=cF2W@!yruRVTqd+Sw2*$9ZwK)c;@q zr6he=|1V8A{0(lU|7OM^v=9jN0D8GSU$A18`os)zUNk!)W@kc- z)gp-Co>P~<14ue^{S0QpN)0`o)3U>C++T1f{=0h72;kKMJ5`zEr8 zF?Ui0m}6HlLVitfik)z%2d=in~JiT{r{sqk#^NgYi! zYealIgj$dJ4Imf|*rClXzjm?AQCBSY8rmu>EqxJPi}x52;2v!6WD%`Bx~?Jp0f zEVyD7ZjY!GyUien1r3u`Lk?L%V_dAlb-@i4ZsDs+JaQwNi__E@QH058-0iC~%{SsA z5aZK~6_f~fpOClI*BDwyf3yH-jXYsi4>eVv>ZyXe)cGz|mxrp4&V~N+!zY{$eJDu6 zNqAMl3l+K~oY^m7gUec#{8Ocm zlgYndc3sTWez~PIq(xUDS8FeKn6N3=JQO*5Lz-C=V`ar_^2K_w>+kU(gY2D32L9&- z7-RwW3vl2i9n&bl=N8}<;C&0o6X35F&~pU9HVb%OfM+xypHgjl)w)u)qx@?m@;(dm zUIA{mfMx-1v48~vTxS8b0xYnA5&`B~K%M~A7T^@1+yZ2K!`vlnym+}}M7~co_3ssZ z_^}q+ZUKfQ0(J}7A~E}RXfZq{z{eJFhX8-GfJOm!Xdu$@jLmkzF7`oR$IcYLr}0~i zYsdWw_WdaV;u>*b++ZqUK5i^-5^gVHDg1_TtD!5u-&wyi@z2Ix zfs^om<`#h?ZMcOkJR4})ZcI9FL$4FcmN>J zb?bf9d{=WTe?#A7x|ZFB2dldQ()Q;4GUt7o5zlb~)tJZMF9QmVjhiroYy3|iiO7EW zqDa=kQFPRyL-%clG!K(ugoR}kXrDHu)^SbP{0co8stsA0G;I`yJ9($i)v||`ziLgD z6V{W`wQMT^tj3nlBH!M;))LA7X_Yg-(!k1c7{38+-{YexEiJ@^4yRtNiA02{3Y|Hx6#4YQ6qJcw+)l1(&aW7ZJ{q6($ zOS5%xD|!F%g_y7cnZ)km`o}jkG@of#S$Pb3sUlXy{#S;>)(t9&J#s=CBI$JoM{@&L z>QlA(Jw5{C#-l`8*ubsEmtdP|Rssd9;HX`!tfz@Zidx((+-&pOU&jjqopwQRaJ|1> z@*AXCR4Y$L0NyU_?Lu=v^^!`TZG09Sf+ex6XJA1r9AppSm%4icw?f1c(?C99v;SAd(r0U9>FOo9es2!( zW?SN$L;ns3|B|Wn+5JqV$DWFiTnEG+s+ed!>ilNQ)|-xNZOj{|&7^}9&Wt@3F*(%b zD1N>1gZSIw;}T7za|)VEF$mA5UIvgNOMD|jCdagqyp~>dc_xs)_C6}2Rn5KC{*_WK z1IqHZQ%@DGJ`e-wIicQ69v14&;Py~&I+L1(f;>f=3Ag%Tu0x0|?|gad^AQyAbS!+| zU`!|r?lB720i9r}o&{wDkMQ{`C9Zd?YOcyE!33F+N=%W&d|<^$Agw?h^^aZ;AHj1p zks(31&z~!(PifTXY)ye+MPaoSTrSBoAQLU-3xa1QC%?hM8-cP(Xe!1ow*noKSa_g` zxk;H{hsy0_8Y?X?hp-}Rrj5Gm`<$r-;=+~g=l-cAzm@6XcUwdP_WqL06?<0&axrJH z5+_G^M4Y=N!SgD?LE_vfagXV^{^ER4V(zkH{;@b$3hECvYJxZwg<324ABa;WA7kOg z#HkoN(hBSoCt^i}vR^y~y9w215a|(6KtM@oqnNV>!>6L28ZLt6?$G1B(-~jQSXIvt{rv1(zzG|J=W{ex!jgAexcUKeQi89QcPgX^HDO_V4ZWu4S#X8!W&e zr0Q3)m0pP+PNCf#M+?T#8WYeW%h{7aw{<5RorSB#iT^6xA^307{4e=X^Y2CNl?iv} z^l>LwcnOs=PkDWz7Bf%8nRzhA%#T#J(w}D|j)u_?y_nmQfEIa$jaGP`3Kw6&r;}gt zpMVpdk*vd#x5aP%M}7P{;B3W5aXDN3%E6&PU+CfaUB5+={!@Ol6Zy^4{O*Up2XIg0 z#J>|4;}?CFx_BzpL|-X&E&CPIFDi>I%4rX`kNt7fhI;jGnzJ^_^zSc9xA-GFMv3z3 zkb1T+Jl7Gvc^)?X%?D(HDC^)XIA(n-CGtd!0-eD$)1zo0Ev9KI8H;)uF~d{r=7S^> zilj4VLy3J|(#TW1&(gl7pYm0ig?*G~#VAuBpYCLO=?%|v=<5_RYYQ*2n=K@?_&6no zt@v08KAoIw9LM=kiR$fUuEobd_;`iYcOM^T2_J0Uu%Y;{rYstc9jGXkjLfry>a@I~ z1Ws6QU`57mezRF|BKY^k@D(Sihu}mdf|I+*L?j}doUb`S+gNY@5n^b0PU_=fT8yS) znvZROi-hm83kyH8o0XtbHdm9_QktN&Ql&gNp1Q}pMp9F@MmIUD!WIFB=Qy-JSrr!g zCWsEX9*OxkE&oW-rN>&T)=Fdq8r-FT63|sNh2EHol?mj+LBA?wHo4`lp zJyq07ojV<3_2}RFXhzYA#u~y*p_o8T3HU0z`H`gZnQneWz-n!&Zk}fQOygVFQ(b2h zKGjG}+Je=rDG1S6f%pA5-i0x|QbkWSfAAvbKY|{6=f~K>riYmtp-tm|2q*12_V3{S zXe~{eP^a{tQlGw7d%mjQPw0={?+ZPAe{^~unx=*6jZUNURQ0l#QOTThzo5TH}?`0eVqJu zH#pU06v*VlhSJ~5{HPpGC^9gzIiE6iDbv}vlvnPlL|^jx^WfWj6n>cf`22Q(+G5cA zM+4m+gEk7(5`*p+XmJc`7U+r?G+&^LV^Enu(>3JJ5uj87oc25lpil!MPZ*c&<2J=J z*Z=&l2*OYc`!NC1Env9-J(ct=ie*Zi`p3CD*{z$D022gGVkl5 zE@e?i=Io)S(Xx{rMZ-<?uCJb$o(?NAaJ}0{uvXV0EI1fuRV>nq% zdP*yaE9u-U7A>yUtIdiSN0g8@4G!hd2KEV3&8vjC9E~iXWTk(B_|cjD8_ZQTS1^74MUc~Xff-Nom z;D7dn3dARhrBtVn#|RR~5VhGOvs~KO-Y>CzAbPy$8$SQj(luwO-08{g7N}>f@B$PN z=;IiqI`Ow+km}&K$DsG6|80*!8wGkI2Hh{v{V}Lnpu1wwe1Vq7pfZ83*O2bguT+55 zrO(rV&+iq!sx3U#nU`C5sxu#F0je_}Z2_t?KUM<>NCpM^7g!!O$=GOW!&Kx$aC zdiYPDv?QT=_}wu`_3%42q>FEp0_dDo5C3EgQT6b@k3p)3|3wT^J$$Q%bPvB&0kIzb zni!($;pb~8Qg^@2Htq}VoKuG9@q00DI_?VGVq6REc3d0oQQYgeFL8sxPr>Emj=_z^ z)#EP1U5k4Loab;K;+lYeg1Z;@5N<7QGwx-aJB^7B#`>EBtti)2Q5uXp3zau3L!O0aTOyKIsG>>57_qKl-*vN`&pd$Z^l(ITVaZ3 zu3-%%eFa>J)t=UgDHB@g5nRg*{&HAs)m{pT!(yhC70tz~?rc<^U>V;hKw3>9=P=lLuy!x)k!kxW*fn;S9iB-%u)j3{R)C0S;l45 zxtClF&0VUMa!df4k@;w84S0C@+P_iq?fLo;@)i9?qI^&KuYV%nyZXs@d7^xO zNZPo3uObGS*Av!HzMI$dWe};R3aq*fzUJe;!2Ms6FSUmAf=u6;yvq)wOx|<86H&H0 z`Jr#*<)tpVT6HoYgu%uZxr|!x&(C2_bJL^NcZ&H+jr*5=xU#EOZyw2Xr7!)rw1|4Y zQ_`QCoc>um!A94=^{gMeJA3KJ1=_`(Sj^NObSjThW#7ad^DT7(VPio#t=~TjOpQ%W_-)!Fw@~Foqd7$O zeD2NL0&JM;=96_{JNusnUp`#eYjlq8Vi!8k)%<)qQ$#kthsyEZEdNFkd)FgUZ1#|{ zeRDIG7FS8=<2p3KB2JcnzC_%uBb3gW+g{4zpP9y&g~!qV6d9dDi!3gcEQb0^CCz-D zCc+s2n;vn#kadoX-}x$keQQl$l+*X1RAg!Ew1F9Nsc$s|!mRI{q!`Cdtb7PX>-A*d zcYUN9L9<9HgKGLpmqn^}$N;&mH%sB5SLb$v+#S@}K|1XvAr8v3vLfZm;oIgIaE+Bp zs9iP$j1CwM))b+X<`_aYgqJuf%nZSL*+M8=GmhBSX?O4=PiqvxZLwrFfKn%syCOW% zft6+{s8G)kSId#C93d3Q8)H862M94aY@J3HXiqJYJlt@Hz}XNs1_;?DPEt%HYl9Rp zG|s49!!11Fkcdej*g+%b5<)7>%QRMrF>TGbIM&2ItkDYVJdK57Z4DRr)Yk^`isIDZ zFqdnArOq)5dkEO@Sw@g;86ogj5KgHu_dncspRP~5@K~Al61;hx73OOSh0o?bsR}^o#xt`L^9^FxD45g~Md1^yOer-c?Adit@@R9`XsmK!bRrF-O^`VD! zm4Gw_EW(ia?zB4!r~{yRDyR?>9UwLdBDv|314-9`;unP}gjYyXp75<*Ss*1E;97~N z!kk7Tp-jan(8b6{O|(~-g+y4lA`==CsN>SMfl^6kbC*>y<>LChqTD&mtNTeoJMqf#-FmF&1R$}>O5lMXtu?FF@dAs*2Q-L;q$_?XlfPaNWzgWcYfB)w?1Qu(-=Y!( zMhbffaBD_!*G)q?$WZ{+h4xSf_k}KU2fr{V4ZXRt#BILtprSgC(<7?i?#2qfwkF0U zZ{8~PdCV0k#;85{%qwoD#mSsdoj-2cC_R5CM;)H$m!nf+Twfi3<@uG^@z=lMWeQni zZd6Gv1*4TzhLI|c4l<^5=ETAN+^07|NseYvJJ#hQ7<#PHTV8&*rIu|%CU68KoRTD;BxI5!Yc^DJu4SmPW z6)&FNyhqwIQrw{f&ft;om|a)T^^UzOJa_u4f{PT%BjuW z^7zH}m*C87+l~G!XdLZ+U+bN>&@G_Gh>~$rEkuY^Nmiy9j$SViX0(O z@82Ur8*T+I%H{yDoOuml;rP3yeDI>7e);k55VX%$s}E4qKy{^&vXdE?teSF+P4|S} z%}m?DY0HkU(~ND#>)Mp|a~!ez@*!i>CwH3& zev`83xTW8uVp{1z;e4!$)o+1vzEtGbsXvf8t7`H`Xbk32mlMep?J|D!@#j&}25WQ& zAV-=Srb^dakb^fv>;rwND z-ZW^a^Oqb2_2i~X>A!#e5^K-j zR{47W@%hU!|KR*(?CfP;Rqqa}SFS!ormBS6e{=A>hohO|l$(G{zvZ0y=Xm;^Gk=)? zS;;OLlp-rx-q#ZI90Q?d*W&|S-%rtv(As4H8AzmE*B`Vo<5|?Jh%zF$YNx6f`>`*@ z!jmca-_i+UXRj|~AWJY9cAe-8yM1O8ofz~^B(vOjW=^M#cytjgR&u?hnQmJOSRHZ8A$82TC)Y#?YiguaVL5IX- z;Ub1QX6Nrg#am<9NvY6bFIr);gfY(~EVMB%I*d1q?_Mw6ZS*$t5@^WixC;tx!pDoH z-tag>&B$wHE&J^OGOV!IU=I-={aWN{*fP`Oe2h28Yd&@o50#6d66fPt9X7=ZQ+zx` znD8;s+%5f=m3ba0R^|z7<{DPaFtL~XWtT4rzONZS}m|?wkZzN{4Yf8!n= z%uCR?r*O8E6l+rfkNjifH8u61y;nOTo=P?d2fIPvgFz|qDluxLEr}3+ay)+C!SQMi z!vT5hA5wp%O;P>L&Ej7mGj>PlJDGXp1dE~c_h0m#D?_z`p--Fn9AV_1*JnjpZHVX6 z!RCG|qIO5K^`X2rFySurLRQ!>#{)GUWjCPC9IN|4T6|7*jrq|x(3~QT;&0-cX_p7G zs?8k&RM^Aic4jD5<{7jLquzl%DDj+SoX3{F+-l;OzLTBwp}&^w9MM$c03ic8fMnAl zbB#^1b*5){+>bQxrWQ9a4>x;%E_IfpZC~NhCX|-SH+}@D3zCUrc#4}PrC9KqW9a~6 zb4B@;`<71g&nmqsuRN&=^MJtJbWkXq`t1Cy>PNOhkzH)(7^Dmu7K6&3i_aWO%h5IH zxvy2bs#R%aipxt}h8j}o~{7@9)AEN7mnI1dP!o~}#^ z3j3-22~Tm7q@MT99Oi!3xF}z&122if#NQS`!M9G%mKdIv0{j?f9924s06n+uE}eSa z2Yx>-d$nMiPv5O78RMsdyX-0vj}Wj!vb-E(DDBe`?FT3LSlK(Q;~G6HgxfE%!K zi2Mb$)kZjeH%>dZ(GHzS@_dzu)vw0r#HOi}5+|vz$VLU#?=85FWxbHB)!cL+ z%~3i6x|vS@^D-*7+$kY;|Gfe%(SW?O+<7t|GaYv%t{68LcQr1A>%iGE`InNKnVBY@ z|J*-&Khi+y8HCs~$@!oB>z^_SSuUcBeZ?VcmrbE}lKJ4cqf{~G^J5GXtBI|Xdae7e zc@~OaqfFx`R??H1;aDYYGl#SPfHo}oqGYvwV=2jy!?;yzhl|IgV{%0y%!M-|Fz@4=G9@FuRB2aI>sF1Z40ln$< z9jiLOs3$(ipxz(G$Nko2M+EKwzRijev=xzFjr?XSs5!`U9jm?(QZ)-3u)#yFq z$Q1XL#Ha9^i#ru}eGFgj9i?y?>K|S^ieFCpAA9WmQUayOeJK0Ca1E<}%6?=Z5F6H2 zd(&gv@kmZr<8HI%HW8Iun>>`Jps$ZmYCH=QODn(HaCqy)o(Yc<=aLuZ)N!Ge$4H~S zGr*5z!67R1YNhDIn*uOD4w&mcm%L=eG!N`m*{WH9EJ4M-n`#+%D%GJ|o^sFu%~k;8 z5bsU#*wmdJ6UB1G7#fB@7DvX4iWpmx7BjPtiViq80ka`R;Yv+P1Gh#+dFU{#fJs(B zmA^KZ%Jkl?!m2}FCb|9S6!&IaH|{Jx*onIocjz(rkOS-gE-;1U{njF}s(g5|Y3cT~ zzPW(lr>9AIs)1AvEClO=&ZlIF{uk*2qQkxZwes0}enMN6T{f;8@cB$o-KgY@1M+Ym zul5yhyT)~XwZB*;QO?0`=<4I-cRBE1GZ>3d9 zL;Ky=xEfsk-9r1aL(y*VK)g6cTvyW=eV*9U)vzHCqzbja;qK%aYRU6R`6woNaNDnP z$K+x0H%oA%t@^7hYWYy>c|d)SN}8OXu1v347+!y)(D)rR{z-l@e(3?p;jVc4`z8Gk z4xb*fqQA5AO6Y0m?t&*<3}pr~Cp1xzK{@>1Px*B;q4MGW=Y_OWeIANpOAtcOI*l*M zIW3G4Vl^XH?HJy+F)x!TF*YLAeHq46Lf7<#9{#>e?;W ztNcCc`&9x*^mJpan9MiSb6z^RdSffCJ8ehWmavM{Z++>vsf=Ml%Wp$S+8W<`j7;i) zJd1X@>wBWVmqn7dOu)kTDgz@!rh{AY=G?$hRsIr@!&pO*c#AVS+~34xAe!!BPTQuKQ`EOG{LipB-8c7O!5|iO(MU_BREuS`a35Q1 z$tU^0FWFY;Y^h`Z`2wE>Y+2}Jn_a!xr)927t1DfmeN5eLtyLMJ4u^gTE%8yXc(dg@ z?4kA-lqohb+fIcYb3%%{O&*40Yc9+Gportd6{=da$xCq1`L<-NA)JvKyDR%`R6a?yNls~2OPgG22@tVjQpE%(j3#wU{BBIIW!ke63cdbFO;=+=axYlElA zDFMz&UPxmI>!fQ^ewK!T$ly>V8(~`d|*%8^@J_lPj@dx%*nS2G!xV zmC!~no0A6{FWsUAl}bIxjV|ej@U2MlF^ynk$;*8*u3?GpJkgWz9xwVvW0(q;<-ZE& zRu`(jZ%`7lLH~+su_&c@%Ox@Aw}f!Lm9x?uv?(gkl{x1#O2wEX2KV(Bsqd)_^`yC$ zHR;N|_C!|C6XXd&%-Z-1MnNyrVw91q>42;*7Gd7PAu*q{$Tv#kSC;lXs*UdeXLad^)h> zos7_jE}jR5T-tVZ=-yl9clEaOtztLvtzQX4yg$n)AXUlnL7`iAs2rC{%qa<-tWhcMWw`yg*_25C`q%zG{n2RGvg;`_weOg(R08w) z>1(a+Qb5x*Qw<}`4JiC%=H)A1^Qk5C=0 z^uG|v&^g|$^XP#jIZ_ak|HlFiH^0=MJ6mO^KR06jNR`#+l+W;!SR3O$!Of-^Y$^7C z@n33MtZe01+GD8wuc4mw#aA-Y6r79(M@k~S;ViSDN4{Mx`lP!!%RDYIAd`T>i2*JG zzT20OWI6$R5(6$G;7uzaatt41^mfAgE4UAEU*R%gAR8CsQ61-U8fW{=RJK>RXKMaj zWXr8Tj>-V7JW39m498C^G=IWVWK_3UVt%c4Oop+9cP(WlWixmP+7WsubLswc-me^N zOe`^~YKu1nv%(pM*TE5zrC+B9J_4&$7Ow+2Mdnv`&mG3#@O5_fReTyLBbeExU${=p z(aMiKFJAJlooBs)ahBqBhx+>v(?6ejug|CU3z^nsvRm6G$b18NZb~3%WX&VI-k7k4 z_cRLIc^ZCL2>}$FW0E(l{H6oCw6wYM-E9)9m>6G?9jFdt{i~v+rM;_SK1jB}Nt~ym zT^bd&*eesyj1t3FD?RGOJmdVl;*OhBjgHc2Y9Y^B=NVa&so`k~`{rwZxTvY0bjfd) zu;+R-UD&K#GT4|C&dMvajXygNDOc=r>*py>nd0$LU7SU9FzG)Yz~o`RpZbK<7ngLkx@BxdNPL-X9Pd9P%3K$1mCk2kYRq(nmmm;!!jv3iRfzdN z{juxOtl8u?b;+={aq@Zg>YJZd^Z(Qc{p{y%+EGd}rfn zK1-TK>)4aaY4sIUo4I^?Yel8k#Jmu1n$M>gINkOB%Pr{&9-~wZ;aA1^p)p}MSroQ+ypw9Yq>oo^)5oi* zkH!*JpttG*wLaIrE>@xo{?!s)V0ahwmFS?ul;{FVbV0mC`(wpRbn!tYD*ateUE!OC zKhIZR95udcJTYD{#a{-7^FBTNhkvy+RwVY~FM}V?yzY&s7&&akA2*g;HFZ^SXP}5D z<&A|U#?(gRrbgp2Ni*n0V@czn&%+8Zwi^qV?0aqG=YtM}moyrs^NTx!&rd3T^`^h5 zvyoE7oZnz$+3l-`B~Fm`7JnI@%~{c_L+ADeF2i0GBx%~To^hd`p}}MKb=hpGwqQon zbMh-tiY+)opcGqln5$K0=8988PPzUym^$bUpIHg(n#d7-aW4n$1DJda`r258J=)-{ z+~#a8kM)b3aA1mQB|2YnE;?k+r_20B=N`T>FgIMcBz#FDO^ADfC0E#NH=fX!pW;Q( zlM#;qG1l4`kEAK3%HqvV57NnFQSW4i_Gd1h#WAO~r!!OBjp1~6FhjlS-pM+9->zfY z^FC#!-Z^Twu-sEh1^BiLwUkTcQQ2Wr%QF8Ed%u)%ERFT`6Y8kyZ zKwF$2*Mhsla`X884KBu^;%{JRe{bM4+T-rbP*3LKJXxX@q_{OtI&;Z)={r4Ny?)Hr zP{$CXqf@?yJ2BrvD-~RaAD+O(A z4{hdNm3YGwo#CUHM}@C&7)2`E@YU`)b1w-y6~O0|I=RCc8~!x^PM_)>i@$U=-@@#v z-q>FJrE!2aR?q7VW*RrUi@yo(E&j&UJd!Mp#csjN#!DYc^dexQ3A0OdCZ~}-Y=H-l z37z}B;BZ3@UQkLwXLy8^MOOy??&JIo*p0WN!;A_yBZME+ zud^#t<|JKd>TinrtLC6!*^nSaBAo}A^p!j2hI)p%T4b3L`-T+0;Vxh!CDfA>EH_$I zGZ-d?J3ePafP>H*>_(j@ZAZAy)1_!@Sw!cLzr+)qtAo1A9V4J&#V~Mqf=B5XW2)0A z_oQ`%%RN@?m{3n`@FYom0@ejcSuQDK#OpMcDVHhfhQ!vu{&JM(q=yl z$S}%F!sWF_i!@au&hDjObvS~T2+vLLbPI`&?$G{%#TUx6E1t8|)|ibSK8U8f!F5N6 z(Gm5GFZUeNzHe7_P_cMQqiG|{J>+CeFDZU0kf9l(Ob6;LmAQfGwR6JLOQ^4rX_u06t#OspncHAvWuzo)OxtEpix@BPIG?fJ zF=m#Mp?=Q(`J^bh1w#&_q!RHgUGr`H!XOQHrksr5KzGDEgE!}tXQ8Y4G36sw#|-k`>F$Cl2W{0v^n*qUL%8=abSxj8#swJ8#p1f-y0Ya+CMLl9ooMza75GorEncA zPpV8Y(RNihiME+(Dko=jfbO`BDP^h}o=XKwNGaUcmr9*|S*bGm>I7#KX(u@?JB`Y+ zfO~vpX>d?NIw`bDDYOc?!lmy#+M7hAVqr+naYEcV4UDiVqMG#>ja|G7nIIxb@GZ*d z@e^qwU*bu~g32A|pj0?0JD7tqIPhr>?6+xl0~7k^E@PJtIYjP|op>d>nIZ zdf>-!pN;1X6=C_rT`9Q0^Y|S^--V5(G`q`{?&4pD{NW$4`X_KEPGI>>gaH-o;8)`1 zSK?zZUIh;r*q@$+C(<7T>~y)ZB>Z3cH#nj5#;dv?s)#(G>(rB1Be2EJRBVUcNK@U) zgryYG;>)Ge-ch1D?Facu+ZQbvy)Qb>_2>a(U-S&I`R?B>TE>sBl4fW(HW%*Px6kN~ z4j;KMI&{!JI^P#x{xIs`@2An!eQ$@abSuSqga-G8wfr>2s{bX*l~7H%=_ zTHFn|CfqXIeK^~I{{K??g9B2N;It&zo&={S!5K+#W)duK94Gz@?Wwe;``mlL8h{f8 zOCy%z7TcMl592}4eIlEPS|qf8XyXp5b7*5_^7yOull5lV=QMknS*pc4R{MuSs-g_qwyug& z`H8aXxJ5km=93`D5KC^c1&-*;&T!sh&8|vr5iLyYKIa9_dNh?XE(Bgtfv_#_w5|{1^PZ?vXdTB4Rt+?P#hN@!i1Hp2B*a`3k*WC>(E?y%Atr@q{FMCV z!G?9RA~Jq1e_1KOdBBY<<@gI;Co^H@;1g>F);adCZ~9szR|1Tg3uOjS3O7vAja6#K zIgyKZ+$DB%A8?_&_$~=^wWwW(QeuK1Gr6ZYS|^qi|JB$LNNcUC1v{sUHKXd7se`U& zwSs4kx45KuyQ}3bVb*2L@*AI{?|VkjIzCN*`Gb}*e{waimqOrajyTx(8%TEqfZ;d zjY+jk{bZ8m2%ldIiY%r_8&ek2a!xcV-Q%w-38sguN}_4us#-&RaD;+a_3&aUWoMXU zDVOwB4;==FQadDm)hcW&#*WwaT z)mva(xG;Q?CtS4}MJ-BoHgrpg_SDEUwoSyeg} z;fmt!#)qS1C$ci^PZ*W+i=PXyD`I$_3QwBPHo@i0ZWLByD&z#>F~(HE zPv^yRS~Tk6KCo6LnpC`_@%iGYt9cg_#aJ)d*W>7~kkW{6@5s5E`2GI=`#UG9{T;1U z3LM2|PL=tlte_UvDmQ4|ggqN7nb_`-I{|&l2|6lKKRElTBiaMU5;oFs8)p>1 z7Ch1LI*qHH_;S!m(5pqCEo`5o9_sEa+&YKeM%K`sg!LaGmFCZD-p@#=muFSx-Qpi6 z!%elh5`Wtkyk4_Op@^oj$_y$L5p1=21%8$t7Fi=pHn?hJ(d(?A=nE^*tYEEW^t9Ta zK~%iNa~!G!%5=35;M=nNdu8JEI4eygq9s_`rFN_Yf3;9FCkqKxFI(*cR?BWrtEWYx zxo4#~aI6-V`^a5tkyEwNsZguT-zrr5YWa*l)U!3JF-*uBVtOL(6oEQ!(`L#rekzlC@t%xL?kztHbqF7j&_ImhO4H%~iM%wEW!+~GgFx*mF8ZMpH_`6FAzbbr_ zERMArujd|P689J9A#J{Ca`E3=0~sle@3z_(trqRErCh8sr%a}_WIf-ef;~%>l+Ga3 zTKY2&+B$d6YSA`d9AJhJ9Hd3|=kNFS>Lx_}=WrzzJB!L5NGa9Iw=d(BR&AX!EjUe8 z6Jthp@s_{|s+HBUDe|^7F1Ad2s?3-1QpZ}$GE2IA(phie7t(zQHzot|-J|(9$XA?eKO*q9oWfDOg zXOcOuRpZxRs+S7Su`BtKalq2Cr@hUVUEP-tg-1+-q$WH$Jhl|TqP|!c1o9hKvw1BCh5afy3pf1KG#ks!BpiTP-<58$F$_{uAjys=ud&T`uS0-&{0|nJTe?tZ*tFrmP~0pS$KW<3@??6>~_g zW-*~+u!Gd=YCZ?=<;IT7!=jK5SJ;hAV~0M9;A$C49OpA!%>(eXPCg*te*md)%@F#T z+$)5MBRCch7yf)pbH7^Ne#ya#{AJ;go3}u>Tc?6C(@q+Q@kEpBEs=d@zoT> z2-=Mo=^}cx6_0I&?Xs(X|H0D})!v;x^O*@sxMY>ex%2Ie#tzxri>0?x(@{_!Oz`0t zGrYz)YU4M7Ni5clO_)I3cFyo%PV?4)XN5Nfz?Tx_#ARw|b87R};BJg5rL#l3s~3&C z!#IzH+m@(I8Z2W; z96Z^497!2mmd=|HlZ#)<-e*3JNxKAz)P;{T7a&dg0~*j2J0e{qNtuvDN|KT;B5A$Z zp$KHhMOv1Z2kV^f7}ZC{5iB-O7c!L0Z<5KJ4gv0VSDA|yy{i?yoESZ>L9d{0hvz!O zbKQTDn)RSPkcPj`Tmk@}G_9P%Pg*_+imoZ!I5V1N1m$VKG0k(`!Sv=iZnV&1L|`iD zw4Pk~v@JIdBsMTWV(rGK(Tf9%c>W!{?}KfMo(JM8j4MwPs@Lm(X(< zn<>=eD9M+D$5O1rrC8@m$-b-$wo3~3t$4vwc?Ph!rvtbdeWSjmqHdZP`_m2-@4L1z zG@UthJvy;ybgk1EjToyCo^dXn9evBIm}#59ztynMyw{4@hd%F7V=|?&f)KT-E1fy0*K3R#^J)wAZ!Mp=TI3*$DhAfe zzWUx_8*@|L)N9+)Yfde(Uvn~gFOOQK<}&^D&u1hvi^nNh$uWnyqaU#6-vlVeJxr{b1 z8ZTGz>AL;%v#exZ^ZO*@IUtpoTBH-#)IBqQDb?ifb^bXuTS zssLip#w_(R+ASzgtum7n|au5tvxIFf2?pTUG~N~w@6dH zBhP^!(c924vXrbwu1;x~<|g**8GoDG19U|ad3k6&rl3ljI+ha8`IT!vHJbC>q&8OO zIr-@#6@Mi$2N{|+N+z9FT&umbV>f0F?bz6~F9#t!gsdeoGm9Z3SpbBGSSet#Y0rF) zXS6owy$`V(v7bB+ZQFvp*=t2%)H*wFwy&Nca~x{Hd?E|*=i-XOS&uPk?n=LdzYL?j z%op-n*W~Sm%H?59!<8Q>e$KT_jw2c0jQ;MW-YFB@CowU@c!kZD)~)~{w@9AwE08E^ zL;>S;K7>kIJ?*V!LtUJ^MY32rk&`U0<`pDu>0NY$@tpD3(Jx$X6s25_LDcrt^MhYf z3k!t9*4hECj*smf@7mKo26a5)rN*YwFHl>@w0csQ?zX#)qgicSg!Ku#agjr8P*gj^ zY)W9A{d|;RV}gH$ixNs{J_JjPcLfI2n8Q{1h-J!r@CsVXt~<~=t?EF>M|6mMMP6&* z^lsNJN6PsaCQEH16W98ZD=SAciuPWBbX?7oR6!mH4m7WKvnUZ1DyFM&C&f{lH%O}%0g$93yhguB)|Z>&8t)m^;J)$*YQ z-+d}3xVGMWjjP!tB((oE=E8XPy-uNxLB?a)*MDur-Q!N?ZISi^#&aU>j(6;%Uz)HM zwAS<8;FTHU5g2+%J2`vA8j6e$S2$hE77bGOOXhu#P2vh{?ajGJ&0!;R2oLQ~b2VqO znMS`fu&-jY-N&bfHoJ}2!l`ZdD67#v#BvlzG&roNo zs&E8Fek+$SkOaMW>t5Jz*(#spYB>q{QZhx%#Ev(HNv-s+Iw{RPDXjcvl_x4W3Qc=dg(B=wM~h@@1cB>9-7ke2IAP+F z)to3%B}KtZ<*5%1m{EWcKJ-SXZyM zI76Sht$Opr1EFXtbuU+%RCJ{h>zaWO7#5S{X4sC4hOtda738qjZVXeR^*W4UO13Cr zXjhRdxM9Nfs^Qxs_Pj0xU~HP8~b4N_=xw{b3OGgUh( zgg|!WLP>m6w~J)xLU(YQ+PAx&P2XxWpzL$HNio!l z%P?l_uIENWl{qUO_mxBEGMtENvoxN|+bVnqhpPU{D36uaH>wtj)EYLO>jh?jlen7A2E% z5VWkYWXd?nN$|+2@h}YWAbCnb3I8Y|MmJQkhn9Nf<9|m8Ht>_aLnB?OsvQy<+h4+Popl%kqXU zm!%O6KXR*z>|T)(i`gtQ02L+gV6T|by<#}XLkJ#f14pO2P@*cjbzqr_b*HOD=jlW` zMyGRUs2DM_xWZ@U6icbe4J69A>RaQc-I3l5yh#4nbNQGF_c9ki%zWiXgg4lt+)Pq6 z$*Aa-o%t*N+=nF7Iu7p7Typ9;obSu@B@sMIGl@Sj)*-Eu89&)6F zoEvfTvu-{EgeV>vdn(1x@3dL^*E>!B)|TntS>yEY>;iu2ROaDw17{i?Oy4Rw+f!{m zFj^Rs#fMz0&kc3jMX{1=q_Gfs8yyKRzR0Xc;*4p{m8j`k4C<^u2ZHABXQ;1=Tt|p8 z*zX~%%B+o1bTy~Rz&zaVB%Jos7ao;CC&O(q~_6@CReS!Es7ax--TjV2rQW9Mli_$ggRSBu+HfHQ-NTC`HRvo=m zqo*ap*KJhnFlIa^HSEhjN*al3Q&gyX)iQLAUK0xsOSp_s+!u74N5sRgmT(zqyj9q# z`bOm~bS_MwQ((Rq51*Johx=gh@RJkhl$w8vhYv}hGtc}*JbXXXzZgFY%}_l29SNuQ z4N)P|zFs86yi|s>o=7MD^(Tt7L>0BZQGAbz4~>p3@>}ttV6a7gAwF3mMsCB$m=Xy~ z$gvV~v-pk^Ur>BUiSLKv6I%q4?}_gi@zskjM|{)8H$r@q#aAJ|@#32zzSHqhpFM>F zh-E1OiUb%2z~Q?Y-O?GnFTMGjs&z;|z8{2!l<2!g#oka)p$wjZ0im8ESIcf9jKOjZ zjZ=mX$MLrkynZ-;BC-p<{z&o3&E@qhg=~?B`9rpH?$@SXI2QoP^Zix~RnHb_wg8%> zEqc8**igZ!7p5GVn@umloj1dbULu2)8l0llMnw;%vtThh;Nt9XU?3M*MW+m*uL-0@c7o8Sp;NIW4=#fZ)8y9c)h_aZKWOS>?|J&gEc`8^po z5m%1;0WN@BiF+D%zx6A$w&6eOk`(uw{C;4$m-rQz7@l^~!C`{)8E!vL;y=bi!k_ zgwBmPl%ejQ;qJ#txFH>Km$xkku`68y>EL85fTg>HNw?Ux5|0F}-7Z}){nXJ!8_4@d>WYGTL1Xn zwJ2K-oXKpl(Y3@8(RKajHaw zl?)~r$kw$iLYK)!u=Z;>IH{zvZ+T{$h-~zK8u zD%g~trxA@|64xfuP1{!7;kxA>BF#JK{z4`@q0a+V28+AW{UG4CnO86-%4x4DFklRm zVz9V7RcK(W@1D^cUg}8~E+dRby_K$(^U#PG!z6POVraUO6jQ?ro0JS=C1|ruW4RiN<+2O z%jlx_84=@a1sX5R)R-?Ar@B$&vsZ?8(kmA5Up2bfXgJ0%jQe_rIfSP3*;T?8f@ZslVv{dkMh7q z^QkPR+oXzl{WBMW-F+kAlI|gx!kc!f*-Yl z)y0xw(%-d7yRK$!QD+vNA-$YCGLkfH(zrzQ!vUzFKvm||tiGwokyOI`_Y1w5ti2_q zo0}Hw&a4%MF0VUCXUtL3OV*|(!DEtOR}w68NlZT^36_%piSb7y!E&ZFF?b65k4vjmX?tiKQ0ND6+vRWoN7pf(i28QEMdPi#8<@9-9<@RsvjJXC99}meFCg zZ1b!wA}%5OI-38oBbW?CYJ!u~ig!WscI zKFGFKGEev{9Yfe*VwhzfCWg8CVPZu4edv5d8-C~*(TN{AMs(zdjuB1yp<_gIe&`s{ zq#rs)H0y_s5#9WuV-7Dj(M26PjZ9q+9V7b(hmMh=J9JELatu}Rt8od{sozGJ&Ah?cM$h7t`Bzxm-~5O;AZ2>am#Qq++DbBxCHJ|+>>ed6i;ynaWCWgaA$D2 zcLN7E8&{57hKu3u!fnGPaF61i#65*OhT39{7IhOIPo9EO~g;qOIiuvhI<6}cewk=>;J<& ziOZ&+{187^Sg=!;thFxb;XwMAIN$g|a!rm`tzyI7TQ1!g7fyXT%)FbxjjDnnbJkr& zXa+h)uw>ubrHx|IrD5=xoUXM?-mVTiJ0_zp7;Mk4TC$YOkd$=7O}VW&%g9emQ)}s1 zsP9oaHfIz{{5vVCAF??o+vhp#)?ZqFDQdlUNSQycy!~ttsEmERYMGqLX2+u~BOXTFj_keiD328e zTiY3cV#sI57HSDzZnyncD_W1HFK3vC#_MQQm-7Hrma+^#Tm+rYqESRi+^o z%$g`ro4meX-ERNpGJ#p3AR>_Zo?E2E!jS4B$N(0jp!i9ZYA?-&9^}OkM#}D7?N;S1 z)X+_&Qb(7nv8BcSA3vZ?N5_aKV$(wjDzKXb)f z6LyV}Zs{W3`d>=A^}L(d_j2%=sSQfJbxg!t_ltOIL0YvlN0~v3N}CqOO|&M7xW+B> zB$3DkpZQw>8hoap?zjU?SQ3Q7a z#y5z}%}~|tH=bVG$d)9)MoX@)F!k+|Eek2O)pgCabYL0xGrLAh?n*(`h@jgPsxFfj zNd60rlMzU=N#bXlNcbzf`qmJ1p8Qk|G~!^0XAvE8wxS#zN{-j=%HLdEBx*Ew^eORM zq6QhAB(;SNafNNtUAxmGG%dlylAtU2N+>Co6-uZ9(&7ClkpPO)V6^E4Jyq%@4CStrLxr z(pSsYd~(EC#c#^EU9crW0fjBh_T+6mDcE`on3OCT8Hs`|xoT<$ntla|OA}lY)mYeD z<>uO0lxQrr$CDkAL66uGS}QvIqq(DxPFE=HjF)@#+>SdmZ$;~i#vsIBSXXe$`9&0d zvHg@>n^mjsH#^sEb7oVL2Dc=fU77@>P@UCN^1SuOjskCcsG`~!Y^d$2yvgf{_V{n| z*b^CxlH5Iz6O!bz`%2l;Z7HW|#+FU`EscPXe+`j0YS)k=mn~U#$GGWZkTyz(+c$|c zc)y=|N!O4%QHNvf3adJd?f(j%Jqw04ef~+{+XF6+cHNuqrRP%Y6fe3Bn#enmyGmiR z#fyS_1dV&7eaGOlwodRxGd?YxeEjA)#w8s~yz}qX1M^qu+S9_oE^#!oH|uEu(J>C4 z*e^zdd;52aYWEVkk0`InAGKdoQ<3IO*eQzL9sYZiQa1;Ys}4I?XOz10nzEwykJB*& zR-PO6OXdkqQ75aOG0~Q;4m1BpM9P6tk#Z<4QZ7h~lnc`$<*8|ra*>FX_3=u`*>@KZYwMD& z#j@c3n9EfqC?i^4{t?mg^8bTq`Q?mg`MI=c`8jLaInna+|K{bY|C18@w*ptyPenO-X(hJ2x!FKl!Vh;PQP0V58?o|s`HuG$ z73SOQdlb#UE`C<9^&f%FS)#7q9myBOVqs|i7M(xpR8ZZjhH_f8|@qCM=SrN{z=zz*=V)ZwdYgQ zI4VNnT{IbK&V<&R1yxnTc7=hDa0_Yrn3{Aq?LqTo2cN0XlS1vvO}JI;%MYx`9J=f~7HCXr~79 zRetjF|2{u8pSvWvvv(ZL?CF?Xda(6HeRBMRPv{eadtXe#aU_@Da=2qMbKl$66qiBe z=JW|i%uX#ar6V7n*H`7pjZoMpr6YL+Xn@WXpfe4t&NNd=ucR~S*d0HPpMCq4GF>P; zH!|r+lbOH2x$F1iXQdDsHBLCZr-;%dCZ6A9E9>f;a_lcsQkizu*#PU89pliHkt>i} zWrw0RI{!w)yCk^x1~qB?TpE4}C-2q7@g05CiV_|rZE#*$$1mn8z@+Pqy}T=vkAxA8<;jDav$`c7(}2pwcdOuohGuUR6 zPeyu;-Am=vxgZR-9CgP>a!JnrbckG}0M^*s&OtMFtKmV5Z-?U|FWI;LqVP#mtOJRO z8@NN02piCW%8Vh!zicd!D!n^Pb+8TRk!az4*jo4DsVHXa0Yf`-redJWs}IRA%$%Qo zs)$lxQ}o-^@%?{Ay9lgX$5iVn{Uyp0?xm+_wf61kzKv~=RptrNw9GcojyHPv3AT=B zvM5)F({_YZN2#@^r4!|6*pgVfix^YuY`itp>&$6M(@8V;Sg);^|~ zJ0a}xbgwbHVS`3v!kT_B9W%o(QARoqW$c#D+2KVULbQmnS`!YrqU)!u)m3eQNd zZ@;vz${u%KhAziTxlggUl3q4Sk7BBu8RG$`XW!PAy043TdvdT2#b$vjo^&A5IwV)J z+9R0C43o_C_Hb&}y-aZAH-*)x;fckw{{XU|8zo~v7Q@`IbFzXvT)3z!f9|gVyzV@JO{tCT&t`=-4)=IN>vmE&PtCf7tdBkBsX|#E z8Z797t^bC{&dS43%po6_LFd{JhAEc0ei+8;ve~>+0!CymH#*!TpE0v~IAsf?XEvYo zI4eo(o)TKq7J+V8NP{0iKT8n_XW8QUnxc z^Ks08rwq**52W=9E;qNP=2cL@)T9GN2wAH8*Ck}%f^DeP2fI`Aw0#6|Zrf&drg+`v z_G15ut(W2Dx1m?eZZTtWd1bMtOEkYdFyHli4N?oV(WAS^s@J_QMW z?eBm~0Y7^qIl8F2wS-qtrK$o`;jt9jzR>qoH|nDjRpIDUbR2M?CGQEEZ}vOBrch%- zAV0Fw7uxy>pyo-`Gy<)jE}Mz$;dx`AOXU@G^5l~R%BMg?9$Hn??gmDw3A?x&Mw zFn8$BF&DMB2p|{~PR(k2Rxve&HT^Ppr>X^=SNlSn-Zjr$xCyJ3#apM@(z$y*l5=CX zO<_D%;7@Bv(U{P>Th9Cfk4=+W&OFO=Yo3jmmB_MWCbB$wJ*alc$Hm~D47%-!>Lt*9 zDDy`-0`;7J{c^O{dRZ9%LAY|VVNGs~W7%l@jWeSor>cG2l4bfV7T>eoaKo`)me7^v z8$LbHjX>xpZ{_SI9L8!cAQ)8E1N93eDTg%y>iQV(xJmCO;8x><)r}<3)^;bRn7#gG z`uBg98X4JP<@gSp{i)J@)?~BC|0I{Ux9G3IgkIe`pkF$;4@Ef?0_EvR89j+9P9btd z7Dl|~yAnp;L=9SCmUb@F$8)N3oWM7RD6r9%DdV9-D;IbWEWn#;n+jU`%5)xh~39I8!?&SAmDp_9?W- z%=6n~j+oV!)|gyHFtM_i8Sl3TGYD>@%I;vrO#01WnihsCH!_ygvJ&M9ZFMvh$JJ?+#fo4u4}9OQD0o$oqW8Q#Gd53 zVpuq=AZWGLG44uYMW_w#lkTox*fD-l*~|J7mM$w@FXImrj@4V;U2lY<6OLKqpHbbC z6XB)L`TBil%y(1LKVK;A!7xk9>(W7usk2l+Jt_~cp|!jT;5f#3)~<%)S&N3tj_KFa z@_#Hlu3tgxztv@j@S23zalCTyddc~E<65`Gi$+M-om}*x`xusoR7mJXJsS%XWrWhk zcXfQpOH18`f*>4F$GEDp!wTdC#w4%f5oG-dexDMEM?cmqcceN#okeC>cI03xqwIvS zzhj|~LKJpvNSR%D=)ZIR1A9cP*LLjdI||#BTq0Wn-Bz#sx|Dm*$5HO|1Q+~1_R!`3 zq&ae8E2hVh#X=q%%^sn>gs=zmYNFu;p~0^`0iH&w{X(nxWO#v4`>orduiH2U5=%4; z*V~_A3Wd<0P=sD~f9jKCU@cF> zx*%H1>}Z!PmVOifx^YvqNgGSZ$z8m!D4!;CpFW+5nt3!PdVX`@JDiD`f)uNQz;=9O z(qvv>gC^r_*|(?5x?D)0)?7b?V9{#UI;LZtE@2F3mU+S8?rv@&b2xtX8d4cKW_3Z9lN~=>V&veDmlZ*B5PTp3YXJWkY>lgz;^0GDd1)dn zW)#QI&e3ywBOwvPI@fjNAcD<91S?)Ll{nKA)uHn0kTHdb#swbu@abBo9Ow z7?d?a&-j3uh@4IrKDhh+9RZQh&UXu+VUW`TS}nNuIkRsL2eH$(IwoMFX5!eW8!Z1l zGkcl1ZwcZ;-M8p6(k(SV=Jg^>!`&s)>>Y zVyH4VpJ*D#?G_!Af8-7Be%9)m`9hcNd-08AW%dcJkV(S$FDw^fNr=h?teV0OPQ?ay z_gl}ep83MjH@e>Obu6EEqV;86Bu!G0XXh7^j28Ju-t3dtNjf9fz5)PPeA$$mbQo4@*SZq~UR#C5gkp&{k=|hc ziVk-eY_j*>)ZrmHjZxmHh%4+54u_!7=3O zGsdm7>o|oLgO%GC@IdTptp-gY-)fd?ZgR~90?^}JZjN|aOO0e1m+jn0p=it8dMLZ$UY!0qlpfLcYI8p-DsI86xexp&qHGT&94+Heh_lbVV z!adF7te#yG(ge4B;tW>ucCCSS3q_g1s87t3Fm*rQxd4sJ@NQ;^#YzvVgCv+WBuTx%2)u3;vcUL)Z%Qk1)n%MIs_V#~k~1seu1!-GTnYTGp^~nyp=`5rYK=YV z6Et`?nIngPiB6`XbM-{?1Qk4RjRdPcetwjXhgduY;;}!6n5}}(K~zzqwlRn1=r?y1 zdyI=VewCqQe}i*%ppvW9jB$I*s1YWawiF8su(Q7wEFavSg9RpRi>BtbRp1e|r%_#& zwz0)pHi4QMtnj=dy3FSJSPtvy zI-`0=AertR1C=d)uReo$~hHV7m5Um3L2b3FWG(DEQbAA=Sq?&e|e649*RDYX3ZFQR2! z8ZFr8Xn9@K*7eygQZ5T0v(CCmF|^e6_MzKAOByF7zw5`wT}+&JE5596`wpPVjG@5{V0(Ck*V?Q2APa!Z_WGZ8&tY zxF9U4Km{;k7a88Z*19dQVX#YMfm5=?-zO(7ur*n)S;tCV8R+sQ8iw?%t=F(kdo~** z;nvh|sZkj?I8bT%;~@Rn@PW-Uz&>j42~^RNd) zbdjOHJ$wx;3Bb1gvo!5(BCgkFR1fuuB)4Rrk1K)Li-njcr?yFERu4lsIk(gDb-kH2 zP?@>t5q!%jtpZZa*4(e@f`?vZJrP>Qw7p0DA1C;B4@5dAC?pklS0jQ zpsPHhZOx5Bw+Q^QI`TtMy_U zhRg1J@iSS*4I7@+y!y4u08Pmd$|jfB*GSr8#yr`CdyRaeKM~jSi$4@wl;dPfn$KYv zMl(0~F${^$15-X$HRw}Jesqo|7Hp*{yYF(@bBL9zd3}ezQ)X_<{{v{k+JTCIsmBmG zJ`HcI0uZwLe_$;IU#30>@gVF8HoT_NtyRyTw%EB?d_Bg616}L`*4W;3kdZZENI^)= z{Xx`z26(YpRaoV@{Q*>2_EQQ{7IS1OX;h12PMG_x5^Hney0D1KJP1$iA4t^w zesjd5&q*#WsZniH+uCd+`cDBUu%XjIk z85n8_SndM&$PzFw>Hml1nySN+zTFGKd<1{$Ux#4yiw1OuOIQWR}Z&GK5WWza^vei^t4BY z;q8;vgQ;_MZ6dzEJ#5|A*)~kOVT|vPDt5 zfzQ+mf9&4zR!(qtSp_P@^xRohpxYXX+7C-?#j+@LV0Q|1>|CYTY&|P=cw<37+YK5& z_E|8z(J!AK`8>s^Oaf9<#lcCZp#zGCEH?x8g&7ZpjkH7}&|Po;ZvvXUYs(jW8@AJ! zNMtQF=_I@?O!5gH48MR!lv@fC3uIB%K211oWB$%N+;UxJ<<;;OO@3)O+`s8Ux$i*A zYQEzS&yy&d|IoOxND5jg1!eI@*V=fccod5Vt1>*=UR|w^vsnRp)=F2<5~?(*NyjO` z+U}-2`%{+@OzJ`s@^xlo^K)7IM{spkVrIP{wnEgt= zz$;MFwNFvl^5$d4WdQb#mD)vXN5R@ISW5~VY?E6W$`^=KEZ8bXsH3*V{G}vgzhxbu zjLCpVg<^2z7aWP8F4!hV9z{lYL3nVB<`zG_H514n_I($zUo0Zg=>FDA4BP`Oq20}P z%f#e@?w*c+X$p2g5IOa{M*B#MG4oGK z1H^dkIv1ePgL(J!clXki$=VUJJ6VB6?Y|#n(uTstOa=irMZ943{&gbf@)y~~!|)eE ze(LS2Tclrf%Ytq{>j4>(N~|S}OJnGX`-80m)cT2vVB0(L^y-s^7kPpn^_pN~g;qS0 z$OjtnCBR%C@D%?skhS5-fEQomvX&7sKA~$ZBck|fOuzyz>k{GC$04ZYH73g;&0DX3 zF3lJ*mvH~wio#{AA6EExghV9cWt=fEk+eA1%TD@5SQqX7_^J+6_&G!&>}9RJp4Br+ z0p3xqwQEj6lb0Kj*9z2sWth28%bNphSu(?KA;*nqN)qO1fg-9PjNWRs?rS-<95SP@ zQ+lvIQQeOixAoOT^{GVlVMckdb;UT$7RgTE&y*l0&#K<9-jtu&e99AipoA##vqjr4 zjGw*tzI>5HTU|b@yANvzItU`<1;@`&zNvFs&6OqnD z$L#h`iMIpTq%_X&32X)As4taDlQued$vD0=~EplwkU=*7q&<#ozac`{M1h zc!^gJ$NTPgeX{ztiO<=qjG3~FV=tn(BI<}73ntgPQMhlB&%Tv>S$OY#F6oaaD;FMi z`b1Ex%;!n^OI7-;O!}cGtN(s^CL1jR#vF5r2DeuyrS&p!^=(-KHG~wq5GS$nIcdc#dZHsDar$l-diE za3AXvV@P4=B=99hNJDm>s6HKRl~Xe;q;jpib*Q-E)f;&UQp~#F`t=IARVPyZN!MWXq1Fe%IK-pCNR_4MUP(sSi;GnR7bVS6hj zsY$j;IyN-i5tE4YBl)?mH*!GWJF`vuQ~GtLovZ)nQf#GC(7yRTq+!!Z8f#Zcdm~aj zj|+#*hQ3RPplbR7xR7Pjbyz}S&0f;hJgiR%KI1uJQ%5pNSF`VJ!6pqR$au!ncZ|=S zcM2vVr)&CT5;5}QXFq4$M4eQj=9SkC?eHb)hS&_)MevSd)_B=+0GWGHUvtHDk;B}k zz(jPKtJ)$e7R&dP(J5+?@-k#C9ZFRH*s5SG?U9a=jQp5|*(A>$ETY&!*tR5cHupVzix)81 zDi3|7jL_B-;C(56KTvTPvcIPWy^%ve@Ni!sd~M$^@o{^G!bkP#beGVzc$r7{u|zKE z>U%;Z8-fB!YQ~;tATk`MSwg((YdRu_dLnPn@vrQS90#*--Hx*)9YfOSH|Ew2JM&bF zEv4xQDvIg38?5S68xoq6%@b8!w?FhPkfx%?0UfCcaX*afj3S7}#Uzb63njHagWn3( z$pZGDND&J@)A^_~%kER}Kkanh8;zjZFNvpf!agL=(ibH}pVs!`eHU#P|X2eDRdLxmbSvN#qklo@O@3+}<$}Wt2fBCMb_cH<3M_6B8mQCGK%L z=8x!B^p{li5HcRv4+-P4+(`eU)(2KUQdr}p>^)9jDt9#Sfl^ra9P#FxvKhfynK#99gI98Rq);8okNh>d;nS8X|QKC z3=ecy=$8-ldi5OI=o+VBpxb>dadHQ`v-Ao07SV3BFwF0<661J@(Lc}~FfK?_t|(Rx z`Y1*C1v!BkVc3PuxUoWKDLz7 z^HrYQh?|!(4%-c{z`|3|8cn64w0WN$i?E;SK#0?j77LzCVH6 zfcpRk*J4!%Qp^1J=35gxB3gS^ify${XM&W~z7jSGO|2o3+ZoxWmTKruc^bM|Tp;IA zh2Jp)wT{A!*uB8ULa#`ExN02QA+@{j4R|A2SOu)^Tch>Zw!fUjQ%MyH?#-#MVjaYu zg^^Bnvn1=jm1MscA&AJZO^@I5Kx5J$8k#E$hpd&EZvr`UFzhZqn>^;_?AV=xncvV- zR{bf&y-VjqHuHR49ZN56&+n+Xq`k_kc(pxOvp}(bc^rL!wvFUoThptakAUOUq#+={ z`d(~4eJ^2I#zgaJS+-|y(pYWxWzjE^Z7=-+yEhL*AZj-1&t;)jc3LHJ30CQ=$)rRm z`FwJ5FW=|Cx~Sc|uAU?Y$ipJIna87VP08c~3wcgxu(%7^&-1zuD-C zvvyUlsV&^foCf|Yv!`HjSb^F8d}^KmI2YEi+POlCblEfaFm0lKQY9TAKMjhCNlw=F ztVaH8Y+32t8!PAzqktyK!l|uumq0hXO5$S9n!|_3oFx@N3bE^Ip4`;NZ*O)nzcR^C zUkOeI;;LrJKs$om0uh^))C5{Skg9DOXLc4iHt10@Zd4e#N>r9j3%T!n#OxU^*%s*f zW6*lxu7iFig5(34AOTL_@&X z(e(k>hkS7J7GKlNpR#WChi}!4<>m)Pn=k!2C5&6o9_8}bEdSuq8Ef`bj^r9wQi2&5 zIWv;CoKO))gCEU^K8-Pse4uFpF8@_;IC)slzh3*&jo&z>{@4f^41e7SOxyrEw_ZLl7ESk14^@& z`B_o9V6A0Z0@L#BSoqYs`81qO_?2L53z@L&wALK)Cj&>get}pC0AL#(04x0A6`FBp z2j~N#?bX4Nu6Eux&x$t(;mtt@KSTR4}Ka-jreLLBz z3Z9F`#&9AhQ8@>ReSb;|wha=#Q+l5qEI2MD%)62=Yo7GxuGfRUrGcNzU{T|zc4Z2i zWfHEEq+#cB5Lh6jQ&xn`$J?cKUAWxkHL`TE8)0cEzHPAwoq{|4Bg)6T7m34NA``eL zkovXqO5JmA%qcxw)$6TEGF(^>b)Cqv4ycGF2a?Mto?4k)TEJ=MuUAm=hz5B~<;f@s zXG@8;_{}e91!}mcAthpv1ycN75~`*@HBbu1HVPGCxQq>V~n3 z{lLT0X4dwHD>LQ2!E(Lsshn9iG}AaO`p3zol@oq#8K;dY*59@g9~C14QDU%0W|mL* zjoxR~4O`EaranSoPFu@?`#d*Jx!E)ok;z)N^RthL*tzt(Da|PjBG~?4|s;Ifd9RM#Jbs!kY?PXA$M8m0>YuYOlxRIby z#>j)Go-x6>HhEiy_N3z`A5h&BB6ZP7kYvV$bmUw8YQ$Q%Xx5kg!tW-w`N@@Ski<5P z^{C*7l5T&O@%wJ#%l^bI8V7HPkyxpvOSi6Lc@BFojNb{(vq!q(%@aKB_!twOA#vP# z{^%cb!=ta1CwF^$rSr)#5%ZEOPN)dP{ECppm=mcwIM4`&jvH2b0^piJOdz!_%a*8y5g8tj4Y}ENWZGdztK}91ceEU_1%x5GZGR&L10U0G!vP_(IlE;uFz76n>fLq%9e30`wp7A zRngrakqNHe`V!Yuvz6P{Nq;)AnEuq=bn{)EGR1u=**Ztfage8C1Rc>guZFl+d=EuKO2I#4KE8bxI)&Na>h(KglIVUpjZrJJrrycQ*6GM!|w+l zl0^+&!zFk(Ga9$#G~FEIX|45#*J{R6$l&Jb>G_<_mt5{uGycOeu)`EN@uzjoM6Db{1H ztfHo#O*Dky6eN8^C=t^V5ZjnPajV8}IHnnEI+l;~LoM2?FO<1-oPYC-c=Ls$bEzU8 z%%#c7hbvtyzu++05+O8}WT<(xRh1m?%#;^`Gm*hrc^yM2vD_=e5LNFgZ(`AKqVl?- zJ`wYyv$B{+FezpoVQ*#wnK63naB@v4gERz3C4>$SXq~WBjV$PBiZ-dYF`OoXDgX?H zZ_^Am97lPr=V7MwoDAmk&+%F-GMG<7d7yHChW3Vl1?IQHb|}nmg$sdQ3HglSgb_L~ z*K^eFD}q=-^{pUWOS67pI8E&ox00hUEZoW%5~t;spTqF;f?*}cIZhy_)Xv>stS@QDXqW&2eGu$KRhK{W~DEhABKY8+IP#$ zBez5nA?N`#spUhDpA+qGzzWsdk8-XBP6k@%>kbcXz9jyT$P!RX*AnA;m-zenXz7(g zJIAda=Zf?S1o|aBTg!-)RS%BYsc~tk+Fw@t9GTV67M7%vqHg=nNszKCh8O<$AVWHmK5dyz5St^EMZ>Y%Q`MIb6W>3q_ zQgWl*>Q>C8uZm4uDv@3}v6h-{22-iL$Jth8%Y$!@Q*QAkb_8HD(6G|;S{#XQ{*iO` z%|8?pfi~P0zkap3tuSR=&gR3yqE88%6Idh|{Xk*#kM2|STs^GMV_{WD?jsOot%pS8 zNcAm|Bm7Jd7e!%bVQ5QscwxaN&B_fwtKZK~$PPoYQqz>Oihvc}gp#G~(+8532MYNL1b0vLhT=0kEoFj` z-U`2T3u8(uTdHm@kl!K>TZQb$Ssc5H01Ca*HuY9ic(!2c|0a#KLrXqbSj0%;ln>?rx^(5zp!tZZh z+)>#2sxgPLv&!2T4|@#%;won_{NCmjqB54v4B;?s1E?L6XUjS{-amgN}ZD&q4w zfP5ygSc>{taKBhf_)4k^$jCjYN*`5?3AOwIL^L(;IDIMg>(snM>E|!f&&Sjgof&Mb z{Tng&eiIL+rzRaEK?A3})XsQ) zoot(LoXRO;ku2X)>G3pxD(k-*l#Fa}p`#0?5L>;^?>TfRy7;;|s}|3hql6E#f??4NQ-*$Ug{ow*?S8UQn=0(j z4JRW*iN(Wmt?pMesllg{fi32C?Z(Yoa4L#aC+@;5XB0j<8$d*>6Y)_zjts#pN~ ze27yPuc;5r&TZkMxXOn#`_nX=<$ox#I6zvB1O!=gA98jIne;eQRZW~p0=y|zYyYF0 z-Zin4X_Pvd*sR&s!l^aZ!a}T8q$5$oodFbMAaOxt_kKAc64TMFT?O{KqjnZMa;Zs= z(e!K^?Ai#b^c$OWG}8V*xsk3v);18+XGc@>BqTNI+r$GBO4oBKSu8c_aY?wspK9_Z za#l5}S=K%_EEedA4@A@|QI&F3 z;t{p$%!K~M8lzA>+88f@nw5bG^I1Djp##m zihAVg-vD#W>AX(&bRJs?*E3JnvmwBplC#*sjKylyQH7S-JQy`;^Xl^X!WIZqgggvsbYVf3`}$!$e&IyAsQd z8%84UI}y|%t~aiZ@5q{)tjaQGrXq*U^~Yduk8`fXxnd;po^zRrZp9Q6-3pRz)wPkx zyG}l7MgFgww~3aL%sOj1pVbS@k*_e)*c6f-n4f^Y zm@|P-xFUOtd?g~M(43E)&~wWpC_)@(^V%Hwo8Uu@$VV{E0(k>Wu=Q#_&5?D%)*)6R z!3Uev=jV2mnIm`UmyltwtsXBaJ4`^Z)dQHm8T>S@gY=v-&t4O3+d+h$NT0Xw%e>&3 z{KZr@wBKL z>_E3by=0mg)mli}OR9Y{sRQ%18%86p zQBkT@ly6H|dybT2v_q-f?)e|&CW<-fy8K)$R|H!hWb~V7*K=9h*+{T0&ev$}TY7TV zyM=sCRCkWWK$eIkv)gm3Tr^#piECufpsxm1asSbcOw99;a`5P1LW=6})u%xUeL|4p z{9MLot-T2-Qo>jaRW!PRv~94hnzvNsQ2cUsFs03EFa-ZTDuqj-TN+dazPWEUap+M@ z`VsVKPRN`br`PVFm%iw(gRyB+3{z@kANp>lu%3<^n>v>1?+z z967~3I{+T3cHEM5(-E!6FBlwsdw4yU14o2V1PR1%ZVa~li=eYNd9Sxm_*3avm(i=x z43$2_hX1=>XJUFZYy`O5GUnMi!L|scNQbO&L(m)prTQo1XIJT0nIrdNUPY>=YfXRC z*f%*Hy&6r|GU9W>Y|iSw4~dWlk}IAT68%$6_c||}EA2CPgO7N%ooXsdMjmTIe`XIc zL8IBc|0`(S+}vQ~{;*+5Pvl>U9A8J>a~t1wz9Nc}N<1oer zJ`(KwL;PksrWdTLLioTYrQ`{?gQA>0?-yFBl)(&yTa=yytU8n?%r-$oO{RUK=O9AFl4HOKN4 zxaUN*r9E;mHSZ1vq3F6MBl~LX_hzG7WkvRZt__Ktsw&6F$VeD3sbkF$;=VNyR4H_g zy-Og(%8kRp)+>2+`_O&TYLP?K5)!wG4=IHec?sPcv&hqTr}*$(#Z#semy#Lun?A2Q z{yw%hDP0`Z+-CD(kSTZ5C>r1PhIGV{dyU&NgEP1>j#sTcTe#+!lb5#HxoVbpi_~cs zPgMS_y5mj$m>s){$fAZ=cie8KU}&~G+J?$K{NuM&lSu@YOP63nAz z&3AXb<#TRM&VS~}TTWRfWd@tCVp8%iU{k-LmV4=Kk@~xcqmELu90#;ABzQd=TvdTtbwr>FzQB49JphmP{sTyF^QL76+R%5 zZUXt}x^m10PRXd|#7+EO?-z|qi|eDs++B2lxfLxcX(Yz5LuG}`TLLBKOp&h|yO}T7 ze=~1NSqO*|t;ivEKJv;Uj@tfU8jc)N3)M8%quflzfdnyZ@LAz=h4170JnORkLW-9@8-hD5X}k+n1+(7stk86gTA^78SF2x# z9gyND!2lLecyLH0%lTz;VM@-ulyr3`7mkd+eK`6yoPLw+<(!h-GwN@9QD5TPR;jnn zm>>8zT{HNySfkNOj)(yu;{%AG9PgJ$h{v<$?|m2$(sSPbSCZxs=N96yjK$ChQo?Sf zz*5rlf(LlVoMh@ZO&8h~ z=$Uhhf3;vxnN4ncHHO7FOzINYDuIrVn822eZ?$`7E|B~@wHys(>wM_b!3RY8O{T$z z{#jn^B6Tk;Ld2G{B8h6gGBX4*uUu=deopm+F)SDs^$b7qq0hVK_|PLC;&9S|fy!IF z9KDOLACF$7*4~ioo=wX2v^R*hRI(ZoKh()5XOpxVb*?itPl{$ApCw(i2-f9El#C1x z3vnbgkKYf2yV;>Sp-t$@Y=ihWj^P8W+v_d{q54Pfu0$_?;5Z>?zKcaObsTWDi`=y`Xu6$-EJ4JwjqM=Y(eW z$ZJ`0l|ShZvq;|~+Uen;?Ho5QUm*E3NB0&3%q`Pit|pdc@O;xPLn0^Hu8PpLc`8Sw zJZx&3cT$9k?D2BFLUBu%D!>WkH!ig8KXq~}1-Ep7^Nq`qBUzexCZ(5k_&7Rn9fm#7 z$eXmCqJpiNf9ae!hqBnRvT_qz$Aorv9Z(*uS{xqS{$mco=BZPw{#VWUEh#o^jq0{n zd#d~`Mt0M{Drdaay;M$mo1K3G8*#EgWQ%s$6c)Sb3NNae&=_$wT){q-5+ zdDR?0zwyQ9S>N_=q|`a~)TCB`DDpz9?Nx_Z<-F7l){sIxn;tWg$bP>v?9s=e*Cz5W zE6410o5k!d4i9bmJtD6A{sZ>$a?TZtluK~FeUJ2QHI$a~$wpDO{R|w0HBYQ(l%_gz zZtT`Cn7=^xE{WPdL=GEc3(f1;N&nNdH=NnzAF93+em^lUP6}o6to3Q)SqlV0*>t_U zuHL?vl$ITf#BW}pUsh+oPBGA#OXR5NbrPKu=l1=u*HW~Y@58d`#=(Y^Dun&)52Qm* z6L1L(i}q$OrKF55k2@$=o?m(|rQaJuoT8Ncu(zR<{C0|25QOQ#utreRqthWIV)zW# z)YjJ9)vA}uiQJ^Wy~bWh`NXbzAx4R`Ce8lQFQnq>_;jSC|Eo38dYcnk^lj0~UYeM9 zFQC^p?$UXlDpjT)DDKw0pYKa>#_$54f*=0s$M~$~4{=sGX zZ1~q%@Tmj$d!P4({CXhe#rg+!QQIe1RjBu0sdwjj_2FmDQ6&JXDxAg2CtC$~gero& zUl}mR0?FIza>y%A07Rr+eYY>nZsK%GE}bTymg#;np*d2^wj$FzG{vc?Oo+vmVK zYapZa#qzqs;3NAIb%jS9>*%e}`259Eke-}1RVgoK;yT27)h%Xop@(5XQEsLvutV%a z>7O9tMPsU%e2H#C|X`nnps<0C+GN!iIw^dQ%Js=!~W^tWt^;Gdkx3LcaIdW+o=^2 zvpjs3QjC^ZpIea_rloc9h?LHwR6v>ir321{I?kaV&zC7B0O`^N zV2`_XfT3=VRVo`eJI9)txhi93X2!;0Dr*<=v$GJS!Ih|^s44LkEUA6EmQ#;|P0SEs z>E#JlePN{WY;P=FP=>LRP47mnce~#7g}*LA!8W;rA(NTAHWm&nouRu0*7AYm8f<-+ z-(=ewR^zU&FOob(2S{*X+JD{i996aR6=&{x)z>7SmL&E;_`(X9iTPV*yCF69ZoHrw z3Z!X=n|!{Zjduc}-aZb>;0lv%chadgRw}3>4t70YAjO6ikUe9?Ds@a;P?-?O ztFiy#DUdG4F}#b-RKfPyX)^;krZT`I(_h*;K#pyFH)CwTEY88Kw}QR>JB?Tg_(#bP z6(QGfp5j&y9TH7^&1p(o1hf>VTc2j2gDwLd&M?q_op+uI?|iY#JLjL{owud1GrMiX z(URLfbbQHe!Yl{U@Gt6^C?bq?SZ7RU@s5+Nj4`^F7`+*zmlM$-bgf0cPW-vp_q*bJ zON_ATy~^Ms?6PZlQR`Wf#VP6Z$J%aX?U7Kmry_ePvhN2|xRm3M92~1MZ9m5_kTuPh zx2sG$M=xBeD^;&5x~nzqYI@8w^5ZPBrd=r?^5e|2rp=KL`EjnayErFp^{2M5|BW3R zNjMZ^6Fp{4ccxj>iY2D}Ga-$X{Y^D%yWUD!&xGU;C?I%VIZulEknUNR)-X55g~O|2-FY1*K>z z|5cJd(-I72YRf7N0v=_tcY&-bkK#Ka#zuX!#!(lJ_eiWn)g5AS?R27QReGPA6_RG< zJq~y^e9JenRlSd6D)W~m=l_gSgnKt($K9wamb_ZME z059RA!PZxK2KRQFLwDS_Nx##yOZ13oUxZN~J71s5<=+2Bcsa^&ZM%3$x0`ve$oZ-A z6zT1#XUO@dfvyUp**sX`d=n!c#%A;N5%bMq^I%rX^KoK2_wNx}({{j!O*qiE2^wnJ zpV8@npD^tSa%wcks2KRqP9q%uWkp{t!Q~A@#wXIps!%S0p7hO6dr!%DKkunv8pfJ? zilq9u(ii(K;ywP$c%NLEvr*<8gaYb7&X(zP$paAZ@N>;#itS<;0+%=@?g=DT`4feS zRa#=zRBj^5@ZV`mC#ly{=rNa16IvAuJ}77D(q!ldZ0Xz}q{^6qt&kU3%3!u5&$Wc| zABuz(;GfH~>zvh+{mxoz{(m@?O=VC!`m@$r#+$R7p1mncKq>FYD3G0z~I?ZrnDTH%c}g1Fn*#U*K`4f#q6t2 z(5MIkV4-jYPphSt;Smiv5tomygY|(bzt^ZVcc5%Olb!qben;*3h#7gwssPoH7D`pg z)_)lwW68z)xD?Kd12`@?`g&$o# zV^pu$_iN{5*BjXwsIo<^HP&>2eLodaT}5$vBEX4;^CZ{$&2<>u!1*O*dQ+L+Qf z`mH%1Y1;K^j!fD9Kqs&dk>4_1TV`BX+jQE|YMcJ#_-dO5Qj=B*0>&k#&f%&EXR>|o zcSift7G6!&m)I3PFYi?!o42orqxN3?2GMN7Sg334aC&KH$$?DvHIjXeWM6YGdowU6 z#jwW+9;kDTz1f4jp35F#Q&CW)w@W;GSJ2LVcH;FWs5|T zPBvyN1Y3LQ#bQE1G)|wuW{ol|(DxsF1-uzc3D}mokW*wa_OXTCOKmA+^axj}7B<*E zP}bu9MwADdtY~0h-~G&^E4XtF@yZnIOjk--_L{E-Pcm>YIsYLi`x!BA({Y=BZT$87 z<7e(i=<$3}A{uDfQRrddbF6TMvYHjZYL+ohE{0=Lu=1CZl@f>MH+CzD$_cceLb+)J z4`P&WEFG)(cse!ubwoh~ix69b)CU#mOqtwZg6j=!UFj{k``Th?U9iaR$R9&h*qekZH= zY`YivINIs#9*W5`)YpUNb3|j$y~8vA;$Z9d_?VxkPiXfoPO-!Iw|p+c-tT6_9H9!a zkCtObLRn5@k1uaAK%C8PRfwC6pnW2B8dIM%eWzwi%;wXw&oyp9HrtsU<|y5ScynsJk=^4P?-U~bl)V*OEJQFDNeF@i@}>L~DR}=9A&L-}q)wf4 zo~WRbS?xI`4FPx~_^?s+H+X*d-+FcC4@G|@6J6F3Ur%^si-uO^{r7^tw6*pEWYI{Z z%`@7j+3$ZRRs8qgJjLC#y+30%^q77AO#$2K$zW8A1Ub>u_suci@)etjY&ZCMq8~$euX^%5*dz46flo3P>iTv7)4c`AL zI^&oWz&=U-r*Nln!#F>M3*ZWHSKz?&RPa2NXCY7SaeJ_UX93R;PYDn3#MIn_8c&U< zpC^*_vF+mGrvi9OajS553+zn0RQag=n08R#)OJi8P&eYZe&@B@|A6X_aCZLBsqPYG z&oE7OcYJG<>Tc(C4ApHpRRH6H%v%JBp+qybGy2u3ybVIwBH9?Ej;#E~T6LV`FVgdy zvc%%1eLFLZu&h4CBS8MT=)6!n0f|<3vljfSNbr(vr$kO&JzP?a;%jL0Y+l(`?8uFu z8E=eBMf!U@c@^y%2fdSjFELA=#n2qZ+kQwSL&^uKvXF20tG>qaDUv6`8Kf7BS@n5Q z4)5KLZSUcdNFW>uZR#jx(TZQN?O}>g-mK}LfyS2`oD;S;JT{7#b-Y647rL_mCMBKT zWcBHKmM|!P22#uu=}Z89ni`=C>HN#N$d3sc9{&e-R&cHsdz5qh6zab_D@D*I@bWS0I?&y25eXjJwWXN zAr(;T8kvFU5&DKeIzB!X^^<;QBe`kDMi~qwU28$JcqV9?ePZKsgTEBUd z>=%ym;oW2SaA{qyetWImLfNcwG533Rt^G-{6i9iNyG%u9k=0Le29S?WvWLNYVvc=^ zN80l7^XRiaD#;N2=G#Zl1ssr*AR>RjZr+|F*ya06_Zi7?yTp21>6F7LvFuxg$xG)V z_5`s(fh1=Eo6w!XN4l)8ZfiX!@uj8Dw>73TfYZV`*-sWtX0HC5a6klS*e8Ph9ejNs zY}w%J)-eekTvuG+bKhR~9bHY3Tgby7S4g>&frLxjRj6y3&6$;e4;J~l=-9v}^} z^a^(bbLX!!O~RrZ_e%h)xJnh`>NzxJt=c6pMB#ot3Y~In3}YdbQpR;4DeY5JjwaYcUX-m9=2CW ztF5=K(+T4^cYoOJEIAoq&IHh{(8^ARAeKFh*%*z%fQ(QLEIekQ0#XWDLkJyIYAYQy zx&F}kP0{U+Ms*CyzU1rDDP(8AlLMN1p1CZb^)6J5yEBmwe{x{~0eC@vJsdcdvlR&p zIE*f+Hu+F+9%Y_Kmo6Q2ck@JrbgkO+_wn5we6d_1`}vuj{4Js-Bs=*~3&`B16m%m4X-MxIdo4_@o#@qp+$!h3M@97&CY~a}BhL$ra&(`uLZ@adtp*vZPOjPr% z6g6Pcv0}RroYk=HgZOBkG#1x@s^(WBKD55Fg9hm7NTWcddP;FFG|UJGtysS*ra= zb_Zne{4GDBbY21S$|o;vi&jF}FS(<*fTzYYF!%}@Os{yxW=ib2Kyl@Tob_%HZ;xQ3tYxNqY|dF;Q&j|*`4w$Zq09`7UkxWxL){CGP3bRqhy;KvmvQc~dx+;ZHVxKY0E{~15td4^nEe*7L@KZYMaKv`%9 ziTv;}-iL5Sd}R3OKjX(G=6{bLS1>bhM!D9%#*e3A>twMV*NS@p_XzGW+~c^P;%Jxu z3;eibW~C1EdkkmehQ;Uq20#AaC6%{|3X&p~G64v+MEothF$;F#;F>P96A~p&E=9hi z>`f}GIC4poKB>GRq=!T=grhtWjfn%5y+XMSs-e4lnoM@+V^wpCQXjVgjnxeaFLRLd zdPZF@t-`uOT>#4Tx8thvNND>fOAnSeXu-el5|MmOv?(`3US-B>>r|1AZxM4-c3Gp> z_&a;~-;SZPj)}UyB=2OJWJl=F(g)kb=9F_Vqm7l%CXHy)J&Tx;ZEOgp-z}eeAVZPu z3^_d%KU1-JQk)a~Il=GjJ9?tqI$YWre|`GV-*c3v^hITeOT!Lm6bS~JWFm3K@;#Q* zuX`fP_=J+`VO?}Ti=dd56Ry%Q=CXsMQw7*?R+nQ;OyyfSXru)HfA-!3zKY^)8=kf& z=Oia2kerhfYJkurLJGYZkS4uX=^g1L(gXq_w9us}2-0kzU_n4cddCXVEP#R%3@QQw zqL}ZxchA|~gZO`Zzvq3Qul(HWchB52b5GgX-Pzfhxo6>lcLsV?|aWI zmuBxbwgLSH*BQO7i+|UVDQt9P@Uc{TAYF-u9XsM;x7B+wyJ+yij4lqX5x!jWg0Xa(wvO){&sVmtR6)7zEKs~_}kdo zns?HYZ#M{6X{psG7LJ%kD{yP37oJ?yIJF0(U^QD74TVw<>Bs{;B>&9UTvf#=^9S>d zGJi!sGo!DV0%n<^Aw->BqDoBupJ|1@kZx*3j$t#$LTlBedrh#AyF&X}pMW=hTdiM}NU zrv}oSTdB>>jrcwGhPkWGqEJwv%|4!%FuOI!yf~IpVe7qnH4l%8hW_&GMSCFNTtMlh zLR0?Nx^*+EGpyjp60ZGFq4`6N+KU$Luyze6j-s!=EHKBkgw{Sa|?UxfRmmpZSb zGkPhv4H6ia$FN1UUin4|ovF3+5Mk6WZF82uHe_d2rZn*vg;HeWzR^?KxN&1He#k$1kFLkaWm*ZE+mFf22~Tr3PNUxVc7*|r{o4!Zrosx%{oC^s z-_fdZTt5E^==HOXPD!s3oR7Yo0E0I8sKW+~9k3G)RiSZL=q-Vl?jQU)2iDAK+BKYL zDmK%;HM_x$Ls{gC!!Jd7=RV=DmCUT;V>M0e&qT^9fSa3Wh zUm&?78CT=*=QV#~NNN|B0cF;v)tpe!9eh8>huk_J*2shI6=SjI2;4bX>{)MM*%O$i z^hDxLp_Odd_`0$i{J_HS?wEHPyY7)>TC0I>!(-rGym~sWOM_?L>2+gatsx!_l{fEG z+DR)d-x~6Thlbx}WSjZVh zoHQ4f`5$VK7nvKD(Jv3H39eDmx3dg=p+NrI2UF9X)wRn=3=0>V=Vc6**?YT}JXC%^ zmM5e|Vuiwbh(ikw=AK;q0-Bgq+H;qf49r(#-i=Hvoq0Eo_F_z=f7zIR}wC1q!Or@8{ zbdH`zGcbt5av#U<1#{~l7>`9-McA0ONGpo1GD_xT&ZLeE{nsXE3fNgb^Z~BEjw}!t z(oEkdmF8NbPBapsE^zH_JPPW5q9U* zIBa%Kp7?9?tC49AosZ0MV-*1QkNt%HWl%7O>m{IddO3MBa8t)&RN?9)$Z{~lXaEK@ zFQZp=9h<1?Z_KiEr{Il)x3@ly)hee2B6ZHbbM+^rfRPeoeKUS#W6b2|o;6lDH_uCj zfbu{UgBn;x5!ijqvJmWgttHEo+y=mN@xRy4O$M!zVuM(8VG zpY`O+dK`TFd$Dy2$?5$I3hns}<01IA+DEqn^f*L4ByzPbB3!() zk8ZZKSNms+%zc#h3HTnPw2va~z4&2k?i{l-YkZ&om;c+!%*`WlVT||+hF@{s~_w4=necfTS(2TO{zk#6})Cuqg4K&*mtk$Wx*R7KixxmshiQP{MRrPq8jFFOxcrUL%5JG)GyY6sG8B-E`{u;9^*Z{oyWRd@QuASZsZ zd!pc;!g*MRl{@x&o<`a%nYC%ui%rJCZ&^bo$5r15>Dg)&b2QyfY2mpSlrqHc-NMyF|=iL(HByU7r@ZKl&SDFt2%` z`@~Y!^?}1lVQBEWEz|G8(10#u$wO#_NcpGV!<2s_Ncm^5n5nD(bfP~K>DoWphp@dA z>Hqk3e>(d0elDYHW9a>C!t#KJsr~3(NPWrzaSGY??9sfc+~=mIoU z_@QeH*(&7(G`~8C{@IS!ZCVYy+XQnd8nTMQB)3KFGSNz(5PfE)Aa#B<5oRxB7 zb_dxS*Y+qzar$THYtyRrz^^FQwg+RSnZevDf|LC_nX4Ha|=12BVpb75;+%}&ZXpBK+Y%cVB6<* zkMOIRr%fN_Wya{#_$X=a1wZVmfJLVb?&@`3X7un$A7s>}fjbO7D8obgm_5C(}v$RvP*0 zmwXyI^?b>hJJ!fl=Z6?M>U>WlJF24Gc1B)0-`L1Vm#JmsqVtKn+EI>l8|B9DYGv}i zUCm71y{kU)wP0j_)~3~5OcxAJZJjf20)1bEV2SGNPcyy^$+)MbyI#G%y)eYEg^n8* z9+Q@GZo6`v7}16}M2>9JxNQj2*@#?_|F}{R^Sg-{PB_tGvU8HD2LNVBJ zMsPxL*d?XxPkLjF0I5JYiE9jxRb2NuBa zhPC3-?$&ap-5TiBWA7o6yCjmAUQ$01d#0oZ?$0zmy9b7Z_a6#j9UA3yLbn*FNnNbs zxOWa5#z|1#9s95Agp6m^ev-_}?Whpl&GOYo(Nfc@&UQ{anwEs|*R(Pjzq!)z6Q^d7 z8?9lq^pMh%X_ZsXjO3(9c&{Ekj28ud3b&okth-g2s8y`>-9`U_>evB0FdWazNknHB zf1Uae-H@@8#>D6cc!@c0%+jA4{1_`fFZ>!Jj*VPH@ei@kJdK##&<^;O za?2(3?!=dD`y7S7EE3Ntisvqz2}k7Hk!06KE&sW6*ifEf6~+SR^Rl z*Wf|7@Ndl@K<7apgLZ*l2Q3Fp1C0Q62ekp!162Z*1?208ig&@Rwg&?3+@(9@uSMCZVRrh?{yR)e;KJ_Vfz-2gct z7Y!;4ssri-q65Pt8TmjFAWRo$V2wh?a8M;s7^o`91sVaubZiC&B{EV#)j-(DJ_7^A z85pL{zyLu8W>_=QK-k$W12eT5;UMIaft`IaFejT)859Mgd~2az+kpCm#)Ia8)`PZ# zj)1-b-3GbOqRgOLpmw0apsAompbem1pc9}R&>x^koNEbCHBd9q!;Zd}#y2E?3hhY@ z9jhfxH?!2TCCkOdH}2P~Z@*DB;wq-~8PPX==!l9#dyP)(H>%>0LA^)x={2Gv85Q~@ zJRO%*p<1;H$rX~S#3d&tR;`#=rD9T2Tw?Vam6K~ER*oBxJ}$1o*b#B@ab=s;YgSIr z$3NEQ!~mN+JYPg){sK|a9&d~K znTeAoXH1!zIW24YjG41$XU~~CZ~lUXi=JJ)Wa+Z!o?pJ=g_WybT)k%Py7e!;{K~7Z zZP@tw8=E%2`PSR-YyyLRvS=G#k`zx)15&eb1sul@Mb&)0vsar4%% zx9{Bj?cSGPeSQAI#lH{#{g3;9=J{(d?&*G`Mh_Z3EH1G^^$JzudXMTgtj|EIpGp;y z;(GT>>qUIWLBm?1qD|RSqZ8tK_Zr==ZyX|)8vT&)xUwU9^?9maT7|wthS;K&3y$~C zu5s@X{VNXZmsSyWkN$&(;PU&gc%@2ou~TrRD<)NrOHQegT&YH4)rVZ{f0obaUQhQ! z`u+T=CnZWEkNB>@ZA00DjSW0prlO*JkLZ?xsVq$W|{FkH(UG|4vb=1@Y z&B#AXd%&n(Lx=VnRbiabOi}XHtQsAp*{XG$w(YPbMyJkQ>`nAA z#>R|AvrPw@=7|$01r9XQQ>ILvnwdFGKeDW2`t%w4F%!qE+5hOs4m#%O$6Pf0^XFsq ze&NDJ_TyPP7B61nKbGQHw(L0^&o5uTV#SIVaID0!>P2W<3BehcI5-Xo4hH9f96BS7 zi>HT>KZ%?26z3ltl!P)OL)u8t7EL)Qe>#L-3Iql0fRvyR)6;M<#Zu6XVRh@J23@Dt zt(FdcirzbnJ+^=@*-*S)J9O-6T(=(G@n)sBO;0RBFXm1&Gw!+au)xldmzEr>dB}$fN z6DLnGvWF7vqzuMrNkqk$x5G@@vS{JrB{a7hl9J+>>T;HyzYLC;f<;*o*sM64GdFuS zz11HnzmdK2>U-?nt%IiKkBmasu6osKRi?4m*fv(EFnfJR78bZ-LL5C$Hja&FM_Cq| z&eGU%_95%QIeUaU8JoxQ;>us*CW zdz-z(E};ZX^P<=hnD>!(1nhr`a2Cx9umtvfUdfPdHu+n=9Ob}_#D_d zNP7k9fMVvrZNLThbltB`P+5#nqdY(IJAUa$_#=pUJnsgkx<~>F{Qg)udiu>-n}?+G zuAUo}h43Q}hUMEduLWz3Yhn2GU_;o*2T~i0>v$e%80Ap5&=LCeqnNE&IY{kfAFz+u z$B;OaSC`er^;^K!<*n08a9&U2O`UI=cgSy7FjF(m#VAG7yiM?L0qUWL_cWy_{BxGf zn&oZCdnHd}f9mOM_NUe~?w-F%$YR+F_5xeO)`B~a8YkCSHkAFyCga0m3Y*F@*|+Q#o}GT|O}3NmW&Kfe zBiU}Y53zrR?5pe;yTitSo5TjNnd~-}C_cxYXUo}swvj!}-eLpUO16r<$X4t53<`4H zU^m$g)`~ra*zJMgYzEr{v_To$p^RO?{f-~by~Yl(%}D(tTdh4zq(O z&k^{&inE)@F0y587tn^SW9!*V>>FII5A>8yvQ0>RB>SA5VyD>|c9xxEU$8IrvR`Ij zv9H;syi0lCvAgUyy&m?kE9`ruK8wwUGVmNWm*uc|Y(Cq<-o+JPh|~h-v=yzvcH9x4 z_|N=P_8Gg%en2VOvqkJ#mdk!(Kbz&CI=-Jb6K7-9%60Y&qhH)<>^^IY6}TbTf7r!B zSr~J(aF!2kKqSkLCp!wyw+Ab7W0();G6PqwAS(o|_#&(*+RHe!TqVpi50vg2JHbk_ zcvgy)W@T7e+{2Hs@@OL-WffROG_6Uv(^6O^R+&{{RarGwoz-A9SuIwZ)nSjZRNUe9 z*yF4|Yrq<^MyxS=f;C}HSu@t0wO}o&xy1D|j@Gc~92m;*&(4A3J?tFFpV{s~a{Yhp z9I{bn+VO(!nZWTscMe95ZT``nM6$7gBKq%PhC9hP=zg^h>kI;Z|LIN&$UMw$Z1c3Y z5aiw3|Mb$GB=8<(XbqTt?+QE_0(WzJ5Z$js&|1Z#ePFt)KknuaZFlr$v?#q1-dBG+ z$LlH3dpZs8+y3yMfwyfxaFkj{$j1Ah35wMkv69ew4ML0dl%7wpD;=%dNVIwJNUa@G zNJ0vf_6XfYJ|oaVrXi)_NNGCq+J%;qawAGZdoUCsBXu(#+%7#OBZZNS+Ua;bJ@Q!w zo>HJ|VXrGnDPHeU7~D0q+*B(c=&21yi%!oYJ&P%NdqQVJ?Mb|OPDV}?+h`4pbmH|C zO5m9rjue#cqBJRO#wZu7R%oOrUT>+=ab+IXQvLM_rxYI6B8@8}nBC2ms=b9E*{A&XFx^RP>^K(Ye#o$-H7IEgMgEiT+yPIG7(Y3Kh8!{8xNs2- zHLiFeK0ZDviHx~P^D-7M&X~QhU;hcuWR737SRd`AVamn&ibPjvc)k)P@mZ6GkY)HJc8QUzBeClThU^+l;Ku)ykRBKu2nMUZfNcCvs9w-BqDsUJzYm_nzJ!d23qPoq{pElgh zV8?+Ppf6oe_iOAANkSVGD9vAO%EicmIHNWKx!ZH5P(w0MMl5XA(~bELsT)_(%9Yxx zEWFb!AB&^=X;4reft&*6vGTWk^kVsA1hI1X8lxz8oFr@7!`TnogijgD53>;R90UxprxxiVs zd`Q`-T*)>`LpBhD`d^faRV#rMEgyS6!M;}hhQCoplD7_fxgV^#u_&AIO=(F5bEE)D zX%pzMLaiJg^bg2d682aIZ-qS=+X^w#3DlHP_GccbVZ8bMWeZ3f@_|@J>V|36T|n0I zF(iyw!M;}d|Jnb)ILR!ThNLBL_y^2D-edAGg#SZw{OBnDCgc-Sz zD{usdSn`4Jf9ms~yitmA{!$saJeV)V36$jT?Z1{V4Od~LKc7)EJpw)C)eLr)v)ICR?yo50!+W`hpC-8S5NKNB?1jwIUcR{O=KI-v`p5 zQKEt%vgteu`EA;llcr8+d%I$wI8bpAjUkl;#e*n~QlQeHGN7`cav<7}t~@9K^eCtT zs3Is4lmw!;R0@dVQ=V8$qua#)OaImZZUg;3py!Z??umd+&wPNVXP%x@dOjaU^t_UM zfasZ}IP~0-AEis~!1Mf|O=15XqI@Vm2u^VD5v##Ma*?{m3v5&#s3Qt8Q zdYzra>tJqS2WT*!uPON6t%~p7;q3A7U6`ktgSK}G=6OEC2wFC47Jd@`DdG1JA2Xq# zyDXG94aYPxi{o`Ur2;cEO$FzQxYCKX;#Tf8pNeKIY!*-s3)m#_l7~ zPWZgz-r`;j6yzJ-%iL?-E8JhPS?-2>hPwiv?q1}c2Dz#3>98lbySs^kf}K-a@Q2|KO(9fx@`?2E9T{0O*1VIRRHZX4*Ou-C%Y zhOO7lC2&6*HV5VuPzH#OXJC&H8>N>3`*VQrA2yRmiAThQu<>Ez!p4Rri-G*9Z5>^c61@421s}+_nEJEkPb(8!Gg%t>kg)2Ao zr_lSMmqIUuUIj6B9`q^b4hgZNp@;cra4|MRJk4_<_f6;~aS@USL@xhQ{30YCm2IJ8 zc&Kp7CqywhmTwK+8M+E_UI~3EbTRCgLZ1yy#tk|vbW-R7xMzT7hi1aWTt{e^&}`m0 z^r_Ikd?0+fg|-Xr9ojXteQ1l&dZCYp)(Wi~+A6fA=pZ|X)(;&jU*M0!ziw!1=n}b- z*9om1`UPJiK9Dbn&*ds!E3`sr>Cm|-(QaNUbglS97Eo36N26e92;~>*2#pF=;2oi- z_+8hRAQpPlbsvw>O;?WVg6p#DlIx7?G(A@A3z$b-dt4v64!icc-gmv{de!xY>vdOI zb(8OdtEJlR>Zi83UW5MxRZA{Xuc~RtZ8m5Rf5o*??pCMN+i-Odx$+Iy4cSptQP)&$ zCABEA7O}>-p3!rf?3&^l?Hc8p1gH(i#yI&w5pEgj!kfV=={+6vGcg|6XzM&JDe{&UvzG9 zZlWfPz3yBIdxdkUbC&MLRd)7qjCU+>T+v=}eBk&=TjyNsJn1Oq_yH3M31~XKXe!5w zHO|5zB}1x*w1TSx=tsDc%t8%boH<$US*g)Zssfiy?yqmv8Y+qNTbN(%IR`$((0JM`u~*Poj;p zm9wyH?M!k$>MZXZ>ntiCaW0a#LRLFtoZFnmWjSZ0v#BcTjBq~YY^EAIFE|G{Z#zrK z5ND{fsvPS4KBSyB-+4J?sk6WKv9qY_l(Vv{w%i+X7$tS%Dii=+61zj1y1L;Cwt-7X zpKK*RmcL7vYN68AY*pFOU2WB3@Z{GB zYpwe~COcwVpA<*;uvsDf!n!$zgpCfH9kwv+Jvk~QJ*0}GEAFmx+8VW8yQ9rf+q7*r{AINec--O+jT8PX2o4oEwa*t6zJI*=|Iy$+ByCVKJ z@R@M^6!KR1+udvhqhEZlJARri?vVCWxfu2Q$4HQ&UZiGA}tyn<$|C%P?9!6D;@D@ z#4xQsT#Pk=*$R}RHP$*rbc?93rRo0TVP=3vYW1|~5pyFR)z<6&k7yerlC_TRw<4mn z?GewqcSjtG_&VZpM5^|)x}`=rUUaA@8{fHkTTdC^kOCwt}p zDPmy$;rXZMUoKZ7>zi9wiGyCz$HhB!J@bL48C7EdWxFj47jgB&X5|SI@<6{;ID#QAwJ=S`)BaKg35

qdRT zJJF|*d31-XZpa4yD&qHx>L0asK-W>gQ^t;j9qu-C-6}>O|Q1sF052HVc zJ`sH?`dswa(HEmHM}HrEHTqig&(Sxce~tbv`uFI(XytKw!aVsr`90B|7*9b@5l?YX zDNi|11y8c4vZtD-mZy%VuBX1Ik*A5Lxu>09jPH(6;+#BhQ^2T^$y@kESyz$<$-bcMj-pbzU z-a6iT-Ui;r-lpCb-qzlB-j3d`-X7jQ-T~er-Vxq3?^y2yZ-#f8cb0dqccFKQ_c`wh z?`rRQ?`z&Syl;8m^=|jR@7?9y=RM#(>ix+3srRJ!wD+9%EAIvGCGU6M9B;1oC+`jK zE$3+F)1-sV`|2v#?+5#6w@T8 zc}%OAwlN)II>$U2(=(=T%)po-F(YHrW5&fyjLC?}ikTHNFJ@89(wOBjD`Qs2ycF|V z%%+&PW46ZZi1{F9Pt3uXqcI=HoQOFc^F_?pF&ASl#axNG8gnh?mzZB;?#BEc^JfhA zDPM>$%opJ+;Pd)oeT98-z7oDtzOudqUj<*1uad8-ucoiIFV*+Buc5DrubHo=ljZc!FSo0+xNRK&!=KTVnbuYVJ|5dJ_KDbLu`OfU#I}#^6x%hnXKdft z0kMN)hsKVKO^+QHJ27@j?6lY!vDvZnVi(3Pj$IbJJa$#=8vO}P(m37-7LsjzJ~JdA zMpja^XqW+bFwXLKFjA|8lt?0)Ro0SqSu2+$Ed@x%Y*io)i}U=AZ$R?@v`wY-;5#uH zE0n5$uYy{5mQ~fy#mIY}S!xet?B!V#R!asnvo__?6YRoyGq| zi7N6Ru*$Cv@_tN9^_L<^tIq49Pw}|!PUT5jJzih?KT)#kS_9-Uk~f6e2)&ymZ49re zJ)t$xbDoHtC-bISUES48Yp&Z=PqTQ7|Lyg(g%9H`k#=?DT9dcZTAR7;;cdXT)!Lap zM|pd#16<8O9d+N6h;@p0(*F09tFzVxsov*ZVKVU~%x+qDm=1h1^@N?Ig^46BT=de~ zXuaWT3+ki$$G|^U^wrwK)eqEP8=(7BoOm(tf2r2)@j?E$b&+b4R$mO(o-$KwDu#d` zstq%J+KJ)dM}S6ZqfFl(Vzib9S3fNs=F^}tde{)8IZTYz#%bgKOH9z7L7Xfx5#~%W z31+sK3^PNU0&}65s%64X(v~94=fpHEOPdbY4A4y7e=Ypii&@%iEgSAR+FY3PK=bv` zw-EY{SfDM`7Qy{2XtB0L51}-7i>2DKzr}NYxf4hOcYto570+wS&G;9@3h*yzD@~sq zu?qZ)pw-$M)Ay!WtF41;J?JIvWz#=TyrR9Ty$1INZ6nOrL2u}x;W9~!kejs4+M5r> zTiV-@i<9rbEGf6ZEG^%KSx#<+xeb)0Rg~Mc_jIljQmZ0&Xzyz~;r;-$OZQKOe?7Td z+oSD;d!M!+<^j+_J+vi4TgyY*VeN=^6h6na<1jx2eWZu?KzJ|tvGxhR|C6-OKqs`5 zdI;q{RDQ0V`Wu|~OHD=!N!nE1%+k%7@(g_D$g|oxUFHjIq5KluSK8OQJ4rjQEteO- zUj%)lee3tVq`f3BYu~~3J?M&-(K{YcWo?BR|P zFh_z$IYv9uV5d8thB*c_)-ev|c+dpLGcYGQCiyWLt_;T%$5cnAW11t&F&*w1pqU_) z80KtHHfRoLE@&QTK4<}GA!wXq5zO(9XJJkNE%v9p1pHFRGMKY4^6?z(Y{wkO^RVYS z<~f$bo{tf)6|fgNUVyn0G|90F=2Cp=uXe0)taYqI$a+2OC7a*Nj+Y!S<7?Tt{{Nc) z*1-SYYk&q30_(~xJ(V!Orb+~6s|j|E6%S^+y$C10mEbkJ9%g8*kY0f&NJoYG?WCuY z0F4_mA4G#7pUV0=ai3;LHAEQcuvCV<3@aYrg>7iMB;$L>0IhN(4HiT5MQArvB6tgx z5&oZ0MNhpIzTy&CDu`B{CqP?fGy6&XfNikrL1U^m=HwoSSs(Ni)>zhtL}gnZmEhA9 zIyHTvY4rp``oY}<`cBQTwq^oWT<*k--T=(@J%d$_6S1Og64tqWuZCg0-Ec9>+PGqwsED*gGit{8J@C>S% zd>nk5q8CJ%Z3~4YOXe1?;T)^mPy@LUYQnCCR2n1wnl_;Kz%6Xy@0utgis37x7Qe+( zF^e3)ZPZ>-5hv;*y#{Cx#_=Cz;2M!#k3Vi=9N&%l{z%k^EXApZ^y+g9L(MBs_rOQ| zV-v&p0kb}-W|OqT+`?!4go&1-ljtH6aeoivBl##3M|dmIS#%Yn`8I?$&?QE53uE|L z6LjC;TSJWZ$JsBofwxeNPqd*1FDaVfOeUdJly50{_7r|x97P;* zP2m=9vFY5xZPX@7%-|pUWfv*y+RWfH`79e|`_s-wIp**v{fi}=TS(GA=N4Qd)I^eY z2kFn@&mtyaG4Cgb$t6f{J7(Ho7mUkJ@mI9~6g> z&T+_o$X81b;vVM~iU{k@{TR>7r`!Tv&ku3sPTDY=uhOs9=cw`LaW3=}Sy$?Feu|$q zk;uIAh*%=e@EASL0@VH)8?5K`UEW9ZHF1v@6V_950wpgYEVMN51-dJ)iJ$aZy2tPH zKTV9|oz#!wXOYLh(#uHY%;Odq?Xlp;CwhDz_FyP1DNZ7L#=jqfv5A61gqRqIHje7t zDO%`uEK+w03%hw3X1oH}i#j4{H}2SikQ|R%uCzs)o7WW<>WNu09e32@DCvGaT~eIKg@tN7T3F~}K4bK(-P7Y7 z;q`@u2I5aKME))sq68oEOgRhfN<+8;z_+rn&|eHN@w;9NAMz%msSVALP6o=?T>LCs z=n^$mb76tDg9!kmJlGm00J>WfSqrh7w-y%aAwBe3WE+&-kQf8rLR-WV)n41rx+*iic_)| zq|cbG>n&4Y8q=7@!8o;cBROTN=;%HM6#;)`p4UCJM=s za*Voyl~+cbL^cpJ*cP(HbQ6Q*%cvQ=wZsuM20emAtPz=EL-6xlPrr(TBt6gcv>s7Q zz+0FpW|>$jYazXAYPR@JUDZ=wA!iEl~Xz1jLg-fA}nh?#s4 z_J#^zhuI!byHHZ>w4szZjlNn1`2ntEF0QJ0to-okGFqOkCjc|XyewOXE39Z@4^ zZ8(Qs+i9^zej&=D1v)7{6Vt>OHY91kU`=EI*1hr?;v_PPb6#Aq;Uccb9(+}NBPwX$ zqI^X}1Mn8^ns*r8Ye%rg%|arhI8DTNHk`y4#R8P+d(c#*H$`OF>g#)PMda9UReY)@ zi%H@KF;V1-XT$_C9=wHn<~>b!H)h3z1@zDmr>(ed!)Y;Aj1f=c{L@7mavv>5nRP*R zazos-;g*<`$tt2UN`P@8@D?Iuq=`{-w8YOzMShu#I7uQ=Y?b+Kh?B)lY?Bp51@WjT zArnM-tOhP8%7V8L+}57NvtLSVlgm(oX?zFQPzUz5wxo3@xXpj%xA;2bbCciTrTHmlwUX;ZX<5bu+IxPT|IEwEpRm``HJ;1! zR9R^uxP=XFJeRr9H%eGYTzvd zx1JScqKR?*7~f0ZJ#rU+nvX!OYzJ>4S*DmcFDgk37sUwv4u6|h#`@DY`DVU}zX9Gt z67vDXico1`pxJs*JF-g*mKOGihP(#9!Jd*;`OnxHr4r8sZvnGn zHrEh2)P`ZQ0)G_yo(-4f_y`%z%knbdEi5tbRJvy|Coe6O=A{tlyqGL4WXO14l9%99 zWO4qjh~ve0QScU4nRg-Gk4;2vX`u)&j5t@sRB0ho7UBhY44)>wJXd&7uTkJFtTyjt zx~K8%OAFg&0mQi>vZRISGCz;x@5vc5g5MVTcsO_S8E^$)-KCA>2JA)tF8dqrWXG;rhMKfvPb@N`QyIx?#Qph=Su8Db)@jUh?n=dP< z``BgdckIYDUs_lo7uv8${)WBIlGwBIXSP`8unOu5cne9|W@*8?=R3-Z>U;Jb;+z-D zq=gK5nI)=A>^b=@_AI-I-N?QGZ{c~l+=dnM4E8WP#a@t!YNh-f`;C1H-ojS%xuPem zyLeJs_yjwZt&~^9T4^CueuRCKj2ecxKzyBTmK(9t+-uk$aUFOIZ_2l9 zcw4SztFiamJ8~7xAuY_3v)Pks7JFY# z!|oC_pnLczcndq_2R7`&`4D!?C)FO4-z@_;Dvz1Kc$&1(Q}xD(&>lHN9=Bl_(&(l7 zs1NnDXyhe0)<@7k2!MJbgiri&NcIzH;d8w=Ltm@G@1GO$q#URQ>*G;pnYz?SRo5nM ze}i3;mrYQ@4n#o+H`*$dangwe>;6Iub2pg=h$R(q=n%3TJSq-mOoBU zTU`5_=c@d{L?EABn{2MM5d6;iQT}AZ&;B^qVgF+C*JS`VW^Oqt^h{EFOju{Zc6}0USpvhhm|<0s!COLP1J+mI5k>5 zt|s`?!n!560$3pHD+>+$G7Z%@Xf|O*58Mrvg(R(mvd~pocl#~u)S!a(zB zqv!65a6#)RfTMbxA7y)G!Dw%eq0WtKOr}-;9n=EZO<4$Bz3z}c=8s|3Zg=&(?5ivU zu1!B%+Sa-D!~4r>55m-XIYe0qT!*2yxI>i%jGo(ER(nuDjWF8-Y8h?_sA`xPWwsC0 zQoJeClm+8TVO5(g$8_ij20$SetQI0pjWt^cYAgN}rIdy7W{W{>$4>c-vJkkI6Ky$8 zR2Hy~&gRNcQ%q#4X(ncmHx8R8LU(mf?ccC z8WS(6mrcB?UNf;tZ8q_idfUV{wcW%H^}dNcYOjg?>VOIB4xFNnns*@Gi$mmeW#PDa zN7B8SqCT=Aa94h8JG+mSg(S`5KSs@1ZB=^}sF}ZOt%BRGuhiEjzE$6vwM6x0+!bVA zLL0YES+HvGW%WH^)#7VrtV`+&+PaO(f>pnpu~zH{vxcdz19@Fhxwt#GC<|8YZ&yD7 z))jc)jFqc?Moaa9vS3}Cz3K*FU7rJHte@3Qv^Iy7h1=?miQm*c69RP*z)htz>yVnz ztQ!0p*W!Y*0F`wUf%r)nfN^W#CL*=`CZaWu39BS`luz?%R%z~;X8?T-Ed?6H77A-c zOjxDV%u-N!V$Hm%6jtu}&Ah1;rL@u}tTc<5eiT|kZ!hW0Dqshj3fPGb>%CxF$c9fg zTcG17>IDKK3qo{C#36`3je7*QwOcAqMRS|uaDWr z3C4Pqot*H2j(z%?5@W?tlJ<;$jmIa5`-y)|$64@a`R_U~lny8zk(e=v6j3mv{4?f- z!57w7hEUEQ>noOsJHd^)eIwt;1mSTV#w>XwL1?VQnCYf98Wc0sKle;C|Ku*9&&Lzz z_0J3UgMU9U5avMtjMzxD zaj}5y-Fz^Fdfnb)8!xMEC9ZMw4YT`Nl4J~s3cT}Om$fc zW-b57VFU0DWMi0(WmA|<{o`%zz_*j_VYZi@V0MySVRrS8LiGjT7ylWdl4vlKGz}#( z%0#2DR}yGJ4XG`I2}oMK}{KTWsIHSi^M;+)K?nywij}H*WYI@tO!NmQ$!VoSrj`PBx%J}Jj{51Klc$uC=Z|V$~c$(C<9jL;GB%J zqHkRCIfU~w&XB%r$>*3fzB)gZe?42{`WoMc#uuIO9cFwx8Q(k|6`?co?yS1#pf5&B z`IhXV2zUMULSKI5e-AZe)DeBVkNHwKkCTVyT`s<9oq{t@(wP(~HeYcQL zm>Q-dBB&M%=wSs=n?`-ocL+&)P_ste($@$1#Hy!t6bY)~I6W*5HEq;2eN~WjNz}Sg z@ANG}K4sJ-9p(MCKN-H0)l`^MRTj)Ff1fNHe72eca}HKB6O49lF?<&Ld+tlXFHuWj zE>+85E>q9Jd`>+N^Lf3uN;$Sut8^G|w9fvTe^C+ELUOIYC$(M?UV+amY6Hv-{=U-d zitq+}-cWDCd{eyx^BsSm=v_tF3ZJd&J(%yQoiKO$`#!rAVK;nst9>x{se>>N`ujMC z6~U;1De%WCR@8)17t})~pJ}KSqh6?AN>KfiEI9P+pbG*NBtQ!NPS95`+d}w=+qjqn>eM|ic^H+5j=3VtWOxoLpa3B2rpnHlVHrHN+ z|BJW-uxb_88}Bh(SFB#d^}~uXTqm@0df%M#`Wp3T)Zi)jpHdF^IkXU%AzCQRP%R8* zn3fM_J}m-fgjN7%0WAt&AS1np6nkD|XwQl+(u zFe_?_FcURt_8=+j|0Ea={yzkTe@}G92X}~0F2Cuc>+`GGQ;AwgkL zKq@3sA=wq~e1Aa%_Ma@|_brNR`d5kn$|n*#rpK^Io#-z*#C2o^aNm^BIj`7lgv0~obh8!Q=kc{X0q#=J ze<=k!L8n&GeIo4~3lpHfk`SbuR0;0nAhciyRUcM{Cqql91*i<48x&pze+UVnHX9{g zg-%Wt(5uidstx_3Kp5Fo;WJ89MMzaPUhGrko($fOo$5*5Z!sjE)aC4JOHhk4XO^-EIbAcCOZzWS5zXe109bZd=CD6b=8JnpkZU- zj!j$U4m09Bi8yv`r+I7?v@kOGJoY4Ci}&DUu~ON?7h*Qj!gQ?QpDY&oWQyy3bs%C==KF>pTO%R^vQ_(Yc7jaxR?HT$4eJltQ z(f?S(ez4(Pp00|EVd@7qRGr4^dXAOi_V8R&o5|p=vtSr;uCowvo%P4qb`NC_uWM>Z z5jWI^kN9Vt;{5sm@(Bw0l@%1-)kM(+Jr29XZOqvR&`Gt%TDghhHZ$V1#(MZb7}*t} zy=7qOOwi9W}%(THJ@(T~v&t-^;ypj!13L~Tv?;}QI4K+#F!>e*TMq}l2 znyAW+IHN@$@D}X)P{i-V8p7$KIv*~^VHF^`>=HGwTEzlM%n~*D1jtUu>cRcsEd;cp z0(M755~+L=;(Q_wh{shRgzS0`fF$OKdVCS+09FOR1lxk8$wS<38|H{tu{yaPG}0)} z7SVz$nXFpygQ7q9!5{;}u+vBY{SjxdI4Fkk^7yvc0#3<57}+Bqz;&!O>@P+lwUInt zk;^V&jFSY+1JKqAptxEripY_C%mXN*2Ft}_3@@z4VDqUWSRZ7UID)m20UWn!)*R=H zvAXhU#GCj4qEw`eP!oARRa}z9Az_!83@t1>42j7+QcmVhbx0J4ZQ)~6?~J%lgD@7W zcPHDlu4d`HrsA>UZx%m-|AmqSSBAe~&gK@5AatzwU1Ig8pg4E&U1^2R=38tiA}nk% zHQY|<+~+|WLY6KUaW9C~&@P)IwqPZng&Xo`>=e3MZ0FZxVfm3RVTEqTx<3n3ptnO3 zJNQR>YRBNVLU-_8LCD1_#A9L?&%v6)@8EH{ztpXRs>6@Hfn3Sm$Wr zOI_j^H{y)JdN?cWm`yj!(9`-V9bXlU7CNSxy1wJk|9|gDb^D&sZHvH9EbJ4fiSY`KLC?eXy12gU?O#S#FNBr)l`(ns_j~8 zp4tQ6LNj4UU(B%2Q_VyvIS+BjWe;r$jgA1?LVF+pyN((0X_&)ST07y?O33+`LB}qr zL0V|-g@qR|dt6Mm7xPt7sk9fA6T2N-uxqDvfM&FXF3?#CpgVL40_b7WI3xZe<<=s# z9-@Fep-y6!F~77+^b~fGgiH3swn7x=zBr-mp}mA1eKCU&fL(iMfT_7-XzW&Rp!;Xo!=TY-#~A2*{HcaPQ)C!s0BXn$L7^jMv}Q=u zkW+)Sca}iQ;~B_~gn!lph}K5RSKwDeW=+8_aSwg8dkF z#GR{1E5$DH9JJ-^n5(LaD)31GB@5Cdv4_4Hq`zZnO%V5~stDP&4}dgH65vOgCZ8(O zHL**q7r`hY3PWl=w0_rPo-Y!5#rE*+&`Jwnhp>>Ro{&!H>a4eE$r&1RN<1MYeDjom zj`bgyQM7B)y(5B=r+$MD$~%bjj<~@|$HX4K3;K2e?6qm7?G?>sH1yTqv1zgyT5Uh` z<}#P>hQ>(_Cy6WIE$o4wRsa<0k>B$@;yc8-484@jG7v`gXEt<}-(o+Ei~KWjfs=*` z>89AjPuR5Ih(8NW_RjKzsI5N1{th2t9@Z{#5;|uA)K>3fe}QfMq}ZzKpuELvt3Vjp z#;jt%JZ000Bi_(fIVC<*Z}|06>=LJ;xd%|;kDPIEK0_oEQuo$~9EP{^8IWeEl!wwvod@6VgU)c2QzJN}j z9aFG3#W?;oG*Hqp+dUduDE83v(7Fr2u6;-Ra6SaPm0S>mv2)2lK7jWJZ{Z@e2QBpD zeR&^#QS^rH3hAwM1#iL9+9U3g4OgHe5kQVj|Bm=B&{FBZb3{Ad2K%72f-Z_(;wtnP zEi}{hQ?81}ydiIZT|;VfE9|OGZ|?{2*KGI+yBP#<1Ns#K*tPM9uY&aiDg35L#%?MJ z&@m|m-oh>DV_GQ5i}N^sOOU<@>46jiZ^5p|_p7*T!#!xp2k<9!GXk*d<`Eyueb6Gw z69sq#C#{cA@D`Y~BZNCJ3CWc zK8I}F12~C&jy_{?@>3A$X?zIVf~7@9T=7K+(I|GnQek>xd%X6 z9~)UYxdB9aA1}eS(9EX2(=14Pr-fY44nnd*5J)Rz6{{c*`n5uqfwxdm24gAqfm*~W z$_1cVNNpx;3wEu5R;I=p>G2$uGq4+0MVsbeC7sV=N1;JdNlw-OggFU&b{YPLSw#k8 zJoeKX%c>x?Dsl{V+DZd&!P1K(&eGi>ZZ!7isv=V#z(_WN4P&X2{suT0JB1AdZ=s$H z#sEftA+IOOFMp(_aWcQroU(C@-apsL-n-Mb<^-S z%wgCgBmmMCPREWL!ysj(##kVX>~u*I__vBpXKxC4@^z?C{MqFT#GYgWm7hW;>G_iD z3tQ+Un{MD_o&Q3Yo9s^w|B+LMzhP!b3(?4pjtnzp;w?E*O%h65pxV;VmWPU#Gzo1WO=6OkqNoK? zQBeU=@o^9pJ*cRtpy)wGMMXsqdQeeOQStaV90f%WdN_LjYtKwF<$dn`-TQs_`S3}e1qNNz0^!=@*5i0nN>axFHQC3#u16n7;IW4=8| zZY_PorYCcV>`g*)J!CS=^Ri||Ue=iJ2a;P$->~V)93p#HkX%oh%<8}@%688>${`%0wvt?91d_smTxT$%s9o)$f6{@VYa zO?LswP4A(p2R5aqxwB#ZFx~khw-&;%>B$_ze0%3e(``QO{)HB|r=ANvY5v;(>}@`B z9b+=bce=mRCv$g)TqkxiCz)>ekz32ru<6Mh;$+hezmqff`>b%C*~ttr-QF1hIXkl% zXu9)9ZY@W{rYCcVL8d!@gYt)(Oi6y$*l<6>Fp}w(9=Wyj$@b>^*poSgabHifDMa=j z9l5mFzI-q4>vcBTn_&n+KtJ>Q?Cm*nX)>3_|7%#B?0r7XMJZf^TYh9~KXZueZ9UDU zg&2v@lp6iaA+mSzG?y0Q98=on5ZRk{noA2^Z3=A;VcfdY?Ch;N&85Zlo8p>7WbfFK z%eWb-+2%Vc7-zcSI4=JJlbMvCHI2AkZkT3#qt-A}aBt2q3EXxwOfo-f z+Hoh%FqhQ?=TtjEvI`RSE;2#|CgBV?%W5r`Tmai4iw2)8nKq-FEicUc^K};OvZde ziexQ~Sj+MsH{IQ#TRi6bJLdaSBy(xRdOZJG)7>4q#bds|W4>KQvX@4zXY*e+-Q9T= z?$=G`O?(U5Fk3QlIPPWKa>^R>{ijbLZTVRz^LN~BGK`TcR(^JSiEc2F`QBvcrjcRH z_jk;9iRd0rHmzSxcXvou6l~>;fe>cq*WGl3=hu9?w_}(C-QS@*Lxwpeb0?_t{T;Eu zD2Z4=#)fAb)81tKm*686$jm4OWbDj13dlH_aX}Z6tH8~S3VlQ>^!-4SZh@B>AG8CJ zejqZX@GpgSATnhzlzUl0IWrZ|=TlKIf|-%f=tDYv$W$_O4)pp^=yM9rWu^*Gq}7Ma zXt+lg)G*^OATx%UTKLyOzYS;;=-(kT7H-nMGY&TNcS8Tpc;*^kFoBu#3do$#%moEx zCNgs&bm)*49Wo8fOoA>QN@G$%fSE?<(xK-@=+X%?SFj+&Oc+mL=+c4yI_T3O(+qcW zL4=tp1!Sf&6NP^iT5&jzG~6E4j%nz|X=ScfXvk@U zs|{LmrZJys1?|jCho&5kGqmMEH!rm2T*}N0XvdjRa2Yd~7m&GvnGWd3>41hDGP9Vu z5_)ndzbgx7GjkO*4<@hvV*s79Grv(4<4=Ubydt9vzOm z51Mp1ZYgx>V2=iUI%NI~H)+%1IMS#?HF*$PbsmC?bn86Kd>)2|o#k*XhnAg3n9m~x zk23QZH0^Mlp=}4+JE3*wab})?rky7Wo@8ca0hv|IJXJvEX=YXzka-4%@_nY@S!VtM zeLEaSI(ODE|25FO^Bi2yLHo}0%;))n7noTK4LlsT7Fu{H{)^DW^AcPyK_Ab{%;#lj zFaru`Me3OJsaTK0L?vb zF`u^z-e%^n(B8vwq`?PTnG4>*|97CphvP_-51CDHZ_>5+a2)CLd7qgN3dn3`=0oV} z`LN(4WAEY=h4>Xz$^;ub{sN zI}T{@;W*ObL*`p%zJm{G@`1)n=H<|54d4){l?6{3&`wY=062werM*7 z0y3P1Ob)cI7; zHPS~i-y+y2ax@IZJlayoOmAomf_7AB4T9ESXbz%x$6Ahq z0S^p1gpOxE$6HQ-fwp8z9~cVL$I_RX6QNZI`aq#s2zw4_7ovA3Tl&F3Z!`1^kyc&k z{kEJ6!*QotPJTPdbgroWsny@FDF+RMsl!x~_(c^c;<5KBFx)FwnGX@xxFUzhw+; z(tA`3+t7Z5RS{Z{>X{h}f6{`4H4&PSIF7U-aU5wx;yBWZ#Bt|aF2H}%jYQ@`W-fvc zX-Oijxg6JEnFNCs(GtM_0CXmiZ=)p$!*M}qPYN-gkR=R*HPJE||0hG2633A~B?{ea ziNJ6iX;zxTe5P2Y!a&!nC5r!~X9=q#bS+Wnm?aK_6%tyP63i!IxfllPq$P>}q=O0T zB=j&*=(MF323n}0k*SUOv{|OXaNIOYJN}b?CajUr0gm<2aw-0ko+dJv!EI=3;<(G9 zTj>h;Tw&?J{|@MF;<%a6-2~n*^fzIBgbpW;n+-iqSRJ9u>1xQ?p_W4P6IMm0{pkVdh5A2bu>T%-<{)eT zQQ<%+oOD@B(!oTiwIxx~5=f=P$&zTKF%b+TN>afxar3NE#Y)L5DF!WgDeZX9a%_+m&IY$ zA)IawC&RI{o`Wb->Nb?VM3Akb&4oYNzE1`Iz>ivJ&~-V5hI^*TU44Dl|3Q;mnxFN5 z&gA}RY1aSj2XYG0>=rJE!)>5EtVg+p`4trvY=a{6oS!nb4s`e@9MO%l^Za-})I?jY z(CCb{XHxSd{6NGe+VSg#5Zn=5w{Eby!O$Z&5a)QU(Ek&~JstWDjI~Cia5glItg0Da zTGcSBqSW6|S5Z|_R$oz0{?&Ek%4+M){uD3S8cRo7!q#vy8BbcFhZ=h4>#J(&>NFpE z0D4hIq}8IHo) zDO@a`wuWQz)~04_DiH{Vt&@>=G(Ih2iWo>o;<0Qz<$&>0>Ci#q$rLZqnhaapBFS`X zAZnf58Vgd|)?gqSWf@Spqywhk5RZl1Bk7Vrnk;LYs+cL4;G}rjddCxCBpi>W;=n^F z+!hI%!s<8*wE9;T%=nvSHKlNiLnP;lzr;SY=#JyIx; z4xqTbdITC{@nj1SkVwXxl7SX0CV`entTUc@R-gU0PdEk)#$zoQW=IcZueKZ3 z%Je)u8J~(Sm53z5Ts;D|1Y*;z(MW7+iqZ~*hQ?#j>DI}}*_xV;dA$X3Dr0RJdLdLV zJeATwS+!vn4Fk96`C7+hy@JYA3CvkT2GXgF=}sP0=GI`dQBji?|J2P!zqi?v25oC+o*33Ms0qCFg>DXt}ee5k)7{nBI;s*=)MU+XKK>uklG zXq1}TG|`$aiMOU<8HrS)GbWR*37Shf&1y*BNJ}qT=9!fZDVtEw)flbI`aT|7B5CU8 zNW&;Dp@gF~^3@-63O@oc5B(qc58ahhC;*Ibz5bI^*c(9aUWEM$U}QL51=^z&({EeY zA5XLPTIucP&5jP-qq6LLi>gA8)B`-&q|Kz z_;J-Gp%Pe}zZ!T2l!t@imc}rl8FgsOxN9)L$-6ELl<5IVTbo)_Y4FKfqik+D2XimQ zE5#^4wp?`}8El3UfO3t!vfoK$_xmh{qv3hj1LiaClDuCw%Y% z?-2|+A}{2PBA_HF5Xyz(p_C{r%8a6;22>IJ4v$`JOiXSdI#Q>#1V+gnlGZx>v?DEO ze}j-yKq?CRAr+;4h&hyh*`{2o2K$}y0o>MHZrOWTKc4(f&*iM|XZlfYA>gP_;0Em4lFNMu_!RIq;CaAuz#V|ufCS(oKrLW6KmrT| z90mC0<6Lel;8nnKz#V|OfEj=(fLeeHFa*#Ka16i#*!@v1_XXg6!1I860Sf@L0d0V0 z0@SY!Fbi-aUfe6!W{<~2=D?X0O*Io+;J4(Xh2T@=+2HfKmr^IumidS zFpN9$03dZcYybz~7{KuWP_=B^R{$G*u>(_N2iW-?y#UCiqYvN&fDAYmK>4b`Yb{_h z;1a-%fTe)dfc1bafL{PTH>1n|6;KbD0+`My+NP`FXKRiI(?_lW-tg{Wg|afYZU zqo&aJ2&T~TGsedFuI2E*Nr^9O=c z!)fF}%YQ{1C=yUaS>L*JAf2jc2d_!@s|&|MTAUQVkD$3KL7r3{9HkhLVu@F&5Cz)bL zV)gN|cmgxwiCN#Ocs$XF$_)=U2ihW7C6COeH7=Z_HJikIwLB^PPyq9Il8TnXMl0h# zI-IVIO^y=|PRXWD*s8})2TLf2uO(z^GQ4&2Wb^~=xiktA4aAT31bLWjxKY#4Sjdjc z)%~bf7~yhsKi0l_xoFR(y+>J5ruyk1;qV0u%@1pC%m~;$8;-RejXW(>EmksGD_N66 zYEg4!TNIqcj9+?q0u@QHpxT=GDfPq*=6dFW6Of=%V_VAHthQV?3RMjkR zSs7}>S}CSc2=uDfXjtno7)h;JKN=|1(D3z>Z$)-9G7hvE(ch)qXY@v|Zw2Uw9xR9Q za0)c+bgmnFD#K1H4Gch|nYJHf2x&E*w8C&F=F$k!Hn4kF_Y%+-(QtYnG;GMNO-IMZ zreP>^UMfkMR^NKId8-7$e_mdFG=%{*E)d14J&vCA{Kk`;mE@E>1RyF&pM56K8>$wI zb1KS(mZ5z_ID}O@$#x{*@0$H9V;TPwDK!nBWpQkzAmK(Ot4oKBQF#$P6Lwkmd`x>A zz)m?qW2h9e?o=!jy6e(O?BG(Rkb~dFeDQgZS>*Lk5e;tm^7FSJa@0$=; zvw#2b;K}8UM;8oJ>F}*YHn#L)521RQYVmL`4R02ZE2MYi^wTDjsKBqd5z*FEGx^bI z$5aCTXl|xt^>L%P+!I>;sfL6P^tM%8I?yx&7KZJD3Yhp$e+ zU0UV`zmn3asi-D*HK+ALDo`m`K;^~cSuY zYvE_Gd*pKb4dA~Ynad5E&v9#y&gCWz%Hwvx_E+U_^RC9}%k@}PmxDj~C=xgWHvBr~ zV1~IC=S#5tvoUAfiEw|y85>|DU@h73n};w<01%hwc3^Q{Ta&}>KssyT=B@*PKq!Pg z31RrTh>x^4V&V7W{Um=5w{=Vox0ce!`wqactB~eZIot}e5ypQT$88-7f0S{@J#eEA zOU^_Z2)hLF)|P;T!=8Psf-tbxBHR+>xr6fUjWhuMYmoLs2!nF$fNcfvaIZkzVN@2R z#UUP#I2+-=7WrJXHJ57wBmpx3*8&y-76TpxJO|hS_yDjCup7|h^IWbkKm^nQS^$>< zt^(WwSPEDPSO@qU;1j^NfZqT|eUZzZ1{eyc0E_`N01|)>z)8^E1~Zy^l?@A7P>y?rRgcL|5DN#i>~Hhf)3W?%ksa8792APwyv zd?D4x4TIkF;anM4&Q)+Dps#%t?gyNMuNhTgL`@@JHe2?L{Ru~o$=aGtPPVULo{T#} zs{kk?Y%v)L6;34M>3Bn^k!uR44bMm{l@3Is4HO;kiEGADJ`IgnMW#kUuV{}!M%J-6 z!FWr8<}33wZ{dItPMBkcdo{5!$375J@t3vqn!E{@_q#!h~5<8gF9pSR<{J z+UrQFAvF#BEzqbe0FFNz+H|T?_eiB14D9Pgje_`Mn_VN0{@8$?lSwEZpW2#0_4F|8 zF&0i|9(7!|1g6B3owEe{b#E_le)X8-YA_Bqw8S(o9cA&!lhJF!Mi*ywF#OQR^lD~X zhg|40<`)fAKP_qYR*$avBmzlrv`qaJj3MG(v5c}AfCP!B!+{_gC>R7|#dvS{2BTrH zOLQD$1DiTs){_`wTKp6ctdX+WXYguU!wu*q@!;N`7z&KWV`ZbbT3Ggf@384)AeO=& z$MDZKdd8=b_5^xbX?+SY9?@p$c#!rk8J|oyO@-5)I~_by0Wgk1Ph^4&C!ax@Wx-js6 z7Y1&>HK(wDZZ5bp+OPCB?F`v?CcC~lY^4o{mF@2!w-Y0Qj7IVVGZLO5>olChYk^3- zWO6dzVhyl!c#5xa&B1@u&qlOUZI^XGisKlYmE;>@6fvM3DQK^_GA$!x!+;dohJxgq z0x_$;Swe9VIMxMASxd`hmTqdn=17xSVfnZq7QvVg))Yxb4FFFVat(2aBj{pN*e_UV ze_+)%2nVT_R&Io6@-$P!$yhjQrR}>WeZaQ<77m9<5F^n%Jw>d3 zln)%!$q>mRyiJ3+PgB;*ng&a>*jl=u(AG%GN@-zFj347sQz8(t(1ajJ+#)L!lYLLc z%)S_qvK9?U6`@^N({PBS?G1ra6q}nkE!7-JC}h)t7&qg`+`_GAafJ!kOC+vv66|?+ zo=nUH9M46F1&bfJ2b2+eggf&JGJ;~JyfM^1tO;j~AO;A215(sOj6O208FDzZLuEY- zK~gSjC>~BhvIESGq*in$k>X=vU>t`x!E|&w@}}`f93CrczF=lJ zjviZ8h1VRtbCr~^aFpGF!huB#{vO9&2)FZ1Vo`U0XXXrcMqK5o5$9`L6E-Fm_W?Q zkqj>3d_XJ5DY9(C8Gp7bMroYV>Fw8`MHx5o|G?ICTf#t|$D>AsLA zathuc$r+;ENy;qKjuew7)M@B3BuQS3HHXw!EjdPlEZ*UT9Koi28ayUZYpf*H@I8=DC1!IB zaCVZBJixj#Amy_fL#^{lf}0~)=)y6r&o<&nTXW%d2+|MheL2xb4~*Z=_~#N?yVCkU0>|^s_btClrsxz;LF@ z=_^O3L(vjQ_{6fBo!64#$)NPmb2OYb1e?RbsST721synO2qto3b!Qre(GzThnuSn7 zW3WZ6lOL`E7&x~M)alFV*7DMFs~;;?m~~L(>pvo|a2NniPJ%rUKxfVUU>5=`aN~2! zg?lV{g^=UocEJ7y068#jE9@1Na1-2{V6O+vgL^gXrGUrbo&$R#;6Av^Ve^0>-2Gs8 z16&LDuH3xBtpFTta~oi<1k8eaDeMlw18_%SPXzoK?sC{XU>V$2*vA1Lgu5GT4)74% zyK;a}z{7BFg1r{-DBR0o&jnlwcL(fAfXCpjhdmIm0`B8rbAYSh-ofP+ZUo?X9^VPf zD_jCt3ilk?%>alL;M;F`g(?8z0661Cc>qtqoez8WAGw83!o3alM!-tA*T7y5SOxb| z*z*8S!QBBn3V0gsNwDhy5HsLL!BzpQ;T{4zAMgy^dw$O?+zogZ?ya!b0R95^3fOZ1 z&%Zcc58LLpN0Cm(Bt^!jn_Ok47%bZ3<{iupsl-&q- zpfVd}t2ULrG}IQrEsv134u}0fLux;GsH>ImfcSuAsz zs%u79*4JclQ~|-O=?T_~opLhAp&X3#M~Z^Ub)1320|ht20;id>FlnfvkpG*yZ$HT3v8}#Q) zetv(vqNKE*27(!<=sz_T4Vr(au=@)KKZIvgeZ z%+%S0C%o!hj_NArl?jUyiTi6`@;9f6XW;&~k# z9bI2h)-a;7wqkr~RTcalJOt(iYXU+W*3xlx)?`4t9j9GCp$c~HGnKfLh&T;`&`?`i zURl$CNR%gfLTkIVt+K9sw6&^K!vW=4RXKX>ga*w=3sadaFV)JUy{oKc&oyOrl}L%= zlO8!z{J*X<<%_!$h&Rnjy@=s<>}YawwIj-`q9V$fB8|X3w6GPzjo6{0AtYFb%yMmf)L`33WlrF392l42oM>tKM^x2}M7gSn?*sWDqH!p% zs`}EZbIG5zPY}W;8qbZrV{KE%`hk%yuD3zFpfw6{rx5DE(x@0+Mt6Q#zQ(p6NowiW z)Sy?>{gmutKxrFuxK=;C-kH9`ab?&F#jV*jqO3u4V?@L&^t9n_Fy?W%tu(RG4h3?y zEN^;`dAPC^9a*biS(K(=U?78jqkUjElvSZZ_yK<R^&cR`$r&dMdl|qdf>gt`2#y3G#I)fK6c0;Rx6Sv@ap(t^@5y2!c8s2|EPn3BWLe zEIxRZfI6VO;B!0=~4dkX?u2nkX;(B6WeO$XXv5a410 z1CUwxzB9g_pabnQ*j@wn48UbNTn?Ln_8tTsI?$ejV3rP7!X}ul!&R^euGZli*aSqQ z6I`pqb+8Gp*I_Pff*W+W5jFwsYY67)FdsI-0v+yyO|Vpl`(YD2pu?YG6D-r=LD&Qj z>F_XYg5^3q0-J#LDFn1HAy}cqlh;le}Z#DSV;N9S6!9MjKK6XTPO}VuhS7CG}3cjln$34$X(Xxy3;pE3|>eCU= zesjZ^M*Big7-V@8=QZq#F6L7gcs{YIL)o5CV_va&xih-xnsf%aICKFnr_r4UYG|YT z80V0T9fWRS@U*nUMG8qABR0wF=a*pKXU;tJOGcxyoa^0DKl8+@iUKxSwUB71YU5Ux zHmhT z1+I;RrV*bIJq|25$^}A|L&4F<#qD5g9L>m1G0o{8Al`oB0LR3l3*iD!65Ksv0fQr{ zAC}Qchc;xh_+w|r1`Y;b1Q73!&Z0G}XxP(F2($0z59@MOs-cJ=lxXQgOs3i{;i!(#i*H+^tlJHwL{j75HHJt+H~J@c#4q? z2L=sB5cNmQaQiv^*Jgb4e|%?2n`1LV0Qjf}eS?5DVaf0m90`F=0;e{?uI!;_rKZQy zIK0!QZOjb%0LVr|Ia81phHO2}-TeMj0nMR*|A2(q*(794KZsw%HiSh6u@}%e@fay2 z)r?ax3<1Ii&0RR&0zb;)xIhPe=}e+S{~i!YI)WQ;cTd5H=Y+%&^$79%e|4i6A~Da#$t6nidYC zrA_6e(P)q)+Sxyy$Z~Wi2OrzX?4A!0jKh~f5{H}le-V_+(o4qh!#Y@`wJ(iNV~iWf zHRkxDCQt~|0@I6Fb7aQ?JCi~^F?J_Mnp*X*xo{lgTjM1zMc_P?iQga;NfjLE9d(=o zy(5VPQ`zWfxl`I$SM=}iT#WDgkemhP)5)k8Lb4JRQQcUXIv1t0pH_s!5p;5NDtyo!Qox zXj~IwU4of5x}u~L6Um^SAx^*uMhLV;wev(e*)!$WIaW4zqc7;Zr|b(;+-zaAq;=F} z>Q5y$zcJEeRWiLW{0)-HNXJ-LKqY9+YU;K?X=Z*cB6?%LAu!kbCulhxWDP08oO`e| zih|MD!2%RTQW1!l9k38Z;e)@gtgAV686kahkSw^OK=T1#YwN@TU(;Ho?Eh^f!3u^p zudeaemL0N`EL?fjVT7wHtv_U_y0X$khAAzr^&cuwDe*TC6$o`?>*oFuLEVj`_46RF zwRQ9$0kF=t9IO#pI~^=OrqF}D=89+zJ4gUphY#|aqd|^pau|nPk+!JqKREgeF(Hbu z_#89<;fxluLj*$qJ7@@Feu$@ZQc9nMX;@NuY50*%!;EYryf)9U)y$Z-Gw;x|JH6P4 z#-lxA6L^Z+VhBD<4DHV-T5|8b6tV*!zaP^bJ3Rw#4iT1-%xOqy8WB)#;@xP`Kr|b3 z9f^{e6GOP_Kx!(!gvJPadaci!DaNY7d)nF>b7>a?GTz}`#UB{ZuAUc zh*bm^Flm*j-ASC6eJ?N>ZUTo0mz{MXZEA@yM6g;JHz~6#r8o>F8XZELzmiJ7wK0kB z8wE*@OIw#s7^HS0dAe*6ic0BZlQ7AF?GvAk0{lC03utE~2PdE?zeuc+%!EB)akWH~G0Yu@2$MRDK;T`afbT;k1vy?O$8gASXdg^p`yGv7 zdE*O>2Fn9@!I&Ng^4A!EjLhC2kHQFt?e`1(Aq>3E8Sn1Okc;wpG4|gQcVX7#!+9IEFClm3v;j#p-3CZJj^mUWWFSvj8l7P z!mMok(#IO~?+#-Mz@*LIldv!m25iuW8EpvKfk-Cy5s#tT?Uf{?)7TAxDY)w70`Fk5 zhfU`+FH8ZW%apdZHtF)exV{3OPHZ|i0JDgGaH1bdP(kSgLc7C79NaSPlNBy&BA!Tq zlS$>v_~|m=#Nfmk{L}!^gj7Fv(+l%ma{yGDMynXKt$&17n@$l<`yvUQt>EJ^_~{?b z;1UpYpl4GYZK{T!!9do&-wfGy_~DBYN!kERP6nFjtHf{;O*#}9!O}zcrq8`(?xbaE zQlTANWNU#iX1+6}lLMGc3@`{ofl$#u5D$U|6LIF6)X0*Lrz1*7;CVktvpb8H2dM zkg}O}ICZ0w8!)EynDoV9G^x(d4^79yj-yO=6!dlvZsXY`_Y2u!vMtaYMfoew%~a+Y`FvH z>GZw;=kl;~CPD5Qb}sBiu=8Lqgq;t29_%Av&xY;jfQ$m{3t*>VPlO$XeJAWmuz!MG z51WJqs$hHZTn<}>ZTyDe`FA|1u!qBTz}^a*hrI)~@dJTDta%P>c$~8)u!oEjA2$?3 z#~>RYOySJ(FpPJLtt`c7ZrE)gn`xZ3fg&M)EX|Gh1TXvOHqeddw9XsG*dabO!Z6-8 z>=eEQOy3No?J>nAi|!#t@YIe%(1(l%god(-2=g2rku`ZmnYCjscCjij&4Dxh4 zA9h~=niyZ|(&T2k!#)Dg6M(M3Z1SULN|4?i2{7JKx)hh}qXCphA%OgP1CG&w{7(mv zKdoK#T&h2p>Cb-H6sK1AuhZ@EuqplX0F-wWKka_Hh|KZ4;TbktUuoao65HoK>7U{K;fPSQ2E{l(EASn^u8~ULim|{uXaay z(nj=e{K(G9A(#GRzQ%)QQ#$4#o!@HtP?)Y?7X}U&1GOc2g#&C!ax@Wx-ig%fi4XE-;V*34cJP81Nbd_ zQIl!Xp7#B}d9U|7_Ih5s*Ymz9{O|Lz7TkQIIdzhAuy!BX3s+^>H|C9Zrfd;xk~K@iCi#j{ut`>|FKm*5+qEH=eam(|Y?8T~2b&7j4ErS5 zJnWNU?}mH^$+B&P-41&#Y`R;#0`?`am%!cw`!3jjz@7^m7W*xG2j55qqyZtoD1Zd$ z3&;oT*qB?m1+X5l6fh4k1CRhr0{8*t0140^a2y~Xu;Z`zCM#eKU=e`A&VijEH((UN z0T=@42j~W%Fx%hO?9H&(0hR$40%ic{{a~Zuy1l3X>F)=OV31Q>OY(N~I|Xi%U!>oy zCie|+lWZdWZZx@XGP&oO+>rgtgkNBC-)wS|yd=pzQhQ{CD&Z!%MS}mQfB$bN1K}Vi zH=m(?DG)Yk*7RAY>xg;aGtF_&{hB@V?yb~?xnY-gFnbxozj)tA_gS^q`~06t!oc_q z)9qD<8NO5x{}jUi_1F~epe1JdpGp7ndsvJy=xAd;y67V-*YMGlk3>^Q z%{lXLn?K$9E5`|!8!FbOabFah8P zr~nB-B`5hX`n8XTeD%wRhAZ@62f}MHwf`LnP0nn`&OiR}*VUU}{nu`P`Ttt{4JcdB z30nEsylyIi`I+3O;+-3CK7hvfZGcsPO@N;Oy|D)JfYE>!fDy-qcjp170Wb%#@5}uS z_KyJiV0sCl8W06sYNh*nLvVRe13dALcI#zBFrnbalJUo;mjR(3(4WBDLQrHe)S)T8 z>GV8QP*T<@_?la&`;^J}kNos2hPWq!FErsf-5%iZ(IDIdZ{m{B(;EdqNh|KUgzycK zHVzkVxm0T-2QhS3=PB%V2)=I^zL=W=>Gvs3X>LjYGVW=Ttw%jB7!acMQaXDexz6I- zCzHrD7Y(&H>Na<#UWg0Yt%Ff23eKIGn3~2lWrS-4G;?|~aN`|H4pmJYlX)kN1oRDN z#2He;aaJs{IIfOs!2b%|Gpge%xf*UXo-6Tx1l;s{F8>G6fs{`^cQt57!|uc0 zYTp~)`%X@Rg{$MzxP=tqV)$ z_JII%9qaKnfUsfo9%{9ztasopCBu0Qi%Y#m!=KSdwbrNJwm&@bxb2sNa#1NmC}$95 z8;#VB{yCnd=Z8P_E8N#)d36rIcPsC&jfb$h3`Y($a;SeDxF46Zu;W-AjapdwKQjcPbp5(8(1n3640K_j3jd z`^9&}9b$LeVA~kmY}=2vi=@k?b5NpJiL`b=lON~Tm1X{*L+XmMB#K{uwWD1LYZ)`5EAYe zUKhR;z7u{GL~)9Eu{cAVE#8h2JTGn(KNLR|Ew zDCKhHAIk5_X?EFOY9C_{*%S6w`}_8}r z?H-G_xA%1K5btR3kv@m-O5Y~J`!Jky!#bXSfq#$xm*BBIZmW|Xlm{rc+NV1nay;#L z0j>Ow<3q>ij&B{gPLDI-Yx+fJ<2LYgSGN>@lXNQ2x^Pp;c>KAy?GZ=DOT3b;}h`5X;0yv0c1bTq-UXpF;n9ReW1~U;IJjF?OT2lx>#nFShNr zf7yPwb(eaho{Cf>1*9obT)Ip8i}a54y|i2EB_A)JCKsW8cG)LSKtFy%eqa7r{-^x2 zT#On{QQDObA~YFenD1?Yi?P^F{m+zM7xQ|B1h!e~f<`z3nx$-uwI?yi2%9NDG$= z*9vQdox&f&5n_MQBaXyuG+w+!yip{`O_qiZHc*-`2#>L7I#X09eR zs;*RDQQuNOP(M?@R)0|crT&hY%;g#Hxxur*v(&TP^O@&3?-|~+y(7Joyi>fFdS`q8 z;$83E=>5q1h4(w}kKW(B$NEP5lD=zw^L%&v-X%PB5dREv5ByR5iM*Y!;wSJI^E3FX z(94(eR|yXYFA9GZJ`g?^z6FMU6>`LGqE);=yh6NH{1aOLGx0dv$+oj>#kMkAjjh?1 zv|VAFV|&i_k!`oFk2F^9r<5vRD4*NEwV&lEag20SJ1%leam;kw%trR-4$j%zdAf6$ zbF1?!XFckibWL;3#XNdDX7-0&&$`m?%Q24&YNa|;U7$X!u25H@m%gHYr2e56czSpW zJtv{JwtMDz9>y%Q3GKhdx7D}J_leS>TR>d5i=d^f%)U&tTF_vQQX zR=z(!5PgH^CEmfS{4l@3&0t~$(FN!OLA@1I<&Twl6=b@|+*+&kS?b%5$Zi&KpsRbRt+R6J*T?cO%; zqh6XY*Ptrb@W1df`tG~JgW^tcknJhVCznYNN}o!D<+ywg@_rSg>F@Fm`8PRV>8tcp ztV(}npfW_^6-jX@sxnL|$GTCaB+x!%&?`Ia3+#Wfe}r=0=lI6a;ryp_2-bpIU9Y6=P@Z3Wr^WAZuvW&U-H!1wr%`OmQu{*(WS{}rRLKsZw9E%Xsi5zZ6@ z!GTq=N*IF?+9X6#)60c9!tKIh%(5$lRhVaA6E2z>*d>y#+rJP?KIl}TM1_8 zO514LILy&gY;Cp~n8mKM%|rYC*|x&A%J!1&P1{D>C$=vzcmHlXLh31}24cbAWqPh@kSLssQs za=APTJ;yKCV-}n!Pm)7&vm8Y)N`v;9A$Q2L66ZIrKX^fT` zo(|7!&m7NOjGKj?MV`B`QZMx^!wj;*v(mHLv&OU5v(B^Lv%#~`vk9x^7SC4CPS0Sk z(_8JW_jXV}TnoV|G-&}wl8t|r{|_G%W(yAqF9;ijZsM8ZiI@{?Y`qI%R*2dXwzRDs zIPCxxHODp=cwLB<@GjdD+fv&y+r{!j^7rzQiWhw{qRdw2D07v0%0kSbcPZZ}-R(Dl z!aCmhAlCg~ou|3VTn(;!T+h2UV9bc_*WI7HbJdenMLi!gL_ul&PwMvXV95&Ugo^c`Df=!l=5xo$DpZxcILVU zxfGPw@4C=61vA?mjP-f0g|0=eyIf0LOI^!c%Uvs6D?!7q0TsK>wH|fa=-TAk?AikA zYn$sE*LK$q*Dlv?j6u$w@9yUA=`M61=k5!-%)X+Cs<+bnlJ{qCuCIshIA1?sf8P+FQ9`3|gRm51?Q`KA@lx?N@o`Y;KZz&Xc(mcGwmn$k`$<-* zzcf%9f>lwHvY4xq{8GInqK}`)`sfCEqr6G}QEpdeU}dLPzE>G&A7baRt~>0t_6B>l zj-q?DdyRXodmU)_58YecyFhC$QXjwy_>#I&{Z!qq{-z$`ISzE)a8C{Tcf>QzbCu_2 zMscq3yn#OZmFFiK*1S_m0BMkRSlvAzEgW*)jiJB7jwvso?9_*JchaAOHXfaA7HW(xVzf> zneQvY3r>@k<9|JWK7YUPFm`!G;ug?_r%9#K4(SB>OnHwiC{vZS$~t8|sJx9RNk6+_ zp8y)~7>DFYI%YYpb1Zb+g>kmrvC{FDqnndjc+nuKup` zT`^ay>l2sPeXe_=dy+eZU0~Fmz^-L6=7cv?J7%_LJ(b=Xv?EbPpL&P+%6+4JRX)G3 z-baF5L2km#S__SDItFrAdwZk)@TYF;mK1m)Tdog1-Vve3I|5<)X{;RxI z-X?zoDsYFqOWuu|{S7qhR^=DaefjoF9rrl;I0vHiyi;;kIsMLh=LF|O=OkyynZ&Gc zlPiRBw!3GzJKVF~bKIp^{jXLZSJ$XtsJ%VBXAFAyO!Vy+F%KW(bpy-ac(;3Zcz1bs zdvh?p`}$7to#`9oEB3j4=laI@#`~ImF<;tuiSHgzc^~*b^Zkd~!-^9`jQ3;sbNMNt zYAy#ob3H$gUxU&9CjSoqfxZ?WEA++Av{)z=&Jo57R|!v|H~&-kO&B8b=+6#O#mag< z_UqSS2k@-;GWIt=iG6HVTe+>;b`ARQ!=Of9vb}5j!1kH#@3tRoNAGujm@2iQSKcPw zFFhxHh5nEyi=d%~$>)Q9xmKPpKP+#S|1IY!rzpdfi*e_1Iais9cNn??vnyb}5&GF7sk9{EH*cd4%gk*IBNsus>hw>bwpN zar4;OIozsy7@*r74yH#N{TrA%p--^0C4BF%c`8Cw&E6n#tpgyO9`ji#7G8S#wtV~m`P;SE7 z{($n7^0M+4>iL!OJw{3odm&Z>zrE4kWS?%o%0A!zhP{X5B*&SK!H)ACjgC3kB|YhQ z7W|9f921?7IiGd@6|3x};8;BGdfD|KwCZSgo%>exQO~y?9%ExP#=%VAoz(aJIZWqq z6Z-tE=@(}W^nEY`JW#kJxl+ZIsq-9XU|!Jd z{*(N;yg~i|wc0KB1T|f*j8V>4Y|itXQ=OMPZ*@M3)&E4$??Y8t^#K3X>SFZ?%syXW zU){~K5qs$zt{Fllwb)&x_{*>-eTmF3jKw%g-PH8HG|$wfZ}ZzW(Xais^$oD zg?Yk4VUci`umo%IGGRGr;FZE^>{{0f>xA{F#l}u6&vs#luuIqtJ_IM`W5?DLwDECb zU$GzdZvDl9Vs<1C6U)U>VwLC@>%|G!(@X-_t67YS2{DZw{tU4LJg7P1TydVbP+TP5 zB`(39e;M|DE5w!JYHj*bi{5Xw z^|uYQ4FUBa;S>8RD8zExD9o~cTRryK6G3|)4!yV>6!}W*$k*7`+Sb|D+ctnQ-(=g2 zR@{mm`Zri(%(M2vSI;rhc=Y6pu})r%74lEg1K_MZ4lczD(ks#y(Cj;;-=qS}`TgWG zL18RH;sPJb&fv*Q;vl%PExAG5ij$%=cR?fg)s|5YMT&V;nW2SPA za)Yv5c>?p-YplP2u6&Id>^G&C{aE`zyUp&lkFZyv*Uz@k1%F^MDEUY2Puc&9-e2sf za8x-iaNOv4+3^N=1fO94_&ZjUGn|95nv8Oebzb0%IcH+ke%QIf`5M;5Z=C4wi5xD3 zes(N4RyBMJe0l26WvB^t4ORryfP``2zjq1kCN{pzSZm*#E!3O^I%= zV$|oMD56E+NG$<3b(yqWS^@fKwX_C1wsoMBHei09E7irA-LA&os8YySkhx8LlX<4DIT;0h@YKjys2j_Hmijt9ZB zUFrA>dcY>^&2ybSomRB{80Y!U7Uz8Dz0PHr3s*UxbH41{;QYY(x$`^cPuMBtfS-GY ztI~BTcnm$j!Trd6qB=r77d(X*)lKRkPpM}dc7)G*J^xx^!1v)7^4AFWVE@-!JW2c< zl%0xzhzo(c zh05c~tI9UzSB#BPjEEWbW%d{C`QTqmj;Wvs=U^l(bld@~JOHZj3CC*3^Nw{G85ow8{`APX1P^G`g$AWi!z7kTN zM88zAhg}SQ>O^35rsHYQp);_{IvP~|T(!eD8~en$;1VwME%Mz(ZM`Cg+YGA}{L{bl z+xY>YY<6OWIYK-eGlz;5qz*LUBDi9Pg5i=DgNLh*V))x55ewkBzP1TV&AqH{dYNf@N?c*y;Z(i--W)Q z?+V{l;Ar3Cd(5}W_Z+A>RA_Au`~G`A-y3|->v1Y`49;Y}5PkqhsR0-+u>B@+vc`?? zj~16@k6a;FW9-xE%cb&_pm!F_Z-UeI3uyjA%mB|So0LzK_dt>UVL#DvnuB*#I>uuD zZg#XgE_Ymwz05-x$?u}C{_Gg#_yCg$FO;dS$8dhO%2Z z0`qGnX4UKL>%d{(Y3~lYvDoo2W{4AQc3b=XmVF?BFL216M8Jx!&{KKHRahGrWbl-n+qN zf0FvvjvTH(_FEiyWJCF#{9wTg&gDxuL&+156)V6OxJA4}blH5MuVdK%UxOL*ZcsKa z+dj7a+cpOL#4DuNz&G51UFYwp_ZYbioWL99zMzrqb|1#?D6A!|_B%17tik%R&c5Eh z!M+i^=FRpqFuM#v-;*#?-Vb{DHOB_bkeeJk9Va`hO}o!#XB3>PXPs-&2iIfuIN5b3 zcvb>9(yLvsxxRM&6WpgF_fWUTJ;9x)c2kRhqf)FPW3jWCs$L6z!1Lh7DBv_+;rSXT zo)Pa=-UYzG6WC+F=KU3?eJ5d0TIy@`MSatJGcd2*>09A@3LL0ceed}G0G4vO)xgn_ z{PEz&pAAmD3smtnIIWqF{_z;UiYKaglyDws;+ewT?1b$N;UB`kgzjP=%+Gegj-Q8p;-l#Kdq7j2=eX9f&G8+2{W#|| zter19H#rNzi@(kF5_lft+!wkV-A(R`-EG*9U**2Zz0kebeV_Xg_Y>ery@>PAjaW-R zbARjpo}Gdoq4vZX+R5lcX9GJ6FJKS$ zw)!{q6YL7Mt2@M&oaaKt^ZG`7s%mC+uYa0R2wiO)Pnc&yn0B-H= z-~-$bPVM91(^5Zt9X#6iz@h!z)6ILdSN0D7pWf1?YDuua_{{@E!=SEhXo}7a-lQx_g-2!gHi{J;p1^(fOe2&ly ze1vl0GVEe*5dI<{!rEM>i)0=+pv%DdTnmopW^g*Wjha90Xo!bK{4?6aa690S{?QYs zHvM?>PGydJF4|=gM)Feka`y^0l8IZm(Y?vN1sua~a8|Jk?Zc`0XrDs0FZTES)q!l3 z(-~~bb2Y~Edgn&xW}K^OXZv(k-q&Syt;Oztqe@&aMCS9j<0uX6IgR}$ z=g;GM0^jqn*Ia{r3vcA0!-sLXL{CgD6o^S64TC320oV~BTANWH3v9B7U^OjY{v8UP6Z?6Y` zaiV<^WF(sHQOHSjV9zxNyRLcmh4w}EyX;HsOTi7T0`(2lbp5(8(1n3640K_j3jpg!C%4f=kA zfkcDUAT;m|PF|d-`%Iih{uBMR=S-~C!`4<**VI>NFNzcR{tWxjT5c}K&pPpUOZT&{ z9(DD_+g!<<0xoan4IDr7+T58lxpk|4tUZ3soU11dI^moPO3s}>^_uxV z$@LTD@7_@^YOJmuBVGK`rISy&cKs)3uba~27yE~c((`{=@aT$FZMW`x@SI@9$l|F- zE*O38;JM#VIOqCJM{GN3$nIGWP5AJw;Xe&s+xqDZ55IQfDR)Gxy4`Z>ryu{&^m+27 z%9j>TQa}IV`4jF7wnvV;^pT;tXzHB%X0GFBzQ{|KZs-;T1xMuMfU`Mp$yrPKUwwui zF_?^YidT|OrG^Fr#qj4(phyEKiJp89Bh$QY{88k8H2LS}$MU^} zqk&e|1uXS-rNU6rjAeACyjjpu>wo3k_5C|O+t#c9OP`+f_&vGzJTPl$&nu6gY40)X zs39xP?-N+Hx#0IXAMcz$|H*MD4SV1p3!Zm4SF|eW|54qQheNr(e`6;5+E|ipEJfCL z7+V_}vZN^@D%%)?IhN6kv1Oe!h?1l|ji{rPI)xKqoRE@o(n{INiGyqU?{;E@?k& zJiEcay-{&T^+gMz$L8w!#uqU!Clh4z`pK021KYq=7ot4)&9pXD1Dze*a%6rSZCD+^~!|P@yF6FW%z->V~mUV}tLawH_>L7{=}Ju5d6KHwNgd2Os@;^x1I~a=Z4qtjAA2549J^7Jj#6 zP;$msNZ4+Tm4(po5(}Zl+`%UHU^jFOo)}KX%0P?Z!-8m08wSmf7#0cdgwC^v2wK23 zh!_N3<)1FCm>xKkON)fbkhdNoPOu0EYI;QE_LSp95+ zV@HLc^bz&A=WDeds6-E)#@-owt*-FA{+b>B_);IX%7I?*iQ%}h_+mdq*2G59&fnFy z7UkY6NsBBQt`vXUyRnTu6T~i&S#>S-w;S_}@f=Ei_J3py*mvd_LkJQ8=;lZ8LDujw zRn$sQSvO_l*hVbqpLk==SH5-?yfv3aU{6(E_9F^G2mnswQV8(OLIv<`rg{HHqQwA( z07o;|$LgCHe{Fx5NB~be22Txm+_X``rpFx9J zR_A`-oi^`|8@hYemYphV>v8{FQ`(R)(IS>NdSq7j;VKtJMRTo5OGk)_;((9#JdUli z^S4_>ceOZ>1I(437&pJ0G34_VjDHkG%^(x7AON8T_z)tUjxok;X846rNSMtuN+^*Q z^DSaA){KZCD%cx7h8t0FkQvr=0h(~rga^&!(*JM<^CTdOmRks^GzL8aLm)>)QE9>0 zRglHp6pdWTv`{*R8h~NY$rxe;2KEp-h)GdVQQw9ZS~wA-OTf?90`8 zH;SkF1GNC67%UcyAP5Hwh5rrwHC4k^2_w4)yUjMuAf?P}gjzG>PfZ_8R1muvJiN{& zv-6>nJ$l)|Z=~2MXY%mF3#%qZ51rJV84q}***-aOI!wXBwCeYQNFfzPbQUJBzjZqa2;bhVFeBb$vvweHAK_)%MJPAL*(-LF@ei$d zcC`h2mOp8`ko?K#-tJ1$so&KgrJ!XdXr!7K6b&?wdz6Y`m3@{984Fuaw)R$$CV12Mf z2+AX2MZk;g{0KRvA6XB=!dFp6fm0wLBG~FIuCalw{~{xRIyUCQAC4se{&J8EZxo;z z<^>HB`K^`!L?A67JU6*@Kmodik2m)u! z4P43+C^?jj(1dgU%{XU( zTY)P#Z`y@yuH<}22rz|}tdzg*xXW$Y-)+dM@Qs7@fnz7rt1cTTH$`hqDJe)M4hB^j zwWXPNzOa0lUTXOZ^YB>V_R2Q~%O7^eA;Q3$j|v42O4|!tO(`vj3DnT+zVWzcbBW@F zL`Szl^1Y;j5SLBa47a_N>f@~g){Hbml3Tor>-OAjO>Ma3S|9KCv1Ne1#()%Qo2Rg) z#rbcG z0F@R-Az~%Csv794MK;7p3Z18vL}cXf)_7Ztt1aH1u*qqYorCQbJ&cnR9=jG=4PQkR zZDKrP255j#18OX(BK!BZnAJGbGhG7p}NqdeZtca3W3^@hSHEYV>wl0^E$vqPFS ztezcWK&GGHP}({qWEo_)yN(K^c!iL$%ck_WeZxq>0uS(`x#6TNO{n7R`K) zJrKYbDR3y{7hOv8=JKCUKsy>Vn3omGPR}V4CL$4#(k_sb0_dT+$;dbPgJ2S51$U{U zEP!!L*v4!u%Wz&~;J4t7LH+>Y^#8&yU%I#?^Z&zcf1^~85Q9fnfR89p;D4BXS@O<; z_*uq(xf>#d_-$nTayR;L7l}-RRN*zzKrMmflK!5{z9&kQ6v)>W>IaG_u889UI_^6J zbMvn&S3WpyR2VoB&L(Jc%6vvUBXKt4Gl_cE+hcnsuDT2f;*yo}Jpa6ze)+1ET)fX< zwFg`2r#*VPvt^D)bK`?_)5@A^%asrzTZ=Ep8D8`|r=@^#uzu~ysrd6#bpNHLIm2{o3+Eu9Z0KVdMJt5xMSEz$#MuK(|S>vrO_z&sXAD)YL3rx5u$5 zleY(A<%uu&s-NI$wJl3EN zJ!_QcY=5-SOXan_iO=}l}B52tKh~ufWa4Kys#aaPr!Tm_|R}{b%KCm3(C1MyCP>JFyI#UP;IIJ0j zHL`$fB=b!y-2B&L*bgb@j_0<#amBp|nNq1Pl-2WB?w5bEwaQ8n6MbOZ)+XID%Qqq-u0xUQWevz6%=hPcH5`L$Yn8X*Iudy2aSpYB92D-6*3=r(?ic#e< zHqbaC;LFtl0w^GN_#jgO;rWu9tRMQd+h{EubgartK1xdmUZYgCEgoFXb)ihk0@iKAOv#7^ic_Nm1rFSI^&W}8&M1gMJ zpfda@DHRFuB1iaDhIH@?Ug`J^wEbp8)OIA|!=&4VT{j0$v>x6$mIt}P4md!kaz$_Tbiy3g0$1psY0&6eBa2nO0L5iRoe(^Whow(ivdl8o;zpdyYnczMV zz3Z>7vQ1>5Qxkmfo$L4C-CJF5XI<6Y9FhI(zJ+sc;kh!q+L6}wU0LqZ?~F3z?pY46 zYe%U$PTt0+IZ{2FWIk?qaN4Q*ky}_Ze~tLLv@DizW#O{w{wt%?89NDqSMD;4p6+*> zG#eaUn>Nzhz4wz+m;uq+o>6*5Pg(n!gXB}$QBC@?)y-*Qo!U-h*IDn9%mIZ(gepwmYoI9T9FX_@idTcc{&kz3rrSwd+WLY+|ZY%JXv)xq$}GyKole);BX#f|kF~ zUmW_it zwk1V=I}G`bSrnK0(CdVTlBBcjB(ikS_?~P5Kerp7E7zPqzh=2)NmIOEhOArqlS8_YN*1O+O{wfEA~}43h?$q z3>D=HzJ<0dq_J=!3JbD~AsMgqt)iI44XW>&Hu}ym#gvQVzm6cFN`*>JDvIBk8T9A+ z98!n;I;j}Cx1!3l?*^G|pO!>&MoRXbX1@!LBdR3}a!Y#0^vdwU~ZIr;tXCe{+LB=jjUI5EP1cO6?u;By$mE!*2JW>!75Sn`k z!Vju9>}?>A<2@7sW)S_-5JUhgeCb()m7IG@U<68xCMGx#@>CakQP{;ODV-?=(&2uK zK~4Y-nS7l;=&u&=usO9z`r55}r5#d{hf%#P6_g5LS(S{f$^(|~9lgfo)-xh(M^c9f zEt7temlogh7XeNaa_ tYG`+@w-!VF7VU0T^K02dm|@Dh_Dkx0k>#JQ^z4c9%FV1M3|Cw5{SW!#GfV&g diff --git a/plugins/dev9ghzdrk/pcap/wpcap_32/wpcap.lib b/plugins/dev9ghzdrk/pcap/wpcap_32/wpcap.lib deleted file mode 100644 index 3c08265db78e8cbb17ae83e70a6fffcd459b8cc4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17658 zcmd5@OKhA)5-ul@hk;%53a^k%jPr0Fjvq6&^R^um2ysjZ;lhDGHecR_ct~+J)SR2PmSkY{;1AQOc!*?)qVi@8^ErQ0QP(gFnA9j ze^b*h_(VE}c}XITwEr7LW4{3in*Bsk;VOWjLzfhtm4p&i8S$ynnv)6G>>fx+Kc@Z zv=8Ma;aKfMn*LJJ@Boev(($sQqfNv^I&oXk$)5ovy@yXhC@W|m;t85s*K`k`NOL6Sl=9yHz5!QlgWj)kVEFYDsFE3XsHAj$GOtw_5w~UZZv(jr}yH>9)RqLf2 z8qwh}$yQ9#;V?-Y4;)Z4G-7P+Sd}ZSMzLL5(d9PFWSU{ItjkrBl_BO@D{L;UEiZ>n zEfnD~X+0hRYtdyf*;@FHnHrU3WvzCx-7;t@9W4#QcesGea+$EbT&cGCJDWU{YJ|;Z z-E_-jSb3}66u<}xUwNa_kiZHpjL{O`%ts!SpS0g5qUv7qBsa`fs z+ANbP7u!W#t!9zgER$)~ijCGv-OPf`GMP#%XuVx*G(xjNID^Tp7O&Tv!Ft$iRq8c8 z7!e+quGHevE{{p$#8F>mGE!EnYd|3=GOWD3hH67>YAwR@Q7OK0rC5CTO7?PftwsAu zG_M(v_84INjaZjdo6&yZ9us>`H$pjvfxK0_2q@=B)XI%w=?1C5R%jU!xj(IiYhh5V zqGBSNmVB|TE|Qt_jRkd+CWozjr0-YFv%sH{TuA4#qvx_3}s-ft=ZU7CX+{e z61OkFSWMP58`O%cVSvjR_nNMgT$EH7>xinNiD+G?$Ws?}d#PDzw5_Elc-@2}!CIY=o>ioxV?iwDI@Q%>_ru~w#&LPA03p7bPn(ysx)N4o$%-UD!N z5a4DW;1{Hu$MA{t&3=I2#sEH<1-M!OxO52pvl9UCq5rfv4e;S4z?)|Q?jT*C0l0e{ z{ib>JL9x#C0e}yX7DoZz9R~Ob>s%iP_zK&}W4&qg2X7;NeFPwfzTYoMUts$;@wo}x znnTQ`Q&^59{MAp9a%TXxO#$4(_P<4$L43z8M*)67`fLJVC%*gpLjZ5>1^5-8BS^RK zeZIo{`}^>{kiNwC9>Di04@#EX=_H7>0vz2oA#q*awfpQP>at@G|@Xo`Xl>F?bS={a?S^W;{!F z>{IIlan#5roAa23#yzd=yV`egn;SEwal`w2nmt*Y#_bGwQ%nbVT%}a|Y&4d8G}lg( zt6&+DsUzZbrF86squdf! zTQDLX6+4v9qu81f4BRLp z#Kh~{xLcH~n|8$04$lcOo7fxKBd9qrGelchs_JuVN~w(MC6>jG&sqI!)|#lI9NJ8t zb7IXzSJ*vZI`wpf!R48Qv&&_^Z=^tmAY5MJzH<)Rt~?Jg@)8P9ai%94=!luXonkU4 z(po`o|3sR(sn+IkYsc&yw{VHJO>TH*)nuM~Q)J0hiHZwSxKA-RyrUVwg&&Dwd6Rj`8jN ziF8Ed zgKJgABYmo}(K{BqqwGD0)tf2za`Lurq+G3P=lb_DluJ@wW8g}%*D{`X(b{n&@T zD*A>0Lf7!2zAc#Y{P6A)-ADBJ(tn#}5ef=f@kc)CkzVnCP%=^um)5Qgy>6gpFj2++ z^WO{%%#8?_t2l(7v-&-OkAI-t9W5*RI0K`1v>ZkW)UO{O_n4gE&Oq)C4jB%^c9Dhc zG-(Im@qw+#Q6q*C0!-h}J$A8DYSvrz<#z7C<>B1I`Na#OTI}~Qazsthf|`-7a;P7a zJOY6kVe0Tj@8=$X`}Yl+nL+Vpo51vU2D>OYD~2O`CQvpTPF~0$!^#vaNANLBLqE|L z-fUA|U@c;<3om+ucEEW4nEp~j?0`*j2jFEnzL)&`@sj&7C_eGYL`7GcNZnKx=UC%zIAyK% z0|JNnBh+^1GvgVv2PFz!j#-e-$ILVTTLcPoqAU!hGLBdwr7yd2X0{5HB=?L!pz~f$ zCa!)`n#3xaeVXiP!z}b!4|Ib zc`{};qJ4y2df4J|7rPfUW1b>t&mh_(gl0T$J4v0dzrs}V`ooJGyu~o<&mcLW>>m1O zZo+br{^1oA-nGO~6Jib)oKhM0fv?8{sn{}_K~SBKbKWzfk6Kg{DCq?$MS}?o_LxO- zjdADuA!Xf&Q^n&BioSB_rAHne`GkulgFhCEQW@7q-qWimBS`XYgaEo&5gx1^5iA+* z>IKU)f={_vGLmMYD3x^tJ*)3&LW)dN=c{ibS!+FotM3^H1;c;Tg)Zi3IvHmt;ylZ6 zY-G`bQ7Yre`7GLVNmwGnLLeL4x1AP`g+nbEr84%-r~RIHu;iDh)O_c?Dx~Py7jVXQ z5mG`7w+GC;XEpBTm?Avf3rA1CzkK_7h+#P~egf&DZyp`Lm*JV~0}Dl|tUXKd#B#U}_r;O) z#RQ?)Eszl}@9Eioi$_-;{~e?Q5hQV$(gTvmP7ZS<9y00JP8L$)G9spVkWkzkpzizR zLpx;AoV%s&(ej=VJWOcv*2;ox=m;KhQ0y1t7LHO`SGvc09*LlF89*yD2dpqh<7n;zsGR7>LxO(gb#iNzR9TfGwiiM(7)>Yv_nsAZC z_d={w9V2<79C;VX+{6+@7xUz?#sxy-m%J8?Qd!5)b4HuASnB$i8tFW_jzW)KmNB_NvnbPGwTj5Aj7oHC9lB8r=OLb0i=cqua{ zBEKgR@Z>iD7Or!h=sEYEBs}(cK@V8Iu{`Bq@h=xFAf>X7Wr`gWtL1b8p7|z%a5|qo z&uTf7fT+H<=m9Uq7ZZNwOadN#$6+BmUojr-Jj*cICnCL|rOctYqnhJr^6L`|M5&Bx z#do?t%W-1IkdBc&<2TQd>=!cx(S;@OjNgk6n)v9^0#PdK_<5}8IgYatzPbnNC5}b^ z1x3BFJKI0QTK54Pt6vn^Ie>xsl+|@D;7z9Pi0{!m2vcZ o{khiWdHyG From 447d7152b5fd4775e7a7a8a78366e268ce65aa52 Mon Sep 17 00:00:00 2001 From: "ramapcsx2.code" Date: Wed, 20 Mar 2013 14:07:31 +0000 Subject: [PATCH 50/81] DEV9ghzdrk: Re-enabled the stack init hack, fixing GT4 network use. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5600 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/dev9ghzdrk/Win32/smap.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/plugins/dev9ghzdrk/Win32/smap.cpp b/plugins/dev9ghzdrk/Win32/smap.cpp index 54d274f39..3e1d1c8c1 100644 --- a/plugins/dev9ghzdrk/Win32/smap.cpp +++ b/plugins/dev9ghzdrk/Win32/smap.cpp @@ -118,16 +118,16 @@ void tx_process() u32 cnt=dev9Ru8(SMAP_R_TXFIFO_FRAME_CNT); //spams// printf("tx_process : %d cnt frames !\n",cnt); - // this hack worsens OPL performance. Is it really needed? OPL works fine without. (rama) - //if (!tx_p_first) - //{ - // dev9Ru8(SMAP_R_TXFIFO_FRAME_CNT)=0; - // tx_p_first=true; - // //THIS IS A HACK.without that the stack wont init, i guess its missing e3/emac emulation .. - // emu_printf("WARN : First packet interrupt hack ..\n"); - // _DEV9irq(SMAP_INTR_RXEND|SMAP_INTR_TXEND|SMAP_INTR_TXDNV,100); - // return; - //} + //Hack needed for GT4. Game fails to init the adapter otherwise (and notices about that via IOP kprintf on bootup). + if (!tx_p_first) + { + dev9Ru8(SMAP_R_TXFIFO_FRAME_CNT)=0; + tx_p_first=true; + //THIS IS A HACK.without that the stack wont init, i guess its missing e3/emac emulation .. + emu_printf("WARN : First packet interrupt hack ..\n"); + _DEV9irq(SMAP_INTR_RXEND|SMAP_INTR_TXEND|SMAP_INTR_TXDNV,100); + return; + } NetPacket pk; int fc=0; From a6f5ac472061b1d75c5d199ab256833a51f2b52c Mon Sep 17 00:00:00 2001 From: "ramapcsx2.code" Date: Wed, 20 Mar 2013 14:50:56 +0000 Subject: [PATCH 51/81] DEV9ghzdrk: Changed the stack init hack so it is consistent on plugin resets and removed a part of it that broke OPL. Hopefully this works for all use cases, but we should fix the initial problem anyway. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5601 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/dev9ghzdrk/DEV9.cpp | 3 +++ plugins/dev9ghzdrk/Win32/smap.cpp | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/dev9ghzdrk/DEV9.cpp b/plugins/dev9ghzdrk/DEV9.cpp index 992d83043..703ac8dd7 100644 --- a/plugins/dev9ghzdrk/DEV9.cpp +++ b/plugins/dev9ghzdrk/DEV9.cpp @@ -168,12 +168,15 @@ void CALLBACK DEV9shutdown() { #endif } +bool tx_p_first; s32 CALLBACK DEV9open(void *pDsp) { DEV9_LOG("DEV9open\n"); LoadConf(); DEV9_LOG("open r+: %s\n", config.Hdd); config.HddSize = 8*1024; + + tx_p_first=false; // reset stack init hack so it works on game reboots iopPC = (u32*)pDsp; diff --git a/plugins/dev9ghzdrk/Win32/smap.cpp b/plugins/dev9ghzdrk/Win32/smap.cpp index 3e1d1c8c1..b48bbb08d 100644 --- a/plugins/dev9ghzdrk/Win32/smap.cpp +++ b/plugins/dev9ghzdrk/Win32/smap.cpp @@ -107,11 +107,12 @@ void rx_process(NetPacket* pk) //note that this _is_ wrong since the IOP interrupt system is not thread safe.. but nothing i can do about that } -bool tx_p_first=false; u32 wswap(u32 d) { return (d>>16)|(d<<16); } + +extern bool tx_p_first; void tx_process() { //we loop based on count ? or just *use* it ? @@ -119,9 +120,10 @@ void tx_process() //spams// printf("tx_process : %d cnt frames !\n",cnt); //Hack needed for GT4. Game fails to init the adapter otherwise (and notices about that via IOP kprintf on bootup). + //Reseting SMAP_R_TXFIFO_FRAME_CNT to 0 however breaks OPL. Thankfully not doing that fixes the problem while GT4 still works. if (!tx_p_first) { - dev9Ru8(SMAP_R_TXFIFO_FRAME_CNT)=0; + //dev9Ru8(SMAP_R_TXFIFO_FRAME_CNT)=0; tx_p_first=true; //THIS IS A HACK.without that the stack wont init, i guess its missing e3/emac emulation .. emu_printf("WARN : First packet interrupt hack ..\n"); From 51fc6dbd078851fded4cf67f9bf6a99bf7193852 Mon Sep 17 00:00:00 2001 From: "ramapcsx2.code" Date: Wed, 20 Mar 2013 16:34:31 +0000 Subject: [PATCH 52/81] Added Visual Studio 2012 solution files for DEV9ghzdrk and avoided a macro redefinition error in WinPcap when that compiler is used. VS2008 is harder to do as there is no automatic downgrader tools for the solution files, sorry. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5602 96395faa-99c1-11dd-bbfe-3dabce05a288 --- 3rdparty/winpcap/include/pcap-stdinc.h | 3 +- pcsx2_suite_2012.sln | 36 +++++ .../dev9ghzdrk/Win32/DEV9ghzdrk_vs11.vcxproj | 138 ++++++++++++++++++ 3 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 plugins/dev9ghzdrk/Win32/DEV9ghzdrk_vs11.vcxproj diff --git a/3rdparty/winpcap/include/pcap-stdinc.h b/3rdparty/winpcap/include/pcap-stdinc.h index 417604177..6170a2344 100644 --- a/3rdparty/winpcap/include/pcap-stdinc.h +++ b/3rdparty/winpcap/include/pcap-stdinc.h @@ -66,7 +66,8 @@ #define strdup _strdup #endif -#define inline __inline +// PCSX2 note: MSVC2012 error with DEV9ghzdrk because of a macro redefinition here +//#define inline __inline #ifdef __MINGW32__ #include diff --git a/pcsx2_suite_2012.sln b/pcsx2_suite_2012.sln index 6bfe50433..a5f519a7f 100644 --- a/pcsx2_suite_2012.sln +++ b/pcsx2_suite_2012.sln @@ -114,6 +114,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "USBqemu", "plugins\USBqemu\ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZZOgl-cg", "plugins\zzogl-pg-cg\opengl\Win32\zerogsogl-cg_vs11.vcxproj", "{019773FA-2DAA-4C12-9511-BD2D4EB2A718}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DEV9ghzdrk", "plugins\dev9ghzdrk\Win32\DEV9ghzdrk_vs11.vcxproj", "{BBE4E5FB-530A-4D18-A633-35AF0577B7F3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug AVX|Win32 = Debug AVX|Win32 @@ -1221,6 +1223,39 @@ Global {019773FA-2DAA-4C12-9511-BD2D4EB2A718}.Release|Win32.ActiveCfg = Release|Win32 {019773FA-2DAA-4C12-9511-BD2D4EB2A718}.Release|Win32.Build.0 = Release|Win32 {019773FA-2DAA-4C12-9511-BD2D4EB2A718}.Release|x64.ActiveCfg = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug AVX|Win32.ActiveCfg = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug AVX|Win32.Build.0 = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug AVX|x64.ActiveCfg = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug SSE2|Win32.ActiveCfg = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug SSE2|Win32.Build.0 = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug SSE2|x64.ActiveCfg = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug SSE4|Win32.ActiveCfg = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug SSE4|Win32.Build.0 = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug SSE4|x64.ActiveCfg = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug SSSE3|Win32.ActiveCfg = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug SSSE3|Win32.Build.0 = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug SSSE3|x64.ActiveCfg = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug|Win32.ActiveCfg = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug|Win32.Build.0 = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Debug|x64.ActiveCfg = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Devel|Win32.ActiveCfg = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Devel|Win32.Build.0 = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Devel|x64.ActiveCfg = Debug|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release AVX|Win32.ActiveCfg = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release AVX|Win32.Build.0 = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release AVX|x64.ActiveCfg = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release SSE2|Win32.ActiveCfg = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release SSE2|Win32.Build.0 = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release SSE2|x64.ActiveCfg = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release SSE4|Win32.ActiveCfg = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release SSE4|Win32.Build.0 = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release SSE4|x64.ActiveCfg = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release SSSE3|Win32.ActiveCfg = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release SSSE3|Win32.Build.0 = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release SSSE3|x64.ActiveCfg = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release|Win32.ActiveCfg = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release|Win32.Build.0 = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release|x64.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1240,6 +1275,7 @@ Global {2D4E85B2-F47F-4D65-B091-701E5C031DAC} = {703FD00B-D7A0-41E3-BD03-CEC86B385DAF} {E613DA9F-41B4-4613-9911-E418EF5533BC} = {703FD00B-D7A0-41E3-BD03-CEC86B385DAF} {019773FA-2DAA-4C12-9511-BD2D4EB2A718} = {703FD00B-D7A0-41E3-BD03-CEC86B385DAF} + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3} = {703FD00B-D7A0-41E3-BD03-CEC86B385DAF} {E9B51944-7E6D-4BCD-83F2-7BBD5A46182D} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38} {2F6C0388-20CB-4242-9F6C-A6EBB6A83F47} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38} {F4EB4AB2-C595-4B05-8BC0-059024BC796C} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38} diff --git a/plugins/dev9ghzdrk/Win32/DEV9ghzdrk_vs11.vcxproj b/plugins/dev9ghzdrk/Win32/DEV9ghzdrk_vs11.vcxproj new file mode 100644 index 000000000..21241ad5d --- /dev/null +++ b/plugins/dev9ghzdrk/Win32/DEV9ghzdrk_vs11.vcxproj @@ -0,0 +1,138 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + DEV9ghzdrk + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3} + DEV9ghzdrk + Win32Proj + + + + DynamicLibrary + MultiByte + true + v110 + + + DynamicLibrary + MultiByte + v110 + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + EnableFastChecks + MultiThreadedDebug + + + $(SvnRootDir)\common\include;$(SvnRootDir)\3rdparty\winpcap\include;%(AdditionalIncludeDirectories) + + + NDEBUG;%(PreprocessorDefinitions) + 0x0408 + + + $(OutDir)$(TargetName)$(TargetExt) + .\DEV9ghzdrk.def + false + + + MachineX86 + ws2_32.lib;iphlpapi.lib;wpcap.lib;packet.lib;%(AdditionalDependencies) + $(SolutionDir)3rdparty\winpcap\lib;%(AdditionalLibraryDirectories) + + + + + + + $(SvnRootDir)\common\include;$(SvnRootDir)\3rdparty\winpcap\include;%(AdditionalIncludeDirectories) + + + NDEBUG;%(PreprocessorDefinitions) + 0x0408 + + + DEV9ghzdrk.def + false + + + MachineX86 + $(SolutionDir)3rdparty\winpcap\lib;%(AdditionalLibraryDirectories) + ws2_32.lib;iphlpapi.lib;wpcap.lib;packet.lib;%(AdditionalDependencies) + + + + + + + + + + + + + true + true + + + true + true + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 9cc306c74f168ed6af04f0db88980804493a1bd5 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Mon, 25 Mar 2013 18:49:29 +0000 Subject: [PATCH 53/81] zzogl-pg: * bump minimal requirement to opengl 2! Basically any Dx9 class hardware. On intel you will need a gen4+ GPU. * remove the bad quality integer texture to use only texture float. Again need an gen4+ Intel GPU. Opensource users: Mesa must be built with support of texture float (stupid patents) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5603 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/zzogl-pg/opengl/Mem.cpp | 69 ++++----- plugins/zzogl-pg/opengl/Mem.h | 2 +- plugins/zzogl-pg/opengl/ZZGl.h | 4 - plugins/zzogl-pg/opengl/ZZoglCreate.cpp | 183 +++++++++++------------- plugins/zzogl-pg/opengl/ZZoglMem.cpp | 46 +++--- plugins/zzogl-pg/opengl/ZZoglMem.h | 2 +- plugins/zzogl-pg/opengl/ps2hw.fx | 2 +- plugins/zzogl-pg/opengl/ps2hw_gl4.glsl | 12 +- plugins/zzogl-pg/opengl/zerogs.h | 1 - 9 files changed, 140 insertions(+), 181 deletions(-) diff --git a/plugins/zzogl-pg/opengl/Mem.cpp b/plugins/zzogl-pg/opengl/Mem.cpp index e4895957f..d337b4bcf 100644 --- a/plugins/zzogl-pg/opengl/Mem.cpp +++ b/plugins/zzogl-pg/opengl/Mem.cpp @@ -249,12 +249,9 @@ 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) +void fill_block(BLOCK b, vector& vBlockData, vector& vBilinearData) { 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) { @@ -266,43 +263,33 @@ void fill_block(BLOCK b, vector& vBlockData, vector& vBilinearData, 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; - + psrcf[i_width + j] = (float)(u) / (float)(GPU_TEXWIDTH * b.mult); } } - if (floatfmt) { - float4* psrcv = (float4*)&vBilinearData[0] + b.ox + b.oy * BLOCK_TEXWIDTH; + 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]; - } - } - } + 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) +void BLOCK::FillBlocks(vector& vBlockData, vector& vBilinearData) { 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); - } + vBlockData.resize(BLOCK_TEXWIDTH * BLOCK_TEXHEIGHT * 4); + vBilinearData.resize(BLOCK_TEXWIDTH * BLOCK_TEXHEIGHT * sizeof(float4)); BLOCK b; @@ -311,7 +298,7 @@ void BLOCK::FillBlocks(vector& vBlockData, vector& vBilinearData, in // 32 b.SetDim(64, 32, 0, 0, 1); b.SetTable(PSMCT32); - fill_block(b, vBlockData, vBilinearData, floatfmt); + fill_block(b, vBlockData, vBilinearData); m_Blocks[PSMCT32] = b; m_Blocks[PSMCT32].SetFun(PSMCT32); @@ -332,7 +319,7 @@ void BLOCK::FillBlocks(vector& vBlockData, vector& vBilinearData, in // 32z b.SetDim(64, 32, 64, 0, 1); b.SetTable(PSMT32Z); - fill_block(b, vBlockData, vBilinearData, floatfmt); + fill_block(b, vBlockData, vBilinearData); m_Blocks[PSMT32Z] = b; m_Blocks[PSMT32Z].SetFun(PSMT32Z); @@ -343,42 +330,42 @@ void BLOCK::FillBlocks(vector& vBlockData, vector& vBilinearData, in // 16 b.SetDim(64, 64, 0, 32, 2); b.SetTable(PSMCT16); - fill_block(b, vBlockData, vBilinearData, floatfmt); + fill_block(b, vBlockData, vBilinearData); 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); + fill_block(b, vBlockData, vBilinearData); 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); + fill_block(b, vBlockData, vBilinearData); 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); + fill_block(b, vBlockData, vBilinearData); 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); + fill_block(b, vBlockData, vBilinearData); 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); + fill_block(b, vBlockData, vBilinearData); m_Blocks[PSMT4] = b; m_Blocks[PSMT4].SetFun(PSMT4); } diff --git a/plugins/zzogl-pg/opengl/Mem.h b/plugins/zzogl-pg/opengl/Mem.h index ad8986c39..f92a1a16e 100644 --- a/plugins/zzogl-pg/opengl/Mem.h +++ b/plugins/zzogl-pg/opengl/Mem.h @@ -150,7 +150,7 @@ struct BLOCK _TransferLocalHost TransferLocalHost; // texture must be of dims BLOCK_TEXWIDTH and BLOCK_TEXHEIGHT - static void FillBlocks(std::vector& vBlockData, std::vector& vBilinearData, int floatfmt); + static void FillBlocks(std::vector& vBlockData, std::vector& vBilinearData); void SetDim(u32 bw, u32 bh, u32 ox2, u32 oy2, u32 mult2) { diff --git a/plugins/zzogl-pg/opengl/ZZGl.h b/plugins/zzogl-pg/opengl/ZZGl.h index 5814e8936..fd4f3b846 100644 --- a/plugins/zzogl-pg/opengl/ZZGl.h +++ b/plugins/zzogl-pg/opengl/ZZGl.h @@ -95,9 +95,6 @@ static __forceinline void SET_STREAM() #endif } -// global alpha blending settings -extern GLenum g_internalRGBAFloat16Fmt; - //static __forceinline void SAFE_RELEASE_TEX(u32& x) //{ // if (x != 0) @@ -148,7 +145,6 @@ extern PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT; extern PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT; extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT; extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT; -extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; extern PFNGLDRAWBUFFERSPROC glDrawBuffers; #ifdef GLSL4_API diff --git a/plugins/zzogl-pg/opengl/ZZoglCreate.cpp b/plugins/zzogl-pg/opengl/ZZoglCreate.cpp index caa46e8f1..ea17bf8c1 100644 --- a/plugins/zzogl-pg/opengl/ZZoglCreate.cpp +++ b/plugins/zzogl-pg/opengl/ZZoglCreate.cpp @@ -96,10 +96,6 @@ GLenum s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha; // set by zgsBlendFuncSeparat 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 @@ -136,35 +132,55 @@ bool IsGLExt(const char* szTargetExtension) return mapGLExtensions.find(string(szTargetExtension)) != mapGLExtensions.end(); } +inline bool check_gl_version(uint32 major, uint32 minor) { + const GLubyte* s; + s = glGetString(GL_VERSION); + if (s == NULL) return false; + ZZLog::Error_Log("Supported Opengl version: %s on GPU: %s. Vendor: %s\n", s, glGetString(GL_RENDERER), glGetString(GL_VENDOR)); + // Could be useful to detect the GPU vendor: + // if ( strcmp((const char*)glGetString(GL_VENDOR), "ATI Technologies Inc.") == 0 ) + + GLuint dot = 0; + while (s[dot] != '\0' && s[dot] != '.') dot++; + if (dot == 0) return false; + + GLuint major_gl = s[dot-1]-'0'; + GLuint minor_gl = s[dot+1]-'0'; + + if ( (major_gl < major) || ( major_gl == major && minor_gl < minor ) ) { + ZZLog::Error_Log("OPENGL %d.%d is not supported\n", major, minor); + return false; + } + + return true; +} + // 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; - } else { - const GLubyte* gl_version = glGetString(GL_VERSION); - ZZLog::Error_Log("Supported Opengl version : %s\n", gl_version); + // Better exit now, any openGL call will segfault. + return false; } - #endif + // Require a minimum of openGL2.0 (first version that support hardware shader) + bSuccess &= check_gl_version(2, 0); + + // GL_EXT_framebuffer_object -> GL3.0 + // Opensource driver -> Intel OK. Radeon need EXT_packed_depth_stencil 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; @@ -173,39 +189,21 @@ inline bool CreateImportantCheck() // 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; + // GL_EXT_blend_equation_separate -> GL2.0 + // Opensource driver -> Intel OK. Radeon OK. + 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; + // GL_EXT_blend_func_separate -> GL1.4 + // Opensource driver -> Intel OK. Radeon OK. + 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: *********"); + // GL_ARB_draw_buffers -> GL2.0 + // Opensource driver -> Intel (need gen4). Radeon OK. + if (glDrawBuffers == NULL) { + ZZLog::Error_Log("*********\nZZogl: OGL ERROR: multiple render targets not supported, some effects might look bad\nZZogl: *********"); conf.mrtdepth = 0; } - if (IsGLExt("GL_ARB_draw_buffers")) - glDrawBuffers = (PFNGLDRAWBUFFERSPROC)GLWin.GetProcAddress("glDrawBuffers"); - else if (IsGLExt("GL_ATI_draw_buffers")) - glDrawBuffers = (PFNGLDRAWBUFFERSPROC)GLWin.GetProcAddress("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; @@ -396,6 +394,8 @@ inline bool CreateFillExtensionsMap() void LoadglFunctions() { + // GL_EXT_framebuffer_object + // CORE -> 3.0 and replaced by GL_ARB_framebuffer_object GL_LOADFN(glIsRenderbufferEXT); GL_LOADFN(glBindRenderbufferEXT); GL_LOADFN(glDeleteRenderbuffersEXT); @@ -412,23 +412,21 @@ void LoadglFunctions() GL_LOADFN(glFramebufferTexture3DEXT); GL_LOADFN(glFramebufferRenderbufferEXT); GL_LOADFN(glGetFramebufferAttachmentParameterivEXT); - GL_LOADFN(glGenerateMipmapEXT); + + // CORE -> 2.0 + GL_LOADFN(glDrawBuffers); } 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); + glTexImage2D(GL_TEXTURE_2D, 0, fmt, 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); +inline bool TryBlinearFormat(GLint fmt32, const GLvoid* vBilinearData) { + glTexImage2D(GL_TEXTURE_2D, 0, fmt32, 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; @@ -584,7 +582,6 @@ bool ZZCreate(int _width, int _height) // create the blocks texture g_fBlockMult = 1; - bool do_not_use_billinear = false; #ifndef ZZNORMAL_MEMORY FillAlowedPsnTable(); @@ -592,58 +589,54 @@ bool ZZCreate(int _width, int _height) #endif vector vBlockData, vBilinearData; - BLOCK::FillBlocks(vBlockData, vBilinearData, 1); + BLOCK::FillBlocks(vBlockData, vBilinearData); glGenTextures(1, &ptexBlocks); glBindTexture(GL_TEXTURE_2D, ptexBlocks); + // Opensource driver -> Intel (need gen4) (enabled by default on mesa 9). Radeon depends on the HW capability +#ifdef GLSL4_API + // texture float -> GL3.0 + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, GL_RED, GL_FLOAT, &vBlockData[0]); + if (glGetError() != GL_NO_ERROR) { + ZZLog::Error_Log("ZZogl ERROR: could not fill blocks"); + return false; + } +#else 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!"); + else { + ZZLog::Error_Log("ZZogl ERROR: float texture not supported. If you use opensource driver (aka Mesa), you probably need to compile it with texture float support."); + ZZLog::Error_Log("ZZogl ERROR: Otherwise you probably have a very very old GPU, either use an older version of the plugin or upgrade your computer"); + return false; } +#endif 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."); + // fill in the bilinear blocks (main variant). + glGenTextures(1, &ptexBilinearBlocks); + glBindTexture(GL_TEXTURE_2D, ptexBilinearBlocks); - setTex2DFilters(GL_NEAREST); - setTex2DWrap(GL_REPEAT); - } +#ifdef GLSL4_API + if (!TryBlinearFormat(GL_RGBA32F, &vBilinearData[0])) + ZZLog::Error_Log("Fill bilinear blocks failed."); +#else + if (TryBlinearFormat(GL_RGBA32F, &vBilinearData[0])) + ZZLog::Error_Log("Fill bilinear blocks OK.!"); + else if (TryBlinearFormat(GL_RGBA_FLOAT32_ATI, &vBilinearData[0])) + ZZLog::Error_Log("Fill bilinear blocks with ATI_texture_float."); + else if (TryBlinearFormat(GL_FLOAT_RGBA32_NV, &vBilinearData[0])) + ZZLog::Error_Log("ZZogl Fill bilinear blocks with NVidia_float."); + else + ZZLog::Error_Log("Fill bilinear blocks failed."); +#endif + + setTex2DFilters(GL_NEAREST); + setTex2DWrap(GL_REPEAT); float fpri = 1; @@ -688,11 +681,6 @@ bool ZZCreate(int _width, int _height) GL_REPORT_ERROR(); #endif - // 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); @@ -746,6 +734,7 @@ bool ZZCreate(int _width, int _height) GL_REPORT_ERROR(); + if (err != GL_NO_ERROR) bSuccess = false; glDisable(GL_STENCIL_TEST); @@ -773,10 +762,6 @@ bool ZZCreate(int _width, int _height) g_vsprog = g_psprog = sZero; -#ifdef OGL4_LOG - glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); -#endif - if (glGetError() == GL_NO_ERROR) { return bSuccess; diff --git a/plugins/zzogl-pg/opengl/ZZoglMem.cpp b/plugins/zzogl-pg/opengl/ZZoglMem.cpp index 1a593ef64..90bd49fc8 100644 --- a/plugins/zzogl-pg/opengl/ZZoglMem.cpp +++ b/plugins/zzogl-pg/opengl/ZZoglMem.cpp @@ -428,7 +428,7 @@ void TransferLocalHost24Z(void* pbyMem, u32 nQWordSize) { FUNCLOG } void TransferLocalHost16Z(void* pbyMem, u32 nQWordSize) { FUNCLOG } void TransferLocalHost16SZ(void* pbyMem, u32 nQWordSize) { FUNCLOG } -inline void FILL_BLOCK(BLOCK& b, int floatfmt, vector& vBlockData, vector& vBilinearData, int ox, int oy, int psmX) { +inline void FILL_BLOCK(BLOCK& b, vector& vBlockData, vector& vBilinearData, int ox, int oy, int psmX) { int bw = ZZ_DT[psmX][4] + 1; int bh = ZZ_DT[psmX][3] + 1; int mult = 1 << ZZ_DT[psmX][0]; @@ -448,36 +448,28 @@ inline void FILL_BLOCK(BLOCK& b, int floatfmt, vector& vBlockData, vector< // This is never true. //assert( sizeof(g_pageTable[psmX]) == bw*bh*sizeof(g_pageTable[psmX][0][0]) ); float* psrcf = (float*)&vBlockData[0] + ox + oy * BLOCK_TEXWIDTH; - u16* psrcw = (u16*)&vBlockData[0] + ox + oy * BLOCK_TEXWIDTH; for(int i = 0; i < bh; ++i) { for(int j = 0; j < bw; ++j) { /* fill the table */ u32 u = g_blockTable[psmX][(i / b.colheight)][(j / b.colwidth)] * 64 * mult + g_columnTable[psmX][i%b.colheight][j%b.colwidth]; b.pageTable[i][j] = u; - if( floatfmt ) { - psrcf[i*BLOCK_TEXWIDTH+j] = (float)(u) / (float)(GPU_TEXWIDTH*mult); - } - else { - psrcw[i*BLOCK_TEXWIDTH+j] = u; - } + psrcf[i*BLOCK_TEXWIDTH+j] = (float)(u) / (float)(GPU_TEXWIDTH*mult); } } - if( floatfmt ) { - float4* psrcv = (float4*)&vBilinearData[0] + ox + oy * BLOCK_TEXWIDTH; - for(int i = 0; i < bh; ++i) { - for(int j = 0; j < bw; ++j) { - float4* pv = &psrcv[i*BLOCK_TEXWIDTH+j]; - pv->x = psrcf[i*BLOCK_TEXWIDTH+j]; - pv->y = psrcf[i*BLOCK_TEXWIDTH+((j+1)%bw)]; - pv->z = psrcf[((i+1)%bh)*BLOCK_TEXWIDTH+j]; - pv->w = psrcf[((i+1)%bh)*BLOCK_TEXWIDTH+((j+1)%bw)]; - } + float4* psrcv = (float4*)&vBilinearData[0] + ox + oy * BLOCK_TEXWIDTH; + for(int i = 0; i < bh; ++i) { + for(int j = 0; j < bw; ++j) { + float4* pv = &psrcv[i*BLOCK_TEXWIDTH+j]; + pv->x = psrcf[i*BLOCK_TEXWIDTH+j]; + pv->y = psrcf[i*BLOCK_TEXWIDTH+((j+1)%bw)]; + pv->z = psrcf[((i+1)%bh)*BLOCK_TEXWIDTH+j]; + pv->w = psrcf[((i+1)%bh)*BLOCK_TEXWIDTH+((j+1)%bw)]; } } } -void BLOCK::FillBlocks(vector& vBlockData, vector& vBilinearData, int floatfmt) +void BLOCK::FillBlocks(vector& vBlockData, vector& vBilinearData) { FUNCLOG vBlockData.resize(BLOCK_TEXWIDTH * BLOCK_TEXHEIGHT * (floatfmt ? 4 : 2)); @@ -490,7 +482,7 @@ void BLOCK::FillBlocks(vector& vBlockData, vector& vBilinearData, in memset(m_Blocks, 0, sizeof(m_Blocks)); // 32 - FILL_BLOCK(b, floatfmt, vBlockData, vBilinearData, 0, 0, PSMCT32); + FILL_BLOCK(b, vBlockData, vBilinearData, 0, 0, PSMCT32); b.TransferHostLocal = TransferHostLocal32; b.TransferLocalHost = TransferLocalHost32; m_Blocks[PSMCT32] = b; @@ -514,7 +506,7 @@ void BLOCK::FillBlocks(vector& vBlockData, vector& vBilinearData, in m_Blocks[PSMT4HH] = b; // 32z - FILL_BLOCK(b, floatfmt, vBlockData, vBilinearData, 64, 0, PSMT32Z); + FILL_BLOCK(b, vBlockData, vBilinearData, 64, 0, PSMT32Z); b.TransferHostLocal = TransferHostLocal32Z; b.TransferLocalHost = TransferLocalHost32Z; m_Blocks[PSMT32Z] = b; @@ -525,37 +517,37 @@ void BLOCK::FillBlocks(vector& vBlockData, vector& vBilinearData, in m_Blocks[PSMT24Z] = b; // 16 - FILL_BLOCK(b, floatfmt, vBlockData, vBilinearData, 0, 32, PSMCT16); + FILL_BLOCK(b, vBlockData, vBilinearData, 0, 32, PSMCT16); b.TransferHostLocal = TransferHostLocal16; b.TransferLocalHost = TransferLocalHost16; m_Blocks[PSMCT16] = b; // 16s - FILL_BLOCK(b, floatfmt, vBlockData, vBilinearData, 64, 32, PSMCT16S); + FILL_BLOCK(b, vBlockData, vBilinearData, 64, 32, PSMCT16S); b.TransferHostLocal = TransferHostLocal16S; b.TransferLocalHost = TransferLocalHost16S; m_Blocks[PSMCT16S] = b; // 16z - FILL_BLOCK(b, floatfmt, vBlockData, vBilinearData, 0, 96, PSMT16Z); + FILL_BLOCK(b, vBlockData, vBilinearData, 0, 96, PSMT16Z); b.TransferHostLocal = TransferHostLocal16Z; b.TransferLocalHost = TransferLocalHost16Z; m_Blocks[PSMT16Z] = b; // 16sz - FILL_BLOCK(b, floatfmt, vBlockData, vBilinearData, 64, 96, PSMT16SZ); + FILL_BLOCK(b, vBlockData, vBilinearData, 64, 96, PSMT16SZ); b.TransferHostLocal = TransferHostLocal16SZ; b.TransferLocalHost = TransferLocalHost16SZ; m_Blocks[PSMT16SZ] = b; // 8 - FILL_BLOCK(b, floatfmt, vBlockData, vBilinearData, 0, 160, PSMT8); + FILL_BLOCK(b, vBlockData, vBilinearData, 0, 160, PSMT8); b.TransferHostLocal = TransferHostLocal8; b.TransferLocalHost = TransferLocalHost8; m_Blocks[PSMT8] = b; // 4 - FILL_BLOCK(b, floatfmt, vBlockData, vBilinearData, 0, 224, PSMT4); + FILL_BLOCK(b, vBlockData, vBilinearData, 0, 224, PSMT4); b.TransferHostLocal = TransferHostLocal4; b.TransferLocalHost = TransferLocalHost4; m_Blocks[PSMT4] = b; diff --git a/plugins/zzogl-pg/opengl/ZZoglMem.h b/plugins/zzogl-pg/opengl/ZZoglMem.h index 42eaca3c2..33a857255 100644 --- a/plugins/zzogl-pg/opengl/ZZoglMem.h +++ b/plugins/zzogl-pg/opengl/ZZoglMem.h @@ -95,7 +95,7 @@ struct BLOCK void (*TransferLocalHost)(void* pbyMem, u32 nQWordSize); // texture must be of dims BLOCK_TEXWIDTH and BLOCK_TEXHEIGHT - static void FillBlocks(std::vector& vBlockData, std::vector& vBilinearData, int floatfmt); + static void FillBlocks(std::vector& vBlockData, std::vector& vBilinearData); }; void FillBlockTables(); diff --git a/plugins/zzogl-pg/opengl/ps2hw.fx b/plugins/zzogl-pg/opengl/ps2hw.fx index 0965c3adc..9eb711127 100644 --- a/plugins/zzogl-pg/opengl/ps2hw.fx +++ b/plugins/zzogl-pg/opengl/ps2hw.fx @@ -96,7 +96,7 @@ float2 ps2memcoord(float2 realtex) off.xy = realtex.xy-fblock.xy; #ifdef ACCURATE_DECOMPRESSION - off.zw = tex2D(g_sBlocks, g_fTexBlock.xy*fblock + g_fTexBlock.zw).ar; + off.z = tex2D(g_sBlocks, g_fTexBlock.xy*fblock + g_fTexBlock.zw).a; off.x = dot(off.xy, g_fTexOffset.xy); float r = g_fTexOffset.w; float f = frac(off.x); diff --git a/plugins/zzogl-pg/opengl/ps2hw_gl4.glsl b/plugins/zzogl-pg/opengl/ps2hw_gl4.glsl index f69dea94d..8227dae51 100644 --- a/plugins/zzogl-pg/opengl/ps2hw_gl4.glsl +++ b/plugins/zzogl-pg/opengl/ps2hw_gl4.glsl @@ -193,7 +193,7 @@ float2 ps2memcoord(float2 realtex) off.xy = realtex.xy-fblock.xy; #ifdef ACCURATE_DECOMPRESSION - off.zw = texture(g_sBlocks, g_fTexBlock.xy*fblock + g_fTexBlock.zw).ar; + off.z = texture(g_sBlocks, g_fTexBlock.xy*fblock + g_fTexBlock.zw).r; off.x = dot(off.xy, g_fTexOffset.xy); float r = g_fTexOffset.w; float f = fract(off.x); @@ -202,7 +202,7 @@ float2 ps2memcoord(float2 realtex) off.x = fract(f + fadd + r); off.w -= off.x ; #else - off.z = texture(g_sBlocks, g_fTexBlock.xy*fblock + g_fTexBlock.zw).a; + off.z = texture(g_sBlocks, g_fTexBlock.xy*fblock + g_fTexBlock.zw).r; // combine the two off.x = dot(off.xyz, g_fTexOffset.xyz)+g_fTexOffset.w; @@ -232,10 +232,10 @@ void ps2memcoord4(float4 orgtex, out float4 off0, out float4 off1) float4 colors;// = texture(g_sBilinearBlocks, ftransblock.xy); // this is faster on ffx ingame - colors.x = texture(g_sBlocks, ftransblock.xy).a; - colors.y = texture(g_sBlocks, ftransblock.zy).a; - colors.z = texture(g_sBlocks, ftransblock.xw).a; - colors.w = texture(g_sBlocks, ftransblock.zw).a; + colors.x = texture(g_sBlocks, ftransblock.xy).r; + colors.y = texture(g_sBlocks, ftransblock.zy).r; + colors.z = texture(g_sBlocks, ftransblock.xw).r; + colors.w = texture(g_sBlocks, ftransblock.zw).r; float4 fr, rem; diff --git a/plugins/zzogl-pg/opengl/zerogs.h b/plugins/zzogl-pg/opengl/zerogs.h index b898d4682..f95542e9a 100644 --- a/plugins/zzogl-pg/opengl/zerogs.h +++ b/plugins/zzogl-pg/opengl/zerogs.h @@ -63,7 +63,6 @@ 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 From 75284c9b7635e63d2cc94e771415d43304678659 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Sat, 30 Mar 2013 23:50:22 +0000 Subject: [PATCH 54/81] microVU: Reverted original Xtreme G Racing 3 change as that was a hack, found the real problem. Evil jumps on E-bits, could it get any worse???? git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5604 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/x86/microVU_Branch.inl | 9 +++++++++ pcsx2/x86/microVU_Lower.inl | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/pcsx2/x86/microVU_Branch.inl b/pcsx2/x86/microVU_Branch.inl index 0de3029ae..d63aabc64 100644 --- a/pcsx2/x86/microVU_Branch.inl +++ b/pcsx2/x86/microVU_Branch.inl @@ -172,6 +172,15 @@ void normJumpCompile(mV, microFlagCycles& mFC, bool isEvilJump) { if (doJumpCaching) xMOV(gprT3, (uptr)mVUpBlock); else xMOV(gprT3, (uptr)&mVUpBlock->pStateEnd); + if(mVUup.eBit && isEvilJump)// E-bit EvilJump + { + //Xtreme G 3 does 2 conditional jumps, the first contains an E Bit on the first instruction + //So if it is taken, you need to end the program, else you get infinite loops. + mVUendProgram(mVU, &mFC, 2); + xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT2); + xJMP(mVU.exitFunct); + } + if (!mVU.index) xCALL(mVUcompileJIT<0>); //(u32 startPC, uptr pState) else xCALL(mVUcompileJIT<1>); diff --git a/pcsx2/x86/microVU_Lower.inl b/pcsx2/x86/microVU_Lower.inl index 8f6c848a3..f44e11501 100644 --- a/pcsx2/x86/microVU_Lower.inl +++ b/pcsx2/x86/microVU_Lower.inl @@ -1245,7 +1245,7 @@ void setBranchA(mP, int x, int _x_) { void condEvilBranch(mV, int JMPcc) { if (mVUlow.badBranch) { xMOV(ptr32[&mVU.branch], gprT1); - xMOV(ptr32[&mVU.badBranch], branchAddr); + xMOV(ptr32[&mVU.badBranch], branchAddrN); xCMP(gprT1b, 0); xForwardJump8 cJMP((JccComparisonType)JMPcc); From e2ff25963ba802c58b45d32bd91612a34f23ec93 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Thu, 4 Apr 2013 19:39:46 +0000 Subject: [PATCH 55/81] GSDX: Applying patch for 2 small errors in GSDX provided by mathew1800. Thanks to KrossX3 for aiding our laziness:P git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5605 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSDevice9.cpp | 2 +- plugins/GSdx/GSSettingsDlg.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/GSdx/GSDevice9.cpp b/plugins/GSdx/GSDevice9.cpp index 6102c0c2e..24e6af94f 100644 --- a/plugins/GSdx/GSDevice9.cpp +++ b/plugins/GSdx/GSDevice9.cpp @@ -136,7 +136,7 @@ static D3DFORMAT BestD3dFormat(IDirect3D9* d3d, UINT adapter, D3DDEVTYPE devtype if(1 == msaaCount) msaaCount = 0; - for(int i = 0; i < sizeof(fmts); i++) + for(int i = 0; i < countof(fmts); i++) { if(TestDepthFormat(d3d, adapter, devtype, fmts[i]) && (!msaaCount || IsMsaaSupported(d3d, adapter, devtype, fmts[i], msaaCount, msaa_desc))) { diff --git a/plugins/GSdx/GSSettingsDlg.cpp b/plugins/GSdx/GSSettingsDlg.cpp index b2413f01d..64ec3ecaa 100644 --- a/plugins/GSdx/GSSettingsDlg.cpp +++ b/plugins/GSdx/GSSettingsDlg.cpp @@ -105,7 +105,7 @@ void GSSettingsDlg::OnInit() buf, size, NULL, NULL); adapters.push_back(Adapter(buf, GSAdapter(desc), level)); - delete buf; + delete [] buf; #else adapters.push_back(Adapter(desc.Description, GSAdapter(desc), level)); #endif From a28ca6554d777b7d3793b873790602c1bbf1975e Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Sun, 7 Apr 2013 13:27:01 +0000 Subject: [PATCH 56/81] Game Index: Changes made by pgert, mostly naming changes, added what i believe is a second disc for the US version of Persona 4 Serial: SLUS-21782B to auto enable VU Clip Flag Hack. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5606 96395faa-99c1-11dd-bbfe-3dabce05a288 --- bin/GameIndex.dbf | 45 +++++++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/bin/GameIndex.dbf b/bin/GameIndex.dbf index 97f0e1f81..8504c7109 100644 --- a/bin/GameIndex.dbf +++ b/bin/GameIndex.dbf @@ -214,7 +214,7 @@ Name = Kiosk Demo Disc 2.02 Region = NTSC-U --------------------------------------------- Serial = SCUS-97128 -Name = Drakan - The Ancients' Gates +Name = Drakan - The Ancients' Gates // aka Drakan 2 Region = NTSC-U Compat = 5 EETimingHack = 1 //flickery textures @@ -349,7 +349,7 @@ Region = NTSC-U Compat = 5 --------------------------------------------- Serial = SCUS-97169 -Name = Drakan - The Ancients' Gates [Demo] +Name = Drakan - The Ancients' Gates [Demo] // aka Drakan 2 [Demo] Region = NTSC-U --------------------------------------------- Serial = SCUS-97170 @@ -3755,6 +3755,9 @@ Serial = SLUS-20484 Name = Devil May Cry 2 [Disc1of2] Region = NTSC-U Compat = 5 +[patches] + comment=Note that this disc has the same CRC as SLPM-65232, the NTSC-J disc. +[/patches] --------------------------------------------- Serial = SLUS-20485 Name = Dino Stalker @@ -5949,7 +5952,7 @@ Name = Samurai Showdown V Region = NTSC-U --------------------------------------------- Serial = SLUS-20973 -Name = Champions - Return to Arms +Name = Champions - Return to Arms // aka Champions of Norrath 2 Region = NTSC-U Compat = 4 --------------------------------------------- @@ -9559,6 +9562,12 @@ Region = NTSC-U Compat = 5 VuClipFlagHack = 1 --------------------------------------------- +Serial = SLUS-21782B +Name = Shin Megami Tensei - Persona 4 +Region = NTSC-U +Compat = 5 +VuClipFlagHack = 1 +--------------------------------------------- Serial = SLUS-21783 Name = Space Chimps Region = NTSC-U @@ -10708,7 +10717,7 @@ Name = Konami Preview Disc Region = NTSC-U --------------------------------------------- Serial = SLUS-29126 -Name = Champions - Return to Arms [Demo] +Name = Champions - Return to Arms [Demo] // aka Champions of Norrath 2 [Demo] Region = NTSC-U Compat = 4 --------------------------------------------- @@ -17697,6 +17706,9 @@ Serial = SLPM-65232 Name = Devil May Cry 2 [Dante Disc] Region = NTSC-J Compat = 5 +[patches] + comment=Note that this disc has the same CRC as SLUS-20484, the NTSC-U disc. +[/patches] --------------------------------------------- Serial = SLPM-65233 Name = Devil May Cry 2 [Lucia Disc] @@ -19904,11 +19916,6 @@ Serial = SLPM-65844 Name = Air [Best] Region = NTSC-J --------------------------------------------- -Serial = SLPM-65845 -Name = Baldur's Gate - Dark Alliance II -Region = NTSC-J -Compat = 4 ---------------------------------------------- Serial = SLPM-65846 Name = Lord of the Rings, The - Uchitsu Kuni Daisanki Region = NTSC-J @@ -29567,9 +29574,14 @@ Region = PAL-E Compat = 5 --------------------------------------------- Serial = SCES-50006 -Name = Drakan - The Ancients' Gates -Region = PAL-Unk +Name = Drakan - The Ancients' Gates // aka Drakan 2 +Region = PAL-M5 EETimingHack = 1 //flickery textures +[patches] + comment=This gamedisc supports multiple languages. + comment=Language selection is done through the BIOS configuration. + comment=Implementation requires full boot - "Boot CDVD (full)". +[/patches] --------------------------------------------- Serial = SCES-50009 Name = Wild Wild Racing @@ -32912,7 +32924,7 @@ Region = PAL-Unk --------------------------------------------- Serial = SLES-50821 Name = Project Zero -Region = PAL-M5 +Region = PAL-Unk Compat = 5 --------------------------------------------- Serial = SLES-50822 @@ -35708,6 +35720,11 @@ Name = Baldur's Gate - Dark Alliance 2 Region = PAL-Unk Compat = 4 --------------------------------------------- +Serial = SLPM-65845 +Name = Baldur's Gate - Dark Alliance II +Region = NTSC-J +Compat = 4 +--------------------------------------------- Serial = SLES-52190 Name = RPM Tuning Region = PAL-Unk @@ -37620,7 +37637,7 @@ Compat = 5 eeRoundMode = 0 --------------------------------------------- Serial = SLES-53039 -Name = Champions - Return to Arms +Name = Champions - Return to Arms // aka Champions of Norrath 2 Region = PAL-Unk Compat = 4 --------------------------------------------- @@ -39373,7 +39390,7 @@ Name = 50cent - Bulletproof Region = PAL-Unk --------------------------------------------- Serial = SLES-53908 -Name = Tomb Raider - Legends +Name = Tomb Raider - Legend Region = PAL-Unk Compat = 5 --------------------------------------------- From fa7d10cfb16ac0707d67dd84258f74e3a86d9236 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Sun, 7 Apr 2013 14:37:14 +0000 Subject: [PATCH 57/81] gsdx ogl: install a GLX error handler before the context creation. Allow to print a nice message when the user doesn't support opengl 3.3 git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5607 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSWnd.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/plugins/GSdx/GSWnd.cpp b/plugins/GSdx/GSWnd.cpp index 88150e7c6..97ac519ae 100644 --- a/plugins/GSdx/GSWnd.cpp +++ b/plugins/GSdx/GSWnd.cpp @@ -225,6 +225,13 @@ GSWnd::~GSWnd() } } +static bool ctxError = false; +static int ctxErrorHandler(Display *dpy, XErrorEvent *ev) +{ + ctxError = true; + return 0; +} + bool GSWnd::CreateContext(int major, int minor) { if ( !m_XDisplay || !m_Xwindow ) @@ -255,6 +262,11 @@ bool GSWnd::CreateContext(int major, int minor) PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((const GLubyte*) "glXCreateContextAttribsARB"); if (!glXCreateContextAttribsARB) return false; + // Install a dummy handler to handle gracefully (aka not segfault) the support of GL version + int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(&ctxErrorHandler); + // Be sure the handler is installed + XSync( m_XDisplay, false); + // Create a context int context_attribs[] = { @@ -268,9 +280,18 @@ bool GSWnd::CreateContext(int major, int minor) }; m_context = glXCreateContextAttribsARB(m_XDisplay, fbc[0], 0, true, context_attribs); - if (!m_context) return false; + // Don't forget to reinstall the older Handler + XSetErrorHandler(oldHandler); + + // Get latest error XSync( m_XDisplay, false); + + if (!m_context || ctxError) { + fprintf(stderr, "Failed to create the opengl context. Check your drivers support openGL %d.%d. Hint: opensource drivers don't\n", major, minor ); + return false; + } + return true; } From c472db6327f772df3220f56151b2bddbfe07c96d Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Mon, 8 Apr 2013 20:47:04 +0000 Subject: [PATCH 58/81] microVU: Fixes to D/T Bit handling and XGKick Delay -Elemental Garde - Fixed up D-Bit so it remembers the microVU state when recompiling, this fixes the bad geometry that was introduced with T/D bit handling. -WRC Rally Evolved - Changed the XGKick delay to an increased number, solves all remaining SPS problems. -Crash Twinsanity - Increased XGKick delay resolves geometry issues on Crash, thanks to Autoran1 for debugging this :) GameDB Changes: Added XGKick hack to Crash Twinsanity auto gamefixes, checked the main entries for the others above have it too. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5608 96395faa-99c1-11dd-bbfe-3dabce05a288 --- bin/GameIndex.dbf | 8 +++++--- pcsx2/x86/microVU_Branch.inl | 7 ++++++- pcsx2/x86/microVU_Compile.inl | 8 ++++---- pcsx2/x86/microVU_IR.h | 1 + pcsx2/x86/microVU_Misc.h | 2 +- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/bin/GameIndex.dbf b/bin/GameIndex.dbf index 8504c7109..88afe2a73 100644 --- a/bin/GameIndex.dbf +++ b/bin/GameIndex.dbf @@ -10667,6 +10667,7 @@ Region = NTSC-U Serial = SLUS-29101 Name = Crash Twinsanity & Spyro - A Hero's Tail [Demo] Region = NTSC-U +XgKickHack = 1 //Fixes bad Geometry --------------------------------------------- Serial = SLUS-29104 Name = Galactic Wrestling - Featuring Ultimate Muscle [Demo] @@ -16456,7 +16457,7 @@ Serial = SLPM-62623 Name = Elemental Gerad Region = NTSC-J Compat = 5 -XgKickHack = 1 +XgKickHack = 1 //Fixes chocolate coloured characters --------------------------------------------- Serial = SLPM-62624 Name = Indoor Helicopter Adventure 2 @@ -29400,7 +29401,7 @@ Region = NTSC-J Serial = TCPS-10111 Name = Eremental Gerad Region = NTSC-J -XgKickHack = 1 +XgKickHack = 1 //Fixes chocolate coloured characters --------------------------------------------- Serial = TCPS-10113 Name = Mushihime-sama @@ -30476,7 +30477,7 @@ Serial = SCES-53247 Name = WRC - World Rally Championship - Rally Evolved Region = PAL-Unk Compat = 4 -XgKickHack = 1 //Most of the ingame SPS gets fixed with it. +XgKickHack = 1 //SPS. [patches = cbbc2e7f] comment=patches by Nachbrenner //fix delay slot violation @@ -36477,6 +36478,7 @@ Serial = SLES-52568 Name = Crash Twinsanity Region = PAL-Unk Compat = 5 +XgKickHack = 1 //Fixes bad Geometry --------------------------------------------- Serial = SLES-52569 Name = Spyro - A Hero's Tail diff --git a/pcsx2/x86/microVU_Branch.inl b/pcsx2/x86/microVU_Branch.inl index d63aabc64..e99b0a16c 100644 --- a/pcsx2/x86/microVU_Branch.inl +++ b/pcsx2/x86/microVU_Branch.inl @@ -35,6 +35,9 @@ void mVUDTendProgram(mV, microFlagCycles* mFC, int isEbit) { int fClip = getLastFlagInst(mVUpBlock->pState, mFC->xClip, 2, isEbit); int qInst = 0; int pInst = 0; + microBlock stateBackup; + memcpy(&stateBackup, &mVUregs, sizeof(mVUregs)); //backup the state, it's about to get screwed with. + mVU.regAlloc->TDwritebackAll(); //Writing back ok, invalidating early kills the rec, so don't do it :P if (isEbit) { @@ -49,7 +52,8 @@ void mVUDTendProgram(mV, microFlagCycles* mFC, int isEbit) { sFLAG.write = fStatus; mVUdivSet(mVU); } - if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); } + //Run any pending XGKick, providing we've got to it. + if (mVUinfo.doXGKICK && xPC >= mVUinfo.XGKICKPC) { mVU_XGKICK_DELAY(mVU, 1); } if (doEarlyExit(mVU)) { if (!isVU1) xCALL(mVU0clearlpStateJIT); else xCALL(mVU1clearlpStateJIT); @@ -82,6 +86,7 @@ void mVUDTendProgram(mV, microFlagCycles* mFC, int isEbit) { xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC); xJMP(mVU.exitFunct); } + memcpy(&mVUregs, &stateBackup, sizeof(mVUregs)); //Restore the state for the rest of the recompile } void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) { diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index 74e57bfbe..349a5be40 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -269,7 +269,7 @@ void mVUincCycles(mV, int x) { } if (mVUregs.xgkick) { calcCycles(mVUregs.xgkick, x); - if (!mVUregs.xgkick) { mVUinfo.doXGKICK = 1; } + if (!mVUregs.xgkick) { mVUinfo.doXGKICK = 1; mVUinfo.XGKICKPC = xPC;} } calcCycles(mVUregs.r, x); } @@ -380,9 +380,9 @@ void mVUtestCycles(microVU& mVU) { // This gets run at the start of every loop of mVU's first pass __fi void startLoop(mV) { - if (curI & _Mbit_) { DevCon.WriteLn (Color_Green, "microVU%d: M-bit set!", getIndex); } - if (curI & _Dbit_) { DevCon.WriteLn (Color_Green, "microVU%d: D-bit set!", getIndex); } - if (curI & _Tbit_) { DevCon.WriteLn (Color_Green, "microVU%d: T-bit set!", getIndex); } + if (curI & _Mbit_) { DevCon.WriteLn (Color_Green, "microVU%d: M-bit set! PC = %x", getIndex, xPC); } + if (curI & _Dbit_) { DevCon.WriteLn (Color_Green, "microVU%d: D-bit set! PC = %x", getIndex, xPC); } + if (curI & _Tbit_) { DevCon.WriteLn (Color_Green, "microVU%d: T-bit set! PC = %x", getIndex, xPC); } memzero(mVUinfo); memzero(mVUregsTemp); } diff --git a/pcsx2/x86/microVU_IR.h b/pcsx2/x86/microVU_IR.h index 2845b39b5..3f77da450 100644 --- a/pcsx2/x86/microVU_IR.h +++ b/pcsx2/x86/microVU_IR.h @@ -159,6 +159,7 @@ struct microOp { bool swapOps; // Run Lower Instruction before Upper Instruction bool backupVF; // Backup mVUlow.VF_write.reg, and restore it before the Upper Instruction is called bool doXGKICK; // Do XGKICK transfer on this instruction + u32 XGKICKPC; // The PC in which the XGKick has taken place, so if we break early (before it) we don run it. bool doDivFlag; // Transfer Div flag to Status Flag on this instruction int readQ; // Q instance for reading int writeQ; // Q instance for writing diff --git a/pcsx2/x86/microVU_Misc.h b/pcsx2/x86/microVU_Misc.h index bc05ddc53..73a9a16e2 100644 --- a/pcsx2/x86/microVU_Misc.h +++ b/pcsx2/x86/microVU_Misc.h @@ -370,7 +370,7 @@ static const bool doJumpAsSameProgram = 0; // Set to 1 to treat jumps as same pr //------------------------------------------------------------------ // XG Kick Transfer Delay Amount -#define mVU_XGKICK_CYCLES ((CHECK_XGKICKHACK) ? 3 : 1) +#define mVU_XGKICK_CYCLES ((CHECK_XGKICKHACK) ? 6 : 1) // Its unknown at recompile time how long the xgkick transfer will take // so give it a value that makes games happy :) (SO3 is fine at 1 cycle delay) From fa2dc3d3d4ba63d98a333ec101d68df13f74c4b9 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Mon, 8 Apr 2013 20:57:40 +0000 Subject: [PATCH 59/81] GameDB: Added Siren 2 to the list of XGKick hack games. Should make it playable now as per the result of Issue 1054 Thanks for testing IceLancerSR :) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5609 96395faa-99c1-11dd-bbfe-3dabce05a288 --- bin/GameIndex.dbf | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bin/GameIndex.dbf b/bin/GameIndex.dbf index 88afe2a73..b0cd9ff62 100644 --- a/bin/GameIndex.dbf +++ b/bin/GameIndex.dbf @@ -11629,6 +11629,7 @@ Region = NTSC-Unk Serial = SCAJ-20161 Name = Siren 2 Region = NTSC-J +XgKickHack = 1 //SPS. --------------------------------------------- Serial = SCAJ-20162 Name = Rogue Galaxy @@ -11653,6 +11654,7 @@ Region = NTSC-Unk Serial = SCAJ-20167 Name = Siren 2 Region = NTSC-Ch-J +XgKickHack = 1 //SPS. --------------------------------------------- Serial = SCAJ-20168 Name = Rule of Rose @@ -12085,6 +12087,7 @@ Region = NTSC-K Serial = SCKA-20069 Name = Siren 2 Region = NTSC-K +XgKickHack = 1 //SPS. --------------------------------------------- Serial = SCKA-20070 Name = Ace Combat Zero - The Belkan War @@ -12807,6 +12810,7 @@ Serial = SCPS-15106 Name = Siren 2 Region = NTSC-J Compat = 4 +XgKickHack = 1 //SPS. --------------------------------------------- Serial = SCPS-15107 Name = Gunparade Orchestra - Midori no Shou [Limited Edition] @@ -13109,6 +13113,7 @@ Region = NTSC-J Serial = SCPS-19326 Name = Siren 2 [PlayStation 2 The Best] Region = NTSC-J +XgKickHack = 1 //SPS. --------------------------------------------- Serial = SCPS-19327 Name = Ape Escape 3 [PlayStation 2 the Best - Reprint] @@ -30648,6 +30653,7 @@ Serial = SCES-53851 Name = Forbidden Siren 2 Region = PAL-M5 Compat = 4 +XgKickHack = 1 //SPS. --------------------------------------------- Serial = SCES-53879 Name = Buzz! The Big Quiz From a0e960b77dc396fb844dcdcdd1d225bd86fb7b1d Mon Sep 17 00:00:00 2001 From: "sudonim1@gmail.com" Date: Tue, 9 Apr 2013 22:17:49 +0000 Subject: [PATCH 60/81] GSDX: Disable a buggy vertex tracer optimisation in GetTextureMinMax (produces a rectangle with a negative dimension leaving it still empty after the follow block which is likely a hack itself). Fixes textures in Kingdom Hearts 2's tron stage. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5610 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSState.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index 093b2ec81..af6289f91 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -2562,6 +2562,9 @@ void GSState::GetTextureMinMax(GSVector4i& r, const GIFRegTEX0& TEX0, const GIFR __assume(0); } +// Kingdom Hearts 2's tron section shows a bug with the CLAMP_REPEAT code here. +// This is just an optimisation so it's disabled until the bug is found. +#if 0 if(wms + wmt < 6) { GSVector4 st = m_vt.m_min.t.xyxy(m_vt.m_max.t); @@ -2577,6 +2580,7 @@ void GSState::GetTextureMinMax(GSVector4i& r, const GIFRegTEX0& TEX0, const GIFR int mask = 0; + // This part is suspicious, as far as I can tell it zeroes fields if tw/th aren't 0, which is probably not the intent if(wms == CLAMP_REPEAT || wmt == CLAMP_REPEAT) { u = uv & GSVector4i::xffffffff().srl32(32 - tw); @@ -2622,6 +2626,7 @@ void GSState::GetTextureMinMax(GSVector4i& r, const GIFRegTEX0& TEX0, const GIFR __assume(0); } } +#endif vr = vr.rintersect(tr); From c4d9ce2e0524f31d88f6c84f3547e56d015b1644 Mon Sep 17 00:00:00 2001 From: "ramapcsx2.code" Date: Wed, 10 Apr 2013 11:48:27 +0000 Subject: [PATCH 61/81] GSdx: Fixed a missing clut offset which broke Disney's Golf. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5611 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSClut.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/GSdx/GSClut.cpp b/plugins/GSdx/GSClut.cpp index f61dabcfe..fda7003da 100644 --- a/plugins/GSdx/GSClut.cpp +++ b/plugins/GSdx/GSClut.cpp @@ -282,6 +282,8 @@ void GSClut::Read32(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) case PSM_PSMT8: case PSM_PSMT8H: // ASSERT(TEX0.CSA == 0); // sfex + // The clut offset was missing here, broke Disney's Golf + clut += (TEX0.CSA & 15) << 4; ReadCLUT_T32_I8(clut, m_buff32); break; case PSM_PSMT4: From be7e1163b4f7e3fe19876462fb26cd082ffb3ab4 Mon Sep 17 00:00:00 2001 From: "sudonim1@gmail.com" Date: Wed, 10 Apr 2013 15:57:21 +0000 Subject: [PATCH 62/81] GSDX: Fixed GetTextureMinMax's vertex tracer interaction properly and added some comments. It wasn't the suspicious code, that actually seems to be correct. The rempty() case should now be unnecessary except in case of bad register settings, but that's outside of our control so it needs to stay until code's added for that case. A console warning would be appropriate. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5612 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSState.cpp | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index af6289f91..c1047e814 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -2562,10 +2562,7 @@ void GSState::GetTextureMinMax(GSVector4i& r, const GIFRegTEX0& TEX0, const GIFR __assume(0); } -// Kingdom Hearts 2's tron section shows a bug with the CLAMP_REPEAT code here. -// This is just an optimisation so it's disabled until the bug is found. -#if 0 - if(wms + wmt < 6) + if(wms != CLAMP_REGION_REPEAT || wmt != CLAMP_REGION_REPEAT) { GSVector4 st = m_vt.m_min.t.xyxy(m_vt.m_max.t); @@ -2580,7 +2577,7 @@ void GSState::GetTextureMinMax(GSVector4i& r, const GIFRegTEX0& TEX0, const GIFR int mask = 0; - // This part is suspicious, as far as I can tell it zeroes fields if tw/th aren't 0, which is probably not the intent + // See commented code below for the meaning of mask if(wms == CLAMP_REPEAT || wmt == CLAMP_REPEAT) { u = uv & GSVector4i::xffffffff().srl32(32 - tw); @@ -2592,11 +2589,17 @@ void GSState::GetTextureMinMax(GSVector4i& r, const GIFRegTEX0& TEX0, const GIFR mask = (uu.upl32(vv) == uu.uph32(vv)).mask(); } - uv = uv.rintersect(tr); + uv = uv.rintersect(vr - GSVector4i(0,0,1,1)); switch(wms) { case CLAMP_REPEAT: + // This commented code cannot be used directly because it needs uv before the intersection + /*if (uv_.x >> tw == uv_.z >> tw) + { + vr.x = max(vr.x, (uv_.x & ((1 << tw) - 1))); + vr.z = min(vr.z, (uv_.z & ((1 << tw) - 1)) + 1); + }*/ if(mask & 0x000f) {if(vr.x < u.x) vr.x = u.x; if(vr.z > u.z + 1) vr.z = u.z + 1;} break; case CLAMP_CLAMP: @@ -2613,6 +2616,11 @@ void GSState::GetTextureMinMax(GSVector4i& r, const GIFRegTEX0& TEX0, const GIFR switch(wmt) { case CLAMP_REPEAT: + /*if (uv_.y >> th == uv_.w >> th) + { + vr.y = max(vr.y, (uv_.y & ((1 << th) - 1))); + vr.w = min(vr.w, (uv_.w & ((1 << th) - 1)) + 1); + }*/ if(mask & 0xf000) {if(vr.y < v.y) vr.y = v.y; if(vr.w > v.w + 1) vr.w = v.w + 1;} break; case CLAMP_CLAMP: @@ -2626,16 +2634,16 @@ void GSState::GetTextureMinMax(GSVector4i& r, const GIFRegTEX0& TEX0, const GIFR __assume(0); } } -#endif vr = vr.rintersect(tr); + // This really shouldn't happen now except with the clamping region set entirely outside the texture, + // special handling should be written for that case. if(vr.rempty()) { // NOTE: this can happen when texcoords are all outside the texture or clamping area is zero, but we can't // let the texture cache update nothing, the sampler will still need a single texel from the border somewhere // examples: - // - ICO opening menu (texture looks like the miniature silhouette of everything except the sky) // - THPS (no visible problems) // - NFSMW (strange rectangles on screen, might be unrelated) From 2fbcafc85e3f8fd84340c68e147d3edacd6f34d0 Mon Sep 17 00:00:00 2001 From: "sudonim1@gmail.com" Date: Wed, 10 Apr 2013 17:55:02 +0000 Subject: [PATCH 63/81] GSDX: Implemented CLUT temporary buffer wrapping by mirroring writes and hopefully fixed all CSA related bugs. There are fewer asserts on register values in the code now. I'm only about 75% confident in this code. Games might be broken. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5613 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSClut.cpp | 48 ++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/plugins/GSdx/GSClut.cpp b/plugins/GSdx/GSClut.cpp index fda7003da..6c76c56d9 100644 --- a/plugins/GSdx/GSClut.cpp +++ b/plugins/GSdx/GSClut.cpp @@ -30,7 +30,7 @@ GSClut::GSClut(GSLocalMemory* mem) { uint8* p = (uint8*)vmalloc(CLUT_ALLOC_SIZE, false); - m_clut = (uint16*)&p[0]; // 1k + 1k for buffer overruns (TODO: wrap CSM2 writes, too) + m_clut = (uint16*)&p[0]; // 1k + 1k for mirrored area simulating wrapping memory m_buff32 = (uint32*)&p[2048]; // 1k m_buff64 = (uint64*)&p[4096]; // 2k m_write.dirty = true; @@ -124,31 +124,43 @@ void GSClut::Write(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT) m_read.dirty = true; (this->*m_wc[TEX0.CSM][TEX0.CPSM][TEX0.PSM])(TEX0, TEXCLUT); + + // Mirror write to other half of buffer to simulate wrapping memory + int offset = (TEX0.CSA & (TEX0.CPSM < PSM_PSMCT16 ? 15 : 31)) * 16; + if (TEX0.PSM == PSM_PSMT8 || TEX0.PSM == PSM_PSMT8H) + { + int size = TEX0.CPSM < PSM_PSMCT16 ? 512 : 256; + + memcpy(m_clut + 512 + offset, m_clut + offset, sizeof *m_clut * min(size, 512 - offset)); + memcpy(m_clut, m_clut + 512, sizeof *m_clut * max(0, size + offset - 512)); + } + else + { + int size = 16; + + memcpy(m_clut + 512 + offset, m_clut + offset, sizeof *m_clut * size); + if (TEX0.CPSM < PSM_PSMCT16) + memcpy(m_clut + 512 + 256 + offset, m_clut + 256 + offset, sizeof *m_clut * size); + } } void GSClut::WriteCLUT32_I8_CSM1(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT) { ALIGN_STACK(32); - // ASSERT(TEX0.CSA == 0); // sfex - - WriteCLUT_T32_I8_CSM1((uint32*)m_mem->BlockPtr32(0, 0, TEX0.CBP, 1), m_clut); + WriteCLUT_T32_I8_CSM1((uint32*)m_mem->BlockPtr32(0, 0, TEX0.CBP, 1), m_clut + ((TEX0.CSA & 15) << 4)); } void GSClut::WriteCLUT32_I4_CSM1(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT) { ALIGN_STACK(32); - ASSERT(TEX0.CSA < 16); - WriteCLUT_T32_I4_CSM1((uint32*)m_mem->BlockPtr32(0, 0, TEX0.CBP, 1), m_clut + ((TEX0.CSA & 15) << 4)); } void GSClut::WriteCLUT16_I8_CSM1(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT) { - ASSERT(TEX0.CSA < 16); - - WriteCLUT_T16_I8_CSM1((uint16*)m_mem->BlockPtr16(0, 0, TEX0.CBP, 1), m_clut + ((TEX0.CSA & 15) << 4)); + WriteCLUT_T16_I8_CSM1((uint16*)m_mem->BlockPtr16(0, 0, TEX0.CBP, 1), m_clut + (TEX0.CSA << 4)); } void GSClut::WriteCLUT16_I4_CSM1(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT) @@ -158,9 +170,7 @@ void GSClut::WriteCLUT16_I4_CSM1(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TE void GSClut::WriteCLUT16S_I8_CSM1(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT) { - ASSERT(TEX0.CSA < 16); - - WriteCLUT_T16_I8_CSM1((uint16*)m_mem->BlockPtr16S(0, 0, TEX0.CBP, 1), m_clut + ((TEX0.CSA & 15) << 4)); + WriteCLUT_T16_I8_CSM1((uint16*)m_mem->BlockPtr16S(0, 0, TEX0.CBP, 1), m_clut + (TEX0.CSA << 4)); } void GSClut::WriteCLUT16S_I4_CSM1(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT) @@ -175,7 +185,7 @@ template void GSClut::WriteCLUT32_CSM2(const GIFRegTEX0& TEX0, const GIFR uint32* RESTRICT s = &m_mem->m_vm32[o->pixel.row[TEXCLUT.COV]]; int* RESTRICT col = &o->pixel.col[0][TEXCLUT.COU << 4]; - uint16* RESTRICT clut = m_clut + (TEX0.CSA << 4); + uint16* RESTRICT clut = m_clut + ((TEX0.CSA & 15) << 4); for(int i = 0; i < n; i++) { @@ -231,13 +241,12 @@ void GSClut::Read(const GIFRegTEX0& TEX0) { case PSM_PSMT8: case PSM_PSMT8H: - ASSERT(TEX0.CSA == 0); + clut += (TEX0.CSA & 15) << 4; ReadCLUT_T32_I8(clut, m_buff32); break; case PSM_PSMT4: case PSM_PSMT4HL: case PSM_PSMT4HH: - //ASSERT(TEX0.CSA < 16); clut += (TEX0.CSA & 15) << 4; ReadCLUT_T32_I4(clut, m_buff32, m_buff64); break; @@ -249,8 +258,7 @@ void GSClut::Read(const GIFRegTEX0& TEX0) { case PSM_PSMT8: case PSM_PSMT8H: - ASSERT(TEX0.CSA < 16); - clut += (TEX0.CSA & 15) << 4; + clut += TEX0.CSA << 4; ReadCLUT_T16_I8(clut, m_buff32); break; case PSM_PSMT4: @@ -281,15 +289,12 @@ void GSClut::Read32(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) { case PSM_PSMT8: case PSM_PSMT8H: - // ASSERT(TEX0.CSA == 0); // sfex - // The clut offset was missing here, broke Disney's Golf clut += (TEX0.CSA & 15) << 4; ReadCLUT_T32_I8(clut, m_buff32); break; case PSM_PSMT4: case PSM_PSMT4HL: case PSM_PSMT4HH: - //ASSERT(TEX0.CSA < 16); // Idol Janshi Suchie-Pai IV (highlighted menu item, mahjong tiles) clut += (TEX0.CSA & 15) << 4; // TODO: merge these functions ReadCLUT_T32_I4(clut, m_buff32); @@ -303,8 +308,7 @@ void GSClut::Read32(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) { case PSM_PSMT8: case PSM_PSMT8H: - ASSERT(TEX0.CSA < 16); - clut += (TEX0.CSA & 15) << 4; + clut += TEX0.CSA << 4; Expand16(clut, m_buff32, 256, TEXA); break; case PSM_PSMT4: From f0c76c3244e65a8afd6edff6e91f499c0e683c79 Mon Sep 17 00:00:00 2001 From: "avihal@gmail.com" Date: Fri, 12 Apr 2013 00:23:05 +0000 Subject: [PATCH 64/81] Cheat files: If no disc is inserted, treat CRC as 00000000 when trying to load pnach files (previously, empty CRC would result in *.pnach wildcard, which tried to load all pnach files). git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5614 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/Patch.cpp | 7 ++++++- pcsx2/Patch.h | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pcsx2/Patch.cpp b/pcsx2/Patch.cpp index 6a899da4d..faf1b57ec 100644 --- a/pcsx2/Patch.cpp +++ b/pcsx2/Patch.cpp @@ -200,8 +200,13 @@ static int LoadCheatsFiles(const wxString& folderName, wxString& fileSpec, const // This routine loads cheats from *.pnach files // Returns number of cheats loaded // Note: Should be called after InitPatches() -int LoadCheats(const wxString& name, const wxString& folderName, const wxString& friendlyName) +int LoadCheats(wxString name, const wxString& folderName, const wxString& friendlyName) { + if (!name.Length()) { + Console.WriteLn(Color_Gray, "Cheats: No CRC, using 00000000 instead."); + name = L"00000000"; + } + int loaded = 0; wxString filespec = name + L"*.pnach"; diff --git a/pcsx2/Patch.h b/pcsx2/Patch.h index ac696252f..a62f8692b 100644 --- a/pcsx2/Patch.h +++ b/pcsx2/Patch.h @@ -58,7 +58,7 @@ namespace PatchFunc } extern void ResetCheatsCount(); -extern int LoadCheats(const wxString& name, const wxString& folderName, const wxString& friendlyName); +extern int LoadCheats(wxString name, const wxString& folderName, const wxString& friendlyName); extern void inifile_command(bool isCheat, const wxString& cmd); extern void inifile_trim(wxString& buffer); From 4ad29982acf256cd9716905ba65add03a5d24e04 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Fri, 12 Apr 2013 09:16:15 +0000 Subject: [PATCH 65/81] microVU: Parametrised D-Bit handling. This *Shouldn't* be needed in retail games, but now it's working it could be useful for homebrew and testing. By default this is now disabled, but can be enabled by editing the parameter in microVU_Misc.h git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5615 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/x86/microVU_Branch.inl | 6 +++--- pcsx2/x86/microVU_Compile.inl | 2 +- pcsx2/x86/microVU_Misc.h | 6 ++++++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/pcsx2/x86/microVU_Branch.inl b/pcsx2/x86/microVU_Branch.inl index e99b0a16c..b6e2a2e99 100644 --- a/pcsx2/x86/microVU_Branch.inl +++ b/pcsx2/x86/microVU_Branch.inl @@ -196,7 +196,7 @@ void normJumpCompile(mV, microFlagCycles& mFC, bool isEvilJump) { void normBranch(mV, microFlagCycles& mFC) { // E-bit or T-Bit or D-Bit Branch - if (mVUup.dBit) + if (mVUup.dBit && doDBitHandling) { u32 tempPC = iPC; xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4)); @@ -307,7 +307,7 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc) { tJMP.SetTarget(); iPC = tempPC; } - if (mVUup.dBit) + if (mVUup.dBit && doDBitHandling) { u32 tempPC = iPC; xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4)); @@ -412,7 +412,7 @@ void normJump(mV, microFlagCycles& mFC) { } incPC(-3); } - if (mVUup.dBit) + if (mVUup.dBit && doDBitHandling) { xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4)); xForwardJump32 eJMP(Jcc_Zero); diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index 349a5be40..0191e4193 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -568,7 +568,7 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) { if(!mVUinfo.isBdelay && !mVUlow.branch) //T/D Bit on branch is handled after the branch, branch delay slots are executed. { if(mVUup.tBit) { mVUDoTBit(mVU, &mFC); } - else if(mVUup.dBit) { mVUDoDBit(mVU, &mFC); } + else if(mVUup.dBit && doDBitHandling) { mVUDoDBit(mVU, &mFC); } } if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); } if (isEvilBlock) { mVUsetupRange(mVU, xPC, 0); normJumpCompile(mVU, mFC, 1); return thisPtr; } diff --git a/pcsx2/x86/microVU_Misc.h b/pcsx2/x86/microVU_Misc.h index 73a9a16e2..47886bf4f 100644 --- a/pcsx2/x86/microVU_Misc.h +++ b/pcsx2/x86/microVU_Misc.h @@ -350,6 +350,12 @@ static const bool doJumpAsSameProgram = 0; // Set to 1 to treat jumps as same pr // constant recompilation problems in certain games. // Note: You MUST disable doJumpCaching if you enable this option. +// Handling of D-Bit in Micro Programs +static const bool doDBitHandling = 0; +// This flag shouldn't be enabled in released versions of games. Any games which +// need this method of pausing the VU should be using the T-Bit instead, however +// this could prove useful for VU debugging. + //------------------------------------------------------------------ // Speed Hacks (can cause infinite loops, SPS, Black Screens, etc...) //------------------------------------------------------------------ From 3f80ce330e9b4b35bc823d5eaa9fef5ac2648a89 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Sat, 13 Apr 2013 19:11:04 +0000 Subject: [PATCH 66/81] CDVD: slightly modified the way PCSX2 checks for oddly sized DVD's. Some CD's weren't providing information as expected so it detected it as a DVD, resulting in nothing but TLB misses. Fixes Impossible Mission, possibly other games that do nothing but TLB miss or fail to load an IRX module. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5616 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/CDVD/CDVDaccess.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pcsx2/CDVD/CDVDaccess.cpp b/pcsx2/CDVD/CDVDaccess.cpp index 3706f5ffd..1352794ab 100644 --- a/pcsx2/CDVD/CDVDaccess.cpp +++ b/pcsx2/CDVD/CDVDaccess.cpp @@ -148,7 +148,11 @@ static int FindDiskType(int mType) { //const cdVolDesc& volDesc = (cdVolDesc&)bleh; //if(volDesc.rootToc.tocSize == 2048) - if(*(u16*)(bleh+166) == 2048) + + //Horrible hack! in CD images position 166 and 171 have block size but not DVD's + //It's not always 2048 however (can be 4096) + //Test Impossible Mission if thia is changed. + if(*(u16*)(bleh+166) == *(u16*)(bleh+171)) iCDType = CDVD_TYPE_DETCTCD; else iCDType = CDVD_TYPE_DETCTDVDS; From cd7c24895c84ec2c792b63716a374d06750d6471 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Sat, 13 Apr 2013 22:04:35 +0000 Subject: [PATCH 67/81] DMA/Path3 Masking: Shameful hack to make Wallace & Gromit in Project Zoo work. Game does something stupid, not sure how we will resolve it properly, but this will be harmless to any games not using Path3 masking. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5617 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/HwRead.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pcsx2/HwRead.cpp b/pcsx2/HwRead.cpp index f6b34a02d..42f58a3aa 100644 --- a/pcsx2/HwRead.cpp +++ b/pcsx2/HwRead.cpp @@ -142,6 +142,14 @@ mem32_t __fastcall _hwRead32(u32 mem) if(mem == (D1_CHCR + 0x10) && CHECK_VIFFIFOHACK) return psHu32(mem) + (vif1ch.qwc * 16); + if((mem == GIF_CHCR) && !vif1ch.chcr.STR && gifRegs.stat.M3P && gifRegs.stat.APATH != 3) + { + //Hack for Wallace and Gromit Curse Project Zoo - Enabled the mask, then starts a new + //GIF DMA, the mask never comes off and it won't proceed until this is unset. + //Unsetting it works too but messes up other PATH3 games. + //If STR is already unset, it won't make the slightest difference. + return (psHu32(mem) & ~0x100); + } return psHu32(mem); } From 86a2f5a8ec97e0a977ba64b06c8d1425021c2941 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Sun, 14 Apr 2013 10:48:50 +0000 Subject: [PATCH 68/81] gcc: * Fix a couple of GCC warning * Fix build with gcc4.8 (issue 1392) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5618 96395faa-99c1-11dd-bbfe-3dabce05a288 --- common/include/PS2Eext.h | 6 ++---- plugins/GSdx/GS.h | 3 ++- plugins/GSdx/GSDeviceSW.cpp | 2 +- plugins/GSdx/stdafx.h | 6 +++++- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/common/include/PS2Eext.h b/common/include/PS2Eext.h index 6a6c3dcce..e6d6fedcb 100644 --- a/common/include/PS2Eext.h +++ b/common/include/PS2Eext.h @@ -144,20 +144,18 @@ struct PluginConf int ReadInt(const std::string& item, int defval) { int value = defval; - int err = 0; std::string buf = item + " = %d\n"; - if (ConfFile) err=fscanf(ConfFile, buf.c_str(), &value); + if (ConfFile) fscanf(ConfFile, buf.c_str(), &value); return value; } void WriteInt(std::string item, int value) { - int err = 0; std::string buf = item + " = %d\n"; - if (ConfFile) err=fprintf(ConfFile, buf.c_str(), value); + if (ConfFile) fprintf(ConfFile, buf.c_str(), value); } }; diff --git a/plugins/GSdx/GS.h b/plugins/GSdx/GS.h index abfdcdf2b..ec414a3ac 100644 --- a/plugins/GSdx/GS.h +++ b/plugins/GSdx/GS.h @@ -807,7 +807,8 @@ REG_END2 if(PSM == PSM_PSMT4) return TW > 7 || TH > 7; } - return (TBW << 6) < (1u << TW); + // The recast of TBW seems useless but it avoid tons of warning from GCC... + return ((uint32)TBW << 6u) < (1u << TW); } REG_END2 diff --git a/plugins/GSdx/GSDeviceSW.cpp b/plugins/GSdx/GSDeviceSW.cpp index e0acc5125..a56c96ad1 100644 --- a/plugins/GSdx/GSDeviceSW.cpp +++ b/plugins/GSdx/GSDeviceSW.cpp @@ -50,7 +50,7 @@ bool GSDeviceSW::Reset(int w, int h) GSTexture* GSDeviceSW::CreateSurface(int type, int w, int h, bool msaa, int format) { - if(format != 0) return false; // there is only one format + if(format != 0) return NULL; // there is only one format return new GSTextureSW(type, w, h); } diff --git a/plugins/GSdx/stdafx.h b/plugins/GSdx/stdafx.h index b3a6a0d09..cd4a62c7f 100644 --- a/plugins/GSdx/stdafx.h +++ b/plugins/GSdx/stdafx.h @@ -434,7 +434,11 @@ struct aligned_free_second {template void operator()(T& p) {_aligned_fr #ifdef __GNUC__ - __forceinline unsigned long long __rdtsc() + // gcc 4.8 define __rdtsc but unfortunately the compiler crash... + // The redefine allow to skip the gcc __rdtsc version -- Gregory + #define __rdtsc _lnx_rdtsc + //__forceinline unsigned long long __rdtsc() + __forceinline unsigned long long _lnx_rdtsc() { #if defined(__amd64__) || defined(__x86_64__) unsigned long long low, high; From 796bdb8f3788d986e67dbdb29b70a5b95ed70fed Mon Sep 17 00:00:00 2001 From: "ramapcsx2.code" Date: Wed, 17 Apr 2013 10:46:57 +0000 Subject: [PATCH 69/81] Soundtouch update from 1.5 to 1.71 as per patch from lincolnh_br. There's been changes in the VS2008 project file which we may want to look at and port to 2010/2012 separately but it builds like this in 2010 here. I want to wait and see if there's any issues with Linux first, too. Thanks to lincolnh_br :) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5619 96395faa-99c1-11dd-bbfe-3dabce05a288 --- 3rdparty/SoundTouch/AAFilter.cpp | 26 +- 3rdparty/SoundTouch/AAFilter.h | 22 +- 3rdparty/SoundTouch/BPMDetect.cpp | 370 ++++++++ 3rdparty/SoundTouch/BPMDetect.h | 33 +- 3rdparty/SoundTouch/FIFOSampleBuffer.cpp | 66 +- 3rdparty/SoundTouch/FIFOSampleBuffer.h | 54 +- 3rdparty/SoundTouch/FIFOSamplePipe.h | 55 +- 3rdparty/SoundTouch/FIRFilter.cpp | 68 +- 3rdparty/SoundTouch/FIRFilter.h | 63 +- 3rdparty/SoundTouch/Makefile.am | 71 +- 3rdparty/SoundTouch/PeakFinder.cpp | 276 ++++++ 3rdparty/SoundTouch/PeakFinder.h | 97 ++ 3rdparty/SoundTouch/README.html | 1001 ++++++++++---------- 3rdparty/SoundTouch/RateTransposer.cpp | 128 ++- 3rdparty/SoundTouch/RateTransposer.h | 42 +- 3rdparty/SoundTouch/STTypes.h | 144 +-- 3rdparty/SoundTouch/SoundTouch.cpp | 129 +-- 3rdparty/SoundTouch/SoundTouch.h | 87 +- 3rdparty/SoundTouch/TDStretch.cpp | 475 +++------- 3rdparty/SoundTouch/TDStretch.h | 97 +- 3rdparty/SoundTouch/cpu_detect.h | 6 +- 3rdparty/SoundTouch/cpu_detect_x86.cpp | 137 +++ 3rdparty/SoundTouch/cpu_detect_x86_gcc.cpp | 23 +- 3rdparty/SoundTouch/cpu_detect_x86_win.cpp | 26 +- 3rdparty/SoundTouch/mmx_optimized.cpp | 45 +- 3rdparty/SoundTouch/sse_optimized.cpp | 227 +---- 26 files changed, 2199 insertions(+), 1569 deletions(-) create mode 100644 3rdparty/SoundTouch/BPMDetect.cpp create mode 100644 3rdparty/SoundTouch/PeakFinder.cpp create mode 100644 3rdparty/SoundTouch/PeakFinder.h create mode 100644 3rdparty/SoundTouch/cpu_detect_x86.cpp diff --git a/3rdparty/SoundTouch/AAFilter.cpp b/3rdparty/SoundTouch/AAFilter.cpp index c73b2c60b..860f7d522 100644 --- a/3rdparty/SoundTouch/AAFilter.cpp +++ b/3rdparty/SoundTouch/AAFilter.cpp @@ -1,9 +1,9 @@ //////////////////////////////////////////////////////////////////////////////// /// /// FIR low-pass (anti-alias) filter with filter coefficient design routine and -/// MMX optimization. -/// -/// Anti-alias filter is used to prevent folding of high frequencies when +/// MMX optimization. +/// +/// Anti-alias filter is used to prevent folding of high frequencies when /// transposing the sample rate with interpolation. /// /// Author : Copyright (c) Olli Parviainen @@ -12,7 +12,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2009-01-11 13:34:24 +0200 (Sun, 11 Jan 2009) $ +// Last changed : $Date: 2009-01-11 09:34:24 -0200 (dom, 11 jan 2009) $ // File revision : $Revision: 4 $ // // $Id: AAFilter.cpp 45 2009-01-11 11:34:24Z oparviai $ @@ -112,21 +112,21 @@ void AAFilter::calculateCoeffs() work = new double[length]; coeffs = new SAMPLETYPE[length]; - fc2 = 2.0 * cutoffFreq; + fc2 = 2.0 * cutoffFreq; wc = PI * fc2; tempCoeff = TWOPI / (double)length; sum = 0; - for (i = 0; i < length; i ++) + for (i = 0; i < length; i ++) { cntTemp = (double)i - (double)(length / 2); temp = cntTemp * wc; - if (temp != 0) + if (temp != 0) { h = fc2 * sin(temp) / temp; // sinc function - } - else + } + else { h = 1.0; } @@ -135,7 +135,7 @@ void AAFilter::calculateCoeffs() temp = w * h; work[i] = temp; - // calc net sum of coefficients + // calc net sum of coefficients sum += temp; } @@ -151,7 +151,7 @@ void AAFilter::calculateCoeffs() // divided by 16384 scaleCoeff = 16384.0f / sum; - for (i = 0; i < length; i ++) + for (i = 0; i < length; i ++) { // scale & round to nearest integer temp = work[i] * scaleCoeff; @@ -169,8 +169,8 @@ void AAFilter::calculateCoeffs() } -// Applies the filter to the given sequence of samples. -// Note : The amount of outputted samples is by value of 'filter length' +// Applies the filter to the given sequence of samples. +// Note : The amount of outputted samples is by value of 'filter length' // smaller than the amount of input samples. uint AAFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels) const { diff --git a/3rdparty/SoundTouch/AAFilter.h b/3rdparty/SoundTouch/AAFilter.h index d92a3eac5..6b885e371 100644 --- a/3rdparty/SoundTouch/AAFilter.h +++ b/3rdparty/SoundTouch/AAFilter.h @@ -1,10 +1,10 @@ //////////////////////////////////////////////////////////////////////////////// /// -/// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo -/// while maintaining the original pitch by using a time domain WSOLA-like method +/// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo +/// while maintaining the original pitch by using a time domain WSOLA-like method /// with several performance-increasing tweaks. /// -/// Anti-alias filter is used to prevent folding of high frequencies when +/// Anti-alias filter is used to prevent folding of high frequencies when /// transposing the sample rate with interpolation. /// /// Author : Copyright (c) Olli Parviainen @@ -13,7 +13,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2008-02-10 18:26:55 +0200 (Sun, 10 Feb 2008) $ +// Last changed : $Date: 2008-02-10 14:26:55 -0200 (dom, 10 fev 2008) $ // File revision : $Revision: 4 $ // // $Id: AAFilter.h 11 2008-02-10 16:26:55Z oparviai $ @@ -67,8 +67,8 @@ public: ~AAFilter(); - /// Sets new anti-alias filter cut-off edge frequency, scaled to sampling - /// frequency (nyquist frequency = 0.5). The filter will cut off the + /// Sets new anti-alias filter cut-off edge frequency, scaled to sampling + /// frequency (nyquist frequency = 0.5). The filter will cut off the /// frequencies than that. void setCutoffFreq(double newCutoffFreq); @@ -77,12 +77,12 @@ public: uint getLength() const; - /// Applies the filter to the given sequence of samples. - /// Note : The amount of outputted samples is by value of 'filter length' + /// Applies the filter to the given sequence of samples. + /// Note : The amount of outputted samples is by value of 'filter length' /// smaller than the amount of input samples. - uint evaluate(SAMPLETYPE *dest, - const SAMPLETYPE *src, - uint numSamples, + uint evaluate(SAMPLETYPE *dest, + const SAMPLETYPE *src, + uint numSamples, uint numChannels) const; }; diff --git a/3rdparty/SoundTouch/BPMDetect.cpp b/3rdparty/SoundTouch/BPMDetect.cpp new file mode 100644 index 000000000..34dbb4730 --- /dev/null +++ b/3rdparty/SoundTouch/BPMDetect.cpp @@ -0,0 +1,370 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// Beats-per-minute (BPM) detection routine. +/// +/// The beat detection algorithm works as follows: +/// - Use function 'inputSamples' to input a chunks of samples to the class for +/// analysis. It's a good idea to enter a large sound file or stream in smallish +/// chunks of around few kilosamples in order not to extinguish too much RAM memory. +/// - Inputted sound data is decimated to approx 500 Hz to reduce calculation burden, +/// which is basically ok as low (bass) frequencies mostly determine the beat rate. +/// Simple averaging is used for anti-alias filtering because the resulting signal +/// quality isn't of that high importance. +/// - Decimated sound data is enveloped, i.e. the amplitude shape is detected by +/// taking absolute value that's smoothed by sliding average. Signal levels that +/// are below a couple of times the general RMS amplitude level are cut away to +/// leave only notable peaks there. +/// - Repeating sound patterns (e.g. beats) are detected by calculating short-term +/// autocorrelation function of the enveloped signal. +/// - After whole sound data file has been analyzed as above, the bpm level is +/// detected by function 'getBpm' that finds the highest peak of the autocorrelation +/// function, calculates it's precise location and converts this reading to bpm's. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2012-08-30 16:45:25 -0300 (qui, 30 ago 2012) $ +// File revision : $Revision: 4 $ +// +// $Id: BPMDetect.cpp 149 2012-08-30 19:45:25Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// License : +// +// SoundTouch audio processing library +// Copyright (c) Olli Parviainen +// +// 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "FIFOSampleBuffer.h" +#include "PeakFinder.h" +#include "BPMDetect.h" + +using namespace soundtouch; + +#define INPUT_BLOCK_SAMPLES 2048 +#define DECIMATED_BLOCK_SAMPLES 256 + +/// decay constant for calculating RMS volume sliding average approximation +/// (time constant is about 10 sec) +const float avgdecay = 0.99986f; + +/// Normalization coefficient for calculating RMS sliding average approximation. +const float avgnorm = (1 - avgdecay); + + +//////////////////////////////////////////////////////////////////////////////// + +// Enable following define to create bpm analysis file: + +// #define _CREATE_BPM_DEBUG_FILE + +#ifdef _CREATE_BPM_DEBUG_FILE + + #define DEBUGFILE_NAME "c:\\temp\\soundtouch-bpm-debug.txt" + + static void _SaveDebugData(const float *data, int minpos, int maxpos, double coeff) + { + FILE *fptr = fopen(DEBUGFILE_NAME, "wt"); + int i; + + if (fptr) + { + printf("\n\nWriting BPM debug data into file " DEBUGFILE_NAME "\n\n"); + for (i = minpos; i < maxpos; i ++) + { + fprintf(fptr, "%d\t%.1lf\t%f\n", i, coeff / (double)i, data[i]); + } + fclose(fptr); + } + } +#else + #define _SaveDebugData(a,b,c,d) +#endif + +//////////////////////////////////////////////////////////////////////////////// + + +BPMDetect::BPMDetect(int numChannels, int aSampleRate) +{ + this->sampleRate = aSampleRate; + this->channels = numChannels; + + decimateSum = 0; + decimateCount = 0; + + envelopeAccu = 0; + + // Initialize RMS volume accumulator to RMS level of 1500 (out of 32768) that's + // safe initial RMS signal level value for song data. This value is then adapted + // to the actual level during processing. +#ifdef SOUNDTOUCH_INTEGER_SAMPLES + // integer samples + RMSVolumeAccu = (1500 * 1500) / avgnorm; +#else + // float samples, scaled to range [-1..+1[ + RMSVolumeAccu = (0.045f * 0.045f) / avgnorm; +#endif + + // choose decimation factor so that result is approx. 1000 Hz + decimateBy = sampleRate / 1000; + assert(decimateBy > 0); + assert(INPUT_BLOCK_SAMPLES < decimateBy * DECIMATED_BLOCK_SAMPLES); + + // Calculate window length & starting item according to desired min & max bpms + windowLen = (60 * sampleRate) / (decimateBy * MIN_BPM); + windowStart = (60 * sampleRate) / (decimateBy * MAX_BPM); + + assert(windowLen > windowStart); + + // allocate new working objects + xcorr = new float[windowLen]; + memset(xcorr, 0, windowLen * sizeof(float)); + + // allocate processing buffer + buffer = new FIFOSampleBuffer(); + // we do processing in mono mode + buffer->setChannels(1); + buffer->clear(); +} + + + +BPMDetect::~BPMDetect() +{ + delete[] xcorr; + delete buffer; +} + + + +/// convert to mono, low-pass filter & decimate to about 500 Hz. +/// return number of outputted samples. +/// +/// Decimation is used to remove the unnecessary frequencies and thus to reduce +/// the amount of data needed to be processed as calculating autocorrelation +/// function is a very-very heavy operation. +/// +/// Anti-alias filtering is done simply by averaging the samples. This is really a +/// poor-man's anti-alias filtering, but it's not so critical in this kind of application +/// (it'd also be difficult to design a high-quality filter with steep cut-off at very +/// narrow band) +int BPMDetect::decimate(SAMPLETYPE *dest, const SAMPLETYPE *src, int numsamples) +{ + int count, outcount; + LONG_SAMPLETYPE out; + + assert(channels > 0); + assert(decimateBy > 0); + outcount = 0; + for (count = 0; count < numsamples; count ++) + { + int j; + + // convert to mono and accumulate + for (j = 0; j < channels; j ++) + { + decimateSum += src[j]; + } + src += j; + + decimateCount ++; + if (decimateCount >= decimateBy) + { + // Store every Nth sample only + out = (LONG_SAMPLETYPE)(decimateSum / (decimateBy * channels)); + decimateSum = 0; + decimateCount = 0; +#ifdef SOUNDTOUCH_INTEGER_SAMPLES + // check ranges for sure (shouldn't actually be necessary) + if (out > 32767) + { + out = 32767; + } + else if (out < -32768) + { + out = -32768; + } +#endif // SOUNDTOUCH_INTEGER_SAMPLES + dest[outcount] = (SAMPLETYPE)out; + outcount ++; + } + } + return outcount; +} + + + +// Calculates autocorrelation function of the sample history buffer +void BPMDetect::updateXCorr(int process_samples) +{ + int offs; + SAMPLETYPE *pBuffer; + + assert(buffer->numSamples() >= (uint)(process_samples + windowLen)); + + pBuffer = buffer->ptrBegin(); + for (offs = windowStart; offs < windowLen; offs ++) + { + LONG_SAMPLETYPE sum; + int i; + + sum = 0; + for (i = 0; i < process_samples; i ++) + { + sum += pBuffer[i] * pBuffer[i + offs]; // scaling the sub-result shouldn't be necessary + } +// xcorr[offs] *= xcorr_decay; // decay 'xcorr' here with suitable coefficients + // if it's desired that the system adapts automatically to + // various bpms, e.g. in processing continouos music stream. + // The 'xcorr_decay' should be a value that's smaller than but + // close to one, and should also depend on 'process_samples' value. + + xcorr[offs] += (float)sum; + } +} + + +// Calculates envelope of the sample data +void BPMDetect::calcEnvelope(SAMPLETYPE *samples, int numsamples) +{ + const static double decay = 0.7f; // decay constant for smoothing the envelope + const static double norm = (1 - decay); + + int i; + LONG_SAMPLETYPE out; + double val; + + for (i = 0; i < numsamples; i ++) + { + // calc average RMS volume + RMSVolumeAccu *= avgdecay; + val = (float)fabs((float)samples[i]); + RMSVolumeAccu += val * val; + + // cut amplitudes that are below cutoff ~2 times RMS volume + // (we're interested in peak values, not the silent moments) + if (val < 0.5 * sqrt(RMSVolumeAccu * avgnorm)) + { + val = 0; + } + + // smooth amplitude envelope + envelopeAccu *= decay; + envelopeAccu += val; + out = (LONG_SAMPLETYPE)(envelopeAccu * norm); + +#ifdef SOUNDTOUCH_INTEGER_SAMPLES + // cut peaks (shouldn't be necessary though) + if (out > 32767) out = 32767; +#endif // SOUNDTOUCH_INTEGER_SAMPLES + samples[i] = (SAMPLETYPE)out; + } +} + + + +void BPMDetect::inputSamples(const SAMPLETYPE *samples, int numSamples) +{ + SAMPLETYPE decimated[DECIMATED_BLOCK_SAMPLES]; + + // iterate so that max INPUT_BLOCK_SAMPLES processed per iteration + while (numSamples > 0) + { + int block; + int decSamples; + + block = (numSamples > INPUT_BLOCK_SAMPLES) ? INPUT_BLOCK_SAMPLES : numSamples; + + // decimate. note that converts to mono at the same time + decSamples = decimate(decimated, samples, block); + samples += block * channels; + numSamples -= block; + + // envelope new samples and add them to buffer + calcEnvelope(decimated, decSamples); + buffer->putSamples(decimated, decSamples); + } + + // when the buffer has enought samples for processing... + if ((int)buffer->numSamples() > windowLen) + { + int processLength; + + // how many samples are processed + processLength = (int)buffer->numSamples() - windowLen; + + // ... calculate autocorrelations for oldest samples... + updateXCorr(processLength); + // ... and remove them from the buffer + buffer->receiveSamples(processLength); + } +} + + + +void BPMDetect::removeBias() +{ + int i; + float minval = 1e12f; // arbitrary large number + + for (i = windowStart; i < windowLen; i ++) + { + if (xcorr[i] < minval) + { + minval = xcorr[i]; + } + } + + for (i = windowStart; i < windowLen; i ++) + { + xcorr[i] -= minval; + } +} + + +float BPMDetect::getBpm() +{ + double peakPos; + double coeff; + PeakFinder peakFinder; + + coeff = 60.0 * ((double)sampleRate / (double)decimateBy); + + // save bpm debug analysis data if debug data enabled + _SaveDebugData(xcorr, windowStart, windowLen, coeff); + + // remove bias from xcorr data + removeBias(); + + // find peak position + peakPos = peakFinder.detectPeak(xcorr, windowStart, windowLen); + + assert(decimateBy != 0); + if (peakPos < 1e-9) return 0.0; // detection failed. + + // calculate BPM + return (float) (coeff / peakPos); +} diff --git a/3rdparty/SoundTouch/BPMDetect.h b/3rdparty/SoundTouch/BPMDetect.h index 75289c6b9..88628def0 100644 --- a/3rdparty/SoundTouch/BPMDetect.h +++ b/3rdparty/SoundTouch/BPMDetect.h @@ -14,10 +14,10 @@ /// taking absolute value that's smoothed by sliding average. Signal levels that /// are below a couple of times the general RMS amplitude level are cut away to /// leave only notable peaks there. -/// - Repeating sound patterns (e.g. beats) are detected by calculating short-term +/// - Repeating sound patterns (e.g. beats) are detected by calculating short-term /// autocorrelation function of the enveloped signal. -/// - After whole sound data file has been analyzed as above, the bpm level is -/// detected by function 'getBpm' that finds the highest peak of the autocorrelation +/// - After whole sound data file has been analyzed as above, the bpm level is +/// detected by function 'getBpm' that finds the highest peak of the autocorrelation /// function, calculates it's precise location and converts this reading to bpm's. /// /// Author : Copyright (c) Olli Parviainen @@ -26,10 +26,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2009-02-21 18:00:14 +0200 (Sat, 21 Feb 2009) $ +// Last changed : $Date: 2012-08-30 16:53:44 -0300 (qui, 30 ago 2012) $ // File revision : $Revision: 4 $ // -// $Id: BPMDetect.h 63 2009-02-21 16:00:14Z oparviai $ +// $Id: BPMDetect.h 150 2012-08-30 19:53:44Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -67,7 +67,7 @@ namespace soundtouch #define MIN_BPM 29 /// Maximum allowed BPM rate. Used to restrict accepted result below a reasonable limit. -#define MAX_BPM 230 +#define MAX_BPM 200 /// Class for calculating BPM rate for audio data. @@ -76,12 +76,12 @@ class BPMDetect protected: /// Auto-correlation accumulator bins. float *xcorr; - + /// Amplitude envelope sliding average approximation level accumulator - float envelopeAccu; + double envelopeAccu; /// RMS volume sliding average approximation level accumulator - float RMSVolumeAccu; + double RMSVolumeAccu; /// Sample average counter. int decimateCount; @@ -104,12 +104,12 @@ protected: /// Beginning of auto-correlation window: Autocorrelation isn't being updated for /// the first these many correlation bins. int windowStart; - + /// FIFO-buffer for decimated processing samples. soundtouch::FIFOSampleBuffer *buffer; - /// Updates auto-correlation function for given number of decimated samples that - /// are read from the internal 'buffer' pipe (samples aren't removed from the pipe + /// Updates auto-correlation function for given number of decimated samples that + /// are read from the internal 'buffer' pipe (samples aren't removed from the pipe /// though). void updateXCorr(int process_samples /// How many samples are processed. ); @@ -128,6 +128,9 @@ protected: int numsamples ///< Number of samples in buffer ); + /// remove constant bias from xcorr data + void removeBias(); + public: /// Constructor. BPMDetect(int numChannels, ///< Number of channels in sample data. @@ -139,9 +142,9 @@ public: /// Inputs a block of samples for analyzing: Envelopes the samples and then /// updates the autocorrelation estimation. When whole song data has been input - /// in smaller blocks using this function, read the resulting bpm with 'getBpm' - /// function. - /// + /// in smaller blocks using this function, read the resulting bpm with 'getBpm' + /// function. + /// /// Notice that data in 'samples' array can be disrupted in processing. void inputSamples(const soundtouch::SAMPLETYPE *samples, ///< Pointer to input/working data buffer int numSamples ///< Number of samples in buffer diff --git a/3rdparty/SoundTouch/FIFOSampleBuffer.cpp b/3rdparty/SoundTouch/FIFOSampleBuffer.cpp index a395315ac..80314d81f 100644 --- a/3rdparty/SoundTouch/FIFOSampleBuffer.cpp +++ b/3rdparty/SoundTouch/FIFOSampleBuffer.cpp @@ -1,12 +1,12 @@ //////////////////////////////////////////////////////////////////////////////// /// -/// A buffer class for temporarily storaging sound samples, operates as a +/// A buffer class for temporarily storaging sound samples, operates as a /// first-in-first-out pipe. /// -/// Samples are added to the end of the sample buffer with the 'putSamples' +/// Samples are added to the end of the sample buffer with the 'putSamples' /// function, and are received from the beginning of the buffer by calling -/// the 'receiveSamples' function. The class automatically removes the -/// outputted samples from the buffer, as well as grows the buffer size +/// the 'receiveSamples' function. The class automatically removes the +/// outputted samples from the buffer, as well as grows the buffer size /// whenever necessary. /// /// Author : Copyright (c) Olli Parviainen @@ -15,10 +15,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2009-02-27 19:24:42 +0200 (Fri, 27 Feb 2009) $ +// Last changed : $Date: 2012-11-08 16:53:01 -0200 (qui, 08 nov 2012) $ // File revision : $Revision: 4 $ // -// $Id: FIFOSampleBuffer.cpp 68 2009-02-27 17:24:42Z oparviai $ +// $Id: FIFOSampleBuffer.cpp 160 2012-11-08 18:53:01Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -47,7 +47,6 @@ #include #include #include -#include #include "FIFOSampleBuffer.h" @@ -63,7 +62,7 @@ FIFOSampleBuffer::FIFOSampleBuffer(int numChannels) samplesInBuffer = 0; bufferPos = 0; channels = (uint)numChannels; - ensureCapacity(32); // allocate initial capacity + ensureCapacity(32); // allocate initial capacity } @@ -89,11 +88,11 @@ void FIFOSampleBuffer::setChannels(int numChannels) // if output location pointer 'bufferPos' isn't zero, 'rewinds' the buffer and -// zeroes this pointer by copying samples from the 'bufferPos' pointer +// zeroes this pointer by copying samples from the 'bufferPos' pointer // location on to the beginning of the buffer. void FIFOSampleBuffer::rewind() { - if (buffer && bufferPos) + if (buffer && bufferPos) { memmove(buffer, ptrBegin(), sizeof(SAMPLETYPE) * channels * samplesInBuffer); bufferPos = 0; @@ -101,7 +100,7 @@ void FIFOSampleBuffer::rewind() } -// Adds 'numSamples' pcs of samples from the 'samples' memory position to +// Adds 'numSamples' pcs of samples from the 'samples' memory position to // the sample buffer. void FIFOSampleBuffer::putSamples(const SAMPLETYPE *samples, uint nSamples) { @@ -114,7 +113,7 @@ void FIFOSampleBuffer::putSamples(const SAMPLETYPE *samples, uint nSamples) // samples. // // This function is used to update the number of samples in the sample buffer -// when accessing the buffer directly with 'ptrEnd' function. Please be +// when accessing the buffer directly with 'ptrEnd' function. Please be // careful though! void FIFOSampleBuffer::putSamples(uint nSamples) { @@ -126,31 +125,31 @@ void FIFOSampleBuffer::putSamples(uint nSamples) } -// Returns a pointer to the end of the used part of the sample buffer (i.e. -// where the new samples are to be inserted). This function may be used for -// inserting new samples into the sample buffer directly. Please be careful! +// Returns a pointer to the end of the used part of the sample buffer (i.e. +// where the new samples are to be inserted). This function may be used for +// inserting new samples into the sample buffer directly. Please be careful! // // Parameter 'slackCapacity' tells the function how much free capacity (in // terms of samples) there _at least_ should be, in order to the caller to -// succesfully insert all the required samples to the buffer. When necessary, +// succesfully insert all the required samples to the buffer. When necessary, // the function grows the buffer size to comply with this requirement. // -// When using this function as means for inserting new samples, also remember -// to increase the sample count afterwards, by calling the +// When using this function as means for inserting new samples, also remember +// to increase the sample count afterwards, by calling the // 'putSamples(numSamples)' function. -SAMPLETYPE *FIFOSampleBuffer::ptrEnd(uint slackCapacity) +SAMPLETYPE *FIFOSampleBuffer::ptrEnd(uint slackCapacity) { ensureCapacity(samplesInBuffer + slackCapacity); return buffer + samplesInBuffer * channels; } -// Returns a pointer to the beginning of the currently non-outputted samples. -// This function is provided for accessing the output samples directly. +// Returns a pointer to the beginning of the currently non-outputted samples. +// This function is provided for accessing the output samples directly. // Please be careful! // // When using this function to output samples, also remember to 'remove' the -// outputted samples from the buffer by calling the +// outputted samples from the buffer by calling the // 'receiveSamples(numSamples)' function SAMPLETYPE *FIFOSampleBuffer::ptrBegin() { @@ -167,7 +166,7 @@ void FIFOSampleBuffer::ensureCapacity(uint capacityRequirement) { SAMPLETYPE *tempUnaligned, *temp; - if (capacityRequirement > getCapacity()) + if (capacityRequirement > getCapacity()) { // enlarge the buffer in 4kbyte steps (round up to next 4k boundary) sizeInBytes = (capacityRequirement * channels * sizeof(SAMPLETYPE) + 4095) & (uint)-4096; @@ -175,10 +174,10 @@ void FIFOSampleBuffer::ensureCapacity(uint capacityRequirement) tempUnaligned = new SAMPLETYPE[sizeInBytes / sizeof(SAMPLETYPE) + 16 / sizeof(SAMPLETYPE)]; if (tempUnaligned == NULL) { - throw std::runtime_error("Couldn't allocate memory!\n"); + ST_THROW_RT_ERROR("Couldn't allocate memory!\n"); } // Align the buffer to begin at 16byte cache line boundary for optimal performance - temp = (SAMPLETYPE *)(((ulong)tempUnaligned + 15) & (ulong)-16); + temp = (SAMPLETYPE *)SOUNDTOUCH_ALIGN_POINTER_16(tempUnaligned); if (samplesInBuffer) { memcpy(temp, ptrBegin(), samplesInBuffer * channels * sizeof(SAMPLETYPE)); @@ -187,8 +186,8 @@ void FIFOSampleBuffer::ensureCapacity(uint capacityRequirement) buffer = temp; bufferUnaligned = tempUnaligned; bufferPos = 0; - } - else + } + else { // simply rewind the buffer (if necessary) rewind(); @@ -260,3 +259,16 @@ void FIFOSampleBuffer::clear() samplesInBuffer = 0; bufferPos = 0; } + + +/// allow trimming (downwards) amount of samples in pipeline. +/// Returns adjusted amount of samples +uint FIFOSampleBuffer::adjustAmountOfSamples(uint numSamples) +{ + if (numSamples < samplesInBuffer) + { + samplesInBuffer = numSamples; + } + return samplesInBuffer; +} + diff --git a/3rdparty/SoundTouch/FIFOSampleBuffer.h b/3rdparty/SoundTouch/FIFOSampleBuffer.h index ed31c8db6..5f1eb5f3d 100644 --- a/3rdparty/SoundTouch/FIFOSampleBuffer.h +++ b/3rdparty/SoundTouch/FIFOSampleBuffer.h @@ -1,12 +1,12 @@ //////////////////////////////////////////////////////////////////////////////// /// -/// A buffer class for temporarily storaging sound samples, operates as a +/// A buffer class for temporarily storaging sound samples, operates as a /// first-in-first-out pipe. /// -/// Samples are added to the end of the sample buffer with the 'putSamples' +/// Samples are added to the end of the sample buffer with the 'putSamples' /// function, and are received from the beginning of the buffer by calling -/// the 'receiveSamples' function. The class automatically removes the -/// output samples from the buffer as well as grows the storage size +/// the 'receiveSamples' function. The class automatically removes the +/// output samples from the buffer as well as grows the storage size /// whenever necessary. /// /// Author : Copyright (c) Olli Parviainen @@ -15,10 +15,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2009-02-21 18:00:14 +0200 (Sat, 21 Feb 2009) $ +// Last changed : $Date: 2012-06-13 16:29:53 -0300 (qua, 13 jun 2012) $ // File revision : $Revision: 4 $ // -// $Id: FIFOSampleBuffer.h 63 2009-02-21 16:00:14Z oparviai $ +// $Id: FIFOSampleBuffer.h 143 2012-06-13 19:29:53Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -54,7 +54,7 @@ namespace soundtouch /// Sample buffer working in FIFO (first-in-first-out) principle. The class takes /// care of storage size adjustment and data moving during input/output operations. /// -/// Notice that in case of stereo audio, one sample is considered to consist of +/// Notice that in case of stereo audio, one sample is considered to consist of /// both channel data. class FIFOSampleBuffer : public FIFOSamplePipe { @@ -75,12 +75,12 @@ private: /// Channels, 1=mono, 2=stereo. uint channels; - /// Current position pointer to the buffer. This pointer is increased when samples are + /// Current position pointer to the buffer. This pointer is increased when samples are /// removed from the pipe so that it's necessary to actually rewind buffer (move data) /// only new data when is put to the pipe. uint bufferPos; - /// Rewind the buffer by moving data from position pointed by 'bufferPos' to real + /// Rewind the buffer by moving data from position pointed by 'bufferPos' to real /// beginning of the buffer. void rewind(); @@ -100,27 +100,27 @@ public: /// destructor ~FIFOSampleBuffer(); - /// Returns a pointer to the beginning of the output samples. - /// This function is provided for accessing the output samples directly. + /// Returns a pointer to the beginning of the output samples. + /// This function is provided for accessing the output samples directly. /// Please be careful for not to corrupt the book-keeping! /// /// When using this function to output samples, also remember to 'remove' the - /// output samples from the buffer by calling the + /// output samples from the buffer by calling the /// 'receiveSamples(numSamples)' function virtual SAMPLETYPE *ptrBegin(); - /// Returns a pointer to the end of the used part of the sample buffer (i.e. - /// where the new samples are to be inserted). This function may be used for + /// Returns a pointer to the end of the used part of the sample buffer (i.e. + /// where the new samples are to be inserted). This function may be used for /// inserting new samples into the sample buffer directly. Please be careful /// not corrupt the book-keeping! /// - /// When using this function as means for inserting new samples, also remember - /// to increase the sample count afterwards, by calling the + /// When using this function as means for inserting new samples, also remember + /// to increase the sample count afterwards, by calling the /// 'putSamples(numSamples)' function. SAMPLETYPE *ptrEnd( - uint slackCapacity ///< How much free capacity (in samples) there _at least_ - ///< should be so that the caller can succesfully insert the - ///< desired samples to the buffer. If necessary, the function + uint slackCapacity ///< How much free capacity (in samples) there _at least_ + ///< should be so that the caller can succesfully insert the + ///< desired samples to the buffer. If necessary, the function ///< grows the buffer size to comply with this requirement. ); @@ -130,17 +130,17 @@ public: uint numSamples ///< Number of samples to insert. ); - /// Adjusts the book-keeping to increase number of samples in the buffer without + /// Adjusts the book-keeping to increase number of samples in the buffer without /// copying any actual samples. /// /// This function is used to update the number of samples in the sample buffer - /// when accessing the buffer directly with 'ptrEnd' function. Please be + /// when accessing the buffer directly with 'ptrEnd' function. Please be /// careful though! virtual void putSamples(uint numSamples ///< Number of samples been inserted. ); - /// Output samples from beginning of the sample buffer. Copies requested samples to - /// output buffer and removes them from the sample buffer. If there are less than + /// Output samples from beginning of the sample buffer. Copies requested samples to + /// output buffer and removes them from the sample buffer. If there are less than /// 'numsample' samples in the buffer, returns all that available. /// /// \return Number of samples returned. @@ -148,8 +148,8 @@ public: uint maxSamples ///< How many samples to receive at max. ); - /// Adjusts book-keeping so that given number of samples are removed from beginning of the - /// sample buffer without copying them anywhere. + /// Adjusts book-keeping so that given number of samples are removed from beginning of the + /// sample buffer without copying them anywhere. /// /// Used to reduce the number of samples in the buffer when accessing the sample buffer directly /// with 'ptrBegin' function. @@ -167,6 +167,10 @@ public: /// Clears all the samples. virtual void clear(); + + /// allow trimming (downwards) amount of samples in pipeline. + /// Returns adjusted amount of samples + uint adjustAmountOfSamples(uint numSamples); }; } diff --git a/3rdparty/SoundTouch/FIFOSamplePipe.h b/3rdparty/SoundTouch/FIFOSamplePipe.h index 31dc40f93..805e92597 100644 --- a/3rdparty/SoundTouch/FIFOSamplePipe.h +++ b/3rdparty/SoundTouch/FIFOSamplePipe.h @@ -5,7 +5,7 @@ /// into one end of the pipe with the 'putSamples' function, and the processed /// samples are received from the other end with the 'receiveSamples' function. /// -/// 'FIFOProcessor' : A base class for classes the do signal processing with +/// 'FIFOProcessor' : A base class for classes the do signal processing with /// the samples while operating like a first-in-first-out pipe. When samples /// are input with the 'putSamples' function, the class processes them /// and moves the processed samples to the given 'output' pipe object, which @@ -17,10 +17,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2009-04-13 16:18:48 +0300 (Mon, 13 Apr 2009) $ +// Last changed : $Date: 2012-06-13 16:29:53 -0300 (qua, 13 jun 2012) $ // File revision : $Revision: 4 $ // -// $Id: FIFOSamplePipe.h 69 2009-04-13 13:18:48Z oparviai $ +// $Id: FIFOSamplePipe.h 143 2012-06-13 19:29:53Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -63,12 +63,12 @@ public: virtual ~FIFOSamplePipe() {} - /// Returns a pointer to the beginning of the output samples. - /// This function is provided for accessing the output samples directly. + /// Returns a pointer to the beginning of the output samples. + /// This function is provided for accessing the output samples directly. /// Please be careful for not to corrupt the book-keeping! /// /// When using this function to output samples, also remember to 'remove' the - /// output samples from the buffer by calling the + /// output samples from the buffer by calling the /// 'receiveSamples(numSamples)' function virtual SAMPLETYPE *ptrBegin() = 0; @@ -89,8 +89,8 @@ public: other.receiveSamples(oNumSamples); }; - /// Output samples from beginning of the sample buffer. Copies requested samples to - /// output buffer and removes them from the sample buffer. If there are less than + /// Output samples from beginning of the sample buffer. Copies requested samples to + /// output buffer and removes them from the sample buffer. If there are less than /// 'numsample' samples in the buffer, returns all that available. /// /// \return Number of samples returned. @@ -98,8 +98,8 @@ public: uint maxSamples ///< How many samples to receive at max. ) = 0; - /// Adjusts book-keeping so that given number of samples are removed from beginning of the - /// sample buffer without copying them anywhere. + /// Adjusts book-keeping so that given number of samples are removed from beginning of the + /// sample buffer without copying them anywhere. /// /// Used to reduce the number of samples in the buffer when accessing the sample buffer directly /// with 'ptrBegin' function. @@ -114,16 +114,21 @@ public: /// Clears all the samples. virtual void clear() = 0; + + /// allow trimming (downwards) amount of samples in pipeline. + /// Returns adjusted amount of samples + virtual uint adjustAmountOfSamples(uint numSamples) = 0; + }; -/// Base-class for sound processing routines working in FIFO principle. With this base +/// Base-class for sound processing routines working in FIFO principle. With this base /// class it's easy to implement sound processing stages that can be chained together, -/// so that samples that are fed into beginning of the pipe automatically go through +/// so that samples that are fed into beginning of the pipe automatically go through /// all the processing stages. /// -/// When samples are input to this class, they're first processed and then put to +/// When samples are input to this class, they're first processed and then put to /// the FIFO pipe that's defined as output of this class. This output pipe can be /// either other processing stage or a FIFO sample buffer. class FIFOProcessor :public FIFOSamplePipe @@ -141,7 +146,7 @@ protected: } - /// Constructor. Doesn't define output pipe; it has to be set be + /// Constructor. Doesn't define output pipe; it has to be set be /// 'setOutPipe' function. FIFOProcessor() { @@ -163,12 +168,12 @@ protected: } - /// Returns a pointer to the beginning of the output samples. - /// This function is provided for accessing the output samples directly. + /// Returns a pointer to the beginning of the output samples. + /// This function is provided for accessing the output samples directly. /// Please be careful for not to corrupt the book-keeping! /// /// When using this function to output samples, also remember to 'remove' the - /// output samples from the buffer by calling the + /// output samples from the buffer by calling the /// 'receiveSamples(numSamples)' function virtual SAMPLETYPE *ptrBegin() { @@ -177,8 +182,8 @@ protected: public: - /// Output samples from beginning of the sample buffer. Copies requested samples to - /// output buffer and removes them from the sample buffer. If there are less than + /// Output samples from beginning of the sample buffer. Copies requested samples to + /// output buffer and removes them from the sample buffer. If there are less than /// 'numsample' samples in the buffer, returns all that available. /// /// \return Number of samples returned. @@ -190,8 +195,8 @@ public: } - /// Adjusts book-keeping so that given number of samples are removed from beginning of the - /// sample buffer without copying them anywhere. + /// Adjusts book-keeping so that given number of samples are removed from beginning of the + /// sample buffer without copying them anywhere. /// /// Used to reduce the number of samples in the buffer when accessing the sample buffer directly /// with 'ptrBegin' function. @@ -214,6 +219,14 @@ public: { return output->isEmpty(); } + + /// allow trimming (downwards) amount of samples in pipeline. + /// Returns adjusted amount of samples + virtual uint adjustAmountOfSamples(uint numSamples) + { + return output->adjustAmountOfSamples(numSamples); + } + }; } diff --git a/3rdparty/SoundTouch/FIRFilter.cpp b/3rdparty/SoundTouch/FIRFilter.cpp index 9f7351dce..13a1896ce 100644 --- a/3rdparty/SoundTouch/FIRFilter.cpp +++ b/3rdparty/SoundTouch/FIRFilter.cpp @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// /// -/// General FIR digital filter routines with MMX optimization. +/// General FIR digital filter routines with MMX optimization. /// -/// Note : MMX optimized functions reside in a separate, platform-specific file, +/// Note : MMX optimized functions reside in a separate, platform-specific file, /// e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp' /// /// Author : Copyright (c) Olli Parviainen @@ -11,10 +11,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2009-02-25 19:13:51 +0200 (Wed, 25 Feb 2009) $ +// Last changed : $Date: 2011-09-02 15:56:11 -0300 (sex, 02 set 2011) $ // File revision : $Revision: 4 $ // -// $Id: FIRFilter.cpp 67 2009-02-25 17:13:51Z oparviai $ +// $Id: FIRFilter.cpp 131 2011-09-02 18:56:11Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -43,7 +43,6 @@ #include #include #include -#include #include "FIRFilter.h" #include "cpu_detect.h" @@ -75,7 +74,7 @@ uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, ui { uint i, j, end; LONG_SAMPLETYPE suml, sumr; -#ifdef FLOAT_SAMPLES +#ifdef SOUNDTOUCH_FLOAT_SAMPLES // when using floating point samples, use a scaler instead of a divider // because division is much slower operation than multiplying. double dScaler = 1.0 / (double)resultDivider; @@ -88,14 +87,14 @@ uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, ui end = 2 * (numSamples - length); - for (j = 0; j < end; j += 2) + for (j = 0; j < end; j += 2) { const SAMPLETYPE *ptr; suml = sumr = 0; ptr = src + j; - for (i = 0; i < length; i += 4) + for (i = 0; i < length; i += 4) { // loop is unrolled by factor of 4 here for efficiency suml += ptr[2 * i + 0] * filterCoeffs[i + 0] + @@ -108,7 +107,7 @@ uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, ui ptr[2 * i + 7] * filterCoeffs[i + 3]; } -#ifdef INTEGER_SAMPLES +#ifdef SOUNDTOUCH_INTEGER_SAMPLES suml >>= resultDivFactor; sumr >>= resultDivFactor; // saturate to 16 bit integer limits @@ -118,7 +117,7 @@ uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, ui #else suml *= dScaler; sumr *= dScaler; -#endif // INTEGER_SAMPLES +#endif // SOUNDTOUCH_INTEGER_SAMPLES dest[j] = (SAMPLETYPE)suml; dest[j + 1] = (SAMPLETYPE)sumr; } @@ -133,7 +132,7 @@ uint FIRFilter::evaluateFilterMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint { uint i, j, end; LONG_SAMPLETYPE sum; -#ifdef FLOAT_SAMPLES +#ifdef SOUNDTOUCH_FLOAT_SAMPLES // when using floating point samples, use a scaler instead of a divider // because division is much slower operation than multiplying. double dScaler = 1.0 / (double)resultDivider; @@ -143,24 +142,24 @@ uint FIRFilter::evaluateFilterMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint assert(length != 0); end = numSamples - length; - for (j = 0; j < end; j ++) + for (j = 0; j < end; j ++) { sum = 0; - for (i = 0; i < length; i += 4) + for (i = 0; i < length; i += 4) { // loop is unrolled by factor of 4 here for efficiency - sum += src[i + 0] * filterCoeffs[i + 0] + - src[i + 1] * filterCoeffs[i + 1] + - src[i + 2] * filterCoeffs[i + 2] + + sum += src[i + 0] * filterCoeffs[i + 0] + + src[i + 1] * filterCoeffs[i + 1] + + src[i + 2] * filterCoeffs[i + 2] + src[i + 3] * filterCoeffs[i + 3]; } -#ifdef INTEGER_SAMPLES +#ifdef SOUNDTOUCH_INTEGER_SAMPLES sum >>= resultDivFactor; // saturate to 16 bit integer limits sum = (sum < -32768) ? -32768 : (sum > 32767) ? 32767 : sum; #else sum *= dScaler; -#endif // INTEGER_SAMPLES +#endif // SOUNDTOUCH_INTEGER_SAMPLES dest[j] = (SAMPLETYPE)sum; src ++; } @@ -174,7 +173,7 @@ uint FIRFilter::evaluateFilterMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint void FIRFilter::setCoefficients(const SAMPLETYPE *coeffs, uint newLength, uint uResultDivFactor) { assert(newLength > 0); - if (newLength % 8) throw std::runtime_error("FIR filter length not divisible by 8"); + if (newLength % 8) ST_THROW_RT_ERROR("FIR filter length not divisible by 8"); lengthDiv8 = newLength / 8; length = lengthDiv8 * 8; @@ -196,9 +195,9 @@ uint FIRFilter::getLength() const -// Applies the filter to the given sequence of samples. +// Applies the filter to the given sequence of samples. // -// Note : The amount of outputted samples is by value of 'filter_length' +// Note : The amount of outputted samples is by value of 'filter_length' // smaller than the amount of input samples. uint FIRFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels) const { @@ -207,7 +206,7 @@ uint FIRFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSample assert(length > 0); assert(lengthDiv8 * 8 == length); if (numSamples < length) return 0; - if (numChannels == 2) + if (numChannels == 2) { return evaluateFilterStereo(dest, src, numSamples); } else { @@ -217,13 +216,13 @@ uint FIRFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSample -// Operator 'new' is overloaded so that it automatically creates a suitable instance +// Operator 'new' is overloaded so that it automatically creates a suitable instance // depending on if we've a MMX-capable CPU available or not. void * FIRFilter::operator new(size_t s) { // Notice! don't use "new FIRFilter" directly, use "newInstance" to create a new instance instead! - throw std::runtime_error("Error in FIRFilter::new: Don't use 'new FIRFilter', use 'newInstance' member instead!"); - return NULL; + ST_THROW_RT_ERROR("Error in FIRFilter::new: Don't use 'new FIRFilter', use 'newInstance' member instead!"); + return newInstance(); } @@ -233,34 +232,25 @@ FIRFilter * FIRFilter::newInstance() uExtensions = detectCPUextensions(); - // Check if MMX/SSE/3DNow! instruction set extensions supported by CPU + // Check if MMX/SSE instruction set extensions supported by CPU -#ifdef ALLOW_MMX +#ifdef SOUNDTOUCH_ALLOW_MMX // MMX routines available only with integer sample types if (uExtensions & SUPPORT_MMX) { return ::new FIRFilterMMX; } else -#endif // ALLOW_MMX +#endif // SOUNDTOUCH_ALLOW_MMX -#ifdef ALLOW_SSE +#ifdef SOUNDTOUCH_ALLOW_SSE if (uExtensions & SUPPORT_SSE) { // SSE support return ::new FIRFilterSSE; } else -#endif // ALLOW_SSE - -#ifdef ALLOW_3DNOW - if (uExtensions & SUPPORT_3DNOW) - { - // 3DNow! support - return ::new FIRFilter3DNow; - } - else -#endif // ALLOW_3DNOW +#endif // SOUNDTOUCH_ALLOW_SSE { // ISA optimizations not supported, use plain C version diff --git a/3rdparty/SoundTouch/FIRFilter.h b/3rdparty/SoundTouch/FIRFilter.h index 2899c9bfd..b59316745 100644 --- a/3rdparty/SoundTouch/FIRFilter.h +++ b/3rdparty/SoundTouch/FIRFilter.h @@ -1,8 +1,8 @@ //////////////////////////////////////////////////////////////////////////////// /// -/// General FIR digital filter routines with MMX optimization. +/// General FIR digital filter routines with MMX optimization. /// -/// Note : MMX optimized functions reside in a separate, platform-specific file, +/// Note : MMX optimized functions reside in a separate, platform-specific file, /// e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp' /// /// Author : Copyright (c) Olli Parviainen @@ -11,10 +11,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2009-02-21 18:00:14 +0200 (Sat, 21 Feb 2009) $ +// Last changed : $Date: 2011-02-13 17:13:57 -0200 (dom, 13 fev 2011) $ // File revision : $Revision: 4 $ // -// $Id: FIRFilter.h 63 2009-02-21 16:00:14Z oparviai $ +// $Id: FIRFilter.h 104 2011-02-13 19:13:57Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -48,11 +48,11 @@ namespace soundtouch { -class FIRFilter +class FIRFilter { protected: // Number of FIR filter taps - uint length; + uint length; // Number of FIR filter taps divided by 8 uint lengthDiv8; @@ -65,44 +65,44 @@ protected: // Memory for filter coefficients SAMPLETYPE *filterCoeffs; - virtual uint evaluateFilterStereo(SAMPLETYPE *dest, - const SAMPLETYPE *src, + virtual uint evaluateFilterStereo(SAMPLETYPE *dest, + const SAMPLETYPE *src, uint numSamples) const; - virtual uint evaluateFilterMono(SAMPLETYPE *dest, - const SAMPLETYPE *src, + virtual uint evaluateFilterMono(SAMPLETYPE *dest, + const SAMPLETYPE *src, uint numSamples) const; public: FIRFilter(); virtual ~FIRFilter(); - /// Operator 'new' is overloaded so that it automatically creates a suitable instance + /// Operator 'new' is overloaded so that it automatically creates a suitable instance /// depending on if we've a MMX-capable CPU available or not. static void * operator new(size_t s); static FIRFilter *newInstance(); - /// Applies the filter to the given sequence of samples. - /// Note : The amount of outputted samples is by value of 'filter_length' + /// Applies the filter to the given sequence of samples. + /// Note : The amount of outputted samples is by value of 'filter_length' /// smaller than the amount of input samples. /// /// \return Number of samples copied to 'dest'. - uint evaluate(SAMPLETYPE *dest, - const SAMPLETYPE *src, - uint numSamples, + uint evaluate(SAMPLETYPE *dest, + const SAMPLETYPE *src, + uint numSamples, uint numChannels) const; uint getLength() const; - virtual void setCoefficients(const SAMPLETYPE *coeffs, - uint newLength, + virtual void setCoefficients(const SAMPLETYPE *coeffs, + uint newLength, uint uResultDivFactor); }; // Optional subclasses that implement CPU-specific optimizations: -#ifdef ALLOW_MMX +#ifdef SOUNDTOUCH_ALLOW_MMX /// Class that implements MMX optimized functions exclusive for 16bit integer samples type. class FIRFilterMMX : public FIRFilter @@ -119,29 +119,10 @@ public: virtual void setCoefficients(const short *coeffs, uint newLength, uint uResultDivFactor); }; -#endif // ALLOW_MMX +#endif // SOUNDTOUCH_ALLOW_MMX -#ifdef ALLOW_3DNOW - - /// Class that implements 3DNow! optimized functions exclusive for floating point samples type. - class FIRFilter3DNow : public FIRFilter - { - protected: - float *filterCoeffsUnalign; - float *filterCoeffsAlign; - - virtual uint evaluateFilterStereo(float *dest, const float *src, uint numSamples) const; - public: - FIRFilter3DNow(); - ~FIRFilter3DNow(); - virtual void setCoefficients(const float *coeffs, uint newLength, uint uResultDivFactor); - }; - -#endif // ALLOW_3DNOW - - -#ifdef ALLOW_SSE +#ifdef SOUNDTOUCH_ALLOW_SSE /// Class that implements SSE optimized functions exclusive for floating point samples type. class FIRFilterSSE : public FIRFilter { @@ -157,7 +138,7 @@ public: virtual void setCoefficients(const float *coeffs, uint newLength, uint uResultDivFactor); }; -#endif // ALLOW_SSE +#endif // SOUNDTOUCH_ALLOW_SSE } diff --git a/3rdparty/SoundTouch/Makefile.am b/3rdparty/SoundTouch/Makefile.am index eb39bcc96..709f0cbd2 100644 --- a/3rdparty/SoundTouch/Makefile.am +++ b/3rdparty/SoundTouch/Makefile.am @@ -1,42 +1,71 @@ ## Process this file with automake to create Makefile.in ## -## $Id: Makefile.am,v 1.3 2006/02/05 18:33:34 Olli Exp $ -## -## Copyright (C) 2003 - David W. Durham +## $Id: Makefile.am 138 2012-04-01 20:00:09Z oparviai $ ## ## This file is part of SoundTouch, an audio processing library for pitch/time adjustments -## +## ## SoundTouch 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. -## +## ## SoundTouch 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 -AUTOMAKE_OPTIONS = foreign -noinst_HEADERS=AAFilter.h cpu_detect.h FIRFilter.h RateTransposer.h TDStretch.h cpu_detect_x86_gcc.cpp -noinst_LIBRARIES = libSoundTouch.a +include $(top_srcdir)/config/am_include.mk -libSoundTouch_a_CXXFLAGS = -msse -mmmx -libSoundTouch_a_CFLAGS = -msse -mmmx -#lib_LTLIBRARIES=libSoundTouch.la -# the mmx_gcc.cpp and cpu_detect_x86_gcc.cpp may need to be conditionally included here from things discovered in configure.ac -libSoundTouch_a_SOURCES=AAFilter.cpp FIRFilter.cpp FIFOSampleBuffer.cpp mmx_optimized.cpp sse_optimized.cpp \ -RateTransposer.cpp SoundTouch.cpp TDStretch.cpp WavFile.cpp cpu_detect_x86_gcc.cpp +# set to something if you want other stuff to be included in the distribution tarball +EXTRA_DIST=SoundTouch.dsp SoundTouch.dsw SoundTouch.sln SoundTouch.vcproj + +noinst_HEADERS=AAFilter.h cpu_detect.h cpu_detect_x86.cpp FIRFilter.h RateTransposer.h TDStretch.h PeakFinder.h + +lib_LTLIBRARIES=libSoundTouch.la +# +libSoundTouch_la_SOURCES=AAFilter.cpp FIRFilter.cpp FIFOSampleBuffer.cpp RateTransposer.cpp SoundTouch.cpp TDStretch.cpp cpu_detect_x86.cpp BPMDetect.cpp PeakFinder.cpp + + +# Compiler flags +AM_CXXFLAGS=-O3 -fcheck-new -I../../include + +# Compile the files that need MMX and SSE individually. +libSoundTouch_la_LIBADD=libSoundTouchMMX.la libSoundTouchSSE.la +noinst_LTLIBRARIES=libSoundTouchMMX.la libSoundTouchSSE.la +libSoundTouchMMX_la_SOURCES=mmx_optimized.cpp +libSoundTouchSSE_la_SOURCES=sse_optimized.cpp + +# We enable optimizations by default. +# If MMX is supported compile with -mmmx. +# Do not assume -msse is also supported. +if HAVE_MMX +libSoundTouchMMX_la_CXXFLAGS = -mmmx $(AM_CXXFLAGS) +else +libSoundTouchMMX_la_CXXFLAGS = $(AM_CXXFLAGS) +endif + +# We enable optimizations by default. +# If SSE is supported compile with -msse. +if HAVE_SSE +libSoundTouchSSE_la_CXXFLAGS = -msse $(AM_CXXFLAGS) +else +libSoundTouchSSE_la_CXXFLAGS = $(AM_CXXFLAGS) +endif + +# Let the user disable optimizations if he wishes to. +if !X86_OPTIMIZATIONS +libSoundTouchMMX_la_CXXFLAGS = $(AM_CXXFLAGS) +libSoundTouchSSE_la_CXXFLAGS = $(AM_CXXFLAGS) +endif -# ??? test for -fcheck-new in configure.ac -# other compiler flags to add -AM_CXXFLAGS=-O3 -msse -fcheck-new -#-I../../include # other linking flags to add -#libSoundTouch_la_LIBADD= - +# noinst_LTLIBRARIES = libSoundTouchOpt.la +# libSoundTouch_la_LIBADD = libSoundTouchOpt.la +# libSoundTouchOpt_la_SOURCES = mmx_optimized.cpp sse_optimized.cpp +# libSoundTouchOpt_la_CXXFLAGS = -O3 -msse -fcheck-new -I../../include diff --git a/3rdparty/SoundTouch/PeakFinder.cpp b/3rdparty/SoundTouch/PeakFinder.cpp new file mode 100644 index 000000000..71203983f --- /dev/null +++ b/3rdparty/SoundTouch/PeakFinder.cpp @@ -0,0 +1,276 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// Peak detection routine. +/// +/// The routine detects highest value on an array of values and calculates the +/// precise peak location as a mass-center of the 'hump' around the peak value. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2012-12-28 17:52:47 -0200 (sex, 28 dez 2012) $ +// File revision : $Revision: 4 $ +// +// $Id: PeakFinder.cpp 164 2012-12-28 19:52:47Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// License : +// +// SoundTouch audio processing library +// Copyright (c) Olli Parviainen +// +// 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "PeakFinder.h" + +using namespace soundtouch; + +#define max(x, y) (((x) > (y)) ? (x) : (y)) + + +PeakFinder::PeakFinder() +{ + minPos = maxPos = 0; +} + + +// Finds real 'top' of a peak hump from neighnourhood of the given 'peakpos'. +int PeakFinder::findTop(const float *data, int peakpos) const +{ + int i; + int start, end; + float refvalue; + + refvalue = data[peakpos]; + + // seek within ±10 points + start = peakpos - 10; + if (start < minPos) start = minPos; + end = peakpos + 10; + if (end > maxPos) end = maxPos; + + for (i = start; i <= end; i ++) + { + if (data[i] > refvalue) + { + peakpos = i; + refvalue = data[i]; + } + } + + // failure if max value is at edges of seek range => it's not peak, it's at slope. + if ((peakpos == start) || (peakpos == end)) return 0; + + return peakpos; +} + + +// Finds 'ground level' of a peak hump by starting from 'peakpos' and proceeding +// to direction defined by 'direction' until next 'hump' after minimum value will +// begin +int PeakFinder::findGround(const float *data, int peakpos, int direction) const +{ + int lowpos; + int pos; + int climb_count; + float refvalue; + float delta; + + climb_count = 0; + refvalue = data[peakpos]; + lowpos = peakpos; + + pos = peakpos; + + while ((pos > minPos+1) && (pos < maxPos-1)) + { + int prevpos; + + prevpos = pos; + pos += direction; + + // calculate derivate + delta = data[pos] - data[prevpos]; + if (delta <= 0) + { + // going downhill, ok + if (climb_count) + { + climb_count --; // decrease climb count + } + + // check if new minimum found + if (data[pos] < refvalue) + { + // new minimum found + lowpos = pos; + refvalue = data[pos]; + } + } + else + { + // going uphill, increase climbing counter + climb_count ++; + if (climb_count > 5) break; // we've been climbing too long => it's next uphill => quit + } + } + return lowpos; +} + + +// Find offset where the value crosses the given level, when starting from 'peakpos' and +// proceeds to direction defined in 'direction' +int PeakFinder::findCrossingLevel(const float *data, float level, int peakpos, int direction) const +{ + float peaklevel; + int pos; + + peaklevel = data[peakpos]; + assert(peaklevel >= level); + pos = peakpos; + while ((pos >= minPos) && (pos < maxPos)) + { + if (data[pos + direction] < level) return pos; // crossing found + pos += direction; + } + return -1; // not found +} + + +// Calculates the center of mass location of 'data' array items between 'firstPos' and 'lastPos' +double PeakFinder::calcMassCenter(const float *data, int firstPos, int lastPos) const +{ + int i; + float sum; + float wsum; + + sum = 0; + wsum = 0; + for (i = firstPos; i <= lastPos; i ++) + { + sum += (float)i * data[i]; + wsum += data[i]; + } + + if (wsum < 1e-6) return 0; + return sum / wsum; +} + + + +/// get exact center of peak near given position by calculating local mass of center +double PeakFinder::getPeakCenter(const float *data, int peakpos) const +{ + float peakLevel; // peak level + int crosspos1, crosspos2; // position where the peak 'hump' crosses cutting level + float cutLevel; // cutting value + float groundLevel; // ground level of the peak + int gp1, gp2; // bottom positions of the peak 'hump' + + // find ground positions. + gp1 = findGround(data, peakpos, -1); + gp2 = findGround(data, peakpos, 1); + + groundLevel = 0.5f * (data[gp1] + data[gp2]); + peakLevel = data[peakpos]; + + // calculate 70%-level of the peak + cutLevel = 0.70f * peakLevel + 0.30f * groundLevel; + // find mid-level crossings + crosspos1 = findCrossingLevel(data, cutLevel, peakpos, -1); + crosspos2 = findCrossingLevel(data, cutLevel, peakpos, 1); + + if ((crosspos1 < 0) || (crosspos2 < 0)) return 0; // no crossing, no peak.. + + // calculate mass center of the peak surroundings + return calcMassCenter(data, crosspos1, crosspos2); +} + + + +double PeakFinder::detectPeak(const float *data, int aminPos, int amaxPos) +{ + + int i; + int peakpos; // position of peak level + double highPeak, peak; + + this->minPos = aminPos; + this->maxPos = amaxPos; + + // find absolute peak + peakpos = minPos; + peak = data[minPos]; + for (i = minPos + 1; i < maxPos; i ++) + { + if (data[i] > peak) + { + peak = data[i]; + peakpos = i; + } + } + + // Calculate exact location of the highest peak mass center + highPeak = getPeakCenter(data, peakpos); + peak = highPeak; + + // Now check if the highest peak were in fact harmonic of the true base beat peak + // - sometimes the highest peak can be Nth harmonic of the true base peak yet + // just a slightly higher than the true base + + for (i = 3; i < 10; i ++) + { + double peaktmp, harmonic; + int i1,i2; + + harmonic = (double)i * 0.5; + peakpos = (int)(highPeak / harmonic + 0.5f); + if (peakpos < minPos) break; + peakpos = findTop(data, peakpos); // seek true local maximum index + if (peakpos == 0) continue; // no local max here + + // calculate mass-center of possible harmonic peak + peaktmp = getPeakCenter(data, peakpos); + + // accept harmonic peak if + // (a) it is found + // (b) is within ±4% of the expected harmonic interval + // (c) has at least half x-corr value of the max. peak + + double diff = harmonic * peaktmp / highPeak; + if ((diff < 0.96) || (diff > 1.04)) continue; // peak too afar from expected + + // now compare to highest detected peak + i1 = (int)(highPeak + 0.5); + i2 = (int)(peaktmp + 0.5); + if (data[i2] >= 0.4*data[i1]) + { + // The harmonic is at least half as high primary peak, + // thus use the harmonic peak instead + peak = peaktmp; + } + } + + return peak; +} diff --git a/3rdparty/SoundTouch/PeakFinder.h b/3rdparty/SoundTouch/PeakFinder.h new file mode 100644 index 000000000..c78164330 --- /dev/null +++ b/3rdparty/SoundTouch/PeakFinder.h @@ -0,0 +1,97 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// The routine detects highest value on an array of values and calculates the +/// precise peak location as a mass-center of the 'hump' around the peak value. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2011-12-30 18:33:46 -0200 (sex, 30 dez 2011) $ +// File revision : $Revision: 4 $ +// +// $Id: PeakFinder.h 132 2011-12-30 20:33:46Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// License : +// +// SoundTouch audio processing library +// Copyright (c) Olli Parviainen +// +// 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _PeakFinder_H_ +#define _PeakFinder_H_ + +namespace soundtouch +{ + +class PeakFinder +{ +protected: + /// Min, max allowed peak positions within the data vector + int minPos, maxPos; + + /// Calculates the mass center between given vector items. + double calcMassCenter(const float *data, ///< Data vector. + int firstPos, ///< Index of first vector item beloging to the peak. + int lastPos ///< Index of last vector item beloging to the peak. + ) const; + + /// Finds the data vector index where the monotoniously decreasing signal crosses the + /// given level. + int findCrossingLevel(const float *data, ///< Data vector. + float level, ///< Goal crossing level. + int peakpos, ///< Peak position index within the data vector. + int direction /// Direction where to proceed from the peak: 1 = right, -1 = left. + ) const; + + // Finds real 'top' of a peak hump from neighnourhood of the given 'peakpos'. + int findTop(const float *data, int peakpos) const; + + + /// Finds the 'ground' level, i.e. smallest level between two neighbouring peaks, to right- + /// or left-hand side of the given peak position. + int findGround(const float *data, /// Data vector. + int peakpos, /// Peak position index within the data vector. + int direction /// Direction where to proceed from the peak: 1 = right, -1 = left. + ) const; + + /// get exact center of peak near given position by calculating local mass of center + double getPeakCenter(const float *data, int peakpos) const; + +public: + /// Constructor. + PeakFinder(); + + /// Detect exact peak position of the data vector by finding the largest peak 'hump' + /// and calculating the mass-center location of the peak hump. + /// + /// \return The location of the largest base harmonic peak hump. + double detectPeak(const float *data, /// Data vector to be analyzed. The data vector has + /// to be at least 'maxPos' items long. + int minPos, ///< Min allowed peak location within the vector data. + int maxPos ///< Max allowed peak location within the vector data. + ); +}; + +} + +#endif // _PeakFinder_H_ diff --git a/3rdparty/SoundTouch/README.html b/3rdparty/SoundTouch/README.html index 15a34c864..5b2bcbb24 100644 --- a/3rdparty/SoundTouch/README.html +++ b/3rdparty/SoundTouch/README.html @@ -1,6 +1,7 @@ + SoundTouch library README @@ -9,32 +10,26 @@ content="Readme file for SoundTouch audio processing library"> - SoundTouch library README - +


-

SoundTouch audio processing library v1.5.0 -

-

SoundTouch library Copyright (c) Olli -Parviainen 2002-2009

+

SoundTouch audio processing library v1.7.1

+

SoundTouch library Copyright © Olli Parviainen 2001-2012


1. Introduction

-

SoundTouch is an open-source audio -processing library that allows changing the sound tempo, pitch -and playback rate parameters independently from each other, i.e.:

+

SoundTouch is an open-source audio processing library that allows +changing the sound tempo, pitch and playback rate parameters +independently from each other, i.e.:

    -
  • Sound tempo can be increased or decreased while -maintaining the original pitch
  • -
  • Sound pitch can be increased or decreased while -maintaining the original tempo
  • -
  • Change playback rate that affects both tempo -and pitch at the same time
  • -
  • Choose any combination of tempo/pitch/rate
  • +
  • Sound tempo can be increased or decreased while maintaining the +original pitch
  • +
  • Sound pitch can be increased or decreased while maintaining the +original tempo
  • +
  • Change playback rate that affects both tempo and pitch at the +same time
  • +
  • Choose any combination of tempo/pitch/rate

1.1 Contact information

Author email: oparviai 'at' iki.fi

@@ -42,50 +37,54 @@ and pitch at the same time

2. Compiling SoundTouch

Before compiling, notice that you can choose the sample data format -if it's desirable to use floating point sample -data instead of 16bit integers. See section "sample data format" -for more information.

+if it's desirable to use floating point sample data instead of 16bit +integers. See section "sample data format" for more information.

2.1. Building in Microsoft Windows

Project files for Microsoft Visual C++ 6.0 and Visual C++ .NET are -supplied with the source code package. 

-

Please notice that SoundTouch -library uses processor-specific optimizations for Pentium III and AMD -processors. Visual Studio .NET and later versions supports the required -instructions by default, but Visual Studio 6.0 requires a processor pack upgrade -to be installed in order to support these optimizations. The processor pack upgrade can be downloaded from -Microsoft site at this URL:

-

http://msdn.microsoft.com/en-us/vstudio/aa718349.aspx

-

If the above URL is unavailable or removed, go -to http://msdn.microsoft.com -and perform a search with keywords "processor pack".

-

To build the binaries with Visual C++ -compiler, either run "make-win.bat" script, or open the -appropriate project files in source code directories with Visual -Studio. The final executable will appear under the "SoundTouch\bin" -directory. If using the Visual Studio IDE instead of the make-win.bat script, directories bin and -lib may need to be created manually to the SoundTouch -package root for the final executables. The make-win.bat script -creates these directories automatically. +supplied with the source code package.

+

Please notice that SoundTouch library uses processor-specific +optimizations for Pentium III and AMD processors. Visual Studio .NET +and later versions supports the required instructions by default, but +Visual Studio 6.0 requires a processor pack upgrade to be installed in +order to support these optimizations. The processor pack upgrade can be +downloaded from Microsoft site at this URL:

+

http://msdn.microsoft.com/en-us/vstudio/aa718349.aspx

+

If the above URL is unavailable or removed, go to http://msdn.microsoft.com and +perform a search with keywords "processor pack".

+

To build the binaries with Visual C++ compiler, either run +"make-win.bat" script, or open the appropriate project files in source +code directories with Visual Studio. The final executable will appear +under the "SoundTouch\bin" directory. If using the Visual Studio IDE +instead of the make-win.bat script, directories bin and lib may need to +be created manually to the SoundTouch package root for the final +executables. The make-win.bat script creates these directories +automatically.

2.2. Building in Gnu platforms

-

The SoundTouch library can be compiled in -practically any platform supporting GNU compiler (GCC) tools. -SoundTouch have been tested with gcc version 3.3.4., but it -shouldn't be very specific about the gcc version. Assembler-level -performance optimizations for GNU platform are currently available in -x86 platforms only, they are automatically disabled and replaced with -standard C routines in other processor platforms.

-

To build and install the binaries, run the -following commands in the SoundTouch/ directory:

+

The SoundTouch library compiles in practically any platform +supporting GNU compiler (GCC) tools. SoundTouch requires GCC version 4.3 or later.

+

To build and install the binaries, run the following commands in +/soundtouch directory:

+ + + + @@ -93,8 +92,7 @@ environment.

make         -
@@ -102,175 +100,163 @@ SoundStretch utility.

make install -
+
./bootstrap  -
+
Creates "configure" file with +local autoconf/automake toolset.
+
./configure  -
-

Configures the SoundTouch package for the local -environment.

+

Configures the SoundTouch package for the local environment. +Notice that "configure" file is not available before running the +"./bootstrap" command as above.
+

-

Builds the SoundTouch library & -SoundStretch utility.

+

Builds the SoundTouch library & SoundStretch utility.

-

Installs the SoundTouch & BPM libraries -to /usr/local/lib and SoundStretch utility to /usr/local/bin. -Please notice that 'root' privileges may be required to install the -binaries to the destination locations.

+

Installs the SoundTouch & BPM libraries to /usr/local/lib +and SoundStretch utility to /usr/local/bin. Please notice that +'root' privileges may be required to install the binaries to the +destination locations.

2.2.1 Required GNU tools 

-

Bash shell, GNU C++ compiler, libtool, autoconf and automake tools are required -for compiling -the SoundTouch library. These are usually included with the GNU/Linux distribution, but if -not, install these packages first. For example, in Ubuntu Linux these can be acquired and -installed with the following command:

-
sudo apt-get install automake autoconf libtool build-essential
+

Bash shell, GNU C++ compiler, libtool, autoconf and automake tools +are required for compiling the SoundTouch library. These are usually +included with the GNU/Linux distribution, but if not, install these +packages first. For example, Ubuntu Linux can acquire and install +these with the following command:

+
sudo apt-get install automake autoconf libtool build-essential

2.2.2 Problems with GCC compiler compatibility

-

At the release time the SoundTouch package has been tested to compile in -GNU/Linux platform. However, in past it's happened that new gcc versions aren't -necessarily compatible with the assembler settings used in the optimized -routines. If you have problems getting the -SoundTouch library compiled, try the workaround of disabling the optimizations -by editing the file "include/STTypes.h" and removing the following -definition there:

+

At the release time the SoundTouch package has been tested to +compile in GNU/Linux platform. However, If you have problems getting the +SoundTouch library compiled, try disabling optimizations that are specific for +x86 processors by running ./configure script with switch

-
#define ALLOW_OPTIMIZATIONS 1
+
--enable-x86-optimizations=no
-

2.2.3 Problems with configure script or build process 

-

Incompatibilities between various GNU toolchain versions may cause errors when running the "configure" script or building the source -codes, if your GNU tool versions are not compatible with the versions used for -preparing the SoundTouch kit. 

-

To resolve the issue, regenerate the configure scripts with your local tool -set by running -the "./bootstrap" script included in the SoundTouch source code -kit. After that, run the configure script and make as usually.

-

2.2.4 Compiler issues with non-x86 processors

-

SoundTouch library works also on non-x86 processors.

-

However, in case that you get compiler errors when trying to compile for non-Intel processor, edit the file -"source\SoundTouch\Makefile.am" and remove the "-msse2" -flag on the AM_CXXFLAGS line:

-
AM_CXXFLAGS=-O3 -fcheck-new -I../../include    # Note: -msse2 flag removed!
-

After that, run "./bootstrap" script, and then run configure -and make again.

+ +Alternatively, if you don't use GNU Configure system, edit file "include/STTypes.h" +directly and remove the following definition:
+
#define SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS 1
+
+ +

2.2.3 Compiling Shared Library / DLL version

+

+ The GNU compilation does not automatically create a shared-library version of + SoundTouch (.so or .dll). If such is desired, then you can create it as follows + after running the usual compilation:

+
+
g++ -shared -static -DDLL_EXPORTS -I../../include -o SoundTouch.dll \
+     SoundTouchDLL.cpp ../SoundTouch/.libs/libSoundTouch.a
+sstrip SoundTouch.dll
+
+ +

2.1. Building in Android

+

Android compilation instructions are within the + source code package, see file "source/Android-lib/README-SoundTouch-Android.html" + in the package.

+
-

3. About implementation & Usage tips

-

3.1. Supported sample data formats

-

The sample data format can be chosen -between 16bit signed integer and 32bit floating point values, the -default is 32bit floating point.

- -

-In Windows environment, the sample data format is chosen -in file "STTypes.h" by choosing one of the following -defines:

+

3. About implementation & Usage tips

3.1. Supported sample data formats

+

The sample data format can be chosen between 16bit signed integer +and 32bit floating point values, the default is 32bit floating point.

+

In Windows environment, the sample data format is chosen in file +"STTypes.h" by choosing one of the following defines:

    -
  • #define INTEGER_SAMPLES -for 16bit signed -integer
  • -
  • #define FLOAT_SAMPLES for -32bit floating point
  • +
  • #define +SOUNDTOUCH_INTEGER_SAMPLES for 16bit signed integer
  • +
  • #define SOUNDTOUCH_FLOAT_SAMPLES for 32bit floating +point
-

-In GNU environment, the floating sample format is used by default, but -integer sample format can be chosen by giving the -following switch to the configure script: +

In GNU environment, the floating sample format is used by default, +but integer sample format can be chosen by giving the following switch +to the configure script:

-
./configure --enable-integer-samples
+
./configure --enable-integer-samples
- -

The sample data can have either single (mono) -or double (stereo) audio channel. Stereo data is interleaved so -that every other data value is for left channel and every second -for right channel. Notice that while it'd be possible in theory -to process stereo sound as two separate mono channels, this isn't -recommended because processing the channels separately would -result in losing the phase coherency between the channels, which -consequently would ruin the stereo effect.

-

Sample rates between 8000-48000H are -supported.

+

The sample data can have either single (mono) or double (stereo) +audio channel. Stereo data is interleaved so that every other data +value is for left channel and every second for right channel. Notice +that while it'd be possible in theory to process stereo sound as two +separate mono channels, this isn't recommended because processing the +channels separately would result in losing the phase coherency between +the channels, which consequently would ruin the stereo effect.

+

Sample rates between 8000-48000H are supported.

3.2. Processing latency

-

The processing and latency constraints of -the SoundTouch library are:

+

The processing and latency constraints of the SoundTouch library are:

    -
  • Input/output processing latency for the -SoundTouch processor is around 100 ms. This is when time-stretching is -used. If the rate transposing effect alone is used, the latency -requirement -is much shorter, see section 'About algorithms'.
  • -
  • Processing CD-quality sound (16bit stereo -sound with 44100H sample rate) in real-time or faster is possible -starting from processors equivalent to Intel Pentium 133Mh or better, -if using the "quick" processing algorithm. If not using the "quick" -mode or -if floating point sample data are being used, several times more CPU -power is typically required.
  • +
  • Input/output processing latency for the SoundTouch processor is +around 100 ms. This is when time-stretching is used. If the rate +transposing effect alone is used, the latency requirement is much +shorter, see section 'About algorithms'.
  • +
  • Processing CD-quality sound (16bit stereo sound with 44100H +sample rate) in real-time or faster is possible starting from +processors equivalent to Intel Pentium 133Mh or better, if using the +"quick" processing algorithm. If not using the "quick" mode or if +floating point sample data are being used, several times more CPU power +is typically required.

3.3. About algorithms

-

SoundTouch provides three seemingly -independent effects: tempo, pitch and playback rate control. -These three controls are implemented as combination of two primary -effects, sample rate transposing and time-stretching.

-

Sample rate transposing affects -both the audio stream duration and pitch. It's implemented simply -by converting the original audio sample stream to the  desired -duration by interpolating from the original audio samples. In SoundTouch, linear interpolation with anti-alias filtering is -used. Theoretically a higher-order interpolation provide better -result than 1st order linear interpolation, but in audio -application linear interpolation together with anti-alias -filtering performs subjectively about as well as higher-order -filtering would.

-

Time-stretching means changing -the audio stream duration without affecting it's pitch. SoundTouch -uses WSOLA-like time-stretching routines that operate in the time -domain. Compared to sample rate transposing, time-stretching is a -much heavier operation and also requires a longer processing -"window" of sound samples used by the -processing algorithm, thus increasing the algorithm input/output -latency. Typical i/o latency for the SoundTouch -time-stretch algorithm is around 100 ms.

-

Sample rate transposing and time-stretching -are then used together to produce the tempo, pitch and rate -controls:

+

SoundTouch provides three seemingly independent effects: tempo, +pitch and playback rate control. These three controls are implemented +as combination of two primary effects, sample rate transposing +and time-stretching.

+

Sample rate transposing affects both the audio stream +duration and pitch. It's implemented simply by converting the original +audio sample stream to the  desired duration by interpolating from +the original audio samples. In SoundTouch, linear interpolation with +anti-alias filtering is used. Theoretically a higher-order +interpolation provide better result than 1st order linear +interpolation, but in audio application linear interpolation together +with anti-alias filtering performs subjectively about as well as +higher-order filtering would.

+

Time-stretching means changing the audio stream duration +without affecting it's pitch. SoundTouch uses WSOLA-like +time-stretching routines that operate in the time domain. Compared to +sample rate transposing, time-stretching is a much heavier operation +and also requires a longer processing "window" of sound samples used by +the processing algorithm, thus increasing the algorithm input/output +latency. Typical i/o latency for the SoundTouch time-stretch algorithm +is around 100 ms.

+

Sample rate transposing and time-stretching are then used together +to produce the tempo, pitch and rate controls:

    -
  • 'Tempo' control is -implemented purely by time-stretching.
  • -
  • 'Rate' control is implemented -purely by sample rate transposing.
  • -
  • 'Pitch' control is -implemented as a combination of time-stretching and sample rate -transposing. For example, to increase pitch the audio stream is first -time-stretched to longer duration (without affecting pitch) and then -transposed back to original duration by sample rate transposing, which -simultaneously reduces duration and increases pitch. The result is -original duration but increased pitch.
  • +
  • 'Tempo' control is implemented purely by +time-stretching.
  • +
  • 'Rate' control is implemented purely by sample +rate transposing.
  • +
  • 'Pitch' control is implemented as a +combination of time-stretching and sample rate transposing. For +example, to increase pitch the audio stream is first time-stretched to +longer duration (without affecting pitch) and then transposed back to +original duration by sample rate transposing, which simultaneously +reduces duration and increases pitch. The result is original duration +but increased pitch.

3.4 Tuning the algorithm parameters

-

The time-stretch algorithm has few -parameters that can be tuned to optimize sound quality for -certain application. The current default parameters have been -chosen by iterative if-then analysis (read: "trial and error") -to obtain best subjective sound quality in pop/rock music -processing, but in applications processing different kind of -sound the default parameter set may result into a sub-optimal -result.

-

The time-stretch algorithm default -parameter values are set by the following #defines in file "TDStretch.h":

+

The time-stretch algorithm has few parameters that can be tuned to +optimize sound quality for certain application. The current default +parameters have been chosen by iterative if-then analysis (read: "trial +and error") to obtain best subjective sound quality in pop/rock music +processing, but in applications processing different kind of sound the +default parameter set may result into a sub-optimal result.

+

The time-stretch algorithm default parameter values are set by the +following #defines in file "TDStretch.h":

-
#define DEFAULT_SEQUENCE_MS     AUTOMATIC
-#define DEFAULT_SEEKWINDOW_MS   AUTOMATIC
-#define DEFAULT_OVERLAP_MS      8
+
#define DEFAULT_SEQUENCE_MS     AUTOMATIC
#define DEFAULT_SEEKWINDOW_MS AUTOMATIC
#define DEFAULT_OVERLAP_MS 8
-

These parameters affect to the time-stretch -algorithm as follows:

+

These parameters affect to the time-stretch algorithm as follows:

    -
  • DEFAULT_SEQUENCE_MS: This is -the default length of a single processing sequence in milliseconds -which determines the how the original sound is chopped in -the time-stretch algorithm. Larger values mean fewer sequences -are used in processing. In principle a larger value sounds better when -slowing down the tempo, but worse when increasing the tempo and vice -versa. 
    +
  • DEFAULT_SEQUENCE_MS: This is the default +length of a single processing sequence in milliseconds which determines +the how the original sound is chopped in the time-stretch algorithm. +Larger values mean fewer sequences are used in processing. In principle +a larger value sounds better when slowing down the tempo, but worse +when increasing the tempo and vice versa. 

    - By default, this setting value is calculated automatically according to - tempo value.
    +By default, this setting value is calculated automatically according to +tempo value.
  • -
  • DEFAULT_SEEKWINDOW_MS: The seeking window +
  • DEFAULT_SEEKWINDOW_MS: The seeking window default length in milliseconds is for the algorithm that seeks the best -possible overlapping location. This determines from how -wide a sample "window" the algorithm can use to find an optimal mixing -location when the sound sequences are to be linked back together. 
    +possible overlapping location. This determines from how wide a sample +"window" the algorithm can use to find an optimal mixing location when +the sound sequences are to be linked back together. 

    The bigger this window setting is, the higher the possibility to find a better mixing position becomes, but at the same time large values may @@ -279,474 +265,513 @@ chosen at more uneven intervals. If there's a disturbing artifact that sounds as if a constant frequency was drifting around, try reducing this setting.

    - By default, this setting value is calculated automatically according to - tempo value.
    +By default, this setting value is calculated automatically according to +tempo value.
  • -
  • DEFAULT_OVERLAP_MS: Overlap -length in milliseconds. When the sound sequences are mixed back -together to form again a continuous sound stream, this parameter -defines how much the ends of the consecutive sequences will overlap with each other.
    +
  • DEFAULT_OVERLAP_MS: Overlap length in +milliseconds. When the sound sequences are mixed back together to form +again a continuous sound stream, this parameter defines how much the +ends of the consecutive sequences will overlap with each other.

    - This shouldn't be that critical parameter. If you reduce the +This shouldn't be that critical parameter. If you reduce the DEFAULT_SEQUENCE_MS setting by a large amount, you might wish to try a smaller value on this.
-

Notice that these parameters can also be -set during execution time with functions "TDStretch::setParameters()" -and "SoundTouch::setSetting()".

-

The table below summaries how the -parameters can be adjusted for different applications:

+

Notice that these parameters can also be set during execution time +with functions "TDStretch::setParameters()" and "SoundTouch::setSetting()".

+

The table below summaries how the parameters can be adjusted for +different applications:

- - - + + + - - - - + + + + - - - - + + + + - + - - + +
Parameter nameDefault value -magnitudeLarger value -affects...Smaller value -affects...Default value magnitudeLarger value affects...Smaller value affects... Effect to CPU burden
SEQUENCE_MS
Default value is relatively -large, chosen for slowing down music tempoLarger value is usually -better for slowing down tempo. Growing the value decelerates the -"echoing" artifact when slowing down the tempo.Smaller value might be better -for speeding up tempo. Reducing the value accelerates the "echoing" -artifact when slowing down the tempo Increasing the parameter -value reduces computation burdenDefault value is relatively large, chosen for +slowing down music tempoLarger value is usually better for slowing down +tempo. Growing the value decelerates the "echoing" artifact when +slowing down the tempo.Smaller value might be better for speeding up +tempo. Reducing the value accelerates the "echoing" artifact when +slowing down the tempo Increasing the parameter value reduces +computation burden
SEEKWINDOW_MS
Default value is relatively -large, chosen for slowing down music tempoLarger value eases finding a -good mixing position, but may cause a "drifting" artifactSmaller reduce possibility to -find a good mixing position, but reduce the "drifting" artifact.Increasing the parameter -value increases computation burdenDefault value is relatively large, chosen for +slowing down music tempoLarger value eases finding a good mixing +position, but may cause a "drifting" artifactSmaller reduce possibility to find a good mixing +position, but reduce the "drifting" artifact.Increasing the parameter value increases +computation burden
OVERLAP_MS
Default value is relatively -large, chosen to suit with above parameters.Default value is relatively large, chosen to +suit with above parameters.  If you reduce the "sequence -ms" setting, you might wish to try a smaller value.Increasing the parameter -value increases computation burdenIf you reduce the "sequence ms" setting, you +might wish to try a smaller value.Increasing the parameter value increases +computation burden

3.5 Performance Optimizations

General optimizations:

-

The time-stretch routine has a 'quick' mode -that substantially speeds up the algorithm but may degrade the -sound quality by a small amount. This mode is activated by -calling SoundTouch::setSetting() function with parameter  id -of SETTING_USE_QUICKSEEK and value "1", i.e.

+

The time-stretch routine has a 'quick' mode that substantially +speeds up the algorithm but may degrade the sound quality by a small +amount. This mode is activated by calling SoundTouch::setSetting() +function with parameter  id of SETTING_USE_QUICKSEEK and value +"1", i.e.

setSetting(SETTING_USE_QUICKSEEK, 1);

CPU-specific optimizations:

    -
  • Intel MMX optimized routines are used with -compatible CPUs when 16bit integer sample type is used. MMX optimizations are available both in Win32 and Gnu/x86 platforms. -Compatible processors are Intel PentiumMMX and later; AMD K6-2, Athlon -and later.
  • -
  • Intel SSE optimized routines are used with -compatible CPUs when floating point sample type is used. SSE optimizations are currently implemented for Win32 platform only. -Processors compatible with SSE extension are Intel processors starting -from Pentium-III, and AMD processors starting from Athlon XP.
  • -
  • AMD 3DNow! optimized routines are used with -compatible CPUs when floating point sample type is used, but SSE -extension isn't supported . 3DNow! optimizations are currently -implemented for Win32 platform only. These optimizations are used in -AMD K6-2 and Athlon (classic) CPU's; better performing SSE routines are -used with AMD processor starting from Athlon XP.
  • +
  • Intel MMX optimized routines are used with compatible CPUs when +16bit integer sample type is used. MMX optimizations are available both +in Win32 and Gnu/x86 platforms. Compatible processors are Intel +PentiumMMX and later; AMD K6-2, Athlon and later.
  • +
  • Intel SSE optimized routines are used with compatible CPUs when +floating point sample type is used. SSE optimizations are currently +implemented for Win32 platform only. Processors compatible with SSE +extension are Intel processors starting from Pentium-III, and AMD +processors starting from Athlon XP.
  • +
  • AMD 3DNow! optimized routines are used with compatible CPUs when +floating point sample type is used, but SSE extension isn't supported . +3DNow! optimizations are currently implemented for Win32 platform only. +These optimizations are used in AMD K6-2 and Athlon (classic) CPU's; +better performing SSE routines are used with AMD processor starting +from Athlon XP.

4. SoundStretch audio processing utility

SoundStretch audio processing utility
-Copyright (c) Olli Parviainen 2002-2009

-

SoundStretch is a simple command-line -application that can change tempo, pitch and playback rates of -WAV sound files. This program is intended primarily to -demonstrate how the "SoundTouch" library can be used to -process sound in your own program, but it can as well be used for -processing sound files.

+ Copyright (c) Olli Parviainen 2002-2012

+

SoundStretch is a simple command-line application that can change +tempo, pitch and playback rates of WAV sound files. This program is +intended primarily to demonstrate how the "SoundTouch" library can be +used to process sound in your own program, but it can as well be used +for processing sound files.

4.1. SoundStretch Usage Instructions

SoundStretch Usage syntax:

soundstretch infilename outfilename [switches]

Where:

- +
- + - + - +
-
"infilename"
+
"infilename"
Name of the input sound -data file (in .WAV audio file format). Give "stdin" as filename to use - standard input pipe. Name of the input sound data file (in .WAV audio +file format). Give "stdin" as filename to use standard input pipe.
-
"outfilename"
+
"outfilename"
Name of the output sound -file where the resulting sound is saved (in .WAV audio file format). -This parameter may be omitted if you  don't want to save the -output -(e.g. when only calculating BPM rate with '-bpm' switch). Give "stdout" - as filename to use standard output pipe.Name of the output sound file where the +resulting sound is saved (in .WAV audio file format). This parameter +may be omitted if you  don't want to save the output (e.g. when +only calculating BPM rate with '-bpm' switch). Give "stdout" as +filename to use standard output pipe.
 [switches]
Are one or more control -switches.Are one or more control switches.

Available control switches are:

- +
- + - + - + - + - + - + - +
-tempo=n 
Change the sound tempo by n -percents (n = -95.0 .. +5000.0 %) Change the sound tempo by n percents (n = -95.0 +.. +5000.0 %)
-pitch=n
Change the sound pitch by n -semitones (n = -60.0 .. + 60.0 semitones) Change the sound pitch by n semitones (n = -60.0 +.. + 60.0 semitones)
-rate=n
Change the sound playback rate by -n percents (n = -95.0 .. +5000.0 %) Change the sound playback rate by n percents (n += -95.0 .. +5000.0 %)
-bpm=n
Detect the Beats-Per-Minute (BPM) rate of the sound and adjust the tempo to meet 'n' - BPMs. When this switch is - applied, the "-tempo" switch is ignored. If "=n" is -omitted, i.e. switch "-bpm" is used alone, then the BPM rate is - estimated and displayed, but tempo not adjusted according to the BPM -value. Detect the Beats-Per-Minute (BPM) rate of the +sound and adjust the tempo to meet 'n' BPMs. When this switch is +applied, the "-tempo" switch is ignored. If "=n" is omitted, i.e. +switch "-bpm" is used alone, then the BPM rate is estimated and +displayed, but tempo not adjusted according to the BPM value.
-quick
Use quicker tempo change -algorithm. Gains speed but loses sound quality. Use quicker tempo change algorithm. Gains speed +but loses sound quality.
-naa
Don't use anti-alias -filtering in sample rate transposing. Gains speed but loses sound -quality. Don't use anti-alias filtering in sample rate +transposing. Gains speed but loses sound quality.
-license
Displays the program license -text (LGPL)Displays the program license text (LGPL)

Notes:

    -
  • To use standard input/output pipes for processing, give "stdin" - and "stdout" as input/output filenames correspondingly. The - standard input/output pipes will still carry the audio data in .wav audio - file format.
  • -
  • The numerical switches allow both integer (e.g. "-tempo=123") and decimal (e.g. -"-tempo=123.45") numbers.
  • -
  • The "-naa" and/or "-quick" switches can be -used to reduce CPU usage while compromising some sound quality
  • -
  • The BPM detection algorithm works by detecting -repeating bass or drum patterns at low frequencies of <250Hz. A - lower-than-expected BPM figure may be reported for music with uneven or - complex bass patterns.
  • +
  • To use standard input/output pipes for processing, give "stdin" +and "stdout" as input/output filenames correspondingly. The standard +input/output pipes will still carry the audio data in .wav audio file +format.
  • +
  • The numerical switches allow both integer (e.g. "-tempo=123") +and decimal (e.g. "-tempo=123.45") numbers.
  • +
  • The "-naa" and/or "-quick" switches can be used to reduce CPU +usage while compromising some sound quality
  • +
  • The BPM detection algorithm works by detecting repeating bass or +drum patterns at low frequencies of <250Hz. A lower-than-expected +BPM figure may be reported for music with uneven or complex bass +patterns.

4.2. SoundStretch usage examples

Example 1

-

The following command increases tempo of -the sound file "originalfile.wav" by 12.5% and stores result to file "destinationfile.wav":

+

The following command increases tempo of the sound file +"originalfile.wav" by 12.5% and stores result to file +"destinationfile.wav":

soundstretch originalfile.wav destinationfile.wav -tempo=12.5

Example 2

-

The following command decreases the sound -pitch (key) of the sound file "orig.wav" by two -semitones and stores the result to file "dest.wav":

+

The following command decreases the sound pitch (key) of the sound +file "orig.wav" by two semitones and stores the result to file +"dest.wav":

soundstretch orig.wav dest.wav -pitch=-2

Example 3

-

The following command processes the file "orig.wav" by decreasing the sound tempo by 25.3% and -increasing the sound pitch (key) by 1.5 semitones. Resulting .wav audio data is -directed to standard output pipe:

+

The following command processes the file "orig.wav" by decreasing +the sound tempo by 25.3% and increasing the sound pitch (key) by 1.5 +semitones. Resulting .wav audio data is directed to standard output +pipe:

soundstretch orig.wav stdout -tempo=-25.3 -pitch=1.5

Example 4

-

The following command detects the BPM rate -of the file "orig.wav" and adjusts the tempo to match -100 beats per minute. Result is stored to file "dest.wav":

+

The following command detects the BPM rate of the file "orig.wav" +and adjusts the tempo to match 100 beats per minute. Result is stored +to file "dest.wav":

soundstretch orig.wav dest.wav -bpm=100

Example 5

-

The following command reads .wav sound data from standard input pipe and -estimates the BPM rate:

+

The following command reads .wav sound data from standard input pipe +and estimates the BPM rate:

soundstretch stdin -bpm

5. Change History

5.1. SoundTouch library Change History

- +

1.7.1:

+
    +
  • Added files for Android compilation +
+

1.7.0:

+
    +
  • Sound quality improvements/li> +
  • Improved flush() to adjust output sound stream duration to match better with + ideal duration
  • +
  • Rewrote x86 cpu feature check to resolve compatibility problems
  • +
  • Configure script automatically checks if CPU supports mmx & sse compatibility for GNU platform, and + the script support now "--enable-x86-optimizations" switch to allow disabling x86-specific optimizations.
  • +
  • Revised #define conditions for 32bit/64bit compatibility
  • +
  • gnu autoconf/automake script compatibility fixes
  • +
  • Tuned beat-per-minute detection algorithm
  • +
+

1.6.0:

+
    +
  • Added automatic cutoff threshold adaptation to beat detection +routine to better adapt BPM calculation to different types of music
  • +
  • Retired 3DNow! optimization support as 3DNow! is nowadays +obsoleted and assembler code is nuisance to maintain
  • +
  • Retired "configure" file from source code package due to +autoconf/automake versio conflicts, so that it is from now on to be +generated by invoking "boostrap" script that uses locally available +toolchain version for generating the "configure" file
  • +
  • Resolved namespace/label naming conflicts with other libraries by +replacing global labels such as INTEGER_SAMPLES with more specific +SOUNDTOUCH_INTEGER_SAMPLES etc.
    +
  • +
  • Updated windows build scripts & project files for Visual +Studio 2008 support
  • +
  • Updated SoundTouch.dll API for .NET compatibility
  • +
  • Added API for querying nominal processing input & output +sample batch sizes
  • +

1.5.0:

    -
  • Added normalization to correlation calculation and improvement automatic seek/sequence parameter calculation to improve sound quality
  • - -
  • Bugfixes:  -
      -
    • Fixed negative array indexing in quick seek algorithm
    • -
    • FIR autoalias filter running too far in processing buffer
    • -
    • Check against zero sample count in rate transposing
    • -
    • Fix for x86-64 support: Removed pop/push instructions from the cpu detection algorithm. 
    • -
    • Check against empty buffers in FIFOSampleBuffer
    • -
    • Other minor fixes & code cleanup
    • -
    -
  • - -
  • Fixes in compilation scripts for non-Intel platforms
  • -
  • Added Dynamic-Link-Library (DLL) version of SoundTouch library build, - provided with Delphi/Pascal wrapper for calling the dll routines
  • -
  • Added #define PREVENT_CLICK_AT_RATE_CROSSOVER that prevents a click artifact - when crossing the nominal pitch from either positive to negative side or vice - versa
  • - +
  • Added normalization to correlation calculation and improvement +automatic seek/sequence parameter calculation to improve sound quality
  • +
  • Bugfixes:  +
      +
    • Fixed negative array indexing in quick seek algorithm
    • +
    • FIR autoalias filter running too far in processing buffer
    • +
    • Check against zero sample count in rate transposing
    • +
    • Fix for x86-64 support: Removed pop/push instructions from +the cpu detection algorithm. 
    • +
    • Check against empty buffers in FIFOSampleBuffer
    • +
    • Other minor fixes & code cleanup
    • +
    +
  • +
  • Fixes in compilation scripts for non-Intel platforms
  • +
  • Added Dynamic-Link-Library (DLL) version of SoundTouch library +build, provided with Delphi/Pascal wrapper for calling the dll routines +
  • +
  • Added #define PREVENT_CLICK_AT_RATE_CROSSOVER that prevents a +click artifact when crossing the nominal pitch from either positive to +negative side or vice versa
-

1.4.1:

    -
  • Fixed a buffer overflow bug in BPM detect algorithm routines if processing - more than 2048 samples at one call 
  • - +
  • Fixed a buffer overflow bug in BPM detect algorithm routines if +processing more than 2048 samples at one call 
-

1.4.0:

    -
  • Improved sound quality by automatic calculation of time stretch algorithm - processing parameters according to tempo setting
  • -
  • Moved BPM detection routines from SoundStretch application into SoundTouch - library
  • -
  • Bugfixes: Usage of uninitialied variables, GNU build scripts, compiler errors - due to 'const' keyword mismatch.
  • -
  • Source code cleanup
  • - +
  • Improved sound quality by automatic calculation of time stretch +algorithm processing parameters according to tempo setting
  • +
  • Moved BPM detection routines from SoundStretch application into +SoundTouch library
  • +
  • Bugfixes: Usage of uninitialied variables, GNU build scripts, +compiler errors due to 'const' keyword mismatch.
  • +
  • Source code cleanup
- -

v1.3.1: -

+

1.3.1:

    -
  • Changed static class declaration to GCC 4.x compiler compatible syntax.
  • -
  • Enabled MMX/SSE-optimized routines also for GCC compilers. Earlier -the MMX/SSE-optimized routines were written in compiler-specific inline -assembler, now these routines are migrated to use compiler intrinsic -syntax which allows compiling the same MMX/SSE-optimized source code with -both Visual C++ and GCC compilers.
  • -
  • Set floating point as the default sample format and added switch to -the GNU configure script for selecting the other sample format.
  • - +
  • Changed static class declaration to GCC 4.x compiler compatible +syntax.
  • +
  • Enabled MMX/SSE-optimized routines also for GCC compilers. +Earlier the MMX/SSE-optimized routines were written in +compiler-specific inline assembler, now these routines are migrated to +use compiler intrinsic syntax which allows compiling the same +MMX/SSE-optimized source code with both Visual C++ and GCC compilers.
  • +
  • Set floating point as the default sample format and added switch +to the GNU configure script for selecting the other sample format.
- -

v1.3.0: -

+

1.3.0:

    -
  • Fixed tempo routine output duration inaccuracy due to rounding +
  • Fixed tempo routine output duration inaccuracy due to rounding error
  • -
  • Implemented separate processing routines for integer and +
  • Implemented separate processing routines for integer and floating arithmetic to allow improvements to floating point routines (earlier used algorithms mostly optimized for integer arithmetic also for floating point samples)
  • -
  • Fixed a bug that distorts sound if sample rate changes during the -sound stream
  • -
  • Fixed a memory leak that appeared in MMX/SSE/3DNow! optimized +
  • Fixed a bug that distorts sound if sample rate changes during +the sound stream
  • +
  • Fixed a memory leak that appeared in MMX/SSE/3DNow! optimized routines
  • -
  • Reduced redundant code pieces in MMX/SSE/3DNow! optimized -routines vs. the standard C routines.
  • -
  • MMX routine incompatibility with new gcc compiler versions
  • -
  • Other miscellaneous bug fixes
  • +
  • Reduced redundant code pieces in MMX/SSE/3DNow! optimized +routines vs. the standard C routines.
  • +
  • MMX routine incompatibility with new gcc compiler versions
  • +
  • Other miscellaneous bug fixes
-

v1.2.1:

+

1.2.1:

    -
  • Added automake/autoconf scripts for GNU -platforms (in courtesy of David Durham)
  • -
  • Fixed SCALE overflow bug in rate transposer -routine.
  • -
  • Fixed 64bit address space bugs.
  • -
  • Created a 'soundtouch' namespace for -SAMPLETYPE definitions.
  • +
  • Added automake/autoconf scripts for GNU platforms (in courtesy +of David Durham)
  • +
  • Fixed SCALE overflow bug in rate transposer routine.
  • +
  • Fixed 64bit address space bugs.
  • +
  • Created a 'soundtouch' namespace for SAMPLETYPE definitions.
-

v1.2.0:

+

1.2.0:

    -
  • Added support for 32bit floating point sample -data type with SSE/3DNow! optimizations for Win32 platform (SSE/3DNow! optimizations currently not supported in GCC environment)
  • -
  • Replaced 'make-gcc' script for GNU environment -by master Makefile
  • -
  • Added time-stretch routine configurability to -SoundTouch main class
  • -
  • Bugfixes
  • +
  • Added support for 32bit floating point sample data type with +SSE/3DNow! optimizations for Win32 platform (SSE/3DNow! optimizations +currently not supported in GCC environment)
  • +
  • Replaced 'make-gcc' script for GNU environment by master +Makefile
  • +
  • Added time-stretch routine configurability to SoundTouch main +class
  • +
  • Bugfixes
-

v1.1.1:

+

1.1.1:

    -
  • Moved SoundTouch under lesser GPL license (LGPL). This allows using SoundTouch library in programs that aren't -released under GPL license.
  • -
  • Changed MMX routine organiation so that MMX optimized routines are now implemented in classes that are derived from -the basic classes having the standard non-mmx routines.
  • -
  • MMX routines to support gcc version 3.
  • -
  • Replaced windows makefiles by script using the .dsw files
  • +
  • Moved SoundTouch under lesser GPL license (LGPL). This allows +using SoundTouch library in programs that aren't released under GPL +license.
  • +
  • Changed MMX routine organiation so that MMX optimized routines +are now implemented in classes that are derived from the basic classes +having the standard non-mmx routines.
  • +
  • MMX routines to support gcc version 3.
  • +
  • Replaced windows makefiles by script using the .dsw files
-

v1.01:

+

1.0.1:

    -
  • "mmx_gcc.cpp": Added "using namespace std" and -removed "return 0" from a function with void return value to fix -compiler errors when compiling the library in Solaris environment.
  • -
  • Moved file "FIFOSampleBuffer.h" to "include" -directory to allow accessing the FIFOSampleBuffer class from external -files.
  • +
  • "mmx_gcc.cpp": Added "using namespace std" and removed "return +0" from a function with void return value to fix compiler errors when +compiling the library in Solaris environment.
  • +
  • Moved file "FIFOSampleBuffer.h" to "include" directory to allow +accessing the FIFOSampleBuffer class from external files.
-

v1.0:

+

1.0:

    -
  • Initial release
  • +
  • Initial release

 

-

5.2. SoundStretch application Change -History

- +

5.2. SoundStretch application Change History

+

1.7.0:

+
    +
  • Bugfixes in Wavfile: exception string formatting, avoid getLengthMs() integer + precision overflow, support WAV files using 24/32bit sample format.
  • +
+

1.5.0:

+
    +
  • Added "-speech" switch to activate algorithm parameters more +suitable for speech processing than the default parameters tuned for +music processing.
  • +

1.4.0:

    -
  • Moved BPM detection routines from SoundStretch application into SoundTouch - library
  • -
  • Allow using standard input/output pipes as audio processing input/output - streams
  • - +
  • Moved BPM detection routines from SoundStretch application into +SoundTouch library
  • +
  • Allow using standard input/output pipes as audio processing +input/output streams
- -

v1.3.0:

+

1.3.0:

    -
  • Simplified accessing WAV files with floating -point sample format. -
  • +
  • Simplified accessing WAV files with floating point sample +format.
-

v1.2.1:

+

1.2.1:

    -
  • Fixed 64bit address space bugs.
  • +
  • Fixed 64bit address space bugs.
-

v1.2.0:

+

1.2.0:

    -
  • Added support for 32bit floating point sample -data type
  • -
  • Restructured the BPM routines into separate -library
  • -
  • Fixed big-endian conversion bugs in WAV file -routines (hopefully :)
  • +
  • Added support for 32bit floating point sample data type
  • +
  • Restructured the BPM routines into separate library
  • +
  • Fixed big-endian conversion bugs in WAV file routines (hopefully +:)
-

v1.1.1:

+

1.1.1:

    -
  • Fixed bugs in WAV file reading & added -byte-order conversion for big-endian processors.
  • -
  • Moved SoundStretch source code under 'example' -directory to highlight difference from SoundTouch stuff.
  • -
  • Replaced windows makefiles by script using the .dsw files
  • -
  • Output file name isn't required if output -isn't desired (e.g. if using the switch '-bpm' in plain format only)
  • +
  • Fixed bugs in WAV file reading & added byte-order conversion +for big-endian processors.
  • +
  • Moved SoundStretch source code under 'example' directory to +highlight difference from SoundTouch stuff.
  • +
  • Replaced windows makefiles by script using the .dsw files
  • +
  • Output file name isn't required if output isn't desired (e.g. if +using the switch '-bpm' in plain format only)
-

v1.1:

+

1.1:

    -
  • Fixed "Release" settings in Microsoft Visual -C++ project file (.dsp)
  • -
  • Added beats-per-minute (BPM) detection routine -and command-line switch "-bpm"
  • +
  • Fixed "Release" settings in Microsoft Visual C++ project file +(.dsp)
  • +
  • Added beats-per-minute (BPM) detection routine and command-line +switch "-bpm"
-

v1.01:

+

1.01:

    -
  • Initial release
  • +
  • Initial release

-

6. Acknowledgements

-

Kudos for these people who have contributed to development or submitted -bugfixes since -SoundTouch v1.3.1:

+

6. Acknowledgements

+

Kudos for these people who have contributed to development or +submitted bugfixes since SoundTouch v1.3.1:

    -
  • Arthur A
  • -
  • Richard Ash
  • -
  • Stanislav Brabec
  • -
  • Christian Budde
  • -
  • Brian Cameron
  • -
  • Jason Champion
  • -
  • Patrick Colis
  • -
  • Justin Frankel
  • -
  • Jason Garland
  • -
  • Takashi Iwai
  • -
  • Paulo Pizarro
  • -
  • RJ Ryan
  • -
  • John Sheehy
  • +
  • Arthur A
  • +
  • Richard Ash
  • +
  • Stanislav Brabec
  • +
  • Christian Budde
  • +
  • Jacek Caban
  • +
  • Brian Cameron
  • +
  • Jason Champion
  • +
  • David Clark
  • +
  • Patrick Colis
  • +
  • Miquel Colon
  • +
  • Justin Frankel
  • +
  • Jason Garland
  • +
  • Takashi Iwai
  • +
  • Yuval Naveh
  • +
  • Paulo Pizarro
  • +
  • Blaise Potard
  • +
  • RJ Ryan
  • +
  • Patrick Colis
  • +
  • Miquel Colon
  • +
  • Sandro Cumerlato
  • +
  • Justin Frankel
  • +
  • Jason Garland
  • +
  • Takashi Iwai
  • +
  • Mathias Möhl
  • +
  • Yuval Naveh
  • +
  • Paulo Pizarro
  • +
  • Blaise Potard
  • +
  • RJ Ryan
  • +
  • John Sheehy
  • +
  • Tim Shuttleworth
  • +
  • John Stumpo
  • +
  • Tim Shuttleworth
  • +
  • Katja Vetter
-

Moral greetings to all other contributors and users also!

+

Moral greetings to all other contributors and users also!


-

7. LICENSE

+

7. LICENSE

SoundTouch audio processing library
Copyright (c) Olli Parviainen

-

This library 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.

-

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., 59 Temple Place, -Suite 330, Boston, MA 02111-1307 USA

-
- +

This library 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.

+

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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

+
+

+ RREADME.html file updated on 28-Dec-2012

diff --git a/3rdparty/SoundTouch/RateTransposer.cpp b/3rdparty/SoundTouch/RateTransposer.cpp index 7d992f8ce..19d4bf8ef 100644 --- a/3rdparty/SoundTouch/RateTransposer.cpp +++ b/3rdparty/SoundTouch/RateTransposer.cpp @@ -1,6 +1,6 @@ //////////////////////////////////////////////////////////////////////////////// -/// -/// Sample rate transposer. Changes sample rate by using linear interpolation +/// +/// Sample rate transposer. Changes sample rate by using linear interpolation /// together with anti-alias filtering (first order interpolation with anti- /// alias filtering should be quite adequate for this application) /// @@ -10,10 +10,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2009-10-31 16:37:24 +0200 (Sat, 31 Oct 2009) $ +// Last changed : $Date: 2011-09-02 15:56:11 -0300 (sex, 02 set 2011) $ // File revision : $Revision: 4 $ // -// $Id: RateTransposer.cpp 74 2009-10-31 14:37:24Z oparviai $ +// $Id: RateTransposer.cpp 131 2011-09-02 18:56:11Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -42,11 +42,9 @@ #include #include #include -#include #include "RateTransposer.h" #include "AAFilter.h" -using namespace std; using namespace soundtouch; @@ -61,18 +59,18 @@ protected: virtual void resetRegisters(); - virtual uint transposeStereo(SAMPLETYPE *dest, - const SAMPLETYPE *src, + virtual uint transposeStereo(SAMPLETYPE *dest, + const SAMPLETYPE *src, uint numSamples); - virtual uint transposeMono(SAMPLETYPE *dest, - const SAMPLETYPE *src, + virtual uint transposeMono(SAMPLETYPE *dest, + const SAMPLETYPE *src, uint numSamples); public: RateTransposerInteger(); virtual ~RateTransposerInteger(); - /// Sets new target rate. Normal rate = 1.0, smaller values represent slower + /// Sets new target rate. Normal rate = 1.0, smaller values represent slower /// rate, larger faster rates. virtual void setRate(float newRate); @@ -89,11 +87,11 @@ protected: virtual void resetRegisters(); - virtual uint transposeStereo(SAMPLETYPE *dest, - const SAMPLETYPE *src, + virtual uint transposeStereo(SAMPLETYPE *dest, + const SAMPLETYPE *src, uint numSamples); - virtual uint transposeMono(SAMPLETYPE *dest, - const SAMPLETYPE *src, + virtual uint transposeMono(SAMPLETYPE *dest, + const SAMPLETYPE *src, uint numSamples); public: @@ -104,18 +102,18 @@ public: -// Operator 'new' is overloaded so that it automatically creates a suitable instance +// Operator 'new' is overloaded so that it automatically creates a suitable instance // depending on if we've a MMX/SSE/etc-capable CPU available or not. void * RateTransposer::operator new(size_t s) { - throw runtime_error("Error in RateTransoser::new: don't use \"new TDStretch\" directly, use \"newInstance\" to create a new instance instead!"); - return NULL; + ST_THROW_RT_ERROR("Error in RateTransoser::new: don't use \"new TDStretch\" directly, use \"newInstance\" to create a new instance instead!"); + return newInstance(); } RateTransposer *RateTransposer::newInstance() { -#ifdef INTEGER_SAMPLES +#ifdef SOUNDTOUCH_INTEGER_SAMPLES return ::new RateTransposerInteger; #else return ::new RateTransposerFloat; @@ -165,7 +163,7 @@ AAFilter *RateTransposer::getAAFilter() -// Sets new target iRate. Normal iRate = 1.0, smaller values represent slower +// Sets new target iRate. Normal iRate = 1.0, smaller values represent slower // iRate, larger faster iRates. void RateTransposer::setRate(float newRate) { @@ -174,11 +172,11 @@ void RateTransposer::setRate(float newRate) fRate = newRate; // design a new anti-alias filter - if (newRate > 1.0f) + if (newRate > 1.0f) { fCutoff = 0.5f / newRate; - } - else + } + else { fCutoff = 0.5f * newRate; } @@ -220,7 +218,7 @@ void RateTransposer::upsample(const SAMPLETYPE *src, uint nSamples) // If the parameter 'uRate' value is smaller than 'SCALE', first transpose // the samples and then apply the anti-alias filter to remove aliasing. - // First check that there's enough room in 'storeBuffer' + // First check that there's enough room in 'storeBuffer' // (+16 is to reserve some slack in the destination buffer) sizeTemp = (uint)((float)nSamples / fRate + 16.0f); @@ -231,7 +229,7 @@ void RateTransposer::upsample(const SAMPLETYPE *src, uint nSamples) // Apply the anti-alias filter to samples in "store output", output the // result to "dest" num = storeBuffer.numSamples(); - count = pAAFilter->evaluate(outputBuffer.ptrEnd(num), + count = pAAFilter->evaluate(outputBuffer.ptrEnd(num), storeBuffer.ptrBegin(), num, (uint)numChannels); outputBuffer.putSamples(count); @@ -253,13 +251,13 @@ void RateTransposer::downsample(const SAMPLETYPE *src, uint nSamples) // Add the new samples to the end of the storeBuffer storeBuffer.putSamples(src, nSamples); - // Anti-alias filter the samples to prevent folding and output the filtered + // Anti-alias filter the samples to prevent folding and output the filtered // data to tempBuffer. Note : because of the FIR filter length, the // filtering routine takes in 'filter_length' more samples than it outputs. assert(tempBuffer.isEmpty()); sizeTemp = storeBuffer.numSamples(); - count = pAAFilter->evaluate(tempBuffer.ptrEnd(sizeTemp), + count = pAAFilter->evaluate(tempBuffer.ptrEnd(sizeTemp), storeBuffer.ptrBegin(), sizeTemp, (uint)numChannels); if (count == 0) return; @@ -274,7 +272,7 @@ void RateTransposer::downsample(const SAMPLETYPE *src, uint nSamples) } -// Transposes sample rate by applying anti-alias filter to prevent folding. +// Transposes sample rate by applying anti-alias filter to prevent folding. // Returns amount of samples returned in the "dest" buffer. // The maximum amount of samples that can be returned at a time is set by // the 'set_returnBuffer_size' function. @@ -288,7 +286,7 @@ void RateTransposer::processSamples(const SAMPLETYPE *src, uint nSamples) // If anti-alias filter is turned off, simply transpose without applying // the filter - if (bUseAAFilter == FALSE) + if (bUseAAFilter == FALSE) { sizeReq = (uint)((float)nSamples / fRate + 1.0f); count = transpose(outputBuffer.ptrEnd(sizeReq), src, nSamples); @@ -297,26 +295,26 @@ void RateTransposer::processSamples(const SAMPLETYPE *src, uint nSamples) } // Transpose with anti-alias filter - if (fRate < 1.0f) + if (fRate < 1.0f) { upsample(src, nSamples); - } - else + } + else { downsample(src, nSamples); } } -// Transposes the sample rate of the given samples using linear interpolation. +// Transposes the sample rate of the given samples using linear interpolation. // Returns the number of samples returned in the "dest" buffer inline uint RateTransposer::transpose(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples) { - if (numChannels == 2) + if (numChannels == 2) { return transposeStereo(dest, src, nSamples); - } - else + } + else { return transposeMono(dest, src, nSamples); } @@ -363,7 +361,7 @@ int RateTransposer::isEmpty() const ////////////////////////////////////////////////////////////////////////////// // // RateTransposerInteger - integer arithmetic implementation -// +// /// fixed-point interpolation routine precision #define SCALE 65536 @@ -371,7 +369,7 @@ int RateTransposer::isEmpty() const // Constructor RateTransposerInteger::RateTransposerInteger() : RateTransposer() { - // Notice: use local function calling syntax for sake of clarity, + // Notice: use local function calling syntax for sake of clarity, // to indicate the fact that C++ constructor can't call virtual functions. RateTransposerInteger::resetRegisters(); RateTransposerInteger::setRate(1.0f); @@ -386,14 +384,14 @@ RateTransposerInteger::~RateTransposerInteger() void RateTransposerInteger::resetRegisters() { iSlopeCount = 0; - sPrevSampleL = + sPrevSampleL = sPrevSampleR = 0; } -// Transposes the sample rate of the given samples using linear interpolation. -// 'Mono' version of the routine. Returns the number of samples returned in +// Transposes the sample rate of the given samples using linear interpolation. +// 'Mono' version of the routine. Returns the number of samples returned in // the "dest" buffer uint RateTransposerInteger::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples) { @@ -402,11 +400,11 @@ uint RateTransposerInteger::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *sr if (nSamples == 0) return 0; // no samples, no work - used = 0; + used = 0; i = 0; // Process the last sample saved from the previous call first... - while (iSlopeCount <= SCALE) + while (iSlopeCount <= SCALE) { vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount); temp = vol1 * sPrevSampleL + iSlopeCount * src[0]; @@ -419,7 +417,7 @@ uint RateTransposerInteger::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *sr while (1) { - while (iSlopeCount > SCALE) + while (iSlopeCount > SCALE) { iSlopeCount -= SCALE; used ++; @@ -440,8 +438,8 @@ end: } -// Transposes the sample rate of the given samples using linear interpolation. -// 'Stereo' version of the routine. Returns the number of samples returned in +// Transposes the sample rate of the given samples using linear interpolation. +// 'Stereo' version of the routine. Returns the number of samples returned in // the "dest" buffer uint RateTransposerInteger::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples) { @@ -450,11 +448,11 @@ uint RateTransposerInteger::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE * if (nSamples == 0) return 0; // no samples, no work - used = 0; + used = 0; i = 0; // Process the last sample saved from the sPrevSampleLious call first... - while (iSlopeCount <= SCALE) + while (iSlopeCount <= SCALE) { vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount); temp = vol1 * sPrevSampleL + iSlopeCount * src[0]; @@ -469,7 +467,7 @@ uint RateTransposerInteger::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE * while (1) { - while (iSlopeCount > SCALE) + while (iSlopeCount > SCALE) { iSlopeCount -= SCALE; used ++; @@ -494,7 +492,7 @@ end: } -// Sets new target iRate. Normal iRate = 1.0, smaller values represent slower +// Sets new target iRate. Normal iRate = 1.0, smaller values represent slower // iRate, larger faster iRates. void RateTransposerInteger::setRate(float newRate) { @@ -506,13 +504,13 @@ void RateTransposerInteger::setRate(float newRate) ////////////////////////////////////////////////////////////////////////////// // // RateTransposerFloat - floating point arithmetic implementation -// +// ////////////////////////////////////////////////////////////////////////////// // Constructor RateTransposerFloat::RateTransposerFloat() : RateTransposer() { - // Notice: use local function calling syntax for sake of clarity, + // Notice: use local function calling syntax for sake of clarity, // to indicate the fact that C++ constructor can't call virtual functions. RateTransposerFloat::resetRegisters(); RateTransposerFloat::setRate(1.0f); @@ -527,24 +525,24 @@ RateTransposerFloat::~RateTransposerFloat() void RateTransposerFloat::resetRegisters() { fSlopeCount = 0; - sPrevSampleL = + sPrevSampleL = sPrevSampleR = 0; } -// Transposes the sample rate of the given samples using linear interpolation. -// 'Mono' version of the routine. Returns the number of samples returned in +// Transposes the sample rate of the given samples using linear interpolation. +// 'Mono' version of the routine. Returns the number of samples returned in // the "dest" buffer uint RateTransposerFloat::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples) { unsigned int i, used; - used = 0; + used = 0; i = 0; // Process the last sample saved from the previous call first... - while (fSlopeCount <= 1.0f) + while (fSlopeCount <= 1.0f) { dest[i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleL + fSlopeCount * src[0]); i++; @@ -556,7 +554,7 @@ uint RateTransposerFloat::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, { while (1) { - while (fSlopeCount > 1.0f) + while (fSlopeCount > 1.0f) { fSlopeCount -= 1.0f; used ++; @@ -575,8 +573,8 @@ end: } -// Transposes the sample rate of the given samples using linear interpolation. -// 'Mono' version of the routine. Returns the number of samples returned in +// Transposes the sample rate of the given samples using linear interpolation. +// 'Mono' version of the routine. Returns the number of samples returned in // the "dest" buffer uint RateTransposerFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples) { @@ -584,11 +582,11 @@ uint RateTransposerFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *sr if (nSamples == 0) return 0; // no samples, no work - used = 0; + used = 0; i = 0; // Process the last sample saved from the sPrevSampleLious call first... - while (fSlopeCount <= 1.0f) + while (fSlopeCount <= 1.0f) { dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleL + fSlopeCount * src[0]); dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleR + fSlopeCount * src[1]); @@ -602,7 +600,7 @@ uint RateTransposerFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *sr { while (1) { - while (fSlopeCount > 1.0f) + while (fSlopeCount > 1.0f) { fSlopeCount -= 1.0f; used ++; @@ -610,9 +608,9 @@ uint RateTransposerFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *sr } srcPos = 2 * used; - dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[srcPos] + dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[srcPos] + fSlopeCount * src[srcPos + 2]); - dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[srcPos + 1] + dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[srcPos + 1] + fSlopeCount * src[srcPos + 3]); i++; diff --git a/3rdparty/SoundTouch/RateTransposer.h b/3rdparty/SoundTouch/RateTransposer.h index 6ab058648..8374a0f83 100644 --- a/3rdparty/SoundTouch/RateTransposer.h +++ b/3rdparty/SoundTouch/RateTransposer.h @@ -1,10 +1,10 @@ //////////////////////////////////////////////////////////////////////////////// -/// -/// Sample rate transposer. Changes sample rate by using linear interpolation +/// +/// Sample rate transposer. Changes sample rate by using linear interpolation /// together with anti-alias filtering (first order interpolation with anti- /// alias filtering should be quite adequate for this application). /// -/// Use either of the derived classes of 'RateTransposerInteger' or +/// Use either of the derived classes of 'RateTransposerInteger' or /// 'RateTransposerFloat' for corresponding integer/floating point tranposing /// algorithm implementation. /// @@ -14,7 +14,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2009-02-21 18:00:14 +0200 (Sat, 21 Feb 2009) $ +// Last changed : $Date: 2009-02-21 13:00:14 -0300 (sáb, 21 fev 2009) $ // File revision : $Revision: 4 $ // // $Id: RateTransposer.h 63 2009-02-21 16:00:14Z oparviai $ @@ -57,9 +57,9 @@ namespace soundtouch /// A common linear samplerate transposer class. /// -/// Note: Use function "RateTransposer::newInstance()" to create a new class -/// instance instead of the "new" operator; that function automatically -/// chooses a correct implementation depending on if integer or floating +/// Note: Use function "RateTransposer::newInstance()" to create a new class +/// instance instead of the "new" operator; that function automatically +/// chooses a correct implementation depending on if integer or floating /// arithmetics are to be used. class RateTransposer : public FIFOProcessor { @@ -85,26 +85,26 @@ protected: virtual void resetRegisters() = 0; - virtual uint transposeStereo(SAMPLETYPE *dest, - const SAMPLETYPE *src, + virtual uint transposeStereo(SAMPLETYPE *dest, + const SAMPLETYPE *src, uint numSamples) = 0; - virtual uint transposeMono(SAMPLETYPE *dest, - const SAMPLETYPE *src, + virtual uint transposeMono(SAMPLETYPE *dest, + const SAMPLETYPE *src, uint numSamples) = 0; - inline uint transpose(SAMPLETYPE *dest, - const SAMPLETYPE *src, + inline uint transpose(SAMPLETYPE *dest, + const SAMPLETYPE *src, uint numSamples); - void downsample(const SAMPLETYPE *src, + void downsample(const SAMPLETYPE *src, uint numSamples); - void upsample(const SAMPLETYPE *src, + void upsample(const SAMPLETYPE *src, uint numSamples); - /// Transposes sample rate by applying anti-alias filter to prevent folding. + /// Transposes sample rate by applying anti-alias filter to prevent folding. /// Returns amount of samples returned in the "dest" buffer. /// The maximum amount of samples that can be returned at a time is set by /// the 'set_returnBuffer_size' function. - void processSamples(const SAMPLETYPE *src, + void processSamples(const SAMPLETYPE *src, uint numSamples); @@ -112,12 +112,12 @@ public: RateTransposer(); virtual ~RateTransposer(); - /// Operator 'new' is overloaded so that it automatically creates a suitable instance + /// Operator 'new' is overloaded so that it automatically creates a suitable instance /// depending on if we're to use integer or floating point arithmetics. static void *operator new(size_t s); - /// Use this function instead of "new" operator to create a new instance of this class. - /// This function automatically chooses a correct implementation, depending on if + /// Use this function instead of "new" operator to create a new instance of this class. + /// This function automatically chooses a correct implementation, depending on if /// integer ot floating point arithmetics are to be used. static RateTransposer *newInstance(); @@ -136,7 +136,7 @@ public: /// Returns nonzero if anti-alias filter is enabled. BOOL isAAFilterEnabled() const; - /// Sets new target rate. Normal rate = 1.0, smaller values represent slower + /// Sets new target rate. Normal rate = 1.0, smaller values represent slower /// rate, larger faster rates. virtual void setRate(float newRate); diff --git a/3rdparty/SoundTouch/STTypes.h b/3rdparty/SoundTouch/STTypes.h index 1fcd9e2da..2c4584a14 100644 --- a/3rdparty/SoundTouch/STTypes.h +++ b/3rdparty/SoundTouch/STTypes.h @@ -8,10 +8,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2009-05-17 14:30:57 +0300 (Sun, 17 May 2009) $ +// Last changed : $Date: 2012-12-28 12:53:56 -0200 (sex, 28 dez 2012) $ // File revision : $Revision: 3 $ // -// $Id: STTypes.h 70 2009-05-17 11:30:57Z oparviai $ +// $Id: STTypes.h 162 2012-12-28 14:53:56Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -42,8 +42,21 @@ typedef unsigned int uint; typedef unsigned long ulong; -#ifdef __GNUC__ - // In GCC, include soundtouch_config.h made by config scritps +// Patch for MinGW: on Win64 long is 32-bit +#ifdef _WIN64 + typedef unsigned long long ulongptr; +#else + typedef ulong ulongptr; +#endif + + +// Helper macro for aligning pointer up to next 16-byte boundary +#define SOUNDTOUCH_ALIGN_POINTER_16(x) ( ( (ulongptr)(x) + 15 ) & ~(ulongptr)15 ) + + +#if (defined(__GNUC__) && !defined(ANDROID)) + // In GCC, include soundtouch_config.h made by config scritps. + // Skip this in Android compilation that uses GCC but without configure scripts. #include "soundtouch_config.h" #endif @@ -60,64 +73,81 @@ typedef unsigned long ulong; namespace soundtouch { + /// Activate these undef's to overrule the possible sampletype + /// setting inherited from some other header file: + //#undef SOUNDTOUCH_INTEGER_SAMPLES + //#undef SOUNDTOUCH_FLOAT_SAMPLES -/// Activate these undef's to overrule the possible sampletype -/// setting inherited from some other header file: -//#undef INTEGER_SAMPLES -//#undef FLOAT_SAMPLES + #if (defined(__SOFTFP__)) + // For Android compilation: Force use of Integer samples in case that + // compilation uses soft-floating point emulation - soft-fp is way too slow + #undef SOUNDTOUCH_FLOAT_SAMPLES + #define SOUNDTOUCH_INTEGER_SAMPLES 1 + #endif -#if !(INTEGER_SAMPLES || FLOAT_SAMPLES) + #if !(SOUNDTOUCH_INTEGER_SAMPLES || SOUNDTOUCH_FLOAT_SAMPLES) + + /// Choose either 32bit floating point or 16bit integer sampletype + /// by choosing one of the following defines, unless this selection + /// has already been done in some other file. + //// + /// Notes: + /// - In Windows environment, choose the sample format with the + /// following defines. + /// - In GNU environment, the floating point samples are used by + /// default, but integer samples can be chosen by giving the + /// following switch to the configure script: + /// ./configure --enable-integer-samples + /// However, if you still prefer to select the sample format here + /// also in GNU environment, then please #undef the INTEGER_SAMPLE + /// and FLOAT_SAMPLE defines first as in comments above. + //#define SOUNDTOUCH_INTEGER_SAMPLES 1 //< 16bit integer samples + #define SOUNDTOUCH_FLOAT_SAMPLES 1 //< 32bit float samples + + #endif - /// Choose either 32bit floating point or 16bit integer sampletype - /// by choosing one of the following defines, unless this selection - /// has already been done in some other file. - //// - /// Notes: - /// - In Windows environment, choose the sample format with the - /// following defines. - /// - In GNU environment, the floating point samples are used by - /// default, but integer samples can be chosen by giving the - /// following switch to the configure script: - /// ./configure --enable-integer-samples - /// However, if you still prefer to select the sample format here - /// also in GNU environment, then please #undef the INTEGER_SAMPLE - /// and FLOAT_SAMPLE defines first as in comments above. - //#define INTEGER_SAMPLES 1 //< 16bit integer samples - #define FLOAT_SAMPLES 1 //< 32bit float samples - - #endif - - #if (WIN32 || __i386__ || __x86_64__) - /// Define this to allow X86-specific assembler/intrinsic optimizations. + #if (_M_IX86 || __i386__ || __x86_64__ || _M_X64) + /// Define this to allow X86-specific assembler/intrinsic optimizations. /// Notice that library contains also usual C++ versions of each of these - /// these routines, so if you're having difficulties getting the optimized - /// routines compiled for whatever reason, you may disable these optimizations + /// these routines, so if you're having difficulties getting the optimized + /// routines compiled for whatever reason, you may disable these optimizations /// to make the library compile. - #define ALLOW_X86_OPTIMIZATIONS 1 + #define SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS 1 + + /// In GNU environment, allow the user to override this setting by + /// giving the following switch to the configure script: + /// ./configure --disable-x86-optimizations + /// ./configure --enable-x86-optimizations=no + #ifdef SOUNDTOUCH_DISABLE_X86_OPTIMIZATIONS + #undef SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS + #endif + #else + /// Always disable optimizations when not using a x86 systems. + #undef SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS #endif - // If defined, allows the SIMD-optimized routines to take minor shortcuts - // for improved performance. Undefine to require faithfully similar SIMD + // If defined, allows the SIMD-optimized routines to take minor shortcuts + // for improved performance. Undefine to require faithfully similar SIMD // calculations as in normal C implementation. - #define ALLOW_NONEXACT_SIMD_OPTIMIZATION 1 + #define SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION 1 - #ifdef INTEGER_SAMPLES + #ifdef SOUNDTOUCH_INTEGER_SAMPLES // 16bit integer sample type typedef short SAMPLETYPE; // data type for sample accumulation: Use 32bit integer to prevent overflows typedef long LONG_SAMPLETYPE; - #ifdef FLOAT_SAMPLES + #ifdef SOUNDTOUCH_FLOAT_SAMPLES // check that only one sample type is defined #error "conflicting sample types defined" - #endif // FLOAT_SAMPLES + #endif // SOUNDTOUCH_FLOAT_SAMPLES - #ifdef ALLOW_X86_OPTIMIZATIONS + #ifdef SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS // Allow MMX optimizations - #define ALLOW_MMX 1 + #define SOUNDTOUCH_ALLOW_MMX 1 #endif #else @@ -127,23 +157,31 @@ namespace soundtouch // data type for sample accumulation: Use double to utilize full precision. typedef double LONG_SAMPLETYPE; - #ifdef ALLOW_X86_OPTIMIZATIONS - // Allow 3DNow! and SSE optimizations - #if WIN32 - #define ALLOW_3DNOW 1 - #endif - - #define ALLOW_SSE 1 + #ifdef SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS + // Allow SSE optimizations + #define SOUNDTOUCH_ALLOW_SSE 1 #endif - #endif // INTEGER_SAMPLES + #endif // SOUNDTOUCH_INTEGER_SAMPLES + }; +// define ST_NO_EXCEPTION_HANDLING switch to disable throwing std exceptions: +// #define ST_NO_EXCEPTION_HANDLING 1 +#ifdef ST_NO_EXCEPTION_HANDLING + // Exceptions disabled. Throw asserts instead if enabled. + #include + #define ST_THROW_RT_ERROR(x) {assert((const char *)x);} +#else + // use c++ standard exceptions + #include + #define ST_THROW_RT_ERROR(x) {throw std::runtime_error(x);} +#endif -// When this #define is active, eliminates a clicking sound when the "rate" or "pitch" -// parameter setting crosses from value <1 to >=1 or vice versa during processing. -// Default is off as such crossover is untypical case and involves a slight sound +// When this #define is active, eliminates a clicking sound when the "rate" or "pitch" +// parameter setting crosses from value <1 to >=1 or vice versa during processing. +// Default is off as such crossover is untypical case and involves a slight sound // quality compromise. -//#define PREVENT_CLICK_AT_RATE_CROSSOVER 1 +//#define SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER 1 #endif diff --git a/3rdparty/SoundTouch/SoundTouch.cpp b/3rdparty/SoundTouch/SoundTouch.cpp index 8abfc23b2..c66c16c54 100644 --- a/3rdparty/SoundTouch/SoundTouch.cpp +++ b/3rdparty/SoundTouch/SoundTouch.cpp @@ -1,27 +1,27 @@ ////////////////////////////////////////////////////////////////////////////// /// -/// SoundTouch - main class for tempo/pitch/rate adjusting routines. +/// SoundTouch - main class for tempo/pitch/rate adjusting routines. /// /// Notes: -/// - Initialize the SoundTouch object instance by setting up the sound stream -/// parameters with functions 'setSampleRate' and 'setChannels', then set +/// - Initialize the SoundTouch object instance by setting up the sound stream +/// parameters with functions 'setSampleRate' and 'setChannels', then set /// desired tempo/pitch/rate settings with the corresponding functions. /// -/// - The SoundTouch class behaves like a first-in-first-out pipeline: The +/// - The SoundTouch class behaves like a first-in-first-out pipeline: The /// samples that are to be processed are fed into one of the pipe by calling -/// function 'putSamples', while the ready processed samples can be read +/// function 'putSamples', while the ready processed samples can be read /// from the other end of the pipeline with function 'receiveSamples'. -/// -/// - The SoundTouch processing classes require certain sized 'batches' of -/// samples in order to process the sound. For this reason the classes buffer -/// incoming samples until there are enough of samples available for +/// +/// - The SoundTouch processing classes require certain sized 'batches' of +/// samples in order to process the sound. For this reason the classes buffer +/// incoming samples until there are enough of samples available for /// processing, then they carry out the processing step and consequently /// make the processed samples available for outputting. -/// -/// - For the above reason, the processing routines introduce a certain +/// +/// - For the above reason, the processing routines introduce a certain /// 'latency' between the input and output, so that the samples input to -/// SoundTouch may not be immediately available in the output, and neither -/// the amount of outputtable samples may not immediately be in direct +/// SoundTouch may not be immediately available in the output, and neither +/// the amount of outputtable samples may not immediately be in direct /// relationship with the amount of previously input samples. /// /// - The tempo/pitch/rate control parameters can be altered during processing. @@ -30,8 +30,8 @@ /// required. /// /// - This class utilizes classes 'TDStretch' for tempo change (without modifying -/// pitch) and 'RateTransposer' for changing the playback rate (that is, both -/// tempo and pitch in the same ratio) of the sound. The third available control +/// pitch) and 'RateTransposer' for changing the playback rate (that is, both +/// tempo and pitch in the same ratio) of the sound. The third available control /// 'pitch' (change pitch but maintain tempo) is produced by a combination of /// combining the two other controls. /// @@ -41,10 +41,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2009-05-19 07:57:30 +0300 (Tue, 19 May 2009) $ +// Last changed : $Date: 2012-06-13 16:29:53 -0300 (qua, 13 jun 2012) $ // File revision : $Revision: 4 $ // -// $Id: SoundTouch.cpp 73 2009-05-19 04:57:30Z oparviai $ +// $Id: SoundTouch.cpp 143 2012-06-13 19:29:53Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -73,7 +73,6 @@ #include #include #include -#include #include #include "SoundTouch.h" @@ -82,7 +81,7 @@ #include "cpu_detect.h" using namespace soundtouch; - + /// test if two floating point numbers are equal #define TEST_FLOAT_EQUAL(a, b) (fabs(a - b) < 1e-10) @@ -91,7 +90,7 @@ using namespace soundtouch; extern "C" void soundtouch_ac_test() { printf("SoundTouch Version: %s\n",SOUNDTOUCH_VERSION); -} +} SoundTouch::SoundTouch() @@ -105,8 +104,8 @@ SoundTouch::SoundTouch() rate = tempo = 0; - virtualPitch = - virtualRate = + virtualPitch = + virtualRate = virtualTempo = 1.0; calcEffectiveRateAndTempo(); @@ -144,9 +143,9 @@ uint SoundTouch::getVersionId() // Sets the number of channels, 1 = mono, 2 = stereo void SoundTouch::setChannels(uint numChannels) { - if (numChannels != 1 && numChannels != 2) + if (numChannels != 1 && numChannels != 2) { - throw std::runtime_error("Illegal number of channels"); + ST_THROW_RT_ERROR("Illegal number of channels"); } channels = numChannels; pRateTransposer->setChannels((int)numChannels); @@ -243,10 +242,10 @@ void SoundTouch::calcEffectiveRateAndTempo() if (!TEST_FLOAT_EQUAL(rate,oldRate)) pRateTransposer->setRate(rate); if (!TEST_FLOAT_EQUAL(tempo, oldTempo)) pTDStretch->setTempo(tempo); -#ifndef PREVENT_CLICK_AT_RATE_CROSSOVER - if (rate <= 1.0f) +#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER + if (rate <= 1.0f) { - if (output != pTDStretch) + if (output != pTDStretch) { FIFOSamplePipe *tempoOut; @@ -263,7 +262,7 @@ void SoundTouch::calcEffectiveRateAndTempo() else #endif { - if (output != pRateTransposer) + if (output != pRateTransposer) { FIFOSamplePipe *transOut; @@ -276,7 +275,7 @@ void SoundTouch::calcEffectiveRateAndTempo() output = pRateTransposer; } - } + } } @@ -293,42 +292,42 @@ void SoundTouch::setSampleRate(uint srate) // the input of the object. void SoundTouch::putSamples(const SAMPLETYPE *samples, uint nSamples) { - if (bSrateSet == FALSE) + if (bSrateSet == FALSE) { - throw std::runtime_error("SoundTouch : Sample rate not defined"); - } - else if (channels == 0) + ST_THROW_RT_ERROR("SoundTouch : Sample rate not defined"); + } + else if (channels == 0) { - throw std::runtime_error("SoundTouch : Number of channels not defined"); + ST_THROW_RT_ERROR("SoundTouch : Number of channels not defined"); } // Transpose the rate of the new samples if necessary /* Bypass the nominal setting - can introduce a click in sound when tempo/pitch control crosses the nominal value... - if (rate == 1.0f) + if (rate == 1.0f) { - // The rate value is same as the original, simply evaluate the tempo changer. + // The rate value is same as the original, simply evaluate the tempo changer. assert(output == pTDStretch); - if (pRateTransposer->isEmpty() == 0) + if (pRateTransposer->isEmpty() == 0) { // yet flush the last samples in the pitch transposer buffer // (may happen if 'rate' changes from a non-zero value to zero) pTDStretch->moveSamples(*pRateTransposer); } pTDStretch->putSamples(samples, nSamples); - } + } */ -#ifndef PREVENT_CLICK_AT_RATE_CROSSOVER - else if (rate <= 1.0f) +#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER + else if (rate <= 1.0f) { // transpose the rate down, output the transposed sound to tempo changer buffer assert(output == pTDStretch); pRateTransposer->putSamples(samples, nSamples); pTDStretch->moveSamples(*pRateTransposer); - } - else + } + else #endif { - // evaluate the tempo changer, then transpose the rate up, + // evaluate the tempo changer, then transpose the rate up, assert(output == pRateTransposer); pTDStretch->putSamples(samples, nSamples); pRateTransposer->moveSamples(*pTDStretch); @@ -346,20 +345,36 @@ void SoundTouch::putSamples(const SAMPLETYPE *samples, uint nSamples) void SoundTouch::flush() { int i; - uint nOut; - SAMPLETYPE buff[128]; + int nUnprocessed; + int nOut; + SAMPLETYPE buff[64*2]; // note: allocate 2*64 to cater 64 sample frames of stereo sound - nOut = numSamples(); + // check how many samples still await processing, and scale + // that by tempo & rate to get expected output sample count + nUnprocessed = numUnprocessedSamples(); + nUnprocessed = (int)((double)nUnprocessed / (tempo * rate) + 0.5); - memset(buff, 0, 128 * sizeof(SAMPLETYPE)); + nOut = numSamples(); // ready samples currently in buffer ... + nOut += nUnprocessed; // ... and how many we expect there to be in the end + + memset(buff, 0, 64 * channels * sizeof(SAMPLETYPE)); // "Push" the last active samples out from the processing pipeline by - // feeding blank samples into the processing pipeline until new, - // processed samples appear in the output (not however, more than + // feeding blank samples into the processing pipeline until new, + // processed samples appear in the output (not however, more than // 8ksamples in any case) - for (i = 0; i < 128; i ++) + for (i = 0; i < 128; i ++) { putSamples(buff, 64); - if (numSamples() != nOut) break; // new samples have appeared in the output! + if ((int)numSamples() >= nOut) + { + // Enough new samples have appeared into the output! + // As samples come from processing with bigger chunks, now truncate it + // back to maximum "nOut" samples to improve duration accuracy + adjustAmountOfSamples(nOut); + + // finish + break; + } } // Clear working buffers @@ -379,7 +394,7 @@ BOOL SoundTouch::setSetting(int settingId, int value) // read current tdstretch routine parameters pTDStretch->getParameters(&sampleRate, &sequenceMs, &seekWindowMs, &overlapMs); - switch (settingId) + switch (settingId) { case SETTING_USE_AA_FILTER : // enables / disabless anti-alias filter @@ -425,7 +440,7 @@ int SoundTouch::getSetting(int settingId) const { int temp; - switch (settingId) + switch (settingId) { case SETTING_USE_AA_FILTER : return (uint)pRateTransposer->isAAFilterEnabled(); @@ -448,7 +463,13 @@ int SoundTouch::getSetting(int settingId) const pTDStretch->getParameters(NULL, NULL, NULL, &temp); return temp; - default : + case SETTING_NOMINAL_INPUT_SEQUENCE : + return pTDStretch->getInputSampleReq(); + + case SETTING_NOMINAL_OUTPUT_SEQUENCE : + return pTDStretch->getOutputBatchSize(); + + default : return 0; } } diff --git a/3rdparty/SoundTouch/SoundTouch.h b/3rdparty/SoundTouch/SoundTouch.h index 9d82886aa..6ae0e4a82 100644 --- a/3rdparty/SoundTouch/SoundTouch.h +++ b/3rdparty/SoundTouch/SoundTouch.h @@ -1,27 +1,27 @@ ////////////////////////////////////////////////////////////////////////////// /// -/// SoundTouch - main class for tempo/pitch/rate adjusting routines. +/// SoundTouch - main class for tempo/pitch/rate adjusting routines. /// /// Notes: -/// - Initialize the SoundTouch object instance by setting up the sound stream -/// parameters with functions 'setSampleRate' and 'setChannels', then set +/// - Initialize the SoundTouch object instance by setting up the sound stream +/// parameters with functions 'setSampleRate' and 'setChannels', then set /// desired tempo/pitch/rate settings with the corresponding functions. /// -/// - The SoundTouch class behaves like a first-in-first-out pipeline: The +/// - The SoundTouch class behaves like a first-in-first-out pipeline: The /// samples that are to be processed are fed into one of the pipe by calling -/// function 'putSamples', while the ready processed samples can be read +/// function 'putSamples', while the ready processed samples can be read /// from the other end of the pipeline with function 'receiveSamples'. -/// -/// - The SoundTouch processing classes require certain sized 'batches' of -/// samples in order to process the sound. For this reason the classes buffer -/// incoming samples until there are enough of samples available for +/// +/// - The SoundTouch processing classes require certain sized 'batches' of +/// samples in order to process the sound. For this reason the classes buffer +/// incoming samples until there are enough of samples available for /// processing, then they carry out the processing step and consequently /// make the processed samples available for outputting. -/// -/// - For the above reason, the processing routines introduce a certain +/// +/// - For the above reason, the processing routines introduce a certain /// 'latency' between the input and output, so that the samples input to -/// SoundTouch may not be immediately available in the output, and neither -/// the amount of outputtable samples may not immediately be in direct +/// SoundTouch may not be immediately available in the output, and neither +/// the amount of outputtable samples may not immediately be in direct /// relationship with the amount of previously input samples. /// /// - The tempo/pitch/rate control parameters can be altered during processing. @@ -30,8 +30,8 @@ /// required. /// /// - This class utilizes classes 'TDStretch' for tempo change (without modifying -/// pitch) and 'RateTransposer' for changing the playback rate (that is, both -/// tempo and pitch in the same ratio) of the sound. The third available control +/// pitch) and 'RateTransposer' for changing the playback rate (that is, both +/// tempo and pitch in the same ratio) of the sound. The third available control /// 'pitch' (change pitch but maintain tempo) is produced by a combination of /// combining the two other controls. /// @@ -41,10 +41,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2009-12-28 22:10:14 +0200 (Mon, 28 Dec 2009) $ +// Last changed : $Date: 2012-12-28 17:32:59 -0200 (sex, 28 dez 2012) $ // File revision : $Revision: 4 $ // -// $Id: SoundTouch.h 78 2009-12-28 20:10:14Z oparviai $ +// $Id: SoundTouch.h 163 2012-12-28 19:32:59Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -79,10 +79,10 @@ namespace soundtouch { /// Soundtouch library version string -#define SOUNDTOUCH_VERSION "1.5.0" +#define SOUNDTOUCH_VERSION "1.7.1" /// SoundTouch library version id -#define SOUNDTOUCH_VERSION_ID (10500) +#define SOUNDTOUCH_VERSION_ID (10701) // // Available setting IDs for the 'setSetting' & 'get_setting' functions: @@ -98,24 +98,49 @@ namespace soundtouch /// quality compromising) #define SETTING_USE_QUICKSEEK 2 -/// Time-stretch algorithm single processing sequence length in milliseconds. This determines -/// to how long sequences the original sound is chopped in the time-stretch algorithm. +/// Time-stretch algorithm single processing sequence length in milliseconds. This determines +/// to how long sequences the original sound is chopped in the time-stretch algorithm. /// See "STTypes.h" or README for more information. #define SETTING_SEQUENCE_MS 3 -/// Time-stretch algorithm seeking window length in milliseconds for algorithm that finds the -/// best possible overlapping location. This determines from how wide window the algorithm -/// may look for an optimal joining location when mixing the sound sequences back together. +/// Time-stretch algorithm seeking window length in milliseconds for algorithm that finds the +/// best possible overlapping location. This determines from how wide window the algorithm +/// may look for an optimal joining location when mixing the sound sequences back together. /// See "STTypes.h" or README for more information. #define SETTING_SEEKWINDOW_MS 4 -/// Time-stretch algorithm overlap length in milliseconds. When the chopped sound sequences -/// are mixed back together, to form a continuous sound stream, this parameter defines over -/// how long period the two consecutive sequences are let to overlap each other. +/// Time-stretch algorithm overlap length in milliseconds. When the chopped sound sequences +/// are mixed back together, to form a continuous sound stream, this parameter defines over +/// how long period the two consecutive sequences are let to overlap each other. /// See "STTypes.h" or README for more information. #define SETTING_OVERLAP_MS 5 +/// Call "getSetting" with this ID to query nominal average processing sequence +/// size in samples. This value tells approcimate value how many input samples +/// SoundTouch needs to gather before it does DSP processing run for the sample batch. +/// +/// Notices: +/// - This is read-only parameter, i.e. setSetting ignores this parameter +/// - Returned value is approximate average value, exact processing batch +/// size may wary from time to time +/// - This parameter value is not constant but may change depending on +/// tempo/pitch/rate/samplerate settings. +#define SETTING_NOMINAL_INPUT_SEQUENCE 6 + + +/// Call "getSetting" with this ID to query nominal average processing output +/// size in samples. This value tells approcimate value how many output samples +/// SoundTouch outputs once it does DSP processing run for a batch of input samples. +/// +/// Notices: +/// - This is read-only parameter, i.e. setSetting ignores this parameter +/// - Returned value is approximate average value, exact processing batch +/// size may wary from time to time +/// - This parameter value is not constant but may change depending on +/// tempo/pitch/rate/samplerate settings. +#define SETTING_NOMINAL_OUTPUT_SEQUENCE 7 + class SoundTouch : public FIFOProcessor { private: @@ -137,7 +162,7 @@ private: /// Flag: Has sample rate been set? BOOL bSrateSet; - /// Calculates effective rate & tempo valuescfrom 'virtualRate', 'virtualTempo' and + /// Calculates effective rate & tempo valuescfrom 'virtualRate', 'virtualTempo' and /// 'virtualPitch' parameters. void calcEffectiveRateAndTempo(); @@ -181,7 +206,7 @@ public: /// represent lower pitches, larger values higher pitch. void setPitch(float newPitch); - /// Sets pitch change in octaves compared to the original pitch + /// Sets pitch change in octaves compared to the original pitch /// (-1.00 .. +1.00) void setPitchOctaves(float newPitch); @@ -221,7 +246,7 @@ public: /// Changes a setting controlling the processing system behaviour. See the /// 'SETTING_...' defines for available setting ID's. - /// + /// /// \return 'TRUE' if the setting was succesfully changed BOOL setSetting(int settingId, ///< Setting ID number. see SETTING_... defines. int value ///< New setting value. @@ -242,7 +267,7 @@ public: /// classes 'FIFOProcessor' and 'FIFOSamplePipe') /// /// - receiveSamples() : Use this function to receive 'ready' processed samples from SoundTouch. - /// - numSamples() : Get number of 'ready' samples that can be received with + /// - numSamples() : Get number of 'ready' samples that can be received with /// function 'receiveSamples()' /// - isEmpty() : Returns nonzero if there aren't any 'ready' samples. /// - clear() : Clears all samples from ready/processing buffers. diff --git a/3rdparty/SoundTouch/TDStretch.cpp b/3rdparty/SoundTouch/TDStretch.cpp index e37a0f53b..8fa598f61 100644 --- a/3rdparty/SoundTouch/TDStretch.cpp +++ b/3rdparty/SoundTouch/TDStretch.cpp @@ -1,10 +1,10 @@ //////////////////////////////////////////////////////////////////////////////// -/// -/// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo -/// while maintaining the original pitch by using a time domain WSOLA-like +/// +/// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo +/// while maintaining the original pitch by using a time domain WSOLA-like /// method with several performance-increasing tweaks. /// -/// Note : MMX optimized functions reside in a separate, platform-specific +/// Note : MMX optimized functions reside in a separate, platform-specific /// file, e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp' /// /// Author : Copyright (c) Olli Parviainen @@ -13,10 +13,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2009-12-28 21:27:04 +0200 (Mon, 28 Dec 2009) $ +// Last changed : $Date: 2012-11-08 16:53:01 -0200 (qui, 08 nov 2012) $ // File revision : $Revision: 1.12 $ // -// $Id: TDStretch.cpp 77 2009-12-28 19:27:04Z oparviai $ +// $Id: TDStretch.cpp 160 2012-11-08 18:53:01Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -46,7 +46,6 @@ #include #include #include -#include #include "STTypes.h" #include "cpu_detect.h" @@ -91,7 +90,7 @@ TDStretch::TDStretch() : FIFOProcessor(&outputBuffer) channels = 2; pMidBuffer = NULL; - pRefMidBufferUnaligned = NULL; + pMidBufferUnaligned = NULL; overlapLength = 0; bAutoSeqSetting = TRUE; @@ -101,7 +100,7 @@ TDStretch::TDStretch() : FIFOProcessor(&outputBuffer) skipFract = 0; tempo = 1.0f; - setParameters(48000, DEFAULT_SEQUENCE_MS, DEFAULT_SEEKWINDOW_MS, DEFAULT_OVERLAP_MS); + setParameters(44100, DEFAULT_SEQUENCE_MS, DEFAULT_SEEKWINDOW_MS, DEFAULT_OVERLAP_MS); setTempo(1.0f); clear(); @@ -111,8 +110,7 @@ TDStretch::TDStretch() : FIFOProcessor(&outputBuffer) TDStretch::~TDStretch() { - delete[] pMidBuffer; - delete[] pRefMidBufferUnaligned; + delete[] pMidBufferUnaligned; } @@ -122,11 +120,11 @@ TDStretch::~TDStretch() // // 'sampleRate' = sample rate of the sound // 'sequenceMS' = one processing sequence length in milliseconds (default = 82 ms) -// 'seekwindowMS' = seeking window length for scanning the best overlapping +// 'seekwindowMS' = seeking window length for scanning the best overlapping // position (default = 28 ms) // 'overlapMS' = overlapping length (default = 12 ms) -void TDStretch::setParameters(int aSampleRate, int aSequenceMS, +void TDStretch::setParameters(int aSampleRate, int aSequenceMS, int aSeekWindowMS, int aOverlapMS) { // accept only positive parameter values - if zero or negative, use old values instead @@ -137,19 +135,19 @@ void TDStretch::setParameters(int aSampleRate, int aSequenceMS, { this->sequenceMs = aSequenceMS; bAutoSeqSetting = FALSE; - } + } else if (aSequenceMS == 0) { // if zero, use automatic setting bAutoSeqSetting = TRUE; } - if (aSeekWindowMS > 0) + if (aSeekWindowMS > 0) { this->seekWindowMs = aSeekWindowMS; bAutoSeekSetting = FALSE; - } - else if (aSeekWindowMS == 0) + } + else if (aSeekWindowMS == 0) { // if zero, use automatic setting bAutoSeekSetting = TRUE; @@ -196,12 +194,17 @@ void TDStretch::getParameters(int *pSampleRate, int *pSequenceMs, int *pSeekWind // Overlaps samples in 'midBuffer' with the samples in 'pInput' void TDStretch::overlapMono(SAMPLETYPE *pOutput, const SAMPLETYPE *pInput) const { - int i, itemp; + int i; + SAMPLETYPE m1, m2; - for (i = 0; i < overlapLength ; i ++) + m1 = (SAMPLETYPE)0; + m2 = (SAMPLETYPE)overlapLength; + + for (i = 0; i < overlapLength ; i ++) { - itemp = overlapLength - i; - pOutput[i] = (pInput[i] * i + pMidBuffer[i] * itemp ) / overlapLength; // >> overlapDividerBits; + pOutput[i] = (pInput[i] * m1 + pMidBuffer[i] * m2 ) / overlapLength; + m1 += 1; + m2 -= 1; } } @@ -247,40 +250,22 @@ BOOL TDStretch::isQuickSeekEnabled() const // Seeks for the optimal overlap-mixing position. int TDStretch::seekBestOverlapPosition(const SAMPLETYPE *refPos) { - if (channels == 2) + if (bQuickSeek) { - // stereo sound - if (bQuickSeek) - { - return seekBestOverlapPositionStereoQuick(refPos); - } - else - { - return seekBestOverlapPositionStereo(refPos); - } - } - else + return seekBestOverlapPositionQuick(refPos); + } + else { - // mono sound - if (bQuickSeek) - { - return seekBestOverlapPositionMonoQuick(refPos); - } - else - { - return seekBestOverlapPositionMono(refPos); - } + return seekBestOverlapPositionFull(refPos); } } - - // Overlaps samples in 'midBuffer' with the samples in 'pInputBuffer' at position // of 'ovlPos'. inline void TDStretch::overlap(SAMPLETYPE *pOutput, const SAMPLETYPE *pInput, uint ovlPos) const { - if (channels == 2) + if (channels == 2) { // stereo sound overlapStereo(pOutput, pInput + 2 * ovlPos); @@ -292,38 +277,34 @@ inline void TDStretch::overlap(SAMPLETYPE *pOutput, const SAMPLETYPE *pInput, ui - // Seeks for the optimal overlap-mixing position. The 'stereo' version of the // routine // // The best position is determined as the position where the two overlapped // sample sequences are 'most alike', in terms of the highest cross-correlation // value over the overlapping period -int TDStretch::seekBestOverlapPositionStereo(const SAMPLETYPE *refPos) +int TDStretch::seekBestOverlapPositionFull(const SAMPLETYPE *refPos) { int bestOffs; double bestCorr, corr; int i; - // Slopes the amplitudes of the 'midBuffer' samples - precalcCorrReferenceStereo(); - bestCorr = FLT_MIN; bestOffs = 0; // Scans for the best correlation value by testing each possible position // over the permitted range. - for (i = 0; i < seekLength; i ++) + for (i = 0; i < seekLength; i ++) { // Calculates correlation value for the mixing position corresponding // to 'i' - corr = (double)calcCrossCorrStereo(refPos + 2 * i, pRefMidBuffer); + corr = calcCrossCorr(refPos + channels * i, pMidBuffer); // heuristic rule to slightly favour values close to mid of the range double tmp = (double)(2 * i - seekLength) / (double)seekLength; corr = ((corr + 0.1) * (1.0 - 0.25 * tmp * tmp)); // Checks for the highest correlation value - if (corr > bestCorr) + if (corr > bestCorr) { bestCorr = corr; bestOffs = i; @@ -342,16 +323,13 @@ int TDStretch::seekBestOverlapPositionStereo(const SAMPLETYPE *refPos) // The best position is determined as the position where the two overlapped // sample sequences are 'most alike', in terms of the highest cross-correlation // value over the overlapping period -int TDStretch::seekBestOverlapPositionStereoQuick(const SAMPLETYPE *refPos) +int TDStretch::seekBestOverlapPositionQuick(const SAMPLETYPE *refPos) { int j; int bestOffs; double bestCorr, corr; int scanCount, corrOffset, tempOffset; - // Slopes the amplitude of the 'midBuffer' samples - precalcCorrReferenceStereo(); - bestCorr = FLT_MIN; bestOffs = _scanOffsets[0][0]; corrOffset = 0; @@ -360,26 +338,26 @@ int TDStretch::seekBestOverlapPositionStereoQuick(const SAMPLETYPE *refPos) // Scans for the best correlation value using four-pass hierarchical search. // // The look-up table 'scans' has hierarchical position adjusting steps. - // In first pass the routine searhes for the highest correlation with + // In first pass the routine searhes for the highest correlation with // relatively coarse steps, then rescans the neighbourhood of the highest // correlation with better resolution and so on. - for (scanCount = 0;scanCount < 4; scanCount ++) + for (scanCount = 0;scanCount < 4; scanCount ++) { j = 0; - while (_scanOffsets[scanCount][j]) + while (_scanOffsets[scanCount][j]) { tempOffset = corrOffset + _scanOffsets[scanCount][j]; if (tempOffset >= seekLength) break; // Calculates correlation value for the mixing position corresponding // to 'tempOffset' - corr = (double)calcCrossCorrStereo(refPos + 2 * tempOffset, pRefMidBuffer); + corr = (double)calcCrossCorr(refPos + channels * tempOffset, pMidBuffer); // heuristic rule to slightly favour values close to mid of the range double tmp = (double)(2 * tempOffset - seekLength) / seekLength; corr = ((corr + 0.1) * (1.0 - 0.25 * tmp * tmp)); // Checks for the highest correlation value - if (corr > bestCorr) + if (corr > bestCorr) { bestCorr = corr; bestOffs = tempOffset; @@ -396,112 +374,7 @@ int TDStretch::seekBestOverlapPositionStereoQuick(const SAMPLETYPE *refPos) -// Seeks for the optimal overlap-mixing position. The 'mono' version of the -// routine -// -// The best position is determined as the position where the two overlapped -// sample sequences are 'most alike', in terms of the highest cross-correlation -// value over the overlapping period -int TDStretch::seekBestOverlapPositionMono(const SAMPLETYPE *refPos) -{ - int bestOffs; - double bestCorr, corr; - int tempOffset; - const SAMPLETYPE *compare; - - // Slopes the amplitude of the 'midBuffer' samples - precalcCorrReferenceMono(); - - bestCorr = FLT_MIN; - bestOffs = 0; - - // Scans for the best correlation value by testing each possible position - // over the permitted range. - for (tempOffset = 0; tempOffset < seekLength; tempOffset ++) - { - compare = refPos + tempOffset; - - // Calculates correlation value for the mixing position corresponding - // to 'tempOffset' - corr = (double)calcCrossCorrMono(pRefMidBuffer, compare); - // heuristic rule to slightly favour values close to mid of the range - double tmp = (double)(2 * tempOffset - seekLength) / seekLength; - corr = ((corr + 0.1) * (1.0 - 0.25 * tmp * tmp)); - - // Checks for the highest correlation value - if (corr > bestCorr) - { - bestCorr = corr; - bestOffs = tempOffset; - } - } - // clear cross correlation routine state if necessary (is so e.g. in MMX routines). - clearCrossCorrState(); - - return bestOffs; -} - - -// Seeks for the optimal overlap-mixing position. The 'mono' version of the -// routine -// -// The best position is determined as the position where the two overlapped -// sample sequences are 'most alike', in terms of the highest cross-correlation -// value over the overlapping period -int TDStretch::seekBestOverlapPositionMonoQuick(const SAMPLETYPE *refPos) -{ - int j; - int bestOffs; - double bestCorr, corr; - int scanCount, corrOffset, tempOffset; - - // Slopes the amplitude of the 'midBuffer' samples - precalcCorrReferenceMono(); - - bestCorr = FLT_MIN; - bestOffs = _scanOffsets[0][0]; - corrOffset = 0; - tempOffset = 0; - - // Scans for the best correlation value using four-pass hierarchical search. - // - // The look-up table 'scans' has hierarchical position adjusting steps. - // In first pass the routine searhes for the highest correlation with - // relatively coarse steps, then rescans the neighbourhood of the highest - // correlation with better resolution and so on. - for (scanCount = 0;scanCount < 4; scanCount ++) - { - j = 0; - while (_scanOffsets[scanCount][j]) - { - tempOffset = corrOffset + _scanOffsets[scanCount][j]; - if (tempOffset >= seekLength) break; - - // Calculates correlation value for the mixing position corresponding - // to 'tempOffset' - corr = (double)calcCrossCorrMono(refPos + tempOffset, pRefMidBuffer); - // heuristic rule to slightly favour values close to mid of the range - double tmp = (double)(2 * tempOffset - seekLength) / seekLength; - corr = ((corr + 0.1) * (1.0 - 0.25 * tmp * tmp)); - - // Checks for the highest correlation value - if (corr > bestCorr) - { - bestCorr = corr; - bestOffs = tempOffset; - } - j ++; - } - corrOffset = bestOffs; - } - // clear cross correlation routine state if necessary (is so e.g. in MMX routines). - clearCrossCorrState(); - - return bestOffs; -} - - -/// clear cross correlation routine state if necessary +/// clear cross correlation routine state if necessary void TDStretch::clearCrossCorrState() { // default implementation is empty. @@ -531,7 +404,7 @@ void TDStretch::calcSeqParameters() #define CHECK_LIMITS(x, mi, ma) (((x) < (mi)) ? (mi) : (((x) > (ma)) ? (ma) : (x))) double seq, seek; - + if (bAutoSeqSetting) { seq = AUTOSEQ_C + AUTOSEQ_K * tempo; @@ -548,7 +421,7 @@ void TDStretch::calcSeqParameters() // Update seek window lengths seekWindowLength = (sampleRate * sequenceMs) / 1000; - if (seekWindowLength < 2 * overlapLength) + if (seekWindowLength < 2 * overlapLength) { seekWindowLength = 2 * overlapLength; } @@ -557,7 +430,7 @@ void TDStretch::calcSeqParameters() -// Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower +// Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower // tempo, larger faster tempo. void TDStretch::setTempo(float newTempo) { @@ -568,11 +441,11 @@ void TDStretch::setTempo(float newTempo) // Calculate new sequence duration calcSeqParameters(); - // Calculate ideal skip length (according to tempo value) + // Calculate ideal skip length (according to tempo value) nominalSkip = tempo * (seekWindowLength - overlapLength); intskip = (int)(nominalSkip + 0.5f); - // Calculate how many samples are needed in the 'inputBuffer' to + // Calculate how many samples are needed in the 'inputBuffer' to // process another batch of samples //sampleReq = max(intskip + overlapLength, seekWindowLength) + seekLength / 2; sampleReq = max(intskip + overlapLength, seekWindowLength) + seekLength; @@ -600,18 +473,18 @@ void TDStretch::processNominalTempo() { assert(tempo == 1.0f); - if (bMidBufferDirty) + if (bMidBufferDirty) { // If there are samples in pMidBuffer waiting for overlapping, - // do a single sliding overlapping with them in order to prevent a + // do a single sliding overlapping with them in order to prevent a // clicking distortion in the output sound - if (inputBuffer.numSamples() < overlapLength) + if (inputBuffer.numSamples() < overlapLength) { // wait until we've got overlapLength input samples return; } - // Mix the samples in the beginning of 'inputBuffer' with the - // samples in 'midBuffer' using sliding overlapping + // Mix the samples in the beginning of 'inputBuffer' with the + // samples in 'midBuffer' using sliding overlapping overlap(outputBuffer.ptrEnd(overlapLength), inputBuffer.ptrBegin(), 0); outputBuffer.putSamples(overlapLength); inputBuffer.receiveSamples(overlapLength); @@ -636,7 +509,7 @@ void TDStretch::processSamples() /* Removed this small optimization - can introduce a click to sound when tempo setting crosses the nominal value - if (tempo == 1.0f) + if (tempo == 1.0f) { // tempo not changed from the original, so bypass the processing processNominalTempo(); @@ -646,14 +519,13 @@ void TDStretch::processSamples() // Process samples as long as there are enough samples in 'inputBuffer' // to form a processing frame. -// while ((int)inputBuffer.numSamples() >= sampleReq - (outDebt / 4)) - while ((int)inputBuffer.numSamples() >= sampleReq) + while ((int)inputBuffer.numSamples() >= sampleReq) { // If tempo differs from the normal ('SCALE'), scan for the best overlapping // position offset = seekBestOverlapPosition(inputBuffer.ptrBegin()); - // Mix the samples in the 'inputBuffer' at position of 'offset' with the + // Mix the samples in the 'inputBuffer' at position of 'offset' with the // samples in 'midBuffer' using sliding overlapping // ... first partially overlap with the end of the previous sequence // (that's in 'midBuffer') @@ -661,16 +533,8 @@ void TDStretch::processSamples() outputBuffer.putSamples((uint)overlapLength); // ... then copy sequence samples from 'inputBuffer' to output: - temp = (seekLength / 2 - offset); - - // compensate cumulated output length diff vs. ideal output -// temp -= outDebt / 4; - - // update ideal vs. true output difference -// outDebt += temp; // length of sequence -// temp += (seekWindowLength - 2 * overlapLength); temp = (seekWindowLength - 2 * overlapLength); // crosscheck that we don't have buffer overflow... @@ -681,11 +545,11 @@ void TDStretch::processSamples() outputBuffer.putSamples(inputBuffer.ptrBegin() + channels * (offset + overlapLength), (uint)temp); - // Copies the end of the current sequence from 'inputBuffer' to - // 'midBuffer' for being mixed with the beginning of the next + // Copies the end of the current sequence from 'inputBuffer' to + // 'midBuffer' for being mixed with the beginning of the next // processing sequence and so on assert((offset + temp + overlapLength * 2) <= (int)inputBuffer.numSamples()); - memcpy(pMidBuffer, inputBuffer.ptrBegin() + channels * (offset + temp + overlapLength), + memcpy(pMidBuffer, inputBuffer.ptrBegin() + channels * (offset + temp + overlapLength), channels * sizeof(SAMPLETYPE) * overlapLength); // Remove the processed samples from the input buffer. Update @@ -722,26 +586,24 @@ void TDStretch::acceptNewOverlapLength(int newOverlapLength) if (overlapLength > prevOvl) { - delete[] pMidBuffer; - delete[] pRefMidBufferUnaligned; + delete[] pMidBufferUnaligned; + + pMidBufferUnaligned = new SAMPLETYPE[overlapLength * 2 + 16 / sizeof(SAMPLETYPE)]; + // ensure that 'pMidBuffer' is aligned to 16 byte boundary for efficiency + pMidBuffer = (SAMPLETYPE *)SOUNDTOUCH_ALIGN_POINTER_16(pMidBufferUnaligned); - pMidBuffer = new SAMPLETYPE[overlapLength * 2]; clearMidBuffer(); - - pRefMidBufferUnaligned = new SAMPLETYPE[2 * overlapLength + 16 / sizeof(SAMPLETYPE)]; - // ensure that 'pRefMidBuffer' is aligned to 16 byte boundary for efficiency - pRefMidBuffer = (SAMPLETYPE *)((((ulong)pRefMidBufferUnaligned) + 15) & (ulong)-16); } } -// Operator 'new' is overloaded so that it automatically creates a suitable instance +// Operator 'new' is overloaded so that it automatically creates a suitable instance // depending on if we've a MMX/SSE/etc-capable CPU available or not. void * TDStretch::operator new(size_t s) { // Notice! don't use "new TDStretch" directly, use "newInstance" to create a new instance instead! - throw std::runtime_error("Error in TDStretch::new: Don't use 'new TDStretch' directly, use 'newInstance' member instead!"); - return NULL; + ST_THROW_RT_ERROR("Error in TDStretch::new: Don't use 'new TDStretch' directly, use 'newInstance' member instead!"); + return newInstance(); } @@ -751,36 +613,26 @@ TDStretch * TDStretch::newInstance() uExtensions = detectCPUextensions(); - // Check if MMX/SSE/3DNow! instruction set extensions supported by CPU + // Check if MMX/SSE instruction set extensions supported by CPU -#ifdef ALLOW_MMX +#ifdef SOUNDTOUCH_ALLOW_MMX // MMX routines available only with integer sample types if (uExtensions & SUPPORT_MMX) { return ::new TDStretchMMX; } else -#endif // ALLOW_MMX +#endif // SOUNDTOUCH_ALLOW_MMX -#ifdef ALLOW_SSE +#ifdef SOUNDTOUCH_ALLOW_SSE if (uExtensions & SUPPORT_SSE) { // SSE support return ::new TDStretchSSE; } else -#endif // ALLOW_SSE - - -#ifdef ALLOW_3DNOW - if (uExtensions & SUPPORT_3DNOW) - { - // 3DNow! support - return ::new TDStretch3DNow; - } - else -#endif // ALLOW_3DNOW +#endif // SOUNDTOUCH_ALLOW_SSE { // ISA optimizations not supported, use plain C version @@ -795,46 +647,9 @@ TDStretch * TDStretch::newInstance() // ////////////////////////////////////////////////////////////////////////////// -#ifdef INTEGER_SAMPLES +#ifdef SOUNDTOUCH_INTEGER_SAMPLES -// Slopes the amplitude of the 'midBuffer' samples so that cross correlation -// is faster to calculate -void TDStretch::precalcCorrReferenceStereo() -{ - int i, cnt2; - int temp, temp2; - - for (i=0 ; i < (int)overlapLength ;i ++) - { - temp = i * (overlapLength - i); - cnt2 = i * 2; - - temp2 = (pMidBuffer[cnt2] * temp) / slopingDivider; - pRefMidBuffer[cnt2] = (short)(temp2); - temp2 = (pMidBuffer[cnt2 + 1] * temp) / slopingDivider; - pRefMidBuffer[cnt2 + 1] = (short)(temp2); - } -} - - -// Slopes the amplitude of the 'midBuffer' samples so that cross correlation -// is faster to calculate -void TDStretch::precalcCorrReferenceMono() -{ - int i; - long temp; - long temp2; - - for (i=0 ; i < (int)overlapLength ;i ++) - { - temp = i * (overlapLength - i); - temp2 = (pMidBuffer[i] * temp) / slopingDivider; - pRefMidBuffer[i] = (short)temp2; - } -} - - -// Overlaps samples in 'midBuffer' with the samples in 'input'. The 'Stereo' +// Overlaps samples in 'midBuffer' with the samples in 'input'. The 'Stereo' // version of the routine. void TDStretch::overlapStereo(short *poutput, const short *input) const { @@ -842,7 +657,7 @@ void TDStretch::overlapStereo(short *poutput, const short *input) const short temp; int cnt2; - for (i = 0; i < overlapLength ; i ++) + for (i = 0; i < overlapLength ; i ++) { temp = (short)(overlapLength - i); cnt2 = 2 * i; @@ -868,8 +683,8 @@ void TDStretch::calculateOverlapLength(int aoverlapMs) assert(aoverlapMs >= 0); // calculate overlap length so that it's power of 2 - thus it's easy to do - // integer division by right-shifting. Term "-1" at end is to account for - // the extra most significatnt bit left unused in result by signed multiplication + // integer division by right-shifting. Term "-1" at end is to account for + // the extra most significatnt bit left unused in result by signed multiplication overlapDividerBits = _getClosest2Power((sampleRate * aoverlapMs) / 1000.0) - 1; if (overlapDividerBits > 9) overlapDividerBits = 9; if (overlapDividerBits < 3) overlapDividerBits = 3; @@ -877,113 +692,70 @@ void TDStretch::calculateOverlapLength(int aoverlapMs) acceptNewOverlapLength(newOvl); - // calculate sloping divider so that crosscorrelation operation won't - // overflow 32-bit register. Max. sum of the crosscorrelation sum without + // calculate sloping divider so that crosscorrelation operation won't + // overflow 32-bit register. Max. sum of the crosscorrelation sum without // divider would be 2^30*(N^3-N)/3, where N = overlap length slopingDivider = (newOvl * newOvl - 1) / 3; } -long TDStretch::calcCrossCorrMono(const short *mixingPos, const short *compare) const +double TDStretch::calcCrossCorr(const short *mixingPos, const short *compare) const { long corr; long norm; int i; corr = norm = 0; - for (i = 1; i < overlapLength; i ++) + // Same routine for stereo and mono. For stereo, unroll loop for better + // efficiency and gives slightly better resolution against rounding. + // For mono it same routine, just unrolls loop by factor of 4 + for (i = 0; i < channels * overlapLength; i += 4) { - corr += (mixingPos[i] * compare[i]) >> overlapDividerBits; - norm += (mixingPos[i] * mixingPos[i]) >> overlapDividerBits; + corr += (mixingPos[i] * compare[i] + + mixingPos[i + 1] * compare[i + 1] + + mixingPos[i + 2] * compare[i + 2] + + mixingPos[i + 3] * compare[i + 3]) >> overlapDividerBits; + norm += (mixingPos[i] * mixingPos[i] + + mixingPos[i + 1] * mixingPos[i + 1] + + mixingPos[i + 2] * mixingPos[i + 2] + + mixingPos[i + 3] * mixingPos[i + 3]) >> overlapDividerBits; } - // Normalize result by dividing by sqrt(norm) - this step is easiest + // Normalize result by dividing by sqrt(norm) - this step is easiest // done using floating point operation if (norm == 0) norm = 1; // to avoid div by zero - return (long)((double)corr * SHRT_MAX / sqrt((double)norm)); + return (double)corr / sqrt((double)norm); } - -long TDStretch::calcCrossCorrStereo(const short *mixingPos, const short *compare) const -{ - long corr; - long norm; - int i; - - corr = norm = 0; - for (i = 2; i < 2 * overlapLength; i += 2) - { - corr += (mixingPos[i] * compare[i] + - mixingPos[i + 1] * compare[i + 1]) >> overlapDividerBits; - norm += (mixingPos[i] * mixingPos[i] + mixingPos[i + 1] * mixingPos[i + 1]) >> overlapDividerBits; - } - - // Normalize result by dividing by sqrt(norm) - this step is easiest - // done using floating point operation - if (norm == 0) norm = 1; // to avoid div by zero - return (long)((double)corr * SHRT_MAX / sqrt((double)norm)); -} - -#endif // INTEGER_SAMPLES +#endif // SOUNDTOUCH_INTEGER_SAMPLES ////////////////////////////////////////////////////////////////////////////// // // Floating point arithmetics specific algorithm implementations. // -#ifdef FLOAT_SAMPLES - - -// Slopes the amplitude of the 'midBuffer' samples so that cross correlation -// is faster to calculate -void TDStretch::precalcCorrReferenceStereo() -{ - int i, cnt2; - float temp; - - for (i=0 ; i < (int)overlapLength ;i ++) - { - temp = (float)i * (float)(overlapLength - i); - cnt2 = i * 2; - pRefMidBuffer[cnt2] = (float)(pMidBuffer[cnt2] * temp); - pRefMidBuffer[cnt2 + 1] = (float)(pMidBuffer[cnt2 + 1] * temp); - } -} - - -// Slopes the amplitude of the 'midBuffer' samples so that cross correlation -// is faster to calculate -void TDStretch::precalcCorrReferenceMono() -{ - int i; - float temp; - - for (i=0 ; i < (int)overlapLength ;i ++) - { - temp = (float)i * (float)(overlapLength - i); - pRefMidBuffer[i] = (float)(pMidBuffer[i] * temp); - } -} - +#ifdef SOUNDTOUCH_FLOAT_SAMPLES // Overlaps samples in 'midBuffer' with the samples in 'pInput' void TDStretch::overlapStereo(float *pOutput, const float *pInput) const { int i; - int cnt2; - float fTemp; float fScale; - float fi; + float f1; + float f2; fScale = 1.0f / (float)overlapLength; - for (i = 0; i < (int)overlapLength ; i ++) + f1 = 0; + f2 = 1.0f; + + for (i = 0; i < 2 * (int)overlapLength ; i += 2) { - fTemp = (float)(overlapLength - i) * fScale; - fi = (float)i * fScale; - cnt2 = 2 * i; - pOutput[cnt2 + 0] = pInput[cnt2 + 0] * fi + pMidBuffer[cnt2 + 0] * fTemp; - pOutput[cnt2 + 1] = pInput[cnt2 + 1] * fi + pMidBuffer[cnt2 + 1] * fTemp; + pOutput[i + 0] = pInput[i + 0] * f1 + pMidBuffer[i + 0] * f2; + pOutput[i + 1] = pInput[i + 1] * f1 + pMidBuffer[i + 1] * f2; + + f1 += fScale; + f2 -= fScale; } } @@ -1004,42 +776,33 @@ void TDStretch::calculateOverlapLength(int overlapInMsec) } - -double TDStretch::calcCrossCorrMono(const float *mixingPos, const float *compare) const +double TDStretch::calcCrossCorr(const float *mixingPos, const float *compare) const { double corr; double norm; int i; corr = norm = 0; - for (i = 1; i < overlapLength; i ++) - { - corr += mixingPos[i] * compare[i]; - norm += mixingPos[i] * mixingPos[i]; - } - - if (norm < 1e-9) norm = 1.0; // to avoid div by zero - return corr / sqrt(norm); -} - - -double TDStretch::calcCrossCorrStereo(const float *mixingPos, const float *compare) const -{ - double corr; - double norm; - int i; - - corr = norm = 0; - for (i = 2; i < 2 * overlapLength; i += 2) + // Same routine for stereo and mono. For Stereo, unroll by factor of 2. + // For mono it's same routine yet unrollsd by factor of 4. + for (i = 0; i < channels * overlapLength; i += 4) { corr += mixingPos[i] * compare[i] + mixingPos[i + 1] * compare[i + 1]; - norm += mixingPos[i] * mixingPos[i] + + + norm += mixingPos[i] * mixingPos[i] + mixingPos[i + 1] * mixingPos[i + 1]; + + // unroll the loop for better CPU efficiency: + corr += mixingPos[i + 2] * compare[i + 2] + + mixingPos[i + 3] * compare[i + 3]; + + norm += mixingPos[i + 2] * mixingPos[i + 2] + + mixingPos[i + 3] * mixingPos[i + 3]; } if (norm < 1e-9) norm = 1.0; // to avoid div by zero return corr / sqrt(norm); } -#endif // FLOAT_SAMPLES +#endif // SOUNDTOUCH_FLOAT_SAMPLES diff --git a/3rdparty/SoundTouch/TDStretch.h b/3rdparty/SoundTouch/TDStretch.h index 1962d818a..686125101 100644 --- a/3rdparty/SoundTouch/TDStretch.h +++ b/3rdparty/SoundTouch/TDStretch.h @@ -1,10 +1,10 @@ //////////////////////////////////////////////////////////////////////////////// -/// -/// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo -/// while maintaining the original pitch by using a time domain WSOLA-like method +/// +/// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo +/// while maintaining the original pitch by using a time domain WSOLA-like method /// with several performance-increasing tweaks. /// -/// Note : MMX/SSE optimized functions reside in separate, platform-specific files +/// Note : MMX/SSE optimized functions reside in separate, platform-specific files /// 'mmx_optimized.cpp' and 'sse_optimized.cpp' /// /// Author : Copyright (c) Olli Parviainen @@ -13,10 +13,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2009-05-17 14:35:13 +0300 (Sun, 17 May 2009) $ +// Last changed : $Date: 2012-04-01 16:49:30 -0300 (dom, 01 abr 2012) $ // File revision : $Revision: 4 $ // -// $Id: TDStretch.h 71 2009-05-17 11:35:13Z oparviai $ +// $Id: TDStretch.h 137 2012-04-01 19:49:30Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -53,14 +53,14 @@ namespace soundtouch { /// Default values for sound processing parameters: -/// Notice that the default parameters are tuned for contemporary popular music +/// Notice that the default parameters are tuned for contemporary popular music /// processing. For speech processing applications these parameters suit better: /// #define DEFAULT_SEQUENCE_MS 40 /// #define DEFAULT_SEEKWINDOW_MS 15 /// #define DEFAULT_OVERLAP_MS 8 /// -/// Default length of a single processing sequence, in milliseconds. This determines to how +/// Default length of a single processing sequence, in milliseconds. This determines to how /// long sequences the original sound is chopped in the time-stretch algorithm. /// /// The larger this value is, the lesser sequences are used in processing. In principle @@ -75,15 +75,15 @@ namespace soundtouch /// according to tempo setting (recommended) #define USE_AUTO_SEQUENCE_LEN 0 -/// Seeking window default length in milliseconds for algorithm that finds the best possible -/// overlapping location. This determines from how wide window the algorithm may look for an -/// optimal joining location when mixing the sound sequences back together. +/// Seeking window default length in milliseconds for algorithm that finds the best possible +/// overlapping location. This determines from how wide window the algorithm may look for an +/// optimal joining location when mixing the sound sequences back together. /// /// The bigger this window setting is, the higher the possibility to find a better mixing /// position will become, but at the same time large values may cause a "drifting" artifact /// because consequent sequences will be taken at more uneven intervals. /// -/// If there's a disturbing artifact that sounds as if a constant frequency was drifting +/// If there's a disturbing artifact that sounds as if a constant frequency was drifting /// around, try reducing this setting. /// /// Increasing this value increases computational burden & vice versa. @@ -94,11 +94,11 @@ namespace soundtouch /// according to tempo setting (recommended) #define USE_AUTO_SEEKWINDOW_LEN 0 -/// Overlap length in milliseconds. When the chopped sound sequences are mixed back together, -/// to form a continuous sound stream, this parameter defines over how long period the two -/// consecutive sequences are let to overlap each other. +/// Overlap length in milliseconds. When the chopped sound sequences are mixed back together, +/// to form a continuous sound stream, this parameter defines over how long period the two +/// consecutive sequences are let to overlap each other. /// -/// This shouldn't be that critical parameter. If you reduce the DEFAULT_SEQUENCE_MS setting +/// This shouldn't be that critical parameter. If you reduce the DEFAULT_SEQUENCE_MS setting /// by a large amount, you might wish to try a smaller value on this. /// /// Increasing this value increases computational burden & vice versa. @@ -115,8 +115,7 @@ protected: float tempo; SAMPLETYPE *pMidBuffer; - SAMPLETYPE *pRefMidBuffer; - SAMPLETYPE *pRefMidBufferUnaligned; + SAMPLETYPE *pMidBufferUnaligned; int overlapLength; int seekLength; int seekWindowLength; @@ -127,8 +126,6 @@ protected: FIFOSampleBuffer outputBuffer; FIFOSampleBuffer inputBuffer; BOOL bQuickSeek; -// int outDebt; -// BOOL bMidBufferDirty; int sampleRate; int sequenceMs; @@ -142,13 +139,10 @@ protected: virtual void clearCrossCorrState(); void calculateOverlapLength(int overlapMs); - virtual LONG_SAMPLETYPE calcCrossCorrStereo(const SAMPLETYPE *mixingPos, const SAMPLETYPE *compare) const; - virtual LONG_SAMPLETYPE calcCrossCorrMono(const SAMPLETYPE *mixingPos, const SAMPLETYPE *compare) const; + virtual double calcCrossCorr(const SAMPLETYPE *mixingPos, const SAMPLETYPE *compare) const; - virtual int seekBestOverlapPositionStereo(const SAMPLETYPE *refPos); - virtual int seekBestOverlapPositionStereoQuick(const SAMPLETYPE *refPos); - virtual int seekBestOverlapPositionMono(const SAMPLETYPE *refPos); - virtual int seekBestOverlapPositionMonoQuick(const SAMPLETYPE *refPos); + virtual int seekBestOverlapPositionFull(const SAMPLETYPE *refPos); + virtual int seekBestOverlapPositionQuick(const SAMPLETYPE *refPos); int seekBestOverlapPosition(const SAMPLETYPE *refPos); virtual void overlapStereo(SAMPLETYPE *output, const SAMPLETYPE *input) const; @@ -157,9 +151,6 @@ protected: void clearMidBuffer(); void overlap(SAMPLETYPE *output, const SAMPLETYPE *input, uint ovlPos) const; - void precalcCorrReferenceMono(); - void precalcCorrReferenceStereo(); - void calcSeqParameters(); /// Changes the tempo of the given sound samples. @@ -167,27 +158,27 @@ protected: /// The maximum amount of samples that can be returned at a time is set by /// the 'set_returnBuffer_size' function. void processSamples(); - + public: TDStretch(); virtual ~TDStretch(); - /// Operator 'new' is overloaded so that it automatically creates a suitable instance + /// Operator 'new' is overloaded so that it automatically creates a suitable instance /// depending on if we've a MMX/SSE/etc-capable CPU available or not. static void *operator new(size_t s); - /// Use this function instead of "new" operator to create a new instance of this class. + /// Use this function instead of "new" operator to create a new instance of this class. /// This function automatically chooses a correct feature set depending on if the CPU /// supports MMX/SSE/etc extensions. static TDStretch *newInstance(); - + /// Returns the output buffer object FIFOSamplePipe *getOutput() { return &outputBuffer; }; /// Returns the input buffer object FIFOSamplePipe *getInput() { return &inputBuffer; }; - /// Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower + /// Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower /// tempo, larger faster tempo. void setTempo(float newTempo); @@ -200,7 +191,7 @@ public: /// Sets the number of channels, 1 = mono, 2 = stereo void setChannels(int numChannels); - /// Enables/disables the quick position seeking algorithm. Zero to disable, + /// Enables/disables the quick position seeking algorithm. Zero to disable, /// nonzero to enable void enableQuickSeek(BOOL enable); @@ -212,7 +203,7 @@ public: // /// 'sampleRate' = sample rate of the sound /// 'sequenceMS' = one processing sequence length in milliseconds - /// 'seekwindowMS' = seeking window length for scanning the best overlapping + /// 'seekwindowMS' = seeking window length for scanning the best overlapping /// position /// 'overlapMS' = overlapping length void setParameters(int sampleRate, ///< Samplerate of sound being processed (Hz) @@ -233,43 +224,45 @@ public: uint numSamples ///< Number of samples in 'samples' so that one sample ///< contains both channels if stereo ); + + /// return nominal input sample requirement for triggering a processing batch + int getInputSampleReq() const + { + return (int)(nominalSkip + 0.5); + } + + /// return nominal output sample amount when running a processing batch + int getOutputBatchSize() const + { + return seekWindowLength - overlapLength; + } }; // Implementation-specific class declarations: -#ifdef ALLOW_MMX +#ifdef SOUNDTOUCH_ALLOW_MMX /// Class that implements MMX optimized routines for 16bit integer samples type. class TDStretchMMX : public TDStretch { protected: - long calcCrossCorrStereo(const short *mixingPos, const short *compare) const; + double calcCrossCorr(const short *mixingPos, const short *compare) const; virtual void overlapStereo(short *output, const short *input) const; virtual void clearCrossCorrState(); }; -#endif /// ALLOW_MMX +#endif /// SOUNDTOUCH_ALLOW_MMX -#ifdef ALLOW_3DNOW - /// Class that implements 3DNow! optimized routines for floating point samples type. - class TDStretch3DNow : public TDStretch - { - protected: - double calcCrossCorrStereo(const float *mixingPos, const float *compare) const; - }; -#endif /// ALLOW_3DNOW - - -#ifdef ALLOW_SSE +#ifdef SOUNDTOUCH_ALLOW_SSE /// Class that implements SSE optimized routines for floating point samples type. class TDStretchSSE : public TDStretch { protected: - double calcCrossCorrStereo(const float *mixingPos, const float *compare) const; + double calcCrossCorr(const float *mixingPos, const float *compare) const; }; -#endif /// ALLOW_SSE +#endif /// SOUNDTOUCH_ALLOW_SSE } #endif /// TDStretch_H diff --git a/3rdparty/SoundTouch/cpu_detect.h b/3rdparty/SoundTouch/cpu_detect.h index 33c5026ce..809f841b3 100644 --- a/3rdparty/SoundTouch/cpu_detect.h +++ b/3rdparty/SoundTouch/cpu_detect.h @@ -2,8 +2,8 @@ /// /// A header file for detecting the Intel MMX instructions set extension. /// -/// Please see 'mmx_win.cpp', 'mmx_cpp.cpp' and 'mmx_non_x86.cpp' for the -/// routine implementations for x86 Windows, x86 gnu version and non-x86 +/// Please see 'mmx_win.cpp', 'mmx_cpp.cpp' and 'mmx_non_x86.cpp' for the +/// routine implementations for x86 Windows, x86 gnu version and non-x86 /// platforms, respectively. /// /// Author : Copyright (c) Olli Parviainen @@ -12,7 +12,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2008-02-10 18:26:55 +0200 (Sun, 10 Feb 2008) $ +// Last changed : $Date: 2008-02-10 14:26:55 -0200 (dom, 10 fev 2008) $ // File revision : $Revision: 4 $ // // $Id: cpu_detect.h 11 2008-02-10 16:26:55Z oparviai $ diff --git a/3rdparty/SoundTouch/cpu_detect_x86.cpp b/3rdparty/SoundTouch/cpu_detect_x86.cpp new file mode 100644 index 000000000..4b09dba20 --- /dev/null +++ b/3rdparty/SoundTouch/cpu_detect_x86.cpp @@ -0,0 +1,137 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// Generic version of the x86 CPU extension detection routine. +/// +/// This file is for GNU & other non-Windows compilers, see 'cpu_detect_x86_win.cpp' +/// for the Microsoft compiler version. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2012-11-08 16:44:37 -0200 (qui, 08 nov 2012) $ +// File revision : $Revision: 4 $ +// +// $Id: cpu_detect_x86.cpp 159 2012-11-08 18:44:37Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// License : +// +// SoundTouch audio processing library +// Copyright (c) Olli Parviainen +// +// 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +//////////////////////////////////////////////////////////////////////////////// + +#include "cpu_detect.h" +#include "STTypes.h" + +#if defined(SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS) + + #if defined(__GNUC__) && defined(__i386__) + // gcc + #include "cpuid.h" + #elif defined(_M_IX86) + // windows non-gcc + #include + #define bit_MMX (1 << 23) + #define bit_SSE (1 << 25) + #define bit_SSE2 (1 << 26) + #endif + +#endif + + +////////////////////////////////////////////////////////////////////////////// +// +// processor instructions extension detection routines +// +////////////////////////////////////////////////////////////////////////////// + +// Flag variable indicating whick ISA extensions are disabled (for debugging) +static uint _dwDisabledISA = 0x00; // 0xffffffff; //<- use this to disable all extensions + +// Disables given set of instruction extensions. See SUPPORT_... defines. +void disableExtensions(uint dwDisableMask) +{ + _dwDisabledISA = dwDisableMask; +} + + + +/// Checks which instruction set extensions are supported by the CPU. +uint detectCPUextensions(void) +{ +/// If building for a 64bit system (no Itanium) and the user wants optimizations. +/// Return the OR of SUPPORT_{MMX,SSE,SSE2}. 11001 or 0x19. +/// Keep the _dwDisabledISA test (2 more operations, could be eliminated). +#if ((defined(__GNUC__) && defined(__x86_64__)) \ + || defined(_M_X64)) \ + && defined(SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS) + return 0x19 & ~_dwDisabledISA; + +/// If building for a 32bit system and the user wants optimizations. +/// Keep the _dwDisabledISA test (2 more operations, could be eliminated). +#elif ((defined(__GNUC__) && defined(__i386__)) \ + || defined(_M_IX86)) \ + && defined(SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS) + + if (_dwDisabledISA == 0xffffffff) return 0; + + uint res = 0; + +#if defined(__GNUC__) + // GCC version of cpuid. Requires GCC 4.3.0 or later for __cpuid intrinsic support. + uint eax, ebx, ecx, edx; // unsigned int is the standard type. uint is defined by the compiler and not guaranteed to be portable. + + // Check if no cpuid support. + if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx)) return 0; // always disable extensions. + + if (edx & bit_MMX) res = res | SUPPORT_MMX; + if (edx & bit_SSE) res = res | SUPPORT_SSE; + if (edx & bit_SSE2) res = res | SUPPORT_SSE2; + +#else + // Window / VS version of cpuid. Notice that Visual Studio 2005 or later required + // for __cpuid intrinsic support. + int reg[4] = {-1}; + + // Check if no cpuid support. + __cpuid(reg,0); + if ((unsigned int)reg[0] == 0) return 0; // always disable extensions. + + __cpuid(reg,1); + if ((unsigned int)reg[3] & bit_MMX) res = res | SUPPORT_MMX; + if ((unsigned int)reg[3] & bit_SSE) res = res | SUPPORT_SSE; + if ((unsigned int)reg[3] & bit_SSE2) res = res | SUPPORT_SSE2; + +#endif + + return res & ~_dwDisabledISA; + +#else + +/// One of these is true: +/// 1) We don't want optimizations. +/// 2) Using an unsupported compiler. +/// 3) Running on a non-x86 platform. + return 0; + +#endif +} diff --git a/3rdparty/SoundTouch/cpu_detect_x86_gcc.cpp b/3rdparty/SoundTouch/cpu_detect_x86_gcc.cpp index 806de7f28..dbb79236b 100644 --- a/3rdparty/SoundTouch/cpu_detect_x86_gcc.cpp +++ b/3rdparty/SoundTouch/cpu_detect_x86_gcc.cpp @@ -2,7 +2,7 @@ /// /// Generic version of the x86 CPU extension detection routine. /// -/// This file is for GNU & other non-Windows compilers, see 'cpu_detect_x86_win.cpp' +/// This file is for GNU & other non-Windows compilers, see 'cpu_detect_x86_win.cpp' /// for the Microsoft compiler version. /// /// Author : Copyright (c) Olli Parviainen @@ -11,10 +11,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2009-02-25 19:13:51 +0200 (Wed, 25 Feb 2009) $ +// Last changed : $Date: 2011-09-02 15:56:11 -0300 (sex, 02 set 2011) $ // File revision : $Revision: 4 $ // -// $Id: cpu_detect_x86_gcc.cpp 67 2009-02-25 17:13:51Z oparviai $ +// $Id: cpu_detect_x86_gcc.cpp 131 2011-09-02 18:56:11Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -39,15 +39,9 @@ // //////////////////////////////////////////////////////////////////////////////// -#include -#include #include "cpu_detect.h" #include "STTypes.h" -using namespace std; - -#include - ////////////////////////////////////////////////////////////////////////////// // // processor instructions extension detection routines @@ -68,7 +62,7 @@ void disableExtensions(uint dwDisableMask) /// Checks which instruction set extensions are supported by the CPU. uint detectCPUextensions(void) { -#if (!(ALLOW_X86_OPTIMIZATIONS) || !(__GNUC__)) +#if (!(SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS) || !(__GNUC__)) return 0; // always disable extensions on non-x86 platforms. @@ -78,8 +72,11 @@ uint detectCPUextensions(void) if (_dwDisabledISA == 0xffffffff) return 0; asm volatile( +#ifndef __x86_64__ + // Check if 'cpuid' instructions is available by toggling eflags bit 21. + // Skip this for x86-64 as they always have cpuid while stack manipulation + // differs from 16/32bit ISA. "\n\txor %%esi, %%esi" // clear %%esi = result register - // check if 'cpuid' instructions is available by toggling eflags bit 21 "\n\tpushf" // save eflags to stack "\n\tmovl (%%esp), %%eax" // load eax from stack (with eflags) @@ -93,6 +90,8 @@ uint detectCPUextensions(void) "\n\txor %%edx, %%edx" // clear edx for defaulting no mmx "\n\tcmp %%ecx, %%eax" // compare to original eflags values "\n\tjz end" // jumps to 'end' if cpuid not present +#endif // __x86_64__ + // cpuid instruction available, test for presence of mmx instructions "\n\tmovl $1, %%eax" @@ -129,7 +128,7 @@ uint detectCPUextensions(void) : "=r" (res) : /* no inputs */ : "%edx", "%eax", "%ecx", "%esi" ); - + return res & ~_dwDisabledISA; #endif } diff --git a/3rdparty/SoundTouch/cpu_detect_x86_win.cpp b/3rdparty/SoundTouch/cpu_detect_x86_win.cpp index 883a3accc..666c7b070 100644 --- a/3rdparty/SoundTouch/cpu_detect_x86_win.cpp +++ b/3rdparty/SoundTouch/cpu_detect_x86_win.cpp @@ -2,8 +2,8 @@ /// /// Win32 version of the x86 CPU detect routine. /// -/// This file is to be compiled in Windows platform with Microsoft Visual C++ -/// Compiler. Please see 'cpu_detect_x86_gcc.cpp' for the gcc compiler version +/// This file is to be compiled in Windows platform with Microsoft Visual C++ +/// Compiler. Please see 'cpu_detect_x86_gcc.cpp' for the gcc compiler version /// for all GNU platforms. /// /// Author : Copyright (c) Olli Parviainen @@ -12,10 +12,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2009-02-13 18:22:48 +0200 (Fri, 13 Feb 2009) $ +// Last changed : $Date: 2011-07-17 07:58:40 -0300 (dom, 17 jul 2011) $ // File revision : $Revision: 4 $ // -// $Id: cpu_detect_x86_win.cpp 62 2009-02-13 16:22:48Z oparviai $ +// $Id: cpu_detect_x86_win.cpp 127 2011-07-17 10:58:40Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -42,9 +42,7 @@ #include "cpu_detect.h" -#ifndef WIN32 -#error wrong platform - this source code file is exclusively for Win32 platform -#endif +#include "STTypes.h" ////////////////////////////////////////////////////////////////////////////// // @@ -71,7 +69,9 @@ uint detectCPUextensions(void) if (_dwDisabledISA == 0xffffffff) return 0; - _asm +#ifndef _M_X64 + // 32bit compilation, detect CPU capabilities with inline assembler. + __asm { ; check if 'cpuid' instructions is available by toggling eflags bit 21 ; @@ -92,7 +92,7 @@ uint detectCPUextensions(void) cmp eax, ecx ; compare to original eflags values jz end ; jumps to 'end' if cpuid not present - ; cpuid instruction available, test for presence of mmx instructions + ; cpuid instruction available, test for presence of mmx instructions mov eax, 1 cpuid test edx, 0x00800000 @@ -125,5 +125,13 @@ uint detectCPUextensions(void) mov res, esi } +#else + + // Visual C++ 64bit compilation doesn't support inline assembler. However, + // all x64 compatible CPUs support MMX & SSE extensions. + res = SUPPORT_MMX | SUPPORT_SSE | SUPPORT_SSE2; + +#endif + return res & ~_dwDisabledISA; } diff --git a/3rdparty/SoundTouch/mmx_optimized.cpp b/3rdparty/SoundTouch/mmx_optimized.cpp index 477119529..15d8af1b7 100644 --- a/3rdparty/SoundTouch/mmx_optimized.cpp +++ b/3rdparty/SoundTouch/mmx_optimized.cpp @@ -1,15 +1,15 @@ //////////////////////////////////////////////////////////////////////////////// /// -/// MMX optimized routines. All MMX optimized functions have been gathered into -/// this single source code file, regardless to their class or original source -/// code file, in order to ease porting the library to other compiler and +/// MMX optimized routines. All MMX optimized functions have been gathered into +/// this single source code file, regardless to their class or original source +/// code file, in order to ease porting the library to other compiler and /// processor platforms. /// /// The MMX-optimizations are programmed using MMX compiler intrinsics that /// are supported both by Microsoft Visual C++ and GCC compilers, so this file /// should compile with both toolsets. /// -/// NOTICE: If using Visual Studio 6.0, you'll need to install the "Visual C++ +/// NOTICE: If using Visual Studio 6.0, you'll need to install the "Visual C++ /// 6.0 processor pack" update to support compiler intrinsic syntax. The update /// is available for download at Microsoft Developers Network, see here: /// http://msdn.microsoft.com/en-us/vstudio/aa718349.aspx @@ -20,10 +20,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2009-10-31 16:53:23 +0200 (Sat, 31 Oct 2009) $ +// Last changed : $Date: 2012-11-08 16:53:01 -0200 (qui, 08 nov 2012) $ // File revision : $Revision: 4 $ // -// $Id: mmx_optimized.cpp 75 2009-10-31 14:53:23Z oparviai $ +// $Id: mmx_optimized.cpp 160 2012-11-08 18:53:01Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -50,13 +50,9 @@ #include "STTypes.h" -#ifdef ALLOW_MMX +#ifdef SOUNDTOUCH_ALLOW_MMX // MMX routines available only with integer sample type -#if !(WIN32 || __i386__ || __x86_64__) -#error "wrong platform - this source code file is exclusively for x86 platforms" -#endif - using namespace soundtouch; ////////////////////////////////////////////////////////////////////////////// @@ -72,23 +68,23 @@ using namespace soundtouch; // Calculates cross correlation of two buffers -long TDStretchMMX::calcCrossCorrStereo(const short *pV1, const short *pV2) const +double TDStretchMMX::calcCrossCorr(const short *pV1, const short *pV2) const { const __m64 *pVec1, *pVec2; __m64 shifter; __m64 accu, normaccu; long corr, norm; int i; - + pVec1 = (__m64*)pV1; pVec2 = (__m64*)pV2; shifter = _m_from_int(overlapDividerBits); normaccu = accu = _mm_setzero_si64(); - // Process 4 parallel sets of 2 * stereo samples each during each - // round to improve CPU-level parallellization. - for (i = 0; i < overlapLength / 8; i ++) + // Process 4 parallel sets of 2 * stereo samples or 4 * mono samples + // during each round for improved CPU-level parallellization. + for (i = 0; i < channels * overlapLength / 16; i ++) { __m64 temp, temp2; @@ -127,10 +123,11 @@ long TDStretchMMX::calcCrossCorrStereo(const short *pV1, const short *pV2) const // Clear MMS state _m_empty(); - // Normalize result by dividing by sqrt(norm) - this step is easiest + // Normalize result by dividing by sqrt(norm) - this step is easiest // done using floating point operation if (norm == 0) norm = 1; // to avoid div by zero - return (long)((double)corr * USHRT_MAX / sqrt((double)norm)); + + return (double)corr / sqrt((double)norm); // Note: Warning about the missing EMMS instruction is harmless // as it'll be called elsewhere. } @@ -161,7 +158,7 @@ void TDStretchMMX::overlapStereo(short *output, const short *input) const // mix1 = mixer values for 1st stereo sample // mix1 = mixer values for 2nd stereo sample // adder = adder for updating mixer values after each round - + mix1 = _mm_set_pi16(0, overlapLength, 0, overlapLength); adder = _mm_set_pi16(1, -1, 1, -1); mix2 = _mm_add_pi16(mix1, adder); @@ -174,7 +171,7 @@ void TDStretchMMX::overlapStereo(short *output, const short *input) const for (i = 0; i < overlapLength / 4; i ++) { __m64 temp1, temp2; - + // load & shuffle data so that input & mixbuffer data samples are paired temp1 = _mm_unpacklo_pi16(pVMidBuf[0], pVinput[0]); // = i0l m0l i0r m0r temp2 = _mm_unpackhi_pi16(pVMidBuf[0], pVinput[0]); // = i1l m1l i1r m1r @@ -242,10 +239,10 @@ void FIRFilterMMX::setCoefficients(const short *coeffs, uint newLength, uint uRe // Ensure that filter coeffs array is aligned to 16-byte boundary delete[] filterCoeffsUnalign; filterCoeffsUnalign = new short[2 * newLength + 8]; - filterCoeffsAlign = (short *)(((ulong)filterCoeffsUnalign + 15) & -16); + filterCoeffsAlign = (short *)SOUNDTOUCH_ALIGN_POINTER_16(filterCoeffsUnalign); - // rearrange the filter coefficients for mmx routines - for (i = 0;i < length; i += 4) + // rearrange the filter coefficients for mmx routines + for (i = 0;i < length; i += 4) { filterCoeffsAlign[2 * i + 0] = coeffs[i + 0]; filterCoeffsAlign[2 * i + 1] = coeffs[i + 2]; @@ -317,4 +314,4 @@ uint FIRFilterMMX::evaluateFilterStereo(short *dest, const short *src, uint numS return (numSamples & 0xfffffffe) - length; } -#endif // ALLOW_MMX +#endif // SOUNDTOUCH_ALLOW_MMX diff --git a/3rdparty/SoundTouch/sse_optimized.cpp b/3rdparty/SoundTouch/sse_optimized.cpp index 7edd1cb79..3566252ca 100644 --- a/3rdparty/SoundTouch/sse_optimized.cpp +++ b/3rdparty/SoundTouch/sse_optimized.cpp @@ -1,20 +1,20 @@ //////////////////////////////////////////////////////////////////////////////// /// -/// SSE optimized routines for Pentium-III, Athlon-XP and later CPUs. All SSE -/// optimized functions have been gathered into this single source -/// code file, regardless to their class or original source code file, in order +/// SSE optimized routines for Pentium-III, Athlon-XP and later CPUs. All SSE +/// optimized functions have been gathered into this single source +/// code file, regardless to their class or original source code file, in order /// to ease porting the library to other compiler and processor platforms. /// /// The SSE-optimizations are programmed using SSE compiler intrinsics that /// are supported both by Microsoft Visual C++ and GCC compilers, so this file /// should compile with both toolsets. /// -/// NOTICE: If using Visual Studio 6.0, you'll need to install the "Visual C++ -/// 6.0 processor pack" update to support SSE instruction set. The update is +/// NOTICE: If using Visual Studio 6.0, you'll need to install the "Visual C++ +/// 6.0 processor pack" update to support SSE instruction set. The update is /// available for download at Microsoft Developers Network, see here: /// http://msdn.microsoft.com/en-us/vstudio/aa718349.aspx /// -/// If the above URL is expired or removed, go to "http://msdn.microsoft.com" and +/// If the above URL is expired or removed, go to "http://msdn.microsoft.com" and /// perform a search with keywords "processor pack". /// /// Author : Copyright (c) Olli Parviainen @@ -23,10 +23,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2009-12-28 22:32:57 +0200 (Mon, 28 Dec 2009) $ +// Last changed : $Date: 2012-11-08 16:53:01 -0200 (qui, 08 nov 2012) $ // File revision : $Revision: 4 $ // -// $Id: sse_optimized.cpp 80 2009-12-28 20:32:57Z oparviai $ +// $Id: sse_optimized.cpp 160 2012-11-08 18:53:01Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -56,9 +56,9 @@ using namespace soundtouch; -#ifdef ALLOW_SSE +#ifdef SOUNDTOUCH_ALLOW_SSE -// SSE routines available only with float sample type +// SSE routines available only with float sample type ////////////////////////////////////////////////////////////////////////////// // @@ -71,35 +71,35 @@ using namespace soundtouch; #include // Calculates cross correlation of two buffers -double TDStretchSSE::calcCrossCorrStereo(const float *pV1, const float *pV2) const +double TDStretchSSE::calcCrossCorr(const float *pV1, const float *pV2) const { int i; const float *pVec1; const __m128 *pVec2; __m128 vSum, vNorm; - // Note. It means a major slow-down if the routine needs to tolerate - // unaligned __m128 memory accesses. It's way faster if we can skip + // Note. It means a major slow-down if the routine needs to tolerate + // unaligned __m128 memory accesses. It's way faster if we can skip // unaligned slots and use _mm_load_ps instruction instead of _mm_loadu_ps. // This can mean up to ~ 10-fold difference (incl. part of which is // due to skipping every second round for stereo sound though). // - // Compile-time define ALLOW_NONEXACT_SIMD_OPTIMIZATION is provided + // Compile-time define SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION is provided // for choosing if this little cheating is allowed. -#ifdef ALLOW_NONEXACT_SIMD_OPTIMIZATION - // Little cheating allowed, return valid correlation only for +#ifdef SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION + // Little cheating allowed, return valid correlation only for // aligned locations, meaning every second round for stereo sound. #define _MM_LOAD _mm_load_ps - if (((ulong)pV1) & 15) return -1e50; // skip unaligned locations + if (((ulongptr)pV1) & 15) return -1e50; // skip unaligned locations #else // No cheating allowed, use unaligned load & take the resulting // performance hit. #define _MM_LOAD _mm_loadu_ps -#endif +#endif // ensure overlapLength is divisible by 8 assert((overlapLength % 8) == 0); @@ -110,8 +110,9 @@ double TDStretchSSE::calcCrossCorrStereo(const float *pV1, const float *pV2) con pVec2 = (const __m128*)pV2; vSum = vNorm = _mm_setzero_ps(); - // Unroll the loop by factor of 4 * 4 operations - for (i = 0; i < overlapLength / 8; i ++) + // Unroll the loop by factor of 4 * 4 operations. Use same routine for + // stereo & mono, for mono it just means twice the amount of unrolling. + for (i = 0; i < channels * overlapLength / 16; i ++) { __m128 vTemp; // vSum += pV1[0..3] * pV2[0..3] @@ -152,7 +153,7 @@ double TDStretchSSE::calcCrossCorrStereo(const float *pV1, const float *pV2) con // Calculates the cross-correlation value between 'pV1' and 'pV2' vectors corr = norm = 0.0; - for (i = 0; i < overlapLength / 8; i ++) + for (i = 0; i < channels * overlapLength / 16; i ++) { corr += pV1[0] * pV2[0] + pV1[1] * pV2[1] + @@ -171,81 +172,13 @@ double TDStretchSSE::calcCrossCorrStereo(const float *pV1, const float *pV2) con pV1[14] * pV2[14] + pV1[15] * pV2[15]; - for (j = 0; j < 15; j ++) norm += pV1[j] * pV1[j]; + for (j = 0; j < 15; j ++) norm += pV1[j] * pV1[j]; pV1 += 16; pV2 += 16; } return corr / sqrt(norm); */ - - /* This is a bit outdated, corresponding routine in assembler. This may be teeny-weeny bit - faster than intrinsic version, but more difficult to maintain & get compiled on multiple - platforms. - - uint overlapLengthLocal = overlapLength; - float corr; - - _asm - { - // Very important note: data in 'pV2' _must_ be aligned to - // 16-byte boundary! - - // give prefetch hints to CPU of what data are to be needed soonish - // give more aggressive hints on pV1 as that changes while pV2 stays - // same between runs - prefetcht0 [pV1] - prefetcht0 [pV2] - prefetcht0 [pV1 + 32] - - mov eax, dword ptr pV1 - mov ebx, dword ptr pV2 - - xorps xmm0, xmm0 - - mov ecx, overlapLengthLocal - shr ecx, 3 // div by eight - - loop1: - prefetcht0 [eax + 64] // give a prefetch hint to CPU what data are to be needed soonish - prefetcht0 [ebx + 32] // give a prefetch hint to CPU what data are to be needed soonish - movups xmm1, [eax] - mulps xmm1, [ebx] - addps xmm0, xmm1 - - movups xmm2, [eax + 16] - mulps xmm2, [ebx + 16] - addps xmm0, xmm2 - - prefetcht0 [eax + 96] // give a prefetch hint to CPU what data are to be needed soonish - prefetcht0 [ebx + 64] // give a prefetch hint to CPU what data are to be needed soonish - - movups xmm3, [eax + 32] - mulps xmm3, [ebx + 32] - addps xmm0, xmm3 - - movups xmm4, [eax + 48] - mulps xmm4, [ebx + 48] - addps xmm0, xmm4 - - add eax, 64 - add ebx, 64 - - dec ecx - jnz loop1 - - // add the four floats of xmm0 together and return the result. - - movhlps xmm1, xmm0 // move 3 & 4 of xmm0 to 1 & 2 of xmm1 - addps xmm1, xmm0 - movaps xmm2, xmm1 - shufps xmm2, xmm2, 0x01 // move 2 of xmm2 as 1 of xmm2 - addss xmm2, xmm1 - movss corr, xmm2 - } - - return (double)corr; - */ } @@ -281,15 +214,15 @@ void FIRFilterSSE::setCoefficients(const float *coeffs, uint newLength, uint uRe FIRFilter::setCoefficients(coeffs, newLength, uResultDivFactor); // Scale the filter coefficients so that it won't be necessary to scale the filtering result - // also rearrange coefficients suitably for 3DNow! + // also rearrange coefficients suitably for SSE // Ensure that filter coeffs array is aligned to 16-byte boundary delete[] filterCoeffsUnalign; filterCoeffsUnalign = new float[2 * newLength + 4]; - filterCoeffsAlign = (float *)(((unsigned long)filterCoeffsUnalign + 15) & (ulong)-16); + filterCoeffsAlign = (float *)SOUNDTOUCH_ALIGN_POINTER_16(filterCoeffsUnalign); fDivider = (float)resultDivider; - // rearrange the filter coefficients for mmx routines + // rearrange the filter coefficients for mmx routines for (i = 0; i < newLength; i ++) { filterCoeffsAlign[2 * i + 0] = @@ -313,7 +246,7 @@ uint FIRFilterSSE::evaluateFilterStereo(float *dest, const float *source, uint n assert(dest != NULL); assert((length % 8) == 0); assert(filterCoeffsAlign != NULL); - assert(((ulong)filterCoeffsAlign) % 16 == 0); + assert(((ulongptr)filterCoeffsAlign) % 16 == 0); // filter is evaluated for two stereo samples with each iteration, thus use of 'j += 2' for (j = 0; j < count; j += 2) @@ -324,13 +257,13 @@ uint FIRFilterSSE::evaluateFilterStereo(float *dest, const float *source, uint n uint i; pSrc = (const float*)source; // source audio data - pFil = (const __m128*)filterCoeffsAlign; // filter coefficients. NOTE: Assumes coefficients + pFil = (const __m128*)filterCoeffsAlign; // filter coefficients. NOTE: Assumes coefficients // are aligned to 16-byte boundary sum1 = sum2 = _mm_setzero_ps(); - for (i = 0; i < length / 8; i ++) + for (i = 0; i < length / 8; i ++) { - // Unroll loop for efficiency & calculate filter for 2*2 stereo samples + // Unroll loop for efficiency & calculate filter for 2*2 stereo samples // at each pass // sum1 is accu for 2*2 filtered stereo sound data at the primary sound data offset @@ -365,14 +298,14 @@ uint FIRFilterSSE::evaluateFilterStereo(float *dest, const float *source, uint n } // Ideas for further improvement: - // 1. If it could be guaranteed that 'source' were always aligned to 16-byte + // 1. If it could be guaranteed that 'source' were always aligned to 16-byte // boundary, a faster aligned '_mm_load_ps' instruction could be used. - // 2. If it could be guaranteed that 'dest' were always aligned to 16-byte + // 2. If it could be guaranteed that 'dest' were always aligned to 16-byte // boundary, a faster '_mm_store_ps' instruction could be used. return (uint)count; - /* original routine in C-language. please notice the C-version has differently + /* original routine in C-language. please notice the C-version has differently organized coefficients though. double suml1, suml2; double sumr1, sumr2; @@ -387,26 +320,26 @@ uint FIRFilterSSE::evaluateFilterStereo(float *dest, const float *source, uint n suml2 = sumr2 = 0.0; ptr = src; pFil = filterCoeffs; - for (i = 0; i < lengthLocal; i ++) + for (i = 0; i < lengthLocal; i ++) { // unroll loop for efficiency. - suml1 += ptr[0] * pFil[0] + + suml1 += ptr[0] * pFil[0] + ptr[2] * pFil[2] + ptr[4] * pFil[4] + ptr[6] * pFil[6]; - sumr1 += ptr[1] * pFil[1] + + sumr1 += ptr[1] * pFil[1] + ptr[3] * pFil[3] + ptr[5] * pFil[5] + ptr[7] * pFil[7]; - suml2 += ptr[8] * pFil[0] + + suml2 += ptr[8] * pFil[0] + ptr[10] * pFil[2] + ptr[12] * pFil[4] + ptr[14] * pFil[6]; - sumr2 += ptr[9] * pFil[1] + + sumr2 += ptr[9] * pFil[1] + ptr[11] * pFil[3] + ptr[13] * pFil[5] + ptr[15] * pFil[7]; @@ -423,88 +356,6 @@ uint FIRFilterSSE::evaluateFilterStereo(float *dest, const float *source, uint n dest += 4; } */ - - - /* Similar routine in assembly, again obsoleted due to maintainability - _asm - { - // Very important note: data in 'src' _must_ be aligned to - // 16-byte boundary! - mov edx, count - mov ebx, dword ptr src - mov eax, dword ptr dest - shr edx, 1 - - loop1: - // "outer loop" : during each round 2*2 output samples are calculated - - // give prefetch hints to CPU of what data are to be needed soonish - prefetcht0 [ebx] - prefetcht0 [filterCoeffsLocal] - - mov esi, ebx - mov edi, filterCoeffsLocal - xorps xmm0, xmm0 - xorps xmm1, xmm1 - mov ecx, lengthLocal - - loop2: - // "inner loop" : during each round eight FIR filter taps are evaluated for 2*2 samples - prefetcht0 [esi + 32] // give a prefetch hint to CPU what data are to be needed soonish - prefetcht0 [edi + 32] // give a prefetch hint to CPU what data are to be needed soonish - - movups xmm2, [esi] // possibly unaligned load - movups xmm3, [esi + 8] // possibly unaligned load - mulps xmm2, [edi] - mulps xmm3, [edi] - addps xmm0, xmm2 - addps xmm1, xmm3 - - movups xmm4, [esi + 16] // possibly unaligned load - movups xmm5, [esi + 24] // possibly unaligned load - mulps xmm4, [edi + 16] - mulps xmm5, [edi + 16] - addps xmm0, xmm4 - addps xmm1, xmm5 - - prefetcht0 [esi + 64] // give a prefetch hint to CPU what data are to be needed soonish - prefetcht0 [edi + 64] // give a prefetch hint to CPU what data are to be needed soonish - - movups xmm6, [esi + 32] // possibly unaligned load - movups xmm7, [esi + 40] // possibly unaligned load - mulps xmm6, [edi + 32] - mulps xmm7, [edi + 32] - addps xmm0, xmm6 - addps xmm1, xmm7 - - movups xmm4, [esi + 48] // possibly unaligned load - movups xmm5, [esi + 56] // possibly unaligned load - mulps xmm4, [edi + 48] - mulps xmm5, [edi + 48] - addps xmm0, xmm4 - addps xmm1, xmm5 - - add esi, 64 - add edi, 64 - dec ecx - jnz loop2 - - // Now xmm0 and xmm1 both have a filtered 2-channel sample each, but we still need - // to sum the two hi- and lo-floats of these registers together. - - movhlps xmm2, xmm0 // xmm2 = xmm2_3 xmm2_2 xmm0_3 xmm0_2 - movlhps xmm2, xmm1 // xmm2 = xmm1_1 xmm1_0 xmm0_3 xmm0_2 - shufps xmm0, xmm1, 0xe4 // xmm0 = xmm1_3 xmm1_2 xmm0_1 xmm0_0 - addps xmm0, xmm2 - - movaps [eax], xmm0 - add ebx, 16 - add eax, 16 - - dec edx - jnz loop1 - } - */ } -#endif // ALLOW_SSE +#endif // SOUNDTOUCH_ALLOW_SSE From 08329122aaf7fea13ec6b00d428067117ef306ea Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Fri, 19 Apr 2013 19:16:26 +0000 Subject: [PATCH 70/81] gsdx (ogl): * Use bigger index for Uniform buffer to avoid any collision with sampler. * add a new config to disable openGL 4.2 requirement. Would be done at runtime later. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5620 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSDeviceOGL.cpp | 71 +++++++++++++++++++++----------- plugins/GSdx/GSDeviceOGL.h | 2 + plugins/GSdx/GSTextureFXOGL.cpp | 7 +++- plugins/GSdx/config.h | 2 + plugins/GSdx/res/interlace.glsl | 6 ++- plugins/GSdx/res/merge.glsl | 6 ++- plugins/GSdx/res/shadeboost.glsl | 6 ++- plugins/GSdx/res/tfx.glsl | 12 +++++- 8 files changed, 81 insertions(+), 31 deletions(-) diff --git a/plugins/GSdx/GSDeviceOGL.cpp b/plugins/GSdx/GSDeviceOGL.cpp index 168699c65..64197f82e 100644 --- a/plugins/GSdx/GSDeviceOGL.cpp +++ b/plugins/GSdx/GSDeviceOGL.cpp @@ -32,6 +32,10 @@ static uint32 g_draw_count = 0; static uint32 g_frame_count = 1; +static const uint32 g_merge_cb_index = 10; +static const uint32 g_interlace_cb_index = 11; +static const uint32 g_shadeboost_cb_index = 12; +static const uint32 g_fxaa_cb_index = 13; GSDeviceOGL::GSDeviceOGL() : m_free_window(false) @@ -287,7 +291,7 @@ bool GSDeviceOGL::Create(GSWnd* wnd) // **************************************************************** // merge // **************************************************************** - m_merge_obj.cb = new GSUniformBufferOGL(1, sizeof(MergeConstantBuffer)); + m_merge_obj.cb = new GSUniformBufferOGL(g_merge_cb_index, sizeof(MergeConstantBuffer)); for(uint i = 0; i < countof(m_merge_obj.ps); i++) CompileShaderFromSource("merge.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, &m_merge_obj.ps[i]); @@ -299,14 +303,14 @@ bool GSDeviceOGL::Create(GSWnd* wnd) // **************************************************************** // interlace // **************************************************************** - m_interlace.cb = new GSUniformBufferOGL(2, sizeof(InterlaceConstantBuffer)); + m_interlace.cb = new GSUniformBufferOGL(g_interlace_cb_index, sizeof(InterlaceConstantBuffer)); for(uint i = 0; i < countof(m_interlace.ps); i++) CompileShaderFromSource("interlace.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, &m_interlace.ps[i]); // **************************************************************** // Shade boost // **************************************************************** - m_shadeboost.cb = new GSUniformBufferOGL(6, sizeof(ShadeBoostConstantBuffer)); + m_shadeboost.cb = new GSUniformBufferOGL(g_shadeboost_cb_index, sizeof(ShadeBoostConstantBuffer)); int ShadeBoost_Contrast = theApp.GetConfig("ShadeBoost_Contrast", 50); int ShadeBoost_Brightness = theApp.GetConfig("ShadeBoost_Brightness", 50); @@ -347,7 +351,7 @@ bool GSDeviceOGL::Create(GSWnd* wnd) // FIXME need to define FXAA_GLSL_130 for the shader // FIXME need to manually set the index... // FIXME need dofxaa interface too - // m_fxaa.cb = new GSUniformBufferOGL(3, sizeof(FXAAConstantBuffer)); + // m_fxaa.cb = new GSUniformBufferOGL(g_fxaa_cb_index, sizeof(FXAAConstantBuffer)); //CompileShaderFromSource("fxaa.fx", format("ps_main", i), GL_FRAGMENT_SHADER, &m_fxaa.ps); // **************************************************************** @@ -597,47 +601,62 @@ void GSDeviceOGL::DebugOutput() //DebugBB(); } -void GSDeviceOGL::DrawPrimitive() +#ifdef DISABLE_GL42 +static void set_uniform_buffer_binding(GLuint prog, GLchar* name, GLuint binding) { + GLuint index; + index = glGetUniformBlockIndex(prog, name); + if (index != GL_INVALID_INDEX) { + glUniformBlockBinding(prog, index, binding); + } +} +#endif + +void GSDeviceOGL::BeforeDraw() { #ifdef OGL_DEBUG DebugInput(); #endif - m_state.vb->DrawPrimitive(); +#ifdef DISABLE_GL42 + set_uniform_buffer_binding(m_state.vs, "cb20", 20); + set_uniform_buffer_binding(m_state.ps, "cb21", 21); + set_uniform_buffer_binding(m_state.ps, "cb10", 10); + set_uniform_buffer_binding(m_state.ps, "cb11", 11); + set_uniform_buffer_binding(m_state.ps, "cb12", 12); + set_uniform_buffer_binding(m_state.ps, "cb13", 13); +#endif +} + +void GSDeviceOGL::AfterDraw() +{ #ifdef OGL_DEBUG DebugOutput(); g_draw_count++; #endif } +void GSDeviceOGL::DrawPrimitive() +{ + BeforeDraw(); + m_state.vb->DrawPrimitive(); + AfterDraw(); +} + void GSDeviceOGL::DrawIndexedPrimitive() { -#ifdef OGL_DEBUG - DebugInput(); -#endif - + BeforeDraw(); m_state.vb->DrawIndexedPrimitive(); - -#ifdef OGL_DEBUG - DebugOutput(); - g_draw_count++; -#endif + AfterDraw(); } void GSDeviceOGL::DrawIndexedPrimitive(int offset, int count) { ASSERT(offset + count <= m_index.count); -#ifdef OGL_DEBUG - DebugInput(); -#endif + BeforeDraw(); m_state.vb->DrawIndexedPrimitive(offset, count); - -#ifdef OGL_DEBUG - DebugOutput(); - g_draw_count++; -#endif + AfterDraw(); } void GSDeviceOGL::ClearRenderTarget(GSTexture* t, const GSVector4& c) @@ -733,7 +752,7 @@ GSTexture* GSDeviceOGL::CopyOffscreen(GSTexture* src, const GSVector4& sr, int w { ASSERT(0); - return false; + return NULL; } // FIXME: It is possible to bypass completely offscreen-buffer on opengl but it needs some re-thinking of the code. @@ -1283,7 +1302,11 @@ void GSDeviceOGL::CompileShaderFromSource(const std::string& glsl_file, const st // Build a header string // ***************************************************** // First select the version (must be the first line so we need to generate it +#ifdef DISABLE_GL42 + std::string version = "#version 330\n#extension GL_ARB_separate_shader_objects : require\n#define DISABLE_GL42\n"; +#else std::string version = "#version 330\n#extension GL_ARB_shading_language_420pack: require\n#extension GL_ARB_separate_shader_objects : require\n"; +#endif //std::string version = "#version 420\n"; // Allow to puts several shader in 1 files diff --git a/plugins/GSdx/GSDeviceOGL.h b/plugins/GSdx/GSDeviceOGL.h index 195e6697f..697c9e6da 100644 --- a/plugins/GSdx/GSDeviceOGL.h +++ b/plugins/GSdx/GSDeviceOGL.h @@ -599,6 +599,8 @@ class GSDeviceOGL : public GSDevice void DrawPrimitive(); void DrawIndexedPrimitive(); void DrawIndexedPrimitive(int offset, int count); + void BeforeDraw(); + void AfterDraw(); void ClearRenderTarget(GSTexture* t, const GSVector4& c); void ClearRenderTarget(GSTexture* t, uint32 c); diff --git a/plugins/GSdx/GSTextureFXOGL.cpp b/plugins/GSdx/GSTextureFXOGL.cpp index ab062688b..80d4e4699 100644 --- a/plugins/GSdx/GSTextureFXOGL.cpp +++ b/plugins/GSdx/GSTextureFXOGL.cpp @@ -23,10 +23,13 @@ #include "GSDeviceOGL.h" #include "GSTables.h" +static const uint32 g_vs_cb_index = 20; +static const uint32 g_ps_cb_index = 21; + void GSDeviceOGL::CreateTextureFX() { - m_vs_cb = new GSUniformBufferOGL(4, sizeof(VSConstantBuffer)); - m_ps_cb = new GSUniformBufferOGL(5, sizeof(PSConstantBuffer)); + m_vs_cb = new GSUniformBufferOGL(g_vs_cb_index, sizeof(VSConstantBuffer)); + m_ps_cb = new GSUniformBufferOGL(g_ps_cb_index, sizeof(PSConstantBuffer)); glGenSamplers(1, &m_rt_ss); // FIXME, seem to have no difference between sampler !!! diff --git a/plugins/GSdx/config.h b/plugins/GSdx/config.h index a11724fcb..80c47392b 100644 --- a/plugins/GSdx/config.h +++ b/plugins/GSdx/config.h @@ -35,3 +35,5 @@ //#define DISABLE_COLCLAMP //#define DISABLE_DATE + +//#define DISABLE_GL42 diff --git a/plugins/GSdx/res/interlace.glsl b/plugins/GSdx/res/interlace.glsl index 97e567fa1..21b81af11 100644 --- a/plugins/GSdx/res/interlace.glsl +++ b/plugins/GSdx/res/interlace.glsl @@ -11,7 +11,11 @@ layout(location = 0) in vertex_basic PSin; layout(location = 0) out vec4 SV_Target0; -layout(std140, binding = 2) uniform cb0 +#ifdef DISABLE_GL42 +layout(std140) uniform cb11 +#else +layout(std140, binding = 11) uniform cb11 +#endif { vec2 ZrH; float hH; diff --git a/plugins/GSdx/res/merge.glsl b/plugins/GSdx/res/merge.glsl index e9a93bdc8..ed3ca3606 100644 --- a/plugins/GSdx/res/merge.glsl +++ b/plugins/GSdx/res/merge.glsl @@ -11,7 +11,11 @@ layout(location = 0) in vertex_basic PSin; layout(location = 0) out vec4 SV_Target0; -layout(std140, binding = 1) uniform cb0 +#ifdef DISABLE_GL42 +layout(std140) uniform cb10 +#else +layout(std140, binding = 10) uniform cb10 +#endif { vec4 BGColor; }; diff --git a/plugins/GSdx/res/shadeboost.glsl b/plugins/GSdx/res/shadeboost.glsl index c98222d80..006329ae8 100644 --- a/plugins/GSdx/res/shadeboost.glsl +++ b/plugins/GSdx/res/shadeboost.glsl @@ -18,7 +18,11 @@ layout(location = 0) in vertex_basic PSin; layout(location = 0) out vec4 SV_Target0; -layout(std140, binding = 6) uniform cb0 +#ifdef DISABLE_GL42 +layout(std140) uniform cb12 +#else +layout(std140, binding = 12) uniform cb12 +#endif { vec4 BGColor; }; diff --git a/plugins/GSdx/res/tfx.glsl b/plugins/GSdx/res/tfx.glsl index 85c1cb732..f25ba617a 100644 --- a/plugins/GSdx/res/tfx.glsl +++ b/plugins/GSdx/res/tfx.glsl @@ -69,7 +69,11 @@ out gl_PerVertex { float gl_ClipDistance[]; }; -layout(std140, binding = 4) uniform cb0 +#ifdef DISABLE_GL42 +layout(std140) uniform cb20 +#else +layout(std140, binding = 20) uniform cb20 +#endif { vec4 VertexScale; vec4 VertexOffset; @@ -278,7 +282,11 @@ layout(binding = 0) uniform sampler2D TextureSampler; layout(binding = 1) uniform sampler2D PaletteSampler; layout(binding = 2) uniform sampler2D RTCopySampler; -layout(std140, binding = 5) uniform cb1 +#ifdef DISABLE_GL42 +layout(std140) uniform cb21 +#else +layout(std140, binding = 21) uniform cb21 +#endif { vec3 FogColor; float AREF; From c5ffa6ae921e898c9c914693075877b996d27bd8 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Thu, 25 Apr 2013 19:11:55 +0000 Subject: [PATCH 71/81] GameDB: Updates by pgert. -Added patch for Drakan (SCES-50006) to improve the corruption problems when using resolution scaling. -Many comment modifications and console comments explaining that BIOS boot is required for correct language selection. Thanks for the updates :) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5621 96395faa-99c1-11dd-bbfe-3dabce05a288 --- bin/GameIndex.dbf | 139 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 107 insertions(+), 32 deletions(-) diff --git a/bin/GameIndex.dbf b/bin/GameIndex.dbf index b0cd9ff62..70dce1fdd 100644 --- a/bin/GameIndex.dbf +++ b/bin/GameIndex.dbf @@ -214,10 +214,10 @@ Name = Kiosk Demo Disc 2.02 Region = NTSC-U --------------------------------------------- Serial = SCUS-97128 -Name = Drakan - The Ancients' Gates // aka Drakan 2 +Name = Drakan - The Ancients' Gates // aka "Drakan 2" Region = NTSC-U Compat = 5 -EETimingHack = 1 //flickery textures +EETimingHack = 1 // flickery textures --------------------------------------------- Serial = SCUS-97129 Name = Okage - Shadow King @@ -349,7 +349,7 @@ Region = NTSC-U Compat = 5 --------------------------------------------- Serial = SCUS-97169 -Name = Drakan - The Ancients' Gates [Demo] // aka Drakan 2 [Demo] +Name = Drakan - The Ancients' Gates [Demo] // aka "Drakan 2 [Demo]" Region = NTSC-U --------------------------------------------- Serial = SCUS-97170 @@ -3670,7 +3670,7 @@ Name = Gravenville - Ghost Master Region = NTSC-U --------------------------------------------- Serial = SLUS-20467 -Name = Tomb Raider - The Angel of Darkness +Name = Tomb Raider - The Angel of Darkness // aka "TRAOD" Region = NTSC-U Compat = 5 OPHFlagHack = 1 @@ -5952,7 +5952,7 @@ Name = Samurai Showdown V Region = NTSC-U --------------------------------------------- Serial = SLUS-20973 -Name = Champions - Return to Arms // aka Champions of Norrath 2 +Name = Champions - Return to Arms // aka "Champions of Norrath 2" Region = NTSC-U Compat = 4 --------------------------------------------- @@ -10718,7 +10718,7 @@ Name = Konami Preview Disc Region = NTSC-U --------------------------------------------- Serial = SLUS-29126 -Name = Champions - Return to Arms [Demo] // aka Champions of Norrath 2 [Demo] +Name = Champions - Return to Arms [Demo] // aka "Champions of Norrath 2 [Demo]" Region = NTSC-U Compat = 4 --------------------------------------------- @@ -11188,7 +11188,7 @@ Name = Chain Drive Region = NTSC-Unk --------------------------------------------- Serial = SCAJ-20044 -Name = Tomb Raider - The Angel of Darkness +Name = Tomb Raider - The Angel of Darkness // aka "TRAOD" Region = NTSC-Unk OPHFlagHack = 1 --------------------------------------------- @@ -26577,7 +26577,7 @@ Name = True Love Story - Summer Days and Yet Region = NTSC-J --------------------------------------------- Serial = SLPS-25246 -Name = Tomb Raider - The Angel of Darkness +Name = Tomb Raider - The Angel of Darkness // aka "TRAOD" Region = NTSC-J OPHFlagHack = 1 --------------------------------------------- @@ -29580,13 +29580,18 @@ Region = PAL-E Compat = 5 --------------------------------------------- Serial = SCES-50006 -Name = Drakan - The Ancients' Gates // aka Drakan 2 +Name = Drakan - The Ancients' Gates // aka "Drakan 2" Region = PAL-M5 -EETimingHack = 1 //flickery textures +Compat = 5 +EETimingHack = 1 // flickery textures [patches] comment=This gamedisc supports multiple languages. comment=Language selection is done through the BIOS configuration. comment=Implementation requires full boot - "Boot CDVD (full)". + + patch=1,EE,001C2274,word,3C013F7F // 3C013F80 + // Fix by pgert that reduces displaycrap which arises with Resolution Scaling + // around the Health & Mana bars. Improvement someone? [/patches] --------------------------------------------- Serial = SCES-50009 @@ -30350,8 +30355,17 @@ Region = PAL-Unk --------------------------------------------- Serial = SCES-52677 Name = Network Access Disc & Hardware - Online Arena -Region = PAL-Unk -Compat = 4 +Region = PAL-Unk // Portuguese * Dutch * Italian * German * Spanish * French * English * Japanese +Compat = 5 +[patches] + comment=- This gamedisc supports multiple languages and widescreen. + comment=- Language & widescreen selection is done through the BIOS configuration. + comment=- Implementation requires full boot - "Boot CDVD (full)". + comment=- + comment=- Using GSdx, this gamedisc crashes in gamemenu with SW-mode, + comment=- and have no 3D display with HW-mode. + comment=- Playable by toggling between HW-mode (in menu) and SW-mode (in game). +[/patches] --------------------------------------------- Serial = SCES-52748 Name = EyeToy - Play 2 @@ -31704,8 +31718,13 @@ Compat = 4 --------------------------------------------- Serial = SLES-50211 Name = Gauntlet - Dark Legacy -Region = PAL-Unk +Region = PAL-Unk // English * French * German Compat = 5 +[patches] + comment=- This gamedisc supports multiple languages. + comment=- Language selection is done through the BIOS configuration. + comment=- Implementation requires full boot - "Boot CDVD (full)". +[/patches] --------------------------------------------- Serial = SLES-50212 Name = Paris-Dakar Rally @@ -32931,8 +32950,14 @@ Region = PAL-Unk --------------------------------------------- Serial = SLES-50821 Name = Project Zero -Region = PAL-Unk +Region = PAL-M5 Compat = 5 +[patches] + comment=- This gamedisc only lets you choose language once, + comment=- whereafter it stores that setting in the memcard. + comment=- To change the language you actually have to erase + comment=- the memcard content for the game. +[/patches] --------------------------------------------- Serial = SLES-50822 Name = Shadow Hearts @@ -33808,10 +33833,16 @@ Region = PAL-Unk Compat = 5 --------------------------------------------- Serial = SLES-51227 -Name = Tomb Raider - Angel of Darkness +Name = Tomb Raider - Angel of Darkness // aka "TRAOD" Region = PAL-Unk Compat = 5 OPHFlagHack = 1 +[patches] + comment=- This gamedisc supports multiple languages and widescreen. + comment=- Language & widescreen selection is done through the BIOS configuration. + comment=- Implementation requires full boot - "Boot CDVD (full)". + comment=- Full boot is recommended anyway for this gamedisc to avoid textproblems. +[/patches] --------------------------------------------- Serial = SLES-51229 Name = Virtua Cop - Elite Edition @@ -35662,6 +35693,12 @@ Compat = 3 Serial = SLES-52149 Name = Tom Clancy's Splinter Cell - Pandora Tomorrow Region = PAL-Unk +Compat = 5 +[patches] + comment=- This gamedisc supports multiple languages. + comment=- Language selection is done through the BIOS configuration. + comment=- Implementation requires full boot - "Boot CDVD (full)". +[/patches] --------------------------------------------- Serial = SLES-52150 Name = Legacy of Kain - Defiance @@ -35961,7 +35998,7 @@ Region = PAL-Unk --------------------------------------------- Serial = SLES-52325 Name = Champions of Norrath - Realms of EverQuest -Region = PAL-Unk +Region = PAL-Unk // English * French * German --------------------------------------------- Serial = SLES-52326 Name = Spawn - Armageddon @@ -37538,8 +37575,13 @@ Region = PAL-Unk --------------------------------------------- Serial = SLES-53007 Name = Tom Clancy's Splinter Cell - Chaos Theory -Region = PAL-M5 +Region = PAL-Unk Compat = 5 +[patches] + comment=- This gamedisc supports multiple languages. + comment=- Language selection is done through the BIOS configuration. + comment=- Implementation requires full boot - "Boot CDVD (full)". +[/patches] --------------------------------------------- Serial = SLES-53011 Name = Gallop Racer 2 @@ -37645,7 +37687,7 @@ Compat = 5 eeRoundMode = 0 --------------------------------------------- Serial = SLES-53039 -Name = Champions - Return to Arms // aka Champions of Norrath 2 +Name = Champions - Return to Arms // aka "Champions of Norrath 2" Region = PAL-Unk Compat = 4 --------------------------------------------- @@ -37923,7 +37965,12 @@ Region = PAL-Unk --------------------------------------------- Serial = SLES-53154 Name = Bard's Tale -Region = PAL-Unk +Region = PAL-Unk // English * Spanish * Italian * French * German * Japanese * Korean * Chinese +[patches] + comment=- This gamedisc supports multiple languages. + comment=- Language selection is done through the BIOS configuration. + comment=- Implementation requires full boot - "Boot CDVD (full)". +[/patches] --------------------------------------------- Serial = SLES-53155 Name = Star Wars - Episode III - Revenge of the Sith @@ -38900,7 +38947,13 @@ Region = PAL-E --------------------------------------------- Serial = SLES-53667 Name = Gauntlet - Seven Sorrows -Region = PAL-Unk +Region = PAL-M5 +Compat = 5 +[patches] + comment=- This gamedisc supports multiple languages. + comment=- Language selection is done through the BIOS configuration. + comment=- Implementation requires full boot - "Boot CDVD (full)". +[/patches] --------------------------------------------- Serial = SLES-53668 Name = Micro Machines v4 @@ -39237,6 +39290,12 @@ Compat = 5 Serial = SLES-53826 Name = Tom Clancy's Splinter Cell - Double Agent Region = PAL-Unk +Compat = 5 +[patches] + comment=- This gamedisc supports multiple languages. + comment=- Language selection is done through the BIOS configuration. + comment=- Implementation requires full boot - "Boot CDVD (full)". +[/patches] --------------------------------------------- Serial = SLES-53827 Name = Tom Clancy's Splinter Cell - Double Agent @@ -39399,8 +39458,13 @@ Region = PAL-Unk --------------------------------------------- Serial = SLES-53908 Name = Tomb Raider - Legend -Region = PAL-Unk +Region = PAL-Unk // English * French * German * Italian * Spanish * Japanese * Portugese * Polish Compat = 5 +[patches] + comment=- This gamedisc supports multiple languages. + comment=- Language selection is done through the BIOS configuration. + comment=- Implementation requires full boot - "Boot CDVD (full)". +[/patches] --------------------------------------------- Serial = SLES-53909 Name = Full Spectrum Warrior - Ten Hammers @@ -39970,17 +40034,17 @@ Region = PAL-R --------------------------------------------- Serial = SLES-54185 Name = Dirge of Cerberus - Final Fantasy VII -Region = PAL-E +Region = PAL-Unk Compat = 5 [patches = 33F7D21A] - - //comment=patches by nachbrenner - - //override sceScfGetLanguage - //patch=0,EE,002486d8,word,24020000 //japanese - //patch=0,EE,002486d8,word,24020001 //english - //patch=0,EE,002486d8,word,24020004 //german - + comment=- This gamedisc supports multiple languages. + comment=- Language selection is done through the BIOS configuration. + comment=- Implementation requires full boot - "Boot CDVD (full)". + + // Override sceScfGetLanguage patches by nachbrenner: + // patch=0,EE,002486d8,word,24020000 // japanese + // patch=0,EE,002486d8,word,24020001 // english + // patch=0,EE,002486d8,word,24020004 // german [/patches] --------------------------------------------- Serial = SLES-54186 @@ -40874,7 +40938,13 @@ Region = PAL-M11 --------------------------------------------- Serial = SLES-54674 Name = Lara Croft Tomb Raider - Anniversary -Region = PAL-M5 +Region = PAL-Unk // English * French * German * Italian * Spanish * Japanese * Portugese * Polish * Russian * Czech +Compat = 5 +[patches] + comment=- This gamedisc supports multiple languages. + comment=- Language selection is done through the BIOS configuration. + comment=- Implementation requires full boot - "Boot CDVD (full)". +[/patches] --------------------------------------------- Serial = SLES-54675 Name = Street Warrior @@ -41707,8 +41777,13 @@ Region = PAL-M5 --------------------------------------------- Serial = SLES-55442 Name = Tomb Raider Underworld -Region = PAL-M5 +Region = PAL-Unk // English * French * German * Italian * Spanish * Japanese * Portugese * Polish * Russian * Czech * Dutch Compat = 5 +[patches] + comment=- This gamedisc supports multiple languages. + comment=- Language selection is done through the BIOS configuration. + comment=- Implementation requires full boot - "Boot CDVD (full)". +[/patches] --------------------------------------------- Serial = SLES-55443 Name = Mana Khemia - Alchemists of Al-Revis From 6bfcf433db0e0dfa3d2f537f2292b707b1b2dc0b Mon Sep 17 00:00:00 2001 From: "avihal@gmail.com" Date: Sat, 27 Apr 2013 16:24:02 +0000 Subject: [PATCH 72/81] (Patch by KrossX): Fixed multitap (e.g. Timesplitters), New: support raw PSX memcards (mcd/mcr), Fixed issues with pad 2 (e.g. issue 1326). - Also, I slightly modified the default column widths at the memory card config panel. - Tip: If the column widths are resized, the new widths will get saved after clicking OK/Apply, but NOT if clicking Cancel or closing the window with [X]. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5622 96395faa-99c1-11dd-bbfe-3dabce05a288 --- common/include/PluginCallbacks.h | 8 ++++++++ pcsx2/PluginManager.cpp | 5 +++++ pcsx2/Plugins.h | 1 + pcsx2/gui/MemoryCardFile.cpp | 12 ++++++++++++ pcsx2/gui/Panels/MemoryCardListPanel.cpp | 23 ++++++++++++++++++++--- pcsx2/gui/Panels/MemoryCardListView.cpp | 15 +++++++++------ pcsx2/gui/Panels/MemoryCardPanels.h | 2 ++ 7 files changed, 57 insertions(+), 9 deletions(-) diff --git a/common/include/PluginCallbacks.h b/common/include/PluginCallbacks.h index ccb3159b3..c2049e376 100644 --- a/common/include/PluginCallbacks.h +++ b/common/include/PluginCallbacks.h @@ -1058,6 +1058,14 @@ typedef struct _PS2E_ComponentAPI_Mcd // void (PS2E_CALLBACK* McdGetSizeInfo)( PS2E_THISPTR thisptr, uint port, uint slot, PS2E_McdSizeInfo* outways ); + // McdIsPSX + // Checks if the memorycard is a PSX one from the Mcd provider. + // + // Returns: + // False: PS2, True: PSX + // + bool (PS2E_CALLBACK* McdIsPSX)( PS2E_THISPTR thisptr, uint port, uint slot ); + // McdRead // Requests that a block of data be loaded from the memorycard into the specified dest // buffer (which is allocated by the caller). Bytes read should match the requested diff --git a/pcsx2/PluginManager.cpp b/pcsx2/PluginManager.cpp index 1166fca2c..5a76a0aa8 100644 --- a/pcsx2/PluginManager.cpp +++ b/pcsx2/PluginManager.cpp @@ -43,6 +43,11 @@ void SysPluginBindings::McdGetSizeInfo( uint port, uint slot, PS2E_McdSizeInfo& Mcd->McdGetSizeInfo( (PS2E_THISPTR) Mcd, port, slot, &outways ); } +bool SysPluginBindings::McdIsPSX( uint port, uint slot ) +{ + return Mcd->McdIsPSX( (PS2E_THISPTR) Mcd, port, slot ); +} + void SysPluginBindings::McdRead( uint port, uint slot, u8 *dest, u32 adr, int size ) { Mcd->McdRead( (PS2E_THISPTR) Mcd, port, slot, dest, adr, size ); diff --git a/pcsx2/Plugins.h b/pcsx2/Plugins.h index 678198909..87f9505f3 100644 --- a/pcsx2/Plugins.h +++ b/pcsx2/Plugins.h @@ -236,6 +236,7 @@ public: bool McdIsPresent( uint port, uint slot ); void McdGetSizeInfo( uint port, uint slot, PS2E_McdSizeInfo& outways ); + bool McdIsPSX( uint port, uint slot ); void McdRead( uint port, uint slot, u8 *dest, u32 adr, int size ); void McdSave( uint port, uint slot, const u8 *src, u32 adr, int size ); void McdEraseBlock( uint port, uint slot, u32 adr ); diff --git a/pcsx2/gui/MemoryCardFile.cpp b/pcsx2/gui/MemoryCardFile.cpp index 57662bddf..a5908934a 100644 --- a/pcsx2/gui/MemoryCardFile.cpp +++ b/pcsx2/gui/MemoryCardFile.cpp @@ -64,6 +64,7 @@ public: s32 IsPresent ( uint slot ); void GetSizeInfo( uint slot, PS2E_McdSizeInfo& outways ); + bool IsPSX ( uint slot ); s32 Read ( uint slot, u8 *dest, u32 adr, int size ); s32 Save ( uint slot, const u8 *src, u32 adr, int size ); s32 EraseBlock ( uint slot, u32 adr ); @@ -266,6 +267,11 @@ void FileMemoryCard::GetSizeInfo( uint slot, PS2E_McdSizeInfo& outways ) outways.McdSizeInSectors = 0x4000; } +bool FileMemoryCard::IsPSX( uint slot ) +{ + return m_file[slot].Length() == 0x20000; +} + s32 FileMemoryCard::Read( uint slot, u8 *dest, u32 adr, int size ) { wxFFile& mcfp( m_file[slot] ); @@ -379,6 +385,11 @@ static void PS2E_CALLBACK FileMcd_GetSizeInfo( PS2E_THISPTR thisptr, uint port, thisptr->impl.GetSizeInfo( FileMcd_ConvertToSlot( port, slot ), *outways ); } +static bool PS2E_CALLBACK FileMcd_IsPSX( PS2E_THISPTR thisptr, uint port, uint slot ) +{ + return thisptr->impl.IsPSX( FileMcd_ConvertToSlot( port, slot ) ); +} + static s32 PS2E_CALLBACK FileMcd_Read( PS2E_THISPTR thisptr, uint port, uint slot, u8 *dest, u32 adr, int size ) { return thisptr->impl.Read( FileMcd_ConvertToSlot( port, slot ), dest, adr, size ); @@ -408,6 +419,7 @@ Component_FileMcd::Component_FileMcd() api.McdIsPresent = FileMcd_IsPresent; api.McdGetSizeInfo = FileMcd_GetSizeInfo; + api.McdIsPSX = FileMcd_IsPSX; api.McdRead = FileMcd_Read; api.McdSave = FileMcd_Save; api.McdEraseBlock = FileMcd_EraseBlock; diff --git a/pcsx2/gui/Panels/MemoryCardListPanel.cpp b/pcsx2/gui/Panels/MemoryCardListPanel.cpp index 3269ab4dd..728285abf 100644 --- a/pcsx2/gui/Panels/MemoryCardListPanel.cpp +++ b/pcsx2/gui/Panels/MemoryCardListPanel.cpp @@ -35,13 +35,18 @@ using namespace Panels; static bool IsMcdFormatted( wxFFile& fhand ) { + static const char formatted_psx[] = "MC"; static const char formatted_string[] = "Sony PS2 Memory Card Format"; static const int fmtstrlen = sizeof( formatted_string )-1; char dest[fmtstrlen]; fhand.Read( dest, fmtstrlen ); - return memcmp( formatted_string, dest, fmtstrlen ) == 0; + + bool formatted = memcmp( formatted_string, dest, fmtstrlen ) == 0; + if(!formatted) formatted = memcmp( formatted_psx, dest, 2 ) == 0; + + return formatted; } //sets IsPresent if the file is valid, and derived properties (filename, formatted, size, etc) @@ -56,7 +61,10 @@ bool EnumerateMemoryCard( McdSlotItem& dest, const wxFileName& filename, const w //DevCon.WriteLn( fullpath ); wxFFile mcdFile( fullpath ); if( !mcdFile.IsOpened() ) return false; // wx should log the error for us. - if( mcdFile.Length() < (1024*528) ) + + wxFileOffset length = mcdFile.Length(); + + if( length < (1024*528) && length != 0x20000 ) { Console.Warning( "... MemoryCard appears to be truncated. Ignoring." ); return false; @@ -67,7 +75,14 @@ bool EnumerateMemoryCard( McdSlotItem& dest, const wxFileName& filename, const w if( filename.GetFullPath() == (basePath+filename.GetFullName()).GetFullPath() ) dest.Filename = filename.GetFullName(); - dest.SizeInMB = (uint)(mcdFile.Length() / (1024 * 528 * 2)); + dest.SizeInMB = (uint)(length / (1024 * 528 * 2)); + + if(length == 0x20000) + { + dest.IsPSX = true; // PSX memcard; + dest.SizeInMB = 1; // MegaBIT + } + dest.IsFormatted = IsMcdFormatted( mcdFile ); filename.GetTimes( NULL, &dest.DateModified, &dest.DateCreated ); @@ -1082,6 +1097,8 @@ void Panels::MemoryCardListPanel_Simple::ReadFilesAtMcdFolder(){ wxArrayString memcardList; wxDir::GetAllFiles(m_FolderPicker->GetPath().ToString(), &memcardList, L"*.ps2", wxDIR_FILES); + wxDir::GetAllFiles(m_FolderPicker->GetPath().ToString(), &memcardList, L"*.mcd", wxDIR_FILES); + wxDir::GetAllFiles(m_FolderPicker->GetPath().ToString(), &memcardList, L"*.mcr", wxDIR_FILES); for(uint i = 0; i < memcardList.size(); i++) { McdSlotItem currentCardFile; diff --git a/pcsx2/gui/Panels/MemoryCardListView.cpp b/pcsx2/gui/Panels/MemoryCardListView.cpp index 0590ab616..40edf7ffb 100644 --- a/pcsx2/gui/Panels/MemoryCardListView.cpp +++ b/pcsx2/gui/Panels/MemoryCardListView.cpp @@ -76,6 +76,7 @@ enum McdColumnType_Simple McdColS_Filename, McdColS_Size, McdColS_Formatted, + McdColS_Type, McdColS_DateModified, McdColS_DateCreated, McdColS_Count @@ -102,13 +103,14 @@ const ListViewColumnInfo& MemoryCardListView_Simple::GetDefaultColumnInfo( uint { static const ListViewColumnInfo columns[] = { - { _("PS2 Port") , 154 , wxLIST_FORMAT_LEFT }, + { _("PS2 Port") , 170 , wxLIST_FORMAT_LEFT }, //{ _("Port status") , 80 , wxLIST_FORMAT_LEFT }, - { _("Card (file) name") , 126 , wxLIST_FORMAT_LEFT }, - { _("Card size") , 60 , wxLIST_FORMAT_LEFT }, + { _("Card (file) name") , 145 , wxLIST_FORMAT_LEFT }, + { _("Card size") , 65 , wxLIST_FORMAT_LEFT }, { _("Formatted") , 80 , wxLIST_FORMAT_LEFT }, - { _("Last Modified"), 85 , wxLIST_FORMAT_LEFT }, - { _("Created on") , 85 , wxLIST_FORMAT_LEFT }, + { _("Type") , 60 , wxLIST_FORMAT_LEFT }, + { _("Last Modified"), 90 , wxLIST_FORMAT_LEFT }, + { _("Created on") , 90 , wxLIST_FORMAT_LEFT }, }; pxAssertDev( idx < ArraySize(columns), "ListView column index is out of bounds." ); @@ -152,8 +154,9 @@ wxString MemoryCardListView_Simple::OnGetItemText(long item, long column) const return prefix + res; } */ - case McdColS_Size: return prefix + ( !it.IsPresent ? L"" : pxsFmt( L"%u MB", it.SizeInMB ) ); + case McdColS_Size: return prefix + ( !it.IsPresent ? L"" : (it.IsPSX? pxsFmt( L"%u MBit", it.SizeInMB ) : pxsFmt( L"%u MiB", it.SizeInMB )) ); case McdColS_Formatted: return prefix + ( !it.IsPresent ? L"" : ( it.IsFormatted ? _("Yes") : _("No")) ); + case McdColS_Type: return prefix + ( !it.IsPresent ? L"" : ( it.IsPSX? _("PSX") : _("PS2")) ); case McdColS_DateModified: return prefix + ( !it.IsPresent ? L"" : it.DateModified.FormatDate() ); case McdColS_DateCreated: return prefix + ( !it.IsPresent ? L"" : it.DateCreated.FormatDate() ); diff --git a/pcsx2/gui/Panels/MemoryCardPanels.h b/pcsx2/gui/Panels/MemoryCardPanels.h index f46200728..826ae3894 100644 --- a/pcsx2/gui/Panels/MemoryCardPanels.h +++ b/pcsx2/gui/Panels/MemoryCardPanels.h @@ -44,6 +44,7 @@ struct McdSlotItem //Only meaningful when IsPresent==true (a file exists for this item): wxFileName Filename; // full pathname bool IsFormatted; + bool IsPSX; // False: PS2 memory card, True: PSX memory card uint SizeInMB; // size, in megabytes! wxDateTime DateCreated; wxDateTime DateModified; @@ -62,6 +63,7 @@ struct McdSlotItem { Slot = -1; + IsPSX = false; IsPresent = false; IsEnabled = false; } From 4548e916faa7980871d4cdb1591ae4384e688b31 Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Mon, 29 Apr 2013 21:46:04 +0000 Subject: [PATCH 73/81] GameDB: Entries for Mafia and True Crime - New York. Helps with bad textures in True Crime, not sure what it's needed for in Mafia but apparently it is (was already present on NTSC version) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5623 96395faa-99c1-11dd-bbfe-3dabce05a288 --- bin/GameIndex.dbf | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/bin/GameIndex.dbf b/bin/GameIndex.dbf index 70dce1fdd..a3eec58e2 100644 --- a/bin/GameIndex.dbf +++ b/bin/GameIndex.dbf @@ -6559,6 +6559,7 @@ Serial = SLUS-21106 Name = True Crime - New York City Region = NTSC-U Compat = 4 +EETimingHack = 1 //Bad Textures (Possibly needs SW Mode too) --------------------------------------------- Serial = SLUS-21107 Name = X-Men - The Official Game @@ -22144,6 +22145,7 @@ Region = NTSC-J Serial = SLPM-66473 Name = True Crime - New York City Region = NTSC-J +EETimingHack = 1 //Bad Textures (Possibly needs SW Mode too) --------------------------------------------- Serial = SLPM-66474 Name = Odin Sphere @@ -24372,6 +24374,7 @@ eeRoundMode = 0 Serial = SLPM-74243 Name = True Crime - New York City [PlayStation 2 the Best] Region = NTSC-J +EETimingHack = 1 //Bad Textures (Possibly needs SW Mode too) --------------------------------------------- Serial = SLPM-74244 Name = Phantasy Star Universe [PlayStation 2 the Best] @@ -35898,14 +35901,17 @@ Compat = 4 Serial = SLES-52278 Name = Mafia Region = PAL-Unk +EETimingHack = 1 --------------------------------------------- Serial = SLES-52279 Name = Mafia Region = PAL-Unk +EETimingHack = 1 --------------------------------------------- Serial = SLES-52280 Name = Mafia Region = PAL-Unk +EETimingHack = 1 --------------------------------------------- Serial = SLES-52282 Name = Mafia @@ -38860,10 +38866,12 @@ Compat = 5 Serial = SLES-53616 Name = True Crime - New York City Region = PAL-Unk +EETimingHack = 1 //Bad Textures (Possibly needs SW Mode too) --------------------------------------------- Serial = SLES-53618 Name = True Crime - New York City Region = PAL-Unk +EETimingHack = 1 //Bad Textures (Possibly needs SW Mode too) --------------------------------------------- Serial = SLES-53621 Name = Wallace & Grommit - The Curse of the Were Rabbit From 43fb0a9a5e5a966ab6b52f1be53d4ef4bae3c59e Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Wed, 1 May 2013 16:02:11 +0000 Subject: [PATCH 74/81] linux various: * Try to launch dev/debug version when pcsx2 isn't found * remove svn metadata from the linux tarball * Add libaio on the cmake dependency message git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5624 96395faa-99c1-11dd-bbfe-3dabce05a288 --- bin/launch_pcsx2_linux.sh | 8 +++++++- cmake/SelectPcsx2Plugins.cmake | 2 +- .../create_pcsx2_tarball_from_svn_repository.sh | 2 ++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/bin/launch_pcsx2_linux.sh b/bin/launch_pcsx2_linux.sh index f18241ea8..6a3681dbb 100755 --- a/bin/launch_pcsx2_linux.sh +++ b/bin/launch_pcsx2_linux.sh @@ -72,9 +72,15 @@ then fi # Launch PCSX2 -if [ -x pcsx2 ] +if [ -x "pcsx2" ] then ./pcsx2 $@ +elif [ -x "pcsx2-dev" ] +then + ./pcsx2-dev $@ +elif [ -x "pcsx2-dbg" ] +then + ./pcsx2-dbg $@ else echo "Error PCSX2 not found" echo "Maybe the script was directly 'called'" diff --git a/cmake/SelectPcsx2Plugins.cmake b/cmake/SelectPcsx2Plugins.cmake index a097c60c9..101c49356 100644 --- a/cmake/SelectPcsx2Plugins.cmake +++ b/cmake/SelectPcsx2Plugins.cmake @@ -1,7 +1,7 @@ #------------------------------------------------------------------------------- # Dependency message print #------------------------------------------------------------------------------- -set(msg_dep_common_libs "check these libraries -> wxWidgets (>=2.8.10), sparsehash (>=1.5)") +set(msg_dep_common_libs "check these libraries -> wxWidgets (>=2.8.10), sparsehash (>=1.5), aio") set(msg_dep_pcsx2 "check these libraries -> wxWidgets (>=2.8.10), gtk2 (>=2.16), zlib (>=1.2.4), pcsx2 common libs") set(msg_dep_cdvdiso "check these libraries -> bzip2 (>=1.0.5), gtk2 (>=2.16)") set(msg_dep_zerogs "check these libraries -> glew (>=1.6), opengl, X11, nvidia-cg-toolkit (>=2.1)") diff --git a/debian-unstable-upstream/create_pcsx2_tarball_from_svn_repository.sh b/debian-unstable-upstream/create_pcsx2_tarball_from_svn_repository.sh index 6f81365eb..3f8aab00c 100755 --- a/debian-unstable-upstream/create_pcsx2_tarball_from_svn_repository.sh +++ b/debian-unstable-upstream/create_pcsx2_tarball_from_svn_repository.sh @@ -136,6 +136,8 @@ echo "Copy the subversion repository to a temporary directory" rm -fr $NEW_DIR cp -r $ROOT_DIR $NEW_DIR +echo "Remove .svn directories" +find $NEW_DIR -name ".svn" -type d -exec rm -fr {} \; 2> /dev/null echo "Remove windows files (useless & potential copyright issues)" # => pcsx2/windows # Copyright header must be updated From c51f8cae54aafb93e64844cfd1eae44fb6cfa84a Mon Sep 17 00:00:00 2001 From: "refraction@gmail.com" Date: Thu, 2 May 2013 13:51:55 +0000 Subject: [PATCH 75/81] GameDB: Re-enable the Neo Contra IPU patch on the EE and USA versions as they were in 1.0.0, seems it still needs it. Removed the True Crime EE Timing Fix, apparently it doesn't need it! Software mode and SuperVU is enough. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5625 96395faa-99c1-11dd-bbfe-3dabce05a288 --- bin/GameIndex.dbf | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/bin/GameIndex.dbf b/bin/GameIndex.dbf index a3eec58e2..cb32a49e8 100644 --- a/bin/GameIndex.dbf +++ b/bin/GameIndex.dbf @@ -5890,8 +5890,8 @@ Compat = 4 //patch=0,EE,003a9538,word,03e00008 //patch=0,EE,003a953c,word,00000000 - //patch=0,EE,003a9460,word,03e00008 - //patch=0,EE,003a9464,word,00000000 + patch=0,EE,003a9460,word,03e00008 + patch=0,EE,003a9464,word,00000000 [/patches] --------------------------------------------- @@ -6559,7 +6559,6 @@ Serial = SLUS-21106 Name = True Crime - New York City Region = NTSC-U Compat = 4 -EETimingHack = 1 //Bad Textures (Possibly needs SW Mode too) --------------------------------------------- Serial = SLUS-21107 Name = X-Men - The Official Game @@ -22145,7 +22144,6 @@ Region = NTSC-J Serial = SLPM-66473 Name = True Crime - New York City Region = NTSC-J -EETimingHack = 1 //Bad Textures (Possibly needs SW Mode too) --------------------------------------------- Serial = SLPM-66474 Name = Odin Sphere @@ -24374,7 +24372,6 @@ eeRoundMode = 0 Serial = SLPM-74243 Name = True Crime - New York City [PlayStation 2 the Best] Region = NTSC-J -EETimingHack = 1 //Bad Textures (Possibly needs SW Mode too) --------------------------------------------- Serial = SLPM-74244 Name = Phantasy Star Universe [PlayStation 2 the Best] @@ -36360,10 +36357,10 @@ Compat = 4 //comment=Patches By Nachbrenner //fix IPU busy! ingame - //patch=0,EE,003a9a88,word,03e00008 - //patch=0,EE,003a9a8c,word,00000000 - //patch=0,EE,003a9b60,word,03e00008 - //patch=0,EE,003a9b64,word,00000000 + patch=0,EE,003a9a88,word,03e00008 + patch=0,EE,003a9a8c,word,00000000 + patch=0,EE,003a9b60,word,03e00008 + patch=0,EE,003a9b64,word,00000000 [/patches] --------------------------------------------- @@ -38866,12 +38863,10 @@ Compat = 5 Serial = SLES-53616 Name = True Crime - New York City Region = PAL-Unk -EETimingHack = 1 //Bad Textures (Possibly needs SW Mode too) --------------------------------------------- Serial = SLES-53618 Name = True Crime - New York City Region = PAL-Unk -EETimingHack = 1 //Bad Textures (Possibly needs SW Mode too) --------------------------------------------- Serial = SLES-53621 Name = Wallace & Grommit - The Curse of the Were Rabbit From 320d3a572e18cb5c558a61eb772acb70469b7924 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Wed, 8 May 2013 15:51:42 +0000 Subject: [PATCH 76/81] gsdx ogl: AMD fix some bugs in their driver ! (catalyst 13.4 branch). Let's remove some buggy workaround now. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5627 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSDeviceOGL.cpp | 48 ----------------------------------- plugins/GSdx/GSDeviceOGL.h | 2 -- plugins/GSdx/GSTextureOGL.cpp | 2 -- plugins/GSdx/res/tfx.glsl | 5 +--- 4 files changed, 1 insertion(+), 56 deletions(-) diff --git a/plugins/GSdx/GSDeviceOGL.cpp b/plugins/GSdx/GSDeviceOGL.cpp index 64197f82e..dae4b5d5d 100644 --- a/plugins/GSdx/GSDeviceOGL.cpp +++ b/plugins/GSdx/GSDeviceOGL.cpp @@ -1262,40 +1262,6 @@ void GSDeviceOGL::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVecto } } -// AMD drivers fail to support correctly the setting of index in fragment shader (layout statement in glsl)... -// So instead to use directly glCreateShaderProgramv, you need to emulate the function and manually set -// the index in the fragment shader. -GLuint GSDeviceOGL::glCreateShaderProgramv_AMD_BUG_WORKAROUND(GLenum type, GLsizei count, const char ** strings) -{ - const GLuint shader = glCreateShader(type); - if (shader) { - glShaderSource(shader, count, strings, NULL); - glCompileShader(shader); - const GLuint program = glCreateProgram(); - if (program) { - GLint compiled = GL_FALSE; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); - glProgramParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE); - if (compiled) { - glAttachShader(program, shader); - // HACK TO SET CORRECTLY THE INDEX - if (type == GL_FRAGMENT_SHADER) { - glBindFragDataLocationIndexed(program, 0, 0, "SV_Target0"); - glBindFragDataLocationIndexed(program, 0, 1, "SV_Target1"); - } - // END OF HACK - glLinkProgram(program); - glDetachShader(program, shader); - } - /* append-shader-info-log-to-program-info-log */ - } - glDeleteShader(shader); - return program; - } else { - return 0; - } -} - void GSDeviceOGL::CompileShaderFromSource(const std::string& glsl_file, const std::string& entry, GLenum type, GLuint* program, const std::string& macro_sel) { // ***************************************************** @@ -1381,20 +1347,6 @@ void GSDeviceOGL::CompileShaderFromSource(const std::string& glsl_file, const st *program = glCreateShaderProgramv(type, 2, sources_array); #endif - // Check the correctness of the (AMD) driver - // Note: glGetFragDataLocation crash too!!! Catalyst 12.10 (and later) => HD 5XXX,6XXX !!! - if (theApp.GetConfig("renderer", 0) == 12) { - GLint slot = glGetFragDataLocation(*program, "SV_Target1"); - if (slot == 0) { // <=> SV_Target1 used same slot as SV_Target0 - GLint index = glGetFragDataIndex(*program, "SV_Target1"); - if (index != 1) { - fprintf(stderr, "Driver bug: failed to set the index, program will be recompiled\n"); - glDeleteProgram(*program); - *program = glCreateShaderProgramv_AMD_BUG_WORKAROUND(type, 2, sources_array); - } - } - } - free(source_str); free(header_str); free(sources_array); diff --git a/plugins/GSdx/GSDeviceOGL.h b/plugins/GSdx/GSDeviceOGL.h index 697c9e6da..ad18b5624 100644 --- a/plugins/GSdx/GSDeviceOGL.h +++ b/plugins/GSdx/GSDeviceOGL.h @@ -656,6 +656,4 @@ class GSDeviceOGL : public GSDevice void SetupGS(GSSelector sel); void SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel); void SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix); - - GLuint glCreateShaderProgramv_AMD_BUG_WORKAROUND(GLenum type, GLsizei count, const char ** strings); }; diff --git a/plugins/GSdx/GSTextureOGL.cpp b/plugins/GSdx/GSTextureOGL.cpp index d21055d69..3c5bc47eb 100644 --- a/plugins/GSdx/GSTextureOGL.cpp +++ b/plugins/GSdx/GSTextureOGL.cpp @@ -19,8 +19,6 @@ * */ -#pragma once - #include #include "GSTextureOGL.h" static int g_state_texture_unit = -1; diff --git a/plugins/GSdx/res/tfx.glsl b/plugins/GSdx/res/tfx.glsl index f25ba617a..e6f87aff2 100644 --- a/plugins/GSdx/res/tfx.glsl +++ b/plugins/GSdx/res/tfx.glsl @@ -153,10 +153,7 @@ out gl_PerVertex { float gl_ClipDistance[]; }; -// FIXME -// AMD Driver bug again !!!! -//layout(location = 0) in vertex GSin[]; -in vertex GSin[]; +layout(location = 0) in vertex GSin[]; layout(location = 0) out vertex GSout; From b9bb7647494dfcfd025a17d7cf78649a79c93157 Mon Sep 17 00:00:00 2001 From: "ramapcsx2.code" Date: Fri, 17 May 2013 07:24:31 +0000 Subject: [PATCH 77/81] Moved some stall related logs to DevCon(sole) as games that trigger them will slow down. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5628 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/IPU/IPUdma.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pcsx2/IPU/IPUdma.cpp b/pcsx2/IPU/IPUdma.cpp index 4fbbd99d6..af49d8321 100644 --- a/pcsx2/IPU/IPUdma.cpp +++ b/pcsx2/IPU/IPUdma.cpp @@ -279,15 +279,15 @@ void IPU0dma() case NO_STD: break; case STD_GIF: // GIF - Console.Warning("GIFSTALL"); + DevCon.Warning("GIFSTALL"); g_nDMATransfer.GIFSTALL = true; break; case STD_VIF1: // VIF - Console.Warning("VIFSTALL"); + DevCon.Warning("VIFSTALL"); g_nDMATransfer.VIFSTALL = true; break; case STD_SIF1: - Console.Warning("SIFSTALL"); + DevCon.Warning("SIFSTALL"); g_nDMATransfer.SIFSTALL = true; break; } @@ -402,7 +402,7 @@ void ipu0Interrupt() if (g_nDMATransfer.GIFSTALL) { // gif - Console.Warning("IPU GIF Stall"); + DevCon.Warning("IPU GIF Stall"); g_nDMATransfer.GIFSTALL = false; //if (gif->chcr.STR) GIFdma(); } @@ -410,7 +410,7 @@ void ipu0Interrupt() if (g_nDMATransfer.VIFSTALL) { // vif - Console.Warning("IPU VIF Stall"); + DevCon.Warning("IPU VIF Stall"); g_nDMATransfer.VIFSTALL = false; //if (vif1ch.chcr.STR) dmaVIF1(); } @@ -418,7 +418,7 @@ void ipu0Interrupt() if (g_nDMATransfer.SIFSTALL) { // sif - Console.Warning("IPU SIF Stall"); + DevCon.Warning("IPU SIF Stall"); g_nDMATransfer.SIFSTALL = false; // Not totally sure whether this needs to be done or not, so I'm From 15b255617afd5906f168511d97e060b90e00d861 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Fri, 17 May 2013 16:55:55 +0000 Subject: [PATCH 78/81] gsdx ogl: use immutable texture, it would avoid multiple validation from the driver git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5629 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSDeviceOGL.cpp | 7 +++--- plugins/GSdx/GSTextureOGL.cpp | 40 +++++++++++++---------------------- 2 files changed, 18 insertions(+), 29 deletions(-) diff --git a/plugins/GSdx/GSDeviceOGL.cpp b/plugins/GSdx/GSDeviceOGL.cpp index dae4b5d5d..39a3463c5 100644 --- a/plugins/GSdx/GSDeviceOGL.cpp +++ b/plugins/GSdx/GSDeviceOGL.cpp @@ -1359,13 +1359,12 @@ void GSDeviceOGL::CompileShaderFromSource(const std::string& glsl_file, const st GLint log_length = 0; glGetProgramiv(*program, GL_INFO_LOG_LENGTH, &log_length); if (log_length > 0) { - char* log = (char*)malloc(log_length); - glGetProgramInfoLog(*program, log_length, NULL, log); + char* log = new char[log_length]; + glGetProgramInfoLog(*program, log_length, NULL, log); fprintf(stderr, "%s", log); - free(log); + delete[] log; } fprintf(stderr, "\n"); - } } diff --git a/plugins/GSdx/GSTextureOGL.cpp b/plugins/GSdx/GSTextureOGL.cpp index 3c5bc47eb..88b31ce6f 100644 --- a/plugins/GSdx/GSTextureOGL.cpp +++ b/plugins/GSdx/GSTextureOGL.cpp @@ -63,7 +63,7 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint //FIXME I not sure we need a pixel buffer object. It seems more a texture // glGenBuffers(1, &m_texture_id); // m_texture_target = GL_PIXEL_UNPACK_BUFFER; - // assert(0); + // ASSERT(0); // Note there is also a buffer texture!!! // http://www.opengl.org/wiki/Buffer_Texture // Note: in this case it must use in GLSL @@ -78,6 +78,7 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint case GSTexture::Backbuffer: m_texture_target = 0; m_texture_id = 0; + break; default: break; } @@ -94,45 +95,34 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint // Allocate the buffer switch (m_type) { - case GSTexture::DepthStencil: - EnableUnit(0); - glTexImage2D(m_texture_target, 0, m_format, m_size.x, m_size.y, 0, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, NULL); - break; - case GSTexture::Offscreen: // Allocate a pbo with the texture if (m_format == GL_RGBA8) m_pbo_size = m_size.x * m_size.y * 4; else if (m_format == GL_R16UI) m_pbo_size = m_size.x * m_size.y * 2; else { fprintf(stderr, "wrong texture pixel format :%x\n", m_format); - assert(0); // TODO Later + ASSERT(0); // TODO Later } glBindBuffer(GL_PIXEL_PACK_BUFFER, m_pbo_id); glBufferData(GL_PIXEL_PACK_BUFFER, m_pbo_size, NULL, GL_STREAM_DRAW); glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + ASSERT(!m_msaa); + case GSTexture::DepthStencil: case GSTexture::RenderTarget: case GSTexture::Texture: - // FIXME + // FIXME: check the opensource driver // Howto allocate the texture unit !!! // In worst case the HW renderer seems to use 3 texture unit // For the moment SW renderer only use 1 so don't bother EnableUnit(0); - // Did we need to setup a default sampler of the texture now? - // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - if (m_format == GL_RGBA8) - glTexImage2D(m_texture_target, 0, m_format, m_size.x, m_size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - else if (m_format == GL_R16UI) - glTexImage2D(m_texture_target, 0, m_format, m_size.x, m_size.y, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, NULL); - else if (m_format == GL_R8) - glTexImage2D(m_texture_target, 0, m_format, m_size.x, m_size.y, 0, GL_RED, GL_UNSIGNED_BYTE, NULL); - else { - fprintf(stderr, "wrong texture pixel format :%x\n", m_format); - assert(0); // TODO Later + if (m_msaa) { + ASSERT(m_texture_target == GL_TEXTURE_2D_MULTISAMPLE); + // Require a recent GLEW and GL4.3 + //glTexStorage2DMultisample(m_texture_target, msaa_level, m_format, m_size.x, m_size.y, false); + } else { + glTexStorage2D(m_texture_target, 1, m_format, m_size.x, m_size.y); } break; default: break; @@ -155,7 +145,7 @@ void GSTextureOGL::Attach(GLenum attachment) bool GSTextureOGL::Update(const GSVector4i& r, const void* data, int pitch) { - if (m_type == GSTexture::DepthStencil || m_type == GSTexture::Offscreen) assert(0); + if (m_type == GSTexture::DepthStencil || m_type == GSTexture::Offscreen) ASSERT(0); // FIXME warning order of the y axis // FIXME I'm not confident with GL_UNSIGNED_BYTE type @@ -176,7 +166,7 @@ bool GSTextureOGL::Update(const GSVector4i& r, const void* data, int pitch) glTexSubImage2D(m_texture_target, 0, r.x, r.y, r.width(), r.height(), GL_RED, GL_R8, data); else { fprintf(stderr, "wrong texture pixel format :%x\n", m_format); - assert(0); + ASSERT(0); } #if 0 //if (m_size.x != 16) @@ -256,7 +246,7 @@ bool GSTextureOGL::Map(GSMap& m, const GSVector4i* r) glReadPixels(0, 0, m_size.x, m_size.y, GL_RED, GL_UNSIGNED_BYTE, 0); } else { fprintf(stderr, "wrong texture pixel format :%x\n", m_format); - assert(0); + ASSERT(0); } glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); From a163677cece081a713e560ece2cb9eb8370251f9 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Fri, 17 May 2013 18:28:51 +0000 Subject: [PATCH 79/81] gsdx ogl: New config option to disable separate shader program. Not enabled by default * workaround AMD driver bleding issue (got at least a nice rendering in GoW) * would run on the opensource driver when they support geometry shader Stil got some crash on the driver. Arg!!! FGLRX user if you want to do some trials uncomment #define DISABLE_GL41_SSO in GSdx/config.h git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5630 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSDeviceOGL.cpp | 76 +++++++++++++++++++++++++++++++++++- plugins/GSdx/GSDeviceOGL.h | 6 +++ plugins/GSdx/config.h | 4 ++ 3 files changed, 84 insertions(+), 2 deletions(-) diff --git a/plugins/GSdx/GSDeviceOGL.cpp b/plugins/GSdx/GSDeviceOGL.cpp index 39a3463c5..17aafb512 100644 --- a/plugins/GSdx/GSDeviceOGL.cpp +++ b/plugins/GSdx/GSDeviceOGL.cpp @@ -611,12 +611,56 @@ static void set_uniform_buffer_binding(GLuint prog, GLchar* name, GLuint binding } #endif +#ifdef DISABLE_GL41_SSO +GLuint GSDeviceOGL::link_prog() +{ + GLuint single_prog = glCreateProgram(); + if (m_state.vs) glAttachShader(single_prog, m_state.vs); + if (m_state.ps) glAttachShader(single_prog, m_state.ps); + if (m_state.gs) glAttachShader(single_prog, m_state.gs); + + glLinkProgram(single_prog); + + GLint status; + glGetProgramiv(single_prog, GL_LINK_STATUS, &status); + if (!status) { + GLint log_length = 0; + glGetProgramiv(single_prog, GL_INFO_LOG_LENGTH, &log_length); + if (log_length > 0) { + char* log = new char[log_length]; + glGetProgramInfoLog(single_prog, log_length, NULL, log); + fprintf(stderr, "%s", log); + delete[] log; + } + fprintf(stderr, "\n"); + } + + if (m_state.vs) glDetachShader(single_prog, m_state.vs); + if (m_state.ps) glDetachShader(single_prog, m_state.ps); + if (m_state.gs) glDetachShader(single_prog, m_state.gs); + + return single_prog; +} +#endif + void GSDeviceOGL::BeforeDraw() { #ifdef OGL_DEBUG DebugInput(); #endif +#ifdef DISABLE_GL41_SSO + uint32 sel = m_state.vs << 24 | m_state.gs << 30 | m_state.ps; + auto single_prog = m_single_prog.find(sel); + if (single_prog == m_single_prog.end()) { + m_single_prog[sel] = link_prog(); + single_prog = m_single_prog.find(sel); + } + + glUseProgram(single_prog->second); + +#endif + #ifdef DISABLE_GL42 set_uniform_buffer_binding(m_state.vs, "cb20", 20); set_uniform_buffer_binding(m_state.ps, "cb21", 21); @@ -1104,7 +1148,9 @@ void GSDeviceOGL::VSSetShader(GLuint vs) if(m_state.vs != vs) { m_state.vs = vs; +#ifndef DISABLE_GL41_SSO glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, vs); +#endif } } @@ -1113,7 +1159,9 @@ void GSDeviceOGL::GSSetShader(GLuint gs) if(m_state.gs != gs) { m_state.gs = gs; +#ifndef DISABLE_GL41_SSO glUseProgramStages(m_pipeline, GL_GEOMETRY_SHADER_BIT, gs); +#endif } } @@ -1154,7 +1202,9 @@ void GSDeviceOGL::PSSetShader(GLuint ps) if(m_state.ps != ps) { m_state.ps = ps; +#ifndef DISABLE_GL41_SSO glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, ps); +#endif } // Sampler and texture must be set at the same time @@ -1268,10 +1318,18 @@ void GSDeviceOGL::CompileShaderFromSource(const std::string& glsl_file, const st // Build a header string // ***************************************************** // First select the version (must be the first line so we need to generate it -#ifdef DISABLE_GL42 - std::string version = "#version 330\n#extension GL_ARB_separate_shader_objects : require\n#define DISABLE_GL42\n"; +#ifdef DISABLE_GL41_SSO + #ifdef DISABLE_GL42 + std::string version = "#version 330\n#define DISABLE_GL42\n"; + #else + std::string version = "#version 330\n#extension GL_ARB_shading_language_420pack: require\n"; + #endif #else + #ifdef DISABLE_GL42 + std::string version = "#version 330\n#extension GL_ARB_separate_shader_objects : require\n#define DISABLE_GL42\n"; + #else std::string version = "#version 330\n#extension GL_ARB_shading_language_420pack: require\n#extension GL_ARB_separate_shader_objects : require\n"; + #endif #endif //std::string version = "#version 420\n"; @@ -1338,6 +1396,7 @@ void GSDeviceOGL::CompileShaderFromSource(const std::string& glsl_file, const st header.copy(header_str, header.size(), 0); header_str[header.size()] = '\0'; +#ifndef DISABLE_GL41_SSO #if 0 // Could be useful one day const GLchar* ShaderSource[1]; @@ -1346,6 +1405,11 @@ void GSDeviceOGL::CompileShaderFromSource(const std::string& glsl_file, const st #else *program = glCreateShaderProgramv(type, 2, sources_array); #endif +#else + *program = glCreateShader(type); + glShaderSource(*program, 2, sources_array, NULL); + glCompileShader(*program); +#endif free(source_str); free(header_str); @@ -1357,10 +1421,18 @@ void GSDeviceOGL::CompileShaderFromSource(const std::string& glsl_file, const st fprintf(stderr, "\n%s", macro_sel.c_str()); GLint log_length = 0; +#ifndef DISABLE_GL41_SSO glGetProgramiv(*program, GL_INFO_LOG_LENGTH, &log_length); +#else + glGetShaderiv(*program, GL_INFO_LOG_LENGTH, &log_length); +#endif if (log_length > 0) { char* log = new char[log_length]; +#ifndef DISABLE_GL41_SSO glGetProgramInfoLog(*program, log_length, NULL, log); +#else + glGetShaderInfoLog(*program, log_length, NULL, log); +#endif fprintf(stderr, "%s", log); delete[] log; } diff --git a/plugins/GSdx/GSDeviceOGL.h b/plugins/GSdx/GSDeviceOGL.h index ad18b5624..f17aa7acf 100644 --- a/plugins/GSdx/GSDeviceOGL.h +++ b/plugins/GSdx/GSDeviceOGL.h @@ -656,4 +656,10 @@ class GSDeviceOGL : public GSDevice void SetupGS(GSSelector sel); void SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel); void SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix); + +#ifdef DISABLE_GL41_SSO + hash_map m_single_prog; + GLuint link_prog(); +#endif + }; diff --git a/plugins/GSdx/config.h b/plugins/GSdx/config.h index 80c47392b..de278d120 100644 --- a/plugins/GSdx/config.h +++ b/plugins/GSdx/config.h @@ -36,4 +36,8 @@ //#define DISABLE_DATE +// Set manually uniform buffer index //#define DISABLE_GL42 + +// Debug: use single program for all shaders. +//#define DISABLE_GL41_SSO From 6760ed552bb5859ba7ad4b5156de0dcb8ca5ee66 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Fri, 17 May 2013 20:14:10 +0000 Subject: [PATCH 80/81] gsdx ogl: fix previous commit * clean shader properly * use a 64 bits map to contain shader pointer git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5631 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSDeviceOGL.cpp | 33 ++++++++++++++++++++++++++++++++- plugins/GSdx/GSDeviceOGL.h | 2 +- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/plugins/GSdx/GSDeviceOGL.cpp b/plugins/GSdx/GSDeviceOGL.cpp index 17aafb512..ddfeaea82 100644 --- a/plugins/GSdx/GSDeviceOGL.cpp +++ b/plugins/GSdx/GSDeviceOGL.cpp @@ -69,19 +69,33 @@ GSDeviceOGL::~GSDeviceOGL() // Clean m_merge_obj for (uint i = 0; i < 2; i++) +#ifndef DISABLE_GL41_SSO glDeleteProgram(m_merge_obj.ps[i]); +#else + glDeleteShader(m_merge_obj.ps[i]); +#endif delete (m_merge_obj.cb); delete (m_merge_obj.bs); // Clean m_interlace for (uint i = 0; i < 2; i++) +#ifndef DISABLE_GL41_SSO glDeleteProgram(m_interlace.ps[i]); +#else + glDeleteShader(m_interlace.ps[i]); +#endif delete (m_interlace.cb); // Clean m_convert +#ifndef DISABLE_GL41_SSO glDeleteProgram(m_convert.vs); for (uint i = 0; i < 2; i++) glDeleteProgram(m_convert.ps[i]); +#else + glDeleteShader(m_convert.vs); + for (uint i = 0; i < 2; i++) + glDeleteShader(m_convert.ps[i]); +#endif glDeleteSamplers(1, &m_convert.ln); glDeleteSamplers(1, &m_convert.pt); delete m_convert.dss; @@ -92,7 +106,9 @@ GSDeviceOGL::~GSDeviceOGL() delete m_date.bs; // Clean various opengl allocation +#ifndef DISABLE_GL41_SSO glDeleteProgramPipelines(1, &m_pipeline); +#endif glDeleteFramebuffers(1, &m_fbo); glDeleteFramebuffers(1, &m_fbo_read); @@ -102,9 +118,18 @@ GSDeviceOGL::~GSDeviceOGL() glDeleteSamplers(1, &m_rt_ss); delete m_vb; +#ifndef DISABLE_GL41_SSO for (auto it = m_vs.begin(); it != m_vs.end() ; it++) glDeleteProgram(it->second); for (auto it = m_gs.begin(); it != m_gs.end() ; it++) glDeleteProgram(it->second); for (auto it = m_ps.begin(); it != m_ps.end() ; it++) glDeleteProgram(it->second); +#else + for (auto it = m_vs.begin(); it != m_vs.end() ; it++) glDeleteShader(it->second); + for (auto it = m_gs.begin(); it != m_gs.end() ; it++) glDeleteShader(it->second); + for (auto it = m_ps.begin(); it != m_ps.end() ; it++) glDeleteShader(it->second); + + for (auto it = m_single_prog.begin(); it != m_single_prog.end() ; it++) glDeleteProgram(it->second); + m_single_prog.clear(); +#endif for (auto it = m_ps_ss.begin(); it != m_ps_ss.end() ; it++) glDeleteSamplers(1, &it->second); m_vs.clear(); m_gs.clear(); @@ -212,8 +237,10 @@ bool GSDeviceOGL::Create(GSWnd* wnd) // **************************************************************** // Various object // **************************************************************** +#ifndef DISABLE_GL41_SSO glGenProgramPipelines(1, &m_pipeline); glBindProgramPipeline(m_pipeline); +#endif glGenFramebuffers(1, &m_fbo); glGenFramebuffers(1, &m_fbo_read); @@ -635,9 +662,11 @@ GLuint GSDeviceOGL::link_prog() fprintf(stderr, "\n"); } +#if 0 if (m_state.vs) glDetachShader(single_prog, m_state.vs); if (m_state.ps) glDetachShader(single_prog, m_state.ps); if (m_state.gs) glDetachShader(single_prog, m_state.gs); +#endif return single_prog; } @@ -650,7 +679,9 @@ void GSDeviceOGL::BeforeDraw() #endif #ifdef DISABLE_GL41_SSO - uint32 sel = m_state.vs << 24 | m_state.gs << 30 | m_state.ps; + // Note: shader are integer lookup pointer. They start from 1 and incr + // every time you create a new shader OR a new program. + uint64 sel = (uint64)m_state.vs << 40 | (uint64)m_state.gs << 20 | m_state.ps; auto single_prog = m_single_prog.find(sel); if (single_prog == m_single_prog.end()) { m_single_prog[sel] = link_prog(); diff --git a/plugins/GSdx/GSDeviceOGL.h b/plugins/GSdx/GSDeviceOGL.h index f17aa7acf..e95269636 100644 --- a/plugins/GSdx/GSDeviceOGL.h +++ b/plugins/GSdx/GSDeviceOGL.h @@ -658,7 +658,7 @@ class GSDeviceOGL : public GSDevice void SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix); #ifdef DISABLE_GL41_SSO - hash_map m_single_prog; + hash_map m_single_prog; GLuint link_prog(); #endif From e3d658b501f389a41597c20b265777f5577f1056 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Sat, 18 May 2013 09:17:30 +0000 Subject: [PATCH 81/81] gsdx ogl: load shader from C code instead of an external file * add a perl script to convert shader to char* * By default use *.glsl file (handy to do some trials). Only drawback, glsl2h need to be manually called at the moment git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5632 96395faa-99c1-11dd-bbfe-3dabce05a288 --- linux_various/glsl2h.pl | 61 +++ plugins/GSdx/GSDeviceOGL.cpp | 50 ++- plugins/GSdx/GSDeviceOGL.h | 2 +- plugins/GSdx/GSTextureFXOGL.cpp | 14 +- plugins/GSdx/res/convert.h | 196 +++++++++ plugins/GSdx/res/interlace.h | 92 +++++ plugins/GSdx/res/merge.h | 68 ++++ plugins/GSdx/res/shadeboost.h | 94 +++++ plugins/GSdx/res/tfx.h | 697 ++++++++++++++++++++++++++++++++ 9 files changed, 1246 insertions(+), 28 deletions(-) create mode 100755 linux_various/glsl2h.pl create mode 100644 plugins/GSdx/res/convert.h create mode 100644 plugins/GSdx/res/interlace.h create mode 100644 plugins/GSdx/res/merge.h create mode 100644 plugins/GSdx/res/shadeboost.h create mode 100644 plugins/GSdx/res/tfx.h diff --git a/linux_various/glsl2h.pl b/linux_various/glsl2h.pl new file mode 100755 index 000000000..b5d96c805 --- /dev/null +++ b/linux_various/glsl2h.pl @@ -0,0 +1,61 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +my @res = qw/convert interlace merge shadeboost tfx/; +my $path = "plugins/GSdx/res"; + +foreach my $r (@res) { + glsl2h($path, $r); +} + +sub glsl2h { + my $path = shift; + my $glsl = shift; + + open(my $GLSL, "<$path/${glsl}.glsl"); + open(my $H, ">$path/${glsl}.h"); + + my $header = <)) { + chomp $line; + $line =~ s/%/\\%/g; + $line =~ s/"/\\"/g; + print $H "\t\"$line\\n\"\n"; + } + print $H "\t;\n"; +} diff --git a/plugins/GSdx/GSDeviceOGL.cpp b/plugins/GSdx/GSDeviceOGL.cpp index ddfeaea82..e280fbd92 100644 --- a/plugins/GSdx/GSDeviceOGL.cpp +++ b/plugins/GSdx/GSDeviceOGL.cpp @@ -21,6 +21,11 @@ #include "GSDeviceOGL.h" +#include "res/convert.h" +#include "res/interlace.h" +#include "res/merge.h" +#include "res/shadeboost.h" + // TODO performance cost to investigate // Texture attachment/glDrawBuffer. For the moment it set every draw and potentially multiple time (first time in clear, second time in rendering) // Attachment 1 is only used with the GL_16UI format @@ -258,10 +263,10 @@ bool GSDeviceOGL::Create(GSWnd* wnd) // **************************************************************** // convert // **************************************************************** - CompileShaderFromSource("convert.glsl", "vs_main", GL_VERTEX_SHADER, &m_convert.vs); - CompileShaderFromSource("convert.glsl", "gs_main", GL_GEOMETRY_SHADER, &m_convert.gs); + CompileShaderFromSource("convert.glsl", "vs_main", GL_VERTEX_SHADER, &m_convert.vs, convert_glsl); + CompileShaderFromSource("convert.glsl", "gs_main", GL_GEOMETRY_SHADER, &m_convert.gs, convert_glsl); for(uint i = 0; i < countof(m_convert.ps); i++) - CompileShaderFromSource("convert.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, &m_convert.ps[i]); + CompileShaderFromSource("convert.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, &m_convert.ps[i], convert_glsl); // Note the following object are initialized to 0 so disabled. // Note: maybe enable blend with a factor of 1 @@ -321,7 +326,7 @@ bool GSDeviceOGL::Create(GSWnd* wnd) m_merge_obj.cb = new GSUniformBufferOGL(g_merge_cb_index, sizeof(MergeConstantBuffer)); for(uint i = 0; i < countof(m_merge_obj.ps); i++) - CompileShaderFromSource("merge.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, &m_merge_obj.ps[i]); + CompileShaderFromSource("merge.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, &m_merge_obj.ps[i], merge_glsl); m_merge_obj.bs = new GSBlendStateOGL(); m_merge_obj.bs->EnableBlend(); @@ -333,7 +338,7 @@ bool GSDeviceOGL::Create(GSWnd* wnd) m_interlace.cb = new GSUniformBufferOGL(g_interlace_cb_index, sizeof(InterlaceConstantBuffer)); for(uint i = 0; i < countof(m_interlace.ps); i++) - CompileShaderFromSource("interlace.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, &m_interlace.ps[i]); + CompileShaderFromSource("interlace.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, &m_interlace.ps[i], interlace_glsl); // **************************************************************** // Shade boost // **************************************************************** @@ -346,7 +351,7 @@ bool GSDeviceOGL::Create(GSWnd* wnd) + format("#define SB_BRIGHTNESS %d\n", ShadeBoost_Brightness) + format("#define SB_CONTRAST %d\n", ShadeBoost_Contrast); - CompileShaderFromSource("shadeboost.glsl", "ps_main", GL_FRAGMENT_SHADER, &m_shadeboost.ps, macro); + CompileShaderFromSource("shadeboost.glsl", "ps_main", GL_FRAGMENT_SHADER, &m_shadeboost.ps, shadeboost_glsl, macro); // **************************************************************** // rasterization configuration @@ -379,7 +384,7 @@ bool GSDeviceOGL::Create(GSWnd* wnd) // FIXME need to manually set the index... // FIXME need dofxaa interface too // m_fxaa.cb = new GSUniformBufferOGL(g_fxaa_cb_index, sizeof(FXAAConstantBuffer)); - //CompileShaderFromSource("fxaa.fx", format("ps_main", i), GL_FRAGMENT_SHADER, &m_fxaa.ps); + //CompileShaderFromSource("fxaa.fx", format("ps_main", i), GL_FRAGMENT_SHADER, &m_fxaa.ps, fxaa_glsl); // **************************************************************** // date @@ -548,10 +553,7 @@ void GSDeviceOGL::Flip() #ifdef PRINT_FRAME_NUMBER fprintf(stderr, "Draw %d (Frame %d)\n", g_draw_count, g_frame_count); -#endif -#ifdef OGL_DEBUG - if (theApp.GetConfig("debug_ogl_dump", 0) != 0) - g_frame_count++; + g_frame_count++; #endif } @@ -707,6 +709,8 @@ void GSDeviceOGL::AfterDraw() { #ifdef OGL_DEBUG DebugOutput(); +#endif +#if defined(OGL_DEBUG) || defined(PRINT_FRAME_NUMBER) g_draw_count++; #endif } @@ -1343,7 +1347,7 @@ void GSDeviceOGL::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVecto } } -void GSDeviceOGL::CompileShaderFromSource(const std::string& glsl_file, const std::string& entry, GLenum type, GLuint* program, const std::string& macro_sel) +void GSDeviceOGL::CompileShaderFromSource(const std::string& glsl_file, const std::string& entry, GLenum type, GLuint* program, const char* glsl_h_code, const std::string& macro_sel) { // ***************************************************** // Build a header string @@ -1399,6 +1403,7 @@ void GSDeviceOGL::CompileShaderFromSource(const std::string& glsl_file, const st const std::string shader_file = string("plugins/") + glsl_file; #endif std::ifstream myfile(shader_file.c_str()); + bool failed_to_open_glsl = true; if (myfile.is_open()) { while ( myfile.good() ) { @@ -1407,26 +1412,29 @@ void GSDeviceOGL::CompileShaderFromSource(const std::string& glsl_file, const st source += '\n'; } myfile.close(); - } else { - fprintf(stderr, "Error opening %s: ", shader_file.c_str()); - *program = 0; - return; + failed_to_open_glsl = false; } // Note it is better to separate header and source file to have the good line number // in the glsl compiler report const char** sources_array = (const char**)malloc(2*sizeof(char*)); - char* source_str = (char*)malloc(source.size() + 1); + char* header_str = (char*)malloc(header.size() + 1); sources_array[0] = header_str; - sources_array[1] = source_str; - - source.copy(source_str, source.size(), 0); - source_str[source.size()] = '\0'; header.copy(header_str, header.size(), 0); header_str[header.size()] = '\0'; + char* source_str = (char*)malloc(source.size() + 1); + if (failed_to_open_glsl) { + sources_array[1] = glsl_h_code; + } else { + sources_array[1] = source_str; + source.copy(source_str, source.size(), 0); + source_str[source.size()] = '\0'; + } + + #ifndef DISABLE_GL41_SSO #if 0 // Could be useful one day diff --git a/plugins/GSdx/GSDeviceOGL.h b/plugins/GSdx/GSDeviceOGL.h index e95269636..b18deb0aa 100644 --- a/plugins/GSdx/GSDeviceOGL.h +++ b/plugins/GSdx/GSDeviceOGL.h @@ -623,7 +623,7 @@ class GSDeviceOGL : public GSDevice GSTexture* Resolve(GSTexture* t); - void CompileShaderFromSource(const std::string& glsl_file, const std::string& entry, GLenum type, GLuint* program, const std::string& macro_sel = ""); + void CompileShaderFromSource(const std::string& glsl_file, const std::string& entry, GLenum type, GLuint* program, const char* glsl_h_code, const std::string& macro_sel = ""); void EndScene(); diff --git a/plugins/GSdx/GSTextureFXOGL.cpp b/plugins/GSdx/GSTextureFXOGL.cpp index 80d4e4699..8e3b54308 100644 --- a/plugins/GSdx/GSTextureFXOGL.cpp +++ b/plugins/GSdx/GSTextureFXOGL.cpp @@ -23,6 +23,8 @@ #include "GSDeviceOGL.h" #include "GSTables.h" +#include "res/tfx.h" + static const uint32 g_vs_cb_index = 20; static const uint32 g_ps_cb_index = 21; @@ -66,9 +68,9 @@ void GSDeviceOGL::CreateTextureFX() // Compile some dummy shaders to allow modification inside Apitrace for debug GLuint dummy; std::string macro = ""; - CompileShaderFromSource("tfx.glsl", "vs_main", GL_VERTEX_SHADER, &dummy, macro); - CompileShaderFromSource("tfx.glsl", "gs_main", GL_GEOMETRY_SHADER, &dummy, macro); - CompileShaderFromSource("tfx.glsl", "ps_main", GL_FRAGMENT_SHADER, &dummy, macro); + CompileShaderFromSource("tfx.glsl", "vs_main", GL_VERTEX_SHADER, &dummy, tfx_glsl, macro); + CompileShaderFromSource("tfx.glsl", "gs_main", GL_GEOMETRY_SHADER, &dummy, tfx_glsl, macro); + CompileShaderFromSource("tfx.glsl", "ps_main", GL_FRAGMENT_SHADER, &dummy, tfx_glsl, macro); } void GSDeviceOGL::SetupVS(VSSelector sel, const VSConstantBuffer* cb) @@ -87,7 +89,7 @@ void GSDeviceOGL::SetupVS(VSSelector sel, const VSConstantBuffer* cb) + format("#define VS_RTCOPY %d\n", sel.rtcopy); GLuint vs; - CompileShaderFromSource("tfx.glsl", "vs_main", GL_VERTEX_SHADER, &vs, macro); + CompileShaderFromSource("tfx.glsl", "vs_main", GL_VERTEX_SHADER, &vs, tfx_glsl, macro); m_vs[sel] = vs; i = m_vs.find(sel); @@ -118,7 +120,7 @@ void GSDeviceOGL::SetupGS(GSSelector sel) std::string macro = format("#define GS_IIP %d\n", sel.iip) + format("#define GS_PRIM %d\n", sel.prim); - CompileShaderFromSource("tfx.glsl", "gs_main", GL_GEOMETRY_SHADER, &gs, macro); + CompileShaderFromSource("tfx.glsl", "gs_main", GL_GEOMETRY_SHADER, &gs, tfx_glsl, macro); m_gs[sel] = gs; } else { @@ -160,7 +162,7 @@ void GSDeviceOGL::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerS + format("#define PS_TCOFFSETHACK %d\n", sel.tcoffsethack) + format("#define PS_POINT_SAMPLER %d\n", sel.point_sampler); - CompileShaderFromSource("tfx.glsl", "ps_main", GL_FRAGMENT_SHADER, &ps, macro); + CompileShaderFromSource("tfx.glsl", "ps_main", GL_FRAGMENT_SHADER, &ps, tfx_glsl, macro); m_ps[sel] = ps; i = m_ps.find(sel); diff --git a/plugins/GSdx/res/convert.h b/plugins/GSdx/res/convert.h new file mode 100644 index 000000000..66379bd16 --- /dev/null +++ b/plugins/GSdx/res/convert.h @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2011-2013 Gregory hainaut + * Copyright (C) 2007-2009 Gabest + * + * This file was generated by glsl2h.pl script + * + * 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#pragma once + +#include "stdafx.h" + +extern const char* convert_glsl = + "//#version 420 // Keep it for editor detection\n" + "\n" + "struct vertex_basic\n" + "{\n" + " vec4 p;\n" + " vec2 t;\n" + "};\n" + "\n" + "\n" + "#ifdef VERTEX_SHADER\n" + "\n" + "out gl_PerVertex {\n" + " vec4 gl_Position;\n" + " float gl_PointSize;\n" + " float gl_ClipDistance[];\n" + "};\n" + "\n" + "layout(location = 0) in vec4 POSITION;\n" + "layout(location = 1) in vec2 TEXCOORD0;\n" + "\n" + "// FIXME set the interpolation (don't know what dx do)\n" + "// flat means that there is no interpolation. The value given to the fragment shader is based on the provoking vertex conventions.\n" + "//\n" + "// noperspective means that there will be linear interpolation in window-space. This is usually not what you want, but it can have its uses.\n" + "//\n" + "// smooth, the default, means to do perspective-correct interpolation.\n" + "//\n" + "// The centroid qualifier only matters when multisampling. If this qualifier is not present, then the value is interpolated to the pixel's center, anywhere in the pixel, or to one of the pixel's samples. This sample may lie outside of the actual primitive being rendered, since a primitive can cover only part of a pixel's area. The centroid qualifier is used to prevent this; the interpolation point must fall within both the pixel's area and the primitive's area.\n" + "layout(location = 0) out vertex_basic VSout;\n" + "\n" + "void vs_main()\n" + "{\n" + " VSout.p = POSITION;\n" + " VSout.t = TEXCOORD0;\n" + " gl_Position = POSITION; // NOTE I don't know if it is possible to merge POSITION_OUT and gl_Position\n" + "}\n" + "\n" + "#endif\n" + "\n" + "#ifdef GEOMETRY_SHADER\n" + "in gl_PerVertex {\n" + " vec4 gl_Position;\n" + " float gl_PointSize;\n" + " float gl_ClipDistance[];\n" + "} gl_in[];\n" + "\n" + "out gl_PerVertex {\n" + " vec4 gl_Position;\n" + " float gl_PointSize;\n" + " float gl_ClipDistance[];\n" + "};\n" + "\n" + "// FIXME\n" + "// AMD Driver bug again !!!!\n" + "//layout(location = 0) in vertex GSin[];\n" + "in vertex_basic GSin[];\n" + "\n" + "layout(location = 0) out vertex_basic GSout;\n" + "layout(triangles) in;\n" + "layout(triangle_strip, max_vertices = 3) out;\n" + "\n" + "void gs_main()\n" + "{\n" + " for(int i = 0; i < gl_in.length(); i++) {\n" + " gl_Position = gl_in[i].gl_Position;\n" + " GSout = GSin[i];\n" + " EmitVertex();\n" + " }\n" + " EndPrimitive();\n" + "}\n" + "#endif\n" + "\n" + "#ifdef FRAGMENT_SHADER\n" + "// NOTE: pixel can be clip with \"discard\"\n" + "\n" + "layout(location = 0) in vertex_basic PSin;\n" + "\n" + "layout(location = 0) out vec4 SV_Target0;\n" + "layout(location = 1) out uint SV_Target1;\n" + "\n" + "layout(binding = 0) uniform sampler2D TextureSampler;\n" + "\n" + "vec4 sample_c()\n" + "{\n" + " return texture(TextureSampler, PSin.t );\n" + "}\n" + "\n" + "vec4 ps_crt(uint i)\n" + "{\n" + " vec4 mask[4] =\n" + " {\n" + " vec4(1, 0, 0, 0),\n" + " vec4(0, 1, 0, 0),\n" + " vec4(0, 0, 1, 0),\n" + " vec4(1, 1, 1, 0)\n" + " };\n" + "\n" + " return sample_c() * clamp((mask[i] + 0.5f), 0.0f, 1.0f);\n" + "}\n" + "\n" + "void ps_main0()\n" + "{\n" + " SV_Target0 = sample_c();\n" + "}\n" + "\n" + "void ps_main1()\n" + "{\n" + " vec4 c = sample_c();\n" + "\n" + " c.a *= 256.0f / 127.0f; // hm, 0.5 won't give us 1.0 if we just multiply with 2\n" + "\n" + " highp uvec4 i = uvec4(c * vec4(uint(0x001f), uint(0x03e0), uint(0x7c00), uint(0x8000)));\n" + "\n" + " SV_Target1 = (i.x & uint(0x001f)) | (i.y & uint(0x03e0)) | (i.z & uint(0x7c00)) | (i.w & uint(0x8000));\n" + "}\n" + "\n" + "void ps_main7()\n" + "{\n" + " vec4 c = sample_c();\n" + "\n" + " c.a = dot(c.rgb, vec3(0.299, 0.587, 0.114));\n" + "\n" + " SV_Target0 = c;\n" + "}\n" + "\n" + "void ps_main5() // triangular\n" + "{\n" + " highp uvec4 p = uvec4(PSin.p);\n" + "\n" + " vec4 c = ps_crt(((p.x + ((p.y >> 1u) & 1u) * 3u) >> 1u) \% 3u);\n" + "\n" + " SV_Target0 = c;\n" + "}\n" + "\n" + "void ps_main6() // diagonal\n" + "{\n" + " uvec4 p = uvec4(PSin.p);\n" + "\n" + " vec4 c = ps_crt((p.x + (p.y \% 3u)) \% 3u);\n" + "\n" + " SV_Target0 = c;\n" + "}\n" + "\n" + "void ps_main2()\n" + "{\n" + " if((sample_c().a - 128.0f / 255) < 0) // >= 0x80 pass\n" + " discard;\n" + "\n" + " SV_Target0 = vec4(0.0f, 0.0f, 0.0f, 0.0f);\n" + "}\n" + "void ps_main3()\n" + "{\n" + " if((127.95f / 255 - sample_c().a) <0) // < 0x80 pass (== 0x80 should not pass)\n" + " discard;\n" + "\n" + " SV_Target0 = vec4(0.0f, 0.0f, 0.0f, 0.0f);\n" + "}\n" + "void ps_main4()\n" + "{\n" + " // FIXME mod and fmod are different when value are negative\n" + " // output.c = fmod(sample_c(input.t) * 255 + 0.5f, 256) / 255;\n" + " vec4 c = mod(sample_c() * 255 + 0.5f, 256) / 255;\n" + "\n" + " SV_Target0 = c;\n" + "}\n" + "\n" + "#endif\n" + ; diff --git a/plugins/GSdx/res/interlace.h b/plugins/GSdx/res/interlace.h new file mode 100644 index 000000000..ed21d59fe --- /dev/null +++ b/plugins/GSdx/res/interlace.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2011-2013 Gregory hainaut + * Copyright (C) 2007-2009 Gabest + * + * This file was generated by glsl2h.pl script + * + * 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#pragma once + +#include "stdafx.h" + +extern const char* interlace_glsl = + "//#version 420 // Keep it for editor detection\n" + "\n" + "struct vertex_basic\n" + "{\n" + " vec4 p;\n" + " vec2 t;\n" + "};\n" + "\n" + "#ifdef FRAGMENT_SHADER\n" + "layout(location = 0) in vertex_basic PSin;\n" + "\n" + "layout(location = 0) out vec4 SV_Target0;\n" + "\n" + "#ifdef DISABLE_GL42\n" + "layout(std140) uniform cb11\n" + "#else\n" + "layout(std140, binding = 11) uniform cb11\n" + "#endif\n" + "{\n" + " vec2 ZrH;\n" + " float hH;\n" + "};\n" + "\n" + "layout(binding = 0) uniform sampler2D TextureSampler;\n" + "\n" + "// TODO ensure that clip (discard) is < 0 and not <= 0 ???\n" + "void ps_main0()\n" + "{\n" + " // I'm not sure it impact us but be safe to lookup texture before conditional if\n" + " // see: http://www.opengl.org/wiki/GLSL_Sampler#Non-uniform_flow_control\n" + " vec4 c = texture(TextureSampler, PSin.t);\n" + " if (fract(PSin.t.y * hH) - 0.5 < 0.0)\n" + " discard;\n" + "\n" + " SV_Target0 = c;\n" + "}\n" + "\n" + "void ps_main1()\n" + "{\n" + " // I'm not sure it impact us but be safe to lookup texture before conditional if\n" + " // see: http://www.opengl.org/wiki/GLSL_Sampler#Non-uniform_flow_control\n" + " vec4 c = texture(TextureSampler, PSin.t);\n" + " if (0.5 - fract(PSin.t.y * hH) < 0.0)\n" + " discard;\n" + "\n" + " SV_Target0 = c;\n" + "}\n" + "\n" + "void ps_main2()\n" + "{\n" + " vec4 c0 = texture(TextureSampler, PSin.t - ZrH);\n" + " vec4 c1 = texture(TextureSampler, PSin.t);\n" + " vec4 c2 = texture(TextureSampler, PSin.t + ZrH);\n" + "\n" + " SV_Target0 = (c0 + c1 * 2 + c2) / 4;\n" + "}\n" + "\n" + "void ps_main3()\n" + "{\n" + " SV_Target0 = texture(TextureSampler, PSin.t);\n" + "}\n" + "\n" + "#endif\n" + ; diff --git a/plugins/GSdx/res/merge.h b/plugins/GSdx/res/merge.h new file mode 100644 index 000000000..a3012684b --- /dev/null +++ b/plugins/GSdx/res/merge.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2011-2013 Gregory hainaut + * Copyright (C) 2007-2009 Gabest + * + * This file was generated by glsl2h.pl script + * + * 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#pragma once + +#include "stdafx.h" + +extern const char* merge_glsl = + "//#version 420 // Keep it for editor detection\n" + "\n" + "struct vertex_basic\n" + "{\n" + " vec4 p;\n" + " vec2 t;\n" + "};\n" + "\n" + "#ifdef FRAGMENT_SHADER\n" + "layout(location = 0) in vertex_basic PSin;\n" + "\n" + "layout(location = 0) out vec4 SV_Target0;\n" + "\n" + "#ifdef DISABLE_GL42\n" + "layout(std140) uniform cb10\n" + "#else\n" + "layout(std140, binding = 10) uniform cb10\n" + "#endif\n" + "{\n" + " vec4 BGColor;\n" + "};\n" + "\n" + "layout(binding = 0) uniform sampler2D TextureSampler;\n" + "\n" + "void ps_main0()\n" + "{\n" + " vec4 c = texture(TextureSampler, PSin.t);\n" + " c.a = min(c.a * 2, 1.0);\n" + " SV_Target0 = c;\n" + "}\n" + "\n" + "void ps_main1()\n" + "{\n" + " vec4 c = texture(TextureSampler, PSin.t);\n" + " c.a = BGColor.a;\n" + " SV_Target0 = c;\n" + "}\n" + "\n" + "#endif\n" + ; diff --git a/plugins/GSdx/res/shadeboost.h b/plugins/GSdx/res/shadeboost.h new file mode 100644 index 000000000..172175c34 --- /dev/null +++ b/plugins/GSdx/res/shadeboost.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2011-2013 Gregory hainaut + * Copyright (C) 2007-2009 Gabest + * + * This file was generated by glsl2h.pl script + * + * 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#pragma once + +#include "stdafx.h" + +extern const char* shadeboost_glsl = + "//#version 420 // Keep it for editor detection\n" + "\n" + "/*\n" + "** Contrast, saturation, brightness\n" + "** Code of this function is from TGM's shader pack\n" + "** http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=21057\n" + "*/\n" + "\n" + "struct vertex_basic\n" + "{\n" + " vec4 p;\n" + " vec2 t;\n" + "};\n" + "\n" + "#ifdef FRAGMENT_SHADER\n" + "\n" + "layout(location = 0) in vertex_basic PSin;\n" + "\n" + "layout(location = 0) out vec4 SV_Target0;\n" + "\n" + "#ifdef DISABLE_GL42\n" + "layout(std140) uniform cb12\n" + "#else\n" + "layout(std140, binding = 12) uniform cb12\n" + "#endif\n" + "{\n" + " vec4 BGColor;\n" + "};\n" + "\n" + "layout(binding = 0) uniform sampler2D TextureSampler;\n" + "\n" + "// For all settings: 1.0 = 100\% 0.5=50\% 1.5 = 150\% \n" + "vec4 ContrastSaturationBrightness(vec4 color)\n" + "{\n" + " const float sat = SB_SATURATION / 50.0;\n" + " const float brt = SB_BRIGHTNESS / 50.0;\n" + " const float con = SB_CONTRAST / 50.0;\n" + " \n" + " // Increase or decrease theese values to adjust r, g and b color channels seperately\n" + " const float AvgLumR = 0.5;\n" + " const float AvgLumG = 0.5;\n" + " const float AvgLumB = 0.5;\n" + " \n" + " const vec3 LumCoeff = vec3(0.2125, 0.7154, 0.0721);\n" + " \n" + " vec3 AvgLumin = vec3(AvgLumR, AvgLumG, AvgLumB);\n" + " vec3 brtColor = color.rgb * brt;\n" + " float dot_intensity = dot(brtColor, LumCoeff);\n" + " vec3 intensity = vec3(dot_intensity, dot_intensity, dot_intensity);\n" + " vec3 satColor = mix(intensity, brtColor, sat);\n" + " vec3 conColor = mix(AvgLumin, satColor, con);\n" + "\n" + " color.rgb = conColor; \n" + " return color;\n" + "}\n" + "\n" + "\n" + "void ps_main()\n" + "{\n" + " vec4 c = texture(TextureSampler, PSin.t);\n" + " SV_Target0 = ContrastSaturationBrightness(c);\n" + "}\n" + "\n" + "\n" + "#endif\n" + ; diff --git a/plugins/GSdx/res/tfx.h b/plugins/GSdx/res/tfx.h new file mode 100644 index 000000000..8f38c2c3e --- /dev/null +++ b/plugins/GSdx/res/tfx.h @@ -0,0 +1,697 @@ +/* + * Copyright (C) 2011-2013 Gregory hainaut + * Copyright (C) 2007-2009 Gabest + * + * This file was generated by glsl2h.pl script + * + * 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#pragma once + +#include "stdafx.h" + +extern const char* tfx_glsl = + "//#version 420 // Keep it for text editor detection\n" + "\n" + "// note lerp => mix\n" + "\n" + "#define FMT_32 0\n" + "#define FMT_24 1\n" + "#define FMT_16 2\n" + "#define FMT_PAL 4 /* flag bit */\n" + "\n" + "// Not sure we have same issue on opengl. Doesn't work anyway on ATI card\n" + "// And I say this as an ATI user.\n" + "#define ATI_SUCKS 0\n" + "\n" + "#ifndef VS_BPPZ\n" + "#define VS_BPPZ 0\n" + "#define VS_TME 1\n" + "#define VS_FST 1\n" + "#define VS_LOGZ 0\n" + "#endif\n" + "\n" + "#ifndef GS_IIP\n" + "#define GS_IIP 0\n" + "#define GS_PRIM 3\n" + "#endif\n" + "\n" + "#ifndef PS_FST\n" + "#define PS_FST 0\n" + "#define PS_WMS 0\n" + "#define PS_WMT 0\n" + "#define PS_FMT FMT_32\n" + "#define PS_AEM 0\n" + "#define PS_TFX 0\n" + "#define PS_TCC 1\n" + "#define PS_ATST 1\n" + "#define PS_FOG 0\n" + "#define PS_CLR1 0\n" + "#define PS_FBA 0\n" + "#define PS_AOUT 0\n" + "#define PS_LTF 1\n" + "#define PS_COLCLIP 0\n" + "#define PS_DATE 0\n" + "#define PS_SPRITEHACK 0\n" + "#define PS_POINT_SAMPLER 0\n" + "#define PS_TCOFFSETHACK 0\n" + "#endif\n" + "\n" + "struct vertex\n" + "{\n" + " vec4 p;\n" + " vec4 t;\n" + " vec4 tp;\n" + " vec4 c;\n" + "};\n" + "\n" + "#ifdef VERTEX_SHADER\n" + "layout(location = 0) in vec2 i_st;\n" + "layout(location = 1) in vec4 i_c;\n" + "layout(location = 2) in float i_q;\n" + "layout(location = 3) in uvec2 i_p;\n" + "layout(location = 4) in uint i_z;\n" + "layout(location = 5) in uvec2 i_uv;\n" + "layout(location = 6) in vec4 i_f;\n" + "\n" + "layout(location = 0) out vertex VSout;\n" + "\n" + "out gl_PerVertex {\n" + " invariant vec4 gl_Position;\n" + " float gl_PointSize;\n" + " float gl_ClipDistance[];\n" + "};\n" + "\n" + "#ifdef DISABLE_GL42\n" + "layout(std140) uniform cb20\n" + "#else\n" + "layout(std140, binding = 20) uniform cb20\n" + "#endif\n" + "{\n" + " vec4 VertexScale;\n" + " vec4 VertexOffset;\n" + " vec2 TextureScale;\n" + "};\n" + "\n" + "void vs_main()\n" + "{\n" + " uint z;\n" + " if(VS_BPPZ == 1) // 24\n" + " z = i_z & uint(0xffffff);\n" + " else if(VS_BPPZ == 2) // 16\n" + " z = i_z & uint(0xffff);\n" + " else\n" + " z = i_z;\n" + "\n" + " // pos -= 0.05 (1/320 pixel) helps avoiding rounding problems (integral part of pos is usually 5 digits, 0.05 is about as low as we can go)\n" + " // example: ceil(afterseveralvertextransformations(y = 133)) => 134 => line 133 stays empty\n" + " // input granularity is 1/16 pixel, anything smaller than that won't step drawing up/left by one pixel\n" + " // example: 133.0625 (133 + 1/16) should start from line 134, ceil(133.0625 - 0.05) still above 133\n" + "\n" + " vec4 p = vec4(i_p, z, 0) - vec4(0.05f, 0.05f, 0, 0); \n" + " vec4 final_p = p * VertexScale - VertexOffset;\n" + " // FIXME\n" + " // FLIP vertically\n" + " final_p.y *= -1.0f;\n" + "\n" + " if(VS_LOGZ == 1)\n" + " {\n" + " final_p.z = log2(1.0f + float(z)) / 32.0f;\n" + " }\n" + "\n" + " VSout.p = final_p;\n" + " gl_Position = final_p; // NOTE I don't know if it is possible to merge POSITION_OUT and gl_Position\n" + "#if VS_RTCOPY\n" + " VSout.tp = final_p * vec4(0.5, -0.5, 0, 0) + 0.5;\n" + "#endif\n" + "\n" + "\n" + " if(VS_TME != 0)\n" + " {\n" + " if(VS_FST != 0)\n" + " {\n" + " //VSout.t.xy = i_t * TextureScale;\n" + " VSout.t.xy = i_uv * TextureScale;\n" + " VSout.t.w = 1.0f;\n" + " }\n" + " else\n" + " {\n" + " //VSout.t.xy = i_t;\n" + " VSout.t.xy = i_st;\n" + " VSout.t.w = i_q;\n" + " }\n" + " }\n" + " else\n" + " {\n" + " VSout.t.xy = vec2(0.0f, 0.0f);\n" + " VSout.t.w = 1.0f;\n" + " }\n" + "\n" + " VSout.c = i_c;\n" + " VSout.t.z = i_f.r;\n" + "}\n" + "\n" + "#endif\n" + "\n" + "#ifdef GEOMETRY_SHADER\n" + "in gl_PerVertex {\n" + " vec4 gl_Position;\n" + " float gl_PointSize;\n" + " float gl_ClipDistance[];\n" + "} gl_in[];\n" + "\n" + "out gl_PerVertex {\n" + " vec4 gl_Position;\n" + " float gl_PointSize;\n" + " float gl_ClipDistance[];\n" + "};\n" + "\n" + "layout(location = 0) in vertex GSin[];\n" + "\n" + "layout(location = 0) out vertex GSout;\n" + "\n" + "#if GS_PRIM == 0\n" + "layout(points) in;\n" + "layout(points, max_vertices = 1) out;\n" + "\n" + "void gs_main()\n" + "{\n" + " for(int i = 0; i < gl_in.length(); i++) {\n" + " gl_Position = gl_in[i].gl_Position; // FIXME is it useful\n" + " GSout = GSin[i];\n" + " EmitVertex();\n" + " }\n" + " EndPrimitive();\n" + "}\n" + "\n" + "#elif GS_PRIM == 1\n" + "layout(lines) in;\n" + "layout(line_strip, max_vertices = 2) out;\n" + "\n" + "void gs_main()\n" + "{\n" + " for(int i = 0; i < gl_in.length(); i++) {\n" + " gl_Position = gl_in[i].gl_Position; // FIXME is it useful\n" + " GSout = GSin[i];\n" + "#if GS_IIP == 0\n" + " if (i == 0)\n" + " GSout.c = GSin[1].c;\n" + "#endif\n" + " EmitVertex();\n" + " }\n" + " EndPrimitive();\n" + "}\n" + "\n" + "#elif GS_PRIM == 2\n" + "layout(triangles) in;\n" + "layout(triangle_strip, max_vertices = 3) out;\n" + "\n" + "void gs_main()\n" + "{\n" + " for(int i = 0; i < gl_in.length(); i++) {\n" + " gl_Position = gl_in[i].gl_Position; // FIXME is it useful\n" + " GSout = GSin[i];\n" + "#if GS_IIP == 0\n" + " if (i == 0 || i == 1)\n" + " GSout.c = GSin[2].c;\n" + "#endif\n" + " EmitVertex();\n" + " }\n" + " EndPrimitive();\n" + "}\n" + "\n" + "#elif GS_PRIM == 3\n" + "layout(lines) in;\n" + "layout(triangle_strip, max_vertices = 6) out;\n" + "\n" + "void gs_main()\n" + "{\n" + " // left top => GSin[0];\n" + " // right bottom => GSin[1];\n" + " vertex rb = GSin[1];\n" + " vertex lt = GSin[0];\n" + "\n" + " lt.p.z = rb.p.z;\n" + " lt.t.zw = rb.t.zw;\n" + "#if GS_IIP == 0\n" + " lt.c = rb.c;\n" + "#endif\n" + "\n" + " vertex lb = rb;\n" + " lb.p.x = lt.p.x;\n" + " lb.t.x = lt.t.x;\n" + "\n" + " vertex rt = rb;\n" + " rt.p.y = lt.p.y;\n" + " rt.t.y = lt.t.y;\n" + "\n" + " // Triangle 1\n" + " gl_Position = lt.p;\n" + " GSout = lt;\n" + " EmitVertex();\n" + "\n" + " gl_Position = lb.p;\n" + " GSout = lb;\n" + " EmitVertex();\n" + "\n" + " gl_Position = rt.p;\n" + " GSout = rt;\n" + " EmitVertex();\n" + "\n" + " EndPrimitive();\n" + "\n" + " // Triangle 2\n" + " gl_Position = lb.p;\n" + " GSout = lb;\n" + " EmitVertex();\n" + "\n" + " gl_Position = rt.p;\n" + " GSout = rt;\n" + " EmitVertex();\n" + "\n" + " gl_Position = rb.p;\n" + " GSout = rb;\n" + " EmitVertex();\n" + "\n" + " EndPrimitive();\n" + "\n" + "}\n" + "\n" + "#endif\n" + "\n" + "#endif\n" + "\n" + "#ifdef FRAGMENT_SHADER\n" + "layout(location = 0) in vertex PSin;\n" + "\n" + "// Same buffer but 2 colors for dual source blending\n" + "layout(location = 0, index = 0) out vec4 SV_Target0;\n" + "layout(location = 0, index = 1) out vec4 SV_Target1;\n" + "\n" + "layout(binding = 0) uniform sampler2D TextureSampler;\n" + "layout(binding = 1) uniform sampler2D PaletteSampler;\n" + "layout(binding = 2) uniform sampler2D RTCopySampler;\n" + "\n" + "#ifdef DISABLE_GL42\n" + "layout(std140) uniform cb21\n" + "#else\n" + "layout(std140, binding = 21) uniform cb21\n" + "#endif\n" + "{\n" + " vec3 FogColor;\n" + " float AREF;\n" + " vec4 HalfTexel;\n" + " vec4 WH;\n" + " vec4 MinMax;\n" + " vec2 MinF;\n" + " vec2 TA;\n" + " uvec4 MskFix;\n" + " vec4 TC_OffsetHack;\n" + "};\n" + "\n" + "vec4 sample_c(vec2 uv)\n" + "{\n" + " // FIXME: check the issue on openGL\n" + " if (ATI_SUCKS == 1 && PS_POINT_SAMPLER == 1)\n" + " {\n" + " // Weird issue with ATI cards (happens on at least HD 4xxx and 5xxx),\n" + " // it looks like they add 127/128 of a texel to sampling coordinates\n" + " // occasionally causing point sampling to erroneously round up.\n" + " // I'm manually adjusting coordinates to the centre of texels here,\n" + " // though the centre is just paranoia, the top left corner works fine.\n" + " uv = (trunc(uv * WH.zw) + vec2(0.5, 0.5)) / WH.zw;\n" + " }\n" + "\n" + " // FIXME I'm not sure it is a good solution to flip texture\n" + " return texture(TextureSampler, uv);\n" + " //FIXME another way to FLIP vertically\n" + " //return texture(TextureSampler, vec2(uv.x, 1.0f-uv.y) );\n" + "}\n" + "\n" + "vec4 sample_p(float u)\n" + "{\n" + " //FIXME do we need a 1D sampler. Big impact on opengl to find 1 dim\n" + " // So for the moment cheat with 0.0f dunno if it work\n" + " return texture(PaletteSampler, vec2(u, 0.0f));\n" + "}\n" + "\n" + "vec4 sample_rt(vec2 uv)\n" + "{\n" + " return texture(RTCopySampler, uv);\n" + "}\n" + "\n" + "vec4 wrapuv(vec4 uv)\n" + "{\n" + " vec4 uv_out = uv;\n" + "\n" + " if(PS_WMS == PS_WMT)\n" + " {\n" + " if(PS_WMS == 2)\n" + " {\n" + " uv_out = clamp(uv, MinMax.xyxy, MinMax.zwzw);\n" + " }\n" + " else if(PS_WMS == 3)\n" + " {\n" + " uv_out = vec4(((ivec4(uv * WH.xyxy) & ivec4(MskFix.xyxy)) | ivec4(MskFix.zwzw)) / WH.xyxy);\n" + " }\n" + " }\n" + " else\n" + " {\n" + " if(PS_WMS == 2)\n" + " {\n" + " uv_out.xz = clamp(uv.xz, MinMax.xx, MinMax.zz);\n" + " }\n" + " else if(PS_WMS == 3)\n" + " {\n" + " uv_out.xz = vec2(((ivec2(uv.xz * WH.xx) & ivec2(MskFix.xx)) | ivec2(MskFix.zz)) / WH.xx);\n" + " }\n" + " if(PS_WMT == 2)\n" + " {\n" + " uv_out.yw = clamp(uv.yw, MinMax.yy, MinMax.ww);\n" + " }\n" + " else if(PS_WMT == 3)\n" + " {\n" + " uv_out.yw = vec2(((ivec2(uv.yw * WH.yy) & ivec2(MskFix.yy)) | ivec2(MskFix.ww)) / WH.yy);\n" + " }\n" + " }\n" + "\n" + " return uv_out;\n" + "}\n" + "\n" + "vec2 clampuv(vec2 uv)\n" + "{\n" + " vec2 uv_out = uv;\n" + "\n" + " if(PS_WMS == 2 && PS_WMT == 2) \n" + " {\n" + " uv_out = clamp(uv, MinF, MinMax.zw);\n" + " }\n" + " else if(PS_WMS == 2)\n" + " {\n" + " uv_out.x = clamp(uv.x, MinF.x, MinMax.z);\n" + " }\n" + " else if(PS_WMT == 2)\n" + " {\n" + " uv_out.y = clamp(uv.y, MinF.y, MinMax.w);\n" + " }\n" + "\n" + " return uv_out;\n" + "}\n" + "\n" + "mat4 sample_4c(vec4 uv)\n" + "{\n" + " mat4 c;\n" + "\n" + " c[0] = sample_c(uv.xy);\n" + " c[1] = sample_c(uv.zy);\n" + " c[2] = sample_c(uv.xw);\n" + " c[3] = sample_c(uv.zw);\n" + "\n" + " return c;\n" + "}\n" + "\n" + "vec4 sample_4a(vec4 uv)\n" + "{\n" + " vec4 c;\n" + "\n" + " // XXX\n" + " // I think .a is related to 8bit texture in alpha channel\n" + " // Opengl is only 8 bits on red channel. Not sure exactly of the impact\n" + " c.x = sample_c(uv.xy).a;\n" + " c.y = sample_c(uv.zy).a;\n" + " c.z = sample_c(uv.xw).a;\n" + " c.w = sample_c(uv.zw).a;\n" + "\n" + " return c * 255./256 + 0.5/256;\n" + "}\n" + "\n" + "mat4 sample_4p(vec4 u)\n" + "{\n" + " mat4 c;\n" + "\n" + " c[0] = sample_p(u.x);\n" + " c[1] = sample_p(u.y);\n" + " c[2] = sample_p(u.z);\n" + " c[3] = sample_p(u.w);\n" + "\n" + " return c;\n" + "}\n" + "\n" + "vec4 sample_color(vec2 st, float q)\n" + "{\n" + " if(PS_FST == 0) st /= q;\n" + "\n" + " if(PS_TCOFFSETHACK == 1) st += TC_OffsetHack.xy;\n" + "\n" + " vec4 t;\n" + " mat4 c;\n" + " vec2 dd;\n" + "\n" + " if (PS_LTF == 0 && PS_FMT <= FMT_16 && PS_WMS < 3 && PS_WMT < 3)\n" + " {\n" + " c[0] = sample_c(clampuv(st));\n" + " }\n" + " else\n" + " {\n" + " vec4 uv;\n" + "\n" + " if(PS_LTF != 0)\n" + " {\n" + " uv = st.xyxy + HalfTexel;\n" + " dd = fract(uv.xy * WH.zw);\n" + " }\n" + " else\n" + " {\n" + " uv = st.xyxy;\n" + " }\n" + "\n" + " uv = wrapuv(uv);\n" + "\n" + " if((PS_FMT & FMT_PAL) != 0)\n" + " {\n" + " c = sample_4p(sample_4a(uv));\n" + " }\n" + " else\n" + " {\n" + " c = sample_4c(uv);\n" + " }\n" + " }\n" + "\n" + " // PERF: see the impact of the exansion before/after the interpolation\n" + " for (int i = 0; i < 4; i++)\n" + " {\n" + " if((PS_FMT & ~FMT_PAL) == FMT_24)\n" + " {\n" + " // FIXME GLSL any only support bvec so try to mix it with notEqual\n" + " bvec3 rgb_check = notEqual( t.rgb, vec3(0.0f, 0.0f, 0.0f) );\n" + " t.a = ( (PS_AEM == 0) || any(rgb_check) ) ? TA.x : 0.0f;\n" + " }\n" + " else if((PS_FMT & ~FMT_PAL) == FMT_16)\n" + " {\n" + " // FIXME GLSL any only support bvec so try to mix it with notEqual\n" + " bvec3 rgb_check = notEqual( t.rgb, vec3(0.0f, 0.0f, 0.0f) );\n" + " t.a = t.a >= 0.5 ? TA.y : ( (PS_AEM == 0) || any(rgb_check) ) ? TA.x : 0.0f;\n" + " }\n" + " }\n" + "\n" + " if(PS_LTF != 0)\n" + " {\n" + " t = mix(mix(c[0], c[1], dd.x), mix(c[2], c[3], dd.x), dd.y);\n" + " }\n" + " else\n" + " {\n" + " t = c[0];\n" + " }\n" + "\n" + " return t;\n" + "}\n" + "\n" + "vec4 tfx(vec4 t, vec4 c)\n" + "{\n" + " vec4 c_out = c;\n" + " if(PS_TFX == 0)\n" + " {\n" + " if(PS_TCC != 0) \n" + " {\n" + " c_out = c * t * 255.0f / 128;\n" + " }\n" + " else\n" + " {\n" + " c_out.rgb = c.rgb * t.rgb * 255.0f / 128;\n" + " }\n" + " }\n" + " else if(PS_TFX == 1)\n" + " {\n" + " if(PS_TCC != 0) \n" + " {\n" + " c_out = t;\n" + " }\n" + " else\n" + " {\n" + " c_out.rgb = t.rgb;\n" + " }\n" + " }\n" + " else if(PS_TFX == 2)\n" + " {\n" + " c_out.rgb = c.rgb * t.rgb * 255.0f / 128 + c.a;\n" + "\n" + " if(PS_TCC != 0) \n" + " {\n" + " c_out.a += t.a;\n" + " }\n" + " }\n" + " else if(PS_TFX == 3)\n" + " {\n" + " c_out.rgb = c.rgb * t.rgb * 255.0f / 128 + c.a;\n" + "\n" + " if(PS_TCC != 0) \n" + " {\n" + " c_out.a = t.a;\n" + " }\n" + " }\n" + "\n" + " return clamp(c_out, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(1.0f, 1.0f, 1.0f, 1.0f));\n" + "}\n" + "\n" + "void datst()\n" + "{\n" + "#if PS_DATE > 0\n" + " float alpha = sample_rt(PSin.tp.xy).a;\n" + " float alpha0x80 = 128. / 255;\n" + "\n" + " if (PS_DATE == 1 && alpha >= alpha0x80)\n" + " discard;\n" + " else if (PS_DATE == 2 && alpha < alpha0x80)\n" + " discard;\n" + "#endif\n" + "}\n" + "\n" + "void atst(vec4 c)\n" + "{\n" + " float a = trunc(c.a * 255 + 0.01);\n" + "\n" + " if(PS_ATST == 0) // never\n" + " {\n" + " discard;\n" + " }\n" + " else if(PS_ATST == 1) // always\n" + " {\n" + " // nothing to do\n" + " }\n" + " else if(PS_ATST == 2 ) // l\n" + " {\n" + " if (PS_SPRITEHACK == 0)\n" + " if ((AREF - a - 0.5f) < 0.0f)\n" + " discard;\n" + " }\n" + " else if(PS_ATST == 3 ) // le\n" + " {\n" + " if ((AREF - a + 0.5f) < 0.0f)\n" + " discard;\n" + " }\n" + " else if(PS_ATST == 4) // e\n" + " {\n" + " if ((0.5f - abs(a - AREF)) < 0.0f)\n" + " discard;\n" + " }\n" + " else if(PS_ATST == 5) // ge\n" + " {\n" + " if ((a-AREF + 0.5f) < 0.0f)\n" + " discard;\n" + " }\n" + " else if(PS_ATST == 6) // g\n" + " {\n" + " if ((a-AREF - 0.5f) < 0.0f)\n" + " discard;\n" + " }\n" + " else if(PS_ATST == 7) // ne\n" + " {\n" + " if ((abs(a - AREF) - 0.5f) < 0.0f)\n" + " discard;\n" + " }\n" + "}\n" + "\n" + "vec4 fog(vec4 c, float f)\n" + "{\n" + " vec4 c_out = c;\n" + " if(PS_FOG != 0)\n" + " {\n" + " c_out.rgb = mix(FogColor, c.rgb, f);\n" + " }\n" + "\n" + " return c_out;\n" + "}\n" + "\n" + "vec4 ps_color()\n" + "{\n" + " datst();\n" + "\n" + " vec4 t = sample_color(PSin.t.xy, PSin.t.w);\n" + "\n" + " vec4 c = tfx(t, PSin.c);\n" + "\n" + " atst(c);\n" + "\n" + " c = fog(c, PSin.t.z);\n" + "\n" + " if (PS_COLCLIP == 2)\n" + " {\n" + " c.rgb = 256.0f/255.0f - c.rgb;\n" + " }\n" + " if (PS_COLCLIP > 0)\n" + " {\n" + " // FIXME !!!!\n" + " //c.rgb *= c.rgb < 128./255;\n" + " bvec3 factor = bvec3(128.0f/255.0f, 128.0f/255.0f, 128.0f/255.0f);\n" + " c.rgb *= vec3(factor);\n" + " }\n" + "\n" + " if(PS_CLR1 != 0) // needed for Cd * (As/Ad/F + 1) blending modes\n" + " {\n" + " c.rgb = vec3(1.0f, 1.0f, 1.0f); \n" + " }\n" + "\n" + " return c;\n" + "}\n" + "\n" + "void ps_main()\n" + "{\n" + " //FIXME\n" + " vec4 c = ps_color();\n" + "\n" + " // FIXME: I'm not sure about the value of others field\n" + " // output.c1 = c.a * 2; // used for alpha blending\n" + "\n" + " float alpha = c.a * 2;\n" + "\n" + " if(PS_AOUT != 0) // 16 bit output\n" + " {\n" + " float a = 128.0f / 255; // alpha output will be 0x80\n" + "\n" + " c.a = (PS_FBA != 0) ? a : step(0.5, c.a) * a;\n" + " }\n" + " else if(PS_FBA != 0)\n" + " {\n" + " if(c.a < 0.5) c.a += 0.5;\n" + " }\n" + "\n" + " SV_Target0 = c;\n" + " SV_Target1 = vec4(alpha, alpha, alpha, alpha);\n" + "}\n" + "#endif\n" + ;

qdRT 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%0A!zhP{X5B*&SK!H)ACjgC3kB|YhQ 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 literal 0 HcmV?d00001 diff --git a/plugins/dev9ghzdrk/pcap/wpcap_32/wpcap.lib b/plugins/dev9ghzdrk/pcap/wpcap_32/wpcap.lib new file mode 100644 index 0000000000000000000000000000000000000000..3c08265db78e8cbb17ae83e70a6fffcd459b8cc4 GIT binary patch literal 17658 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 o{khiWdHyG literal 0 HcmV?d00001 diff --git a/plugins/dev9ghzdrk/pcap/wpcap_64/Packet.dll b/plugins/dev9ghzdrk/pcap/wpcap_64/Packet.dll new file mode 100644 index 0000000000000000000000000000000000000000..102954e96abc488efff5373e45f66a9c7673c4eb GIT binary patch literal 80384 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 literal 0 HcmV?d00001 diff --git a/plugins/dev9ghzdrk/pcap/wpcap_64/Packet.lib b/plugins/dev9ghzdrk/pcap/wpcap_64/Packet.lib new file mode 100644 index 0000000000000000000000000000000000000000..8529e0f0a7f75a55372eec44ae50c2e639b111a4 GIT binary patch literal 8286 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