GLES2Dbg: code gen for frame

Also loading *.gles2dbg dump files.

Change-Id: I87e5ae6fda22b3cad920d2a06671efef5adb2e8a
Signed-off-by: David Li <davidxli@google.com>
diff --git a/tools/glesv2debugger/generate_MessageFormatter_java.py b/tools/glesv2debugger/generate_MessageFormatter_java.py
index 8b2b338..9e4efe3 100755
--- a/tools/glesv2debugger/generate_MessageFormatter_java.py
+++ b/tools/glesv2debugger/generate_MessageFormatter_java.py
@@ -60,103 +60,109 @@
 
     static String FormatFloats(int count, final ByteBuffer data) {
         if (data.remaining() == 0)
-            return "[null]";
+            return "{}";
         data.order(SampleView.targetByteOrder);
-        String ret = "[";
+        String ret = "{";
         for (int i = 0; i < count; i++) {
             ret += Float.intBitsToFloat(data.getInt());
             if (i < count - 1)
                 ret += ", ";
         }
-        return ret + "]";
+        return ret + "}";
     }
-    
+
     static String FormatInts(int count, final ByteBuffer data) {
         if (data.remaining() == 0)
-            return "[null]";
+            return "{}";
         data.order(SampleView.targetByteOrder);
-        String ret = "[";
+        String ret = "{";
         for (int i = 0; i < count; i++) {
             ret += data.getInt();
             if (i < count - 1)
                 ret += ", ";
         }
-        return ret + "]";
+        return ret + "}";
     }
-    
+
     static String FormatUints(int count, final ByteBuffer data) {
         if (data.remaining() == 0)
-            return "[null]";
+            return "{}";
         data.order(SampleView.targetByteOrder);
-        String ret = "[";
+        String ret = "{";
         for (int i = 0; i < count; i++) {
             long bits = data.getInt() & 0xffffffff;
             ret += bits;
             if (i < count - 1)
                 ret += ", ";
         }
-        return ret + "]";
-    }
-    
-    static String FormatMatrix(int columns, int count, final ByteBuffer data) {
-        if (data.remaining() == 0)
-            return "[null]";
-        data.order(SampleView.targetByteOrder);
-        String ret = "[";
-        for (int i = 0; i < count; i++) {
-            ret += Float.intBitsToFloat(data.getInt());
-            if (i % columns == columns - 1)
-                ret += "\\n                                             ";
-            else if (i < count - 1)
-                ret += ", ";
-        }
-        return ret + "]";
+        return ret + "}";
     }
 
