fluke9
Full Member
Karma: +26/-1
Offline
Posts: 113
|
|
« on: November 03, 2019, 03:16:31 PM »
|
|
|
Small tool, may not be worth much but for people interested where setzi62s info on the eeprom descriptor table came from in here: http://nefariousmotorsports.com/forum/index.php?topic=362.0title=Tool is up at github here: https://github.com/fluke9/ME7_eepromtablefinderlinux and windows bins included (windows bin might need mingw dlls, too lazy for now to build native) Output is like follows: image is 512kb big... loaded file "0261207609-1037363702-55180795.BIN" ... trying to find the table len=524288 found at addr 0x073B0C we found the table address 0x59c8 but we do not know the segment yet... dumping table at 159c8 00 0027 (PAGEUSED) (CHECKSUM) (BIT2) (BIT5) 01 0010 (BIT4) 02 0103 (PAGEUSED) (CHECKSUM) 03 0227 (PAGEUSED) (CHECKSUM) (BIT2) (BIT5) 04 0323 (PAGEUSED) (CHECKSUM) (BIT5) 05 0483 (PAGEUSED) (CHECKSUM) (BACKUPPAGE) 06 04C3 (PAGEUSED) (CHECKSUM) (CSUM-1) (BACKUPPAGE) 07 0527 (PAGEUSED) (CHECKSUM) (BIT2) (BIT5) 08 0623 (PAGEUSED) (CHECKSUM) (BIT5) 09 07A3 (PAGEUSED) (CHECKSUM) (BACKUPPAGE) (BIT5) 10 07E3 (PAGEUSED) (CHECKSUM) (CSUM-1) (BACKUPPAGE) (BIT5) 11 0823 (PAGEUSED) (CHECKSUM) (BIT5) 12 0923 (PAGEUSED) (CHECKSUM) (BIT5) 13 0A23 (PAGEUSED) (CHECKSUM) (BIT5) 14 0B07 (PAGEUSED) (CHECKSUM) (BIT2) 15 0B10 (BIT4) 16 0B10 (BIT4) 17 0B10 (BIT4) 18 0B10 (BIT4) 19 0B10 (BIT4) 20 0B10 (BIT4) 21 0B10 (BIT4) 22 0C33 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 23 0D33 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 24 0E33 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 25 0F33 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 26 1033 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 27 1133 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 28 1233 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 29 1333 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 30 1433 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 31 1533 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 32 1633 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 33 1733 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 34 1833 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 35 1933 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 36 1A33 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 37 1B33 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 38 1C33 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 39 1D33 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 40 1E33 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 41 1F33 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 42 2033 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 43 2133 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 44 2233 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 45 2333 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 46 2433 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 47 2533 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 48 2633 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 49 2733 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 50 2833 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 51 2933 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 52 2A33 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 53 2B33 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 54 2C33 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 55 2D33 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 56 2E33 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 57 2F33 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 58 3033 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 59 3133 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 60 3233 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 61 3333 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 62 3433 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) 63 3533 (PAGEUSED) (CHECKSUM) (BIT4) (BIT5) your table has 64 pages, so your eeprom is 1024 bytes big
Will use this later on to reconstruct eeprom files from the eeprom mirror in ram retrieved via my McMess code so one can read and write the eeprom without bootmode on all ecus which support mcmess. Worked on all of nyets stock bins and all my Alfa ME7.3.1 bins. More stuff will follow on github.
|
|
|
Logged
|
|
|
|
360trev
Full Member
Karma: +68/-2
Offline
Posts: 235
|
|
« Reply #1 on: November 05, 2019, 08:51:29 AM »
|
|
|
Good job, so glad to see people doing these little projects still.
I've just added a single line snippet and included my C16x disassembler. Plus 1 include file.
if (!memcmp(data+addr, needle, sizeof(needle))) { printf("found at addr 0x%06X\n", addr); foundaddr = addr;
if(show_diss) { c167x_diss(addr, data+addr, 32); } // Show asm output on found byte match. break; }
Result is...
Searching for EEPROM table...trying to find the table len=524288 found at addr 0x069576
0x00069576: (+0 ) C4 20 04 00 mov [r0+4], r2 0x0006957A: (+4 ) F4 85 02 00 movb r14, [r5+2] 0x0006957E: (+8 ) C0 84 movbz r4, r14 0x00069580: (+10 ) C4 40 06 00 mov [r0+6], r4 0x00069584: (+14 ) 08 54 add r5, #4 0x00069586: (+16 ) A9 85 movb r14, [r5] 0x00069588: (+18 ) 47 F8 20 00 cmpb r14, #0020h 0x0006958C: (+22 ) EA 30 66 97 jmpa cc_UC, loc_69766 ; ------------------------------------------------------------------------------
0x00069590: (+26 ) F7 8E 27 A6 movb byte_A627, ZEROS ***
I'll upload a git project with the C16x dissassembler standalone for you to add to your projects. Makes it easier indeed. Also have some good helper functions which support mask searching.
I also wrote the table format dumpers too so you can dump all the different types of tables you can find in a rom in all the different formats they come in and your segment calculator too.
So adding this little snippet..
printf("we found the table address 0x%x but we do not know the segment yet...\n", tableoffset);
MPTR _offset; translate_seg(&_offset, "OFFSET", data, dpp1_value-1, get16((unsigned char *)data+foundaddr) /*val*/); show_seg(&_offset);
unsigned int testaddr = tableoffset;
testaddr += 0x10000; printf ("dumping table at %x\n", testaddr);
Shows...
we found the table address 0x6132 but we do not know the segment yet... OFFSET @ ROM:0x816132 RAM:0x7b7152 File-Offset:0x16132 (seg=0x0204 val=0x6132) dumping table at 16132
If your interested in these helper functions let me know and ill add them as a standalone project to my Swiss Army Knife tool.
|
|
|
Logged
|
|
|
|
fluke9
Full Member
Karma: +26/-1
Offline
Posts: 113
|
|
« Reply #2 on: November 05, 2019, 11:00:49 AM »
|
|
|
Good job, so glad to see people doing these little projects still.
This was really a superquick 5 minute hack as i was curios why my eepromMirror memory location does differ a lot from the real eeprom. This table explains it. I have done a lot of McMess reverse engineering recently and wanted to use it to dump/write the eeprom by using the mirror in ram without bootmode. It is written to the eeprom in the afterrun code after ignition goes off. With this table i can reconstruct it now (besides the IMMO bytes which are missing?!). With my current McMess code i can dump the whole ram in about 10-20 seconds and write to any location. Coolest thing ever would be a function in ram which i have yet to find to take over the ecu from OBD. I've just added a single line snippet and included my C16x disassembler. Plus 1 include file.
Cool, i have seen your stuff (and used it quickly already) and i already wanted to steal your disassembler. I'll upload a git project with the C16x dissassembler standalone for you to add to your projects. Makes it easier indeed. Also have some good helper functions which support mask searching.
If your interested in these helper functions let me know and ill add them as a standalone project to my Swiss Army Knife tool.
Would really rock, i could use it for my McMess stuff too, just have to figure out how to link in a repo as dependency. The McMess code is not ready for primetime yet but will follow soon(tm) on github.
|
|
|
Logged
|
|
|
|
360trev
Full Member
Karma: +68/-2
Offline
Posts: 235
|
|
« Reply #3 on: November 05, 2019, 12:20:19 PM »
|
|
|
Did you fully reverse the entire McMess and all its sub functions?
Something like this... ?
McMess_MainProtocol McMess_MainProtocol: McMess_MainProtocol 88 C0 mov [-r0], r12 McMess_MainProtocol+2 88 90 mov [-r0], r9 McMess_MainProtocol+4 88 80 mov [-r0], r8 McMess_MainProtocol+6 88 70 mov [-r0], r7 McMess_MainProtocol+8 88 60 mov [-r0], r McMess_MainProtocol+A 26 F0 0A 00 sub r0, #0Ah McMess_MainProtocol+E F4 80 12 00 movb rl4, [r0+12h] McMess_MainProtocol+12 49 82 cmpb rl4, #2 ; ... read pp McMess_MainProtocol+14 EA 20 18 77 jmpa cc_Z, mcMess_readPP McMess_MainProtocol+18 49 84 cmpb rl4, #4 ; ... read Var1 McMess_MainProtocol+1A EA 20 26 77 jmpa cc_Z, mcMess_readVar1 McMess_MainProtocol+1E 49 87 cmpb rl4, #7 ; ... read Var2 McMess_MainProtocol+20 EA 20 34 77 jmpa cc_Z, mcMess_readVar2 McMess_MainProtocol+24 47 F8 0B 00 cmpb rl4, #0Bh ; ... read ROM(Var2,Var1 ) McMess_MainProtocol+28 EA 20 42 77 jmpa cc_Z, mcMess_readROM McMess_MainProtocol+2C 47 F8 0E 00 cmpb rl4, #0Eh ; ... read RAM(Var1,Var2) McMess_MainProtocol+30 EA 20 84 77 jmpa cc_Z, mcMess_readRAM McMess_MainProtocol+34 47 F8 10 00 cmpb rl4, #10h ; ... Read byte (Var1) McMess_MainProtocol+38 EA 20 C6 77 jmpa cc_Z, mcMess_readByte McMess_MainProtocol+3C 47 F8 13 00 cmpb rl4, #13h ; ... Read error memory (var1, var2) McMess_MainProtocol+40 EA 20 22 78 jmpa cc_Z, mcMess_readErrorMemory_unsupported_EB McMess_MainProtocol+44 47 F8 15 00 cmpb rl4, #15h McMess_MainProtocol+48 EA 20 2C 78 jmpa cc_Z, mcMess_unknown1_unsupported_EB McMess_MainProtocol+4C 47 F8 16 00 cmpb rl4, #16h McMess_MainProtocol+50 EA 20 36 78 jmpa cc_Z, mcMess_unknown2_unsupported_EB McMess_MainProtocol+54 47 F8 19 00 cmpb rl4, #19h ; ... Read SG identification (DAMOS-ID) code (var1) McMess_MainProtocol+58 EA 20 40 78 jmpa cc_Z, mcMess_ReadSGid McMess_MainProtocol+5C 47 F8 1F 00 cmpb rl4, #1Fh McMess_MainProtocol+60 EA 20 38 79 jmpa cc_Z, mcMess_unknown3 McMess_MainProtocol+64 47 F8 25 00 cmpb rl4, #25h ; ... Var1:= pp (used as LSB address) McMess_MainProtocol+68 EA 20 64 79 jmpa cc_Z, mcMess_var1pp McMess_MainProtocol+6C 47 F8 26 00 cmpb rl4, #26h ; ... Var2:= pp (used as midB address) McMess_MainProtocol+70 EA 20 80 79 jmpa cc_Z, mcMess_var2pp McMess_MainProtocol+74 47 F8 2F 00 cmpb rl4, #2Fh ; McMess_MainProtocol+78 EA 20 9C 79 jmpa cc_Z, mcMess_unknown4 McMess_MainProtocol+7C 47 F8 31 00 cmpb rl4, #31h ; ... Byte (var1) of request table := pp McMess_MainProtocol+80 EA 20 FE 79 jmpa cc_Z, mcMess_var1reqtable McMess_MainProtocol+84 47 F8 34 00 cmpb rl4, #34h ; ... Preparing adjustment ("prefix function") McMess_MainProtocol+88 EA 20 08 7B jmpa cc_Z, mcMess_prefix McMess_MainProtocol+8C 47 F8 37 00 cmpb rl4, #37h ; McMess_MainProtocol+90 EA 20 26 7B jmpa cc_Z, mcMess_unknown5 McMess_MainProtocol+94 47 F8 38 00 cmpb rl4, #38h ; McMess_MainProtocol+98 EA 20 70 7B jmpa cc_Z, mcMess_unknown6_copy_bytes McMess_MainProtocol+9C 47 F8 3D 00 cmpb rl4, #3Dh ; McMess_MainProtocol+A0 EA 20 82 7B jmpa cc_Z, mcMess_unknown7 McMess_MainProtocol+A4 EA 00 B0 7B jmpa cc_UC, mcMess_unsupported_EB
etc..?
|
|
|
Logged
|
|
|
|
fluke9
Full Member
Karma: +26/-1
Offline
Posts: 113
|
|
« Reply #4 on: November 05, 2019, 12:51:27 PM »
|
|
|
Almost all of its subfunctions, and i did a patch to redirect the synctable to another address and introduce a len byte in front of it. So can log cranksync as many memory locations as i want to. I also patched out the stupid coding "mistake" they made that they read their own data as command (commands need bit9 set), if the receivebuffer has a byte without command bit it exits sync reading and tears down mcmess. 821B78 mcmess_routine: ; CODE XREF: McMess_Handler10ms+32↓P 821B78 mov [-r0], r12 821B7A mov [-r0], r9 821B7C mov [-r0], r8 821B7E mov [-r0], r7 821B80 mov [-r0], r6 821B82 sub r0, #0Ah 821B86 movb rl4, [r0+12h] 821B8A cmpb rl4, #2 821B8C jmpa cc_Z, readNewData 821B90 cmpb rl4, #4 821B92 jmpa cc_Z, readLowAddress 821B96 cmpb rl4, #7 821B98 jmpa cc_Z, readHighAddress 821B9C cmpb rl4, #0Bh 821BA0 jmpa cc_Z, readFromFlashMemory 821BA4 cmpb rl4, #0Eh 821BA8 jmpa cc_Z, readFromRAMMemory 821BAC cmpb rl4, #10h 821BB0 jmpa cc_Z, highspeed_readFromSyncAddressTable 821BB4 cmpb rl4, #13h 821BB8 jmpa cc_Z, notImplemented_13h 821BBC cmpb rl4, #15h 821BC0 jmpa cc_Z, notImplemented_15h 821BC4 cmpb rl4, #16h 821BC8 jmpa cc_Z, notImplemented_16h 821BCC cmpb rl4, #19h 821BD0 jmpa cc_Z, getStringECUEPK 821BD4 cmpb rl4, #1Fh 821BD8 jmpa cc_Z, readNextVerstellsystemVariable 821BDC cmpb rl4, #25h ; '%' 821BE0 jmpa cc_Z, setLowAddress 821BE4 cmpb rl4, #26h ; '&' 821BE8 jmpa cc_Z, setHighAddress 821BEC cmpb rl4, #2Fh ; '/' 821BF0 jmpa cc_Z, writeToRAMMemory 821BF4 cmpb rl4, #31h ; '1' 821BF8 jmpa cc_Z, highspeed_writeToSyncAddressTable 821BFC cmpb rl4, #34h ; '4' 821C00 jmpa cc_Z, setDataByte 821C04 cmpb rl4, #37h ; '7' 821C08 jmpa cc_Z, writeNextVerstellsystemVariable 821C0C cmpb rl4, #38h ; '8' 821C10 jmpa cc_Z, initializeVerstellSystemVaribles 821C14 cmpb rl4, #3Dh ; '=' 821C18 jmpa cc_Z, highspeed_gotoReadSyncValues 821C1C jmpa cc_UC, loc_8220B8
My logger works for me but needs my currently quite ugly patch. Want to do automated patching soon.
|
|
|
Logged
|
|
|
|
fluke9
Full Member
Karma: +26/-1
Offline
Posts: 113
|
|
« Reply #5 on: November 05, 2019, 12:58:11 PM »
|
|
|
I use the writing to memory function to fill my relocated table (used the memory normally used by define local identifier) and the crank sync routine is patched: 822450 MCMessSyncroPush: ; CODE XREF: CrankShaftSyncronousRoutine_sub_821226+9C↑P 822450 mov [-r0], r9 822452 mov [-r0], r8 822454 movb rl4, asc0_ComMode ; 0x1? == McMess 822458 cmpb rl4, #15h 82245C jmpa cc_NZ, _mcmh_out 822460 mov r8, S0RBUF 822464 movb nosync_TimoutCounter, ZEROS 822468 mov r4, #100h 82246C and r4, r8 82246E cmp r4, #100h 822472 jmpr cc_NZ, _ENDCOMM 822474 cmp r8, #1AAh 822478 jmpr cc_Z, _recv1AA_return_to_normal_mcmess 82247A mov r4, #10h 82247E or asc0_Bits, r4 822482 bclr S0TIR 822484 822484 loc_822484: 822484 calls 82h, mcmess_patched_transmit_8267E2 822488 nop lots of nops ;-) 8224C0 nop 8224C2 8224C2 _ENDCOMM: ; CODE XREF: MCMessSyncroPush+22↑j 8224C2 nop 8224C4 nop 8224C6 jmpr cc_UC, _mcmh_out
patched transmit routine (i just copied the original one to a keil a66 file and defined stuff need so i can produce my hex): $MOD167 $CASE $NOMACRO MAINCODE section code WORD PUBLIC 'MAINCODE' MAINPROC proc TASK INTNO RESET = 0
;__CSTART_PR SECTION CODE WORD PUBLIC 'CPROGRAM' ;?C_RESET PROC TASK C_STARTUP INTNO RESET = 0
mcMessSynchroTabPre EQU 0AA2Eh mcMessSynchroTab EQU 0AA30h mcMessSynchroTab2 EQU 0AA32h asc0_CommunicationBuf EQU 0E0A4h asc0_CommunicationBuf_1 EQU 0E0A5h asc0_ComMode EQU 0E07Ch asc0_Bits EQU 0E074h asc0_MaxToReceive EQU 0E076h nosync_TimoutCounter EQU 8EA2h word_380E86 EQU 8E86h transmitData_s0 EQU 821B4Ah
S0RBUF EQU 0FEB2h S0TBUF EQU 0FEB0h S0TIC EQU 0FF6Ch S0TIE BIT S0TIC.6 S0TIR BIT S0TIC.7 S0RIC EQU 0FF6Eh S0RIE BIT S0RIC.6 S0RIR BIT S0RIC.7
;MCMessSyncroPush: ; CODE XREF: sub_821226+9C?P ; mov [-r0], r9 ; mov [-r0], r8 ; movb rl4, asc0_ComMode ; 0x1? == McMess ; cmpb rl4, #15h ; jmpa cc_NZ, _mcmh_out ; mov r8, S0RBUF ; movb nosync_TimoutCounter, ZEROS ; mov r4, #100h ; and r4, r8 ; cmp r4, #100h ; jmpr cc_NZ, _ENDCOMM ; cmp r8, #1AAh ; jmpr cc_Z, _recv1AA_return_to_normal_mcmess ; mov r4, #10h ; or asc0_Bits, r4 ; bclr S0TIR
mov r8, #mcMessSynchroTabPre mov r8, [r8] mov r9, #1 loc_822486: ; CODE XREF: MCMessSyncroPush+4E?j mov r4, r9 shl r4, #2 mov r10, [r4+#mcMessSynchroTab] mov r11, [r4+#mcMessSynchroTab2] exts r11, #1 movb rl4, [r10] movb [r9+#asc0_CommunicationBuf], rl4 add r9, #1 cmp r9, r8 jmpr cc_C, loc_822486 bset S0TIE mov r4, #asc0_CommunicationBuf_1 add r8, #500h mov SRCP6, r4 mov PECC6, r8 mov r4, mcMessSynchroTab mov r5, mcMessSynchroTab2 exts r5, #1 movb rl3, [r4] movbz r2, rl3 mov S0TBUF, r2
rets
MAINPROC endp MAINCODE ends
end
McMess normally only supports 6 bytes to be read crank sync...
|
|
« Last Edit: November 05, 2019, 01:05:22 PM by fluke9 »
|
Logged
|
|
|
|
360trev
Full Member
Karma: +68/-2
Offline
Posts: 235
|
|
« Reply #6 on: November 05, 2019, 01:10:59 PM »
|
|
|
Impressive work.
Just found a small bug on your eepromtable finder... Some roms I have here have many more pages than your artificially set limit of 65...
I raised it to 129 and it works now successfully on 1mb roms with 2048 byte eeprom tables.
for (i=0; i < 129; i++) { unsigned short value = *((unsigned short*)(data + testaddr + (i*2))); ...
|
|
|
Logged
|
|
|
|
fluke9
Full Member
Karma: +26/-1
Offline
Posts: 113
|
|
« Reply #7 on: November 05, 2019, 01:16:43 PM »
|
|
|
Impressive work.
Thanks a lot, yours too! I have to find time to half polish my console application, so i can put it on github, right now its quite a (mc)mess/hackbed.. if you want to take a glimpse: https://gist.github.com/fluke9/697f264618ec5929cabd6211fc25b673Just found a small bug on your eepromtable finder... Some roms I have here have many more pages than your artificially set limit of 65...
I raised it to 129 and it works now successfully on 1mb roms with 2048 byte eeprom tables.
for (i=0; i < 129; i++) { unsigned short value = *((unsigned short*)(data + testaddr + (i*2))); ...
ohhh, did not know that that big eeproms exist, i introduced an arbitrary limit so that the output stops if the magic is missing in some bins. changed and pushed, thanks!
|
|
« Last Edit: November 05, 2019, 01:20:53 PM by fluke9 »
|
Logged
|
|
|
|
fluke9
Full Member
Karma: +26/-1
Offline
Posts: 113
|
|
« Reply #8 on: November 05, 2019, 01:25:42 PM »
|
|
|
|
|
|
Logged
|
|
|
|
360trev
Full Member
Karma: +68/-2
Offline
Posts: 235
|
|
« Reply #9 on: November 05, 2019, 02:22:44 PM »
|
|
|
You have a PM!
|
|
|
Logged
|
|
|
|
chill gates
Full Member
Karma: +2/-4
Offline
Posts: 84
I became a full member by talking to myself lol
|
|
« Reply #10 on: April 29, 2021, 06:06:10 PM »
|
|
|
Looks ground breaking. Impressive work. I'll def have to go alpha n for now but I'm coming back for ya eventually.... I'm gonna blow my motor up anyway
|
|
|
Logged
|
**** if your car wont start then you don't have to post logs....
|
|
|
nyet
|
|
« Reply #11 on: April 29, 2021, 07:09:29 PM »
|
|
|
I'll def have to go alpha n for now
SMH
|
|
|
Logged
|
ME7.1 tuning guideECUx PlotME7Sum checksumTrim heatmap toolPlease do not ask me for tunes. I'm here to help people make their own. Do not PM me technical questions! Please, ask all questions on the forums! Doing so will ensure the next person with the same issue gets the opportunity to learn from your ex
|
|
|
|