//------------------------------------------------ //--- 010 Editor v12.0 Binary Template // // File: FL_xx__x.odx.FD_2DATA.BIN // Authors: Jille, Dark // Version: 0.9.9 // Purpose: Parse the contents of the MQB soundaktor firmware // Category: // File Mask: // ID Bytes: // History: 0.1 - Initial version // 0.2 - Additional field descriptions taken from MxCar sheet // 0.3.1 - 10 out of 12 tables mapped // 0.3.2 - Gain table key // 0.4 - Parsed and visualized all the tables found at this moment // 0.5 - Transposed some tables to be viewed in the right way // 0.6 - Added Lib_Sig (whatever it may be.. noise signature?) // 0.7 - template code cleanup, started GEN2.5 parsing // 0.8 - Checksum mechanism included // 0.9 - GEN2 finished, GEN2.5 work in progress // 0.9.1 - several more table params for GEN2.5 // 0.9.8 - parsed and printed everything except SUM_DATA and MX_PROFILE // 0.9.9 - MX_Profile parsed // 1.0 - more GEN2.5 Car / MX Profile options parsed //------------------------------------------------ // legend: // yellow/aqua = uncertain // red = checksum // green = confirmed // gray = seemingly irrelevant // blue = special // LOCAL VARIABLES local int i = 0; local int j = 0; local float x = 0; local int factor = 0; local string format = ""; local int start = 0x02; local int end = 0xE000; local string output = ""; local int GEN25 = (FileSize() == 0x18000 ? 1 : 0); if (GEN25) { end = 0x18000; } string getFilterProperties(int filterSetting) { switch (filterSetting) { case 0x00: return "No";     case 0x01: return "50Hz/6dB";       case 0x02: return "100Hz/6dB";     case 0x03: return "150Hz/6dB"; case 0x04: return "200Hz/6dB";     case 0x05: return "250Hz/6dB";     case 0x06: return "300Hz/6dB"; case 0x07: return "350Hz/6dB";     case 0x08: return "400Hz/6dB";     case 0x09: return "450Hz/6dB"; case 0x0A: return "50Hz/12dB";     case 0x0B: return "100Hz/12dB";     case 0x0C: return "150Hz/12dB"; case 0x0D: return "200Hz/12dB"; case 0x0E: return "250Hz/12dB";     case 0x0F: return "300Hz/12dB"; case 0x10: return "350Hz/12dB"; case 0x11: return "400Hz/12dB";     case 0x12: return "450Hz/12dB"; default: return "Unknown"; } } string getSampleRate(int sampleRate) { switch (sampleRate) { case 0: return "512"; case 1: return "1024"; case 2: return "2048"; case 3: return "4096"; case 4: return "8192"; case 5: return "16384"; case 6: return "32768"; default:return "Unknown"; } } int getIntegerSampleRate(int sampleRate) { switch (sampleRate) { case 0: return 512; case 1: return 1024; case 2: return 2048; case 3: return 4096; case 4: return 8192; case 5: return 16384; case 6: return 32768; default:return 0; } } string getSumEffect(int effectNumber) { switch(effectNumber) { case 0: return "Bypass"; case 1: return "Tiefpass"; case 2: return "Hochpass"; case 3: return "Bandpass"; case 4: return "Notch"; case 5: return "Peak"; case 6: return "LowShelf"; case 7: return "HighShelf"; default:return "Unknown"; } } // START PARSING LittleEndian(); ushort file_checksum ; //some kind of checksum? byte unknown_2 ; byte Gain_table_flag ; ushort DEFAULTS_Profiles ; if (!GEN25) { ushort DEFAULTS_Effects ; } else { local int DEFAULTS_Effects = 16; } ushort DEFAULTS_RevsFunctions ; // engine revolutions / LIB_n_Gain ushort DEFAULTS_AccelFunctions ; // acceleration / G-meter / LIB_m_Gain ushort DEFAULTS_SpeedFunctions ; // speed / LIB_v_Gain if (GEN25) { ushort DEFAULTS_PedalFunctions ; // pedal / LIB_p_Gain ushort DEFAULTS_Samples_count ; ushort unknown_9 ; ushort unknown_10 ; ushort unknown_11 ; ushort unknown_12 ; } else { ushort DEFAULTS_Revolutions_length ; ushort DEFAULTS_Acceleration_length ; ushort DEFAULTS_Speed_length ; ushort DEFAULTS_Acceleration_Table_size ; // size of LIB_m_Gain table in bytes, 512 ushort DEFAULTS_Revolutions_Table_size ; // size of LIB_n_Gain table in bytes, 8192 } ushort DEFAULTS_Profiles_2 ; if (!GEN25) { ushort DEFAULTS_Effects_2 ; } ushort DEFAULTS_RevsFunctions_2 ; ushort DEFAULTS_AccelFunctions_2 ; ushort DEFAULTS_SpeedFunctions_2 ; if (GEN25) { ushort DEFAULTS_PedalFunctions_2 ; ushort DEFAULTS_Samples_count_2 ; ushort DEFAULTS_Sample_Rate ; ushort unknown_14 ; ushort unknown_15 ; ushort unknown_16 ; ushort unknown_17 ; ushort unknown_18 ; } else { // the following 2 values are linked to SampleRate // Depending on the value there, the values here are different. ushort DEFAULTS_Samples_count ; // LIB_Sig ushort DEFAULTS_Sample_length ; // LIB_Sig ushort DEFAULTS_Damping_factor ; // Range 0-65535 } // Offset where the filename starts. FSeek(62); ushort source_filename_checksum ;// CRC16-CCITT char source_filename[64] ; ushort Profiles ; ushort RevsFunctions ; ushort AccelFunctions ; ushort SpeedFunctions ; if (!GEN25) { ushort Samples_count ; ushort Sample_Rate ; ushort Damping_factor ; // 0 <= DF <= 1 Quantization 0-65535 // they refer to it as initial speed value in GEN2 ???? (always set to 0!) ushort InitialSpeedValue ; // should be 0 in most cases, some electric cars have reversed value of 32768 } else { ushort PedalFunctions ; ushort Samples_count ; ushort Sample_Rate ; ushort unknown_22 ; ushort unknown_23 ; ushort unknown_24 ; ushort unknown_25 ; ushort unknown_26 ; ushort unknown_27 ; ushort unknown_28 ; ushort unknown_29 ; ushort unknown_30 ; } Printf("%s \n\n", source_filename); if (!GEN25) { Printf("GEN2 firmware\n\n"); struct { ubyte Engine_code ; char VIN_mask[17] ; ubyte Charisma_01_Switch_Relapse_Clamp15 ; ubyte Charisma_02_Switch_Gearbox ; ubyte Charisma_03_Default_driving_profile ; ubyte Charisma_04_Reverse_driving_profile ; ubyte Charisma_05_Comfort_driving_profile ; ubyte Charisma_06_Normal_driving_profile ; ubyte Charisma_07_Sport_driving_profile ; ubyte Charisma_08_Offroad_driving_profile ; ubyte Charisma_09_Eco_driving_profile ; ubyte Charisma_10_Race_driving_profile ; ubyte Charisma_11_GTE_driving_profile ; ubyte HighPass_filter ; ubyte Reserved_for_future_use_2 ; ubyte PHEV_button_led_bits ; // 335 only } Car[Profiles]; // Engine codes // 06 - high-perf 2.0l diesel engine? CUNA / CUPA / CUBA 190hp+ // 07 - mid-perf DFGA (could cover DFE also, maybe CRL too) Kodiaq 150hp 2.0l diesel // 0C - CEPA / CZGB 2.5l I5 engine // 17 - DAZA 2.5l 340+hp // 29 - MLB-version of high-perf 2.0l // 2B - CJX 2.0l 220+hp GTI, S3, SQ2, etc // 2A - CJS 1.8 Leon FR 170+hp // 42 - CJE / CPK / CPR 1.8 Leon FR // 45 - something between CJX and higher-perf 2.5l engines, maybe overtuned CJX from Clubsport models? 260-280hp // 32 - Passat PHEV / Tiguan PHEV, 2.0l maybe? // 13 - CUK 1.4TSI GTE, Bora / Lavida / Golf // 14 - old-school A4 diesels 2.0l / 2.7l / 3.0l // 2D - A6 diesel ? // 48 - CWGD / DLZA V6 3.0l 350hp S4 // 49 - DECA / DKMB V6 2.9l 450hp RS4 / RS5 // 5A - ??? // 3F - ANY // D5 - S3 8Y // E4 - S3 8Y // D8 - Urus V8 struct { // ST_Gain ushort value[DEFAULTS_Effects]; } Gain_Effect[Profiles] ; struct { // ST_Phase ushort value[DEFAULTS_Effects]; } Phase_Effect[Profiles] ; struct { // ST_Pitch_Shift ushort value[DEFAULTS_Effects]; } Pitch_Shift_Effect[Profiles] ; struct { // ST_Delay ushort value[DEFAULTS_Effects]; } Delay_Effect[Profiles] ; struct { byte value[DEFAULTS_Effects]; } Effects_to_Accel[Profiles] ; struct { byte value[DEFAULTS_Effects]; } Effects_to_Revs[Profiles] ; struct { byte value[DEFAULTS_Effects]; } Effects_to_Speed[Profiles] ; // general table to apply effects on the final sound of every car profile if (Gain_table_flag > 0) { // this gain table appears only in newer firmware: 5F 0003+, 8S, 8W // but 5F 0001, 0002, 8K firmwares dont have it struct { byte value[DEFAULTS_Effects]; } Effects_to_Profiles[Profiles] ; } struct { // MX_Sig ushort gain[Profiles]; ushort clip[Profiles]; } Effects_to_Samples ; ushort Acceleration_Scale[DEFAULTS_Acceleration_length] ; // values in [-0.3 - 0.98] range (5F 0003 fw) / [-0.4 - 1.00] range (565 AGA fw) ushort Revolutions_Scale[DEFAULTS_Revolutions_length] ; // values in [500 - 8150] (rpm) range quanified by 16256 ushort Speed_Scale[DEFAULTS_Speed_length] ; // values in [0 - 326.39] (km/h) range struct { // LIB_m_Gain ushort value[DEFAULTS_Acceleration_length]; } Acceleration[AccelFunctions] ; struct { // LIB_n_Gain ushort value[DEFAULTS_Revolutions_length]; } Revolutions[RevsFunctions] ; struct { // LIB_v_Gain ushort value[DEFAULTS_Speed_length]; } Speed[SpeedFunctions] ; struct { // LIB_Sig short value[getIntegerSampleRate(Sample_Rate)]; } Samples[Samples_count] ; // Print a report to output Printf("ID\tEngine\tVIN\t\tRelapseKl15\tGearbox\tDefault\tReverse\tComfort(1)\tNormal(2)\tSport(3)\tOffroad(4)\tEco(5)\tRace(6)\tHybrid(8)\tHighPassFtr\tRFU2\tRFU3\t\n"); for( i = 0; i < Profiles; i++ ) { Printf("%i\t%02X\t%s\t%i\t%i\t%i\t%i\t%i\t%i\t%i\t%i\t%i\t%i\t%i\t%s\t%i\t%i\n", i+1, Car[i].Engine_code, Car[i].VIN_mask, Car[i].Charisma_01_Switch_Relapse_Clamp15, Car[i].Charisma_02_Switch_Gearbox, Car[i].Charisma_03_Default_driving_profile + 1,// these all need +1 for some reason, unless it's 255 Car[i].Charisma_04_Reverse_driving_profile + 1, Car[i].Charisma_05_Comfort_driving_profile + 1, Car[i].Charisma_06_Normal_driving_profile + 1, Car[i].Charisma_07_Sport_driving_profile + 1, Car[i].Charisma_08_Offroad_driving_profile + 1, Car[i].Charisma_09_Eco_driving_profile + 1, Car[i].Charisma_10_Race_driving_profile + 1, Car[i].Charisma_11_GTE_driving_profile + 1, getFilterProperties(Car[i].HighPass_filter), Car[i].Reserved_for_future_use_2, Car[i].PHEV_button_led_bits ); } } else if (GEN25) { Printf("GEN2.5 firmware\n\n"); local int DEFAULTS_Acceleration_length = 32; local int DEFAULTS_Revolutions_length = 256; local int DEFAULTS_Speed_length = 32; local int DEFAULTS_Pedal_length = 32; FSeek(160); struct { ubyte Power_kW ; ubyte unknown_2 ; // car Class / Group ubyte Engine_code ; char VIN_mask[17] ; char Transmission ; // A - Auto // H - Hybrid ??? char BodyType ; // G - ??? // O - Cabrio / Open Roof char Drivetrain ; // V - All-wheel drive ??? // H - Hybrid char FPA_installed ; ubyte unknown_25 ; ubyte MX_ID ; // Priority ??? } Car[Profiles]; // local int MXP_y = 32; // local int MXP_x = 12; local int SUM_x = 14; // 19 if (Gain_table_flag == 3) { SUM_x = 19; } // struct { // ubyte unknown[MXP_x]; // } ubyte MX_Profile[384] ; struct { ushort value[SUM_x]; // there is NO parameter with such a value and sometimes it is 19 !!!! } SUM_data[Profiles] ; struct { ushort value[DEFAULTS_Effects]; } Gain_Effect[Profiles] ; struct { ushort value[DEFAULTS_Effects]; } Pitch_Shift_Effect[Profiles] ; struct { ushort value[DEFAULTS_Effects]; } Phase_Effect[Profiles] ; struct { ushort value[DEFAULTS_Effects]; } Delay_Effect[Profiles] ; struct { ubyte value[DEFAULTS_Effects]; } Effects_to_Revs[Profiles] ; ushort Revolutions_Scale[DEFAULTS_Revolutions_length] ; // values in [500 - 8150] (rpm) range quanified by 16256 struct { // LIB_n_Gain ushort value[DEFAULTS_Revolutions_length]; } Revolutions[RevsFunctions] ; struct { ubyte value[DEFAULTS_Effects]; } Effects_to_Accel[Profiles] ; ushort Acceleration_Scale[DEFAULTS_Acceleration_length] ; // values in [-0.5 - 1.00] range, acceleration struct { // LIB_m_Gain ushort value[DEFAULTS_Acceleration_length]; } Acceleration[AccelFunctions] ; struct { ubyte value[DEFAULTS_Effects]; } Effects_to_Speed[Profiles] ; ushort Speed_Scale[DEFAULTS_Speed_length] ; // values in [0 - 326.39] (km/h) range struct { // LIB_v_Gain ushort value[DEFAULTS_Speed_length]; } Speed[SpeedFunctions] ; struct { ubyte value[DEFAULTS_Effects]; } Effects_to_Pedal[Profiles] ; ushort Pedal_Scale[DEFAULTS_Pedal_length] ; struct { // LIB_p_Gain ushort value[DEFAULTS_Pedal_length]; } Pedal[PedalFunctions] ; struct { // MX_Sig ubyte value[DEFAULTS_Effects]; } Effects_to_Samples[Profiles] ; struct { // LIB_Sig short value[getIntegerSampleRate(Sample_Rate)]; } Samples[Samples_count] ; // Print a report to output Printf("CAR\n"); Printf("ID\tPower kW\tunknown_2\tEngine\tVIN\t\tTransmissn\tBody Type\tDrivetrain\tFPA Flag\tunknown_25\tMX ID\n"); for( i = 0; i < Profiles; i++ ) { Printf("%i\t%i\t%i\t%02X\t%s\t%s\t%s\t%s\t%s\t%i\t%i\n", i + 1, Car[i].Power_kW == 63 ? 0 : Car[i].Power_kW, Car[i].unknown_2, Car[i].Engine_code, Car[i].VIN_mask, Car[i].Transmission, Car[i].BodyType, Car[i].Drivetrain, (Car[i].FPA_installed == 'J' ? "Yes" : Car[i].FPA_installed == 'N' ? "No" : "Any"), Car[i].unknown_25, Car[i].MX_ID ); } } // FUNCTIONS void PrintHeader( char name[] ) { Printf("\n%s\n", name); if (!GEN25) { Printf("BOOST\t\t\tHYBRID\t\t\tEFFICIENCY\n"); Printf("Normal\tSport\tEco\tNormal\tSport\tEco\tNormal\tSport\n"); } } ubyte get2HalfByte(ubyte source) { return source >> 4; } ubyte get1HalfByte(ubyte source) { return source & 0x0F; } // SHORT spreadsheets 8x12(16) if (GEN25) { // WORK IN PROGRESS // WORK IN PROGRESS // WORK IN PROGRESS local int schema_type_byte_position = (Gain_table_flag == 3 ? 4 : 2); local int original_line_length = schema_type_byte_position + 4; local int current_line_length = original_line_length; local int line_counter = 0; local int profile = 0; j = 0; i = 0; Printf("\nMX_Profile\n"); Printf("ID\t byte_1\t"); if (schema_type_byte_position == 4) { Printf(" byte_2\t"); Printf(" byte_3\t"); } Printf("Schemas\t"); Printf(" Comfort(1)\t Normal(2)\t Sport(3)\t Offroad(4)\t Eco(5)\t Race(6)\t Hybrid(8)\t \t"); Printf(" Comfort(1)\t Normal(2)\t Sport(3)\t Offroad(4)\t Eco(5)\t Race(6)\t Hybrid(8)\t "); Printf("\n"); do { if (j == 0) { Printf("%i\t", line_counter+1); } j++; if (j == schema_type_byte_position && MX_Profile[i] > 0) { current_line_length +=4; } if ( j == schema_type_byte_position ) { profile = get1HalfByte(MX_Profile[i]); // if (profile > 127) { // profile = 255 - profile; // Printf("-"); // } if (profile == 0) { Printf("0 B\t"); } else if (profile == 1) { Printf("1 M\t"); } else if (profile == 2) { Printf("2 H\t"); } else if (profile == 3) { Printf("3 HM\t"); } else if (profile == 4) { Printf("4 C\t"); } else if (profile == 5) { Printf("5 CM\t"); } else if (profile == 6) { Printf("6 CH\t"); } else if (profile == 7) { Printf("7 CHM\t"); } else if (profile == 8) { Printf("8 BK\t"); } else { Printf("%i unkwn\t", profile); } } else { if ( j < schema_type_byte_position ) { Printf("( %02i %02i ) \t", get1HalfByte(MX_Profile[i]), get2HalfByte(MX_Profile[i]) ); } else { if ( j == schema_type_byte_position + 1 || j == schema_type_byte_position + 5 || j == schema_type_byte_position + 9 ) { Printf("[ "); } if ( j == schema_type_byte_position + 4 || j == schema_type_byte_position + 8 || j == schema_type_byte_position + 12 ) { Printf("%i\t]\t", get1HalfByte(MX_Profile[i]) + 1); // skip 8th unused half-byte } else { Printf("%i\t %i\t ", get1HalfByte(MX_Profile[i]) + 1, get2HalfByte(MX_Profile[i]) + 1); } } } if (j == current_line_length) { Printf("\n"); line_counter++; j = 0; current_line_length = original_line_length; } i++; } while (line_counter < 8); Printf("%i bytes length\n", i); /* // WORK IN PROGRESS // WORK IN PROGRESS // WORK IN PROGRESS Printf("\nSUM_data\n"); for ( j = 0; j < SUM_x; j++ ) { for( i = 0; i < Profiles; i++ ) { if (j == SUM_x-3) { x = (float) SUM_data[i].value[j] / 65536; Printf("%.2g\t", x); } else if (j == SUM_x-2) { x = (float) SUM_data[i].value[j] / 2048 * 16; Printf("%.2g\t", x); } else if (j == SUM_x-1) { x = (float) SUM_data[i].value[j] / 2048 * 8; Printf("%.2g\t", x); } else { x = (float) SUM_data[i].value[j] ; Printf("%g\t", x); } } Printf("\n"); }; // WORK IN PROGRESS // WORK IN PROGRESS // WORK IN PROGRESS */ } PrintHeader("Gain_Effect (ST/TS_Gain)"); for ( j = 0; j < DEFAULTS_Effects; j++ ) { for( i = 0; i < Profiles; i++ ) { if (GEN25) { x = (float) Gain_Effect[i].value[j] / (0xffff / 4); Printf("%.3g\t", x); } else { // there is definitelly a rounding issue exists // trying to compensate it with 1.0058 multiplier x = (float) Gain_Effect[i].value[j] * 1.0058 / 16; Printf("%.4g°\t", x); } } Printf("\n"); }; PrintHeader("Phase_Effect (ST/TS_Phase)"); for ( j = 0; j < DEFAULTS_Effects; j++ ) { for( i = 0; i < Profiles; i++ ) { x = (float) Phase_Effect[i].value[j]; if (GEN25) { x = (float) Phase_Effect[i].value[j] / (0xFFFF / (2 * 3.14159265359)); // 2Pi / 65536 } Printf("%.3g\t", x); } Printf("\n"); }; PrintHeader("Pitch_Shift_Effect (ST/TS_Pitch-Shift)"); for ( j = 0; j < DEFAULTS_Effects; j++ ) { for( i = 0; i < Profiles; i++ ) { x = (float) Pitch_Shift_Effect[i].value[j] / 0xffff; if (GEN25) { x *= 1.4265; // FMax value } Printf("%.3g\t", x); } Printf("\n"); }; PrintHeader("Delay_Effect (ST/TS_Delay)"); for ( j = 0; j < DEFAULTS_Effects; j++ ) { for( i = 0; i < Profiles; i++ ) { x = (float) Delay_Effect[i].value[j] / 0xffff; if (GEN25) { x *= 0.01024; // 0.005 / 65536 } Printf("%.2g\t", x); } Printf("\n"); }; // BYTE spreadsheets 8x12(16) PrintHeader("Effects_to_Accel (MX_m_Gain)"); for ( j = 0; j < DEFAULTS_Effects; j++ ) { for( i = 0; i < Profiles; i++ ) { Printf("%i\t", Effects_to_Accel[i].value[j] + 1); // not sure do we need this +1 } Printf("\n"); }; PrintHeader("Effects_to_Revs (MX_n_Gain)"); for ( j = 0; j < DEFAULTS_Effects; j++ ) { for( i = 0; i < Profiles; i++ ) { Printf("%i\t", Effects_to_Revs[i].value[j] + 1); // not sure do we need this +1 } Printf("\n"); }; PrintHeader("Effects_to_Speed (MX_v_Gain)"); for ( j = 0; j < DEFAULTS_Effects; j++ ) { for( i = 0; i < Profiles; i++ ) { Printf("%i\t", Effects_to_Speed[i].value[j] + 1); // not sure do we need this +1 } Printf("\n"); }; if (GEN25) { PrintHeader("Effects_to_Pedal (MX_p_Gain)"); for ( j = 0; j < DEFAULTS_Effects; j++ ) { for( i = 0; i < Profiles; i++ ) { Printf("%i\t", Effects_to_Pedal[i].value[j] + 1); // not sure do we need this +1 } Printf("\n"); }; PrintHeader("Effects_to_Samples (MX_Sig)"); for ( j = 0; j < DEFAULTS_Effects; j++ ) { for( i = 0; i < Profiles; i++ ) { Printf("%i\t", Effects_to_Samples[i].value[j] + 1); // not sure do we need this +1 } Printf("\n"); }; } else { if (Gain_table_flag > 0) { PrintHeader("Effects_to_Profiles"); for ( j = 0; j < DEFAULTS_Effects; j++ ) { for( i = 0; i < Profiles; i++ ) { Printf("%i\t", Effects_to_Profiles[i].value[j] + 1); // not sure do we need this +1 } Printf("\n"); }; } PrintHeader("Effects_to_Samples (MX_Sig)"); for ( j = 0; j < 8; j++ ) { Printf("%.3g\t", (float) Effects_to_Samples.gain[j] / 0xffff * 2); // 0 < X < 1 // Q:65536 } Printf("GAIN"); Printf("\n"); for ( j = 0; j < 8; j++ ) { Printf("%.3g\t", (float) Effects_to_Samples.clip[j] / 0xffff * 512); // 0 < X < 8 // Q:65536 } Printf("CLIP"); Printf("\n"); } Printf("\nAcceleration (LIB_m_Gain)\nHEADER\tDATA\n"); for( i = 0; i < DEFAULTS_Acceleration_length; i++ ) { Printf("%.2f", (float) Acceleration_Scale[i] / 32768 - 1); for( j = 0; j < AccelFunctions; j++ ) { Printf("\t%.4f", (float) Acceleration[j].value[i] / 0xffff); } Printf("\n"); } Printf("\nRevolutions (LIB_n_Gain)\nHEADER\tDATA\n"); for( i = 0; i < DEFAULTS_Revolutions_length; i++ ) { Printf("%i", (float) Revolutions_Scale[i] / 4); for( j = 0; j < 16; j++ ) { Printf("\t%.4f", (float) Revolutions[j].value[i] / 0xffff); } Printf("\n"); } Printf("\nSpeed (LIB_v_Gain)\nHEADER\tDATA\n"); for( i = 0; i < DEFAULTS_Speed_length; i++ ) { // real scale for this header column is the percentage [0 - 100%] from 326.39 value // multipliying it to 3.2639 shows absolute speed // (VW e-UP! is limited to 150kmh) Printf("%.2f", (float) Speed_Scale[i] / 326.39 * 3.2639); for( j = 0; j < SpeedFunctions; j++ ) { Printf("\t%.4f", (float) Speed[j].value[i] / 0xffff); } Printf("\n"); } if (GEN25) { Printf("\nPedal (LIB_p_Gain)\nHEADER\tDATA\n"); for( i = 0; i < DEFAULTS_Pedal_length; i++ ) { Printf("%.2f", (float) Pedal_Scale[i] / 0xffff); for( j = 0; j < PedalFunctions; j++ ) { Printf("\t%.4f", (float) Pedal[j].value[i] / 0xffff); } Printf("\n"); } } /* Printf("\nSamples (LIB_Sig) %i length x %i\nHEADER\tDATA\n", getIntegerSampleRate(Sample_Rate), Samples_count); for( i = 0; i < getIntegerSampleRate(Sample_Rate); i++ ) { for( j = 0; j < Samples_count; j++ ) { Printf("%i\t", (float) Samples[j].value[i]); } Printf("\n"); } */ local int checksum = -1; for (j = start;j < end; j += 2) { checksum = checksum + ReadUShort(j); } checksum = (checksum & 0xffff) ^ 0xffff; local int name_checksum = Checksum(CHECKSUM_CRCCCITT, 64, 64, -1, -1); // algo, size, length, poly, init Printf("\nFILE CHECKSUM: %.04X", SwapBytes(checksum) >> 16 & 0x0000ffff); Printf("\nNAME CHECKSUM: %.04X", SwapBytes(name_checksum) >> 16 & 0x0000ffff);