-    public static String Format(final DebuggerMessage.Message msg) {
+    static String FormatMatrix(int columns, int count, final ByteBuffer data) {
+        if (data.remaining() == 0)
+            return "{}";
+        data.order(SampleView.targetByteOrder);
+        String ret = "{";
+        for (int i = 0; i < count; i++) {
+            ret += Float.intBitsToFloat(data.getInt());
+            if (i < count - 1)
+                ret += ", ";
+            if (i % columns == columns - 1)
+                ret += "\\n                                             ";
+        }
+        return ret + "}";
+    }
+
+    public static String Format(final DebuggerMessage.Message msg,
+                                final boolean code) {
         String str;
         switch (msg.getFunction()) {
 """)
-            
+    #in source code these turn into program_%d etc.
+    nameReplaces = ["program", "shader", "texture", "buffer", "framebuffer", "renderbuffer"]
     for line in lines:
         if line.find("API_ENTRY(") >= 0: # a function prototype
             returnType = line[0: line.find(" API_ENTRY(")].replace("const ", "")
             functionName = line[line.find("(") + 1: line.find(")")] #extract GL function name
             parameterList = line[line.find(")(") + 2: line.find(") {")]
-                        
+
             parameters = parameterList.split(',')
             paramIndex = 0
-            
-            formatString = "%s "
+
+            formatString = "%s"
             formatArgs = ""
             if returnType != "void":
                 if returnType == "GLenum":
-                    formatArgs += "GLEnum.valueOf(msg.getRet())"
+                    formatArgs += '\
+                    (code ? "%s" : GLEnum.valueOf(msg.getRet()))\n' % (functionName)
                 elif returnType.find("*") >= 0:
-                    formatArgs += '"0x" + Integer.toHexString(msg.getRet())'
+                    formatArgs += '\
+                    (code ? "%s" : "0x" + Integer.toHexString(msg.getRet()))\n' % (functionName)
                 else:
-                    formatArgs += "msg.getRet()"
+                    formatArgs += '\
+                    (code ? "%s" : msg.getRet())\n' % (functionName)
             else:
-                formatArgs += '"void"'
-            
-            #formatString += "%s(" % (functionName)
+                formatArgs += '\
+                    (code ? "%s" : "void")\n' % (functionName)
+
             formatString += "("
-            
+
             if parameterList == "void":
                 parameters = []
             inout = ""
-            
+
             paramNames = []
-            
+
             for parameter in parameters:
                 parameter = parameter.replace("const","")
                 parameter = parameter.strip()
                 paramType = parameter.split(' ')[0]
                 paramName = parameter.split(' ')[1]
                 annotation = ""
-                
-                formatString += paramName + "=%s"
-                    
+
+                formatString += "%s%s"
+                formatArgs += '\
+                    , (code ? "/*%s*/ " : "%s=")\n' % (paramName, paramName)
                 if parameter.find(":") >= 0:
                     assert inout == "" # only one parameter should be annotated
                     inout = paramType.split(":")[2]
@@ -193,26 +199,42 @@
                         assert columns * columns == count
                         assert countArg != ""
                         assert paramType == "GLfloat"
-                        formatArgs += ", FormatMatrix(%d, %d * msg.getArg%d(), msg.getData().asReadOnlyByteBuffer())" % (columns, count, paramNames.index(countArg))
+                        formatArgs += '\
+                    , (code ? "(GLfloat [])" : "") + FormatMatrix(%d, %d * msg.getArg%d(), msg.getData().asReadOnlyByteBuffer())' % (
+                        columns, count, paramNames.index(countArg))
                     elif annotation == "GLstring":
-                        formatArgs += ", msg.getData().toStringUtf8()"
+                        formatArgs += '\
+                    , (code ? "\\"" : "") + msg.getData().toStringUtf8() + (code ? "\\"" : "")'
                     elif paramType.find("void") >= 0:
-                        formatArgs += ', "0x" + Integer.toHexString(msg.getArg%d())' % (paramIndex)
+                        formatArgs += '\
+                    , (code ? "arg%d" : "0x" + Integer.toHexString(msg.getArg%d()))' % (paramIndex, paramIndex)
                     elif countArg == "":
-                        formatArgs += ", %s(%d, msg.getData().asReadOnlyByteBuffer())" % (dataFormatter, count)
+                        formatArgs += '\
+                    , (code ? "(%s [])" : "") + %s(%d, msg.getData().asReadOnlyByteBuffer())' % (
+                        paramType, dataFormatter, count)
                     else:
-                        formatArgs += ", %s(%d * msg.getArg%d(), msg.getData().asReadOnlyByteBuffer())" % (dataFormatter, count, paramNames.index(countArg))
+                        formatArgs += '\
+                    , (code ? "(%s [])" : "") +  %s(%d * msg.getArg%d(), msg.getData().asReadOnlyByteBuffer())' % (
+                        paramType, dataFormatter, count, paramNames.index(countArg))
                 else:
                     if paramType == "GLfloat" or paramType == "GLclampf":
-                        formatArgs += ", Float.intBitsToFloat(msg.getArg%d())" % (paramIndex)
+                        formatArgs += "\
+                    , Float.intBitsToFloat(msg.getArg%d())" % (paramIndex)
                     elif paramType == "GLenum": 
-                        formatArgs += ", GLEnum.valueOf(msg.getArg%d())" % (paramIndex)
+                        formatArgs += "\
+                    , GLEnum.valueOf(msg.getArg%d())" % (paramIndex)
                     elif paramType.find("*") >= 0:
-                        formatArgs += ', "0x" + Integer.toHexString(msg.getArg%d())' % (paramIndex)
+                        formatArgs += '\
+                    , (code ? "arg%d" : "0x" + Integer.toHexString(msg.getArg%d()))' % (paramIndex, paramIndex)
+                    elif paramName in nameReplaces:
+                        formatArgs += '\
+                    , (code ? "%s_" : "") + msg.getArg%d()' % (paramName, paramIndex)
                     else:
-                        formatArgs += ", msg.getArg%d()" % (paramIndex)
+                        formatArgs += "\
+                    , msg.getArg%d()" % (paramIndex)
                 if paramIndex < len(parameters) - 1:
                     formatString += ", "
+                    formatArgs += '\n'
                 paramNames.append(paramName)
                 paramIndex += 1  
 
@@ -223,8 +245,10 @@
             if line.find("*") >= 0 and (line.find("*") < line.find(":") or line.find("*") > line.rfind(":")):
                 sys.stderr.write(line)
                 output.write("                // FIXME: this function uses pointers, debugger may send data in msg.data\n")
-            output.write('                str = String.format("%s", %s); break;\n' % (formatString, formatArgs))
-            
+            output.write('\
+                str = String.format("%s",\n%s);\n\
+                break;\n' % (formatString, formatArgs))
+
 
     output.write("""            default:
                 str = msg.toString();
diff --git a/tools/glesv2debugger/generate_MessageParser_java.py b/tools/glesv2debugger/generate_MessageParser_java.py
index 47ab5c9..0c5934b 100755
--- a/tools/glesv2debugger/generate_MessageParser_java.py
+++ b/tools/glesv2debugger/generate_MessageParser_java.py
@@ -67,15 +67,15 @@
 
     String[] GetList()
     {
-        assert args.charAt(0) == '[';
+        assert args.charAt(0) == '{';
         String arg = args;
-        args = args.substring(args.indexOf(']') + 1);
+        args = args.substring(args.lastIndexOf('}') + 1);
         int comma = args.indexOf(',');
         if (comma >= 0)
             args = args.substring(comma + 1).trim();
         else
             args = null;
-        arg = arg.substring(1, arg.indexOf(']')).trim();
+        arg = arg.substring(1, arg.lastIndexOf('}')).trim();
         return arg.split(",");
     }
 
diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/BreakpointOption.java b/tools/glesv2debugger/src/com/android/glesv2debugger/BreakpointOption.java
index 0974526..0733f28 100644
--- a/tools/glesv2debugger/src/com/android/glesv2debugger/BreakpointOption.java
+++ b/tools/glesv2debugger/src/com/android/glesv2debugger/BreakpointOption.java
@@ -20,6 +20,7 @@
 import com.android.glesv2debugger.DebuggerMessage.Message.Function;
 import com.android.glesv2debugger.DebuggerMessage.Message.Prop;
 import com.android.glesv2debugger.DebuggerMessage.Message.Type;
+
 import org.eclipse.jface.dialogs.InputDialog;
 import org.eclipse.jface.window.Window;
 import org.eclipse.swt.SWT;
@@ -111,9 +112,9 @@
         shell.getDisplay().syncExec(new Runnable() {
             @Override
             public void run() {
-                String call = MessageFormatter.Format(msg);
-                call = call.substring(0, call.indexOf("(")) + msg.getFunction().toString()
-                        + call.substring(call.indexOf("("));
+                String call = MessageFormatter.Format(msg, false);
+                call = call.substring(0, call.indexOf("(")) + ' ' +
+                        msg.getFunction() + call.substring(call.indexOf("("));
                 if (msg.hasData() && msg.getFunction() == Function.glShaderSource)
                 {
                     int index = call.indexOf("string=") + 7;
@@ -134,7 +135,7 @@
                 {
                     assert msg.getType() == Type.AfterGeneratedCall;
                     assert msg.getFunction() == lastFunction;
-                    call = "skip" + call;
+                    call = "skip " + call;
                     builder.setFunction(Function.SKIP);
                 }
                 InputDialog inputDialog = new InputDialog(shell,
@@ -164,6 +165,9 @@
                     {
                         MessageParserEx.instance.Parse(builder, inputDialog.getValue());
                         lastFunction = builder.getFunction();
+                        // AfterCall is skipped, so push BeforeCall to complete
+                        if (msg.getType() == Type.BeforeCall)
+                            queue.CompletePartialMessage(msg.getContextId());
                     }
                 }
                 // else defaults to continue BeforeCall and skip AfterCall
diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/CodeGen.java b/tools/glesv2debugger/src/com/android/glesv2debugger/CodeGen.java
new file mode 100644
index 0000000..a8503cd
--- /dev/null
+++ b/tools/glesv2debugger/src/com/android/glesv2debugger/CodeGen.java
@@ -0,0 +1,850 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+package com.android.glesv2debugger;
+
+import com.android.glesv2debugger.DebuggerMessage.Message;
+import com.android.glesv2debugger.DebuggerMessage.Message.Function;
+import com.android.sdklib.util.SparseIntArray;
+
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.ByteBuffer;
+
+public class CodeGen {
+    private FileWriter codeFile, makeFile, namesHeaderFile, namesSourceFile;
+    private PrintWriter code, make, namesHeader, namesSource;
+    private FileOutputStream dataOut;
+    private SparseIntArray bufferNames,
+            framebufferNames, programNames, textureNames, shaderNames, renderbufferNames;
+
+    /** return true if msg was a texture upload */
+    private boolean CodeGenTextureUpload(final Message msg, final boolean replaceCopy) {
+        String s = null;
+        switch (msg.getFunction()) {
+            case glCompressedTexImage2D:
+                s = MessageFormatter.Format(msg, true).replace("arg7", "texData");
+                break;
+            case glCompressedTexSubImage2D:
+            case glTexImage2D:
+            case glTexSubImage2D:
+                s = MessageFormatter.Format(msg, true).replace("arg8", "texData");
+                break;
+            case glCopyTexImage2D:
+                if (!replaceCopy) {
+                    code.write(MessageFormatter.Format(msg, true));
+                    code.write(";CHKERR;\n");
+                    return true;
+                }
+                assert msg.getArg2() == msg.getPixelFormat(); // TODO
+                s = "//" + MessageFormatter.Format(msg, true) + "\n";
+                s += String.format("glTexImage2D(%s, %d, %s, %d, %d, %d, %s, %s, texData);CHKERR;",
+                        GLEnum.valueOf(msg.getArg0()), msg.getArg1(),
+                        GLEnum.valueOf(msg.getArg2()), msg.getArg5(), msg.getArg6(),
+                        msg.getArg7(), GLEnum.valueOf(msg.getPixelFormat()),
+                        GLEnum.valueOf(msg.getPixelType()));
+                break;
+            case glCopyTexSubImage2D:
+                if (!replaceCopy) {
+                    code.write(MessageFormatter.Format(msg, true));
+                    code.write(";CHKERR;\n");
+                    return true;
+                }
+                assert msg.getArg2() == msg.getPixelFormat(); // TODO
+                s = "//" + MessageFormatter.Format(msg, true) + "\n";
+                s += String.format(
+                        "glTexSubImage2D(%s, %d, %d, %d, %d, %d, %s, %s, texData);CHKERR;",
+                        GLEnum.valueOf(msg.getArg0()), msg.getArg1(), msg.getArg2(),
+                        msg.getArg3(), msg.getArg6(), msg.getArg7(),
+                        GLEnum.valueOf(msg.getPixelFormat()), GLEnum.valueOf(msg.getPixelType()));
+                break;
+            default:
+                return false;
+        }
+
+        if (msg.hasData()) {
+            final byte[] data = MessageProcessor.LZFDecompressChunks(msg.getData());
+            try {
+                code.write("{\n");
+                code.format("    void * texData = malloc(%d);CHKERR;\n", data.length);
+                code.format("    FILE * texFile = fopen(\"/sdcard/frame_data.bin\", \"rb\");CHKERR;\n");
+                code.format("    assert(texFile);CHKERR;\n");
+                code.format("    fseek(texFile, %d, SEEK_SET);CHKERR;\n", dataOut.getChannel()
+                        .position());
+                dataOut.write(data);
+                code.format("    fread(texData, %d, 1, texFile);CHKERR;\n", data.length);
+                code.format("    fclose(texFile);CHKERR;\n");
+                code.format("    " + s + ";\n");
+                code.format("    free(texData);CHKERR;\n");
+                code.format("}\n");
+            } catch (IOException e) {
+                e.printStackTrace();
+                assert false;
+            }
+        } else
+            code.write(s.replace("texData", "NULL") + ";\n");
+        return true;
+    }
+
+    private void CodeGenServerState(final GLServerState serverState) {
+        code.write("// CodeGenServerState\n");
+        for (int i = 0; i < serverState.enableDisables.size(); i++) {
+            final GLEnum key = GLEnum.valueOf(serverState.enableDisables.keyAt(i));
+            if (serverState.enableDisables.valueAt(i) == 0)
+                code.format("glDisable(%s);CHKERR;\n", key);
+            else
+                code.format("glEnable(%s);CHKERR;\n", key);
+        }
+        for (int i = 0; i < serverState.lastSetter.size(); i++) {
+            final Function key = Function.valueOf(serverState.lastSetter.keyAt(i));
+            final Message msg = serverState.lastSetter.valueAt(i);
+            if (msg == null) {
+                code.format("// %s is default\n", key);
+                continue;
+            }
+            final String s = MessageFormatter.Format(msg, true);
+            code.write(s);
+            code.write(";\n");
+        }
+        // TODO: stencil and integers
+    }
+
+    private void CodeGenServerShader(final GLServerShader serverShader) {
+        code.write("// CodeGenServerShader\n");
+        for (int i = 0; i < serverShader.shaders.size(); i++) {
+            final int name = serverShader.shaders.keyAt(i);
+            final GLShader shader = serverShader.shaders.valueAt(i);
+            final String id = "shader_" + name;
+            if (shaderNames.indexOfKey(name) < 0) {
+                namesSource.format("GLuint %s = 0;\n", id);
+                namesHeader.format("extern GLuint %s;\n", id);
+            }
+            code.format("%s = glCreateShader(%s);CHKERR;\n", id, shader.type);
+            shaderNames.put(name, name);
+
+            if (shader.source != null) {
+                final String src = shader.source.replace("\r", "").replace("\n", "\\n\\\n")
+                        .replace("\"", "\\\"");
+                code.format("glShaderSource(%s, 1, (const GLchar *[]){\"%s\"}, NULL);CHKERR;\n",
+                                id, src);
+                code.format("glCompileShader(%s);CHKERR;\n", id);
+            }
+        }
+
+        for (int i = 0; i < serverShader.programs.size(); i++) {
+            final int name = serverShader.programs.keyAt(i);
+            final GLProgram program = serverShader.programs.valueAt(i);
+            final String id = "program_" + name;
+            if (programNames.indexOfKey(name) < 0) {
+                namesSource.format("GLuint %s = 0;\n", id);
+                namesHeader.format("extern GLuint %s;\n", id);
+            }
+            code.format("%s = glCreateProgram();CHKERR;\n", id);
+            programNames.put(name, name);
+            code.format("glAttachShader(%s, shader_%d);CHKERR;\n", id,
+                    program.vert);
+            code.format("glAttachShader(%s, shader_%d);CHKERR;\n", id,
+                    program.frag);
+            code.format("glLinkProgram(%s);CHKERR;\n", id);
+            if (serverShader.current == program)
+                code.format("glUseProgram(%s);CHKERR;\n", id);
+        }
+    }
+
+    private void CodeGenServerTexture(final GLServerTexture serverTexture, final boolean replaceCopy) {
+        code.write("// CodeGenServerTexture\n");
+        for (int i = 0; i < serverTexture.textures.size(); i++) {
+            final int name = serverTexture.textures.keyAt(i);
+            final GLTexture tex = serverTexture.textures.valueAt(i);
+            final String id = "texture_" + name;
+            if (textureNames.indexOfKey(name) < 0) {
+                namesHeader.format("extern GLuint %s;\n", id);
+                namesSource.format("GLuint %s = 0;\n", id);
+            }
+            code.format("%s = 0;\n", id);
+            textureNames.put(name, name);
+
+            if (name == 0)
+                continue;
+            code.format("glGenTextures(1, &%s);CHKERR;\n", id);
+            String s = String.format("glBindTexture(%s, texture_%d);CHKERR;\n", tex.target,
+                    tex.name);
+            code.write(s);
+            for (final Message msg : tex.contentChanges) {
+                if (CodeGenTextureUpload(msg, replaceCopy))
+                    continue;
+                switch (msg.getFunction()) {
+                    case glGenerateMipmap:
+                        s = MessageFormatter.Format(msg, true);
+                        break;
+                    default:
+                        assert false;
+                }
+                code.write(s + ";\n");
+            }
+            code.format("glTexParameteriv(%s, GL_TEXTURE_WRAP_S, (GLint[]){%s});CHKERR;\n",
+                    tex.target, tex.wrapS);
+            code.format("glTexParameteriv(%s, GL_TEXTURE_WRAP_T, (GLint[]){%s});CHKERR;\n",
+                    tex.target, tex.wrapT);
+            code.format("glTexParameteriv(%s, GL_TEXTURE_MIN_FILTER, (GLint[]){%s});CHKERR;\n",
+                    tex.target, tex.min);
+            code.format("glTexParameteriv(%s, GL_TEXTURE_MAG_FILTER, (GLint[]){%s});CHKERR;\n",
+                    tex.target, tex.mag);
+        }
+        for (int i = 0; i < serverTexture.tmu2D.length && i < 16; i++) {
+            code.format("glActiveTexture(%s);CHKERR;\n",
+                    GLEnum.valueOf(GLEnum.GL_TEXTURE0.value + i));
+            code.format("glBindTexture(GL_TEXTURE_2D, texture_%d);CHKERR;\n",
+                    serverTexture.tmu2D[i]);
+        }
+        for (int i = 0; i < serverTexture.tmuCube.length && i < 16; i++) {
+            code.format("glActiveTexture(%s);CHKERR;\n",
+                    GLEnum.valueOf(GLEnum.GL_TEXTURE0.value + i));
+            code.format("glBindTexture(GL_TEXTURE_CUBE_MAP, texture_%d);CHKERR;\n",
+                    serverTexture.tmuCube[i]);
+        }
+        code.format("glActiveTexture(%s);CHKERR;\n", serverTexture.activeTexture);
+        if (serverTexture.tex2D == null)
+            code.format("glBindTexture(GL_TEXTURE_2D, 0);CHKERR;\n");
+        else
+            code.format("glBindTexture(GL_TEXTURE_2D, texture_%d);CHKERR;\n",
+                    serverTexture.tex2D.name);
+        if (serverTexture.texCube == null)
+            code.format("glBindTexture(GL_TEXTURE_CUBE_MAP, 0);CHKERR;\n");
+        else
+            code.format("glBindTexture(GL_TEXTURE_CUBE_MAP, texture_%d);CHKERR;\n",
+                    serverTexture.texCube.name);
+    }
+
+    private void CodeGenBufferData(final ByteBuffer buffer, final String call) {
+        ByteBuffer bfr = buffer;
+        if (buffer.isReadOnly()) {
+            bfr = ByteBuffer.allocate(buffer.capacity());
+            bfr.put(buffer);
+        }
+        final byte[] data = bfr.array();
+        try {
+            code.write("{\n");
+            code.format("    void * bufferData = malloc(%d);\n", data.length);
+            code.format("    FILE * bufferFile = fopen(\"/sdcard/frame_data.bin\", \"rb\");\n");
+            code.format("    assert(bufferFile);\n");
+            code.format("    fseek(bufferFile, %d, SEEK_SET);\n", dataOut.getChannel()
+                    .position());
+            dataOut.write(data);
+            code.format("    fread(bufferData, %d, 1, bufferFile);\n", data.length);
+            code.format("    fclose(bufferFile);\n");
+            code.format("    " + call + ";CHKERR;\n");
+            code.format("    free(bufferData);\n");
+            code.format("}\n");
+        } catch (IOException e) {
+            e.printStackTrace();
+            assert false;
+        }
+    }
+
+    private void CodeGenServerVertex(final GLServerVertex v) {
+        code.write("// CodeGenServerVertex\n");
+        for (int i = 0; i < v.buffers.size(); i++) {
+            final int name = v.buffers.keyAt(i);
+            final String id = "buffer_" + name;
+            final GLBuffer buffer = v.buffers.valueAt(i);
+            if (bufferNames.indexOfKey(name) < 0) {
+                namesHeader.format("extern GLuint %s;\n", id);
+                namesSource.format("GLuint %s = 0;\n", id);
+            }
+            code.format("%s = 0;\n", id);
+            bufferNames.put(name, name);
+            if (name == 0)
+                continue;
+            code.format("glGenBuffers(1, &%s);CHKERR;\n", id);
+            if (buffer.target != null) {
+                code.format("glBindBuffer(%s, %s);CHKERR;\n", buffer.target, id);
+                if (buffer.data != null) {
+                    String s = String.format("glBufferData(%s, %d, bufferData, %s)", buffer.target,
+                            buffer.data.capacity(), buffer.usage);
+                    CodeGenBufferData(buffer.data, s);
+                }
+            }
+        }
+        // TODO: use MAX_VERTEX_ATTRIBS
+        for (int i = 0; i < v.defaultAttribs.length; i++)
+            code.format("glVertexAttrib4f(%d, %f, %f, %f, %f);CHKERR;\n", i,
+                    v.defaultAttribs[i][0],
+                    v.defaultAttribs[i][1], v.defaultAttribs[i][2], v.defaultAttribs[i][3]);
+        for (int i = 0; i < v.attribPointers.length; i++) {
+            final GLAttribPointer att = v.attribPointers[i];
+            if (att.type == null)
+                continue;
+            if (att.buffer != null)
+                code.format("glBindBuffer(GL_ARRAY_BUFFER, buffer_%d);CHKERR;\n", att.buffer.name);
+            else
+                code.format("glBindBuffer(GL_ARRAY_BUFFER, 0);CHKERR;\n");
+            code.format("glVertexAttribPointer(%d, %d, %s, %b, %d, (const GLvoid *)%d);CHKERR;\n",
+                    i, att.size, att.type, att.normalized, att.stride, att.ptr);
+        }
+        if (v.attribBuffer != null)
+            code.format("glBindBuffer(GL_ARRAY_BUFFER, buffer_%d);CHKERR;\n", v.attribBuffer.name);
+        else
+            code.write("glBindBuffer(GL_ARRAY_BUFFER, 0);CHKERR;\n");
+        if (v.indexBuffer != null)
+            code.format("glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer_%d);CHKERR;\n",
+                    v.indexBuffer.name);
+        else
+            code.write("glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);CHKERR;\n");
+    }
+
+    private void CodeGenGenNames(final Message msg) {
+        final ByteBuffer names = msg.getData().asReadOnlyByteBuffer();
+        names.order(SampleView.targetByteOrder);
+        SparseIntArray namesArray = null;
+        for (int i = 0; i < msg.getArg0(); i++) {
+            String id = "";
+            final int name = names.getInt();
+            switch (msg.getFunction()) {
+                case glGenBuffers:
+                    id = "buffer";
+                    namesArray = bufferNames;
+                    break;
+                case glGenFramebuffers:
+                    id = "framebuffer";
+                    namesArray = framebufferNames;
+                    break;
+                case glGenRenderbuffers:
+                    id = "renderbuffer";
+                    namesArray = renderbufferNames;
+                    break;
+                case glGenTextures:
+                    id = "texture";
+                    namesArray = textureNames;
+                    break;
+                default:
+                    assert false;
+            }
+            id += "_" + name;
+            if (namesArray.indexOfKey(name) < 0) {
+                namesHeader.format("extern GLuint %s;\n", id);
+                namesSource.format("GLuint %s = 0;\n", id);
+            }
+            code.format("%s = 0;\n", id);
+            namesArray.put(name, name);
+            code.format("%s(1, &%s);CHKERR;\n", msg.getFunction(), id);
+        }
+    }
+
+    private void CodeGenDeleteNames(final Message msg) {
+        final ByteBuffer names = msg.getData().asReadOnlyByteBuffer();
+        names.order(SampleView.targetByteOrder);
+        SparseIntArray namesArray = null;
+        for (int i = 0; i < msg.getArg0(); i++) {
+            String id = null;
+            final int name = names.getInt();
+            switch (msg.getFunction()) {
+                case glDeleteBuffers:
+                    id = "buffer";
+                    namesArray = bufferNames;
+                    break;
+                case glDeleteFramebuffers:
+                    id = "framebuffer";
+                    namesArray = framebufferNames;
+                    break;
+                case glDeleteRenderbuffers:
+                    id = "renderbuffer";
+                    namesArray = renderbufferNames;
+                    break;
+                case glDeleteTextures:
+                    id = "texture";
+                    namesArray = textureNames;
+                    break;
+                default:
+                    assert false;
+            }
+            id += "_" + name;
+            code.format("%s = 0;\n", id);
+            namesArray.put(name, 0);
+            code.format("%s(1, &%s);CHKERR;\n", msg.getFunction(), id);
+        }
+    }
+
+    private void CodeGenBindNames(final Message msg) {
+        String id = null;
+        SparseIntArray namesArray = null;
+        final int name = msg.getArg1();
+        switch (msg.getFunction()) {
+            case glBindBuffer:
+                id = "buffer";
+                namesArray = bufferNames;
+                break;
+            case glBindFramebuffer:
+                id = "framebuffer";
+                namesArray = framebufferNames;
+                break;
+            case glBindRenderbuffer:
+                id = "renderbuffer";
+                namesArray = renderbufferNames;
+                break;
+            case glBindTexture:
+                id = "texture";
+                namesArray = textureNames;
+                break;
+            default:
+                assert false;
+        }
+        id += "_" + name;
+        if (namesArray.indexOfKey(name) < 0) {
+            namesHeader.format("extern GLuint %s;\n", id);
+            namesSource.format("GLuint %s = 0;\n", id);
+        }
+        code.format("%s = %d;\n", id, name);
+        namesArray.put(name, name);
+        code.write(MessageFormatter.Format(msg, true));
+        code.write(";CHKERR;\n");
+    }
+
+    private void CodeGenDrawArrays(final GLServerVertex v, final ByteBuffer[] attribs,
+            final int mode, final int count) throws IOException {
+        code.write("{\n");
+        code.format("    FILE * attribFile = fopen(\"/sdcard/frame_data.bin\", \"rb\");CHKERR;\n");
+        code.format("    assert(attribFile);CHKERR;\n");
+        code.format("    fseek(attribFile, %d, SEEK_SET);CHKERR;\n", dataOut.getChannel()
+                .position());
+        code.format("    glBindBuffer(GL_ARRAY_BUFFER, 0);CHKERR;\n");
+        for (int i = 0; i < attribs.length; i++) {
+            final GLAttribPointer att = v.attribPointers[i];
+            if (!att.enabled)
+                continue;
+            final byte[] data = attribs[i].array();
+            final String typeName = "GL" + att.type.name().substring(3).toLowerCase();
+            code.format("    %s * attrib%d = (%s *)malloc(%d);CHKERR;\n", typeName, i, typeName,
+                    data.length);
+            dataOut.write(data);
+            code.format("    fread(attrib%d, %d, 1, attribFile);CHKERR;\n", i, data.length);
+            // code.format("    for (unsigned int i = 0; i < %d; i++)\n", count
+            // * att.size);
+            // code.format("        printf(\"%%f \\n\", attrib%d[i]);CHKERR;\n",
+            // i);
+            code.format("    glVertexAttribPointer(%d, %d, %s, %b, %d, attrib%d);CHKERR;\n",
+                    i, att.size, att.type, att.normalized,
+                    att.size * GLServerVertex.TypeSize(att.type), i);
+        }
+        code.format("    fclose(attribFile);CHKERR;\n");
+        code.format("    glDrawArrays(%s, 0, %d);CHKERR;\n", GLEnum.valueOf(mode), count);
+        for (int i = 0; i < attribs.length; i++)
+            if (v.attribPointers[i].enabled)
+                code.format("    free(attrib%d);CHKERR;\n", i);
+
+        if (v.attribBuffer != null)
+            code.format("    glBindBuffer(GL_ARRAY_BUFFER, %d);CHKERR;\n",
+                    v.attribBuffer.name);
+        code.write("};\n");
+    }
+
+    private void CodeGenFunction(final Context ctx, final MessageData msgData) throws IOException {
+        final Message msg = msgData.msg;
+        final Message oriMsg = msgData.oriMsg;
+        String call = MessageFormatter.Format(msg, true);
+        switch (msg.getFunction()) {
+            case glActiveTexture:
+            case glAttachShader:
+            case glBindAttribLocation:
+                break;
+            case glBindBuffer:
+            case glBindFramebuffer:
+            case glBindRenderbuffer:
+            case glBindTexture:
+                CodeGenBindNames(msg);
+                return;
+            case glBlendColor:
+            case glBlendEquation:
+            case glBlendEquationSeparate:
+            case glBlendFunc:
+            case glBlendFuncSeparate:
+                break;
+            case glBufferData:
+                call = MessageFormatter.Format(msg, true).replace("arg2", "bufferData");
+                CodeGenBufferData(msg.getData().asReadOnlyByteBuffer(), call);
+                return;
+            case glBufferSubData:
+                call = MessageFormatter.Format(msg, true).replace("arg3", "bufferData");
+                CodeGenBufferData(msg.getData().asReadOnlyByteBuffer(), call);
+                return;
+            case glCheckFramebufferStatus:
+            case glClear:
+            case glClearColor:
+            case glClearDepthf:
+            case glClearStencil:
+            case glColorMask:
+            case glCompileShader:
+                break;
+            case glCompressedTexImage2D:
+            case glCompressedTexSubImage2D:
+            case glCopyTexImage2D:
+            case glCopyTexSubImage2D:
+                CodeGenTextureUpload(msg, false);
+                return;
+            case glCreateProgram:
+                namesHeader.format("extern GLuint program_%d;\n", msg.getRet());
+                namesSource.format("GLuint program_%d = 0;\n", msg.getRet());
+                code.format("program_%d = glCreateProgram();CHKERR;\n", msg.getRet());
+                return;
+            case glCreateShader:
+                namesHeader.format("extern GLuint shader_%d;\n", msg.getRet());
+                namesSource.format("GLuint shader_%d = 0;\n", msg.getRet());
+                code.format("shader_%d = %s;\n", msg.getRet(), call);
+                return;
+            case glCullFace:
+                break;
+            case glDeleteBuffers:
+            case glDeleteFramebuffers:
+            case glDeleteProgram:
+                programNames.put(msg.getArg0(), 0);
+                break;
+            case glDeleteRenderbuffers:
+                CodeGenDeleteNames(msg);
+                return;
+            case glDeleteShader:
+                shaderNames.put(msg.getArg0(), 0);
+                return;
+            case glDeleteTextures:
+                CodeGenDeleteNames(msg);
+                return;
+            case glDepthFunc:
+            case glDepthMask:
+            case glDepthRangef:
+            case glDetachShader:
+            case glDisable:
+            case glDisableVertexAttribArray:
+                break;
+            case glDrawArrays:
+                CodeGenDrawArrays(ctx.serverVertex, msgData.attribs, msg.getArg0(), msg.getArg2());
+                return;
+            case glDrawElements:
+                CodeGenDrawArrays(ctx.serverVertex, msgData.attribs, msg.getArg0(), msg.getArg1());
+                return;
+            case glEnable:
+            case glEnableVertexAttribArray:
+            case glFinish:
+            case glFlush:
+            case glFramebufferRenderbuffer:
+            case glFramebufferTexture2D:
+            case glFrontFace:
+                break;
+            case glGenBuffers:
+                CodeGenGenNames(msg);
+                return;
+            case glGenerateMipmap:
+                break;
+            case glGenFramebuffers:
+            case glGenRenderbuffers:
+            case glGenTextures:
+                CodeGenGenNames(msg);
+                return;
+            case glGetActiveAttrib:
+            case glGetActiveUniform:
+            case glGetAttachedShaders:
+                break;
+            case glGetAttribLocation:
+                call = String.format("assert(%d == %s)", msg.getRet(), call);
+                break;
+            case glGetBooleanv:
+            case glGetBufferParameteriv:
+                return; // TODO
+            case glGetError:
+                code.write("CHKERR;\n");
+                return;
+            case glGetFloatv:
+            case glGetFramebufferAttachmentParameteriv:
+            case glGetIntegerv:
+            case glGetProgramiv:
+            case glGetProgramInfoLog:
+            case glGetRenderbufferParameteriv:
+            case glGetShaderiv:
+            case glGetShaderInfoLog:
+            case glGetShaderPrecisionFormat:
+            case glGetShaderSource:
+            case glGetString:
+            case glGetTexParameterfv:
+            case glGetTexParameteriv:
+            case glGetUniformfv:
+            case glGetUniformiv:
+                return;
+            case glGetUniformLocation:
+                call = String.format("assert(%d == %s)", msg.getRet(), call);
+                break;
+            case glGetVertexAttribfv:
+            case glGetVertexAttribiv:
+            case glGetVertexAttribPointerv:
+                return; // TODO
+            case glHint:
+            case glIsBuffer:
+            case glIsEnabled:
+            case glIsFramebuffer:
+            case glIsProgram:
+            case glIsRenderbuffer:
+            case glIsShader:
+            case glIsTexture:
+            case glLineWidth:
+            case glLinkProgram:
+            case glPixelStorei:
+            case glPolygonOffset:
+                break;
+            case glReadPixels:
+                return; // TODO
+            case glReleaseShaderCompiler:
+            case glRenderbufferStorage:
+            case glSampleCoverage:
+            case glScissor:
+                break;
+            case glShaderBinary:
+                return; // TODO
+            case glShaderSource:
+                call = String.format(
+                        "glShaderSource(shader_%d, 1, (const char * []){\"%s\"}, NULL)",
+                        msg.getArg0(),
+                        msg.getData().toStringUtf8().replace("\r", "").replace("\n", "\\n\\\n")
+                                .replace("\"", "\\\"")
+                                );
+                break;
+            case glStencilFunc:
+            case glStencilFuncSeparate:
+            case glStencilMask:
+            case glStencilMaskSeparate:
+            case glStencilOp:
+            case glStencilOpSeparate:
+                break;
+            case glTexImage2D:
+                CodeGenTextureUpload(msg, false);
+                return;
+            case glTexParameterf:
+                break;
+            case glTexParameterfv:
+                return; // TODO
+            case glTexParameteri:
+                break;
+            case glTexParameteriv:
+                return; // TODO
+            case glTexSubImage2D:
+                CodeGenTextureUpload(msg, false);
+                return;
+            case glUniform1f:
+            case glUniform1fv:
+            case glUniform1i:
+            case glUniform1iv:
+            case glUniform2f:
+            case glUniform2fv:
+            case glUniform2i:
+            case glUniform2iv:
+            case glUniform3f:
+            case glUniform3fv:
+            case glUniform3i:
+            case glUniform3iv:
+            case glUniform4f:
+            case glUniform4fv:
+            case glUniform4i:
+            case glUniform4iv:
+            case glUniformMatrix2fv:
+            case glUniformMatrix3fv:
+            case glUniformMatrix4fv:
+            case glUseProgram:
+            case glValidateProgram:
+            case glVertexAttrib1f:
+            case glVertexAttrib1fv:
+            case glVertexAttrib2f:
+            case glVertexAttrib2fv:
+            case glVertexAttrib3f:
+            case glVertexAttrib3fv:
+            case glVertexAttrib4f:
+            case glVertexAttrib4fv:
+                break;
+            case glVertexAttribPointer:
+                // pointer set during glDrawArrays/Elements from captured data
+                call = call.replace("arg5", "NULL");
+                break;
+            case glViewport:
+                break;
+            case eglSwapBuffers:
+                return;
+            default:
+                assert false;
+                return;
+        }
+        code.write(call + ";CHKERR;\n");
+    }
+
+    private void CodeGenSetup(final Context ctx) {
+        try {
+            codeFile = new FileWriter("frame_setup.cpp", false);
+            code = new PrintWriter(codeFile);
+            dataOut = new FileOutputStream("frame_data.bin", false);
+            namesHeaderFile = new FileWriter("frame_names.h", false);
+            namesHeader = new PrintWriter(namesHeaderFile);
+            namesSourceFile = new FileWriter("frame_names.cpp", false);
+            namesSource = new PrintWriter(namesSourceFile);
+        } catch (IOException e) {
+            e.printStackTrace();
+            assert false;
+        }
+        bufferNames = new SparseIntArray();
+        framebufferNames = new SparseIntArray();
+        programNames = new SparseIntArray();
+        textureNames = new SparseIntArray();
+        shaderNames = new SparseIntArray();
+        renderbufferNames = new SparseIntArray();
+
+        namesHeader.write("#include <stdlib.h>\n");
+        namesHeader.write("#include <stdio.h>\n");
+        namesHeader.write("#include <assert.h>\n");
+        namesHeader.write("#include <GLES2/gl2.h>\n");
+        namesHeader.write("#include <GLES2/gl2ext.h>\n");
+        namesHeader.write("#define CHKERR assert(GL_NO_ERROR == glGetError());/**/\n");
+        namesHeader.write("void FrameSetup();\n");
+        namesHeader.write("extern const unsigned int FrameCount;\n");
+        namesHeader.write("extern const GLuint program_0;\n");
+
+        namesSource.write("#include \"frame_names.h\"\n");
+        namesSource.write("const GLuint program_0 = 0;\n");
+
+        code.write("#include \"frame_names.h\"\n");
+        code.write("void FrameSetup(){\n");
+
+        CodeGenServerState(ctx.serverState);
+        CodeGenServerShader(ctx.serverShader);
+        CodeGenServerTexture(ctx.serverTexture, true);
+        CodeGenServerVertex(ctx.serverVertex);
+
+        code.write("}\n");
+
+        try {
+            codeFile.close();
+            makeFile = new FileWriter("frame_src.mk", false);
+            make = new PrintWriter(makeFile);
+            make.write("LOCAL_SRC_FILES := \\\n");
+        } catch (IOException e) {
+            e.printStackTrace();
+            assert false;
+        }
+    }
+
+    private void CodeGenCleanup() {
+        make.write("    frame_setup.cpp \\\n");
+        make.write("    frame_names.cpp");
+        try {
+            dataOut.flush();
+            dataOut.close();
+            codeFile.close();
+            makeFile.close();
+            namesHeaderFile.close();
+            namesSourceFile.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+            assert false;
+        }
+        dataOut = null;
+        code = null;
+        codeFile = null;
+        make = null;
+        makeFile = null;
+
+        bufferNames = null;
+        framebufferNames = null;
+        programNames = null;
+        textureNames = null;
+        shaderNames = null;
+        renderbufferNames = null;
+    }
+
+    void CodeGenFrames(final DebugContext dbgCtx, int count) {
+        Context ctx = dbgCtx.frames.get(0).startContext.clone();
+        CodeGenSetup(ctx);
+        for (int i = 0; i < count; i++) {
+            try {
+                codeFile = new FileWriter("frame" + i + ".cpp", false);
+                code = new PrintWriter(codeFile);
+            } catch (IOException e1) {
+                e1.printStackTrace();
+                assert false;
+            }
+            make.format("    frame%d.cpp \\\n", i);
+
+            code.write("#include \"frame_names.h\"\n");
+            code.format("void Frame%d(){\n", i);
+            final Frame frame = dbgCtx.frames.get(i);
+            for (int j = 0; j < frame.calls.size(); j++) {
+                final MessageData msgData = frame.calls.get(j);
+                code.format("/* frame function %d: %s %s*/\n", j, msgData.msg.getFunction(),
+                        MessageFormatter.Format(msgData.msg, false));
+                ctx.ProcessMessage(msgData.oriMsg);
+                try {
+                    CodeGenFunction(ctx, msgData);
+                } catch (IOException e) {
+                    e.printStackTrace();
+                    assert false;
+                }
+            }
+            code.write("}\n");
+            try {
+                codeFile.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+                assert false;
+            }
+        }
+        for (int i = 0; i < count; i++)
+            namesHeader.format("void Frame%d();\n", i);
+        namesHeader.format("extern void (* Frames[%d])();\n", count);
+        namesSource.format("void (* Frames[%d])() = {\n", count);
+        for (int i = 0; i < count; i++) {
+            namesSource.format("    Frame%d,\n", i);
+        }
+        namesSource.write("};\n");
+        namesSource.format("const unsigned int FrameCount = %d;\n", count);
+        CodeGenCleanup();
+    }
+
+    void CodeGenFrame(final Frame frame) {
+        Context ctx = frame.startContext.clone();
+        CodeGenSetup(ctx);
+        try {
+            codeFile = new FileWriter("frame0.cpp", false);
+            code = new PrintWriter(codeFile);
+        } catch (IOException e1) {
+            e1.printStackTrace();
+            assert false;
+        }
+        make.format("    frame0.cpp \\\n");
+        code.write("#include \"frame_names.h\"\n");
+        code.format("void Frame0(){\n");
+        for (int i = 0; i < frame.calls.size(); i++) {
+            final MessageData msgData = frame.calls.get(i);
+            code.format("/* frame function %d: %s %s*/\n", i, msgData.msg.getFunction(),
+                    MessageFormatter.Format(msgData.msg, false));
+            ctx.ProcessMessage(msgData.oriMsg);
+            try {
+                CodeGenFunction(ctx, msgData);
+            } catch (IOException e) {
+                e.printStackTrace();
+                assert false;
+            }
+        }
+        code.write("}\n");
+        namesHeader.write("void Frame0();\n");
+        namesHeader.write("extern void (* Frames[1])();\n");
+        namesSource.write("void (* Frames[1])() = {Frame0};\n");
+        namesSource.write("const unsigned int FrameCount = 1;\n");
+        CodeGenCleanup();
+    }
+}
diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/Context.java b/tools/glesv2debugger/src/com/android/glesv2debugger/Context.java
index c228df8..15b2da6 100644
--- a/tools/glesv2debugger/src/com/android/glesv2debugger/Context.java
+++ b/tools/glesv2debugger/src/com/android/glesv2debugger/Context.java
@@ -66,6 +66,7 @@
             msg = currentContext.processed;
         currentContext.processed = null;
         MessageData msgData = new MessageData(Display.getCurrent(), msg, oriMsg, currentContext);
+        msgData.attribs = currentContext.serverVertex.fetchedAttribs;
         currentFrame.calls.add(msgData);
         if (msg.getFunction() != Function.eglSwapBuffers)
             return msgData;
@@ -107,6 +108,9 @@
     public Context clone() {
         try {
             Context copy = (Context) super.clone();
+            // FIXME: context sharing list clone
+            copy.shares = new ArrayList<Context>(1);
+            copy.shares.add(copy);
             copy.serverVertex = serverVertex.clone();
             copy.serverShader = serverShader.clone(copy);
             copy.serverState = serverState.clone();
@@ -156,7 +160,7 @@
             if (entry.obj != null) {
                 objStr = entry.obj.toString();
                 if (entry.obj instanceof Message)
-                    objStr = MessageFormatter.Format((Message) entry.obj);
+                    objStr = MessageFormatter.Format((Message) entry.obj, false);
             }
             return entry.name + " = " + objStr;
         }
@@ -240,7 +244,7 @@
                 final Message val = context.serverState.integers.valueAt(i);
                 if (val != null)
                     children.add(GLEnum.valueOf(key).name() + " : " +
-                            MessageFormatter.Format(val));
+                            MessageFormatter.Format(val, false));
                 else
                     children.add(GLEnum.valueOf(key).name() + " : default");
             }
@@ -252,7 +256,7 @@
                     children.add(Function.valueOf(key).name() + " : default");
                 else
                     children.add(Function.valueOf(key).name() + " : "
-                            + MessageFormatter.Format(msg));
+                            + MessageFormatter.Format(msg, false));
             }
         } else if (entry.obj instanceof SparseArray) {
             SparseArray<?> sa = (SparseArray<?>) entry.obj;
diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/GLEnum.java b/tools/glesv2debugger/src/com/android/glesv2debugger/GLEnum.java
index 8fd3014..898c6e9 100644
--- a/tools/glesv2debugger/src/com/android/glesv2debugger/GLEnum.java
+++ b/tools/glesv2debugger/src/com/android/glesv2debugger/GLEnum.java
@@ -53,7 +53,7 @@
     GL_STACK_OVERFLOW(0x0503),
     GL_STACK_UNDERFLOW(0x0504),
     GL_OUT_OF_MEMORY(0x0505),
-    GL_INVALID_FRAMEBUFFER_OPERATION_OES(0x0506),
+    GL_INVALID_FRAMEBUFFER_OPERATION(0x0506),
     GL_EXP(0x0800),
     GL_EXP2(0x0801),
     GL_CW(0x0900),
@@ -207,7 +207,7 @@
     GL_TEXTURE_ENV_MODE(0x2200),
     GL_TEXTURE_ENV_COLOR(0x2201),
     GL_TEXTURE_ENV(0x2300),
-    GL_TEXTURE_GEN_MODE_OES(0x2500),
+    GL_TEXTURE_GEN_MODE(0x2500),
     GL_NEAREST(0x2600),
     GL_LINEAR(0x2601),
     GL_NEAREST_MIPMAP_NEAREST(0x2700),
@@ -240,26 +240,26 @@
     GL_CONSTANT_ALPHA(0x8003),
     GL_ONE_MINUS_CONSTANT_ALPHA(0x8004),
     GL_BLEND_COLOR(0x8005),
-    GL_FUNC_ADD_OES(0x8006),
+    GL_FUNC_ADD(0x8006),
     GL_MIN_EXT(0x8007),
     GL_MAX_EXT(0x8008),
-    GL_BLEND_EQUATION_RGB_OES(0x8009),
-    GL_FUNC_SUBTRACT_OES(0x800A),
-    GL_FUNC_REVERSE_SUBTRACT_OES(0x800B),
+    GL_BLEND_EQUATION_RGB(0x8009),
+    GL_FUNC_SUBTRACT(0x800A),
+    GL_FUNC_REVERSE_SUBTRACT(0x800B),
     GL_UNSIGNED_SHORT_4_4_4_4(0x8033),
     GL_UNSIGNED_SHORT_5_5_5_1(0x8034),
     GL_POLYGON_OFFSET_FILL(0x8037),
     GL_POLYGON_OFFSET_FACTOR(0x8038),
     GL_RESCALE_NORMAL(0x803A),
-    GL_RGB8_OES(0x8051),
-    GL_RGBA4_OES(0x8056),
-    GL_RGB5_A1_OES(0x8057),
-    GL_RGBA8_OES(0x8058),
+    GL_RGB8(0x8051),
+    GL_RGBA4(0x8056),
+    GL_RGB5_A1(0x8057),
+    GL_RGBA8(0x8058),
     GL_TEXTURE_BINDING_2D(0x8069),
-    GL_TEXTURE_BINDING_3D_OES(0x806A),
-    GL_TEXTURE_3D_OES(0x806F),
-    GL_TEXTURE_WRAP_R_OES(0x8072),
-    GL_MAX_3D_TEXTURE_SIZE_OES(0x8073),
+    GL_TEXTURE_BINDING_3D(0x806A),
+    GL_TEXTURE_3D(0x806F),
+    GL_TEXTURE_WRAP_R(0x8072),
+    GL_MAX_3D_TEXTURE_SIZE(0x8073),
     GL_VERTEX_ARRAY(0x8074),
     GL_NORMAL_ARRAY(0x8075),
     GL_COLOR_ARRAY(0x8076),
@@ -287,10 +287,10 @@
     GL_SAMPLES(0x80A9),
     GL_SAMPLE_COVERAGE_VALUE(0x80AA),
     GL_SAMPLE_COVERAGE_INVERT(0x80AB),
-    GL_BLEND_DST_RGB_OES(0x80C8),
-    GL_BLEND_SRC_RGB_OES(0x80C9),
-    GL_BLEND_DST_ALPHA_OES(0x80CA),
-    GL_BLEND_SRC_ALPHA_OES(0x80CB),
+    GL_BLEND_DST_RGB(0x80C8),
+    GL_BLEND_SRC_RGB(0x80C9),
+    GL_BLEND_DST_ALPHA(0x80CA),
+    GL_BLEND_SRC_ALPHA(0x80CB),
     GL_BGRA_EXT(0x80E1),
     GL_POINT_SIZE_MIN(0x8126),
     GL_POINT_SIZE_MAX(0x8127),
@@ -299,14 +299,14 @@
     GL_CLAMP_TO_EDGE(0x812F),
     GL_GENERATE_MIPMAP(0x8191),
     GL_GENERATE_MIPMAP_HINT(0x8192),
-    GL_DEPTH_COMPONENT16_OES(0x81A5),
-    GL_DEPTH_COMPONENT24_OES(0x81A6),
-    GL_DEPTH_COMPONENT32_OES(0x81A7),
+    GL_DEPTH_COMPONENT16(0x81A5),
+    GL_DEPTH_COMPONENT24(0x81A6),
+    GL_DEPTH_COMPONENT32(0x81A7),
     GL_UNSIGNED_SHORT_5_6_5(0x8363),
     GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT(0x8365),
     GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT(0x8366),
     GL_UNSIGNED_INT_2_10_10_10_REV_EXT(0x8368),
-    GL_MIRRORED_REPEAT_OES(0x8370),
+    GL_MIRRORED_REPEAT(0x8370),
     GL_COMPRESSED_RGB_S3TC_DXT1_EXT(0x83F0),
     GL_COMPRESSED_RGBA_S3TC_DXT1_EXT(0x83F1),
     GL_ALIASED_POINT_SIZE_RANGE(0x846D),
@@ -347,30 +347,30 @@
     GL_CLIENT_ACTIVE_TEXTURE(0x84E1),
     GL_MAX_TEXTURE_UNITS(0x84E2),
     GL_SUBTRACT(0x84E7),
-    GL_MAX_RENDERBUFFER_SIZE_OES(0x84E8),
+    GL_MAX_RENDERBUFFER_SIZE(0x84E8),
     GL_ALL_COMPLETED_NV(0x84F2),
     GL_FENCE_STATUS_NV(0x84F3),
     GL_FENCE_CONDITION_NV(0x84F4),
-    GL_DEPTH_STENCIL_OES(0x84F9),
-    GL_UNSIGNED_INT_24_8_OES(0x84FA),
+    GL_DEPTH_STENCIL(0x84F9),
+    GL_UNSIGNED_INT_24_8(0x84FA),
     GL_MAX_TEXTURE_LOD_BIAS_EXT(0x84FD),
     GL_TEXTURE_MAX_ANISOTROPY_EXT(0x84FE),
     GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT(0x84FF),
     GL_TEXTURE_FILTER_CONTROL_EXT(0x8500),
     GL_TEXTURE_LOD_BIAS_EXT(0x8501),
-    GL_INCR_WRAP_OES(0x8507),
-    GL_DECR_WRAP_OES(0x8508),
-    GL_NORMAL_MAP_OES(0x8511),
-    GL_REFLECTION_MAP_OES(0x8512),
-    GL_TEXTURE_CUBE_MAP_OES(0x8513),
-    GL_TEXTURE_BINDING_CUBE_MAP_OES(0x8514),
-    GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES(0x8515),
-    GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES(0x8516),
-    GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES(0x8517),
-    GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES(0x8518),
-    GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES(0x8519),
-    GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES(0x851A),
-    GL_MAX_CUBE_MAP_TEXTURE_SIZE_OES(0x851C),
+    GL_INCR_WRAP(0x8507),
+    GL_DECR_WRAP(0x8508),
+    GL_NORMAL_MAP(0x8511),
+    GL_REFLECTION_MAP(0x8512),
+    GL_TEXTURE_CUBE_MAP(0x8513),
+    GL_TEXTURE_BINDING_CUBE_MAP(0x8514),
+    GL_TEXTURE_CUBE_MAP_POSITIVE_X(0x8515),
+    GL_TEXTURE_CUBE_MAP_NEGATIVE_X(0x8516),
+    GL_TEXTURE_CUBE_MAP_POSITIVE_Y(0x8517),
+    GL_TEXTURE_CUBE_MAP_NEGATIVE_Y(0x8518),
+    GL_TEXTURE_CUBE_MAP_POSITIVE_Z(0x8519),
+    GL_TEXTURE_CUBE_MAP_NEGATIVE_Z(0x851A),
+    GL_MAX_CUBE_MAP_TEXTURE_SIZE(0x851C),
     GL_COMBINE(0x8570),
     GL_COMBINE_RGB(0x8571),
     GL_COMBINE_ALPHA(0x8572),
@@ -392,7 +392,7 @@
     GL_OPERAND0_ALPHA(0x8598),
     GL_OPERAND1_ALPHA(0x8599),
     GL_OPERAND2_ALPHA(0x859A),
-    GL_VERTEX_ARRAY_BINDING_OES(0x85B5),
+    GL_VERTEX_ARRAY_BINDING(0x85B5),
     GL_VERTEX_ATTRIB_ARRAY_ENABLED(0x8622),
     GL_VERTEX_ATTRIB_ARRAY_SIZE(0x8623),
     GL_VERTEX_ATTRIB_ARRAY_STRIDE(0x8624),
@@ -401,39 +401,39 @@
     GL_VERTEX_ATTRIB_ARRAY_POINTER(0x8645),
     GL_NUM_COMPRESSED_TEXTURE_FORMATS(0x86A2),
     GL_COMPRESSED_TEXTURE_FORMATS(0x86A3),
-    GL_MAX_VERTEX_UNITS_OES(0x86A4),
-    GL_WEIGHT_ARRAY_TYPE_OES(0x86A9),
-    GL_WEIGHT_ARRAY_STRIDE_OES(0x86AA),
-    GL_WEIGHT_ARRAY_SIZE_OES(0x86AB),
-    GL_WEIGHT_ARRAY_POINTER_OES(0x86AC),
-    GL_WEIGHT_ARRAY_OES(0x86AD),
+    GL_MAX_VERTEX_UNITS(0x86A4),
+    GL_WEIGHT_ARRAY_TYPE(0x86A9),
+    GL_WEIGHT_ARRAY_STRIDE(0x86AA),
+    GL_WEIGHT_ARRAY_SIZE(0x86AB),
+    GL_WEIGHT_ARRAY_POINTER(0x86AC),
+    GL_WEIGHT_ARRAY(0x86AD),
     GL_DOT3_RGB(0x86AE),
     GL_DOT3_RGBA(0x86AF),
     GL_Z400_BINARY_AMD(0x8740),
-    GL_PROGRAM_BINARY_LENGTH_OES(0x8741),
+    GL_PROGRAM_BINARY_LENGTH(0x8741),
     GL_BUFFER_SIZE(0x8764),
     GL_BUFFER_USAGE(0x8765),
     GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD(0x87EE),
     GL_3DC_X_AMD(0x87F9),
     GL_3DC_XY_AMD(0x87FA),
-    GL_NUM_PROGRAM_BINARY_FORMATS_OES(0x87FE),
-    GL_PROGRAM_BINARY_FORMATS_OES(0x87FF),
+    GL_NUM_PROGRAM_BINARY_FORMATS(0x87FE),
+    GL_PROGRAM_BINARY_FORMATS(0x87FF),
     GL_STENCIL_BACK_FUNC(0x8800),
     GL_STENCIL_BACK_FAIL(0x8801),
     GL_STENCIL_BACK_PASS_DEPTH_FAIL(0x8802),
     GL_STENCIL_BACK_PASS_DEPTH_PASS(0x8803),
     GL_WRITEONLY_RENDERING_QCOM(0x8823),
-    GL_BLEND_EQUATION_ALPHA_OES(0x883D),
-    GL_MATRIX_PALETTE_OES(0x8840),
-    GL_MAX_PALETTE_MATRICES_OES(0x8842),
-    GL_CURRENT_PALETTE_MATRIX_OES(0x8843),
-    GL_MATRIX_INDEX_ARRAY_OES(0x8844),
-    GL_MATRIX_INDEX_ARRAY_SIZE_OES(0x8846),
-    GL_MATRIX_INDEX_ARRAY_TYPE_OES(0x8847),
-    GL_MATRIX_INDEX_ARRAY_STRIDE_OES(0x8848),
-    GL_MATRIX_INDEX_ARRAY_POINTER_OES(0x8849),
-    GL_POINT_SPRITE_OES(0x8861),
-    GL_COORD_REPLACE_OES(0x8862),
+    GL_BLEND_EQUATION_ALPHA(0x883D),
+    GL_MATRIX_PALETTE(0x8840),
+    GL_MAX_PALETTE_MATRICES(0x8842),
+    GL_CURRENT_PALETTE_MATRIX(0x8843),
+    GL_MATRIX_INDEX_ARRAY(0x8844),
+    GL_MATRIX_INDEX_ARRAY_SIZE(0x8846),
+    GL_MATRIX_INDEX_ARRAY_TYPE(0x8847),
+    GL_MATRIX_INDEX_ARRAY_STRIDE(0x8848),
+    GL_MATRIX_INDEX_ARRAY_POINTER(0x8849),
+    GL_POINT_SPRITE(0x8861),
+    GL_COORD_REPLACE(0x8862),
     GL_MAX_VERTEX_ATTRIBS(0x8869),
     GL_VERTEX_ATTRIB_ARRAY_NORMALIZED(0x886A),
     GL_MAX_TEXTURE_IMAGE_UNITS(0x8872),
@@ -445,22 +445,22 @@
     GL_NORMAL_ARRAY_BUFFER_BINDING(0x8897),
     GL_COLOR_ARRAY_BUFFER_BINDING(0x8898),
     GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING(0x889A),
-    GL_WEIGHT_ARRAY_BUFFER_BINDING_OES(0x889E),
+    GL_WEIGHT_ARRAY_BUFFER_BINDING(0x889E),
     GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING(0x889F),
-    GL_WRITE_ONLY_OES(0x88B9),
-    GL_BUFFER_ACCESS_OES(0x88BB),
-    GL_BUFFER_MAPPED_OES(0x88BC),
-    GL_BUFFER_MAP_POINTER_OES(0x88BD),
+    GL_WRITE_ONLY(0x88B9),
+    GL_BUFFER_ACCESS(0x88BB),
+    GL_BUFFER_MAPPED(0x88BC),
+    GL_BUFFER_MAP_POINTER(0x88BD),
     GL_STREAM_DRAW(0x88E0),
     GL_STATIC_DRAW(0x88E4),
     GL_DYNAMIC_DRAW(0x88E8),
-    GL_DEPTH24_STENCIL8_OES(0x88F0),
-    GL_POINT_SIZE_ARRAY_TYPE_OES(0x898A),
-    GL_POINT_SIZE_ARRAY_STRIDE_OES(0x898B),
-    GL_POINT_SIZE_ARRAY_POINTER_OES(0x898C),
-    GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES(0x898D),
-    GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES(0x898E),
-    GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES(0x898F),
+    GL_DEPTH24_STENCIL8(0x88F0),
+    GL_POINT_SIZE_ARRAY_TYPE(0x898A),
+    GL_POINT_SIZE_ARRAY_STRIDE(0x898B),
+    GL_POINT_SIZE_ARRAY_POINTER(0x898C),
+    GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS(0x898D),
+    GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS(0x898E),
+    GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS(0x898F),
     GL_FRAGMENT_SHADER(0x8B30),
     GL_VERTEX_SHADER(0x8B31),
     GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS(0x8B4C),
@@ -480,7 +480,7 @@
     GL_FLOAT_MAT3(0x8B5B),
     GL_FLOAT_MAT4(0x8B5C),
     GL_SAMPLER_2D(0x8B5E),
-    GL_SAMPLER_3D_OES(0x8B5F),
+    GL_SAMPLER_3D(0x8B5F),
     GL_SAMPLER_CUBE(0x8B60),
     GL_DELETE_STATUS(0x8B80),
     GL_COMPILE_STATUS(0x8B81),
@@ -493,25 +493,25 @@
     GL_SHADER_SOURCE_LENGTH(0x8B88),
     GL_ACTIVE_ATTRIBUTES(0x8B89),
     GL_ACTIVE_ATTRIBUTE_MAX_LENGTH(0x8B8A),
-    GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES(0x8B8B),
+    GL_FRAGMENT_SHADER_DERIVATIVE_HINT(0x8B8B),
     GL_SHADING_LANGUAGE_VERSION(0x8B8C),
     GL_CURRENT_PROGRAM(0x8B8D),
-    GL_PALETTE4_RGB8_OES(0x8B90),
-    GL_PALETTE4_RGBA8_OES(0x8B91),
-    GL_PALETTE4_R5_G6_B5_OES(0x8B92),
-    GL_PALETTE4_RGBA4_OES(0x8B93),
-    GL_PALETTE4_RGB5_A1_OES(0x8B94),
-    GL_PALETTE8_RGB8_OES(0x8B95),
-    GL_PALETTE8_RGBA8_OES(0x8B96),
-    GL_PALETTE8_R5_G6_B5_OES(0x8B97),
-    GL_PALETTE8_RGBA4_OES(0x8B98),
-    GL_PALETTE8_RGB5_A1_OES(0x8B99),
-    GL_IMPLEMENTATION_COLOR_READ_TYPE_OES(0x8B9A),
-    GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES(0x8B9B),
-    GL_POINT_SIZE_ARRAY_OES(0x8B9C),
-    GL_TEXTURE_CROP_RECT_OES(0x8B9D),
-    GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES(0x8B9E),
-    GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES(0x8B9F),
+    GL_PALETTE4_RGB8(0x8B90),
+    GL_PALETTE4_RGBA8(0x8B91),
+    GL_PALETTE4_R5_G6_B5(0x8B92),
+    GL_PALETTE4_RGBA4(0x8B93),
+    GL_PALETTE4_RGB5_A1(0x8B94),
+    GL_PALETTE8_RGB8(0x8B95),
+    GL_PALETTE8_RGBA8(0x8B96),
+    GL_PALETTE8_R5_G6_B5(0x8B97),
+    GL_PALETTE8_RGBA4(0x8B98),
+    GL_PALETTE8_RGB5_A1(0x8B99),
+    GL_IMPLEMENTATION_COLOR_READ_TYPE(0x8B9A),
+    GL_IMPLEMENTATION_COLOR_READ_FORMAT(0x8B9B),
+    GL_POINT_SIZE_ARRAY(0x8B9C),
+    GL_TEXTURE_CROP_RECT(0x8B9D),
+    GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING(0x8B9E),
+    GL_POINT_SIZE_ARRAY_BUFFER_BINDING(0x8B9F),
     GL_COUNTER_TYPE_AMD(0x8BC0),
     GL_COUNTER_RANGE_AMD(0x8BC1),
     GL_UNSIGNED_INT64_AMD(0x8BC2),
@@ -546,52 +546,52 @@
     GL_STENCIL_BACK_REF(0x8CA3),
     GL_STENCIL_BACK_VALUE_MASK(0x8CA4),
     GL_STENCIL_BACK_WRITEMASK(0x8CA5),
-    GL_FRAMEBUFFER_BINDING_OES(0x8CA6),
-    GL_RENDERBUFFER_BINDING_OES(0x8CA7),
-    GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES(0x8CD0),
-    GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES(0x8CD1),
-    GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES(0x8CD2),
-    GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_OES(0x8CD3),
-    GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES(0x8CD4),
-    GL_FRAMEBUFFER_COMPLETE_OES(0x8CD5),
-    GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES(0x8CD6),
-    GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES(0x8CD7),
-    GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES(0x8CD9),
-    GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES(0x8CDA),
-    GL_FRAMEBUFFER_UNSUPPORTED_OES(0x8CDD),
-    GL_COLOR_ATTACHMENT0_OES(0x8CE0),
-    GL_DEPTH_ATTACHMENT_OES(0x8D00),
-    GL_STENCIL_ATTACHMENT_OES(0x8D20),
-    GL_FRAMEBUFFER_OES(0x8D40),
-    GL_RENDERBUFFER_OES(0x8D41),
-    GL_RENDERBUFFER_WIDTH_OES(0x8D42),
-    GL_RENDERBUFFER_HEIGHT_OES(0x8D43),
-    GL_RENDERBUFFER_INTERNAL_FORMAT_OES(0x8D44),
-    GL_STENCIL_INDEX1_OES(0x8D46),
-    GL_STENCIL_INDEX4_OES(0x8D47),
-    GL_STENCIL_INDEX8_OES(0x8D48),
-    GL_RENDERBUFFER_RED_SIZE_OES(0x8D50),
-    GL_RENDERBUFFER_GREEN_SIZE_OES(0x8D51),
-    GL_RENDERBUFFER_BLUE_SIZE_OES(0x8D52),
-    GL_RENDERBUFFER_ALPHA_SIZE_OES(0x8D53),
-    GL_RENDERBUFFER_DEPTH_SIZE_OES(0x8D54),
-    GL_RENDERBUFFER_STENCIL_SIZE_OES(0x8D55),
-    GL_TEXTURE_GEN_STR_OES(0x8D60),
-    GL_HALF_FLOAT_OES(0x8D61),
-    GL_RGB565_OES(0x8D62),
-    GL_ETC1_RGB8_OES(0x8D64),
-    GL_TEXTURE_EXTERNAL_OES(0x8D65),
-    GL_SAMPLER_EXTERNAL_OES(0x8D66),
-    GL_TEXTURE_BINDING_EXTERNAL_OES(0x8D67),
-    GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES(0x8D68),
+    GL_FRAMEBUFFER_BINDING(0x8CA6),
+    GL_RENDERBUFFER_BINDING(0x8CA7),
+    GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE(0x8CD0),
+    GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME(0x8CD1),
+    GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL(0x8CD2),
+    GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE(0x8CD3),
+    GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET(0x8CD4),
+    GL_FRAMEBUFFER_COMPLETE(0x8CD5),
+    GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT(0x8CD6),
+    GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT(0x8CD7),
+    GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS(0x8CD9),
+    GL_FRAMEBUFFER_INCOMPLETE_FORMATS(0x8CDA),
+    GL_FRAMEBUFFER_UNSUPPORTED(0x8CDD),
+    GL_COLOR_ATTACHMENT0(0x8CE0),
+    GL_DEPTH_ATTACHMENT(0x8D00),
+    GL_STENCIL_ATTACHMENT(0x8D20),
+    GL_FRAMEBUFFER(0x8D40),
+    GL_RENDERBUFFER(0x8D41),
+    GL_RENDERBUFFER_WIDTH(0x8D42),
+    GL_RENDERBUFFER_HEIGHT(0x8D43),
+    GL_RENDERBUFFER_INTERNAL_FORMAT(0x8D44),
+    GL_STENCIL_INDEX1(0x8D46),
+    GL_STENCIL_INDEX4(0x8D47),
+    GL_STENCIL_INDEX8(0x8D48),
+    GL_RENDERBUFFER_RED_SIZE(0x8D50),
+    GL_RENDERBUFFER_GREEN_SIZE(0x8D51),
+    GL_RENDERBUFFER_BLUE_SIZE(0x8D52),
+    GL_RENDERBUFFER_ALPHA_SIZE(0x8D53),
+    GL_RENDERBUFFER_DEPTH_SIZE(0x8D54),
+    GL_RENDERBUFFER_STENCIL_SIZE(0x8D55),
+    GL_TEXTURE_GEN_STR(0x8D60),
+    GL_HALF_FLOAT(0x8D61),
+    GL_RGB565(0x8D62),
+    GL_ETC1_RGB8(0x8D64),
+    GL_TEXTURE_EXTERNAL(0x8D65),
+    GL_SAMPLER_EXTERNAL(0x8D66),
+    GL_TEXTURE_BINDING_EXTERNAL(0x8D67),
+    GL_REQUIRED_TEXTURE_IMAGE_UNITS(0x8D68),
     GL_LOW_FLOAT(0x8DF0),
     GL_MEDIUM_FLOAT(0x8DF1),
     GL_HIGH_FLOAT(0x8DF2),
     GL_LOW_INT(0x8DF3),
     GL_MEDIUM_INT(0x8DF4),
     GL_HIGH_INT(0x8DF5),
-    GL_UNSIGNED_INT_10_10_10_2_OES(0x8DF6),
-    GL_INT_10_10_10_2_OES(0x8DF7),
+    GL_UNSIGNED_INT_10_10_10_2(0x8DF6),
+    GL_INT_10_10_10_2(0x8DF7),
     GL_SHADER_BINARY_FORMATS(0x8DF8),
     GL_NUM_SHADER_BINARY_FORMATS(0x8DF9),
     GL_SHADER_COMPILER(0x8DFA),
diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerShader.java b/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerShader.java
index cf70993..088a2b2 100644
--- a/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerShader.java
+++ b/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerShader.java
@@ -172,7 +172,9 @@
     // void API_ENTRY(glAttachShader)(GLuint program, GLuint shader)
     void glAttachShader(final Message msg) {
         GLProgram program = GetProgram(msg.getArg0());
+        assert program != null;
         GLShader shader = GetShader(msg.getArg1());
+        assert program != null;
         if (GLEnum.GL_VERTEX_SHADER == shader.type)
             program.vert = shader.name;
         else
@@ -229,7 +231,7 @@
             program.frag = 0;
         else
             return;
-        shader.programs.remove(program.name);
+        shader.programs.remove(new Integer(program.name));
         if (shader.delete && shader.programs.size() == 0)
             shaders.remove(shader.name);
     }
@@ -251,7 +253,7 @@
             for (Context ctx : context.shares)
                 if (ctx.serverShader.current == oldCurrent)
                     return;
-            oldCurrent.context.programs.remove(oldCurrent.name);
+            oldCurrent.context.programs.remove(new Integer(oldCurrent.name));
         }
     }
 }
diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerState.java b/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerState.java
index adab930..38868a7 100644
--- a/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerState.java
+++ b/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerState.java
@@ -50,7 +50,7 @@
 
     GLServerState(final Context context) {
         this.context = context;
-        enableDisables = new SparseIntArray(9);
+        enableDisables = new SparseIntArray();
         enableDisables.put(GLEnum.GL_BLEND.value, 0);
         enableDisables.put(GLEnum.GL_DITHER.value, 1);
         enableDisables.put(GLEnum.GL_DEPTH_TEST.value, 0);
@@ -60,6 +60,7 @@
         enableDisables.put(GLEnum.GL_SAMPLE_ALPHA_TO_COVERAGE.value, 0);
         enableDisables.put(GLEnum.GL_POLYGON_OFFSET_FILL.value, 0);
         enableDisables.put(GLEnum.GL_CULL_FACE.value, 0);
+        // enableDisables.put(GLEnum.GL_TEXTURE_2D.value, 1);
 
         lastSetter = new SparseArray<Message>();
         lastSetter.put(Function.glBlendColor.getNumber(), null);
@@ -173,7 +174,11 @@
 
     boolean EnableDisable(boolean enable, final Message msg) {
         int index = enableDisables.indexOfKey(msg.getArg0());
-        assert index >= 0;
+        if (index < 0) {
+            System.out.print("invalid glDisable/Enable: ");
+            System.out.println(MessageFormatter.Format(msg, false));
+            return true;
+        }
         if ((enableDisables.valueAt(index) != 0) == enable)
             return true; // TODO: redundant
         enableDisables.put(msg.getArg0(), enable ? 1 : 0);
diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerTexture.java b/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerTexture.java
index d246e3f..fe3a34c 100644
--- a/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerTexture.java
+++ b/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerTexture.java
@@ -139,12 +139,12 @@
                         if (tex2D != null)
                             return tex2D.ProcessMessage(msg);
                         return true;
-                    case GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES:
-                    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES:
-                    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES:
-                    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES:
-                    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES:
-                    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES:
+                    case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+                    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+                    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+                    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+                    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+                    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
                         if (texCube != null)
                             return texCube.ProcessMessage(msg);
                         return true;
@@ -159,7 +159,7 @@
                     if (tex2D != null && tex2D.name == name)
                         BindTexture(GLEnum.GL_TEXTURE_2D.value, 0);
                     if (texCube != null && texCube.name == name)
-                        BindTexture(GLEnum.GL_TEXTURE_CUBE_MAP_OES.value, 0);
+                        BindTexture(GLEnum.GL_TEXTURE_CUBE_MAP.value, 0);
                     if (name != 0)
                         textures.remove(name);
                 }
@@ -168,7 +168,7 @@
             case glGenerateMipmap:
                 if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_TEXTURE_2D && tex2D != null)
                     return tex2D.ProcessMessage(msg);
-                else if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_TEXTURE_CUBE_MAP_OES
+                else if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_TEXTURE_CUBE_MAP
                         && texCube != null)
                     return texCube.ProcessMessage(msg);
                 return true;
