Intel Disassembly

by Michael Decipha Ponthieux
Posted: 2015-03-08
Last Updated: 2017-06-09

If you are considering performing disassembly I highly recommend to check out the EEC-V Master Hardware List first to make sure that you are not disassembling an already broken out strategy.

Binary Files

Hardware

In most cases, the only method of retrieving a clean unmodified bin is to extract the bin from the ecu. This can be achieved using a
Moates device such as the QuarterHorse for most all 1983-2004 EEC-IV and EEC-V Intel ECU's or the OBD-II to USB Adapter for most all 1996-2004 EEC-V Intel ECU's with OBD-II capability. Tomas Tomin also offers hardware for reading ECU's, more info can be had on his FORUM.

Software

At this time, the only known software available to extract a bin is TunerPro, Binary Editor software from Clint Garrity, and the ForDiag software from Tomas Tomin. If using Binary Editor, be sure when you license the software you pay the additional registration fees for the Quarterhorse or OBD-II flashing device. If you are using a simplified tuning program such as those offered by SCT, Diablo, HPTuners, etc... you will not have access to your actual binary file. In order to get a copy of your bin file you must submit a request to your tuning software provider. This should not be an issues but if they will not help you then your only option is to change tuning software to something you have full control over otherwise you have no way of manipulating your newly found parameters!

Padded Binarys and Swapped Banks

Before we can even begin to discuss the disassembly process we must first have a valid bin we can disassemble. This in itself can be extremely difficult before even beginning disassembly due to the fact that some software uses a full size bin of 64k per bank where the first 8192 bytes (0x2000 hex) of each bank is padded with null filler, whilst most software uses a non-padded bin of 56k per bank (224k 4 bank file). To fuel the fire, some software will swap banks 8 and 9 while saving the bin. This can make getting a true unaltered bin for disassembly very difficult. For reference a binary size chart is below.

Binary File Sizes
BanksHexbytesKB
10x 8 00032 768 32 k
10x E 00057 34456 k
10x10 00065 536 64 k
20x16 00090 112 88 k
20x1C 000114 688112 k
20x20 000131 072128 k
40x38 000229 376224 k
40x40 000262 144256 k
ECU Clock Speed - XTALHPS
MHzXTALHPSVehicles
274.003/04 Cobra, Lincoln, Crown Vic
233.0Lightning/Harley Trucks, most all 99-04
212.0
181.0
150.0most all single bank eec-iv from 89-95




Flat Memory Addressing

For reference, I have attached a quick reference table or a "cheat sheet" if you will, that will break down the memory differences between various size bin files and how to get to the actual flat addressing the binary is referencing. This table can be used to cross calculate memory addressing between non-padded 224k to padded 256k binarys with banks 8 and 9 swapped, as-is most commonplace. Note: 4 Bank EEC-V 256k binaries include the RAM (usually all filler =0xFF) 4 bank bin files are truly 216k with the end of bank 1 being used for RAM.
2-Bank MEMORY Addressing
BANK112 K Binary+/- OFFSET=256 K Binary+/- OFFSET=MEMORYBANKROM HEX DATA
FILLER0-FFFF0=0-FFFFX
FILLER10000-11FFF0=0-1FFF1
1 0-DFFF+12000=12000-1FFFF0=2000-FFFF127 FE
FILLER20000-21FFF-10000=0-1FFF8
8E000-1BFFF+14000=22000-2FFFF-10000=2000-FFFF8FF FA
FILLER30000-3FFFF0=0-FFFFX
4-Bank MEMORY Addressing
BANK224 K Binary+/- OFFSET=256 K Binary+/- OFFSET=MEMORYBANKROM HEX DATAASCii
FILLER0-1FFF0=0-1FFF
0 0-DFFF+2000=2000-FFFF0=2000-FFFF0FF,FA,27,FE,...,60,20,63` c
FILLER10000-11FFF-10000=0-1FFF
1E000-1BFFF+4000=12000-1FFFF-10000=2000-FFFF127,FE,0C,20,...'
FILLER30000-31FFF-30000=0-1FFF
91C000-29FFF+16000=32000-3FFFF-30000=2000-FFFF9FF,FA,27,FE,...60,20,65,...` e
FILLER20000-21FFF-20000=0-1FFF
82A000-37FFF-8000=22000-2FFFF-20000=2000-FFFF8FF,FA,E7,...

ADDING & REMOVING FILLER

ADDING FILLER
ROM BanksBinary SizeBankInsert 8192
bytes at:
Fill Address Range
Below with 0xFF ==
2
112k >> 128k8E0000000 E000 - 0000 FFFF
100000000 0000 - 0000 1FFF
4
224k >> 256k000000000 0000 - 0000 1FFF
11 00000001 0000 - 0001 1FFF
82 00000002 0000 - 0002 1FFF
93 00000003 0000 - 0003 1FFF
REMOVING FILLER
ROM BanksBinary SizeBankDelete 8192 bytes at
Address Range Below
2
128k >> 112k10000 0000 - 0000 1FFF
80000 E000 - 0000 FFFF
4
256k >> 224k80003 0000 - 0003 1FFF
90002 0000 - 0002 1FFF
10001 0000 - 0001 1FFF
00000 0000 - 0000 1FFF
Note: When adding or removing filler from 4 bank files, you may need to swap banks as-is most common for viewing on different software.

Quick Reference Conversion Chart

Note: When creating EDITING FILES from a 256k full size binary listing, to convert to 224k (EDITING ONLY), you simply add 0xC000 to ROM locations for bank 1.
Ex: [780c] + 0xC000 = [0x1380C]; see the Quick Reference Chart below for details.

2 BANK Address Quick Reference Conversion Chart
112k to MEMORY128k to MEMORY
112k Address=MEMORYBank=128k Address
0 xxx=2 xxx1=0 2 xxx
1 xxx=3 xxx1=0 3 xxx
2 xxx=4 xxx1=0 4 xxx
3 xxx=5 xxx1=0 5 xxx
8 xxx=A xxx1=0 A xxx
9 xxx=B xxx1=0 B xxx
A xxx=C xxx1=0 C xxx
E xxx=12 xxx8=1 2 xxx
F xxx=13 xxx8=1 3 xxx
11 xxx=15 xxx8=1 5 xxx
12 xxx=16 xxx8=1 6 xxx
13 xxx=17 xxx8=1 7 xxx
15 xxx=19 xxx8=1 9 xxx
16 xxx=1a xxx8=1 A xxx
18 xxx=1c xxx8=1 C xxx
4 BANK Address Quick Reference Conversion Chart
224k to MEMORY256k to MEMORY
224k Address=MEMORYBank=256k Address
0 xxx=2 xxx0=0 2 xxx
8 xxx=A xxx0=0 A xxx
D xxx=F xxx0=0 F xxx
E xxx=2 xxx1=1 2 xxx
F xxx=3 xxx1=1 3 xxx
10 xxx=4 xxx1=1 4 xxx
13 xxx=7 xxx1=1 7 xxx
14 xxx=8 xxx1=1 8 xxx
19 xxx=D xxx1=1 D xxx
1A xxx=E xxx1=1 E xxx
1B xxx=F xxx1=1 F xxx
1C xxx=2 xxx9=3 2 xxx
1D xxx=3 xxx9=3 3 xxx
21 xxx=7 xxx9=3 7 xxx
29 xxx=F xxx9=3 F xxx
2A xxx=2 xxx8=2 2 xxx
37 xxx=F xxx8=2 F xxx

Semi Automatic Disassembler (SAD) - EEC-V Bank Order Required

Currently, SAD requires 4 bank binaries to be configured such that the banks are saved in the binary as 0 , 1 , 8 , 9 using a 224k non-padded binary only. Otherwise, SAD will have a hard fault and cannot process the binary. Be sure to follow this bank arrangement for your comments file. However, to throw a little confusion in the mix, the directive file must be arranged by bank order 0 , 1, 9, 8 due to the process that SAD accesses the banks. If you configure this incorrectly all bank 8 comments will appear at the end of bank 9 and not where they belong, and all directive references will not be used.

<<<----- How to Swap Bank Order ------>>>

256k [0,1,8,9] (TunerPro Read) ---> 224k [0,1,9,8] (typical)

Most hex editing software like HHD's Hex Editor will not let you cut and paste without overwriting so you have to do it the difficult way.
You need to do 2 steps, 1st- remove filler, then swap banks 8 and 9.
REMOVING FILLER
Just as outlined above, delete filler starting at the highest address and work down.
fill 00030000 - 00031fff
fill 00020000 - 00021fff
fill 00010000 - 00011fff
fill 0 - 1fff
Now that you have a 224k bin you can simply swap banks 9 and 8 same as outlined above in the 224k details.
  • insert 57,344 bytes (0xE000) at 0x1C000
  • Cut 0x38000 [FF FA 27] to the end 0x46000
  • Then paste bank 9 there at 0x1C000, If done correctly, 0x1C000 will now have FF FA 27
  • Lastly, verify your bin stops at 0x37FFF for a max file size of 38,000 / 224 kb.

256k Bin [0,1,9,8] (typ. but w/ flr added) ---> [0,1,8,9] (needed for QH)

  • For a 256k bin add 65,536 bytes at 0x20,000 then
  • cut 0x40000 to the end of the ROM
  • paste it at 0x20000, which will now have FF FA 27

    256k Bin [8,1,0,9] ---> [0,1,8,9] (needed for QH)


    If banks 0 and 8 are swapped:
  • insert 131072 bytes at 0,
  • cut 40000 - 4ffff
  • paste at 0, then
  • cut 30000 - 3ffff
  • paste at 10000

    Be sure to always set the null filler to 0xFF to clear it
    fill 0 - 1fff
    fill 00010000 - 00011fff
    fill 00020000 - 00021fff
    fill 00030000 - 00031fff

224k Bin [0,1,9,8] (typical)---> [0,1,8,9]

If you have a 224k bin file with banks ordered 0,1,9,8 as is most common, to swap banks 9 and 8 simply:
  • CUT address 0x2A000 (which will start with FF FA E7) all the way to the end of the rom 0x37FFF and paste it at 0x1C000
    If your hex editor will not let you cut and paste,
  • insert 57,344 bytes (0xE000) at 0x1C000
  • Cut 0x38000 [FF FA 27] to the end 0x46000
  • Then paste bank 9 there at 0x1C000, If done correctly, 0x1C000 will now have FF FA 27
  • Lastly, verify your bin stops at 0x37FFF for a max file size of 38,000 / 224 kb.

224k [8-1-0-9] (database read) ---> 256k [0-1-8-9] (needed for QH)

  • add null filler infront each bank 0x8192 bytes at (2a000, 1c000, e000, 0)
  • add 65,536 at 0x000000
  • cut 0x30000 to 3ffff, paste at 0x0, banks now ordered 0-8-1-9
  • add 65,536 at 0x10,000
  • cut 0x30000 to 0x3ffff, paste at 0x10000, banks are now ordered 0-1-8-9
  • lastly, go FF out the null filler

