From f7aae60371c945d272563b32eff9b90bb85d26d5 Mon Sep 17 00:00:00 2001 From: arcum42 Date: Sat, 6 Jun 2009 09:24:10 +0000 Subject: [PATCH] Fixed Linux, and merged a few minor changes I had lying around that I hadn't committed yet. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1336 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/Gif.cpp | 10 +++----- pcsx2/HwRead.cpp | 32 +++++++++++------------- pcsx2/HwWrite.cpp | 46 ++++++++++++++++------------------ pcsx2/IPU/IPU.cpp | 23 ++++++++--------- pcsx2/IPU/IPU.h | 4 +++ pcsx2/SPR.cpp | 4 +-- pcsx2/Sif.cpp | 2 +- pcsx2/VU0.cpp | 2 +- pcsx2/Vif.cpp | 2 +- pcsx2/x86/microVU_Misc.inl | 51 ++++++++++++++++++++++++++++++++++++++ 10 files changed, 111 insertions(+), 65 deletions(-) diff --git a/pcsx2/Gif.cpp b/pcsx2/Gif.cpp index 049ed0191a..ac18745ca9 100644 --- a/pcsx2/Gif.cpp +++ b/pcsx2/Gif.cpp @@ -160,10 +160,7 @@ static __forceinline void dmaGIFend() // not to do the gif->qwc != 0 check. --arcum42 static __forceinline void GIFdmaEnd() { - //if (psHu32(GIF_MODE) & 0x4) CPU_INT(2, gscycles * BIAS); - /*else - CPU_INT(2, min( gifsplit, (int)gif->qwc ) * BIAS);*/ } void GIFdma() @@ -178,7 +175,6 @@ void GIFdma() return; } - if ((psHu32(DMAC_CTRL) & 0xC0) == 0x80 && prevcycles != 0) { // STD == GIF Console::WriteLn("GS Stall Control Source = %x, Drain = %x\n MADR = %x, STADR = %x", params (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3, gif->madr, psHu32(DMAC_STADR)); @@ -324,8 +320,8 @@ void GIFdma() } void dmaGIF() { - //We used to addd wait time for the buffer to fill here, fixing some timing problems in path 3 masking - //It takes the time of 24 QW for the BUS to become ready - The Punisher, And1 Streetball + //We used to add wait time for the buffer to fill here, fixing some timing problems in path 3 masking + //It takes the time of 24 QW for the BUS to become ready - The Punisher And Streetball GIF_LOG("dmaGIFstart chcr = %lx, madr = %lx, qwc = %lx\n tadr = %lx, asr0 = %lx, asr1 = %lx", gif->chcr, gif->madr, gif->qwc, gif->tadr, gif->asr0, gif->asr1); Path3progress = 2; @@ -555,7 +551,7 @@ void gifMFIFOInterrupt() if((spr0->chcr & 0x100) && spr0->qwc == 0) { spr0->chcr &= ~0x100; - hwDmacIrq(8); + hwDmacIrq(DMAC_FROM_SPR); } if(gifstate != GIF_STATE_STALL) { diff --git a/pcsx2/HwRead.cpp b/pcsx2/HwRead.cpp index d1ca5c3b67..d84b9a7da2 100644 --- a/pcsx2/HwRead.cpp +++ b/pcsx2/HwRead.cpp @@ -61,38 +61,37 @@ __forceinline mem8_t hwRead8(u32 mem) switch (mem) { - // Note: the values without defines = the defines + 1. case RCNT0_COUNT: ret = (u8)rcntRcount(0); break; case RCNT0_MODE: ret = (u8)counters[0].modeval; break; case RCNT0_TARGET: ret = (u8)counters[0].target; break; case RCNT0_HOLD: ret = (u8)counters[0].hold; break; - case 0x10000001: ret = (u8)(rcntRcount(0)>>8); break; - case 0x10000011: ret = (u8)(counters[0].modeval>>8); break; - case 0x10000021: ret = (u8)(counters[0].target>>8); break; - case 0x10000031: ret = (u8)(counters[0].hold>>8); break; + case RCNT0_COUNT + 1: ret = (u8)(rcntRcount(0)>>8); break; + case RCNT0_MODE + 1: ret = (u8)(counters[0].modeval>>8); break; + case RCNT0_TARGET + 1: ret = (u8)(counters[0].target>>8); break; + case RCNT0_HOLD + 1: ret = (u8)(counters[0].hold>>8); break; case RCNT1_COUNT: ret = (u8)rcntRcount(1); break; case RCNT1_MODE: ret = (u8)counters[1].modeval; break; case RCNT1_TARGET: ret = (u8)counters[1].target; break; case RCNT1_HOLD: ret = (u8)counters[1].hold; break; - case 0x10000801: ret = (u8)(rcntRcount(1)>>8); break; - case 0x10000811: ret = (u8)(counters[1].modeval>>8); break; - case 0x10000821: ret = (u8)(counters[1].target>>8); break; - case 0x10000831: ret = (u8)(counters[1].hold>>8); break; + case RCNT1_COUNT + 1: ret = (u8)(rcntRcount(1)>>8); break; + case RCNT1_MODE + 1: ret = (u8)(counters[1].modeval>>8); break; + case RCNT1_TARGET + 1: ret = (u8)(counters[1].target>>8); break; + case RCNT1_HOLD + 1: ret = (u8)(counters[1].hold>>8); break; case RCNT2_COUNT: ret = (u8)rcntRcount(2); break; case RCNT2_MODE: ret = (u8)counters[2].modeval; break; case RCNT2_TARGET: ret = (u8)counters[2].target; break; - case 0x10001001: ret = (u8)(rcntRcount(2)>>8); break; - case 0x10001011: ret = (u8)(counters[2].modeval>>8); break; - case 0x10001021: ret = (u8)(counters[2].target>>8); break; + case RCNT2_COUNT + 1: ret = (u8)(rcntRcount(2)>>8); break; + case RCNT2_MODE + 1: ret = (u8)(counters[2].modeval>>8); break; + case RCNT2_TARGET + 1: ret = (u8)(counters[2].target>>8); break; case RCNT3_COUNT: ret = (u8)rcntRcount(3); break; case RCNT3_MODE: ret = (u8)counters[3].modeval; break; case RCNT3_TARGET: ret = (u8)counters[3].target; break; - case 0x10001801: ret = (u8)(rcntRcount(3)>>8); break; - case 0x10001811: ret = (u8)(counters[3].modeval>>8); break; - case 0x10001821: ret = (u8)(counters[3].target>>8); break; + case RCNT3_COUNT + 1: ret = (u8)(rcntRcount(3)>>8); break; + case RCNT3_MODE + 1: ret = (u8)(counters[3].modeval>>8); break; + case RCNT3_TARGET + 1: ret = (u8)(counters[3].target>>8); break; default: if ((mem & 0xffffff0f) == SBUS_F200) @@ -225,7 +224,7 @@ mem32_t __fastcall hwRead32_page_01(u32 mem) // This is used internally to produce two inline versions, one with INTC_HACK, and one without. static __forceinline mem32_t __hwRead32_page_0F( u32 mem, bool intchack ) { - // *Performance Warning* This function is called -A-LOT. Be weary when making changes. It + // *Performance Warning* This function is called -A-LOT. Be wary when making changes. It // could impact FPS significantly. mem &= 0xffff; @@ -258,7 +257,6 @@ static __forceinline mem32_t __hwRead32_page_0F( u32 mem, bool intchack ) return psHu32(0xf240) | 0xF0000102; case 0xf440: // MCH_DRD - if( !((psHu32(0xf430) >> 6) & 0xF) ) { switch ((psHu32(0xf430)>>16) & 0xFFF) diff --git a/pcsx2/HwWrite.cpp b/pcsx2/HwWrite.cpp index f715b4e67b..43659dc34a 100644 --- a/pcsx2/HwWrite.cpp +++ b/pcsx2/HwWrite.cpp @@ -152,24 +152,24 @@ void hwWrite8(u32 mem, u8 value) switch (mem) { case RCNT0_COUNT: rcntWcount(0, value); break; case RCNT0_MODE: rcntWmode(0, (counters[0].modeval & 0xff00) | value); break; - case 0x10000011: rcntWmode(0, (counters[0].modeval & 0xff) | value << 8); break; + case RCNT0_MODE + 1: rcntWmode(0, (counters[0].modeval & 0xff) | value << 8); break; case RCNT0_TARGET: rcntWtarget(0, value); break; case RCNT0_HOLD: rcntWhold(0, value); break; case RCNT1_COUNT: rcntWcount(1, value); break; case RCNT1_MODE: rcntWmode(1, (counters[1].modeval & 0xff00) | value); break; - case 0x10000811: rcntWmode(1, (counters[1].modeval & 0xff) | value << 8); break; + case RCNT1_MODE + 1: rcntWmode(1, (counters[1].modeval & 0xff) | value << 8); break; case RCNT1_TARGET: rcntWtarget(1, value); break; case RCNT1_HOLD: rcntWhold(1, value); break; case RCNT2_COUNT: rcntWcount(2, value); break; case RCNT2_MODE: rcntWmode(2, (counters[2].modeval & 0xff00) | value); break; - case 0x10001011: rcntWmode(2, (counters[2].modeval & 0xff) | value << 8); break; + case RCNT2_MODE + 1: rcntWmode(2, (counters[2].modeval & 0xff) | value << 8); break; case RCNT2_TARGET: rcntWtarget(2, value); break; case RCNT3_COUNT: rcntWcount(3, value); break; case RCNT3_MODE: rcntWmode(3, (counters[3].modeval & 0xff00) | value); break; - case 0x10001811: rcntWmode(3, (counters[3].modeval & 0xff) | value << 8); break; + case RCNT3_MODE + 1: rcntWmode(3, (counters[3].modeval & 0xff) | value << 8); break; case RCNT3_TARGET: rcntWtarget(3, value); break; case SIO_TXFIFO: @@ -193,7 +193,7 @@ void hwWrite8(u32 mem, u8 value) //case 0x10003c02: //Tony Hawks Project 8 uses this // vif1Write32(mem & ~0x2, value << 16); // break; - case 0x10008001: // dma0 - vif0 + case D0_CHCR + 1: // dma0 - vif0 DMA_LOG("VIF0dma EXECUTE, value=0x%x", value); if ((value & 0x1) && !(psHu32(DMAC_CTRL) & 0x1)) { @@ -203,7 +203,7 @@ void hwWrite8(u32 mem, u8 value) DmaExec8(dmaVIF0, mem, value); break; - case 0x10009001: // dma1 - vif1 + case D1_CHCR + 1: // dma1 - vif1 DMA_LOG("VIF1dma EXECUTE, value=0x%x", value); if ((value & 0x1) && !(psHu32(DMAC_CTRL) & 0x1)) { @@ -214,7 +214,7 @@ void hwWrite8(u32 mem, u8 value) DmaExec8(dmaVIF1, mem, value); break; - case 0x1000a001: // dma2 - gif + case D2_CHCR + 1: // dma2 - gif DMA_LOG("GSdma EXECUTE, value=0x%x", value); if ((value & 0x1) && !(psHu32(DMAC_CTRL) & 0x1)) { @@ -224,7 +224,7 @@ void hwWrite8(u32 mem, u8 value) DmaExec8(dmaGIF, mem, value); break; - case 0x1000b001: // dma3 - fromIPU + case D3_CHCR + 1: // dma3 - fromIPU DMA_LOG("IPU0dma EXECUTE, value=0x%x", value); if ((value & 0x1) && !(psHu32(DMAC_CTRL) & 0x1)) { @@ -234,7 +234,7 @@ void hwWrite8(u32 mem, u8 value) DmaExec8(dmaIPU0, mem, value); break; - case 0x1000b401: // dma4 - toIPU + case D4_CHCR + 1: // dma4 - toIPU DMA_LOG("IPU1dma EXECUTE, value=0x%x", value); if ((value & 0x1) && !(psHu32(DMAC_CTRL) & 0x1)) { @@ -244,7 +244,7 @@ void hwWrite8(u32 mem, u8 value) DmaExec8(dmaIPU1, mem, value); break; - case 0x1000c001: // dma5 - sif0 + case D5_CHCR + 1: // dma5 - sif0 DMA_LOG("SIF0dma EXECUTE, value=0x%x", value); // if (value == 0) psxSu32(0x30) = 0x40000; if ((value & 0x1) && !(psHu32(DMAC_CTRL) & 0x1)) @@ -255,7 +255,7 @@ void hwWrite8(u32 mem, u8 value) DmaExec8(dmaSIF0, mem, value); break; - case 0x1000c401: // dma6 - sif1 + case D6_CHCR + 1: // dma6 - sif1 DMA_LOG("SIF1dma EXECUTE, value=0x%x", value); if ((value & 0x1) && !(psHu32(DMAC_CTRL) & 0x1)) { @@ -265,7 +265,7 @@ void hwWrite8(u32 mem, u8 value) DmaExec8(dmaSIF1, mem, value); break; - case 0x1000c801: // dma7 - sif2 + case D7_CHCR + 1: // dma7 - sif2 DMA_LOG("SIF2dma EXECUTE, value=0x%x", value); if ((value & 0x1) && !(psHu32(DMAC_CTRL) & 0x1)) { @@ -275,7 +275,7 @@ void hwWrite8(u32 mem, u8 value) DmaExec8(dmaSIF2, mem, value); break; - case 0x1000d001: // dma8 - fromSPR + case D8_CHCR + 1: // dma8 - fromSPR DMA_LOG("fromSPRdma8 EXECUTE, value=0x%x", value); if ((value & 0x1) && !(psHu32(DMAC_CTRL) & 0x1)) { @@ -285,7 +285,7 @@ void hwWrite8(u32 mem, u8 value) DmaExec8(dmaSPR0, mem, value); break; - case 0x1000d401: // dma9 - toSPR + case SPR1_CHCR + 1: // dma9 - toSPR DMA_LOG("toSPRdma8 EXECUTE, value=0x%x", value); if ((value & 0x1) && !(psHu32(DMAC_CTRL) & 0x1)) { @@ -295,7 +295,7 @@ void hwWrite8(u32 mem, u8 value) DmaExec8(dmaSPR1, mem, value); break; - case 0x1000f592: // DMAC_ENABLEW + 2 + case DMAC_ENABLEW + 2: psHu8(0xf592) = value; psHu8(0xf522) = value; break; @@ -316,7 +316,7 @@ void hwWrite8(u32 mem, u8 value) psHu8(mem) = value; break; - case SBUS_F240:// SIF(?) + case SBUS_F240: if (!(value & 0x100)) psHu32(mem) &= ~0x100; break; @@ -540,7 +540,7 @@ __forceinline void hwWrite16(u32 mem, u16 value) DmaExec16(dmaSIF0, mem, value); break; - case 0x1000c002: // D5_CHCR + 2 + case D5_CHCR + 2: //? break; @@ -586,7 +586,7 @@ __forceinline void hwWrite16(u32 mem, u16 value) DmaExec16(dmaSIF2, mem, value); break; - case 0x1000c802: // D7_CHCR + 2 + case D7_CHCR + 2: //? break; @@ -610,17 +610,17 @@ __forceinline void hwWrite16(u32 mem, u16 value) DmaExec16(dmaSPR1, mem, value); break; - case 0x1000f592: // DMAC_ENABLEW + 2 + case DMAC_ENABLEW + 2: psHu16(0xf592) = value; psHu16(0xf522) = value; break; case SIO_ISR: - case 0x1000f132: + case SIO_ISR + 2: case 0x1000f410: - case 0x1000f412: + case 0x1000f410 + 2: case MCH_RICM: - case 0x1000f432: + case MCH_RICM + 2: break; case SBUS_F200: @@ -1139,8 +1139,6 @@ void __fastcall hwWrite64_page_0E( u32 mem, const mem64_t* srcval ) void __fastcall hwWrite64_generic( u32 mem, const mem64_t* srcval ) { - //hwWrite64( mem, *srcval ); return; - const u64 value = *srcval; switch (mem) diff --git a/pcsx2/IPU/IPU.cpp b/pcsx2/IPU/IPU.cpp index 8a183e91a2..a47e1ad681 100644 --- a/pcsx2/IPU/IPU.cpp +++ b/pcsx2/IPU/IPU.cpp @@ -241,7 +241,7 @@ void SaveState::ipuFreeze() bool ipuCanFreeze() { - return ipuCurCmd == 0xffffffff; + return (ipuCurCmd == 0xffffffff); } __forceinline u32 ipuRead32(u32 mem) @@ -256,7 +256,7 @@ __forceinline u32 ipuRead32(u32 mem) switch (mem) { - case 0x10: // IPU_CTRL + ipucase(IPU_CTRL): // IPU_CTRL ipuRegs->ctrl.IFC = g_BP.IFC; ipuRegs->ctrl.CBP = coded_block_pattern; @@ -265,7 +265,7 @@ __forceinline u32 ipuRead32(u32 mem) return ipuRegs->ctrl._u32; - case 0x20: // IPU_BP + ipucase(IPU_BP): // IPU_BP ipuRegs->ipubp = g_BP.BP & 0x7f; ipuRegs->ipubp |= g_BP.IFC << 8; @@ -290,20 +290,20 @@ __forceinline u64 ipuRead64(u32 mem) switch (mem) { - case 0x00: // IPU_CMD - if (ipuRegs->cmd.DATA&0xffffff) + ipucase(IPU_CMD): // IPU_CMD + if (ipuRegs->cmd.DATA & 0xffffff) IPU_LOG("Ipu read64: IPU_CMD=BUSY=%x, DATA=%08X", ipuRegs->cmd.BUSY ? 1 : 0, ipuRegs->cmd.DATA); break; - case 0x10: + ipucase(IPU_CTRL): DevCon::Notice("reading 64bit IPU ctrl"); break; - case 0x20: + ipucase(IPU_BP): DevCon::Notice("reading 64bit IPU top"); break; - case 0x30: // IPU_TOP + ipucase(IPU_TOP): // IPU_TOP IPU_LOG("Ipu read64: IPU_TOP=%x, bp = %d", ipuRegs->top, g_BP.BP); break; @@ -348,12 +348,12 @@ __forceinline void ipuWrite32(u32 mem, u32 value) switch (mem) { - case 0x00: // IPU_CMD + ipucase(IPU_CMD): // IPU_CMD IPU_LOG("Ipu write32: IPU_CMD=0x%08X", value); IPUCMD_WRITE(value); break; - case 0x10: // IPU_CTRL + ipucase(IPU_CTRL): // IPU_CTRL ipuRegs->ctrl._u32 = (value & 0x47f30000) | (ipuRegs->ctrl._u32 & 0x8000ffff); if (ipuRegs->ctrl.IDP == 3) { @@ -385,7 +385,7 @@ __forceinline void ipuWrite64(u32 mem, u64 value) switch (mem) { - case 0x00: + ipucase(IPU_CMD): IPU_LOG("Ipu write64: IPU_CMD=0x%08X", value); IPUCMD_WRITE((u32)value); break; @@ -788,7 +788,6 @@ __forceinline void IPU_INTERRUPT() //dma void IPUCMD_WRITE(u32 val) { - // don't process anything if currently busy if (ipuRegs->ctrl.BUSY) Console::WriteLn("IPU BUSY!"); // wait for thread diff --git a/pcsx2/IPU/IPU.h b/pcsx2/IPU/IPU.h index b644887550..c148bac652 100644 --- a/pcsx2/IPU/IPU.h +++ b/pcsx2/IPU/IPU.h @@ -41,6 +41,10 @@ #pragma pack(1) #endif + +#define ipumsk( src ) ( (src) & 0xff ) +#define ipucase( src ) case ipumsk(src) + // // Bitfield Structure // diff --git a/pcsx2/SPR.cpp b/pcsx2/SPR.cpp index 5c5291fad0..702cdb3306 100644 --- a/pcsx2/SPR.cpp +++ b/pcsx2/SPR.cpp @@ -241,7 +241,7 @@ void SPRFROMinterrupt() } if (spr0finished == 0) return; spr0->chcr &= ~0x100; - hwDmacIrq(8); + hwDmacIrq(DMAC_FROM_SPR); } @@ -418,7 +418,7 @@ void SPRTOinterrupt() _dmaSPR1(); if (spr1finished == 0) return; spr1->chcr &= ~0x100; - hwDmacIrq(9); + hwDmacIrq(DMAC_TO_SPR); } void SaveState::sprFreeze() diff --git a/pcsx2/Sif.cpp b/pcsx2/Sif.cpp index 940fa7a266..d6b9469d9d 100644 --- a/pcsx2/Sif.cpp +++ b/pcsx2/Sif.cpp @@ -495,7 +495,7 @@ __forceinline void dmaSIF2() sif2dma->chcr, sif2dma->madr, sif2dma->qwc); sif2dma->chcr &= ~0x100; - hwDmacIrq(7); + hwDmacIrq(DMAC_SIF2); Console::WriteLn("*PCSX2*: dmaSIF2"); } diff --git a/pcsx2/VU0.cpp b/pcsx2/VU0.cpp index 2b6c831f6d..a017527406 100644 --- a/pcsx2/VU0.cpp +++ b/pcsx2/VU0.cpp @@ -108,7 +108,7 @@ namespace OpcodeImpl // Asadr.Changed //TODO: check this - // HUH why ? doesn;t make any sense ... + // HUH why ? doesn't make any sense ... void SQC2() { u32 addr = _Imm_ + cpuRegs.GPR.r[_Rs_].UL[0]; //memWrite64(addr, VU0.VF[_Ft_].UD[0]); diff --git a/pcsx2/Vif.cpp b/pcsx2/Vif.cpp index 73e874c9f7..a3c7cfc4fa 100644 --- a/pcsx2/Vif.cpp +++ b/pcsx2/Vif.cpp @@ -547,7 +547,7 @@ void vifMFIFOInterrupt() if((spr0->chcr & 0x100) && spr0->qwc == 0) { spr0->chcr &= ~0x100; - hwDmacIrq(8); + hwDmacIrq(DMAC_FROM_SPR); } if (vif1.inprogress == 1) mfifo_VIF1chain(); diff --git a/pcsx2/x86/microVU_Misc.inl b/pcsx2/x86/microVU_Misc.inl index 7660b14479..e2379dac43 100644 --- a/pcsx2/x86/microVU_Misc.inl +++ b/pcsx2/x86/microVU_Misc.inl @@ -438,6 +438,7 @@ void SSE_ADD2PS_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { // Micro VU - Custom Quick Search //------------------------------------------------------------------ +#ifndef __LINUX__ // Generates a custom optimized block-search function (Note: Structs must be 16-byte aligned!) static __declspec(naked) u32 __fastcall mVUsearchXMM(void *dest, void *src) { @@ -484,3 +485,53 @@ exitPoint: ret } } +#else +// Generates a custom optimized block-search function (Note: Structs must be 16-byte aligned!) +static u32 __fastcall mVUsearchXMM(void *dest, void *src) +{ + __asm__ + ( + ".intel_syntax noprefix\n" + "movaps xmm0, [ecx]\n" + "pcmpeqd xmm0, [edx]\n" + "movaps xmm1, [ecx + 0x10]\n" + "pcmpeqd xmm1, [edx + 0x10]\n" + "pand xmm0, xmm1\n" + + "movmskps eax, xmm0\n" + "cmp eax, 0xf\n" + "jl exitPoint\n" + + "movaps xmm0, [ecx + 0x20]\n" + "pcmpeqd xmm0, [edx + 0x20]\n" + "movaps xmm1, [ecx + 0x30]\n" + "pcmpeqd xmm1, [edx + 0x30]\n" + "pand xmm0, xmm1\n" + + "movaps xmm2, [ecx + 0x40]\n" + "pcmpeqd xmm2, [edx + 0x40]\n" + "movaps xmm3, [ecx + 0x50]\n" + "pcmpeqd xmm3, [edx + 0x50]\n" + "pand xmm2, xmm3\n" + + "movaps xmm4, [ecx + 0x60]\n" + "pcmpeqd xmm4, [edx + 0x60]\n" + "movaps xmm5, [ecx + 0x70]\n" + "pcmpeqd xmm5, [edx + 0x70]\n" + "pand xmm4, xmm5\n" + + "movaps xmm6, [ecx + 0x80]\n" + "pcmpeqd xmm6, [edx + 0x80]\n" + "movaps xmm7, [ecx + 0x90]\n" + "pcmpeqd xmm7, [edx + 0x90]\n" + "pand xmm6, xmm7\n" + + "pand xmm0, xmm2\n" + "pand xmm4, xmm6\n" + "pand xmm0, xmm4\n" + "movmskps eax, xmm0\n" +"exitPoint:\n" + ".att_syntax\n" + ); +} +#endif