@@ -191,11 +191,11 @@
                         GLEnum.GL_TEXTURE_2D));
             if (index >= 0 && index < tmu2D.length)
                 tmu2D[index] = name;
-        } else if (GLEnum.valueOf(target) == GLEnum.GL_TEXTURE_CUBE_MAP_OES) {
+        } else if (GLEnum.valueOf(target) == GLEnum.GL_TEXTURE_CUBE_MAP) {
             texCube = textures.get(name);
             if (name != 0 && texCube == null)
                 textures.put(name, texCube = new GLTexture(name,
-                        GLEnum.GL_TEXTURE_CUBE_MAP_OES));
+                        GLEnum.GL_TEXTURE_CUBE_MAP));
             if (index >= 0 && index < tmu2D.length)
                 tmu2D[index] = name;
         } else
@@ -207,7 +207,7 @@
         GLTexture tex = null;
         if (GLEnum.valueOf(target) == GLEnum.GL_TEXTURE_2D)
             tex = tex2D;
-        else if (GLEnum.valueOf(target) == GLEnum.GL_TEXTURE_CUBE_MAP_OES)
+        else if (GLEnum.valueOf(target) == GLEnum.GL_TEXTURE_CUBE_MAP)
             tex = texCube;
         if (tex == null)
             return true;
diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerVertex.java b/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerVertex.java
index a9b5ab8..8ee4c22 100644
--- a/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerVertex.java
+++ b/tools/glesv2debugger/src/com/android/glesv2debugger/GLServerVertex.java
@@ -25,6 +25,7 @@
     public final int name;
     public GLEnum usage;
     public GLEnum target;
+    /** in SampleView.targetByteOrder */
     public ByteBuffer data;
 
     public GLBuffer(final int name) {
@@ -81,6 +82,8 @@
     public float defaultAttribs[][];
     int maxAttrib;
 
+    ByteBuffer[] fetchedAttribs;
+
     public GLServerVertex() {
         buffers.append(0, null);
         // TODO: get MAX_VERTEX_ATTRIBS from server
@@ -215,9 +218,11 @@
         if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_ARRAY_BUFFER) {
             attribBuffer.usage = GLEnum.valueOf(msg.getArg3());
             attribBuffer.data = msg.getData().asReadOnlyByteBuffer();
+            attribBuffer.data.order(SampleView.targetByteOrder);
         } else if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_ELEMENT_ARRAY_BUFFER) {
             indexBuffer.usage = GLEnum.valueOf(msg.getArg3());
             indexBuffer.data = msg.getData().asReadOnlyByteBuffer();
+            indexBuffer.data.order(SampleView.targetByteOrder);
         } else
             assert false;
     }
@@ -228,6 +233,7 @@
         if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_ARRAY_BUFFER) {
             if (attribBuffer.data.isReadOnly()) {
                 ByteBuffer buffer = ByteBuffer.allocate(attribBuffer.data.capacity());
+                buffer.order(SampleView.targetByteOrder);
                 buffer.put(attribBuffer.data);
                 attribBuffer.data = buffer;
             }
@@ -236,6 +242,7 @@
         } else if (GLEnum.valueOf(msg.getArg0()) == GLEnum.GL_ELEMENT_ARRAY_BUFFER) {
             if (indexBuffer.data.isReadOnly()) {
                 ByteBuffer buffer = ByteBuffer.allocate(indexBuffer.data.capacity());
+                buffer.order(SampleView.targetByteOrder);
                 buffer.put(indexBuffer.data);
                 indexBuffer.data = buffer;
             }
@@ -268,7 +275,8 @@
 
     // void glDisableVertexAttribArray(GLuint index)
     public void glDisableVertexAttribArray(Message msg) {
-        attribPointers[msg.getArg0()].enabled = false;
+        if (msg.getArg0() >= 0 && msg.getArg0() < attribPointers.length)
+            attribPointers[msg.getArg0()].enabled = false;
     }
 
     float FetchConvert(final ByteBuffer src, final GLEnum type, final boolean normalized) {
@@ -314,19 +322,49 @@
         return 0;
     }
 
+    static int TypeSize(final GLEnum type) {
+        switch (type) {
+            case GL_FLOAT:
+            case GL_UNSIGNED_INT:
+            case GL_INT:
+            case GL_FIXED:
+                return 4;
+            case GL_UNSIGNED_SHORT:
+            case GL_SHORT:
+                return 2;
+            case GL_UNSIGNED_BYTE:
+            case GL_BYTE:
+                return 1;
+            default:
+                assert false;
+                return 0;
+        }
+    }
+
     void Fetch(int index, final ByteBuffer nonVBO, final ByteBuffer dst) {
         for (int i = 0; i < maxAttrib; i++) {
             final GLAttribPointer attrib = attribPointers[i];
             int size = 0;
-            if (attrib.enabled)
+            if (attrib.enabled) {
                 size = attrib.size;
-            if (null != attrib.buffer) {
-                final ByteBuffer src = attrib.buffer.data;
-                src.position(attrib.ptr + i * attrib.stride);
-                dst.putFloat(FetchConvert(src, attrib.type, attrib.normalized));
-            } else
-                for (int j = 0; j < size; j++)
-                    dst.putFloat(FetchConvert(nonVBO, attrib.type, attrib.normalized));
+                final ByteBuffer fetched = fetchedAttribs[i];
+                final byte[] element = new byte[TypeSize(attrib.type) * size];
+                if (null != attrib.buffer) {
+                    final ByteBuffer src = attrib.buffer.data;
+                    src.position(attrib.ptr + index * attrib.stride);
+                    src.get(element);
+                    src.position(attrib.ptr + index * attrib.stride);
+                    for (int j = 0; j < size; j++)
+                        dst.putFloat(FetchConvert(src, attrib.type, attrib.normalized));
+                } else {
+                    final int position = nonVBO.position();
+                    nonVBO.get(element);
+                    nonVBO.position(position);
+                    for (int j = 0; j < size; j++)
+                        dst.putFloat(FetchConvert(nonVBO, attrib.type, attrib.normalized));
+                }
+                fetched.put(element);
+            }
             if (size < 1)
                 dst.putFloat(defaultAttribs[i][0]);
             if (size < 2)
@@ -341,6 +379,13 @@
     // void glDrawArrays(GLenum mode, GLint first, GLsizei count)
     public Message glDrawArrays(Message msg) {
         maxAttrib = msg.getArg7();
+        fetchedAttribs = new ByteBuffer[maxAttrib];
+        for (int i = 0; i < maxAttrib; i++) {
+            if (!attribPointers[i].enabled)
+                continue;
+            fetchedAttribs[i] = ByteBuffer.allocate(TypeSize(attribPointers[i].type)
+                    * attribPointers[i].size * msg.getArg2());
+        }
         final int first = msg.getArg1(), count = msg.getArg2();
         final ByteBuffer buffer = ByteBuffer.allocate(4 * 4 * maxAttrib * count);
         ByteBuffer arrays = null;
@@ -352,6 +397,11 @@
         for (int i = first; i < first + count; i++)
             Fetch(i, arrays, buffer);
         assert null == arrays || arrays.remaining() == 0;
+        for (int i = 0; i < maxAttrib; i++) {
+            if (!attribPointers[i].enabled)
+                continue;
+            assert fetchedAttribs[i].remaining() == 0;
+        }
         buffer.rewind();
         return msg.toBuilder().setData(com.google.protobuf.ByteString.copyFrom(buffer))
                 .setArg8(GLEnum.GL_FLOAT.value).build();
@@ -361,6 +411,13 @@
     // GLvoid* indices)
     public Message glDrawElements(Message msg) {
         maxAttrib = msg.getArg7();
+        fetchedAttribs = new ByteBuffer[maxAttrib];
+        for (int i = 0; i < maxAttrib; i++) {
+            if (!attribPointers[i].enabled)
+                continue;
+            fetchedAttribs[i] = ByteBuffer.allocate(TypeSize(attribPointers[i].type)
+                    * attribPointers[i].size * msg.getArg1());
+        }
         final int count = msg.getArg1();
         final GLEnum type = GLEnum.valueOf(msg.getArg2());
         final ByteBuffer buffer = ByteBuffer.allocate(4 * 4 * maxAttrib * count);
@@ -386,6 +443,11 @@
         else
             assert false;
         assert null == arrays || arrays.remaining() == 0;
+        for (int i = 0; i < maxAttrib; i++) {
+            if (!attribPointers[i].enabled)
+                continue;
+            assert fetchedAttribs[i].remaining() == 0;
+        }
         buffer.rewind();
         return msg.toBuilder().setData(com.google.protobuf.ByteString.copyFrom(buffer))
                 .setArg8(GLEnum.GL_FLOAT.value).build();
@@ -393,7 +455,8 @@
 
     // void glEnableVertexAttribArray(GLuint index)
     public void glEnableVertexAttribArray(Message msg) {
-        attribPointers[msg.getArg0()].enabled = true;
+        if (msg.getArg0() >= 0 && msg.getArg0() < attribPointers.length)
+            attribPointers[msg.getArg0()].enabled = true;
     }
 
     // void API_ENTRY(glGenBuffers)(GLsizei n, GLuint:n:out buffers)
@@ -418,7 +481,7 @@
         attrib.normalized = msg.getArg3() != 0;
         attrib.stride = msg.getArg4();
         if (0 == attrib.stride)
-            attrib.stride = attrib.size * 4;
+            attrib.stride = attrib.size * TypeSize(attrib.type);
         attrib.ptr = msg.getArg5();
         attrib.buffer = attribBuffer;
     }
diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/MessageData.java b/tools/glesv2debugger/src/com/android/glesv2debugger/MessageData.java
index 13965d3..d118f6b 100644
--- a/tools/glesv2debugger/src/com/android/glesv2debugger/MessageData.java
+++ b/tools/glesv2debugger/src/com/android/glesv2debugger/MessageData.java
@@ -25,6 +25,8 @@
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.graphics.ImageData;
 
+import java.nio.ByteBuffer;
+
 public class MessageData {
     public final Message msg, oriMsg;
     public Image image; // texture
@@ -36,6 +38,8 @@
     public GLEnum dataType; // could be float, int; mainly for formatting use
     Context context; // the context before this call
 
+    ByteBuffer[] attribs = null;
+
     public MessageData(final Device device, final Message msg, final Message oriMsg,
             final Context context) {
         this.msg = msg;
@@ -67,7 +71,7 @@
             columns[2] = "[AfterGeneratedCall] ";
         else
             assert msg.getType() == Type.AfterCall;
-        columns[2] += MessageFormatter.Format(msg);
+        columns[2] += MessageFormatter.Format(msg, false);
         builder.append(columns[2]);
         switch (function) {
             case glDrawArrays: // msg was modified by GLServerVertex
diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/MessageFormatter.java b/tools/glesv2debugger/src/com/android/glesv2debugger/MessageFormatter.java
index c674dc0..115cb99 100644
--- a/tools/glesv2debugger/src/com/android/glesv2debugger/MessageFormatter.java
+++ b/tools/glesv2debugger/src/com/android/glesv2debugger/MessageFormatter.java
@@ -24,378 +24,1462 @@
 
     static String FormatFloats(int count, final ByteBuffer data) {
         if (data.remaining() == 0)
-            return "[null]";
+            return "{}";
         data.order(SampleView.targetByteOrder);
-        String ret = "[";
+        String ret = "{";
         for (int i = 0; i < count; i++) {
             ret += Float.intBitsToFloat(data.getInt());
             if (i < count - 1)
                 ret += ", ";
         }
-        return ret + "]";
+        return ret + "}";
     }
-    
+
     static String FormatInts(int count, final ByteBuffer data) {
         if (data.remaining() == 0)
-            return "[null]";
+            return "{}";
         data.order(SampleView.targetByteOrder);
-        String ret = "[";
+        String ret = "{";
         for (int i = 0; i < count; i++) {
             ret += data.getInt();
             if (i < count - 1)
                 ret += ", ";
         }
-        return ret + "]";
+        return ret + "}";
     }
-    
+
     static String FormatUints(int count, final ByteBuffer data) {
         if (data.remaining() == 0)
-            return "[null]";
+            return "{}";
         data.order(SampleView.targetByteOrder);
-        String ret = "[";
+        String ret = "{";
         for (int i = 0; i < count; i++) {
             long bits = data.getInt() & 0xffffffff;
             ret += bits;
             if (i < count - 1)
                 ret += ", ";
         }
-        return ret + "]";
-    }
-    
-    static String FormatMatrix(int columns, int count, final ByteBuffer data) {
-        if (data.remaining() == 0)
-            return "[null]";
-        data.order(SampleView.targetByteOrder);
-        String ret = "[";
-        for (int i = 0; i < count; i++) {
-            ret += Float.intBitsToFloat(data.getInt());
-            if (i % columns == columns - 1)
-                ret += "\n                                             ";
-            else if (i < count - 1)
-                ret += ", ";
-        }
-        return ret + "]";
+        return ret + "}";
     }
 
-    public static String Format(final DebuggerMessage.Message msg) {
+    static String FormatMatrix(int columns, int count, final ByteBuffer data) {
+        if (data.remaining() == 0)
+            return "{}";
+        data.order(SampleView.targetByteOrder);
+        String ret = "{";
+        for (int i = 0; i < count; i++) {
+            ret += Float.intBitsToFloat(data.getInt());
+            if (i < count - 1)
+                ret += ", ";
+            if (i % columns == columns - 1)
+                ret += "\n                                             ";
+        }
+        return ret + "}";
+    }
+
+    public static String Format(final DebuggerMessage.Message msg,
+                                final boolean code) {
         String str;
         switch (msg.getFunction()) {
             case glActiveTexture:
-                str = String.format("%s (texture=%s)", "void", GLEnum.valueOf(msg.getArg0())); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glActiveTexture" : "void")
+                    , (code ? "/*texture*/ " : "texture=")
+                    , GLEnum.valueOf(msg.getArg0()));
+                break;
             case glAttachShader:
-                str = String.format("%s (program=%s, shader=%s)", "void", msg.getArg0(), msg.getArg1()); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glAttachShader" : "void")
+                    , (code ? "/*program*/ " : "program=")
+                    , (code ? "program_" : "") + msg.getArg0()
+                    , (code ? "/*shader*/ " : "shader=")
+                    , (code ? "shader_" : "") + msg.getArg1());
+                break;
             case glBindAttribLocation:
-                str = String.format("%s (program=%s, index=%s, name=%s)", "void", msg.getArg0(), msg.getArg1(), msg.getData().toStringUtf8()); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glBindAttribLocation" : "void")
+                    , (code ? "/*program*/ " : "program=")
+                    , (code ? "program_" : "") + msg.getArg0()
+                    , (code ? "/*index*/ " : "index=")
+                    , msg.getArg1()
+                    , (code ? "/*name*/ " : "name=")
+                    , (code ? "\"" : "") + msg.getData().toStringUtf8() + (code ? "\"" : ""));
+                break;
             case glBindBuffer:
-                str = String.format("%s (target=%s, buffer=%s)", "void", GLEnum.valueOf(msg.getArg0()), msg.getArg1()); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glBindBuffer" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*buffer*/ " : "buffer=")
+                    , (code ? "buffer_" : "") + msg.getArg1());
+                break;
             case glBindFramebuffer:
-                str = String.format("%s (target=%s, framebuffer=%s)", "void", GLEnum.valueOf(msg.getArg0()), msg.getArg1()); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glBindFramebuffer" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*framebuffer*/ " : "framebuffer=")
+                    , (code ? "framebuffer_" : "") + msg.getArg1());
+                break;
             case glBindRenderbuffer:
-                str = String.format("%s (target=%s, renderbuffer=%s)", "void", GLEnum.valueOf(msg.getArg0()), msg.getArg1()); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glBindRenderbuffer" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*renderbuffer*/ " : "renderbuffer=")
+                    , (code ? "renderbuffer_" : "") + msg.getArg1());
+                break;
             case glBindTexture:
-                str = String.format("%s (target=%s, texture=%s)", "void", GLEnum.valueOf(msg.getArg0()), msg.getArg1()); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glBindTexture" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*texture*/ " : "texture=")
+                    , (code ? "texture_" : "") + msg.getArg1());
+                break;
             case glBlendColor:
