this is EXPERIMENTAL. Implemented 3 different paths to use depth textures and allow peeking.

they are extremely hard/driver Dependant so your test is needed.
there plugin will automatically select the path thats work for your hard, need that everyone post the messages that the video init throw (yes all will hate me for the messages) but is the only way to see what is the optimal path. in the next commit will clean the unused paths.
i'm afraid thath the second path is Vista dependant (you need to include vista sdk to make it work).
the third path use lockable depth buffer so there is no change in that. 
now peek color is fully working and is fast because the you never lock the the real color texture only the offscreen surface.
please if someone knows a game that use peek color please test it.
also fixed blending so SMS underwater must be fixed.
this work with d3d teach me that i love opengl :)

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4393 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Rodolfo Osvaldo Bogado 2009-10-10 23:36:18 +00:00
parent 9701b88be1
commit 56224bd966
4 changed files with 286 additions and 110 deletions

View File

@ -32,31 +32,6 @@ const bool renderFog = false;
using namespace D3D;
// State translation lookup tables
static const D3DBLEND d3dSrcFactors[8] =
{
D3DBLEND_ZERO,
D3DBLEND_ONE,
D3DBLEND_DESTCOLOR,
D3DBLEND_INVDESTCOLOR,
D3DBLEND_SRCALPHA,
D3DBLEND_INVSRCALPHA,
D3DBLEND_DESTALPHA,
D3DBLEND_INVDESTALPHA
};
static const D3DBLEND d3dDestFactors[8] =
{
D3DBLEND_ZERO,
D3DBLEND_ONE,
D3DBLEND_SRCCOLOR,
D3DBLEND_INVSRCCOLOR,
D3DBLEND_SRCALPHA,
D3DBLEND_INVSRCALPHA,
D3DBLEND_DESTALPHA,
D3DBLEND_INVDESTALPHA
};
static const D3DCULL d3dCullModes[4] =
{
D3DCULL_NONE,
@ -150,42 +125,7 @@ void SetDepthMode(const BPCmd &bp)
void SetBlendMode(const BPCmd &bp)
{
if (bp.changes & 1)
D3D::SetRenderState(D3DRS_ALPHABLENDENABLE, bpmem.blendmode.blendenable);
D3DBLEND src = d3dSrcFactors[bpmem.blendmode.srcfactor];
D3DBLEND dst = d3dDestFactors[bpmem.blendmode.dstfactor];
if (bp.changes & 0x700)
D3D::SetRenderState(D3DRS_SRCBLEND, src);
if (bp.changes & 0xE0)
{
if (!bpmem.blendmode.subtract)
{
D3D::SetRenderState(D3DRS_DESTBLEND, dst);
}
else
{
D3D::SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
}
}
if (bp.changes & 0x800)
{
if (bpmem.blendmode.subtract)
{
D3D::SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
D3D::SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
}
else
{
D3D::SetRenderState(D3DRS_SRCBLEND, src);
D3D::SetRenderState(D3DRS_DESTBLEND, dst);
}
D3D::SetRenderState(D3DRS_BLENDOP,
bpmem.blendmode.subtract ? D3DBLENDOP_SUBTRACT : D3DBLENDOP_ADD);
}
Renderer::SetBlendMode(false);
}
void SetDitherMode(const BPCmd &bp)
{

View File

@ -24,20 +24,33 @@ namespace FBManager
{
static LPDIRECT3DTEXTURE9 s_efb_color_texture;
static LPDIRECT3DTEXTURE9 s_efb_colorBuffer_texture;
static LPDIRECT3DTEXTURE9 s_efb_depth_texture;
static LPDIRECT3DTEXTURE9 s_efb_depthBuffer_texture;
static LPDIRECT3DSURFACE9 s_efb_color_surface;
static LPDIRECT3DSURFACE9 s_efb_depth_surface;
static LPDIRECT3DSURFACE9 s_efb_color_OffScreensurface;
static LPDIRECT3DSURFACE9 s_efb_color_ReadBuffer;
static LPDIRECT3DSURFACE9 s_efb_depth_ReadBuffer;
static LPDIRECT3DSURFACE9 s_efb_color_OffScreenReadBuffer;
static LPDIRECT3DSURFACE9 s_efb_depth_OffScreenReadBuffer;
static D3DFORMAT s_efb_color_surface_Format;
static D3DFORMAT s_efb_depth_surface_Format;
#undef CHECK
#define CHECK(hr) if (FAILED(hr)) { PanicAlert("FAIL: " __FUNCTION__); }
#define CHECK(hr,Message) if (FAILED(hr)) { PanicAlert(__FUNCTION__ " FAIL: %s" ,Message); }
LPDIRECT3DSURFACE9 GetEFBColorRTSurface() { return s_efb_color_surface; }
LPDIRECT3DSURFACE9 GetEFBDepthRTSurface() { return s_efb_depth_surface; }
LPDIRECT3DSURFACE9 GetEFBColorOffScreenRTSurface() { return s_efb_color_OffScreensurface; }
LPDIRECT3DSURFACE9 GetEFBColorOffScreenRTSurface() { return s_efb_color_OffScreenReadBuffer; }
LPDIRECT3DSURFACE9 GetEFBDepthOffScreenRTSurface() { return s_efb_depth_OffScreenReadBuffer; }
LPDIRECT3DSURFACE9 GetEFBColorReadSurface() { return s_efb_color_ReadBuffer; }
LPDIRECT3DSURFACE9 GetEFBDepthReadSurface() { return s_efb_depth_ReadBuffer; }
D3DFORMAT GetEFBDepthRTSurfaceFormat(){return s_efb_depth_surface_Format;}
D3DFORMAT GetEFBColorRTSurfaceFormat(){return s_efb_color_surface_Format;}
@ -47,11 +60,12 @@ LPDIRECT3DTEXTURE9 GetEFBColorTexture(const EFBRectangle& sourceRc)
return s_efb_color_texture;
}
LPDIRECT3DTEXTURE9 GetEFBDepthTexture(const EFBRectangle &sourceRc)
{
// Depth textures not supported under DX9. We're gonna fake this
// with a secondary render target later.
return NULL;
return s_efb_depth_texture;
}
@ -59,56 +73,171 @@ LPDIRECT3DTEXTURE9 GetEFBDepthTexture(const EFBRectangle &sourceRc)
void Create()
{
// Simplest possible setup to start with.
int target_width = Renderer::GetTargetWidth();
int target_height = Renderer::GetTargetHeight();
s_efb_color_surface_Format = D3DFMT_A8R8G8B8;
//get the framebuffer texture
HRESULT hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
D3DPOOL_DEFAULT, &s_efb_color_texture, NULL);
CHECK(hr);
CHECK(hr,"Create Color Texture");
//get the Surface
hr = s_efb_color_texture->GetSurfaceLevel(0, &s_efb_color_surface);
CHECK(hr);
hr = D3D::dev->CreateOffscreenPlainSurface(target_width, target_height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &s_efb_color_OffScreensurface, NULL );
CHECK(hr);
CHECK(hr,"Get Color Surface");
//create a one pixel texture to work as a buffer for peeking
hr = D3D::dev->CreateTexture(1, 1, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
D3DPOOL_DEFAULT, &s_efb_colorBuffer_texture, NULL);
if (!FAILED(hr))
{
//get the surface for the peeking texture
hr = s_efb_colorBuffer_texture->GetSurfaceLevel(0, &s_efb_color_ReadBuffer);
CHECK(hr,"Get Color Pixel Surface");
//create an offscreen surface that we can lock to retrieve the data
hr = D3D::dev->CreateOffscreenPlainSurface(1, 1, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &s_efb_color_OffScreenReadBuffer, NULL );
CHECK(hr,"Create Color offScreen Surface");
}
//Select Zbuffer format supported by hadware.
if (g_ActiveConfig.bEFBAccessEnable)
{
s_efb_depth_surface_Format = D3DFMT_D32F_LOCKABLE;
//depth format in prefered order
D3DFORMAT *DepthTexFormats = new D3DFORMAT[7];
DepthTexFormats[0] = (D3DFORMAT)MAKEFOURCC('D','F','2','4');
DepthTexFormats[1] = (D3DFORMAT)MAKEFOURCC('I','N','T','Z');
DepthTexFormats[2] = (D3DFORMAT)MAKEFOURCC('R','A','W','Z');
DepthTexFormats[3] = (D3DFORMAT)MAKEFOURCC('D','F','1','6');
DepthTexFormats[4] = D3DFMT_D32F_LOCKABLE;
DepthTexFormats[5] = D3DFMT_D16_LOCKABLE;
DepthTexFormats[6] = D3DFMT_D24X8;
for(int i = 0;i<4;i++)
{
s_efb_depth_surface_Format = DepthTexFormats[i];
hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_DEPTHSTENCIL, s_efb_depth_surface_Format,
D3DPOOL_DEFAULT, &s_efb_depth_texture, NULL);
if (!FAILED(hr))
break;
}
CHECK(hr,"Create Depth Texture");
if (!FAILED(hr))
{
//we found a dept texture suported by hardware so get the surface to draw to
hr = s_efb_depth_texture->GetSurfaceLevel(0, &s_efb_depth_surface);
CHECK(hr,"Get Depth Surface");
//create a buffer texture for peeking
hr = D3D::dev->CreateTexture(1, 1, 1, D3DUSAGE_DEPTHSTENCIL, s_efb_depth_surface_Format,
D3DPOOL_DEFAULT, &s_efb_depthBuffer_texture, NULL);
CHECK(hr,"Create Depth Pixel Texture");
if (!FAILED(hr))
{
//texture create correctly so get the surface
hr = s_efb_depthBuffer_texture->GetSurfaceLevel(0, &s_efb_depth_ReadBuffer);
CHECK(hr,"Get Depth Pixel Surface");
// create an ofscren surface to grab the data
hr = D3D::dev->CreateOffscreenPlainSurface(1, 1, s_efb_depth_surface_Format, D3DPOOL_SYSTEMMEM, &s_efb_depth_OffScreenReadBuffer, NULL );
CHECK(hr,"Create Depth offscreen Surface");
if (FAILED(hr))
{
//no depth in system mem so try vista path to grab depth data
//create a offscreen lockeable surface
hr = D3D::dev->CreateOffscreenPlainSurface(1, 1, D3DFMT_D32F_LOCKABLE, D3DPOOL_DEFAULT, &s_efb_depth_OffScreenReadBuffer, NULL );
CHECK(hr,"Create Depth D3DFMT_D32F_LOCKABLE offscreen Surface");
if(s_efb_depth_ReadBuffer)
s_efb_depth_ReadBuffer->Release();
//this is ugly but is a fast way to test wich path to proceed for peeking
s_efb_depth_ReadBuffer = s_efb_depth_OffScreenReadBuffer;
s_efb_depth_surface_Format = D3DFMT_D32F_LOCKABLE;
}
}
}
if (!FAILED(hr))
{
//so far so god, texture depth works so return
delete [] DepthTexFormats;
return;
}
else
{
//no depth texture... cleanup
if(s_efb_depth_ReadBuffer)
s_efb_depth_ReadBuffer->Release();
s_efb_depth_ReadBuffer = NULL;
if(s_efb_depth_OffScreenReadBuffer)
s_efb_depth_OffScreenReadBuffer->Release();
if(s_efb_depth_surface)
s_efb_depth_surface->Release();
s_efb_depth_surface = NULL;
if(s_efb_depthBuffer_texture)
s_efb_depthBuffer_texture->Release();
s_efb_depthBuffer_texture=NULL;
if(s_efb_depth_texture)
s_efb_depth_texture->Release();
s_efb_depth_texture = NULL;
}
// no depth textures... try to create an lockable depth surface
for(int i = 4;i<7;i++)
{
s_efb_depth_surface_Format = DepthTexFormats[i];
hr = D3D::dev->CreateDepthStencilSurface(target_width, target_height, s_efb_depth_surface_Format,
D3DMULTISAMPLE_NONE, 0, FALSE, &s_efb_depth_surface, NULL);
if (!FAILED(hr)) break;
}
s_efb_depth_ReadBuffer = s_efb_depth_surface;
CHECK(hr,"CreateDepthStencilSurface");
delete [] DepthTexFormats;
}
else
{
s_efb_depth_surface_Format = D3DFMT_D24S8;
}
hr = D3D::dev->CreateDepthStencilSurface(target_width, target_height, D3DFMT_D32F_LOCKABLE,
s_efb_depth_surface_Format = D3DFMT_D24X8;
hr = D3D::dev->CreateDepthStencilSurface(target_width, target_height, s_efb_depth_surface_Format,
D3DMULTISAMPLE_NONE, 0, FALSE, &s_efb_depth_surface, NULL);
if (FAILED(hr))
{
s_efb_depth_surface_Format = D3DFMT_D16_LOCKABLE;
hr = D3D::dev->CreateDepthStencilSurface(target_width, target_height, D3DFMT_D16_LOCKABLE,
D3DMULTISAMPLE_NONE, 0, FALSE, &s_efb_depth_surface, NULL);
if(FAILED(hr))
{
s_efb_depth_surface_Format = D3DFMT_D24S8;
hr = D3D::dev->CreateDepthStencilSurface(target_width, target_height, D3DFMT_D24S8,
D3DMULTISAMPLE_NONE, 0, FALSE, &s_efb_depth_surface, NULL);
}
CHECK(hr,"CreateDepthStencilSurface");
}
CHECK(hr);
}
void Destroy()
{
if(s_efb_color_OffScreensurface)
s_efb_color_OffScreensurface->Release();
if(s_efb_depth_ReadBuffer)
s_efb_depth_ReadBuffer->Release();
s_efb_depth_ReadBuffer = NULL;
if(s_efb_depth_OffScreenReadBuffer)
s_efb_depth_OffScreenReadBuffer->Release();
if(s_efb_depth_surface)
s_efb_depth_surface->Release();
s_efb_depth_surface = NULL;
if(s_efb_depthBuffer_texture)
s_efb_depthBuffer_texture->Release();
s_efb_depthBuffer_texture=NULL;
if(s_efb_depth_texture)
s_efb_depth_texture->Release();
s_efb_depth_texture = NULL;
if(s_efb_color_OffScreenReadBuffer )
s_efb_color_OffScreenReadBuffer->Release();
s_efb_color_OffScreenReadBuffer = NULL;
if(s_efb_color_ReadBuffer )
s_efb_color_ReadBuffer->Release();
s_efb_color_ReadBuffer = NULL;
if(s_efb_color_surface)
s_efb_color_surface->Release();
s_efb_color_surface = NULL;
s_efb_color_surface = NULL;
if(s_efb_colorBuffer_texture)
s_efb_colorBuffer_texture->Release();
s_efb_colorBuffer_texture = NULL;
if(s_efb_color_texture)
s_efb_color_texture->Release();

View File

@ -38,6 +38,10 @@ LPDIRECT3DSURFACE9 GetEFBColorOffScreenRTSurface();
LPDIRECT3DSURFACE9 GetEFBDepthOffScreenRTSurface();
D3DFORMAT GetEFBDepthRTSurfaceFormat();
D3DFORMAT GetEFBColorRTSurfaceFormat();
LPDIRECT3DSURFACE9 GetEFBColorReadSurface();
LPDIRECT3DSURFACE9 GetEFBDepthReadSurface();
/*

View File

@ -59,10 +59,37 @@ static int s_recordHeight;
static bool s_LastFrameDumped;
static bool s_AVIDumping;
static u32 s_blendMode;
#define NUMWNDRES 6
extern int g_Res[NUMWNDRES][2];
char st[32768];
// State translation lookup tables
static const D3DBLEND d3dSrcFactors[8] =
{
D3DBLEND_ZERO,
D3DBLEND_ONE,
D3DBLEND_DESTCOLOR,
D3DBLEND_INVDESTCOLOR,
D3DBLEND_SRCALPHA,
D3DBLEND_INVSRCALPHA,
D3DBLEND_DESTALPHA,
D3DBLEND_INVDESTALPHA
};
static const D3DBLEND d3dDestFactors[8] =
{
D3DBLEND_ZERO,
D3DBLEND_ONE,
D3DBLEND_SRCCOLOR,
D3DBLEND_INVSRCCOLOR,
D3DBLEND_SRCALPHA,
D3DBLEND_INVSRCALPHA,
D3DBLEND_DESTALPHA,
D3DBLEND_INVDESTALPHA
};
void SetupDeviceObjects()
{
D3D::font.Init();
@ -100,7 +127,7 @@ bool Renderer::Init()
h_temp = 480;
}
EmuWindow::SetSize(w_temp, h_temp);
s_blendMode = 0;
int backbuffer_ms_mode = 0; // g_ActiveConfig.iMultisampleMode;
sscanf(g_Config.cFSResolution, "%dx%d", &w_temp, &h_temp);
@ -441,24 +468,29 @@ void Renderer::SetColorMask()
u32 Renderer::AccessEFB(EFBAccessType type, int x, int y)
{
//Get the working buffer and it's format
//Get the working buffer
LPDIRECT3DSURFACE9 pBuffer = (type == PEEK_Z || type == POKE_Z) ?
FBManager::GetEFBDepthRTSurface() : FBManager::GetEFBColorRTSurface();
//get the temporal buffer to move 1pixel data
LPDIRECT3DSURFACE9 RBuffer = (type == PEEK_Z || type == POKE_Z) ?
FBManager::GetEFBDepthReadSurface() : FBManager::GetEFBColorReadSurface();
//get the memory buffer that can be locked
LPDIRECT3DSURFACE9 pOffScreenBuffer = (type == PEEK_Z || type == POKE_Z) ?
FBManager::GetEFBDepthRTSurface() : FBManager::GetEFBColorOffScreenRTSurface();
D3DLOCKED_RECT drect;
FBManager::GetEFBDepthOffScreenRTSurface() : FBManager::GetEFBColorOffScreenRTSurface();
//get the buffer format
D3DFORMAT BufferFormat = (type == PEEK_Z || type == POKE_Z) ?
FBManager::GetEFBDepthRTSurfaceFormat() : FBManager::GetEFBColorRTSurfaceFormat();
D3DLOCKED_RECT drect;
//Buffer not found alert
if(!pBuffer) {
PanicAlert("No %s!", (type == PEEK_Z || type == POKE_Z) ? "Z-Buffer" : "Color EFB");
return 0;
}
// Z buffer lock not suported: returning
if((type == PEEK_Z || type == POKE_Z) && BufferFormat == D3DFMT_D24S8)
if((type == PEEK_Z || type == POKE_Z) && BufferFormat == D3DFMT_D24X8)
{
return 0;
}
@ -472,7 +504,6 @@ u32 Renderer::AccessEFB(EFBAccessType type, int x, int y)
TargetRectangle targetPixelRc = Renderer::ConvertEFBRectangle(efbPixelRc);
u32 z = 0;
float val = 0.0f;
HRESULT hr;
@ -484,19 +515,54 @@ u32 Renderer::AccessEFB(EFBAccessType type, int x, int y)
//lock the buffer
if(!(type == PEEK_Z || type == POKE_Z))
if(!(BufferFormat == D3DFMT_D32F_LOCKABLE || BufferFormat == D3DFMT_D16_LOCKABLE))
{
hr = D3D::dev->StretchRect(pBuffer,&RectToLock,pOffScreenBuffer,&RectToLock, D3DTEXF_NONE);
//the hard support stretchrect in both color and z so use it
hr = D3D::dev->StretchRect(pBuffer,&RectToLock,RBuffer,NULL, D3DTEXF_NONE);
if(FAILED(hr))
{
PanicAlert("Unable to stretch data to buffer");
return 0;
}
//retriebe the pixel data to the local memory buffer
D3D::dev->GetRenderTargetData(RBuffer,pOffScreenBuffer);
if(FAILED(hr))
{
PanicAlert("Unable to copy data to mem buffer");
return 0;
}
//change the rect to lock the entire one pixel buffer
RectToLock.bottom = 1;
RectToLock.left = 0;
RectToLock.right = 1;
RectToLock.top = 0;
}
else
{
//like i say in FramebufferManager this is ugly... using the pointers to decide the peek path.. but it works:)
if(BufferFormat == D3DFMT_D32F_LOCKABLE && RBuffer == pOffScreenBuffer)
{
//we are using vista path so use updateSurface to copy depth data
hr = D3D::dev->UpdateSurface(pBuffer,&RectToLock,pOffScreenBuffer,NULL);
if(FAILED(hr))
{
PanicAlert("Unable to update data to mem buffer");
return 0;
}
}
else
{
//we are using lockable depth buffer so change the pointer to lock it directly
pOffScreenBuffer = pBuffer;
}
}
//the surface is good.. lock it
if((hr = pOffScreenBuffer->LockRect(&drect, &RectToLock, D3DLOCK_READONLY)) != D3D_OK)
{
PanicAlert("ERROR: %s", hr == D3DERR_WASSTILLDRAWING ? "Still drawing" :
hr == D3DERR_INVALIDCALL ? "Invalid call" : "w00t");
return 0;
}
switch(type) {
case PEEK_Z:
@ -505,16 +571,19 @@ u32 Renderer::AccessEFB(EFBAccessType type, int x, int y)
{
case D3DFMT_D32F_LOCKABLE:
val = ((float *)drect.pBits)[0];
z = ((u32)(val * 0xffffff));// 0xFFFFFFFF;
break;
case (D3DFORMAT)MAKEFOURCC('D','F','1','6'):
case D3DFMT_D16_LOCKABLE:
val = ((float)((u16 *)drect.pBits)[0])/((float)0xFFFF);
z = ((u32)(val * 0xffffff));
break;
default:
val = 0;
z = ((u32 *)drect.pBits)[0] >> 8;
break;
};
// [0.0, 1.0] ==> [0, 0xFFFFFFFF]
z = ((u32)(val * 0xffffff));// 0xFFFFFFFF;
break;
}
case POKE_Z:
@ -535,17 +604,12 @@ u32 Renderer::AccessEFB(EFBAccessType type, int x, int y)
}
pBuffer->UnlockRect();
pOffScreenBuffer->UnlockRect();
// Scale the 32-bit value returned to a 24-bit
// value (GC uses a 24-bit Z-buffer).
// TODO: in RE0 this value is often off by one, which causes lighting to disappear
return z;//z >> 8;
return z;
DEBUGGER_PAUSE_LOG_AT(NEXT_EFB_CMD,true,{printf("AccessEFB, type = %d",type);});
return 0;
}
// mtx.m[0][3] = pMatrix[1]; // -0.5f/s_target_width; <-- fix d3d pixel center?
@ -616,6 +680,45 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE
D3D::dev->Clear(0, NULL, clearflags, color,(z & 0xFFFFFF) / float(0xFFFFFF), 0);
}
void Renderer::SetBlendMode(bool forceUpdate)
{
// blend mode bit mask
// 0 - blend enable
// 2 - reverse subtract enable (else add)
// 3-5 - srcRGB function
// 6-8 - dstRGB function
u32 newval = bpmem.blendmode.subtract << 2;
if (bpmem.blendmode.subtract) {
newval |= 0x0049; // enable blending src 1 dst 1
} else if (bpmem.blendmode.blendenable) {
newval |= 1; // enable blending
newval |= bpmem.blendmode.srcfactor << 3;
newval |= bpmem.blendmode.dstfactor << 6;
}
u32 changes = forceUpdate ? 0xFFFFFFFF : newval ^ s_blendMode;
if (changes & 1) {
// blend enable change
D3D::SetRenderState(D3DRS_ALPHABLENDENABLE, (newval & 1));
}
if (changes & 4) {
// subtract enable change
D3D::SetRenderState(D3DRS_BLENDOP, newval & 4 ? D3DBLENDOP_REVSUBTRACT : D3DBLENDOP_ADD);
}
if (changes & 0x1F8) {
// blend RGB change
D3D::SetRenderState(D3DRS_SRCBLEND, d3dSrcFactors[(newval >> 3) & 7]);
D3D::SetRenderState(D3DRS_DESTBLEND, d3dDestFactors[(newval >> 6) & 7]);
}
s_blendMode = newval;
}