224k [1-8-0-9] ---> 256k [0-1-8-9] (needed for QH)

  • add null filler infront each bank 0x8192 bytes
  • add 65,536 at 0x000000
  • cut 0x30000 to 3ffff
  • paste at 0x0
  • banks are now ordered 0-1-8-9

224k [8-1-0-9] ---> 224k [0-1-9-8] (224k typical)

  • add 57,344 bytes at 0
  • cut 0x2a000 to 0x37fff and paste at 0
  • banks now ordered 0-8-1-9
  • add 57,344 bytes at the end of the binary 0x38000
  • cut 0xe000 to 0x1bfff and paste it at 0x2a000
  • banks now ordered 0-1-9-8

256k >> 112k (readout of 2 bank conversion)

  • delete 0x00000 to 0x11FFF
  • delete 0xe000 to 0xffff
  • delete 0x1c000 to 0x2bfff (end of rom)

112k >> 128k

  • add 8192 bytes of filler at 0000e000, fill 0000e000 to 0000FFFF with 0xff =
  • add 8192 bytes of filler at 00000000, fill 00000000 to 00001FFF with 0xff =


Disassembler

Now that we have a valid bin its time to run it through the disassembler. For this example I will be using
FBFG2 (2004 Mustang GT) and AJAQ3 (95 Ford Ranger) There's a few disassemblers out there for the Intel 8061/8065 processors but the two most used are the Bill Lawrence Disassembler that has been around since the late 90s and the much much more recent SAD - Semi Automatic Disassembler by Andy "TVRFAN". The Bill Lawrence disassembler has been updated over the years and works flawlessly. The newer SAD Disassembler does a lot of the work for you and is much easier for the beginner to use. Not only that, its updated by the author so we can simply tell him any problem we have and he's pretty good about fixing it. A+++ in my book, the less work we have to do the better!!! So to begin, create a new folder named "disassembly" just to keep everything organized. Toss your extracted stock tune in there and name your binary file stock.bin, be sure to also toss in there a shortcut to the SAD executable.



Run the Disassembler
Now is the time to run your binary through the disassembler, File >> Open the binary in SAD and Tools >> Disassemble. Hopefully you don't get any hard faults and the disassembly completes.

SAD - _msg.txt - Messages

First things first, open up the message file stock_msg.txt and make sure theres no major errors. Scroll on down to the 2nd rbase list toward the end of the messages file. Now click just above it and scroll back up to the top, hold down the Shift button and Press A to select all of it and press backspace, you'll now see the rbase list at the top of the msgs file in notepad. Now scroll on down to the end of the subroutine list just beaneath it and deleted everything after the end of the subroutine list. You can do a simple Ctrl + F and pop up the find type in "---" and delete the entire line that those comments are noted. Now save the file as stock_dir.txt You now have a directive file to begin tinkering.

Directive File

The directive file is where you will assign labels to addresses you decode, this will make it MUCH EASIER to do disassembly since you can very easily see the PID name where a value is being used. The following is a quick cheat list of the temporary registers used in most EEC-V's. Copy and paste the following into your xxxx_dir.txt file at the top of the list just beneath the rbase parameters and before the subroutines:

SYM 24 "temp0l"
SYM 25 "temp0h"
SYM 26 "temp1l"
SYM 27 "temp1h"
SYM 28 "temp2l"
SYM 29 "temp2h"
SYM 2A "temp3l"
SYM 2B "temp3h"
SYM 2C "temp4l"
SYM 2D "temp4h"
SYM 2E "temp5l"
SYM 2F "temp5h"
SYM 30 "temp6l"
SYM 31 "temp6h"
SYM 32 "temp7l"
SYM 33 "temp7h"
SYM 34 "tmp1l"
SYM 35 "tmp1h"
SYM 36 "tmp2l"
SYM 37 "tmp2h"
SYM 38 "tmp3l"
SYM 39 "tmp3h"
SYM 3A "tmp4l"
SYM 3B "tmp4h"
SYM 3C "tmp5l"
SYM 3D "tmp5h"
SYM 3E "tmp6l"
SYM 3F "tmp6h"
SYM 40 "tmp7l"
SYM 41 "tmp7h"
SYM 42 "tmp8l"
SYM 43 "tmp8h"
SYM 44 "tmp9l"
SYM 45 "tmp9h"
SYM 46 "tmp0l"
SYM 47 "tmp0h"
SYM 48 "fgtmp0l"
SYM 49 "fgtmp0h"
SYM 4A "fgtmp1l"
SYM 4B "fgtmp1h"
SYM 4C "fgtmp2l"
SYM 4D "fgtmp2h"
SYM 4E "fgtmp3l"
SYM 4F "fgtmp3h"
SYM 50 "fgtmp4l"
SYM 51 "fgtmp4h"
SYM 52 "fgtmp5l"
SYM 53 "fgtmp5h"

SAD - _lst.txt - Listing

Now go back to SAD and click View >> Output File (or just open the stock_lst.txt file it created). Your disassembly listing should now be opened in notepad. At this time your probably wondering, where do I begin? Well that depends on who you ask, many start at the beginning and work their way through the code, me personally, I'm rather impatient and like to jump right to the good stuff as quickly as possible. The most important function in a Mass Air ECU is the Mass Air Flow transfer curve, so I jump straight to it :) The MAF transfer is VERY EASY to find. AFAIK, in all strategies (at least all that I've worked on) the MAF lookup code is identical. In your listing file, go up top and click on search and type in "LSSI_C". You want to keep searching until you find where interrupts have been disabled right before the LSSI is read. If it has, directly beneath LSSI_C you will see LSSI_B and LSSI_A being read as well and interrupts re-enabled. If you scroll down just below that a few operands, you will see a call to the interpolation routine.

Here is an example of the maf lookup in a 2 bank strategyHere is an example of the maf lookup in a 4 bank strategy
(CLICK TEXT TO ENLARGE)
(CLICK TEXT TO ENLARGE)
2 Bank MAF Routine 4 Bank MAF Routine

Verify MAF Transfer

On 2 bank ecu's, the call will have the function number in it being called, in the example above SAD automatically named the maf transfer function "Func16", you can verify that is the actual MAF transfer by going to that function number and looking at its values. For 4 bank ecu's the lookup routine will have the maf transfer address loaded into register 36 before the call is made. You can go to that address (2250 in the example above) and verify it is correct as well. In both cases the MAF function will be 30 rows long and start with an FF FF and end with an 00 00. Congrats! you've just found the most important function in the ecu!

Directive and Comments Files

Now that we know the maf transfer's address we can add that to the directive file along with the maf voltage register and name the maf and interpolation routines. In your disassembly folder where your tune is saved, right-click >> new text document, name it stock_dir.txt, while your at it create a stock_cmt.txt file as well.

Directive

In your directive file, you will want to assign the maf a name so it will automatically be labelled in the code, this will make life MUCH easier. To do so, you simply open up your newly created stock_dir.txt text file with notepad and enter the following.
subr9e210"subr_MAF"
func2250 22c71"func_MAF_Transfer":WV+12800:WV+1024

For detailed information reference
SAD.pdf for a full breakdown of the disassemblers functions.

The following quick reference charts are to quickly find the end address of a function and table to input in your directive file.
Table End Address
TblY RowsxX Cols
Table Size
Decimal SizeHex Size
Tbl10x12byte(*2)(120-1)= 11977
Tbl10x10byte(*2)(100-1)= 9963
Tbl9x11byte(*2)(99-1)= 9862
Tbl8x12byte(*2)(96-1)= 955F
Tbl8x10byte(*2)(80-1)= 794F
Tbl6x12byte(*2)(72-1)= 7147
Tbl6x6WORD(*4)(72-1)= 7147
Tbl6x6byte(*2)(36-1)= 3523
Tbl5x5byte(*2)(25-1)= 2418
Function End Address
FuncColumns
Function Size
Decimal SizeHex Size
Func30WORD(*4)(120-1)= 11977
Func13WORD(*4)(52-1)= 5133
Func12WORD(*4)(48-1)= 392F
Func12byte(*2)(24-1)= 2317
Func10WORD(*4)(40-1)= 3927
Func10byte(*2)(20-1)= 1913
Func8WORD(*4)(32-1)= 311F
Func8byte(*2)(16-1)= 15F
Func7WORD(*4)(28-1)= 271B
Func7byte(*2)(14-1)= 13D
Func6WORD(*4)(24-1)= 2317
Func6byte(*2)(12-1)= 11B
Func5WORD(*4)(20-1)= 1913
Func5byte(*2)(10-1)= 99
Func4WORD(*4)(16-1)= 15F
Func4byte(*2)(8-1)= 77
***Add HEX size to Start address to find end address.

Comments

In your comments file, you want to put notes as to what each line of code is doing, that way you can very easily work on the code without having to decipha what you've already deciphered. This will make the process MUCH easier in the long run especially when you walk away from the code for a while and jump back in it months later. So open up your newly created stock_cmt.txt text file with notepad and enter the following.
09e20|<--------------------------------->
09e20|MAF Subroutine
09e20|<--------------------------------->
09e66// MAF Transfer Function
12250// MAF Transfer Function

Repeat

Now that you've updated the comments and directive file, re-run SAD and check out the labels you've made. You will now see that its much easier to follow the code with comments and labels instead of memory address locations. Get used to re-running the disassembler, you will be repeating the disassembler indefinitely to resolve addresses to labels to make the process much easier.

Understanding Opcodes

Now that we have a segment of known code, we can go through and discuss the operation codes and what exactly the calculator "ecu" is doing. The following is a listing of the Intel 8096 opcodes adjusted for the 8061/8065 instruction set. The following data is the best known information available, there are no known publically released or available 8061/8065 instruction sets, thus the following was adapted from 8096 over the years.

8065 Opcodes
Obvious, any of the bank opcodes will not apply to single bank binaries.

The following is a very simplified list of the more common opcodes dummied down explaining what they do / how they work. It's most helpful if you are creating your own code or hacking away at the code. As you can infer, its aimed more toward the C / C++ programmers. For those not savvy in C and C++, anytime you see a bang "!" it means false / not (I.E. the result equates to ==0), any value other than 0 will return true.