-                str = String.format("%s (red=%s, green=%s, blue=%s, alpha=%s)", "void", Float.intBitsToFloat(msg.getArg0()), Float.intBitsToFloat(msg.getArg1()), Float.intBitsToFloat(msg.getArg2()), Float.intBitsToFloat(msg.getArg3())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glBlendColor" : "void")
+                    , (code ? "/*red*/ " : "red=")
+                    , Float.intBitsToFloat(msg.getArg0())
+                    , (code ? "/*green*/ " : "green=")
+                    , Float.intBitsToFloat(msg.getArg1())
+                    , (code ? "/*blue*/ " : "blue=")
+                    , Float.intBitsToFloat(msg.getArg2())
+                    , (code ? "/*alpha*/ " : "alpha=")
+                    , Float.intBitsToFloat(msg.getArg3()));
+                break;
             case glBlendEquation:
-                str = String.format("%s (mode=%s)", "void", GLEnum.valueOf(msg.getArg0())); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glBlendEquation" : "void")
+                    , (code ? "/*mode*/ " : "mode=")
+                    , GLEnum.valueOf(msg.getArg0()));
+                break;
             case glBlendEquationSeparate:
-                str = String.format("%s (modeRGB=%s, modeAlpha=%s)", "void", GLEnum.valueOf(msg.getArg0()), GLEnum.valueOf(msg.getArg1())); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glBlendEquationSeparate" : "void")
+                    , (code ? "/*modeRGB*/ " : "modeRGB=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*modeAlpha*/ " : "modeAlpha=")
+                    , GLEnum.valueOf(msg.getArg1()));
+                break;
             case glBlendFunc:
-                str = String.format("%s (sfactor=%s, dfactor=%s)", "void", GLEnum.valueOf(msg.getArg0()), GLEnum.valueOf(msg.getArg1())); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glBlendFunc" : "void")
+                    , (code ? "/*sfactor*/ " : "sfactor=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*dfactor*/ " : "dfactor=")
+                    , GLEnum.valueOf(msg.getArg1()));
+                break;
             case glBlendFuncSeparate:
-                str = String.format("%s (srcRGB=%s, dstRGB=%s, srcAlpha=%s, dstAlpha=%s)", "void", GLEnum.valueOf(msg.getArg0()), GLEnum.valueOf(msg.getArg1()), GLEnum.valueOf(msg.getArg2()), GLEnum.valueOf(msg.getArg3())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glBlendFuncSeparate" : "void")
+                    , (code ? "/*srcRGB*/ " : "srcRGB=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*dstRGB*/ " : "dstRGB=")
+                    , GLEnum.valueOf(msg.getArg1())
+                    , (code ? "/*srcAlpha*/ " : "srcAlpha=")
+                    , GLEnum.valueOf(msg.getArg2())
+                    , (code ? "/*dstAlpha*/ " : "dstAlpha=")
+                    , GLEnum.valueOf(msg.getArg3()));
+                break;
             case glBufferData:
-                str = String.format("%s (target=%s, size=%s, data=%s, usage=%s)", "void", GLEnum.valueOf(msg.getArg0()), msg.getArg1(), "0x" + Integer.toHexString(msg.getArg2()), GLEnum.valueOf(msg.getArg3())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glBufferData" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*size*/ " : "size=")
+                    , msg.getArg1()
+                    , (code ? "/*data*/ " : "data=")
+                    , (code ? "arg2" : "0x" + Integer.toHexString(msg.getArg2()))
+                    , (code ? "/*usage*/ " : "usage=")
+                    , GLEnum.valueOf(msg.getArg3()));
+                break;
             case glBufferSubData:
-                str = String.format("%s (target=%s, offset=%s, size=%s, data=%s)", "void", GLEnum.valueOf(msg.getArg0()), msg.getArg1(), msg.getArg2(), "0x" + Integer.toHexString(msg.getArg3())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glBufferSubData" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*offset*/ " : "offset=")
+                    , msg.getArg1()
+                    , (code ? "/*size*/ " : "size=")
+                    , msg.getArg2()
+                    , (code ? "/*data*/ " : "data=")
+                    , (code ? "arg3" : "0x" + Integer.toHexString(msg.getArg3())));
+                break;
             case glCheckFramebufferStatus:
-                str = String.format("%s (target=%s)", GLEnum.valueOf(msg.getRet()), GLEnum.valueOf(msg.getArg0())); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glCheckFramebufferStatus" : GLEnum.valueOf(msg.getRet()))
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0()));
+                break;
             case glClear:
-                str = String.format("%s (mask=%s)", "void", msg.getArg0()); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glClear" : "void")
+                    , (code ? "/*mask*/ " : "mask=")
+                    , msg.getArg0());
+                break;
             case glClearColor:
-                str = String.format("%s (red=%s, green=%s, blue=%s, alpha=%s)", "void", Float.intBitsToFloat(msg.getArg0()), Float.intBitsToFloat(msg.getArg1()), Float.intBitsToFloat(msg.getArg2()), Float.intBitsToFloat(msg.getArg3())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glClearColor" : "void")
+                    , (code ? "/*red*/ " : "red=")
+                    , Float.intBitsToFloat(msg.getArg0())
+                    , (code ? "/*green*/ " : "green=")
+                    , Float.intBitsToFloat(msg.getArg1())
+                    , (code ? "/*blue*/ " : "blue=")
+                    , Float.intBitsToFloat(msg.getArg2())
+                    , (code ? "/*alpha*/ " : "alpha=")
+                    , Float.intBitsToFloat(msg.getArg3()));
+                break;
             case glClearDepthf:
-                str = String.format("%s (depth=%s)", "void", Float.intBitsToFloat(msg.getArg0())); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glClearDepthf" : "void")
+                    , (code ? "/*depth*/ " : "depth=")
+                    , Float.intBitsToFloat(msg.getArg0()));
+                break;
             case glClearStencil:
-                str = String.format("%s (s=%s)", "void", msg.getArg0()); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glClearStencil" : "void")
+                    , (code ? "/*s*/ " : "s=")
+                    , msg.getArg0());
+                break;
             case glColorMask:
-                str = String.format("%s (red=%s, green=%s, blue=%s, alpha=%s)", "void", msg.getArg0(), msg.getArg1(), msg.getArg2(), msg.getArg3()); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glColorMask" : "void")
+                    , (code ? "/*red*/ " : "red=")
+                    , msg.getArg0()
+                    , (code ? "/*green*/ " : "green=")
+                    , msg.getArg1()
+                    , (code ? "/*blue*/ " : "blue=")
+                    , msg.getArg2()
+                    , (code ? "/*alpha*/ " : "alpha=")
+                    , msg.getArg3());
+                break;
             case glCompileShader:
-                str = String.format("%s (shader=%s)", "void", msg.getArg0()); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glCompileShader" : "void")
+                    , (code ? "/*shader*/ " : "shader=")
+                    , (code ? "shader_" : "") + msg.getArg0());
+                break;
             case glCompressedTexImage2D:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (target=%s, level=%s, internalformat=%s, width=%s, height=%s, border=%s, imageSize=%s, data=%s)", "void", GLEnum.valueOf(msg.getArg0()), msg.getArg1(), GLEnum.valueOf(msg.getArg2()), msg.getArg3(), msg.getArg4(), msg.getArg5(), msg.getArg6(), "0x" + Integer.toHexString(msg.getArg7())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s, %s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glCompressedTexImage2D" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*level*/ " : "level=")
+                    , msg.getArg1()
+                    , (code ? "/*internalformat*/ " : "internalformat=")
+                    , GLEnum.valueOf(msg.getArg2())
+                    , (code ? "/*width*/ " : "width=")
+                    , msg.getArg3()
+                    , (code ? "/*height*/ " : "height=")
+                    , msg.getArg4()
+                    , (code ? "/*border*/ " : "border=")
+                    , msg.getArg5()
+                    , (code ? "/*imageSize*/ " : "imageSize=")
+                    , msg.getArg6()
+                    , (code ? "/*data*/ " : "data=")
+                    , (code ? "arg7" : "0x" + Integer.toHexString(msg.getArg7())));
+                break;
             case glCompressedTexSubImage2D:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (target=%s, level=%s, xoffset=%s, yoffset=%s, width=%s, height=%s, format=%s, imageSize=%s, data=%s)", "void", GLEnum.valueOf(msg.getArg0()), msg.getArg1(), msg.getArg2(), msg.getArg3(), msg.getArg4(), msg.getArg5(), GLEnum.valueOf(msg.getArg6()), msg.getArg7(), "0x" + Integer.toHexString(msg.getArg8())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s, %s%s, %s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glCompressedTexSubImage2D" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*level*/ " : "level=")
+                    , msg.getArg1()
+                    , (code ? "/*xoffset*/ " : "xoffset=")
+                    , msg.getArg2()
+                    , (code ? "/*yoffset*/ " : "yoffset=")
+                    , msg.getArg3()
+                    , (code ? "/*width*/ " : "width=")
+                    , msg.getArg4()
+                    , (code ? "/*height*/ " : "height=")
+                    , msg.getArg5()
+                    , (code ? "/*format*/ " : "format=")
+                    , GLEnum.valueOf(msg.getArg6())
+                    , (code ? "/*imageSize*/ " : "imageSize=")
+                    , msg.getArg7()
+                    , (code ? "/*data*/ " : "data=")
+                    , (code ? "arg8" : "0x" + Integer.toHexString(msg.getArg8())));
+                break;
             case glCopyTexImage2D:
-                str = String.format("%s (target=%s, level=%s, internalformat=%s, x=%s, y=%s, width=%s, height=%s, border=%s)", "void", GLEnum.valueOf(msg.getArg0()), msg.getArg1(), GLEnum.valueOf(msg.getArg2()), msg.getArg3(), msg.getArg4(), msg.getArg5(), msg.getArg6(), msg.getArg7()); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s, %s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glCopyTexImage2D" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*level*/ " : "level=")
+                    , msg.getArg1()
+                    , (code ? "/*internalformat*/ " : "internalformat=")
+                    , GLEnum.valueOf(msg.getArg2())
+                    , (code ? "/*x*/ " : "x=")
+                    , msg.getArg3()
+                    , (code ? "/*y*/ " : "y=")
+                    , msg.getArg4()
+                    , (code ? "/*width*/ " : "width=")
+                    , msg.getArg5()
+                    , (code ? "/*height*/ " : "height=")
+                    , msg.getArg6()
+                    , (code ? "/*border*/ " : "border=")
+                    , msg.getArg7());
+                break;
             case glCopyTexSubImage2D:
-                str = String.format("%s (target=%s, level=%s, xoffset=%s, yoffset=%s, x=%s, y=%s, width=%s, height=%s)", "void", GLEnum.valueOf(msg.getArg0()), msg.getArg1(), msg.getArg2(), msg.getArg3(), msg.getArg4(), msg.getArg5(), msg.getArg6(), msg.getArg7()); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s, %s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glCopyTexSubImage2D" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*level*/ " : "level=")
+                    , msg.getArg1()
+                    , (code ? "/*xoffset*/ " : "xoffset=")
+                    , msg.getArg2()
+                    , (code ? "/*yoffset*/ " : "yoffset=")
+                    , msg.getArg3()
+                    , (code ? "/*x*/ " : "x=")
+                    , msg.getArg4()
+                    , (code ? "/*y*/ " : "y=")
+                    , msg.getArg5()
+                    , (code ? "/*width*/ " : "width=")
+                    , msg.getArg6()
+                    , (code ? "/*height*/ " : "height=")
+                    , msg.getArg7());
+                break;
             case glCreateProgram:
-                str = String.format("%s ()", msg.getRet()); break;
+                str = String.format("%s()",
+                    (code ? "glCreateProgram" : msg.getRet())
+);
+                break;
             case glCreateShader:
-                str = String.format("%s (type=%s)", msg.getRet(), GLEnum.valueOf(msg.getArg0())); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glCreateShader" : msg.getRet())
+                    , (code ? "/*type*/ " : "type=")
+                    , GLEnum.valueOf(msg.getArg0()));
+                break;
             case glCullFace:
-                str = String.format("%s (mode=%s)", "void", GLEnum.valueOf(msg.getArg0())); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glCullFace" : "void")
+                    , (code ? "/*mode*/ " : "mode=")
+                    , GLEnum.valueOf(msg.getArg0()));
+                break;
             case glDeleteBuffers:
-                str = String.format("%s (n=%s, buffers=%s)", "void", msg.getArg0(), FormatUints(1 * msg.getArg0(), msg.getData().asReadOnlyByteBuffer())); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glDeleteBuffers" : "void")
+                    , (code ? "/*n*/ " : "n=")
+                    , msg.getArg0()
+                    , (code ? "/*buffers*/ " : "buffers=")
+                    , (code ? "(GLuint [])" : "") +  FormatUints(1 * msg.getArg0(), msg.getData().asReadOnlyByteBuffer()));
+                break;
             case glDeleteFramebuffers:
-                str = String.format("%s (n=%s, framebuffers=%s)", "void", msg.getArg0(), FormatUints(1 * msg.getArg0(), msg.getData().asReadOnlyByteBuffer())); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glDeleteFramebuffers" : "void")
+                    , (code ? "/*n*/ " : "n=")
+                    , msg.getArg0()
+                    , (code ? "/*framebuffers*/ " : "framebuffers=")
+                    , (code ? "(GLuint [])" : "") +  FormatUints(1 * msg.getArg0(), msg.getData().asReadOnlyByteBuffer()));
+                break;
             case glDeleteProgram:
-                str = String.format("%s (program=%s)", "void", msg.getArg0()); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glDeleteProgram" : "void")
+                    , (code ? "/*program*/ " : "program=")
+                    , (code ? "program_" : "") + msg.getArg0());
+                break;
             case glDeleteRenderbuffers:
-                str = String.format("%s (n=%s, renderbuffers=%s)", "void", msg.getArg0(), FormatUints(1 * msg.getArg0(), msg.getData().asReadOnlyByteBuffer())); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glDeleteRenderbuffers" : "void")
+                    , (code ? "/*n*/ " : "n=")
+                    , msg.getArg0()
+                    , (code ? "/*renderbuffers*/ " : "renderbuffers=")
+                    , (code ? "(GLuint [])" : "") +  FormatUints(1 * msg.getArg0(), msg.getData().asReadOnlyByteBuffer()));
+                break;
             case glDeleteShader:
-                str = String.format("%s (shader=%s)", "void", msg.getArg0()); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glDeleteShader" : "void")
+                    , (code ? "/*shader*/ " : "shader=")
+                    , (code ? "shader_" : "") + msg.getArg0());
+                break;
             case glDeleteTextures:
-                str = String.format("%s (n=%s, textures=%s)", "void", msg.getArg0(), FormatUints(1 * msg.getArg0(), msg.getData().asReadOnlyByteBuffer())); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glDeleteTextures" : "void")
+                    , (code ? "/*n*/ " : "n=")
+                    , msg.getArg0()
+                    , (code ? "/*textures*/ " : "textures=")
+                    , (code ? "(GLuint [])" : "") +  FormatUints(1 * msg.getArg0(), msg.getData().asReadOnlyByteBuffer()));
+                break;
             case glDepthFunc:
-                str = String.format("%s (func=%s)", "void", GLEnum.valueOf(msg.getArg0())); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glDepthFunc" : "void")
+                    , (code ? "/*func*/ " : "func=")
+                    , GLEnum.valueOf(msg.getArg0()));
+                break;
             case glDepthMask:
-                str = String.format("%s (flag=%s)", "void", msg.getArg0()); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glDepthMask" : "void")
+                    , (code ? "/*flag*/ " : "flag=")
+                    , msg.getArg0());
+                break;
             case glDepthRangef:
-                str = String.format("%s (zNear=%s, zFar=%s)", "void", Float.intBitsToFloat(msg.getArg0()), Float.intBitsToFloat(msg.getArg1())); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glDepthRangef" : "void")
+                    , (code ? "/*zNear*/ " : "zNear=")
+                    , Float.intBitsToFloat(msg.getArg0())
+                    , (code ? "/*zFar*/ " : "zFar=")
+                    , Float.intBitsToFloat(msg.getArg1()));
+                break;
             case glDetachShader:
-                str = String.format("%s (program=%s, shader=%s)", "void", msg.getArg0(), msg.getArg1()); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glDetachShader" : "void")
+                    , (code ? "/*program*/ " : "program=")
+                    , (code ? "program_" : "") + msg.getArg0()
+                    , (code ? "/*shader*/ " : "shader=")
+                    , (code ? "shader_" : "") + msg.getArg1());
+                break;
             case glDisable:
-                str = String.format("%s (cap=%s)", "void", GLEnum.valueOf(msg.getArg0())); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glDisable" : "void")
+                    , (code ? "/*cap*/ " : "cap=")
+                    , GLEnum.valueOf(msg.getArg0()));
+                break;
             case glDisableVertexAttribArray:
-                str = String.format("%s (index=%s)", "void", msg.getArg0()); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glDisableVertexAttribArray" : "void")
+                    , (code ? "/*index*/ " : "index=")
+                    , msg.getArg0());
+                break;
             case glDrawArrays:
-                str = String.format("%s (mode=%s, first=%s, count=%s)", "void", GLEnum.valueOf(msg.getArg0()), msg.getArg1(), msg.getArg2()); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glDrawArrays" : "void")
+                    , (code ? "/*mode*/ " : "mode=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*first*/ " : "first=")
+                    , msg.getArg1()
+                    , (code ? "/*count*/ " : "count=")
+                    , msg.getArg2());
+                break;
             case glDrawElements:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (mode=%s, count=%s, type=%s, indices=%s)", "void", GLEnum.valueOf(msg.getArg0()), msg.getArg1(), GLEnum.valueOf(msg.getArg2()), "0x" + Integer.toHexString(msg.getArg3())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glDrawElements" : "void")
+                    , (code ? "/*mode*/ " : "mode=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*count*/ " : "count=")
+                    , msg.getArg1()
+                    , (code ? "/*type*/ " : "type=")
+                    , GLEnum.valueOf(msg.getArg2())
+                    , (code ? "/*indices*/ " : "indices=")
+                    , (code ? "arg3" : "0x" + Integer.toHexString(msg.getArg3())));
+                break;
             case glEnable:
-                str = String.format("%s (cap=%s)", "void", GLEnum.valueOf(msg.getArg0())); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glEnable" : "void")
+                    , (code ? "/*cap*/ " : "cap=")
+                    , GLEnum.valueOf(msg.getArg0()));
+                break;
             case glEnableVertexAttribArray:
-                str = String.format("%s (index=%s)", "void", msg.getArg0()); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glEnableVertexAttribArray" : "void")
+                    , (code ? "/*index*/ " : "index=")
+                    , msg.getArg0());
+                break;
             case glFinish:
-                str = String.format("%s ()", "void"); break;
+                str = String.format("%s()",
+                    (code ? "glFinish" : "void")
+);
+                break;
             case glFlush:
-                str = String.format("%s ()", "void"); break;
+                str = String.format("%s()",
+                    (code ? "glFlush" : "void")
+);
+                break;
             case glFramebufferRenderbuffer:
-                str = String.format("%s (target=%s, attachment=%s, renderbuffertarget=%s, renderbuffer=%s)", "void", GLEnum.valueOf(msg.getArg0()), GLEnum.valueOf(msg.getArg1()), GLEnum.valueOf(msg.getArg2()), msg.getArg3()); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glFramebufferRenderbuffer" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*attachment*/ " : "attachment=")
+                    , GLEnum.valueOf(msg.getArg1())
+                    , (code ? "/*renderbuffertarget*/ " : "renderbuffertarget=")
+                    , GLEnum.valueOf(msg.getArg2())
+                    , (code ? "/*renderbuffer*/ " : "renderbuffer=")
+                    , (code ? "renderbuffer_" : "") + msg.getArg3());
+                break;
             case glFramebufferTexture2D:
-                str = String.format("%s (target=%s, attachment=%s, textarget=%s, texture=%s, level=%s)", "void", GLEnum.valueOf(msg.getArg0()), GLEnum.valueOf(msg.getArg1()), GLEnum.valueOf(msg.getArg2()), msg.getArg3(), msg.getArg4()); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glFramebufferTexture2D" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*attachment*/ " : "attachment=")
+                    , GLEnum.valueOf(msg.getArg1())
+                    , (code ? "/*textarget*/ " : "textarget=")
+                    , GLEnum.valueOf(msg.getArg2())
+                    , (code ? "/*texture*/ " : "texture=")
+                    , (code ? "texture_" : "") + msg.getArg3()
+                    , (code ? "/*level*/ " : "level=")
+                    , msg.getArg4());
+                break;
             case glFrontFace:
-                str = String.format("%s (mode=%s)", "void", GLEnum.valueOf(msg.getArg0())); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glFrontFace" : "void")
+                    , (code ? "/*mode*/ " : "mode=")
+                    , GLEnum.valueOf(msg.getArg0()));
+                break;
             case glGenBuffers:
-                str = String.format("%s (n=%s, buffers=%s)", "void", msg.getArg0(), FormatUints(1 * msg.getArg0(), msg.getData().asReadOnlyByteBuffer())); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glGenBuffers" : "void")
+                    , (code ? "/*n*/ " : "n=")
+                    , msg.getArg0()
+                    , (code ? "/*buffers*/ " : "buffers=")
+                    , (code ? "(GLuint [])" : "") +  FormatUints(1 * msg.getArg0(), msg.getData().asReadOnlyByteBuffer()));
+                break;
             case glGenerateMipmap:
-                str = String.format("%s (target=%s)", "void", GLEnum.valueOf(msg.getArg0())); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glGenerateMipmap" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0()));
+                break;
             case glGenFramebuffers:
