Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/Makefile.kmk	(revision 51312)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/Makefile.kmk	(revision 51313)
@@ -176,5 +176,4 @@
 	VBOX_WITH_WINE_FIX_SURFUPDATA \
 	VBOX_WITH_WINE_FIX_CURVBO \
-	VBOX_WITH_WINE_FIX_ZEROVERTATTR \
 	VBOX_WITH_WINE_FIX_FTOA \
 	VBOX_WITH_WINE_DBG
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/context.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/context.c	(revision 51312)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/context.c	(revision 51313)
@@ -1919,4 +1919,5 @@
      * this is a kinda hack, but it is needed since our ogl driver currently does not support ShareLists */
     pglChromiumParameteriCR(GL_SHARE_CONTEXT_RESOURCES_CR, GL_TRUE);
+    pglChromiumParameteriCR(GL_CHECK_ZERO_VERT_ARRT, GL_TRUE);
 # if defined(VBOX_WINE_WITH_SINGLE_CONTEXT) || defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
     pglChromiumParameteriCR(GL_FLUSH_ON_THREAD_SWITCH_CR,  GL_TRUE);
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/device.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/device.c	(revision 51312)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/device.c	(revision 51313)
@@ -1341,5 +1341,7 @@
     gl_info = context->gl_info;
 
+#ifdef VBOX_WITH_WINE_FIX_ZEROVERTATTR
     zv_destroy(device);