HEX OpcodeC++Operation Comments
00 SKIPjump 1 location, kin to NOP, basically a NopNopjumps over 1 byte or "skips" the next byte, usually the following byte is a clear carry
01reg CLRWreg = 0sets 2 bytes to 0 clears word
05reg DECWreg--reg = reg - 1 used to decrease a value during loops
07reg INCWreg++increases value by 1 increments a word, 0++ = 1 not 2
08bitreg SHRWreg /= bit07 = / 128; 04 = /16 bit 7 = 10000000 in binary; usually used with /10 to convert from word scaling to byte for table lookup
09bitreg SHLWreg *= bit 07 = *128
0abitreg ASRWreg /= bit 03 = /8
0cbitreg SHRDWreg /= bit 05 = /32; 0a = /1024 0x400
0dbitreg SHLDWregL *= bit 07 = *128
10xx RBANKBank = xxReference Bank for next address
11reg CLRBreg = 0clears byte of data
17reg INCBreg++increments value by 1 increments one byte
20jj SJMPjump forwardjump forward jj locationsE7 is a GOTO / JUMP for direct addressing
22jj SJMPjump forward +200jump forward jj locations THEN jump +200
23jj SJMPjump forward +300jump forward jj locations THEN jump +300
24jj SJMPjump back -400jump forward jj THEN jumpBACK -400
26jj SJMPjump back -200jump forward jj THEN jumpBACK -200
27jj SJMPjump backjump forwards jj locations THEN jump back -100
28jj SCALLcall addresspushes current address to stack then jumps forwards jj
29jj SCALLcall address +100does the same as 28 but then jumps +100 more
2ajj SCALLcall address +200""
2bjj SCALLcall address +300""
2fJ3 SCALLscall lower address -J3
J3 Subtraction Addresses
HEX = SUBTRACT
14 = -EC
1c = -e4
2f = -d1
4f = -b1
7b = -85
8b = -75
b2 = -4e
ba = -46
c9 = -37
d4 = -2c
30regjj JNBif !Bit 0if bit0=0 then jj signed jump, if exceeds 7F jump backwards
31regjj JNBif !Bit 1if bit1=0 then jj
32regjj JNBif !Bit 2if bit2=0 then jj
33regjj JNBif !Bit 3if bit3=0 then jj
34regjj JNBif !Bit 4if bit4=0 then jj
35regjj JNBif !Bit 5if bit5=0 then jj
36regjj JNBif !Bit 6if bit6=0 then jj
37regjj JNBif !Bit 7if bit7=0 then jj
38regjj JBif Bit 0if bit0=1 then jj
39regjj JBif Bit 1if bit1=1 then jj
3aregjj JBif Bit 2if bit2=1 then jj
3bregjj JBif Bit 3if bit3=1 then jj
3cregjj JBif Bit 4if bit4=1 then jj
3dregjj JBif Bit 5if bit5=1 then jj
3eregjj JBif Bit 6if bit6=1 then jj
3fregjj JBif Bit 7if bit7=1 then jj
45xxyyreg3reg2 AD3Wreg2 = [reg3 + yyxx]
4bptrofreg2reg SB3Wreg = reg2 - [ptr+of] used to subtract a minimum from a current value
57reg2of2of1adr2 AD3Breg2= ad + [(reg2-1) + of1of2] used to follow up with comparison usually 0quick way to make sure value is greater than 0
5creg3reg2reg ML3Breg = reg2 * reg3 used to multiply byte registers and save the result as a word
64reg2reg AD2Wreg += reg2
65xxyyreg AD2Wreg += yyxx simply does addition on words sister is 75 for byte, subtraction is the opcode 69
66reg2reg AD2Wreg += [reg2] saves the value of reg2 and then increments reg2
69xxyyreg SB2Wreg -= yyxx subtraction for words addition is the opcode 65
6dxxyyreg ML2Wreg *= yyxx simple multiplication for words division is the opcode 8C
71hexreg AN2B reg (hex)bit=false both the current and hex bit have to be equivalent for the resulting bit to be set true, think of this as AND(1) if both bits are 1 the resulting bit is 1disables / turns off a bit
fe = bit 0 off
fd = bit 1 off
fb = bit 2 off
f7 = bit 3 off
ef = bit 4 off
df = bit 5 off
bf = bit 6 off
7f = bit 7 off
75hexreg AN2B reg += hex adds HEX to reg sister is 65 for word
7creg2reg ML2Breg *= reg2 multiplies 2 bytes used to multiply a byte by another byte register
7dxxreg ML2Breg *= xx simple multiplication of a byte by X value used for simple arithmetic
88regreg2 CMPWreg2, reg compare reg, reg2If reg2=0, instead of R0, just 0 will be compared
89xxyyreg CMPWreg, yyxx
8areg2reg CMPWreg, [reg2-1] compare reg, to reg2-1instead of comparing to reg2 and reg2+ (for word) it compares to reg2- and reg2
8bptrofreg CMPWreg, [ptr+of]
8creg2reg DIVWreg = regL /= reg2 divides a long by a word this may not be simple division
90reg2reg ORB reg |= reg2 used to OR compare 2 different bytes
91hexreg ORB reg ^ HexBits if either the current or hex bit is set, the result is a set bit ; think of this as OR1, if either bit is 1 the resulting bit is 1 used to turn on flags and pins
1 = bit 0 on
2 = bit 1 on
4 = bit 2 on
8 = bit 3 on
10 = bit 4 on
20 = bit 5 on
40 = bit 6 on
80 = bit 7 on
92[ptr]reg ORB reg |= [ptr] used to OR compare 2 different bytes
93ptrofsreg ORB reg |= ptr+ofs used to OR compare 2 different bytes
94reg2reg1 XORBreg1 ^ reg2 exclusive OR, think of this as a difference compare, if the bits are not equal the resulting bit is 1, if both bits are equivalent the resulting bit is 0 changes its state and flips it back
95hexreg XORBreg ^ HexBits toggles a bit changes its state and flips it back
97ptrofsreg XORBreg = reg^[ptr+ofs] toggles a bit changes its state and flips it back
98reg2reg CMPB(signed)
99xxreg CMPBreg, xx
9aR[ptr]reg CMPBreg, [Rptr] compares byte to pointer
9bptrofreg CMPBreg,[ptr+of] reg 0 will compare to 0
a0reg2reg LDWreg = reg2
a1xxyyreg LDWreg = yyxx could be val or pointer
a2reg2reg1 LDBreg1 = [reg2-1]; then reg2++ takes the value at that address, then the next loop increments reg2 used to get to the next address in an array
a3ptrofreg LDWreg = [ptr+of] special function only
a3ptr(-1)xxyyreg LDWreg = [ptr(-1) + yyxx] loads a RAM value to a scratch register used to compare RAM
a4xxreg ADCWreg += xx + c7 wtf is c7 ?
a5x1x2reg ADCWreg += x2,x1 + CY wtf is CY>
acreg2reg LDZBWreg = reg2
adxxreg LDZBWreg = xx
b0reg2reg reg = [reg2] (signed)
b1xxreg LDBreg = xx (byte)
b301xxyyreg LDBreg = [yyxx] copies the value out that memory [address]
b3ptrofsreg LDBreg = [ptr+ofs]
b3ptr(-1)ofs00reg LDBreg = [ptr+ofs] loads a byte of RAM into a scratch register used to get at an index
bcxxreg int
bdxxreg LDSBWreg = SSxx loads a word with a signed byte, bits 8 through 15 will be filled with the value of bit 7, either all 0 or all 1's
c2ptrxx STW[address++] = xx loads xx into pointer address, not into this actual address usually used for loops to clear data
c301xxyyreg2 STW[yyxx] = reg2 used to get to the upper RAM addresses 0xF000 inverse is A3 01
c3ptrofreg2 STW[ptr+of] = reg2 used to get to the lower RAM addresses 0x1000 special function only
c3ptr(-1)of00reg2 STWreg2 = [ptr(-1)+of] used to save a scratch register to a RAM address
c6ptrxx STB[address++] = xx loads xx into pointer address, not into this actual address usually used for loops to clear data
c7ptrof0 STB[(ptr+of] = 0 if xx==0 then no reg2 check used to clear a ram address
c7ptr(-1)ofxxreg2 STB[(ptr-1)+of] = reg2 note the ptr-1 to get lower address
c9xxyy PUSHWyyxx puts value of x1x2 at top of stack array
cbptrof PUSHW[ptr+of] puts value at address on the top of the stack array
cbptrof POP[ptr+of] removes value at the top of the stack array and saves it into the address
d1jj if <= reciprocol is > inverse opcode is DB
d2jj if (signed) > reciprocol is <= inverse opcode is DE
d3jj if < recipricol is >= inverse opcode is D9
d5jj if (!overflow) jumps if overflow==0
d6jj if (signed) >= jumps if >= inverse opcode is DA
d7jj JNEif != jumps if != inverse opcode is DF
d9jj if > recipricol is <= inverse opcode is D3
dajj if (signed) <= jumps if <= inverse opcode is D6
dbjj if >= jumps if < inverse opcode is D1
dejj if (signed) < reciprocol is >= inverse opcode is D2
dfjj if == jumps if == inverse opcode is D7
e0regjj reg--, if !=0, then jj, then jj-100 decrements reg (for loop) if !=0, jump forward jj then jump back -100used for FOR loops
e7jjj2 JUMPjump jj then j2 jumps forward jj then jumps again j2
efjjj2 CALLjump forward jj then j2 pushes current address to stack, then jumps forward jj then jumps again j2
f0 RETcall stack return address returns to the top address of the stack
f8 clear carry
fb EIenable interrupts
ff NOPno output jump self (do nothing), kin to SKIP burns a clock tic, useful for accurate repetitve timing


J2 Jump Addresses

<----Negative Jumps---->
9c=-6400
96=-6a00
97=-6900
88=-7800
a1=-5f00
a6=-5a00
ba=-4600
cb=-3500
ef=-1100
f0=-1000
f1=-f00
f2=-e00
f3=-d00
f9=-700
fa=-600
fe=-200
ff=-100
<----Positive Jumps---->
00=+0
01=+100
02=+200
04=+400
06=+600
07=+700
09=+900
0b=+b00
0d=+d00
0f=+f00
15=+1500
3b=+3b00
46=+4600
54=+5400
5f=+5f00
64=+6400
65=+6500
Note: Jumps are words that roll over within the same bank, a jump to 1XXXX will result in the 1 being omitted.

2's Complement Math

To understand bits, you need to understand how a byte is structured. A byte is a single register of data with a value from 0-255. A byte consists of 8 bits which is 8 "switches" in binary being that in binary you only have a value of 1 or 0, I.E. switch on (1) or off (0), or true (1) or false (0). 2s complement math can easily be broken down by understand the bits position and value. In a byte, the lowest bit (right most - bit 0) has a multiplier of 1. The first bit has a multiplier of 2, the 2nd bit a multiplier of 4, the 3rd bit a multiplier of 8, the fourth bit a multiplier of 16, the fifth bit a multiplier of 32, the sixth bit a multiplier of 64 and the final seventh bit a multiplier of 128.

So to break this down, we can do a few examples to make it easier to understand.
Binary=b7b6b5b4b3b2b1b0=decimal
00000000=0+0+0+0+0+0+0+0=0
00000001=0+0+0+0+0+0+0+1=1
00000010=0+0+0+0+0+0+2+0=2
00000011=0+0+0+0+0+0+2+1=3
00000100=0+0+0+0+0+4+0+0=4
00000101=0+0+0+0+0+1+0+1=5
00001000=0+0+0+0+8+0+0+0=8
00010000=0+0+0+16+0+0+0+0=16
00100000=0+0+32+0+0+0+0+0=32
01000000=0+64+0+0+0+0+0+0=64
10000000=128+0+0+0+0+0+0+0=128
11111111=128+64+32+16+8+4+2+1=255

Subroutine / Function Arguments

Some operations in the ecu such as doing interpolation look up or setting fault codes are very redundant, and to prevent an excessive amount of functions to do the same task, the ecu passes arguments to a function so it can carry out the task. Think of it as being variables modifying variables. In the RZAS0 binary there are only 3 functions that accepts these variable of variables "arguments". To define arguments in your directive file, simply go to the function or subroutine address and add : Y O +2 or : Y O +6. The # defines how many bytes are omitted after the function call and not used as code, that way the disassembler doesn't try to disassemble it. At this point, its not important whether the arguments are words or bytes, whats most important is that the disassembler can decipher code from arguments so you get a clean listing. For example in cbaza, you would have the following line in your directive file

subr 717c "717c" : Y O +4

which tells the disassembler anytime 0x717c subroutine is called to omit the followig 4 bytes since they are arguements and not code.

Definition File

A definition file is basically the same across all software. It maps the memory locations to human readable values. In order to add a parameter to your definition file there are a minimum of 6 values you will need to know.

PIDgood to have but a good name will suffice if need be
Address
Byte / Wordbyte (1 byte = =8 bits) or word (2 bytes == 16 bits)
Signed / Unsignedsigned allows negative numbers
Equation for example: x/2
Input/UnitLoad, ECT, ACT, VSBAR, etc..
TIP: I HIGHLY RECOMMEND to add your parameters to your definition file in order by memory address to keep them organized. Doing so will help prevent you from accidentally inputting the wrong address, it also makes it significantly easier to navigate, modify, and update your definition file and will save you thousands of hours.

Categories / Levels

I use the following categories as I've found its most effective for me and easiest to comprehend for most all users.
1Airmost commonly un-altered air parameters
2Emissionsmost purge and cat related parameters
3MAF / MAP / BAP<---
4Axle / VSS / Chassisratios axle etc...
5Fan <---
6Fuelfuel tables and modifiers including PERLOAD
7Adaptives<---
8DFSO / Failsafe Cooling <---
9Cranking / Startup<---
10Injectorinjector parameters
11OL / CLswitches flags and threhsolds to set status
12Pumpreturn and returnless params
13Transienttransient fuel
14Idle / Dashpot<---
15Knock Sensorall knock sensor related
16o2 / HEGObias amplitude and all o2 sensor related
17RPM / Limitersall limiters
18SecurityPATS disable sw and pats code
19Sparkspark advance params including engine size SARCHG
20Error Codesto quickly disable error codes
21System / Fail-Safe / OBDall obd params
22Scaling / Luggingall scaling functions
23Temp / Voltageect / act threshold and alternator params
24TP / WOTwot thresh and the like, any wot modifiers
25Manual Transgear ratios for manual usually and reverse lockout params
26Variable Camfor variable camshaft selections
27Unusedparams not referenced in the strategy
28A/C / Accessoriesa/c parameters and accessories like power steering params
29Hardware / Switchesfor quick tune setup adjustment of hardware present
30Console PIDscode modifying parameters not typically calibration constants, include all hacks here too
31Auto Transauto parameters
32Tuning / Engine / ConfigurationReference all of the important tuning variables here for ease of tuning.
33Temporary / Unknownquick add scalars for testing purposes and what have you
34Verifyany parameter you are unsure of being correct and need to verify or revisit
35VID Blockaxle ratio and options VIN number and pats code
36Catalytic Convertertypically the cat monitor parameters
37TQ Modulationspark limiting switches and shift functions
38EPC / TV Pressureengine tq table and slope and offset scalars
39TCC / Torque Converter Clutchfor the tcc lock and unlock speeds and scalar clips
40Shiftingfor quick auto adjustments
41Dynotypically just the lock tcc and trans in gear patch/switch
42Templatesinjector and maf quick load patches
43Reference Datafor other strategy binaries loaded into tunerpro compare to copy values
44Canister Purgecan purge emissions parameters
45ECU Clock

VID Block

The VID block is typically stored in the same location on all binaries. The VID block should be added to your definition file to give you full access.
VID Block Parameters
Parameter128k256kEquationComments
CAL_IDFF063xFF06ASCIIthe strategy and two letter calibration identification
PATS_CODEFF133xFF13HEXthe unique vehicle specific pats code
TAGFF633xFF63ASCIITAG - contains ford copyright info such as year
VINFF803xFF80ASCIIVIN - used for emissions testing and by some OBD-II scanners for vehicle info
VID_ENABLESW3xFF95X42 (0xA2) == VID block enabled, 255 (0xFF) == VID Block disabled
VID_REVMILE3xFF9AXvehicle tire revolutions per mile for information only, not used in any calcs
VID_RT_AXLE3xFF9CX/1024rear end gear ratio used for vehicle speed calc when the vid gear axle ratio switch is enabled

Important Addresses

These addresses are typical in most all 4 bank ecu's.
IMPORTANT ADDRESSES
AddressPIDCOMMENTS
1x2004ROM_TOchecksum
1x200ABIN_CHIP_IDcalibation id
1x2062AICE_VERS
1x2063AICE_SETR1_B
1x2064AICE_SETR1_C
1x2065AICE_SETR1_D
1x2066AICE_VRS_VAL
1xDF9AShadowing address for datalogging on mbus
8xFFDEPatch code to execute shadowing

Quick Find Code Blocks

The EEC's use the same code with tidbits of code added and removed over the years, this is what causes the different strategy names. Below is a quick reference chart of common code in most eec-v ecu's. This can be used as a cheat menu to quickly find segments of code your looking for specifically. This will be aimed more toward locatings payloads but it applies for calibration constants as well.
Quick Reference Code
PIDHEX SEARCH STRINGRZASA Addy / COMMENTS
ATMR1_HI_RESb0,3c,c4
IPSIBRb1,ff,34
ECT69,64,00,46
ACT64,36,40
SAFTOT
LOAD_FG
N79,04,3c
PERLOAD88,28,26
TP_REL
TOTLDST64,42,26
IMAF
VBAT_WORD8c,36,3c0xBCF2
DPFE
LAMBSE1b1,80,2d
KAMRF180,00,44or 65,80,00,44
IEGO1
DASPOT
ISCDTYa0,3c,40
VSBART_RT
BCSDCa0,06,36
SUBR_CONSOLE_CALL99,f2,34USED ABOVE FOR DATALOGGING PATCH
DASPTK44,3c,42,2c
SARCHG0c,01,48MAKE SUR YOU UPDATED THE NUMCYL REFERENCE ADDRESS!!!
Dashpot Decay FN87968,3c,2call dashpot in routine
XTALHPS71,03,3f9x30DD
UPDISCUPDATM in following routine
P1000
EGRHP
TQM_SWGear Axle Ratio and Rev Mile to follow
Crank_PW_Multb1,00,3a
Pump_Voltagead,09,38RFS routine
OL_Delay19,04,36
TP_OL_Threshold: 01,3e
FN1036a0,3c,26
FN1037a1,00,09,36
[code] JUMP_FRAC7c,35,34byte in code
[code] xx09,04,30CL idle modulation
[code] JUMP_MULT08,02,38
Slopes6e,ca,38
Offsetc0,2e,42
deltapa1,00,40,26
tc_under71,ef,34psibrn/m,etc...
WOT_Thresa0,27,46
fn012a0,37,46mbt routine
hsf91,40,a1fan values
crank pwb1,00,3a3rd or 4th from top, can find lambse values and a great many functions!!!
P100037,2a,03mil sw and force good code

Checksum

The ecu calculates the checksum to verify the ROM is not corrupt. To calculate the checksum the following addresses are summed up, if their value equals 0, then the checksum is valid.
Side note: The actual address the checksum is saved to is null since a correct checksum will return 0.
I recommend rewriting the checksum calc routine to include the higher range on older 4 bank strategies instead of cross calculating.
StrategyBank 0Bank 1Bank 8Bank 9ROM_TO
4-BANK (newer)2000 - FFFF12000 - 1DFFF22000 - 2FFFF32000 - 3FEFF12004
4-BANK (older)2000 - FFFF12000 - 19FFF22000 - 2FFFF32000 - 3FEFF12004
CDAN42000 - FEFF12000 - 1FFFF1200A
CBAZA2000 - FFFD200A
GUFB2000 - 9FFF200A
In all cases, the checksum is saved as an LSB 2-byte word using 2s compliment math.

TunerPro Checksum Calc

TunerPro will apply the checksum calcs STARTING with the FIRST ENTERED and working in order to the LAST ENTERED. The order they are added to the xdf is most important as the order they are displayed is not the order they are executed!!! Keep this in mind as you must ALWAYS enter in your checksum calcs in the correct order otherwise it will not function correctly.
Special Instructions
Special instructions include any background manipulation you need to complete to correctly calculate the checksum.
These must be performed first (ENTERED FIRST) otherwise they will incorrectly excute after the checksum has been calculated.
TitleStartEndStoreStore SizeData SizeLSBPlug-inCalcComments
XX --->Enter any Special Instructions first
SumBank02000FFFF3FFF022LSBDefaultTWOsSum of bank 0
SumBank1120001DFFF3FFF222LSBDefaultTWOsSum of Bank 1; Older Strats may only check up to 19FFF
SumBank8220002FFFF3FFF422LSBDefaultTWOsSum of Bank 8
SumBank9320003FEFF3FFF622LSBDefaultTWOsSum of Bank 9
SumErr3FFF03FFF73FFF822LSBDefaultSumSum of All Banks
SumOld12004120053FFFA22LSBDefaultSumCopy old checksum
Checksum_ROM3FFF83FFFB1200422LSBDefaultSumSave New Checksum to ROM
CleanupB32000320003FFFB11LSBDefaultSumSet Null filler back to FF==null
CleanupA32000320003FFFA11LSBDefaultSumSet Null filler back to FF==null
Cleanup932000320003FFF911LSBDefaultSumSet Null filler back to FF==null
Cleanup832000320003FFF811LSBDefaultSumSet Null filler back to FF==null
Cleanup732000320003FFF711LSBDefaultSumSet Null filler back to FF==null
Cleanup632000320003FFF611LSBDefaultSumSet Null filler back to FF==null
Cleanup532000320003FFF511LSBDefaultSumSet Null filler back to FF==null
Cleanup432000320003FFF411LSBDefaultSumSet Null filler back to FF==null
Cleanup332000320003FFF311LSBDefaultSumSet Null filler back to FF==null
Cleanup232000320003FFF211LSBDefaultSumSet Null filler back to FF==null
Cleanup132000320003FFF111LSBDefaultSumSet Null filler back to FF==null
Cleanup032000320003FFF011LSBDefaultSumSet Null filler back to FF==null
VID BLOCK CHECKSUM
CLR_VID_3FFFC
CLR_VID_3FFFD
3FFFC2'sLSB
Note: 3x2061 typically contains 0x00 on most all EEC-Vs, this is needed to clear the checksum in order to correctly calculate the new.

Equation (useable fractional digits)

The following is a quick reference list for useable digits AFTER the decimal, this is important when creating a definition file so users can accurately change values without a loss of resolution.

USEABLE FRACTIONAL DIGITS & EQUATION REFERENCE CHART

*(recip)(pwr)EquationDigitsComments
ByteWord
0.52^1X/21typically vehicle speed
0.252^2X/40 (or ~2)0 (or ~1)typically spark or RPM, if RPM set decimals to 0
0.1252^3X/810 (or ~1)typically timers
2^4X/16~0 (or 2)RPM but also used for scaling =0, volts=2
2^5X/322usually Airmass but also idle speed
XX/502typically relative throttle voltage TPREL used for trans functions
2^6X/6422typically trans related specifically TP_REL
2^7X/12832typically lambse and tq
2^8X/2563 or ~0this is usually used for scaling and trans related
2^9X/5123typically accel rate or multiplier modifiers
2^10X/10243typically ratio
2^11X/20486typically dashpot
2^12X/40964typically isc airmass
2^13X/81924usually hego bias
XX/128003typically voltage
2^14X/163844typically ratio related to trans
2^15X/3276835typically load but also duty cycle=3, gain=5
2^16X/655365typically timers
2^18X/262144XXX
2^25X/335544327typically fuel mass for injector breakpoint
XX/75497472003typically lbs/hr for injector slopes
MULTIPLICATION WILL ALWAYS HAVE 0 USEABLE DIGITS

Multi-addressed variables

Many scalars in the EEC-V's have multiple addresses to achieve the same value. This is due to the code actually having the value present rather than performing a look-up to a scalar. This makes the code more efficient. In these cases, I highly recommend using the PATCH type paramater in tunerpro and add all the addresses to the patch so they are all changed at once. The Rear Hego Present scalar is a perfect example, in RZAS0 this scalar is reference in 21 different locations!!!!! You can simply assign the patch with a value of 0 to disable the hegos and a non-patched value of 2 to allow the rear hegos (stock h-pipe). This can be done for any switch type scalar, in more complex scalars like the injector slopes for example, this cannot be done since the value must be inputted.

Hacks

A "Hack" is simply a modification to the code that was never intended to be performed. It is often common to swap operands when 'hacking' to make a function perform differently. When doing so, an enumerated value should be used, however, I have my own decipha exclusive equation I'll share below.

Decipha Exclusive Equations / Elude Enumeration

When adding new scalars for hacks, I use the following equation (this is a decipha exclusive) and not recommended
(x-lower value) / [remainder of high-low]
so lets say you have
22610 stock value
8584 is your new hacked value

22610-8584 = 14026, This gives us an equation of:

(x-8584)/14026

a value of 1 = 1*14026; 14026 + 8584 = 22610 (stock)
a value of 0 = 0*14026; 00000 + 8584 = 8584 (hacked)

thats how I make my scalar switches 0.000 and 1.000 to alter opcodes and what not, if using BE be sure to add at least 3 decimal places and limit the value range from 0 to 1 to prevent any corrupt values from accidentally being loaded. The decimals make it easy to see if the value is corrupt. If using TunerPro YOU CANNOT USE THIS EQUATION since TunerPro will not prevent someone from inserting decimals between 0 and 1. For TunerPro enumarations, I recommend using the PATCH data type. Then just assign your data there with an enable/disable button simple enough.

TunerPro Value Equation for Automated Hide / View

When creating hacks such as moving or extending scaling function for more resolution you will need a new table parameter to show the new scaling of your new function. This can be tricky since users that do not have your patch enabled will be viewing the incorrect values. However, decipha has a fool-proof solution that will make it easier for everyone. Tunerpro has an excellent feature that allows you to reference a value for arithmetic. This will solve our patch/hack problems from causing the wrong scaling to be viewed. By creating two exact copies of the same table one with the old scaling (for reverse compatibility) and one with the new, you can use this equation to 0 out the table not in use. This will make it very easy to identify which table scaling is in use.


so for example, lets say one of the bytes of your modified code is now 0x04 and the prior stock value was 0x00.
The following equation will show you how I invert the value so high and low are swapped.

For example lets say your actual table equation is:
X / 128

The following will hide and display the tables automatically based on your manipulated code

Extended Table Equation Modifier
Y==4; X / 128 * (Y / 4) = 1 = multiply the equation by 1 = correct viewing
Y==0; X / 128 * (Y / 4) = 0 = multiply the equation by 0 = result is all 0s, table is 'hidden'

To INVERT for Stock Table Equation Modifier
Y==4; X / 128 * ((((Y -4) *-1) +0) / 4) == 0 == result is all 0s, table is 'hidden'
Y==0; X / 128 * ((((Y -4) *-1) +0) / 4) == 1 == correct viewing

Why the +0 ? So that the table doesn't display negative values

Check out the FN904 Sealevel Spark Table and Extended Table in my GUFx def file to see it in action based on if the FN071_EXT patch value.

Datalogging

Datalogging can simplistically be broken down into 4 basics, 1- disrupting the code, 2- executing the patch code, 3- shadowing payloads, 4- reading/polling with the QH With the new "Universal" ADX datalogging its simplified significantly. This will prevent errors when jumping between strategies and makes it very easy to create datalogging files. The patch code stays consistent for all defs, the only variable that MAY need to be updated is the "moved bitmask" that you took out the console routine to call to the patch code routine. Once you've located the console call routine, insert your CALL to address 8xFF57. If your console call routine is not within' bank 8 you will have to update the patch code. I have listed patch codes for the logging list and patch in different banks to make it easier to implement. Part 1 - RAM Addresses

Payload Order List @ 0xFE98


The following is the ORDERED list that MUST be used for the Universal ADX to function correctly.
Note: that the list is shown from top to bottom with the MSB first as-is displayed exactly in TunerPro as I have it specifically listed to for simplicity and to prevent errors.

NOTE: To skip over a word address insert FFFF, if that address is to be used for two bytes defined in list C. If you do not have the word address for a value set the address to FFFE which will zero out that value to clean up the logged parameters and make it very easy to identify which parameters are not being logged.

List A - Word Shadowing - Payload List at 0xFEE0
Descriptions
OffsetPIDXX Address XXEquationUnits
00 00 == STOP MUST BE HERE to END MARKER LIST A
PSPT voltage6C was 30PSPT_CNTS0180/64ADCnts
BAP sensor voltage6A was 3EBP_CNTS0186/64ADCnts
MAP sensor voltage68 was 38MAP_VOLTS14FA/1024Voltage
knk sensor 2 voltage66 was 4CKNKTST_A2D1710XVolts?
Fuel Level Sensor Input ADCts64 was 52FLI_CNTS0152/64AdCnts
Fuel tank pres transducer voltage62 was 4ATPR_CNTS0176/64ADCnts
Est Fuel Consumption60 was 48FLI_FUEL_SUM148E/33554432lb/m
deciphas enrichment fuel5E was 42LOST_FUEL__AF112/32768Lambse
Feeback Spark5C was 56SPK_ACTUALF0DE/4dBtdc
Calc pump fuel flow5A was 54FP_FLOWRATEF322/16384
Fuel Rail Pressure58 was 50FIP_DELTAF0F2
modulated fuel pump dutycycle56 was 40FPUMP_DC1132/32768%duty
spk_bdl_act_retard54 was 6AFN725A_ACTF225
filtered Acceleration Rate52 was 68VS_RATE1274/ 512MPH/sec
target AFR50F_A_RATIO101B2/32768AFR
Spark Source4E was 3ASpark FlagsFFFF
SPK_SOURCEXRef
Trans RPM4C was 66NEBART1210/ 4RPM
trans Input/Output Ratio4A was 64SPD_RATIO1226/16384Slip Ratio
Trans oil temp48 ws 62TOT02AC/8Temp F
Engine Tq into TCC46 was 60TQ_NET129A/ 0.5ft/lbs
Trans Line Pressure44 was 5ETrans FlagsFFFF
TV_PRES/2psi
Gear Commanded42 was 5CGR_CM1288/2Gear
OSS RPM40 was 5ANOBART1264/4RPM
TCC PWM DutyCycle3E was 58BCSDC1230/32768TCC_DTY
total fault codes stored3C was 3CNUM_CODES077AXX
hego2 voltage3A was 36IEGO210164/64
driver side ltft38 was 34KAMRF207A6
driver side stft36 was 32LAMBSE2012A
knk sensor 1 voltage34 was 4EKNKTST_A2D_21712XVolts?
transient fuel time const32 was 46EFUEL/TFC_TAU or TSIEF01B6512sec?
transient dynamic fuel trapped fraction30 was 44EFTRFF/TFC_DYNX or AEFUEL01B8512%
desired idle rpm2EDSDRPM / PDLFFFF
injector pulse width2CFUELPW1012C/ 0.5pw (in ticks)
2A
APT,ISCFLG = FFFF
throttle position voltage28TP0122/64ADCnts
battery voltage26VBAT / CHT (IAT2)FFFF/16Volts
24**FLAGS** --------------------- FFFF
vsbart is mph calculated from oss22VSBART_RT / VSBARFFFF/2MPH
isc duty20ISCDTY012632768%Duty
dashpot airmass1EDASPOT1418/4096lbs/min
hego1 passenger1CIEGO11015C/64ADCnts?
passenger ltft1AKAMRF107A4256Err%
passenger bank1 STFT18LAMBSE1012832768Lambda
dpfe voltage?16EPTBAR / IEVP (WBo2)014A/64ADCnts
raw maf voltage14IMAF (VMAF)017E64ADCnts
inferred load (not PCT_LOAD)12TOTLDST or MAPF018/32768LOAD
filtered TP_REL for shifting10TP_SS_L / RATCHF38C/64ADCnts
percentage of load0EPERLOAD or MAPPA1372/32768%load
Filtered RPM0CNE03EA/4RPM
engine VE0ALOAD or MAPOPE0134/32768Load
spark advance08SAFTOT1794/4dBtdc
airmass flow06AM134C/1024lbs/min
temperatures04ACT = 05
ECT = 04
FFFF must be done per byte in List B
CL idle isc correction02IPSIBR140E/4096lbs/min
engine run timer00ATMR3_HI_RES15FEXsec


REMEMBER: FFFF skips that address for byte or bitmask manipulation.
and FFFE zeros that value for unlogged words.
Part 2 - Copy MSB to LSB for odd addesses.
Again, start at the bottom and work up to the top, and most importantly, don't forget to put the Quad 0s to mark the end of the list and continue on to C.

LIST B - SHADOW BYTES
ParameterAddress
0000 == STOP, END MARKER FOR LIST B
C04E
SPK_SOURCE0637
C046
TQ_NETxxxx
C044
TV_PRES1297
C042
GR_CMxxxx
C02F
PDL1270
C02E
DSDRPM1449
C02B
ISCFLG144D
C02A
APT00D0
C027
CHT or IAT211EF
C026
VBAT0763
C023
VSBAR11CF
C022
VSBART_RT127D
C005
ACT007B
C004
ECT0079



Part 3 - Bit Comparisons
NOTE: Bits can only report when they are on, anything in the off state will
not show an indicator so FFFE can zero out unlogged bytes/words/bits and not
set an incorrect flag button.

REMEMBER: C0XX == offset to copy to
Bit Flags Reference Values
Bit-0Bit-1Bit-2Bit-3Bit-4Bit-5Bit-6Bit-7
0102040810204080


List C - Shadow and Stack BitFlags - C024, C025, C043, C045, C047, C04F
C04F
INJ8_FAULT
Bit 7
4F02
0071
INJ7_FAULT
Bit 6
4F01
0071
INJ6_FAULT
Bit 5
4F20
0071
INJ5_FAULT
Bit 4
4F10
0071
INJ4_FAULT
Bit 3
4F02
0070
INJ3_FAULT
Bit 2
4F01
0070
INJ2_FAULT
Bit 1
4F02
006F
INJ1_FAULT
Bit 0
4F01
006F
C045
FLASH_TCIL
Bit 7
4580
03B6
DO_KOEO_TST
Bit 6
4520
00BE
FLG_ADAPT_RST
Bit 5
4501
13F4
FLG_OLUP
Bit 4
4510
00B0
BOO_LVL
Bit 3
4508
0058
DSFFLG
Bit 2
4580
00B1
CL_THRTL
Bit 1
4580
00D0
OCTADJ
Bit 0
4540
13F2
C025
MISFIRING
Bit 7
2502
00B8
MIL
Bit 6
2508
006C
LEGOFG11
Bit 5
2580Hego 1 not swtiching
07C2
KNOCK_DETECT
Bit 4
2520
00A5
KNK_FMEM_2
Bit 3
2502
07C2
KNK_FMEM_1
Bit 2
2510
07C4
FRP_FAULT
Bit 1
2580
04D6
MASTER_KEY
Bit 0
2520
1757
C024
OL_DES
Bit 7
2402
0094
NDSFLG
Bit 6
2480
009D
LSF
Bit 5
2480
0377
HSF
Bit 4
2480
014F
ACCFLG
Bit 3
2404
00C1
FUEL_IN_SYNC
Bit 2
2480
008E
UNDSP
Bit 1
2404
0098
WOT
Bit 0
2401
0090


To summarize:

first words are payload adresses - List A
second bytes are copying high to low - List B
3rd bits are copying bits flags to 0 - List C
Note: Max Polling Limit of the QH is 102 bytes, 0xC000 to 0xC066
below needs to be updated
We saved the best for last, now that the patch is written we are ready to start requesting RAM addresses to poll. But not just so fast there young grasshoppah, it is very important that you keep track of the order in which you poll your addresses. If you have setup the patch code with registers in the correct order then you are done! Simply enable the datalogging patch code in your tune and use the DECIPHA.ADX datalogging file to datalog. The following is the ACTUAL functioning of the datalogging in detail for your knowledge.

8065 REGISTERS are from 0x000 to 0x3FF, the QuarterHorse cannot access those addresses directly. Directly addressable RAM begins at 0x400 on up. Since you cannot access the ecu's REGISTERS directly, In order to datalog these registers you must write patch code to copy/shadow REGISTERS to MBUS where they are visible. For simplicity and to reduce errors, the majority of the QH_CONFIG can be reused from the available strategy files, but for the sake of understanding, I will break down exactly what is going on so you have a much better understanding of it and can write your own datalogging files for the strategy your working on. The QH Write Patch command is fairly simple once you know how it works.

I highly recommend referencing the DECIPHA.ADX file to follow along. The following applies to the Quarterhorse from Moates.net using Tunerpro RT.

To follow along open up the ADX Editor in TunerPro and cruise on down to Commands >> Configure QH for Payloads [QH_CONFIG] tab

I highly recommend overwriting the console routine and using a 0xC000 offset for datalogging.

< 0 > Configure QH for Payloads [QH_CONFIG]

This is the actual list of steps IN ORDER that TunerPro will perform to datalog and MUST ALWAYS be in this exact order:

TunerPro Command Structure
  • 1
  • (Pause for Data Rate) 100msec [WAIT]
  • 2
  • reQuest QH Packet
  • 3
  • Reply to Q - 400 msec (0x4F)

    < 1 > Pause for Data Rate

    Pause for Data Rate; just as it states, the QH must reply with its data rate before anything can function, its nothing more than a 100ms wait timeout

    < 2 > reQuest QH Packet - KEEP TRACK OF OFFSETS!!!!

    The order in which the addresses are polled below will determine the TunerPro offset for each VALUE so when it comes time to configuring the values you must keep track of the offset they are at. This is a VERY TEDIOUS PROCESS THEREFORE, If you poll your payloads in the order I have defined below then you can use my DECIPHA.ADX and the hard part is already done for you!!!!!!!! I recommend you log all the critical payloads I have defined below in the ordered layed out. You can then log any additional payloads as you desire AFTERWARDS. If doing so, be sure to you configure a new dashboard for your additional values.

    Also note, the QH has a hard poll limit of 126 bytes, I have concluded that the most efficient way of maximizing on the total amount available is to poll 54 WORDS 16 BYTES and 16 BITFLAGS. I have created my TunerPro dash to accept 70 payloads, I highly recommend you follow suit as it is a significant time investment to create an in depth dashboard. I will keep the RAM addresses here to personally keep track of the payloads and value offset but also for others to reference. If you look at the registers you'll see many are in the same location throughout most if not all strategies. This can give you a head start in many cases. If you do develop any datalogging support I highly encourage you to send me your identified addresses and I will add them here. It makes it much much easier to keep track of everything.
    NOTE: Only addresses in the 0x000 - 0x3FF range must be shadowed up above in the 2nd step of writing the patch code "INSERT Registers Payloads." I shadow all registers even upper memory which is directly accessible over the MBUS because it allows me to have a "STANDARD" offset for payloads.



    51 is the Query code in ASCii = Q
    0x5c is the sum of elements to poll, 0x5c = 92 bytes

    NOTE: 0x5C == 92 is the maximum bytes of data the QuarterHorse can poll per Query.

    0x01 0x01 0xC0 0x65
    read 1 byte(s) from QHRam1 address C065; this has an offset of 0 since it is the first address being queried
    keep in mind, the address requested will be polled in the order you query them


    0x01 0x01 0xC0 0x65 = offset bytes 2 and 3
    0x02 0x01 0x00 0x23 = offset bytes 4 and 5
    0x02 0x01 0x00 0x27 = offset bytes 6 and 7

    0x01 0x01 0x02 0xA8
    read 1 byte from ""RAM1"" address 02A8, this has an offset of byte 8 (which you don't need to know, but for more understanding, it's shadowed at 1xDD98)

    0x02 0x01 0x02 0xC0 = offset 9-10, since the prior address was only 1 byte, these byte will be placed in the next address, 1xDD99 to 1xDD9A

    0x01 0x01 0x03 0x6F = offset byte 1

    and so on and so fourth...
  • 8>Payloads - RAM ADDRESS LIST This is where the RAM Addresses are shadowed, reference the Payloads section for the list of RAM Addresses.
  • 9>Config Reply to Q request a reply and that patch code is complete, now its time to move on to the "Values" and add in the payloads, be mindful of your offsets and byte sizes!!!

    < 2 > Insert Register Payloads

    57 36 05 DF 9A 4E 00 78 00 ....CONTINUE ADDRESS LIST OF REGISTERS...

    0x57 is W in ASCii which is the QH command to WRITE
    0x36 is the # of RAM BYTES in HEX of the code to be copied to shadow memory ( 2 bytes taken per register )
    0x05 is the QH MEMORY SLOT to write the patch, see the table below for reference.

    QH Write Modes
    Note: 0x05 is to write up to a 256 bytes at a time, you can also write to 0x15 if you choose to write a patch for each byte!!!! Wayyy too time consuming to even be considered. Again, with 0x05 you can only write 256 bytes at a time, if your patch code is longer than that you'll need to split it up into more Send Commands.

    The QuarterHorse command mapping is listed in the table below for reference.
    QH MEMORY MAPPING
    01= QH Memory Bank 1
    05= ROM Bank 1
    15= ROM bank1 (1 byte)
    06= ROM Bank 8
    16= ROM bank8 (1 byte)
    07= Upper Memory (single bank tunes)
    0xYYHSB of address YYzz to write patch code
    0xZZLSB of address yyZZ to write patch code
    Note: single bank EEC-IV use bank 07 as the code goes at the top of RAM.

    8xDD6A is the actual ROM location where the payloads are to be written, for my patch, bank 8 is what we are going after. Keep in mind, this patch will most likely work for 99% of all 4 bank strategies but you MUST VERIFY this address contains null filler and no code. Note: Usually, only the inserting jump to patch code address would need to be updated to be within the main loop later down in "Step X - Write Patch Routine".

    These address are the RAM registers you wish to datalog, note that they are LSB first as thats how the Intel ECU accesses ROM.
    AC 02 // TOT
    00 00 // MARKER FOR END OF LIST
    00 00 // MARKET FOR END OF LIST

    IMPORTANT NOTE: make sure you do not shadow into RAM!!! RAM is from 1xE000 to 1xFFFF, shadowing in ram will corrupt the ecu and cause odd behavior!!! 1xE000 - 1xDF9A = 0x66 == 102 bytes, highly unlikely you'll ever have that many payloads in the 0x000 to 0x3FF range but noteworthy.

    Note: The addresses above are ONLY in the 0x000 to 0x3FF range where registers are inaccessible on the MBUS and must be shadowed. All addresses 0x400 and above will be read directly in Step 6

    < 3 > Reply to Q

    < 4 > Insert Jump to Patch Code / (BE - QHorse tab in XLS)

    For my code, I chose to 'splice' a jump to my new datalogging patch code routine at the tail end of the console routine (8xF66F), you can insert a jump wherever you wish or find most reasonable. I highly recommend using the console routine, it can very easily be found by searching for "= 2062" in your disassembly, you will see another scratch register being set to "= f0" directly beneath it for the rom pointers to be loaded. You want to go to the end of that routine where it 'returns' with the 0xF0 op-code. Usually just before that op-code there is a flag being set that is 3 bytes in length including the op-code. You can rewrite that line and jump to null filler at the end of bank 8 to execute the datalogging patch code. In RZASA, 8xFFDE is tail end of null filler at the end of bank 8. And 8xF66F is the console routine with the line that contains the code we will overwrite to jump to our new patch code routine.

    f66f: 71,ef,90 an2b R90,ef ATMR2_FLAG &= ef;
    ^^ must save the above and put it at the end of the shadowing patch routine so its executed.

    I will rewrite this with
    f66f: ef,6c,09 scall 8xFFDE
    so to do so we simply enter it in...

    0x57 0x03 0x06 0xF6 0x6F 0xEF 0x6C 0x09
    57 is W in ASCii = Write
    03 is the number of bytes to be written
    06 is the QH memory slot which corresponds with rom bank 8
    F6 6F is the ROM memory location 8xF66F to write the following code
    EF 6C 09 is the code to be written

    EF 6C 09 in intel disassembly is an 0xEF= call to +0x6C, so being that 8xF672 is the next location +0x6C = F6DE, and 0x09= +0x900; F6DE+0x900 = 8xFFDE is being called.

    < 5 > Reply to Q

    < 6 > Write Patch Routine

    I recommend using the console routine to execute your patch code. If you cannot do so for whatever reason, in mosy 4 bank defs, 8xFFDE is null filler at the very end of bank 8 where I recommend writing your patch code. This should work for all eec-v ecu's as code is not normally written to the very tail end of bank 8.

    57 20 06 FF DE A1 9A DF 42 8A 42 00 DF 13 A2 42 46 A2 46 44 65 00 C0 46 C2 46 44 65 02 00 42 27 E8 71 EF 90 F0

    57 is W=Write
    20 is the number of bytes to write (32 bytes == 0x20 in hex)
    06 is the QH memory slot == bank 8 from reference chart above,
    8xFFDE is where we are writing the following new subroutine we are creating for the patch code to execute within the rom's code
    0xA1 and onward is the actual patch code to write (0xA1 is the load word op-code in intel assembly)
    9A DF using Intel LSB == DF9A, this is the address where we wrote our register list of addresses to log

    Now you've reached the point where you need to actually start writing some patch code, or just reuse this.

    The following is the actual datalogging patch code in my decipha.adx file. Keep in mind, this can be reused on other strategies with only the shadowing address needing to be updated if changed.

  • Patch Code
  • This is the actual patch code written in Intel Assembly
    A1 9A DF 42 // r42 = DF9A // shadowing address
    8A 42 00 DF 13
    A2 42 46
    A2 46 44
    65 00 C0 46 // Offset Address 0xC000 is visible on the MBUS for shadowing
    C2 46 44
    65 02 00 42
    27 E8
    71 EF 90 // code overwritten in console routine to insert jump to new patch routine
    F0 // return back to console routine and execute normal ecu code flow

    Note: The datalogging offset 0xC000 is the ACTUAL QH RAM ADDRESS, there is no additional offset added and it IS NOT added to the Base Address!!!!
    Skip down to step 7
    ----------------------------------------------------------------------------------------------------------------------------------------------------------------
    The following is for reference only
    CBAZA Patch Code
    The following is how the cbaza patch code functions for datalogging for referece, special thanks to derek fenwick for creating this and sharing.

    d6d5: a1,08,d7,42 ldw R42,d708 R42 = d708; // list of registers to shadow to mbus
    d6d9: a2,43,14 ldw R14,[R42++] R14 = [R42++]; // 14 = register address
    d6dc: a2,14,1c ldw R1c,[R14] R1c = [R14]; // 1c = registers value
    d6df: c3,15,00,0d,1c stw R1c,[R14+d00] [R14+d00] = R1c; // shadowed =register+offset = value
    d6e4: 8a,42,00 cmpw 0,[R42] // check 0 to stop loop
    d6e7: d7,f0 jne d6d9 if (0 != [R42]) goto d6d9; // loop until reached end of list
    d6e9: a1,22,20,14 ldw R14,2022 R14 = 2022; // lost console code follows
    d6ed: 3c,24,01 jb B4,R24,d6f1 if (!B4_R24) {
    d6f0: fb ei enable ints; }
    d6f1: a1,f0,00,18 ldw R18,f0 R18 = f0;
    d6f5: b3,01,20,20,1a ldb R1a,[2020] R1a = [2020];
    d6fa: a2,15,1c ldw R1c,[R14++] R1c = [R14++];
    d6fd: c2,19,1c stw R1c,[R18++] [R18++] = R1c;
    d700: e0,1a,f7 djnz R1a,d6fa R1a--;
    if (R1a != 0) goto d6fa;
    d703: 71,ef,24 an2b R24,ef R24 &= ef;
    d706: f0 ret return;

    d707: ff fill

    d708: ac,00 // reg 0xac = start of register list to shadow

    d70a: b0,00, // register 0xb0 = 2nd register to shadow
    ...
    d728: 00,00 // end of register list
    d72a: 00,00 // end of register list
    ----------------------------------------------------------------------------------------------------------------------------------------------------------------

    SuperLogger Configuration

    ADX Header Config
    Connection Command:None
    Monitor Command:Harvest Data Macro
    Disconnect Command:None
    Pause Command:VersionFetch
    Unpause Command:VersionFetch
    SUPERLOGGER SEND COMMANDS
    TitleUnique IDDescriptionBaudHex CMD StringChecksumManually Sendable
    Set Accel Paramsetaccelparam00x41 0x01 0x2B 0x02Sum 0x6FN,N
    Set LogBut Active Startup Inactivesetlogbutactsu00x44 0x4F 0x61Sum 0xF4N,N
    DR: Configure PacketD_R_QH00x44 0x52 0xFF 0x00 0xC8 0x00 0x01 0x01 0x74 0x71Sum 0x44N,N
    readeepreqreadeepreq00x48 0x52 0x80 0x05 0x00Sum 0x1FN,N
    PT close lastbyteptlastbyteclos00x74None -
    SL DS Setup for PatchetcSLDS00x44 0x53 0x0A 0x0B 0x0C 0x0D 0x03 0xFE 0x00 0x51 0x4A 0x01 0x03 0x0D 0xB1 0x01 0x03 0x0D 0xB0 0x02 0x03 0x02 0x50 0x02 0x03 0x02 0x4E 0x02 0x03 0x02 0x5C 0x02 0x03 0x02 0x60 0x02 0x03 0x02 0x0A 0x02 0x03 0x02 0x0C 0x02 0x03 0x07 0xB4 0x02 0x03 0x07 0xB6 0x02 0x03 0x02 0x06 0x02 0x03 0x02 0x08 0x02 0x03 0x01 0x1C 0x02 0x03 0x01 0x1E 0x02 0x03 0x01 0x16 0x02 0x03 0x0D 0xAE 0x01 0x03 0x02 0x9F 0x01 0x03 0x02 0xBD 0x02 0x03 0x02 0x9A 0x02 0x03 0x0D 0xAA 0x01 0x03 0x0D 0xD0 0x02 0x03 0x01 0x26 0x01 0x03 0x02 0x11 0x02 0x03 0x01 0x8C 0x02 0x03 0x01 0x88 0x01 0x03 0x01 0x2F 0x01 0x03 0x01 0x66 0x02 0x03 0x01 0x5C 0x02 0x03 0x0D 0xB8 0x01 0x03 0x01 0x57 0x01 0x03 0x01 0x6B 0x02 0x03 0x01 0x54 0x01 0x03 0x0D 0xEE 0x01 0x03 0x0D 0xE7 0x01 0x03 0x0D 0x26 0x01 0x03 0x0D 0x27 0x01 0x03 0x0D 0xEC 0x01 0x03 0x0D 0xE9 0x01 0x03 0x0D 0x29 0x01 0x03 0x0D 0x28 0x01 0x03 0x0D 0x2E 0x01 0x03 0x0D 0xEF 0x02 0x03 0x02 0x52 0x02 0x03 0x02 0x58 0x02 0x03 0x02 0x56 0x01 0x03 0x02 0xDC 0x01 0x03 0x01 0x2C 0x02 0x03 0x01 0x68 0x02 0x03 0x0D 0xD2 0x01 0x03 0x02 0x88 0x01 0x03 0x01 0x93 0x02 0x03 0x01 0x8E 0x02 0x03 0x03 0x2A 0x02 0x03 0x03 0xA6 0x02 0x03 0x03 0x30 0x02 0x03 0x02 0x9C 0x02 0x03 0x01 0x6C 0x01 0x03 0x02 0x9E 0x02 0x03 0x01 0x24 0x02 0x03 0x07 0xE4 0x02 0x03 0x07 0xE6 0x02 0x03 0x07 0xE8 0x02 0x03 0x07 0xEA 0x02 0x00 0x01 0x03 0x2B 0x01 0x01 0x44 0x01 0x03 0xFF 0xFE 0x01 0x03 0x02 0x72 0x01 0x03 0x0D 0xC8 0x01 0x03 0x0D 0xC9 0x01 0x03 0x01 0x4D 0x01 0x03 0x01 0x48 0x02 0x03 0x01 0x14 0x02 0x03 0x01 0x12 0x02 0x03 0x01 0x80 0x01 0x03 0x0D 0xCB 0x24 0x4FSum 0x8BN,N
    SLSetupSimpleSetupSimple00x44 0x53 0x0A 0x0B 0x0C 0x0D 0x02 0x80 0x00 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x80 0x00 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01Sum 0xC7N,N
    Read Time Requestreadtimereq00x44 0x54 0x52 0x00 0x08Sum 0xF2n,n
    QH Patch Sendqhpatch00x57 0x3D 0x07 0x84 0xB2 0xA1 0xEE 0x84 0x42 0xA2 0x43 0x14 0xA2 0x14 0x1C 0xC3 0x15 0x00 0x0D 0x1C 0x8A 0x42 0x00 0xD7 0xF0 0xA1 0x22 0x20 0x14 0x3C 0x24 0x01 0xFB 0xA1 0xF0 0x00 0x18 0xB3 0x01 0x20 0x20 0x1A 0xA2 0x15 0x1C 0xC2 0x19 0x1C 0xE0 0x1A 0xF7 0x71 0xEF 0x24 0xA3 0x01 0xFC 0xFF 0x42 0xC3 0x01 0xFE 0xFF 0x42 0xF0 0x00Sum 0xA2n,n
    QH Patch Send 2patch200x57 0x21 0x07 0x84 0xEE 0xB0 0x00 0xAE 0x00 0xAA 0x00 0xD0 0x00 0xB8 0x00 0xEE 0x00 0xE6 0x00 0x26 0x00 0xEC 0x00 0xE8 0x00 0x28 0x00 0x2E 0x00 0xD2 0x00 0xC8 0x00 0xCA 0x00 0x00 0x00 0x00Sum 0x09n,n
    QH Config Singleqhsingleconfig00x51 0x4A 0x01 0x03 0x0D 0xB1 0x01 0x03 0x0D 0xB0 0x02 0x03 0x02 0x50 0x02 0x03 0x02 0x4E 0x02 0x03 0x02 0x5C 0x02 0x03 0x02 0x60 0x02 0x03 0x02 0x0A 0x02 0x03 0x02 0x0C 0x02 0x03 0x07 0xB4 0x02 0x03 0x07 0xB6 0x02 0x03 0x02 0x06 0x02 0x03 0x02 0x08 0x02 0x03 0x01 0x1C 0x02 0x03 0x01 0x1E 0x02 0x03 0x01 0x16 0x02 0x03 0x0D 0xAE 0x01 0x03 0x02 0x9F 0x01 0x03 0x02 0xBD 0x02 0x03 0x02 0x9A 0x02 0x03 0x0D 0xAA 0x01 0x03 0x0D 0xD0 0x02 0x03 0x01 0x26 0x01 0x03 0x02 0x11 0x02 0x03 0x01 0x8C 0x02 0x03 0x01 0x88 0x01 0x03 0x01 0x2F 0x01 0x03 0x01 0x66 0x02 0x03 0x01 0x5C 0x02 0x03 0x0D 0xB8 0x01 0x03 0x01 0x57 0x01 0x03 0x01 0x6B 0x02 0x03 0x01 0x54 0x01 0x03 0x0D 0xEE 0x01 0x03 0x0D 0xE7 0x01 0x03 0x0D 0x26 0x01 0x03 0x0D 0x27 0x01 0x03 0x0D 0xEC 0x01 0x03 0x0D 0xE9 0x01 0x03 0x0D 0x29 0x01 0x03 0x0D 0x28 0x01 0x03 0x0D 0x2E 0x01 0x03 0x0D 0xEF 0x02 0x03 0x02 0x52 0x02 0x03 0x02 0x58 0x02 0x03 0x02 0x56 0x01 0x03 0x02 0xDC 0x01 0x03 0x01 0x2C 0x02 0x03 0x01 0x68 0x02 0x03 0x0D 0xD2 0x01 0x03 0x02 0x88 0x01 0x03 0x01 0x93 0x02 0x03 0x01 0x8E 0x02 0x03 0x03 0x2A 0x02 0x03 0x03 0xA6 0x02 0x03 0x03 0x30 0x02 0x03 0x02 0x9C 0x02 0x03 0x01 0x6C 0x01 0x03 0x02 0x9E 0x02 0x03 0x01 0x24 0x02 0x03 0x07 0xE4 0x02 0x03 0x07 0xE6 0x02 0x03 0x07 0xE8 0x02 0x03 0x07 0xEA 0x01 0x03 0x01 0x44 0x01 0x03 0xFF 0xFE 0x01 0x03 0x02 0x72 0x01 0x03 0x0D 0xC8 0x01 0x03 0x0D 0xC9 0x01 0x03 0x01 0x4D 0x01 0x03 0x01 0x48 0x02 0x03 0x01 0x14 0x02 0x03 0x01 0x12 0x02 0x03 0x01 0x80 0x01 0x03 0x0D 0xCBSum 0x24n,n
    QH Config Single SimplifiedQHSIMPLE00x51 0x4A 0x01 0x03 0x0D 0xB1 0x01 0x03 0x0D 0xB0 0x02 0x03 0x02 0x50 0x02 0x03 0x02 0x4E 0x02 0x03 0x02 0x5C 0x02 0x03 0x02 0x60 0x02 0x03 0x02 0x0A 0x02 0x03 0x02 0x0C 0x02 0x03 0x07 0xB4 0x02 0x03 0x07 0xB6 0x02 0x03 0x02 0x06 0x02 0x03 0x02 0x08 0x02 0x03 0x01 0x1C 0x02 0x03 0x01 0x1E 0x02 0x03 0x01 0x16 0x02 0x03 0x0D 0xAE 0x01 0x03 0x02 0x9F 0x01 0x03 0x02 0xBD 0x02 0x03 0x02 0x9A 0x02 0x03 0x0D 0xAA 0x01 0x03 0x0D 0xD0 0x02 0x03 0x01 0x26 0x01 0x03 0x02 0x11 0x02 0x03 0x01 0x8C 0x02 0x03 0x01 0x88 0x01 0x03 0x01 0x2F 0x01 0x03 0x01 0x66 0x02 0x03 0x01 0x5C 0x02 0x03 0x0D 0xB8 0x01 0x03 0x01 0x57 0x01 0x03 0x01 0x6B 0x02 0x03 0x01 0x54 0x01 0x03 0x0D 0xEE 0x01 0x03 0x0D 0xE7 0x01 0x03 0x0D 0x26 0x01 0x03 0x0D 0x27 0x01 0x03 0x0D 0xEC 0x01 0x03 0x0D 0xE9 0x01 0x03 0x0D 0x29 0x01 0x03 0x0D 0x28 0x01 0x03 0x0D 0x2E 0x01 0x03 0x0D 0xEF 0x02 0x03 0x02 0x52 0x02 0x03 0x02 0x58 0x02 0x03 0x02 0x56 0x01 0x03 0x02 0xDC 0x01 0x03 0x01 0x2C 0x02 0x03 0x01 0x68 0x02 0x03 0x0D 0xD2 0x01 0x03 0x02 0x88 0x01 0x03 0x01 0x93 0x02 0x03 0x01 0x8E 0x02 0x03 0x03 0x2A 0x02 0x03 0x03 0xA6 0x02 0x03 0x03 0x30 0x02 0x03 0x02 0x9C 0x02 0x03 0x01 0x6C 0x01 0x03 0x02 0x9E 0x02 0x03 0x01 0x24 0x02 0x03 0x07 0xE4 0x02 0x03 0x07 0xE6 0x02 0x03 0x07 0xE8 0x02 0x03 0x07 0xEA 0x01 0x03 0x01 0x44 0x01 0x03 0xFF 0xFE 0x01 0x03 0x02 0x72 0x01 0x03 0x0D 0xC8 0x01 0x03 0x0D 0xC9 0x01 0x03 0x01 0x4D 0x01 0x03 0x01 0x48 0x02 0x03 0x01 0x14 0x02 0x03 0x01 0x12 0x02 0x03 0x01 0x80 0x01 0x03 0x0D 0xCBSum 0x24n,n
    Passthrough Beginptbegin00x70 0x70Sum 0xE0n,n
    d: Query for packetQUERY00x64None -n,n
    DOLI: Request Onboard StatusREQSTATUS00x44 0x4F 0x4C 0x49Sum 0x28n,n
    VV: Request VersionVER_REQ00x56 0x56None -n,n
    DOCYsendDOCYsend00x44 0x4F 0x43 0x59Sum 0x2Fn,n
    DOCNsendDOCNsend00x44 0x4F 0x43 0x4ESum 0x24n,n
    DOEsendDOEsend00x44 0x4F 0x45Sum 0xD8n,n
    DOLYsendDOLYSEND00x44 0x4F 0x4C 0x59Sum 0x38n,n
    DOLNsendDOLNSEND00x44 0x4F 0x4C 0x4ESum 0x2Dn,n
    DOLysendDOLySEND00x44 0x4F 0x4C 0x79Sum 0x58n,n
    DOLnsendDOLnSEND00x44 0x4F 0x4C 0x6ESum 0x4Dn,n
    DLsendDLSENDThis should set things up to log no ADC, do a 10:1 skip ratio for logging, and no conditional windows. So every 10th frame will get stored.00x44 0x4C 0x00 0x00 0x00 0x00 0x00Sum 0x90Y,Y
    Exit Passthroughexitpass00x45 0x78 0x69None -n,n
    SUPERLOGGER MACRO COMMANDS
    TitleUnique IDDescriptionManually SendableMacros Repeat CountCommandEntry Repeat CountBOF,BOS
    AccelMacroaccelmacroY,Y1Set Accel Param
    Okay Response1
    Initialize SettingsInitY,Y1QH Config Macro
    Configure SL for Payload
    DL: Configure Onboad Logging Structure
    DOCN: Turn Compression Off
    DOLN: Disable Onboard Logging
    DOLn: Disable Background Polling1n,n
    Set Logbut ActiveMacsetlogbutactmaY,Y1Set LogBut Active Startup Inactive
    Okay Response1n,n
    Configure SL for PayloadCONFIGY,Y1Pause for Data Rate
    DR: Configure Packet
    Okay Response1n,n
    Read EEPreadeepmacY,Y1readeepreq
    eepreadrec1n,n
    SL SetupstringSLSTRINGY,Y1SL DS Setup for Patchetc
    Okay Response1n,n
    Passthrough StartptstartY,Y1Passthrough Begin
    Okay Response1n,n
    QH Config MacroqhconfigmacroY,Y1Passthrough Start
    VersionFetch
    QH Patch Send
    Okay Response
    QH Patch Send 2
    Okay Response
    QH Config Single
    1 Second Pause
    Okay Reponse
    Passthrough End / Version Fetch1n,n
    Passthrough End / Version FetchDISCONY,Y1Pause for Data Rate
    Exit Passthrough
    Bytes for Drain
    PT close lastbyte
    VV: Version Response1n,n
    QH Config Basicqhconfig basicY,Y1QH Config Single
    1 second Pause
    Okay Response
    VersionFetch1n,n
    SL Setup Simple MacroslsetmacsimpleY,Y1SLSetupSimple
    Okay Response1n,n
    ReadTime MacroreadmacY,Y1Read Time Request
    ReadTimeResp1n,n
    Pass-Patch-ReturnpasspatchY,Y1Passthrough Start
    VersionFetch
    QH Patch Send
    QH Patch Send 2
    Okay Response
    VersionFetch
    Passthorugh End / Version Fetch1n,n
    Poll Status MacroPOLLSTATUSY,Y1DOLI: Request Onboard Status
    DOLI: Retrieve Status1n,n
    DOE: Erase DataFlash Onboard MemoryERASE_DFY,Y1DOEsend
    1 Second Pause
    1 Second Pause
    1 Second Pause
    1 Second Pause
    1 Second Pause
    1 Second Pause
    1 Second Pause
    1 Second Pause
    1 Second Pause
    1 Second Pause
    1 Second Pause
    okay Response LongErase1n,n
    Monitor MacroMONITORn,n1Harvest Data Macro
    Poll Status Macro1n,n
    Harvest Data MacroHARVESTY,Y1d: Query for packet
    d: Harvest Packet
    Okay Response
    Pause for Data Rate1n,n
    HarvestBothharvestbothn,n1d: Harvest Packet
    d: Harvest Extras1n,n
    VersionFetchverfetchY,Y1VV: Request Version
    VV: Version Response1n,n
    DOCY: Turn Compression OnCOMPRESS_YY,Y1DOCYsend
    Okay Response1n,n
    DOCN: Turn Compression OffCOMPRESS_NY,Y1DOCNsend
    Okay Response1n,n
    DOLY: Enable Onboard LoggingONBOARD_YY,Y1DOLYsend
    Okay Response1n,n
    DOLN: Disable Onboard LoggingONBOARD_NY,Y1DOLNsend
    Okay Response1n,n
    DOLy: Enable Background PollingPOLLING_yY,Y1DOLysend
    Okay Response1n,n
    DOLn: Disable Background PollingPOLLING_nY,Y1DOLnsend
    Okay Response1n,n
    DL: Configure Onboard Logging StructureCONFIGURE_LOGSY,Y1DLsend
    Okay Response1n,n
    SUPERLOGGER LISTEN PACKET COMMANDS
    TitleUnique IDDescriptionBaudProcess DataPacket TypeHeaderFooterTimeoutBody SizePayload OffsetPayload Size
    eepreadreceepreadrec0NStatic40040000
    Bytes for DrainDrainbytes0nStatic20303
    ReadTimeRespReadTimeResp0YStatic40010010
    d: Harvest PacketPACKET0YStatic4001590159
    d: Harvest Extrasextraharv0YStatic40041041
    DOLI: Retrieve StatusGETSTATUS0YStatic40017017
    VV: Version ResponseVERSION_RESP0nStatic400202
    Okay ResponseOK0YStatic1000101
    Okay Response LongEraseOKLONG0NStatic100000101
    SUPERLOGGER SILENCE/TIMEOUT COMMANDS
    TitleUnique IDDescriptionBaudSilence LengthTimeout
    Pause for Data RateWAITThis timeout mS value can be adjusted to 100 for 10 samples per second.005
    1 Second Pause1SEC00800

    Important Ford Variables

    j1979_01_06SCP Lambse1 byte
    j1979_01_08SCP Lambse2 byte
    R63"new_data"



    Talk Code - Jump to Disassembly Forum


    Return Home
    Jump to Forum
    www.EFIDynoTuning.com - EFIDynoTuning LC - New Orleans, LA