-                str = String.format("%s (n=%s, framebuffers=%s)", "void", msg.getArg0(), FormatUints(1 * msg.getArg0(), msg.getData().asReadOnlyByteBuffer())); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glGenFramebuffers" : "void")
+                    , (code ? "/*n*/ " : "n=")
+                    , msg.getArg0()
+                    , (code ? "/*framebuffers*/ " : "framebuffers=")
+                    , (code ? "(GLuint [])" : "") +  FormatUints(1 * msg.getArg0(), msg.getData().asReadOnlyByteBuffer()));
+                break;
             case glGenRenderbuffers:
-                str = String.format("%s (n=%s, renderbuffers=%s)", "void", msg.getArg0(), FormatUints(1 * msg.getArg0(), msg.getData().asReadOnlyByteBuffer())); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glGenRenderbuffers" : "void")
+                    , (code ? "/*n*/ " : "n=")
+                    , msg.getArg0()
+                    , (code ? "/*renderbuffers*/ " : "renderbuffers=")
+                    , (code ? "(GLuint [])" : "") +  FormatUints(1 * msg.getArg0(), msg.getData().asReadOnlyByteBuffer()));
+                break;
             case glGenTextures:
-                str = String.format("%s (n=%s, textures=%s)", "void", msg.getArg0(), FormatUints(1 * msg.getArg0(), msg.getData().asReadOnlyByteBuffer())); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glGenTextures" : "void")
+                    , (code ? "/*n*/ " : "n=")
+                    , msg.getArg0()
+                    , (code ? "/*textures*/ " : "textures=")
+                    , (code ? "(GLuint [])" : "") +  FormatUints(1 * msg.getArg0(), msg.getData().asReadOnlyByteBuffer()));
+                break;
             case glGetActiveAttrib:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (program=%s, index=%s, bufsize=%s, length=%s, size=%s, type=%s, name=%s)", "void", msg.getArg0(), msg.getArg1(), msg.getArg2(), "0x" + Integer.toHexString(msg.getArg3()), "0x" + Integer.toHexString(msg.getArg4()), "0x" + Integer.toHexString(msg.getArg5()), msg.getData().toStringUtf8()); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glGetActiveAttrib" : "void")
+                    , (code ? "/*program*/ " : "program=")
+                    , (code ? "program_" : "") + msg.getArg0()
+                    , (code ? "/*index*/ " : "index=")
+                    , msg.getArg1()
+                    , (code ? "/*bufsize*/ " : "bufsize=")
+                    , msg.getArg2()
+                    , (code ? "/*length*/ " : "length=")
+                    , (code ? "arg3" : "0x" + Integer.toHexString(msg.getArg3()))
+                    , (code ? "/*size*/ " : "size=")
+                    , (code ? "arg4" : "0x" + Integer.toHexString(msg.getArg4()))
+                    , (code ? "/*type*/ " : "type=")
+                    , (code ? "arg5" : "0x" + Integer.toHexString(msg.getArg5()))
+                    , (code ? "/*name*/ " : "name=")
+                    , (code ? "\"" : "") + msg.getData().toStringUtf8() + (code ? "\"" : ""));
+                break;
             case glGetActiveUniform:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (program=%s, index=%s, bufsize=%s, length=%s, size=%s, type=%s, name=%s)", "void", msg.getArg0(), msg.getArg1(), msg.getArg2(), "0x" + Integer.toHexString(msg.getArg3()), "0x" + Integer.toHexString(msg.getArg4()), "0x" + Integer.toHexString(msg.getArg5()), msg.getData().toStringUtf8()); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glGetActiveUniform" : "void")
+                    , (code ? "/*program*/ " : "program=")
+                    , (code ? "program_" : "") + msg.getArg0()
+                    , (code ? "/*index*/ " : "index=")
+                    , msg.getArg1()
+                    , (code ? "/*bufsize*/ " : "bufsize=")
+                    , msg.getArg2()
+                    , (code ? "/*length*/ " : "length=")
+                    , (code ? "arg3" : "0x" + Integer.toHexString(msg.getArg3()))
+                    , (code ? "/*size*/ " : "size=")
+                    , (code ? "arg4" : "0x" + Integer.toHexString(msg.getArg4()))
+                    , (code ? "/*type*/ " : "type=")
+                    , (code ? "arg5" : "0x" + Integer.toHexString(msg.getArg5()))
+                    , (code ? "/*name*/ " : "name=")
+                    , (code ? "\"" : "") + msg.getData().toStringUtf8() + (code ? "\"" : ""));
+                break;
             case glGetAttachedShaders:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (program=%s, maxcount=%s, count=%s, shaders=%s)", "void", msg.getArg0(), msg.getArg1(), "0x" + Integer.toHexString(msg.getArg2()), "0x" + Integer.toHexString(msg.getArg3())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glGetAttachedShaders" : "void")
+                    , (code ? "/*program*/ " : "program=")
+                    , (code ? "program_" : "") + msg.getArg0()
+                    , (code ? "/*maxcount*/ " : "maxcount=")
+                    , msg.getArg1()
+                    , (code ? "/*count*/ " : "count=")
+                    , (code ? "arg2" : "0x" + Integer.toHexString(msg.getArg2()))
+                    , (code ? "/*shaders*/ " : "shaders=")
+                    , (code ? "arg3" : "0x" + Integer.toHexString(msg.getArg3())));
+                break;
             case glGetAttribLocation:
-                str = String.format("%s (program=%s, name=%s)", msg.getRet(), msg.getArg0(), msg.getData().toStringUtf8()); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glGetAttribLocation" : msg.getRet())
+                    , (code ? "/*program*/ " : "program=")
+                    , (code ? "program_" : "") + msg.getArg0()
+                    , (code ? "/*name*/ " : "name=")
+                    , (code ? "\"" : "") + msg.getData().toStringUtf8() + (code ? "\"" : ""));
+                break;
             case glGetBooleanv:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (pname=%s, params=%s)", "void", GLEnum.valueOf(msg.getArg0()), "0x" + Integer.toHexString(msg.getArg1())); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glGetBooleanv" : "void")
+                    , (code ? "/*pname*/ " : "pname=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*params*/ " : "params=")
+                    , (code ? "arg1" : "0x" + Integer.toHexString(msg.getArg1())));
+                break;
             case glGetBufferParameteriv:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (target=%s, pname=%s, params=%s)", "void", GLEnum.valueOf(msg.getArg0()), GLEnum.valueOf(msg.getArg1()), "0x" + Integer.toHexString(msg.getArg2())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glGetBufferParameteriv" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*pname*/ " : "pname=")
+                    , GLEnum.valueOf(msg.getArg1())
+                    , (code ? "/*params*/ " : "params=")
+                    , (code ? "arg2" : "0x" + Integer.toHexString(msg.getArg2())));
+                break;
             case glGetError:
-                str = String.format("%s ()", GLEnum.valueOf(msg.getRet())); break;
+                str = String.format("%s()",
+                    (code ? "glGetError" : GLEnum.valueOf(msg.getRet()))
+);
+                break;
             case glGetFloatv:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (pname=%s, params=%s)", "void", GLEnum.valueOf(msg.getArg0()), "0x" + Integer.toHexString(msg.getArg1())); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glGetFloatv" : "void")
+                    , (code ? "/*pname*/ " : "pname=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*params*/ " : "params=")
+                    , (code ? "arg1" : "0x" + Integer.toHexString(msg.getArg1())));
+                break;
             case glGetFramebufferAttachmentParameteriv:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (target=%s, attachment=%s, pname=%s, params=%s)", "void", GLEnum.valueOf(msg.getArg0()), GLEnum.valueOf(msg.getArg1()), GLEnum.valueOf(msg.getArg2()), "0x" + Integer.toHexString(msg.getArg3())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glGetFramebufferAttachmentParameteriv" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*attachment*/ " : "attachment=")
+                    , GLEnum.valueOf(msg.getArg1())
+                    , (code ? "/*pname*/ " : "pname=")
+                    , GLEnum.valueOf(msg.getArg2())
+                    , (code ? "/*params*/ " : "params=")
+                    , (code ? "arg3" : "0x" + Integer.toHexString(msg.getArg3())));
+                break;
             case glGetIntegerv:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (pname=%s, params=%s)", "void", GLEnum.valueOf(msg.getArg0()), "0x" + Integer.toHexString(msg.getArg1())); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glGetIntegerv" : "void")
+                    , (code ? "/*pname*/ " : "pname=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*params*/ " : "params=")
+                    , (code ? "arg1" : "0x" + Integer.toHexString(msg.getArg1())));
+                break;
             case glGetProgramiv:
-                str = String.format("%s (program=%s, pname=%s, params=%s)", "void", msg.getArg0(), GLEnum.valueOf(msg.getArg1()), FormatInts(1, msg.getData().asReadOnlyByteBuffer())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glGetProgramiv" : "void")
+                    , (code ? "/*program*/ " : "program=")
+                    , (code ? "program_" : "") + msg.getArg0()
+                    , (code ? "/*pname*/ " : "pname=")
+                    , GLEnum.valueOf(msg.getArg1())
+                    , (code ? "/*params*/ " : "params=")
+                    , (code ? "(GLint [])" : "") + FormatInts(1, msg.getData().asReadOnlyByteBuffer()));
+                break;
             case glGetProgramInfoLog:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (program=%s, bufsize=%s, length=%s, infolog=%s)", "void", msg.getArg0(), msg.getArg1(), "0x" + Integer.toHexString(msg.getArg2()), msg.getData().toStringUtf8()); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glGetProgramInfoLog" : "void")
+                    , (code ? "/*program*/ " : "program=")
+                    , (code ? "program_" : "") + msg.getArg0()
+                    , (code ? "/*bufsize*/ " : "bufsize=")
+                    , msg.getArg1()
+                    , (code ? "/*length*/ " : "length=")
+                    , (code ? "arg2" : "0x" + Integer.toHexString(msg.getArg2()))
+                    , (code ? "/*infolog*/ " : "infolog=")
+                    , (code ? "\"" : "") + msg.getData().toStringUtf8() + (code ? "\"" : ""));
+                break;
             case glGetRenderbufferParameteriv:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (target=%s, pname=%s, params=%s)", "void", GLEnum.valueOf(msg.getArg0()), GLEnum.valueOf(msg.getArg1()), "0x" + Integer.toHexString(msg.getArg2())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glGetRenderbufferParameteriv" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*pname*/ " : "pname=")
+                    , GLEnum.valueOf(msg.getArg1())
+                    , (code ? "/*params*/ " : "params=")
+                    , (code ? "arg2" : "0x" + Integer.toHexString(msg.getArg2())));
+                break;
             case glGetShaderiv:
-                str = String.format("%s (shader=%s, pname=%s, params=%s)", "void", msg.getArg0(), GLEnum.valueOf(msg.getArg1()), FormatInts(1, msg.getData().asReadOnlyByteBuffer())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glGetShaderiv" : "void")
+                    , (code ? "/*shader*/ " : "shader=")
+                    , (code ? "shader_" : "") + msg.getArg0()
+                    , (code ? "/*pname*/ " : "pname=")
+                    , GLEnum.valueOf(msg.getArg1())
+                    , (code ? "/*params*/ " : "params=")
+                    , (code ? "(GLint [])" : "") + FormatInts(1, msg.getData().asReadOnlyByteBuffer()));
+                break;
             case glGetShaderInfoLog:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (shader=%s, bufsize=%s, length=%s, infolog=%s)", "void", msg.getArg0(), msg.getArg1(), "0x" + Integer.toHexString(msg.getArg2()), msg.getData().toStringUtf8()); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glGetShaderInfoLog" : "void")
+                    , (code ? "/*shader*/ " : "shader=")
+                    , (code ? "shader_" : "") + msg.getArg0()
+                    , (code ? "/*bufsize*/ " : "bufsize=")
+                    , msg.getArg1()
+                    , (code ? "/*length*/ " : "length=")
+                    , (code ? "arg2" : "0x" + Integer.toHexString(msg.getArg2()))
+                    , (code ? "/*infolog*/ " : "infolog=")
+                    , (code ? "\"" : "") + msg.getData().toStringUtf8() + (code ? "\"" : ""));
+                break;
             case glGetShaderPrecisionFormat:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (shadertype=%s, precisiontype=%s, range=%s, precision=%s)", "void", GLEnum.valueOf(msg.getArg0()), GLEnum.valueOf(msg.getArg1()), "0x" + Integer.toHexString(msg.getArg2()), "0x" + Integer.toHexString(msg.getArg3())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glGetShaderPrecisionFormat" : "void")
+                    , (code ? "/*shadertype*/ " : "shadertype=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*precisiontype*/ " : "precisiontype=")
+                    , GLEnum.valueOf(msg.getArg1())
+                    , (code ? "/*range*/ " : "range=")
+                    , (code ? "arg2" : "0x" + Integer.toHexString(msg.getArg2()))
+                    , (code ? "/*precision*/ " : "precision=")
+                    , (code ? "arg3" : "0x" + Integer.toHexString(msg.getArg3())));
+                break;
             case glGetShaderSource:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (shader=%s, bufsize=%s, length=%s, source=%s)", "void", msg.getArg0(), msg.getArg1(), "0x" + Integer.toHexString(msg.getArg2()), msg.getData().toStringUtf8()); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glGetShaderSource" : "void")
+                    , (code ? "/*shader*/ " : "shader=")
+                    , (code ? "shader_" : "") + msg.getArg0()
+                    , (code ? "/*bufsize*/ " : "bufsize=")
+                    , msg.getArg1()
+                    , (code ? "/*length*/ " : "length=")
+                    , (code ? "arg2" : "0x" + Integer.toHexString(msg.getArg2()))
+                    , (code ? "/*source*/ " : "source=")
+                    , (code ? "\"" : "") + msg.getData().toStringUtf8() + (code ? "\"" : ""));
+                break;
             case glGetString:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (name=%s)", "0x" + Integer.toHexString(msg.getRet()), GLEnum.valueOf(msg.getArg0())); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glGetString" : "0x" + Integer.toHexString(msg.getRet()))
+                    , (code ? "/*name*/ " : "name=")
+                    , GLEnum.valueOf(msg.getArg0()));
+                break;
             case glGetTexParameterfv:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (target=%s, pname=%s, params=%s)", "void", GLEnum.valueOf(msg.getArg0()), GLEnum.valueOf(msg.getArg1()), "0x" + Integer.toHexString(msg.getArg2())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glGetTexParameterfv" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*pname*/ " : "pname=")
+                    , GLEnum.valueOf(msg.getArg1())
+                    , (code ? "/*params*/ " : "params=")
+                    , (code ? "arg2" : "0x" + Integer.toHexString(msg.getArg2())));
+                break;
             case glGetTexParameteriv:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (target=%s, pname=%s, params=%s)", "void", GLEnum.valueOf(msg.getArg0()), GLEnum.valueOf(msg.getArg1()), "0x" + Integer.toHexString(msg.getArg2())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glGetTexParameteriv" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*pname*/ " : "pname=")
+                    , GLEnum.valueOf(msg.getArg1())
+                    , (code ? "/*params*/ " : "params=")
+                    , (code ? "arg2" : "0x" + Integer.toHexString(msg.getArg2())));
+                break;
             case glGetUniformfv:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (program=%s, location=%s, params=%s)", "void", msg.getArg0(), msg.getArg1(), "0x" + Integer.toHexString(msg.getArg2())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glGetUniformfv" : "void")
+                    , (code ? "/*program*/ " : "program=")
+                    , (code ? "program_" : "") + msg.getArg0()
+                    , (code ? "/*location*/ " : "location=")
+                    , msg.getArg1()
+                    , (code ? "/*params*/ " : "params=")
+                    , (code ? "arg2" : "0x" + Integer.toHexString(msg.getArg2())));
+                break;
             case glGetUniformiv:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (program=%s, location=%s, params=%s)", "void", msg.getArg0(), msg.getArg1(), "0x" + Integer.toHexString(msg.getArg2())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glGetUniformiv" : "void")
+                    , (code ? "/*program*/ " : "program=")
+                    , (code ? "program_" : "") + msg.getArg0()
+                    , (code ? "/*location*/ " : "location=")
+                    , msg.getArg1()
+                    , (code ? "/*params*/ " : "params=")
+                    , (code ? "arg2" : "0x" + Integer.toHexString(msg.getArg2())));
+                break;
             case glGetUniformLocation:
-                str = String.format("%s (program=%s, name=%s)", msg.getRet(), msg.getArg0(), msg.getData().toStringUtf8()); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glGetUniformLocation" : msg.getRet())
+                    , (code ? "/*program*/ " : "program=")
+                    , (code ? "program_" : "") + msg.getArg0()
+                    , (code ? "/*name*/ " : "name=")
+                    , (code ? "\"" : "") + msg.getData().toStringUtf8() + (code ? "\"" : ""));
+                break;
             case glGetVertexAttribfv:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (index=%s, pname=%s, params=%s)", "void", msg.getArg0(), GLEnum.valueOf(msg.getArg1()), "0x" + Integer.toHexString(msg.getArg2())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glGetVertexAttribfv" : "void")
+                    , (code ? "/*index*/ " : "index=")
+                    , msg.getArg0()
+                    , (code ? "/*pname*/ " : "pname=")
+                    , GLEnum.valueOf(msg.getArg1())
+                    , (code ? "/*params*/ " : "params=")
+                    , (code ? "arg2" : "0x" + Integer.toHexString(msg.getArg2())));
+                break;
             case glGetVertexAttribiv:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (index=%s, pname=%s, params=%s)", "void", msg.getArg0(), GLEnum.valueOf(msg.getArg1()), "0x" + Integer.toHexString(msg.getArg2())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glGetVertexAttribiv" : "void")
+                    , (code ? "/*index*/ " : "index=")
+                    , msg.getArg0()
+                    , (code ? "/*pname*/ " : "pname=")
+                    , GLEnum.valueOf(msg.getArg1())
+                    , (code ? "/*params*/ " : "params=")
+                    , (code ? "arg2" : "0x" + Integer.toHexString(msg.getArg2())));
+                break;
             case glGetVertexAttribPointerv:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (index=%s, pname=%s, pointer=%s)", "void", msg.getArg0(), GLEnum.valueOf(msg.getArg1()), "0x" + Integer.toHexString(msg.getArg2())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glGetVertexAttribPointerv" : "void")
+                    , (code ? "/*index*/ " : "index=")
+                    , msg.getArg0()
+                    , (code ? "/*pname*/ " : "pname=")
+                    , GLEnum.valueOf(msg.getArg1())
+                    , (code ? "/*pointer*/ " : "pointer=")
+                    , (code ? "arg2" : "0x" + Integer.toHexString(msg.getArg2())));
+                break;
             case glHint:
-                str = String.format("%s (target=%s, mode=%s)", "void", GLEnum.valueOf(msg.getArg0()), GLEnum.valueOf(msg.getArg1())); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glHint" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*mode*/ " : "mode=")
+                    , GLEnum.valueOf(msg.getArg1()));
+                break;
             case glIsBuffer:
-                str = String.format("%s (buffer=%s)", msg.getRet(), msg.getArg0()); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glIsBuffer" : msg.getRet())
+                    , (code ? "/*buffer*/ " : "buffer=")
+                    , (code ? "buffer_" : "") + msg.getArg0());
+                break;
             case glIsEnabled:
-                str = String.format("%s (cap=%s)", msg.getRet(), GLEnum.valueOf(msg.getArg0())); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glIsEnabled" : msg.getRet())
+                    , (code ? "/*cap*/ " : "cap=")
+                    , GLEnum.valueOf(msg.getArg0()));
+                break;
             case glIsFramebuffer:
-                str = String.format("%s (framebuffer=%s)", msg.getRet(), msg.getArg0()); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glIsFramebuffer" : msg.getRet())
+                    , (code ? "/*framebuffer*/ " : "framebuffer=")
+                    , (code ? "framebuffer_" : "") + msg.getArg0());
+                break;
             case glIsProgram:
-                str = String.format("%s (program=%s)", msg.getRet(), msg.getArg0()); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glIsProgram" : msg.getRet())
+                    , (code ? "/*program*/ " : "program=")
+                    , (code ? "program_" : "") + msg.getArg0());
+                break;
             case glIsRenderbuffer:
-                str = String.format("%s (renderbuffer=%s)", msg.getRet(), msg.getArg0()); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glIsRenderbuffer" : msg.getRet())
+                    , (code ? "/*renderbuffer*/ " : "renderbuffer=")
+                    , (code ? "renderbuffer_" : "") + msg.getArg0());
+                break;
             case glIsShader:
-                str = String.format("%s (shader=%s)", msg.getRet(), msg.getArg0()); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glIsShader" : msg.getRet())
+                    , (code ? "/*shader*/ " : "shader=")
+                    , (code ? "shader_" : "") + msg.getArg0());
+                break;
             case glIsTexture:
-                str = String.format("%s (texture=%s)", msg.getRet(), msg.getArg0()); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glIsTexture" : msg.getRet())
+                    , (code ? "/*texture*/ " : "texture=")
+                    , (code ? "texture_" : "") + msg.getArg0());
+                break;
             case glLineWidth:
-                str = String.format("%s (width=%s)", "void", Float.intBitsToFloat(msg.getArg0())); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glLineWidth" : "void")
+                    , (code ? "/*width*/ " : "width=")
+                    , Float.intBitsToFloat(msg.getArg0()));
+                break;
             case glLinkProgram:
-                str = String.format("%s (program=%s)", "void", msg.getArg0()); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glLinkProgram" : "void")
+                    , (code ? "/*program*/ " : "program=")
+                    , (code ? "program_" : "") + msg.getArg0());
+                break;
             case glPixelStorei:
-                str = String.format("%s (pname=%s, param=%s)", "void", GLEnum.valueOf(msg.getArg0()), msg.getArg1()); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glPixelStorei" : "void")
+                    , (code ? "/*pname*/ " : "pname=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*param*/ " : "param=")
+                    , msg.getArg1());
+                break;
             case glPolygonOffset:
-                str = String.format("%s (factor=%s, units=%s)", "void", Float.intBitsToFloat(msg.getArg0()), Float.intBitsToFloat(msg.getArg1())); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glPolygonOffset" : "void")
+                    , (code ? "/*factor*/ " : "factor=")
+                    , Float.intBitsToFloat(msg.getArg0())
+                    , (code ? "/*units*/ " : "units=")
+                    , Float.intBitsToFloat(msg.getArg1()));
+                break;
             case glReadPixels:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (x=%s, y=%s, width=%s, height=%s, format=%s, type=%s, pixels=%s)", "void", msg.getArg0(), msg.getArg1(), msg.getArg2(), msg.getArg3(), GLEnum.valueOf(msg.getArg4()), GLEnum.valueOf(msg.getArg5()), "0x" + Integer.toHexString(msg.getArg6())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glReadPixels" : "void")