+#endif
 
     if (device->logo_surface)
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/state.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/state.c	(revision 51312)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/state.c	(revision 51313)
@@ -4136,4 +4136,7 @@
 #endif
             {
+#ifdef DEBUG_misha
+                Assert(i);
+#endif
 
             if (context->numbered_array_mask & (1 << i))
@@ -4225,4 +4228,7 @@
 #endif
             {
+#ifdef DEBUG_misha
+                Assert(i);
+#endif
 
             if (context->numbered_array_mask & (1 << i)) unload_numbered_array(context, i);
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/wined3d_gl.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/wined3d_gl.h	(revision 51312)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/wined3d_gl.h	(revision 51313)
@@ -189,4 +189,7 @@
 /*configures host to create windows initially hidden*/
 #define GL_HOST_WND_CREATED_HIDDEN_CR 0x8B2B
+
+/* enable zero vertex attribute generation to work around wine bug */
+#define GL_CHECK_ZERO_VERT_ARRT       0x8B30
 
 typedef void (WINE_GLAPI *PGLFNCHROMIUMPARAMETERUCR)(GLenum param, GLint value);
Index: /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu.h
===================================================================
--- /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu.h	(revision 51312)
+++ /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu.h	(revision 51313)
@@ -28,4 +28,24 @@
 typedef struct thread_info_t ThreadInfo;
 typedef struct context_info_t ContextInfo;
+typedef struct zvabuffer_info_t ZvaBufferInfo;
+
+struct zvabuffer_info_t
+{
+    /* GL_ARRAY_BUFFER_ARB buffer */
+    GLuint idBuffer;
+    /* buffer length */
+    GLuint cbBuffer;
+    /* number of values stored in the buffer currently */
+    GLuint cValues;
+    /* current buffer value */
+    union
+    {
+        GLfloat f[4];
+        GLuint ui[4];
+        GLubyte ub[4];
+        GLshort s[4];
+        GLushort us[4];
+    } Value;
+};
 
 struct thread_info_t {
@@ -48,5 +68,7 @@
     GLint serverCtx;         /* context ID returned by server */
     GLboolean  fAutoFlush;
+    GLboolean  fCheckZerroVertAttr;
     ThreadInfo *currentThread;
+    ZvaBufferInfo zvaBufferInfo;
     GLubyte glVersion[100];     /* GL_VERSION string */
     GLubyte pszRealVendor[100];
@@ -76,7 +98,7 @@
 #endif
 
-#ifdef VBOX_WITH_CRPACKSPU_DUMPER
     SPUDispatchTable self;
 
+#ifdef VBOX_WITH_CRPACKSPU_DUMPER
     CR_RECORDER Recorder;
     CR_DBGPRINT_DUMPER Dumper;
Index: /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_client.c
===================================================================
--- /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_client.c	(revision 51312)
+++ /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_client.c	(revision 51313)
@@ -9,4 +9,5 @@
 #include "cr_glstate.h"
 #include "packspu_proto.h"
+#include "cr_mem.h"
 
 void PACKSPU_APIENTRY packspu_FogCoordPointerEXT( GLenum type, GLsizei stride, const GLvoid *pointer )
@@ -173,4 +174,166 @@
 }
 
+#ifdef DEBUG_misha
+/* debugging */
+//# define CR_FORCE_ZVA_SERVER_ARRAY
+#endif
+# define CR_FORCE_ZVA_EXPAND
+
+
+GLboolean packspuZvaCreate(ContextInfo *pCtx, const GLfloat *pValue, GLuint cValues)
+{
+    ZvaBufferInfo *pInfo = &pCtx->zvaBufferInfo;
+    GLuint cbValue = 4 * sizeof (*pValue);
+    GLuint cbValues = cValues * cbValue;
+    GLfloat *pBuffer;
+    uint8_t *pu8Buf;
+    GLuint i;
+
+    /* quickly sort out if we can use the current value */
+    if (pInfo->idBuffer
+            && pInfo->cValues >= cValues
+            && !memcmp(pValue, &pInfo->Value, cbValue))
+        return GL_FALSE;
+
+    pBuffer = (GLfloat*)crAlloc(cbValues);
+    if (!pBuffer)
+    {
+        WARN(("crAlloc for pBuffer failed"));
+        return GL_FALSE;
+    }
+
+    pu8Buf = (uint8_t *)pBuffer;
+    for (i = 0; i < cValues; ++i)
+    {
+        memcpy(pu8Buf, pValue, cbValue);
+        pu8Buf += cbValue;
+    }
+
+    /* */
+    if (!pInfo->idBuffer)
+    {
+        pack_spu.self.GenBuffersARB(1, &pInfo->idBuffer);
+        Assert(pInfo->idBuffer);
+    }
+
+    pack_spu.self.BindBufferARB(GL_ARRAY_BUFFER_ARB, pInfo->idBuffer);
+
+    if (pInfo->cbBuffer < cbValues)
+    {
+        pack_spu.self.BufferDataARB(GL_ARRAY_BUFFER_ARB, cbValues, pBuffer, GL_DYNAMIC_DRAW_ARB);
+        pInfo->cbBuffer = cbValues;
+    }
+    else
+    {
+        pack_spu.self.BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, cbValues, pBuffer);
+    }
+
+    pInfo->cValues = cValues;
+    memcpy(&pInfo->Value, pValue, cbValue);
+
+    crFree(pBuffer);
+
+    return GL_TRUE;
+}
+
+typedef struct
+{
+    ContextInfo *pCtx;
+    GLuint idBuffer;
+    CRClientPointer cp;
+} CR_ZVA_RESTORE_CTX;
+
+void packspuZvaEnable(ContextInfo *pCtx, const GLfloat *pValue, GLuint cValues, CR_ZVA_RESTORE_CTX *pRestoreCtx)
+{
+    CRContext *g = pCtx->clientState;
+
+    Assert(0);
+
+#ifdef DEBUG
+    {
+        CRContext *pCurState = crStateGetCurrent();
+
+        Assert(g == pCurState);
+    }
+#endif
+
+    pRestoreCtx->pCtx = pCtx;
+    pRestoreCtx->idBuffer = g->bufferobject.arrayBuffer ? g->bufferobject.arrayBuffer->id : 0;
+    pRestoreCtx->cp = g->client.array.a[0];
+
+    Assert(!pRestoreCtx->cp.enabled);
+
+    /* buffer ref count mechanism does not work actually atm,
+     * still ensure the buffer does not get destroyed if we fix it in the future */
+    if (pRestoreCtx->cp.buffer)
+        pRestoreCtx->cp.buffer->refCount++;
+
+    packspuZvaCreate(pCtx, pValue, cValues);
+
+    pack_spu.self.BindBufferARB(GL_ARRAY_BUFFER_ARB, pCtx->zvaBufferInfo.idBuffer);
+
+    pack_spu.self.VertexAttribPointerARB(0, 4, GL_FLOAT,
+            GL_FALSE, /*normalized*/
+            0, /*stride*/
+            NULL /*addr*/);
+
+    pack_spu.self.EnableVertexAttribArrayARB(0);
+}
+
+void packspuZvaDisable(CR_ZVA_RESTORE_CTX *pRestoreCtx)
+{
+    if (pRestoreCtx->cp.buffer)
+        pack_spu.self.BindBufferARB(GL_ARRAY_BUFFER_ARB, pRestoreCtx->cp.buffer->id);
+    else
+        pack_spu.self.BindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+
+    pack_spu.self.VertexAttribPointerARB(0, pRestoreCtx->cp.size, pRestoreCtx->cp.type,
+            pRestoreCtx->cp.normalized, /*normalized*/
+            pRestoreCtx->cp.stride, /*stride*/
+            pRestoreCtx->cp.p);
+
+    if (pRestoreCtx->cp.enabled)
+        pack_spu.self.EnableVertexAttribArrayARB(0);
+    else
+        pack_spu.self.DisableVertexAttribArrayARB(0);
+
+    if (pRestoreCtx->cp.buffer)
+    {
+        if (pRestoreCtx->cp.buffer->id != pRestoreCtx->idBuffer)
+            pack_spu.self.BindBufferARB(GL_ARRAY_BUFFER_ARB, pRestoreCtx->idBuffer);
+
+        /* we have increased the refcount above, decrease it back */
+        pRestoreCtx->cp.buffer->refCount--;
+    }
+    else
+    {
+        if (pRestoreCtx->idBuffer)
+            pack_spu.self.BindBufferARB(GL_ARRAY_BUFFER_ARB, pRestoreCtx->idBuffer);
+    }
+
+#ifdef DEBUG
+    {
+        CRContext *g = pRestoreCtx->pCtx->clientState;
+        CRContext *pCurState = crStateGetCurrent();
+
+        Assert(g == pCurState);
+
+        Assert(pRestoreCtx->cp.p == g->client.array.a[0].p);
+        Assert(pRestoreCtx->cp.size == g->client.array.a[0].size);
+        Assert(pRestoreCtx->cp.type == g->client.array.a[0].type);
+        Assert(pRestoreCtx->cp.stride == g->client.array.a[0].stride);
+        Assert(pRestoreCtx->cp.enabled == g->client.array.a[0].enabled);
+        Assert(pRestoreCtx->cp.normalized == g->client.array.a[0].normalized);
+        Assert(pRestoreCtx->cp.bytesPerIndex == g->client.array.a[0].bytesPerIndex);
+# ifdef CR_ARB_vertex_buffer_object
+        Assert(pRestoreCtx->cp.buffer == g->client.array.a[0].buffer);
+# endif
+# ifdef CR_EXT_compiled_vertex_array
+        Assert(pRestoreCtx->cp.locked == g->client.array.a[0].locked);
+# endif
+        Assert(pRestoreCtx->idBuffer == (g->bufferobject.arrayBuffer ? g->bufferobject.arrayBuffer->id : 0));
+    }
+#endif
+}
 
 void PACKSPU_APIENTRY
@@ -180,4 +343,6 @@
 #if 1
     GLboolean serverArrays = GL_FALSE;
+    GLuint cZvaValues = 0;
+    GLfloat aAttrib[4];
 
 #if CR_ARB_vertex_buffer_object
@@ -185,10 +350,21 @@
     /*crDebug("packspu_ArrayElement index:%i", index);*/
     if (ctx->clientState->extensions.ARB_vertex_buffer_object)
+    {
         serverArrays = crStateUseServerArrays();
-#endif
-
-    if (serverArrays) {
+        if (ctx->fCheckZerroVertAttr)
+            cZvaValues = crStateNeedDummyZeroVertexArray(thread->currentContext->clientState, &thread->packer->current, aAttrib);
+    }
+#endif
+
+    if (serverArrays
+#ifdef CR_FORCE_ZVA_EXPAND
+            && !cZvaValues
+#endif
+            ) {
+        CR_ZVA_RESTORE_CTX RestoreCtx;
         GET_CONTEXT(ctx);
         CRClientState *clientState = &(ctx->clientState->client);
+
+        Assert(cZvaValues < UINT32_MAX/2);
 
         /* LockArraysEXT can not be executed between glBegin/glEnd pair, it also
@@ -198,4 +374,7 @@
         CRASSERT(!clientState->array.locked || clientState->array.synced);
 
+        if (cZvaValues)
+            packspuZvaEnable(ctx, aAttrib, cZvaValues, &RestoreCtx);
+
         /* Send the DrawArrays command over the wire */
         if (pack_spu.swap)
@@ -203,4 +382,7 @@
         else
             crPackArrayElement( index );
+
+        if (cZvaValues)
+            packspuZvaDisable(&RestoreCtx);
     }
     else {
@@ -208,17 +390,33 @@
         GET_CONTEXT(ctx);
         CRClientState *clientState = &(ctx->clientState->client);
-        if (pack_spu.swap)
-            crPackExpandArrayElementSWAP( index, clientState );
-        else
-            crPackExpandArrayElement( index, clientState );
+
+#ifdef CR_FORCE_ZVA_SERVER_ARRAY
+        CR_ZVA_RESTORE_CTX RestoreCtx;
+
+        if (cZvaValues && cZvaValues < UINT32_MAX/2)
+            packspuZvaEnable(ctx, aAttrib, cZvaValues, &RestoreCtx);
+#endif
+
+        if (pack_spu.swap)
+            crPackExpandArrayElementSWAP( index, clientState, cZvaValues ? aAttrib : NULL );
+        else
+            crPackExpandArrayElement( index, clientState, cZvaValues ? aAttrib : NULL );
+
+#ifdef CR_FORCE_ZVA_SERVER_ARRAY
+        if (cZvaValues && cZvaValues < UINT32_MAX/2)
+            packspuZvaDisable(&RestoreCtx);
+#endif
     }
 #else
     GET_CONTEXT(ctx);
     CRClientState *clientState = &(ctx->clientState->client);
-    crPackExpandArrayElement(index, clientState);
+    crPackExpandArrayElement(index, clientState, NULL);
 #endif
 }
 
 /*#define CR_USE_LOCKARRAYS*/
+#ifdef CR_USE_LOCKARRAYS
+# error "check Zero Vertex Attrib hack is supported properly!"
+#endif
 
 void PACKSPU_APIENTRY
@@ -226,4 +424,6 @@
 {
     GLboolean serverArrays = GL_FALSE;
+    GLuint cZvaValues = 0;
+    GLfloat aAttrib[4];
 
 #if CR_ARB_vertex_buffer_object
@@ -233,5 +433,9 @@
     /*crDebug("DrawElements count=%d, indices=%p", count, indices);*/
     if (ctx->clientState->extensions.ARB_vertex_buffer_object)
+    {
         serverArrays = crStateUseServerArrays();
+        if (ctx->fCheckZerroVertAttr)
+            cZvaValues = crStateNeedDummyZeroVertexArray(thread->currentContext->clientState, &thread->packer->current, aAttrib);
+    }
 
 # ifdef CR_USE_LOCKARRAYS
@@ -298,8 +502,18 @@
 #endif
 
-    if (serverArrays) {
+    if (serverArrays
+#ifdef CR_FORCE_ZVA_EXPAND
+            && !cZvaValues
+#endif
+            ) {
+        CR_ZVA_RESTORE_CTX RestoreCtx;
         GET_CONTEXT(ctx);
         CRClientState *clientState = &(ctx->clientState->client);
 
+        Assert(cZvaValues < UINT32_MAX/2);
+
+        if (cZvaValues)
+            packspuZvaEnable(ctx, aAttrib, cZvaValues, &RestoreCtx);
+
         /*Note the comment in packspu_LockArraysEXT*/
         if (clientState->array.locked && !clientState->array.synced)
@@ -308,4 +522,5 @@
             clientState->array.synced = GL_TRUE;
         }
+
         /* Send the DrawArrays command over the wire */
         if (pack_spu.swap)
@@ -313,4 +528,7 @@
         else
             crPackDrawElements( mode, count, type, indices );
+
+        if (cZvaValues)
+            packspuZvaDisable(&RestoreCtx);
     }
     else {
@@ -318,12 +536,25 @@
         GET_CONTEXT(ctx);
         CRClientState *clientState = &(ctx->clientState->client);
-        if (pack_spu.swap)
-            crPackExpandDrawElementsSWAP( mode, count, type, indices, clientState );
+
+#ifdef CR_FORCE_ZVA_SERVER_ARRAY
+        CR_ZVA_RESTORE_CTX RestoreCtx;
+
+        if (cZvaValues && cZvaValues < UINT32_MAX/2)
+            packspuZvaEnable(ctx, aAttrib, cZvaValues, &RestoreCtx);
+#endif
+
+        if (pack_spu.swap)
+            crPackExpandDrawElementsSWAP( mode, count, type, indices, clientState, cZvaValues ? aAttrib : NULL );
         else
         {
             //packspu_Begin(mode);
-            crPackExpandDrawElements( mode, count, type, indices, clientState );
+            crPackExpandDrawElements( mode, count, type, indices, clientState, cZvaValues ? aAttrib : NULL );
             //packspu_End();
         }
+
+#ifdef CR_FORCE_ZVA_SERVER_ARRAY
+        if (cZvaValues && cZvaValues < UINT32_MAX/2)
+            packspuZvaDisable(&RestoreCtx);
+#endif
     }
 
@@ -341,4 +572,6 @@
 {
     GLboolean serverArrays = GL_FALSE;
+    GLuint cZvaValues = 0;
+    GLfloat aAttrib[4];
 
 #if CR_ARB_vertex_buffer_object
@@ -346,11 +579,25 @@
     /*crDebug("DrawRangeElements count=%d", count);*/
     if (ctx->clientState->extensions.ARB_vertex_buffer_object)
+    {
          serverArrays = crStateUseServerArrays();
-#endif
-
-    if (serverArrays) {
+         if (ctx->fCheckZerroVertAttr)
+             cZvaValues = crStateNeedDummyZeroVertexArray(thread->currentContext->clientState, &thread->packer->current, aAttrib);
+    }
+#endif
+
+    if (serverArrays
+#ifdef CR_FORCE_ZVA_EXPAND
+            && !cZvaValues
+#endif
+            ) {
+        CR_ZVA_RESTORE_CTX RestoreCtx;
         GET_CONTEXT(ctx);
         CRClientState *clientState = &(ctx->clientState->client);
 
+        Assert(cZvaValues < UINT32_MAX/2);
+
+        if (cZvaValues)
+            packspuZvaEnable(ctx, aAttrib, cZvaValues, &RestoreCtx);
+
         /*Note the comment in packspu_LockArraysEXT*/
         if (clientState->array.locked && !clientState->array.synced)
@@ -365,4 +612,7 @@
         else
             crPackDrawRangeElements( mode, start, end, count, type, indices );
+
+        if (cZvaValues)
+            packspuZvaDisable(&RestoreCtx);
     }
     else {
@@ -370,10 +620,22 @@
         GET_CONTEXT(ctx);
         CRClientState *clientState = &(ctx->clientState->client);
-        if (pack_spu.swap)
-            crPackExpandDrawRangeElementsSWAP( mode, start, end, count, type, indices, clientState );
-        else
-        {
-            crPackExpandDrawRangeElements( mode, start, end, count, type, indices, clientState );
-        }
+#ifdef CR_FORCE_ZVA_SERVER_ARRAY
+        CR_ZVA_RESTORE_CTX RestoreCtx;
+
+        if (cZvaValues && cZvaValues < UINT32_MAX/2)
+            packspuZvaEnable(ctx, aAttrib, cZvaValues, &RestoreCtx);
+#endif
+
+        if (pack_spu.swap)
+            crPackExpandDrawRangeElementsSWAP( mode, start, end, count, type, indices, clientState, cZvaValues ? aAttrib : NULL );
+        else
+        {
+            crPackExpandDrawRangeElements( mode, start, end, count, type, indices, clientState, cZvaValues ? aAttrib : NULL );
+        }
+
+#ifdef CR_FORCE_ZVA_SERVER_ARRAY
+        if (cZvaValues && cZvaValues < UINT32_MAX/2)
+            packspuZvaDisable(&RestoreCtx);
+#endif
     }
 }
@@ -384,4 +646,6 @@
 {
     GLboolean serverArrays = GL_FALSE;
+    GLuint cZvaValues = 0;
+    GLfloat aAttrib[4];
 
 #if CR_ARB_vertex_buffer_object
@@ -390,5 +654,9 @@
     /*crDebug("DrawArrays count=%d", count);*/
     if (ctx->clientState->extensions.ARB_vertex_buffer_object)
+    {
          serverArrays = crStateUseServerArrays();
+         if (ctx->fCheckZerroVertAttr)
+             cZvaValues = crStateNeedDummyZeroVertexArray(thread->currentContext->clientState, &thread->packer->current, aAttrib);
+    }
 
 # ifdef CR_USE_LOCKARRAYS
@@ -409,9 +677,19 @@
 #endif
 
-    if (serverArrays)
-    {
+    if (serverArrays
+#ifdef CR_FORCE_ZVA_EXPAND
+            && !cZvaValues
+#endif
+            )
+    {
+        CR_ZVA_RESTORE_CTX RestoreCtx;
         GET_CONTEXT(ctx);
         CRClientState *clientState = &(ctx->clientState->client);
 
+        Assert(cZvaValues < UINT32_MAX/2);
+
+        if (cZvaValues)
+            packspuZvaEnable(ctx, aAttrib, cZvaValues, &RestoreCtx);
+
         /*Note the comment in packspu_LockArraysEXT*/
         if (clientState->array.locked && !clientState->array.synced)
@@ -426,4 +704,7 @@
         else
             crPackDrawArrays( mode, first, count );
+
+        if (cZvaValues)
+            packspuZvaDisable(&RestoreCtx);
     }
     else
@@ -432,8 +713,21 @@
         GET_CONTEXT(ctx);
         CRClientState *clientState = &(ctx->clientState->client);
-        if (pack_spu.swap)
-            crPackExpandDrawArraysSWAP( mode, first, count, clientState );
-        else
-            crPackExpandDrawArrays( mode, first, count, clientState );
+#ifdef CR_FORCE_ZVA_SERVER_ARRAY
+        CR_ZVA_RESTORE_CTX RestoreCtx;
+
+        if (cZvaValues && cZvaValues < UINT32_MAX/2)
+            packspuZvaEnable(ctx, aAttrib, cZvaValues, &RestoreCtx);
+#endif
+
+        if (pack_spu.swap)
+            crPackExpandDrawArraysSWAP( mode, first, count, clientState, cZvaValues ? aAttrib : NULL );
+        else
+            crPackExpandDrawArrays( mode, first, count, clientState, cZvaValues ? aAttrib : NULL );
+
+#ifdef CR_FORCE_ZVA_SERVER_ARRAY
+        if (cZvaValues && cZvaValues < UINT32_MAX/2)
+            packspuZvaDisable(&RestoreCtx);
+#endif
+
     }
 
Index: /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_context.c
===================================================================
--- /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_context.c	(revision 51312)
+++ /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_context.c	(revision 51313)
@@ -419,4 +419,6 @@
     context->serverCtx = 0;
     context->currentThread = NULL;
+
+    memset (&context->zvaBufferInfo, 0, sizeof (context->zvaBufferInfo));
 
     if (curContext == context)
@@ -500,4 +502,9 @@
             }
 
+            if (thread->currentContext && newCtx != thread->currentContext && thread->currentContext->fCheckZerroVertAttr)
+            {
+                crStateCurrentRecoverNew(thread->currentContext->clientState, &thread->packer->current);
+                crStateResetCurrentPointers(&thread->packer->current);
+            }
             thread->currentContext = newCtx;
             crPackSetContext( thread->packer );
Index: /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_get.py
===================================================================
--- /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_get.py	(revision 51312)
+++ /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_get.py	(revision 51313)
@@ -58,4 +58,6 @@
 simple_funcs = [ 'GetIntegerv', 'GetFloatv', 'GetDoublev', 'GetBooleanv' ]
 simple_swaps = [ 'SWAP32', 'SWAPFLOAT', 'SWAPDOUBLE', '(GLboolean) SWAP32' ]
+
+vertattr_get_funcs = [ 'GetVertexAttribdv' 'GetVertexAttribfv' 'GetVertexAttribiv' ]
 
 hard_funcs = {
@@ -122,4 +124,8 @@
         || pname == GL_DRAW_FRAMEBUFFER_BINDING_EXT 
 #endif
+        || pname == GL_ARRAY_BUFFER_BINDING
+        || pname == GL_ELEMENT_ARRAY_BUFFER_BINDING
+        || pname == GL_PIXEL_PACK_BUFFER_BINDING
+        || pname == GL_PIXEL_UNPACK_BUFFER_BINDING
         )
         {
@@ -157,4 +163,32 @@
         }
             """ % (params[-1][1], params[-1][1], func_name, func_name, apiutil.MakeCallString(params), func_name, func_name)
+            
+        if func_name in vertattr_get_funcs:
+            print """
+    if (pname != GL_CURRENT_VERTEX_ATTRIB_ARB)
+    {
+#ifdef DEBUG
+        %s localparams;
+        localparams = (%s) crAlloc(__numValues(pname) * sizeof(*localparams));
+        crState%s(index, pname, localparams);
+        crPack%s(index, %s, &writeback);
+        packspuFlush( (void *) thread );
+        CRPACKSPU_WRITEBACK_WAIT(thread, writeback);
+        for (i=0; i<crStateHlpComponentsCount(pname); ++i)
+        {
+            if (localparams[i] != params[i])
+            {
+                crWarning("Incorrect local state in %s for %%x param %%i", pname, i);
+                crWarning("Expected %%i but got %%i", (int)localparams[i], (int)params[i]);
+            }
+        }
+        crFree(localparams);
+#else
+        crState%s(pname, params);
+#endif
+        return;
+    } 
+            """ % (params[-1][1], params[-1][1], func_name, func_name, apiutil.MakeCallString(params), func_name, func_name)
+
         params.append( ("&writeback", "foo", 0) )
         print '\tif (pack_spu.swap)'
Index: /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_init.c
===================================================================
--- /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_init.c	(revision 51312)
+++ /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_init.c	(revision 51313)
@@ -80,10 +80,6 @@
 packSPUSelfDispatch(SPUDispatchTable *self)
 {
-#ifdef VBOX_WITH_CRPACKSPU_DUMPER
     crSPUInitDispatchTable( &(pack_spu.self) );
     crSPUCopyDispatchTable( &(pack_spu.self), self );
-#else
-    (void)self;
-#endif
 }
 
Index: /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_misc.c
===================================================================
--- /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_misc.c	(revision 51312)
+++ /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_misc.c	(revision 51313)
@@ -435,4 +435,11 @@
 }
 
+static void packspuCheckZerroVertAttr(GLboolean fEnable)
+{
+    GET_THREAD(thread);
+
+    thread->currentContext->fCheckZerroVertAttr = fEnable;
+}
+
 void PACKSPU_APIENTRY packspu_ChromiumParameteriCR(GLenum target, GLint value)
 {
@@ -442,4 +449,7 @@
             /* this is a pure packspu state, don't propagate it any further */
             packspuFluchOnThreadSwitch(value);
+            return;
+        case GL_CHECK_ZERO_VERT_ARRT:
+            packspuCheckZerroVertAttr(value);
             return;
         case GL_SHARE_CONTEXT_RESOURCES_CR:
Index: /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_net.c
===================================================================
--- /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_net.c	(revision 51312)
+++ /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_net.c	(revision 51313)
@@ -131,4 +131,10 @@
     CRASSERT(buf);
 
+    if (ctx && ctx->fCheckZerroVertAttr)
+    {
+        crStateCurrentRecoverNew(ctx->clientState, &thread->packer->current);
+        crStateResetCurrentPointers(&thread->packer->current);
+    }
+
     /* We're done packing into the current buffer, unbind it */
     crPackReleaseBuffer( thread->packer );
Index: /trunk/src/VBox/GuestHost/OpenGL/include/chromium.h
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/include/chromium.h	(revision 51312)
+++ /trunk/src/VBox/GuestHost/OpenGL/include/chromium.h	(revision 51313)
@@ -731,4 +731,7 @@
 #define GL_HH_RENDERTHREAD_INFORM     0x8B2F
 
+/* enable zero vertex attribute generation to work around wine bug */
+#define GL_CHECK_ZERO_VERT_ARRT       0x8B30
+
 /**********************************************************************/
 /*****                Chromium-specific API                       *****/
Index: /trunk/src/VBox/GuestHost/OpenGL/include/state/cr_current.h
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/include/state/cr_current.h	(revision 51312)
+++ /trunk/src/VBox/GuestHost/OpenGL/include/state/cr_current.h	(revision 51313)
@@ -90,4 +90,6 @@
 DECLEXPORT(void) crStateCurrentRecover( void );
 
+DECLEXPORT(void) crStateCurrentRecoverNew(CRContext *g, CRCurrentStatePointers  *current);
+
 DECLEXPORT(void) crStateCurrentDiff(CRCurrentBits *bb, CRbitvalue *bitID,
                                     CRContext *fromCtx, CRContext *toCtx);
@@ -97,4 +99,6 @@
 DECLEXPORT(void) crStateRasterPosUpdate(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
 
+DECLEXPORT(GLuint) crStateNeedDummyZeroVertexArray(CRContext *g, CRCurrentStatePointers  *current, GLfloat *pZva);
+
 #ifdef __cplusplus
 }
Index: /trunk/src/VBox/GuestHost/OpenGL/packer/pack_client.c
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/packer/pack_client.c	(revision 51312)
+++ /trunk/src/VBox/GuestHost/OpenGL/packer/pack_client.c	(revision 51313)
@@ -28,7 +28,13 @@
     unsigned char *p = array->a[attr].p + index * array->a[attr].stride;
 
+#ifdef DEBUG_misha
+    Assert(index >= 0);
+#endif
+
 #ifdef CR_ARB_vertex_buffer_object
     if (array->a[attr].buffer && array->a[attr].buffer->data)
     {
+        Assert(((GLuint)p) < array->a[attr].buffer->size);
+        Assert(((GLint)p) >= 0);
         p = (unsigned char *)(array->a[attr].buffer->data) + (unsigned long)p;
     }
@@ -298,5 +304,5 @@
  */
 void
-crPackExpandArrayElement(GLint index, CRClientState *c)
+crPackExpandArrayElement(GLint index, CRClientState *c, const GLfloat *pZva)
 {
     unsigned char *p;
@@ -561,4 +567,8 @@
         crPackVertexAttrib(array, VERT_ATTRIB_POS, index);
     }
+    else if (pZva)
+    {
+        crPackVertexAttrib4fvARB(VERT_ATTRIB_POS, pZva);
+    }
     else if (array->v.enabled)
     {
@@ -613,5 +623,5 @@
 
 void
-crPackExpandDrawArrays(GLenum mode, GLint first, GLsizei count, CRClientState *c)
+crPackExpandDrawArrays(GLenum mode, GLint first, GLsizei count, CRClientState *c, const GLfloat *pZva)
 {
     int i;
@@ -632,5 +642,5 @@
     for (i=0; i<count; i++)
     {
-        crPackExpandArrayElement(first + i, c);
+        crPackExpandArrayElement(first + i, c, pZva);
     }
     crPackEnd();
@@ -753,5 +763,5 @@
 void
 crPackExpandDrawElements(GLenum mode, GLsizei count, GLenum type,
-                                                 const GLvoid *indices, CRClientState *c)
+                                                 const GLvoid *indices, CRClientState *c, const GLfloat *pZva)
 {
     int i;
@@ -801,5 +811,5 @@
             for (i=0; i<count; i++)
             {
-                crPackExpandArrayElement((GLint) *p++, c);
+                crPackExpandArrayElement((GLint) *p++, c, pZva);
             }
             break;
@@ -807,5 +817,5 @@
             for (i=0; i<count; i++)
             {
-                crPackExpandArrayElement((GLint) * (GLushort *) p, c);
+                crPackExpandArrayElement((GLint) * (GLushort *) p, c, pZva);
                 p+=sizeof (GLushort);
             }
@@ -814,5 +824,5 @@
             for (i=0; i<count; i++)
             {
-                crPackExpandArrayElement((GLint) * (GLuint *) p, c);
+                crPackExpandArrayElement((GLint) * (GLuint *) p, c, pZva);
                 p+=sizeof (GLuint);
             }
@@ -872,5 +882,5 @@
  */
 void
-crPackExpandDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, CRClientState *c)
+crPackExpandDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, CRClientState *c, const GLfloat *pZva)
 {
     if (start>end)
@@ -880,5 +890,5 @@
     }
 
-    crPackExpandDrawElements(mode, count, type, indices, c);
+    crPackExpandDrawElements(mode, count, type, indices, c, pZva);
 }
 
@@ -906,10 +916,10 @@
 void
 crPackExpandMultiDrawArraysEXT( GLenum mode, GLint *first, GLsizei *count,
-                                                                GLsizei primcount, CRClientState *c )
+                                                                GLsizei primcount, CRClientState *c, const GLfloat *pZva )
 {
    GLint i;
    for (i = 0; i < primcount; i++) {
       if (count[i] > 0) {
-         crPackExpandDrawArrays(mode, first[i], count[i], c);
+         crPackExpandDrawArrays(mode, first[i], count[i], c, pZva);
       }
    }
@@ -939,10 +949,10 @@
 crPackExpandMultiDrawElementsEXT( GLenum mode, const GLsizei *count,
                                   GLenum type, const GLvoid **indices,
-                                  GLsizei primcount, CRClientState *c )
+                                  GLsizei primcount, CRClientState *c, const GLfloat *pZva )
 {
    GLint i;
    for (i = 0; i < primcount; i++) {
       if (count[i] > 0) {
-         crPackExpandDrawElements(mode, count[i], type, indices[i], c);
+         crPackExpandDrawElements(mode, count[i], type, indices[i], c, pZva);
       }
    }
Index: /trunk/src/VBox/GuestHost/OpenGL/packer/pack_currentheader.py
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/packer/pack_currentheader.py	(revision 51312)
+++ /trunk/src/VBox/GuestHost/OpenGL/packer/pack_currentheader.py	(revision 51313)
@@ -57,5 +57,5 @@
 	unsigned int vtx_count_begin;
 	unsigned int attribsUsedMask;
-
+    unsigned int changedVertexAttrib;
 } CRCurrentStatePointers;
 
Index: /trunk/src/VBox/GuestHost/OpenGL/packer/pack_currenttypes.py
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/packer/pack_currenttypes.py	(revision 51312)
+++ /trunk/src/VBox/GuestHost/OpenGL/packer/pack_currenttypes.py	(revision 51313)
@@ -57,4 +57,14 @@
 		'members': []
 	},
+}
+
+current_fns_new = {
+    'VertexAttrib': {
+        'types': ['s','f','d','b','i','ub','ui','us','Nub','Nus','Nui','Nb','Ns','Ni'],
+        'sizes': [1,2,3,4],
+        'default': [0,0,0,1],
+        'members': ['x', 'y', 'z', 'w'],
+        'array': 'CR_MAX_VERTEX_ATTRIBS'
+    },
 }
 
Index: /trunk/src/VBox/GuestHost/OpenGL/packer/pack_program.c
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/packer/pack_program.c	(revision 51312)
+++ /trunk/src/VBox/GuestHost/OpenGL/packer/pack_program.c	(revision 51313)
@@ -366,5 +366,5 @@
     unsigned char *data_ptr;
     CR_GET_BUFFERED_POINTER( pc, 8 );
-    pc->current.c.vertexAttrib.b4[index] = data_ptr + 12;
+    pc->current.c.vertexAttrib.b4[index] = data_ptr + 4;
     pc->current.attribsUsedMask |= (1 << index);
     WRITE_DATA( 0, GLuint, index );
@@ -382,5 +382,5 @@
     unsigned char *data_ptr;
     CR_GET_BUFFERED_POINTER( pc, 20 );
-    pc->current.c.vertexAttrib.i4[index] = data_ptr + 12;
+    pc->current.c.vertexAttrib.i4[index] = data_ptr + 4;
     pc->current.attribsUsedMask |= (1 << index);
     WRITE_DATA( 0, GLuint, index );
@@ -398,5 +398,5 @@
     unsigned char *data_ptr;
     CR_GET_BUFFERED_POINTER( pc, 12 );
-    pc->current.c.vertexAttrib.s4[index] = data_ptr + 12;
+    pc->current.c.vertexAttrib.s4[index] = data_ptr + 4;
     pc->current.attribsUsedMask |= (1 << index);
     WRITE_DATA( 0, GLuint, index );
@@ -414,5 +414,5 @@
     unsigned char *data_ptr;
     CR_GET_BUFFERED_POINTER( pc, 8 );
-    pc->current.c.vertexAttrib.ub4[index] = data_ptr + 12;
+    pc->current.c.vertexAttrib.ub4[index] = data_ptr + 4;
     pc->current.attribsUsedMask |= (1 << index);
     WRITE_DATA( 0, GLuint, index );
@@ -430,5 +430,5 @@
     unsigned char *data_ptr;
     CR_GET_BUFFERED_POINTER( pc, 20 );
-    pc->current.c.vertexAttrib.ui4[index] = data_ptr + 12;
+    pc->current.c.vertexAttrib.ui4[index] = data_ptr + 4;
     pc->current.attribsUsedMask |= (1 << index);
     WRITE_DATA( 0, GLuint, index );
@@ -446,5 +446,5 @@
     unsigned char *data_ptr;
     CR_GET_BUFFERED_POINTER( pc, 12 );
-    pc->current.c.vertexAttrib.s4[index] = data_ptr + 12;
+    pc->current.c.vertexAttrib.s4[index] = data_ptr + 4;
     pc->current.attribsUsedMask |= (1 << index);
     WRITE_DATA( 0, GLuint, index );
@@ -462,5 +462,5 @@
     unsigned char *data_ptr;
     CR_GET_BUFFERED_POINTER( pc, 8 );
-    pc->current.c.vertexAttrib.b4[index] = data_ptr + 12;
+    pc->current.c.vertexAttrib.b4[index] = data_ptr + 4;
     pc->current.attribsUsedMask |= (1 << index);
     WRITE_DATA( 0, GLuint, index );
@@ -478,5 +478,5 @@
     unsigned char *data_ptr;
     CR_GET_BUFFERED_POINTER( pc, 20 );
-    pc->current.c.vertexAttrib.i4[index] = data_ptr + 12;
+    pc->current.c.vertexAttrib.i4[index] = data_ptr + 4;
     pc->current.attribsUsedMask |= (1 << index);
     WRITE_DATA( 0, GLuint, index );
@@ -494,5 +494,5 @@
     unsigned char *data_ptr;
     CR_GET_BUFFERED_POINTER( pc, 20 );
-    pc->current.c.vertexAttrib.ui4[index] = data_ptr + 12;
+    pc->current.c.vertexAttrib.ui4[index] = data_ptr + 4;
     pc->current.attribsUsedMask |= (1 << index);
     WRITE_DATA( 0, GLuint, index );
@@ -510,5 +510,5 @@
     unsigned char *data_ptr;
     CR_GET_BUFFERED_POINTER( pc, 12 );
-    pc->current.c.vertexAttrib.s4[index] = data_ptr + 12;
+    pc->current.c.vertexAttrib.s4[index] = data_ptr + 4;
     pc->current.attribsUsedMask |= (1 << index);
     WRITE_DATA( 0, GLuint, index );
@@ -527,5 +527,5 @@
     unsigned char *data_ptr;
     CR_GET_BUFFERED_POINTER( pc, 8 );
-    pc->current.c.vertexAttrib.ub4[index] = data_ptr + 12;
+    pc->current.c.vertexAttrib.ub4[index] = data_ptr + 4;
     pc->current.attribsUsedMask |= (1 << index);
     WRITE_DATA( 0, GLuint, index );
Index: /trunk/src/VBox/GuestHost/OpenGL/packer/packer.py
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/packer/packer.py	(revision 51312)
+++ /trunk/src/VBox/GuestHost/OpenGL/packer/packer.py	(revision 51313)
@@ -104,7 +104,8 @@
         type = m.group(3) + m.group(2)
         # Add 12 to skip the packet length, opcode and index fields
-        print "\tpc->current.c.%s.%s[index] = data_ptr + 12;" % (name,type)
+        print "\tpc->current.c.%s.%s[index] = data_ptr + 4;" % (name,type)
         if m.group(4) == "ARB" or m.group(4) == "NV":
             print "\tpc->current.attribsUsedMask |= (1 << index);"
+            print "\tpc->current.changedVertexAttrib |= (1 << index);"
         return
 
Index: /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_client.c
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_client.c	(revision 51312)
+++ /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_client.c	(revision 51313)
@@ -1565,5 +1565,5 @@
 #ifdef DEBUG_misha
 /* debugging */
-# define CR_NO_SERVER_ARRAYS
+//# define CR_NO_SERVER_ARRAYS
 #endif
 
@@ -1627,4 +1627,48 @@
 
     return res;
+#else
+    return GL_FALSE;
+#endif
+}
+
+GLuint crStateNeedDummyZeroVertexArray(CRContext *g, CRCurrentStatePointers *current, GLfloat *pZva)
+{
+#if defined(CR_ARB_vertex_buffer_object)
+    CRClientState *c = &(g->client);
+    int i;
+    GLuint zvMax = 0;
+
+    if (c->array.a[0].enabled)
+        return 0;
+
+    for (i = 1; (unsigned int)i < g->limits.maxVertexProgramAttribs; i++)
+    {
+        if (c->array.a[i].enabled)
+        {
+            if (c->array.a[i].buffer && c->array.a[i].buffer->id)
+            {
+                GLuint cElements = c->array.a[i].buffer->size / c->array.a[i].stride;
+                if (zvMax < cElements)
+                    zvMax = cElements;
+            }
+            else
+            {
+                zvMax = ~0;
+                break;
+            }
+        }
+    }
+
+    if (zvMax)
+    {
+        Assert(!c->array.v.enabled);
+
+        crStateCurrentRecoverNew(g, current);
+        crStateResetCurrentPointers(current);
+
+        memcpy(pZva, &g->current.vertexAttrib[0][0], sizeof (*pZva) * 4);
+    }
+
+    return zvMax;
 #else
     return GL_FALSE;
Index: /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_current.c
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_current.c	(revision 51312)
+++ /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_current.c	(revision 51313)
@@ -111,15 +111,9 @@
 void crStateResetCurrentPointers( CRCurrentStatePointers *current )
 {
-    crMemset(&(current->c.index), 0, sizeof(GLindex_p));
-    crMemset(&(current->c.vertexAttrib), 0, sizeof(GLvertexattrib_p));
-    crMemset(&(current->c.fogCoord), 0, sizeof(GLfogcoord_p));
-    crMemset(&(current->c.edgeFlag), 0, sizeof(GLedgeflag_p));
-    crMemset(&(current->c.normal), 0, sizeof(GLnormal_p));
-    crMemset(&(current->c.color), 0, sizeof(GLcolor_p));
-    crMemset(&(current->c.secondaryColor), 0, sizeof(GLsecondarycolor_p));
-    crMemset(&(current->c.texCoord), 0, sizeof(GLtexcoord_p));
-    /*
-    current->attribsUsedMask = 0;
-    */
+    uint32_t attribsUsedMask = current->attribsUsedMask;
+
+    crMemset(current, 0, sizeof (*current));
+
+    current->attribsUsedMask = attribsUsedMask;
 }
 
Index: /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_current.py
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_current.py	(revision 51312)
+++ /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_current.py	(revision 51313)
@@ -287,2 +287,193 @@
 		print '\t}'
 print '}'
+
+print '''
+
+void crStateCurrentRecoverNew(CRContext *g, CRCurrentStatePointers  *current)
+{
+    const unsigned char *v;
+    convert_func convert=NULL;
+    CRCurrentState *c = &(g->current);
+    CRStateBits *sb = GetCurrentBits();
+    CRCurrentBits *cb = &(sb->current);
+
+    static const GLfloat vertexAttrib_default[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+
+    GLvertexattrib_p *vertexAttrib = &(current->c.vertexAttrib);
+
+    unsigned int i;
+    CRbitvalue nbitID[CR_MAX_BITARRAY];
+
+
+    /* silence warnings */
+    (void) __convert_b1;
+    (void) __convert_b2;
+    (void) __convert_b3;
+    (void) __convert_b4;
+    (void) __convert_ui1;
+    (void) __convert_ui2;
+    (void) __convert_ui3;
+    (void) __convert_ui4;
+    (void) __convert_l1;
+    (void) __convert_l2;
+    (void) __convert_l3;
+    (void) __convert_l4;
+    (void) __convert_us1;
+    (void) __convert_us2;
+    (void) __convert_us3;
+    (void) __convert_us4;
+    (void) __convert_ub1;
+    (void) __convert_ub2;
+    (void) __convert_ub3;
+    (void) __convert_ub4;
+    (void) __convert_rescale_s1;
+    (void) __convert_rescale_s2;
+    (void) __convert_rescale_b1;
+    (void) __convert_rescale_b2;
+    (void) __convert_rescale_ui1;
+    (void) __convert_rescale_ui2;
+    (void) __convert_rescale_i1;
+    (void) __convert_rescale_i2;
+    (void) __convert_rescale_us1;
+    (void) __convert_rescale_us2;
+    (void) __convert_rescale_ub1;
+    (void) __convert_rescale_ub2;
+    (void) __convert_Ni1;
+    (void) __convert_Ni2;
+    (void) __convert_Ni3;
+    (void) __convert_Ni4;
+    (void) __convert_Nb1;
+    (void) __convert_Nb2;
+    (void) __convert_Nb3;
+    (void) __convert_Nb4;
+    (void) __convert_Nus1;
+    (void) __convert_Nus2;
+    (void) __convert_Nus3;
+    (void) __convert_Nus4;
+    (void) __convert_Nui1;
+    (void) __convert_Nui2;
+    (void) __convert_Nui3;
+    (void) __convert_Nui4;
+    (void) __convert_Ns1;
+    (void) __convert_Ns2;
+    (void) __convert_Ns3;
+    (void) __convert_Ns4;
+    (void) __convert_Nub1;
+    (void) __convert_Nub2;
+    (void) __convert_Nub3;
+    (void) __convert_Nub4;
+
+
+'''
+
+for k in current_fns_new.keys():
+    print '\t/* %s */' % k
+    print '\tif (current->changed%s)' % k
+    print '\t{'
+    print '\t\tv=NULL;'
+    name = '%s%s' % (k[:1].lower(),k[1:])
+
+    indent = ""
+    if current_fns_new[k].has_key( 'array' ):
+        print '\t\tfor (i = 0 ; i < %s ; i++)' % current_fns_new[k]['array']
+        print '\t\t{'
+        indent += "\t\t"
+        print '\t\tif (!(current->changed%s & (1 << i))) continue;' % k
+    for type in current_fns_new[k]['types']:
+        if type[0:1] == "N":
+            normalized = 1
+            type2 = type[1:]
+        else:
+            normalized = 0
+            type2 = type
+        for size in current_fns_new[k]['sizes']:
+            ptr = '%s->%s%d' % (name, type, size )
+            if current_fns_new[k].has_key( 'array' ):
+                ptr += "[i]"
+            print '#ifdef DEBUG_misha'
+            print '%s\tif (%s)' % (indent, ptr)
+            print '%s\t{' % (indent)
+            print '%s\t\tuint32_t *pTst = (uint32_t*)(%s);' % (indent, ptr)
+            print '%s\t\t--pTst;' % (indent)
+            print '%s\t\tAssert((*pTst) == i);' % (indent)
+            print '%s\t}' % (indent)
+            print '#endif'
+            print '%s\tif (v < %s)' % (indent, ptr)
+            print '%s\t{' % indent
+            print '%s\t\tv = %s;' % (indent, ptr)
+            if (k == 'Color' or k == 'Normal' or k == 'SecondaryColor' or normalized) and type != 'f' and type != 'd' and type != 'l':
+                print '%s\t\tconvert = (convert_func) __convert_rescale_%s%d;' % (indent,type,size)
+            else:
+                print '%s\t\tconvert = (convert_func) __convert_%s%d;' % (indent,type,size)
+            print '%s\t}' % indent
+    print ''
+    print '%s\tif (v != NULL) {' % indent
+    if current_fns_new[k].has_key( 'array' ):
+        if k == 'TexCoord':
+            print '%s\t\tCOPY_4V(c->vertexAttrib[VERT_ATTRIB_TEX0 + i], %s_default);' % (indent,name)
+        else:
+            print '%s\t\tCOPY_4V(c->%s[i], %s_default);' % (indent,name,name)
+    else:
+        if k == 'Normal':
+            print '%s\t\tCOPY_4V(c->vertexAttrib[VERT_ATTRIB_NORMAL], %s_default);' % (indent,name)
+        elif k == 'FogCoord':
+            print '%s\t\tc->vertexAttrib[VERT_ATTRIB_FOG][0] =  %s_default;' % (indent,name)
+        elif k == 'Color':
+            print '%s\t\tCOPY_4V(c->vertexAttrib[VERT_ATTRIB_COLOR0], %s_default);' % (indent,name)
+        elif k == 'SecondaryColor':
+            print '%s\t\tCOPY_4V(c->vertexAttrib[VERT_ATTRIB_COLOR1],  %s_default);' % (indent,name)
+        elif k == 'TexCoord':
+            print '%s\t\tCOPY_4V(c->vertexAttrib[VERT_ATTRIB_TEX0], %s_default);' % (indent,name)
+        elif k == 'Index':
+            print '%s\t\tc->colorIndex =  %s_default;' % (indent,name)
+        elif k == 'EdgeFlag':
+            print '%s\t\tc->edgeFlag =  %s_default;' % (indent,name)
+        else:
+            print '%s\t\tc->%s = %s_default;' % (indent,name,name)
+    if k == 'EdgeFlag':
+        print '%s\t\t__convert_boolean (&c->edgeFlag, v);' % (indent)
+        dirtyVar = 'cb->edgeFlag'
+    elif k == 'Normal':
+        print '%s\t\tconvert(&(c->vertexAttrib[VERT_ATTRIB_NORMAL][0]), v);' % (indent)
+        dirtyVar = 'cb->vertexAttrib[VERT_ATTRIB_NORMAL]'
+    elif k == 'TexCoord':
+        print '%s\t\tconvert(&(c->vertexAttrib[VERT_ATTRIB_TEX0 + i][0]), v);' % (indent)
+        dirtyVar = 'cb->vertexAttrib[VERT_ATTRIB_TEX0 + i]'
+    elif k == 'Color':
+        print '%s\t\tconvert(&(c->vertexAttrib[VERT_ATTRIB_COLOR0][0]), v);' % (indent)
+        dirtyVar = 'cb->vertexAttrib[VERT_ATTRIB_COLOR0]'
+    elif k == 'Index':
+        print '%s\t\tconvert(&(c->colorIndex), v);' % (indent)
+        dirtyVar = 'cb->colorIndex'
+    elif k == 'SecondaryColor':
+        print '%s\t\tconvert(&(c->vertexAttrib[VERT_ATTRIB_COLOR1][0]), v);' % (indent)
+        dirtyVar = 'cb->vertexAttrib[VERT_ATTRIB_COLOR1]'
+    elif k == 'FogCoord':
+        print '%s\t\tconvert(&(c->vertexAttrib[VERT_ATTRIB_FOG][0]), v);' % (indent)
+        dirtyVar = 'cb->vertexAttrib[VERT_ATTRIB_FOG]'
+    elif k == 'VertexAttrib':
+        print '%s\t\tconvert(&(c->vertexAttrib[i][0]), v);' % (indent)
+        dirtyVar = 'cb->vertexAttrib[i]'
+    else:
+        assert 0  # should never get here
+
+    print '%s\t\tDIRTY(%s, nbitID);' % (indent, dirtyVar)
+
+#   if current_fns_new[k].has_key( 'array' ):
+#       print '%s\t\tDIRTY(cb->%s[i], nbitID);' % (indent,name)
+#   else:
+#       print '%s\t\tDIRTY(cb->%s, nbitID);' % (indent,name)
+
+
+
+    print '%s\t\tDIRTY(cb->dirty, nbitID);' % indent
+    print '%s\t}' % indent
+    if current_fns_new[k].has_key( 'array' ):
+        print '%s\t%s->ptr[i] = v;' % (indent, name )
+    else:
+        print '%s\t%s->ptr = v;' % (indent, name )
+    if current_fns_new[k].has_key( 'array' ):
+        print '\t\t}'
+        print '\t\tcurrent->changed%s = 0;' % k
+        print '\t}'
+print '}'
