Export LEGO MINDSTORMS EV3 Lab Code I was wondering if it was possible in any way to see the actual code that is generated by the Lego Mindstorms IDE.

I know there isn't a direct 'export to code' option within the tool but I wondered if there was a third party tool by any chance.

On a related note, it seems the files that are saved (.ev3) are just raw data. Is there any specification for the file format?

Any info would be greatly appreciated!
Update:

I have written a tool to disassemble EV3 programs. The EV3 software compiles the .ev3 file to a .rbf file and sends that to the EV3 brick. The disassembler can convert the .rbf file into a .lms file, which is a sort of assembly language that can be used to create programs for the EV3.

Here is a simple example using a trivial .ev3 project.



To create the .rbf file, we have to download the program to an EV3 brick. Then we can upload the .rbf file from the brick using the Memory Browser.



Running the disassembler on the .rbf file will result in this:

    // Disassembly of C:\Users\david\Desktop\Program.rbf
    //
    // Byte code version: 0.57

    DATA8 GLOBAL0
    DATA8 GLOBAL1
    DATA8 GLOBAL2
    DATA8 GLOBAL3
    DATA8 GLOBAL4
    DATA8 GLOBAL5
    DATA8 GLOBAL6
    DATA8 GLOBAL7
    DATA8 GLOBAL8
    DATA8 GLOBAL9
    DATA8 GLOBAL10
    DATA8 GLOBAL11
    DATA8 GLOBAL12
    DATA8 GLOBAL13
    DATA8 GLOBAL14
    DATA8 GLOBAL15
    DATA8 GLOBAL16
    DATA8 GLOBAL17
    DATA8 GLOBAL18
    DATA8 GLOBAL19
    DATA8 GLOBAL20

    vmthread OBJECT1
    {
            DATA8 LOCAL0
            DATA8 LOCAL1
            DATA8 LOCAL2
            DATA8 LOCAL3
            DATA8 LOCAL4

    OFFSET1_0:
            OUTPUT_RESET(0,15)
    OFFSET1_3:
            INPUT_DEVICE(CLR_ALL,-1)
    OFFSET1_6:
            MOVE32_32(0,LOCAL0)
    OFFSET1_9:
            ADD32(GLOBAL12,1,GLOBAL12)
    OFFSET1_13:
            MOVE8_8(GLOBAL20,LOCAL4)
    OFFSET1_16:
            ADD32(GLOBAL8,1,GLOBAL8)
    OFFSET1_20:
            JR_FALSE(LOCAL4,OFFSET1_29)
    OFFSET1_23:
            ADD32(LOCAL0,1,LOCAL0)
    OFFSET1_27:
            JR(OFFSET1_9)
    OFFSET1_29:
            ADD32(GLOBAL4,1,GLOBAL4)
    OFFSET1_33:
            CALL(OBJECT2,1123418112,0,1117126656,1065353216,0,1)
    OFFSET1_58:
            ADD32(GLOBAL0,1,GLOBAL0)
    }

    subcall OBJECT2
    {
            IN_F LOCAL0
            IN_F LOCAL4
            IN_F LOCAL8
            IN_F LOCAL12
            IN_32 LOCAL16
            IN_8 LOCAL20

            DATA8 LOCAL21
            DATA8 LOCAL22
            DATA8 LOCAL23
            DATA8 LOCAL24
            DATA8 LOCAL25
            DATA8 LOCAL26
            DATA8 LOCAL27
            DATA8 LOCAL28
            DATA8 LOCAL29
            DATA8 LOCAL30
            DATA8 LOCAL31
            DATA8 LOCAL32
            DATA8 LOCAL33
            DATA8 LOCAL34
            DATA8 LOCAL35
            DATA8 LOCAL36
            DATA8 LOCAL37
            DATA8 LOCAL38
            DATA8 LOCAL39
            DATA8 LOCAL40
            DATA8 LOCAL41
            DATA8 LOCAL42
            DATA8 LOCAL43
            DATA8 LOCAL44
            DATA8 LOCAL45
            DATA8 LOCAL46
            DATA8 LOCAL47
            DATA8 LOCAL48
            DATA8 LOCAL49
            DATA8 LOCAL50
            DATA8 LOCAL51
            DATA8 LOCAL52
            DATA8 LOCAL53
            DATA8 LOCAL54
            DATA8 LOCAL55
            DATA8 LOCAL56
            DATA8 LOCAL57
            DATA8 LOCAL58
            DATA8 LOCAL59
            DATA8 LOCAL60
            DATA8 LOCAL61
            DATA8 LOCAL62
            DATA8 LOCAL63
            DATA8 LOCAL64
            DATA8 LOCAL65
            DATA8 LOCAL66

    OFFSET2_7:
            CP_EQF(LOCAL12,0,LOCAL66)
    OFFSET2_12:
            MOVE32_32(GLOBAL16,LOCAL36)
    OFFSET2_16:
            AND32(LOCAL16,LOCAL36,LOCAL48)
    OFFSET2_22:
            CP_GT32(LOCAL48,0,LOCAL65)
    OFFSET2_28:
            OR8(LOCAL66,LOCAL65,LOCAL64)
    OFFSET2_35:
            JR_EQ8(LOCAL64,1,OFFSET2_45)
    OFFSET2_40:
            JR_EQ8(LOCAL64,0,OFFSET2_48)
    OFFSET2_45:
            JR(OFFSET2_139)
    OFFSET2_48:
            MULF(LOCAL12,360.0F,LOCAL24)
    OFFSET2_56:
            CALL(OBJECT3,LOCAL0,LOCAL8,LOCAL24,LOCAL4,LOCAL58,LOCAL60,LOCAL20)
    OFFSET2_68:
            MOVE32_32(LOCAL16,LOCAL52)
    OFFSET2_72:
            MOVE8_8(LOCAL60,LOCAL59)
    OFFSET2_77:
            MOVE8_8(LOCAL58,LOCAL57)
    OFFSET2_82:
            MOVE32_32(0,LOCAL44)
    OFFSET2_86:
            MOVE32_32(GLOBAL16,LOCAL40)
    OFFSET2_90:
            AND32(LOCAL52,LOCAL40,LOCAL32)
    OFFSET2_97:
            CP_GT32(LOCAL32,0,LOCAL62)
    OFFSET2_103:
            OUTPUT_TEST(LOCAL57,LOCAL59,LOCAL56)
    OFFSET2_110:
            CP_EQ8(LOCAL56,0,LOCAL61)
    OFFSET2_116:
            OR8(LOCAL61,LOCAL62,LOCAL63)
    OFFSET2_123:
            SLEEP()
    OFFSET2_124:
            JR_TRUE(LOCAL63,OFFSET2_137)
    OFFSET2_128:
            ADD32(LOCAL44,1,LOCAL44)
    OFFSET2_134:
            JR(OFFSET2_86)
    OFFSET2_137:
            JR(OFFSET2_139)
    OFFSET2_139:
    }

    subcall OBJECT3
    {
            IN_F LOCAL0
            IN_F LOCAL4
            IN_F LOCAL8
            IN_F LOCAL12
            OUT_8 LOCAL16
            OUT_8 LOCAL17
            IN_8 LOCAL18

            DATA8 LOCAL19
            DATA8 LOCAL20
            DATA8 LOCAL21
            DATA8 LOCAL22
            DATA8 LOCAL23
            DATA8 LOCAL24
            DATA8 LOCAL25
            DATA8 LOCAL26
            DATA8 LOCAL27
            DATA8 LOCAL28
            DATA8 LOCAL29
            DATA8 LOCAL30
            DATA8 LOCAL31
            DATA8 LOCAL32
            DATA8 LOCAL33
            DATA8 LOCAL34
            DATA8 LOCAL35
            DATA8 LOCAL36
            DATA8 LOCAL37
            DATA8 LOCAL38
            DATA8 LOCAL39
            DATA8 LOCAL40
            DATA8 LOCAL41
            DATA8 LOCAL42
            DATA8 LOCAL43
            DATA8 LOCAL44
            DATA8 LOCAL45
            DATA8 LOCAL46
            DATA8 LOCAL47
            DATA8 LOCAL48
            DATA8 LOCAL49
            DATA8 LOCAL50
            DATA8 LOCAL51
            DATA8 LOCAL52
            DATA8 LOCAL53
            DATA8 LOCAL54
            DATA8 LOCAL55
            DATA8 LOCAL56
            DATA8 LOCAL57
            DATA8 LOCAL58
            DATA8 LOCAL59
            DATA8 LOCAL60
            DATA8 LOCAL61
            DATA8 LOCAL62
            DATA8 LOCAL63
            DATA8 LOCAL64
            DATA8 LOCAL65
            DATA8 LOCAL66
            DATA8 LOCAL67
            DATA8 LOCAL68
            DATA8 LOCAL69
            DATA8 LOCAL70
            DATA8 LOCAL71
            DATA8 LOCAL72
            DATA8 LOCAL73
            DATA8 LOCAL74
            DATA8 LOCAL75
            DATA8 LOCAL76
            DATA8 LOCAL77
            DATA8 LOCAL78
            DATA8 LOCAL79
            DATA8 LOCAL80
            DATA8 LOCAL81
            DATA8 LOCAL82
            DATA8 LOCAL83
            DATA8 LOCAL84
            DATA8 LOCAL85
            DATA8 LOCAL86
            DATA8 LOCAL87
            DATA8 LOCAL88
            DATA8 LOCAL89
            DATA8 LOCAL90
            DATA8 LOCAL91
            DATA8 LOCAL92
            DATA8 LOCAL93
            DATA8 LOCAL94
            DATA8 LOCAL95
            DATA8 LOCAL96
            DATA8 LOCAL97
            DATA8 LOCAL98
            DATA8 LOCAL99
            DATA8 LOCAL100
            DATA8 LOCAL101
            DATA8 LOCAL102
            DATA8 LOCAL103
            DATA8 LOCAL104
            DATA8 LOCAL105

    OFFSET3_8:
            CP_LTF(LOCAL8,0,LOCAL100)
    OFFSET3_13:
            JR_EQ8(LOCAL100,1,OFFSET3_24)
    OFFSET3_18:
            MOVEF_F(LOCAL4,LOCAL56)
    OFFSET3_22:
            JR(OFFSET3_40)
    OFFSET3_24:
            SUBF(0.0F,LOCAL4,LOCAL72)
    OFFSET3_33:
            MOVEF_F(LOCAL72,LOCAL56)
    OFFSET3_38:
            JR(OFFSET3_40)
    OFFSET3_40:
            MOVEF_8(LOCAL56,LOCAL97)
    OFFSET3_45:
            CP_NEQF(LOCAL56,0,LOCAL101)
    OFFSET3_51:
            MATH(ABS,LOCAL8,LOCAL68)
    OFFSET3_56:
            MOVEF_32(LOCAL68,LOCAL88)
    OFFSET3_61:
            MOVEF_F(2.0F,LOCAL32)
    OFFSET3_69:
            MOVEF_32(LOCAL0,LOCAL84)
    OFFSET3_73:
            PORT_CNV_OUTPUT(LOCAL84,LOCAL99,LOCAL98,LOCAL104)
    OFFSET3_82:
            MOVE8_8(LOCAL98,LOCAL17)
    OFFSET3_86:
            MOVE8_8(LOCAL99,LOCAL16)
    OFFSET3_90:
            AND8(LOCAL101,LOCAL18,LOCAL103)
    OFFSET3_96:
            MOVE16_16(0,LOCAL92)
    OFFSET3_100:
            JR_FALSE(LOCAL103,OFFSET3_108)
    OFFSET3_104:
            MOVE16_16(1,LOCAL92)
    OFFSET3_108:
            MOVE16_8(LOCAL92,LOCAL96)
    OFFSET3_113:
            MOVEF_F(LOCAL12,LOCAL40)
    OFFSET3_117:
            MOVEF_F(-100.0F,LOCAL36)
    OFFSET3_125:
            MOVEF_F(LOCAL40,LOCAL44)
    OFFSET3_130:
            MOVEF_F(100.0F,LOCAL52)
    OFFSET3_138:
            CP_GTF(LOCAL44,LOCAL52,LOCAL102)
    OFFSET3_145:
            MOVEF_F(LOCAL44,LOCAL48)
    OFFSET3_150:
            JR_FALSE(LOCAL102,OFFSET3_159)
    OFFSET3_154:
            MOVEF_F(LOCAL52,LOCAL48)
    OFFSET3_159:
            CP_LTF(LOCAL48,LOCAL36,LOCAL105)
    OFFSET3_166:
            MOVEF_F(LOCAL48,LOCAL24)
    OFFSET3_170:
            JR_FALSE(LOCAL105,OFFSET3_178)
    OFFSET3_174:
            MOVEF_F(LOCAL36,LOCAL24)
    OFFSET3_178:
            MOVEF_F(LOCAL24,LOCAL20)
    OFFSET3_181:
            MULF(LOCAL20,LOCAL32,LOCAL28)
    OFFSET3_186:
            JR_EQ8(LOCAL104,1,OFFSET3_197)
    OFFSET3_191:
            MOVEF_F(LOCAL28,LOCAL60)
    OFFSET3_195:
            JR(OFFSET3_218)
    OFFSET3_197:
            MOVEF_F(0.0F,LOCAL76)
    OFFSET3_205:
            SUBF(LOCAL76,LOCAL28,LOCAL64)
    OFFSET3_211:
            MOVEF_F(LOCAL64,LOCAL60)
    OFFSET3_216:
            JR(OFFSET3_218)
    OFFSET3_218:
            MOVEF_16(LOCAL60,LOCAL94)
    OFFSET3_223:
            OUTPUT_STEP_SYNC(LOCAL99,LOCAL98,LOCAL97,LOCAL94,LOCAL88,LOCAL96)
    OFFSET3_236:
    }


Being a disassembly, this can be a bit hard to interpret since there are not any helpful variable names. You can find information on EV3 assembly language here.



Original answer:

The .ev3 file is actually just a zip file. You can use any zip utility to browse the contents or unzip it. It will look something like this:

├── Activity.x3a
├── ActivityAssets.laz
├── Program.ev3p
├── Project.lvprojx
├── ___CopyrightYear
└── ___ProjectTitle


The ___* files are just plain text files, ActivityAssets.laz is another zip file and the rest are xml files.