+                    , (code ? "/*x*/ " : "x=")
+                    , msg.getArg0()
+                    , (code ? "/*y*/ " : "y=")
+                    , msg.getArg1()
+                    , (code ? "/*width*/ " : "width=")
+                    , msg.getArg2()
+                    , (code ? "/*height*/ " : "height=")
+                    , msg.getArg3()
+                    , (code ? "/*format*/ " : "format=")
+                    , GLEnum.valueOf(msg.getArg4())
+                    , (code ? "/*type*/ " : "type=")
+                    , GLEnum.valueOf(msg.getArg5())
+                    , (code ? "/*pixels*/ " : "pixels=")
+                    , (code ? "arg6" : "0x" + Integer.toHexString(msg.getArg6())));
+                break;
             case glReleaseShaderCompiler:
-                str = String.format("%s ()", "void"); break;
+                str = String.format("%s()",
+                    (code ? "glReleaseShaderCompiler" : "void")
+);
+                break;
             case glRenderbufferStorage:
-                str = String.format("%s (target=%s, internalformat=%s, width=%s, height=%s)", "void", GLEnum.valueOf(msg.getArg0()), GLEnum.valueOf(msg.getArg1()), msg.getArg2(), msg.getArg3()); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glRenderbufferStorage" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*internalformat*/ " : "internalformat=")
+                    , GLEnum.valueOf(msg.getArg1())
+                    , (code ? "/*width*/ " : "width=")
+                    , msg.getArg2()
+                    , (code ? "/*height*/ " : "height=")
+                    , msg.getArg3());
+                break;
             case glSampleCoverage:
-                str = String.format("%s (value=%s, invert=%s)", "void", Float.intBitsToFloat(msg.getArg0()), msg.getArg1()); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glSampleCoverage" : "void")
+                    , (code ? "/*value*/ " : "value=")
+                    , Float.intBitsToFloat(msg.getArg0())
+                    , (code ? "/*invert*/ " : "invert=")
+                    , msg.getArg1());
+                break;
             case glScissor:
-                str = String.format("%s (x=%s, y=%s, width=%s, height=%s)", "void", msg.getArg0(), msg.getArg1(), msg.getArg2(), msg.getArg3()); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glScissor" : "void")
+                    , (code ? "/*x*/ " : "x=")
+                    , msg.getArg0()
+                    , (code ? "/*y*/ " : "y=")
+                    , msg.getArg1()
+                    , (code ? "/*width*/ " : "width=")
+                    , msg.getArg2()
+                    , (code ? "/*height*/ " : "height=")
+                    , msg.getArg3());
+                break;
             case glShaderBinary:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (n=%s, shaders=%s, binaryformat=%s, binary=%s, length=%s)", "void", msg.getArg0(), "0x" + Integer.toHexString(msg.getArg1()), GLEnum.valueOf(msg.getArg2()), "0x" + Integer.toHexString(msg.getArg3()), msg.getArg4()); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glShaderBinary" : "void")
+                    , (code ? "/*n*/ " : "n=")
+                    , msg.getArg0()
+                    , (code ? "/*shaders*/ " : "shaders=")
+                    , (code ? "arg1" : "0x" + Integer.toHexString(msg.getArg1()))
+                    , (code ? "/*binaryformat*/ " : "binaryformat=")
+                    , GLEnum.valueOf(msg.getArg2())
+                    , (code ? "/*binary*/ " : "binary=")
+                    , (code ? "arg3" : "0x" + Integer.toHexString(msg.getArg3()))
+                    , (code ? "/*length*/ " : "length=")
+                    , msg.getArg4());
+                break;
             case glShaderSource:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (shader=%s, count=%s, string=%s, length=%s)", "void", msg.getArg0(), msg.getArg1(), "0x" + Integer.toHexString(msg.getArg2()), "0x" + Integer.toHexString(msg.getArg3())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glShaderSource" : "void")
+                    , (code ? "/*shader*/ " : "shader=")
+                    , (code ? "shader_" : "") + msg.getArg0()
+                    , (code ? "/*count*/ " : "count=")
+                    , msg.getArg1()
+                    , (code ? "/*string*/ " : "string=")
+                    , (code ? "arg2" : "0x" + Integer.toHexString(msg.getArg2()))
+                    , (code ? "/*length*/ " : "length=")
+                    , (code ? "arg3" : "0x" + Integer.toHexString(msg.getArg3())));
+                break;
             case glStencilFunc:
-                str = String.format("%s (func=%s, ref=%s, mask=%s)", "void", GLEnum.valueOf(msg.getArg0()), msg.getArg1(), msg.getArg2()); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glStencilFunc" : "void")
+                    , (code ? "/*func*/ " : "func=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*ref*/ " : "ref=")
+                    , msg.getArg1()
+                    , (code ? "/*mask*/ " : "mask=")
+                    , msg.getArg2());
+                break;
             case glStencilFuncSeparate:
-                str = String.format("%s (face=%s, func=%s, ref=%s, mask=%s)", "void", GLEnum.valueOf(msg.getArg0()), GLEnum.valueOf(msg.getArg1()), msg.getArg2(), msg.getArg3()); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glStencilFuncSeparate" : "void")
+                    , (code ? "/*face*/ " : "face=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*func*/ " : "func=")
+                    , GLEnum.valueOf(msg.getArg1())
+                    , (code ? "/*ref*/ " : "ref=")
+                    , msg.getArg2()
+                    , (code ? "/*mask*/ " : "mask=")
+                    , msg.getArg3());
+                break;
             case glStencilMask:
-                str = String.format("%s (mask=%s)", "void", msg.getArg0()); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glStencilMask" : "void")
+                    , (code ? "/*mask*/ " : "mask=")
+                    , msg.getArg0());
+                break;
             case glStencilMaskSeparate:
-                str = String.format("%s (face=%s, mask=%s)", "void", GLEnum.valueOf(msg.getArg0()), msg.getArg1()); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glStencilMaskSeparate" : "void")
+                    , (code ? "/*face*/ " : "face=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*mask*/ " : "mask=")
+                    , msg.getArg1());
+                break;
             case glStencilOp:
-                str = String.format("%s (fail=%s, zfail=%s, zpass=%s)", "void", GLEnum.valueOf(msg.getArg0()), GLEnum.valueOf(msg.getArg1()), GLEnum.valueOf(msg.getArg2())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glStencilOp" : "void")
+                    , (code ? "/*fail*/ " : "fail=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*zfail*/ " : "zfail=")
+                    , GLEnum.valueOf(msg.getArg1())
+                    , (code ? "/*zpass*/ " : "zpass=")
+                    , GLEnum.valueOf(msg.getArg2()));
+                break;
             case glStencilOpSeparate:
-                str = String.format("%s (face=%s, fail=%s, zfail=%s, zpass=%s)", "void", GLEnum.valueOf(msg.getArg0()), GLEnum.valueOf(msg.getArg1()), GLEnum.valueOf(msg.getArg2()), GLEnum.valueOf(msg.getArg3())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glStencilOpSeparate" : "void")
+                    , (code ? "/*face*/ " : "face=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*fail*/ " : "fail=")
+                    , GLEnum.valueOf(msg.getArg1())
+                    , (code ? "/*zfail*/ " : "zfail=")
+                    , GLEnum.valueOf(msg.getArg2())
+                    , (code ? "/*zpass*/ " : "zpass=")
+                    , GLEnum.valueOf(msg.getArg3()));
+                break;
             case glTexImage2D:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (target=%s, level=%s, internalformat=%s, width=%s, height=%s, border=%s, format=%s, type=%s, pixels=%s)", "void", GLEnum.valueOf(msg.getArg0()), msg.getArg1(), msg.getArg2(), msg.getArg3(), msg.getArg4(), msg.getArg5(), GLEnum.valueOf(msg.getArg6()), GLEnum.valueOf(msg.getArg7()), "0x" + Integer.toHexString(msg.getArg8())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s, %s%s, %s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glTexImage2D" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*level*/ " : "level=")
+                    , msg.getArg1()
+                    , (code ? "/*internalformat*/ " : "internalformat=")
+                    , msg.getArg2()
+                    , (code ? "/*width*/ " : "width=")
+                    , msg.getArg3()
+                    , (code ? "/*height*/ " : "height=")
+                    , msg.getArg4()
+                    , (code ? "/*border*/ " : "border=")
+                    , msg.getArg5()
+                    , (code ? "/*format*/ " : "format=")
+                    , GLEnum.valueOf(msg.getArg6())
+                    , (code ? "/*type*/ " : "type=")
+                    , GLEnum.valueOf(msg.getArg7())
+                    , (code ? "/*pixels*/ " : "pixels=")
+                    , (code ? "arg8" : "0x" + Integer.toHexString(msg.getArg8())));
+                break;
             case glTexParameterf:
-                str = String.format("%s (target=%s, pname=%s, param=%s)", "void", GLEnum.valueOf(msg.getArg0()), GLEnum.valueOf(msg.getArg1()), Float.intBitsToFloat(msg.getArg2())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glTexParameterf" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*pname*/ " : "pname=")
+                    , GLEnum.valueOf(msg.getArg1())
+                    , (code ? "/*param*/ " : "param=")
+                    , Float.intBitsToFloat(msg.getArg2()));
+                break;
             case glTexParameterfv:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (target=%s, pname=%s, params=%s)", "void", GLEnum.valueOf(msg.getArg0()), GLEnum.valueOf(msg.getArg1()), "0x" + Integer.toHexString(msg.getArg2())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glTexParameterfv" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*pname*/ " : "pname=")
+                    , GLEnum.valueOf(msg.getArg1())
+                    , (code ? "/*params*/ " : "params=")
+                    , (code ? "arg2" : "0x" + Integer.toHexString(msg.getArg2())));
+                break;
             case glTexParameteri:
-                str = String.format("%s (target=%s, pname=%s, param=%s)", "void", GLEnum.valueOf(msg.getArg0()), GLEnum.valueOf(msg.getArg1()), msg.getArg2()); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glTexParameteri" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*pname*/ " : "pname=")
+                    , GLEnum.valueOf(msg.getArg1())
+                    , (code ? "/*param*/ " : "param=")
+                    , msg.getArg2());
+                break;
             case glTexParameteriv:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (target=%s, pname=%s, params=%s)", "void", GLEnum.valueOf(msg.getArg0()), GLEnum.valueOf(msg.getArg1()), "0x" + Integer.toHexString(msg.getArg2())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glTexParameteriv" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*pname*/ " : "pname=")
+                    , GLEnum.valueOf(msg.getArg1())
+                    , (code ? "/*params*/ " : "params=")
+                    , (code ? "arg2" : "0x" + Integer.toHexString(msg.getArg2())));
+                break;
             case glTexSubImage2D:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (target=%s, level=%s, xoffset=%s, yoffset=%s, width=%s, height=%s, format=%s, type=%s, pixels=%s)", "void", GLEnum.valueOf(msg.getArg0()), msg.getArg1(), msg.getArg2(), msg.getArg3(), msg.getArg4(), msg.getArg5(), GLEnum.valueOf(msg.getArg6()), GLEnum.valueOf(msg.getArg7()), "0x" + Integer.toHexString(msg.getArg8())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s, %s%s, %s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glTexSubImage2D" : "void")
+                    , (code ? "/*target*/ " : "target=")
+                    , GLEnum.valueOf(msg.getArg0())
+                    , (code ? "/*level*/ " : "level=")
+                    , msg.getArg1()
+                    , (code ? "/*xoffset*/ " : "xoffset=")
+                    , msg.getArg2()
+                    , (code ? "/*yoffset*/ " : "yoffset=")
+                    , msg.getArg3()
+                    , (code ? "/*width*/ " : "width=")
+                    , msg.getArg4()
+                    , (code ? "/*height*/ " : "height=")
+                    , msg.getArg5()
+                    , (code ? "/*format*/ " : "format=")
+                    , GLEnum.valueOf(msg.getArg6())
+                    , (code ? "/*type*/ " : "type=")
+                    , GLEnum.valueOf(msg.getArg7())
+                    , (code ? "/*pixels*/ " : "pixels=")
+                    , (code ? "arg8" : "0x" + Integer.toHexString(msg.getArg8())));
+                break;
             case glUniform1f:
-                str = String.format("%s (location=%s, x=%s)", "void", msg.getArg0(), Float.intBitsToFloat(msg.getArg1())); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glUniform1f" : "void")
+                    , (code ? "/*location*/ " : "location=")
+                    , msg.getArg0()
+                    , (code ? "/*x*/ " : "x=")
+                    , Float.intBitsToFloat(msg.getArg1()));
+                break;
             case glUniform1fv:
-                str = String.format("%s (location=%s, count=%s, v=%s)", "void", msg.getArg0(), msg.getArg1(), FormatFloats(1 * msg.getArg1(), msg.getData().asReadOnlyByteBuffer())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glUniform1fv" : "void")
+                    , (code ? "/*location*/ " : "location=")
+                    , msg.getArg0()
+                    , (code ? "/*count*/ " : "count=")
+                    , msg.getArg1()
+                    , (code ? "/*v*/ " : "v=")
+                    , (code ? "(GLfloat [])" : "") +  FormatFloats(1 * msg.getArg1(), msg.getData().asReadOnlyByteBuffer()));
+                break;
             case glUniform1i:
-                str = String.format("%s (location=%s, x=%s)", "void", msg.getArg0(), msg.getArg1()); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glUniform1i" : "void")
+                    , (code ? "/*location*/ " : "location=")
+                    , msg.getArg0()
+                    , (code ? "/*x*/ " : "x=")
+                    , msg.getArg1());
+                break;
             case glUniform1iv:
-                str = String.format("%s (location=%s, count=%s, v=%s)", "void", msg.getArg0(), msg.getArg1(), FormatInts(1 * msg.getArg1(), msg.getData().asReadOnlyByteBuffer())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glUniform1iv" : "void")
+                    , (code ? "/*location*/ " : "location=")
+                    , msg.getArg0()
+                    , (code ? "/*count*/ " : "count=")
+                    , msg.getArg1()
+                    , (code ? "/*v*/ " : "v=")
+                    , (code ? "(GLint [])" : "") +  FormatInts(1 * msg.getArg1(), msg.getData().asReadOnlyByteBuffer()));
+                break;
             case glUniform2f:
-                str = String.format("%s (location=%s, x=%s, y=%s)", "void", msg.getArg0(), Float.intBitsToFloat(msg.getArg1()), Float.intBitsToFloat(msg.getArg2())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glUniform2f" : "void")
+                    , (code ? "/*location*/ " : "location=")
+                    , msg.getArg0()
+                    , (code ? "/*x*/ " : "x=")
+                    , Float.intBitsToFloat(msg.getArg1())
+                    , (code ? "/*y*/ " : "y=")
+                    , Float.intBitsToFloat(msg.getArg2()));
+                break;
             case glUniform2fv:
-                str = String.format("%s (location=%s, count=%s, v=%s)", "void", msg.getArg0(), msg.getArg1(), FormatFloats(2 * msg.getArg1(), msg.getData().asReadOnlyByteBuffer())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glUniform2fv" : "void")
+                    , (code ? "/*location*/ " : "location=")
+                    , msg.getArg0()
+                    , (code ? "/*count*/ " : "count=")
+                    , msg.getArg1()
+                    , (code ? "/*v*/ " : "v=")
+                    , (code ? "(GLfloat [])" : "") +  FormatFloats(2 * msg.getArg1(), msg.getData().asReadOnlyByteBuffer()));
+                break;
             case glUniform2i:
-                str = String.format("%s (location=%s, x=%s, y=%s)", "void", msg.getArg0(), msg.getArg1(), msg.getArg2()); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glUniform2i" : "void")
+                    , (code ? "/*location*/ " : "location=")
+                    , msg.getArg0()
+                    , (code ? "/*x*/ " : "x=")
+                    , msg.getArg1()
+                    , (code ? "/*y*/ " : "y=")
+                    , msg.getArg2());
+                break;
             case glUniform2iv:
-                str = String.format("%s (location=%s, count=%s, v=%s)", "void", msg.getArg0(), msg.getArg1(), FormatInts(2 * msg.getArg1(), msg.getData().asReadOnlyByteBuffer())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glUniform2iv" : "void")
+                    , (code ? "/*location*/ " : "location=")
+                    , msg.getArg0()
+                    , (code ? "/*count*/ " : "count=")
+                    , msg.getArg1()
+                    , (code ? "/*v*/ " : "v=")
+                    , (code ? "(GLint [])" : "") +  FormatInts(2 * msg.getArg1(), msg.getData().asReadOnlyByteBuffer()));
+                break;
             case glUniform3f:
-                str = String.format("%s (location=%s, x=%s, y=%s, z=%s)", "void", msg.getArg0(), Float.intBitsToFloat(msg.getArg1()), Float.intBitsToFloat(msg.getArg2()), Float.intBitsToFloat(msg.getArg3())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glUniform3f" : "void")
+                    , (code ? "/*location*/ " : "location=")
+                    , msg.getArg0()
+                    , (code ? "/*x*/ " : "x=")
+                    , Float.intBitsToFloat(msg.getArg1())
+                    , (code ? "/*y*/ " : "y=")
+                    , Float.intBitsToFloat(msg.getArg2())
+                    , (code ? "/*z*/ " : "z=")
+                    , Float.intBitsToFloat(msg.getArg3()));
+                break;
             case glUniform3fv:
-                str = String.format("%s (location=%s, count=%s, v=%s)", "void", msg.getArg0(), msg.getArg1(), FormatFloats(3 * msg.getArg1(), msg.getData().asReadOnlyByteBuffer())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glUniform3fv" : "void")
+                    , (code ? "/*location*/ " : "location=")
+                    , msg.getArg0()
+                    , (code ? "/*count*/ " : "count=")
+                    , msg.getArg1()
+                    , (code ? "/*v*/ " : "v=")
+                    , (code ? "(GLfloat [])" : "") +  FormatFloats(3 * msg.getArg1(), msg.getData().asReadOnlyByteBuffer()));
+                break;
             case glUniform3i:
-                str = String.format("%s (location=%s, x=%s, y=%s, z=%s)", "void", msg.getArg0(), msg.getArg1(), msg.getArg2(), msg.getArg3()); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glUniform3i" : "void")
+                    , (code ? "/*location*/ " : "location=")
+                    , msg.getArg0()
+                    , (code ? "/*x*/ " : "x=")
+                    , msg.getArg1()
+                    , (code ? "/*y*/ " : "y=")
+                    , msg.getArg2()
+                    , (code ? "/*z*/ " : "z=")
+                    , msg.getArg3());
+                break;
             case glUniform3iv:
-                str = String.format("%s (location=%s, count=%s, v=%s)", "void", msg.getArg0(), msg.getArg1(), FormatInts(3 * msg.getArg1(), msg.getData().asReadOnlyByteBuffer())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glUniform3iv" : "void")
+                    , (code ? "/*location*/ " : "location=")
+                    , msg.getArg0()
+                    , (code ? "/*count*/ " : "count=")
+                    , msg.getArg1()
+                    , (code ? "/*v*/ " : "v=")
+                    , (code ? "(GLint [])" : "") +  FormatInts(3 * msg.getArg1(), msg.getData().asReadOnlyByteBuffer()));
+                break;
             case glUniform4f:
-                str = String.format("%s (location=%s, x=%s, y=%s, z=%s, w=%s)", "void", msg.getArg0(), Float.intBitsToFloat(msg.getArg1()), Float.intBitsToFloat(msg.getArg2()), Float.intBitsToFloat(msg.getArg3()), Float.intBitsToFloat(msg.getArg4())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glUniform4f" : "void")
+                    , (code ? "/*location*/ " : "location=")
+                    , msg.getArg0()
+                    , (code ? "/*x*/ " : "x=")
+                    , Float.intBitsToFloat(msg.getArg1())
+                    , (code ? "/*y*/ " : "y=")
+                    , Float.intBitsToFloat(msg.getArg2())
+                    , (code ? "/*z*/ " : "z=")
+                    , Float.intBitsToFloat(msg.getArg3())
+                    , (code ? "/*w*/ " : "w=")
+                    , Float.intBitsToFloat(msg.getArg4()));
+                break;
             case glUniform4fv:
-                str = String.format("%s (location=%s, count=%s, v=%s)", "void", msg.getArg0(), msg.getArg1(), FormatFloats(4 * msg.getArg1(), msg.getData().asReadOnlyByteBuffer())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glUniform4fv" : "void")
+                    , (code ? "/*location*/ " : "location=")
+                    , msg.getArg0()
+                    , (code ? "/*count*/ " : "count=")
+                    , msg.getArg1()
+                    , (code ? "/*v*/ " : "v=")
+                    , (code ? "(GLfloat [])" : "") +  FormatFloats(4 * msg.getArg1(), msg.getData().asReadOnlyByteBuffer()));
+                break;
             case glUniform4i:
-                str = String.format("%s (location=%s, x=%s, y=%s, z=%s, w=%s)", "void", msg.getArg0(), msg.getArg1(), msg.getArg2(), msg.getArg3(), msg.getArg4()); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glUniform4i" : "void")
+                    , (code ? "/*location*/ " : "location=")
+                    , msg.getArg0()
+                    , (code ? "/*x*/ " : "x=")
+                    , msg.getArg1()
+                    , (code ? "/*y*/ " : "y=")
+                    , msg.getArg2()
+                    , (code ? "/*z*/ " : "z=")
+                    , msg.getArg3()
+                    , (code ? "/*w*/ " : "w=")
+                    , msg.getArg4());
+                break;
             case glUniform4iv:
-                str = String.format("%s (location=%s, count=%s, v=%s)", "void", msg.getArg0(), msg.getArg1(), FormatInts(4 * msg.getArg1(), msg.getData().asReadOnlyByteBuffer())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glUniform4iv" : "void")
+                    , (code ? "/*location*/ " : "location=")
+                    , msg.getArg0()
+                    , (code ? "/*count*/ " : "count=")
+                    , msg.getArg1()
+                    , (code ? "/*v*/ " : "v=")
+                    , (code ? "(GLint [])" : "") +  FormatInts(4 * msg.getArg1(), msg.getData().asReadOnlyByteBuffer()));
+                break;
             case glUniformMatrix2fv:
-                str = String.format("%s (location=%s, count=%s, transpose=%s, value=%s)", "void", msg.getArg0(), msg.getArg1(), msg.getArg2(), FormatMatrix(2, 4 * msg.getArg1(), msg.getData().asReadOnlyByteBuffer())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glUniformMatrix2fv" : "void")
+                    , (code ? "/*location*/ " : "location=")
+                    , msg.getArg0()
+                    , (code ? "/*count*/ " : "count=")
+                    , msg.getArg1()
+                    , (code ? "/*transpose*/ " : "transpose=")
+                    , msg.getArg2()
+                    , (code ? "/*value*/ " : "value=")
+                    , (code ? "(GLfloat [])" : "") + FormatMatrix(2, 4 * msg.getArg1(), msg.getData().asReadOnlyByteBuffer()));
+                break;
             case glUniformMatrix3fv:
-                str = String.format("%s (location=%s, count=%s, transpose=%s, value=%s)", "void", msg.getArg0(), msg.getArg1(), msg.getArg2(), FormatMatrix(3, 9 * msg.getArg1(), msg.getData().asReadOnlyByteBuffer())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glUniformMatrix3fv" : "void")
+                    , (code ? "/*location*/ " : "location=")
+                    , msg.getArg0()
+                    , (code ? "/*count*/ " : "count=")
+                    , msg.getArg1()
+                    , (code ? "/*transpose*/ " : "transpose=")
+                    , msg.getArg2()
+                    , (code ? "/*value*/ " : "value=")
+                    , (code ? "(GLfloat [])" : "") + FormatMatrix(3, 9 * msg.getArg1(), msg.getData().asReadOnlyByteBuffer()));
+                break;
             case glUniformMatrix4fv:
-                str = String.format("%s (location=%s, count=%s, transpose=%s, value=%s)", "void", msg.getArg0(), msg.getArg1(), msg.getArg2(), FormatMatrix(4, 16 * msg.getArg1(), msg.getData().asReadOnlyByteBuffer())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glUniformMatrix4fv" : "void")
+                    , (code ? "/*location*/ " : "location=")
+                    , msg.getArg0()
+                    , (code ? "/*count*/ " : "count=")
+                    , msg.getArg1()
+                    , (code ? "/*transpose*/ " : "transpose=")
+                    , msg.getArg2()
+                    , (code ? "/*value*/ " : "value=")
+                    , (code ? "(GLfloat [])" : "") + FormatMatrix(4, 16 * msg.getArg1(), msg.getData().asReadOnlyByteBuffer()));
+                break;
             case glUseProgram:
-                str = String.format("%s (program=%s)", "void", msg.getArg0()); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glUseProgram" : "void")
+                    , (code ? "/*program*/ " : "program=")
+                    , (code ? "program_" : "") + msg.getArg0());
+                break;
             case glValidateProgram:
-                str = String.format("%s (program=%s)", "void", msg.getArg0()); break;
+                str = String.format("%s(%s%s)",
+                    (code ? "glValidateProgram" : "void")
+                    , (code ? "/*program*/ " : "program=")
+                    , (code ? "program_" : "") + msg.getArg0());
+                break;
             case glVertexAttrib1f:
-                str = String.format("%s (indx=%s, x=%s)", "void", msg.getArg0(), Float.intBitsToFloat(msg.getArg1())); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glVertexAttrib1f" : "void")
+                    , (code ? "/*indx*/ " : "indx=")
+                    , msg.getArg0()
+                    , (code ? "/*x*/ " : "x=")
+                    , Float.intBitsToFloat(msg.getArg1()));
+                break;
             case glVertexAttrib1fv:
-                str = String.format("%s (indx=%s, values=%s)", "void", msg.getArg0(), FormatFloats(1, msg.getData().asReadOnlyByteBuffer())); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glVertexAttrib1fv" : "void")
+                    , (code ? "/*indx*/ " : "indx=")
+                    , msg.getArg0()
+                    , (code ? "/*values*/ " : "values=")
+                    , (code ? "(GLfloat [])" : "") + FormatFloats(1, msg.getData().asReadOnlyByteBuffer()));
+                break;
             case glVertexAttrib2f:
-                str = String.format("%s (indx=%s, x=%s, y=%s)", "void", msg.getArg0(), Float.intBitsToFloat(msg.getArg1()), Float.intBitsToFloat(msg.getArg2())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s)",
+                    (code ? "glVertexAttrib2f" : "void")
+                    , (code ? "/*indx*/ " : "indx=")
+                    , msg.getArg0()
+                    , (code ? "/*x*/ " : "x=")
+                    , Float.intBitsToFloat(msg.getArg1())
+                    , (code ? "/*y*/ " : "y=")
+                    , Float.intBitsToFloat(msg.getArg2()));
+                break;
             case glVertexAttrib2fv:
-                str = String.format("%s (indx=%s, values=%s)", "void", msg.getArg0(), FormatFloats(2, msg.getData().asReadOnlyByteBuffer())); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glVertexAttrib2fv" : "void")
+                    , (code ? "/*indx*/ " : "indx=")
+                    , msg.getArg0()
+                    , (code ? "/*values*/ " : "values=")
+                    , (code ? "(GLfloat [])" : "") + FormatFloats(2, msg.getData().asReadOnlyByteBuffer()));
+                break;
             case glVertexAttrib3f:
-                str = String.format("%s (indx=%s, x=%s, y=%s, z=%s)", "void", msg.getArg0(), Float.intBitsToFloat(msg.getArg1()), Float.intBitsToFloat(msg.getArg2()), Float.intBitsToFloat(msg.getArg3())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glVertexAttrib3f" : "void")
+                    , (code ? "/*indx*/ " : "indx=")
+                    , msg.getArg0()
+                    , (code ? "/*x*/ " : "x=")
+                    , Float.intBitsToFloat(msg.getArg1())
+                    , (code ? "/*y*/ " : "y=")
+                    , Float.intBitsToFloat(msg.getArg2())
+                    , (code ? "/*z*/ " : "z=")
+                    , Float.intBitsToFloat(msg.getArg3()));
+                break;
             case glVertexAttrib3fv:
-                str = String.format("%s (indx=%s, values=%s)", "void", msg.getArg0(), FormatFloats(3, msg.getData().asReadOnlyByteBuffer())); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glVertexAttrib3fv" : "void")
+                    , (code ? "/*indx*/ " : "indx=")
+                    , msg.getArg0()
+                    , (code ? "/*values*/ " : "values=")
+                    , (code ? "(GLfloat [])" : "") + FormatFloats(3, msg.getData().asReadOnlyByteBuffer()));
+                break;
             case glVertexAttrib4f:
-                str = String.format("%s (indx=%s, x=%s, y=%s, z=%s, w=%s)", "void", msg.getArg0(), Float.intBitsToFloat(msg.getArg1()), Float.intBitsToFloat(msg.getArg2()), Float.intBitsToFloat(msg.getArg3()), Float.intBitsToFloat(msg.getArg4())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glVertexAttrib4f" : "void")
+                    , (code ? "/*indx*/ " : "indx=")
+                    , msg.getArg0()
+                    , (code ? "/*x*/ " : "x=")
+                    , Float.intBitsToFloat(msg.getArg1())
+                    , (code ? "/*y*/ " : "y=")
+                    , Float.intBitsToFloat(msg.getArg2())
+                    , (code ? "/*z*/ " : "z=")
+                    , Float.intBitsToFloat(msg.getArg3())
+                    , (code ? "/*w*/ " : "w=")
+                    , Float.intBitsToFloat(msg.getArg4()));
+                break;
             case glVertexAttrib4fv:
-                str = String.format("%s (indx=%s, values=%s)", "void", msg.getArg0(), FormatFloats(4, msg.getData().asReadOnlyByteBuffer())); break;
+                str = String.format("%s(%s%s, %s%s)",
+                    (code ? "glVertexAttrib4fv" : "void")
+                    , (code ? "/*indx*/ " : "indx=")
+                    , msg.getArg0()
+                    , (code ? "/*values*/ " : "values=")
+                    , (code ? "(GLfloat [])" : "") + FormatFloats(4, msg.getData().asReadOnlyByteBuffer()));
+                break;
             case glVertexAttribPointer:
                 // FIXME: this function uses pointers, debugger may send data in msg.data
-                str = String.format("%s (indx=%s, size=%s, type=%s, normalized=%s, stride=%s, ptr=%s)", "void", msg.getArg0(), msg.getArg1(), GLEnum.valueOf(msg.getArg2()), msg.getArg3(), msg.getArg4(), "0x" + Integer.toHexString(msg.getArg5())); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glVertexAttribPointer" : "void")
+                    , (code ? "/*indx*/ " : "indx=")
+                    , msg.getArg0()
+                    , (code ? "/*size*/ " : "size=")
+                    , msg.getArg1()
+                    , (code ? "/*type*/ " : "type=")
+                    , GLEnum.valueOf(msg.getArg2())
+                    , (code ? "/*normalized*/ " : "normalized=")
+                    , msg.getArg3()
+                    , (code ? "/*stride*/ " : "stride=")
+                    , msg.getArg4()
+                    , (code ? "/*ptr*/ " : "ptr=")
+                    , (code ? "arg5" : "0x" + Integer.toHexString(msg.getArg5())));
+                break;
             case glViewport:
-                str = String.format("%s (x=%s, y=%s, width=%s, height=%s)", "void", msg.getArg0(), msg.getArg1(), msg.getArg2(), msg.getArg3()); break;
+                str = String.format("%s(%s%s, %s%s, %s%s, %s%s)",
+                    (code ? "glViewport" : "void")
+                    , (code ? "/*x*/ " : "x=")
+                    , msg.getArg0()
+                    , (code ? "/*y*/ " : "y=")
+                    , msg.getArg1()
+                    , (code ? "/*width*/ " : "width=")
+                    , msg.getArg2()
+                    , (code ? "/*height*/ " : "height=")
+                    , msg.getArg3());
+                break;
             default:
                 str = msg.toString();
         }
diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/MessageParser.java b/tools/glesv2debugger/src/com/android/glesv2debugger/MessageParser.java
index af3567e..545f261 100644
--- a/tools/glesv2debugger/src/com/android/glesv2debugger/MessageParser.java
+++ b/tools/glesv2debugger/src/com/android/glesv2debugger/MessageParser.java
@@ -31,15 +31,15 @@
 
     String[] GetList()
     {
-        assert args.charAt(0) == '[';
+        assert args.charAt(0) == '{';
         String arg = args;
-        args = args.substring(args.indexOf(']') + 1);
+        args = args.substring(args.lastIndexOf('}') + 1);
         int comma = args.indexOf(',');
         if (comma >= 0)
             args = args.substring(comma + 1).trim();
         else
             args = null;
-        arg = arg.substring(1, arg.indexOf(']')).trim();
+        arg = arg.substring(1, arg.lastIndexOf('}')).trim();
         return arg.split(",");
     }
 
diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/MessageQueue.java b/tools/glesv2debugger/src/com/android/glesv2debugger/MessageQueue.java
index fecc24a..09dbc5d 100644
--- a/tools/glesv2debugger/src/com/android/glesv2debugger/MessageQueue.java
+++ b/tools/glesv2debugger/src/com/android/glesv2debugger/MessageQueue.java
@@ -23,14 +23,18 @@
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.EOFException;
+import java.io.FileInputStream;
 import java.io.IOException;
 import java.net.Socket;
+import java.nio.ByteOrder;
 import java.util.ArrayList;
 import java.util.HashMap;
 
 public class MessageQueue implements Runnable {
 
     boolean running = false;
+    private ByteOrder byteOrder;
+    private FileInputStream file; // if null, create and use socket
     Thread thread = null;
     ArrayList<Message> complete = new ArrayList<Message>(); // need synchronized
     ArrayList<Message> commands = new ArrayList<Message>(); // need synchronized
@@ -40,10 +44,12 @@
         this.sampleView = sampleView;
     }
 
-    public void Start() {
+    public void Start(final ByteOrder byteOrder, final FileInputStream file) {
         if (running)
             return;
         running = true;
+        this.byteOrder = byteOrder;
+        this.file = file;
         thread = new Thread(this);
         thread.start();
     }
@@ -84,18 +90,32 @@
 
     @Override
     public void run() {
-        Socket socket = new Socket();
-        try {
-            socket.connect(new java.net.InetSocketAddress("127.0.0.1", Integer
-                    .parseInt(sampleView.actionPort.getText())));
-            dis = new DataInputStream(socket.getInputStream());
-            dos = new DataOutputStream(socket.getOutputStream());
-        } catch (Exception e) {
-            running = false;
-            Error(e);
-        }
+        Socket socket = null;
+        if (file == null)
+            try {
+                socket = new Socket();
+                socket.connect(new java.net.InetSocketAddress("127.0.0.1", Integer
+                        .parseInt(sampleView.actionPort.getText())));
+                dis = new DataInputStream(socket.getInputStream());
+                dos = new DataOutputStream(socket.getOutputStream());
+            } catch (Exception e) {
+                running = false;
+                Error(e);
+            }
+        else
+            dis = new DataInputStream(file);
 
         while (running) {
+            try {
+                if (file != null && file.available() == 0) {
+                    running = false;
+                    break;
+                }
+            } catch (IOException e1) {
+                e1.printStackTrace();
+                assert false;
+            }
+
             Message msg = null;
             if (incoming.size() > 0) { // find queued incoming
                 for (ArrayList<Message> messages : incoming.values())
@@ -116,11 +136,15 @@
         }
 
         try {
-            socket.close();
+            if (socket != null)
+                socket.close();
+            else
+                file.close();
         } catch (IOException e) {
             Error(e);
             running = false;
         }
+
     }
 
     private void PutMessage(final Message msg) {
@@ -214,6 +238,8 @@
         int len = 0;
         try {
             len = dis.readInt();
+            if (byteOrder == ByteOrder.LITTLE_ENDIAN)
+                len = Integer.reverseBytes(len); // readInt reads BIT_ENDIAN
         } catch (EOFException e) {
             Error(new Exception("EOF"));
         }
@@ -241,12 +267,16 @@
             throws IOException {
         assert message.getFunction() != Function.NEG;
         final byte[] data = message.toByteArray();
-        dos.writeInt(data.length);
+        if (byteOrder == ByteOrder.BIG_ENDIAN)
+            dos.writeInt(data.length);
+        else
+            dos.writeInt(Integer.reverseBytes(data.length));
         dos.write(data);
     }
 
     private void ProcessMessage(final DataOutputStream dos, final Message msg) throws IOException {
         if (msg.getExpectResponse()) {
+            assert file == null; // file cannot be interactive mode
             if (sampleView.shaderEditor.ProcessMessage(this, msg))
                 return;
             else if (sampleView.breakpointOption.ProcessMessage(this, msg))
diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/SampleView.java b/tools/glesv2debugger/src/com/android/glesv2debugger/SampleView.java
index 9c2a28f..66a7dd3 100644
--- a/tools/glesv2debugger/src/com/android/glesv2debugger/SampleView.java
+++ b/tools/glesv2debugger/src/com/android/glesv2debugger/SampleView.java
@@ -28,6 +28,7 @@
 import org.eclipse.jface.action.IToolBarManager;
 import org.eclipse.jface.action.MenuManager;
 import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.dialogs.InputDialog;
 import org.eclipse.jface.dialogs.MessageDialog;
 import org.eclipse.jface.viewers.ColumnWeightData;
 import org.eclipse.jface.viewers.ISelectionChangedListener;
@@ -56,6 +57,7 @@
 import org.eclipse.swt.widgets.Canvas;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.FileDialog;
 import org.eclipse.swt.widgets.Listener;
 import org.eclipse.swt.widgets.Menu;
 import org.eclipse.swt.widgets.ScrollBar;
@@ -71,6 +73,8 @@
 import org.eclipse.ui.PlatformUI;
 import org.eclipse.ui.part.ViewPart;
 
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.FileWriter;
 import java.io.IOException;
 import java.io.PrintWriter;
@@ -204,7 +208,7 @@
     public SampleView() {
         MessageParserEx messageParserEx = new MessageParserEx();
         Message.Builder builder = Message.newBuilder();
-        messageParserEx.Parse(builder, "glUniform4fv(1,2,[0,1,2,3,4,5,6,7])");
+        messageParserEx.Parse(builder, "glUniform4fv(1,2,{0,1,2,3,4,5,6,7})");
         messageParserEx
                 .Parse(builder,
                         "void glShaderSource(shader=4, count=1, string=\"dksjafhskjahourehghskjg\", length=0x0)");
@@ -394,7 +398,6 @@
             }
         });
 
-        makeActions();
         hookContextMenu();
         hookSelectionChanged();
         contributeToActionBars();
@@ -434,7 +437,24 @@
     }
 
     private void fillLocalToolBar(final IToolBarManager manager) {
+        actionConnect = new Action("Connect", Action.AS_PUSH_BUTTON) {
+            @Override
+            public void run() {
+                ConnectDisconnect();
+            }
+        };
         manager.add(actionConnect);
+
+        manager.add(new Action("Open File", Action.AS_PUSH_BUTTON)
+        {
+            @Override
+            public void run()
+            {
+                if (!running)
+                    OpenFile();
+            }
+        });
+
         final Shell shell = this.getViewSite().getShell();
         actionAutoScroll = new Action("Auto Scroll", Action.AS_CHECK_BOX) {
             @Override
@@ -507,19 +527,18 @@
 
         actContext = new Action("Context: 0x", Action.AS_DROP_DOWN_MENU) {
             @Override
-            public void run()
-                              {
-                                  if (debugContexts.size() < 2)
-                                      return;
-                                  final String idStr = this.getText().substring(
+            public void run() {
+                if (debugContexts.size() < 2)
+                    return;
+                final String idStr = this.getText().substring(
                                           "Context: 0x".length());
-                                  if (idStr.length() == 0)
-                                      return;
-                                  final int contextId = Integer.parseInt(idStr, 16);
-                                  int index = debugContexts.indexOfKey(contextId);
-                                  index = (index + 1) % debugContexts.size();
-                                  ChangeContext(debugContexts.valueAt(index));
-                              }
+                if (idStr.length() == 0)
+                    return;
+                final int contextId = Integer.parseInt(idStr, 16);
+                int index = debugContexts.indexOfKey(contextId);
+                index = (index + 1) % debugContexts.size();
+                ChangeContext(debugContexts.valueAt(index));
+            }
         };
         manager.add(actContext);
 
@@ -527,9 +546,7 @@
         {
             @Override
             public void run() {
-                org.eclipse.jface.dialogs.InputDialog dialog = new org.eclipse.jface.dialogs.InputDialog(
-                        shell, "Port",
-                        "Debugger port",
+                InputDialog dialog = new InputDialog(shell, "Port", "Debugger port",
                         actionPort.getText(), null);
                 if (Window.OK == dialog.open()) {
                     actionPort.setText(dialog.getValue());
@@ -538,21 +555,63 @@
             }
         };
         manager.add(actionPort);
+
+        manager.add(new Action("CodeGen Frame", Action.AS_PUSH_BUTTON)
+        {
+            @Override
+            public void run()
+            {
+                if (current != null)
+                    new CodeGen().CodeGenFrame((Frame) viewer.getInput());
+            }
+        });
+
+        manager.add(new Action("CodeGen Frames", Action.AS_PUSH_BUTTON)
+        {
+            @Override
+            public void run()
+            {
+                if (current != null)
+                    new CodeGen().CodeGenFrames(current, frameNum.getSelection() + 1);
+            }
+        });
+    }
+
+    private void OpenFile() {
+        FileDialog dialog = new FileDialog(getSite().getShell(), SWT.OPEN);
+        dialog.setText("Open");
+        dialog.setFilterExtensions(new String[] {
+                "*.gles2dbg"
+        });
+        String filePath = dialog.open();
+        if (filePath == null)
+            return;
+        FileInputStream file = null;
+        try {
+            file = new FileInputStream(filePath);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+            return;
+        }
+        running = true;
+        messageQueue.Start(targetByteOrder, file);
+        thread = new Thread(this);
+        thread.start();
+        actionConnect.setText("Disconnect");
+        getViewSite().getActionBars().getToolBarManager().update(true);
     }
 
     private void ConnectDisconnect() {
         if (!running) {
             running = true;
-            messageQueue.Start();
+            messageQueue.Start(targetByteOrder, null);
             thread = new Thread(this);
             thread.start();
             actionConnect.setText("Disconnect");
-            actionConnect.setToolTipText("Disconnect from debuggee");
         } else {
             running = false;
             messageQueue.Stop();
             actionConnect.setText("Connect");
-            actionConnect.setToolTipText("Connect to debuggee");
         }
         this.getSite().getShell().getDisplay().syncExec(new Runnable() {
             @Override
@@ -562,17 +621,6 @@
         });
     }
 
-    private void makeActions() {
-        actionConnect = new Action() {
-            @Override
-            public void run() {
-                ConnectDisconnect();
-            }
-        };
-        actionConnect.setText("Connect");
-        actionConnect.setToolTipText("Connect to debuggee");
-    }
-
     void MessageDataSelected(final MessageData msgData) {
         if (null == msgData)
             return;
@@ -626,7 +674,6 @@
                         "GL ES 2.0 Debugger Client", e.getMessage());
             }
         });
-
     }
 
     /**
@@ -656,10 +703,9 @@
 
         boolean shaderEditorUpdate = false, currentUpdate = false;
         while (running) {
-            if (!messageQueue.IsRunning())
-                break;
-
             final Message oriMsg = messageQueue.RemoveCompleteMessage(0);
+            if (oriMsg == null && !messageQueue.IsRunning())
+                break;
             if (newMessages > 60 || (newMessages > 0 && null == oriMsg)) {
                 newMessages = 0;
 
@@ -669,11 +715,14 @@
                         public void run() {
                             if (current == null)
                                 ChangeContext(debugContexts.valueAt(0));
-                            else
+                            else if (frameNum.getSelection() == current.frames.size() - 1)
+                            {
                                 viewer.refresh(false);
+                                if (actionAutoScroll.isChecked())
+                                    viewer.getList().setSelection(
+                                            viewer.getList().getItemCount() - 1);
+                            }
                             frameNum.setMaximum(current.frames.size());
-                            if (actionAutoScroll.isChecked())
-                                viewer.getList().setSelection(viewer.getList().getItemCount() - 1);
                         }
                     });
                 currentUpdate = false;
diff --git a/tools/glesv2debugger/src/com/android/glesv2debugger/ShaderEditor.java b/tools/glesv2debugger/src/com/android/glesv2debugger/ShaderEditor.java
index dfb19d2..56676e3 100644
--- a/tools/glesv2debugger/src/com/android/glesv2debugger/ShaderEditor.java
+++ b/tools/glesv2debugger/src/com/android/glesv2debugger/ShaderEditor.java
@@ -253,9 +253,9 @@
 
         ExchangeMessage(contextId, queue, "glCompileShader(%d)", shader.name);
 
-        // the 0, "" and [0] are dummies for the parser
+        // the 0, "" and {0} are dummies for the parser
         Message rcv = ExchangeMessage(contextId, queue,
-                "glGetShaderiv(%d, GL_COMPILE_STATUS, [0])", shader.name);
+                "glGetShaderiv(%d, GL_COMPILE_STATUS, {0})", shader.name);
         assert rcv.hasData();
         if (rcv.getData().asReadOnlyByteBuffer().getInt() == 0) {
             // compile failed
@@ -276,7 +276,7 @@
                 GLProgram program = shader.context.GetProgram(programName);
                 ExchangeMessage(contextId, queue, "glLinkProgram(%d)", program.name);
                 rcv = ExchangeMessage(contextId, queue,
-                        "glGetProgramiv(%d, GL_LINK_STATUS, [0])", program.name);
+                        "glGetProgramiv(%d, GL_LINK_STATUS, {0})", program.name);
                 assert rcv.hasData();
                 if (rcv.getData().asReadOnlyByteBuffer().getInt() != 0)
                     continue;