Announcement

Collapse
No announcement yet.

CSL '0401' Program Binary Disassembly Notes

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • terra
    replied
    Originally posted by karter16 View Post
    Was working through some unknown variables in the DPR that needed figuring out and came across this:

    Click image for larger version  Name:	Screenshot 2026-01-30 at 6.08.14 PM.png Views:	4 Size:	232.6 KB ID:	341753

    This is where the CVNs are generated for CARB. They're built off the CRCs of the various sections same as is done elsewhere, but here they're XOR'd with various values - I'm gunna go ahead and guess that that was to stop it being used as a way to generate checksums (unless anyone has any other ideas) the CARB specification makes no mention of anything that would explain it.
    I guess it makes it harder to generate an arbitrary checksum if you don't know the algorithm, but if one makes the connection that generating a checksum to match the original results in the CVN also matching the original, then it's kinda moot. They probably just thought they were being cute with the MS_S stuff.

    CARB does leave it entirely to the manufacturer on how to calculate it. On various non-M DMEs from the E6x/9x generation (MS45, MSx70/8x), the CVN is simply the same as the stored checksum (CRC32 in those cases). I'm not sure about MSS6x, I never looked into that.

    Leave a comment:


  • karter16
    replied
    Originally posted by bmwfnatic View Post
    4D 53 5F 53 35 34 35 32 in ASCII reads MS_S5452
    Ha nice! I'd missed that


    Sent from my iPhone using Tapatalk

    Leave a comment:


  • bmwfnatic
    replied
    4D 53 5F 53 35 34 35 32 in ASCII reads MS_S5452

    Leave a comment:


  • karter16
    replied
    Was working through some unknown variables in the DPR that needed figuring out and came across this:

    Click image for larger version

Name:	Screenshot 2026-01-30 at 6.08.14 PM.png
Views:	60
Size:	232.6 KB
ID:	341753

    This is where the CVNs are generated for CARB. They're built off the CRCs of the various sections same as is done elsewhere, but here they're XOR'd with various values - I'm gunna go ahead and guess that that was to stop it being used as a way to generate checksums (unless anyone has any other ideas) the CARB specification makes no mention of anything that would explain it.

    Leave a comment:


  • karter16
    replied
    These are the P_UMG (ambient pressure) functions.

    p_umg_init() runs once in the initialisation function when the DME boots. It establishes the starting values for the key variables.

    Click image for larger version  Name:	Screenshot 2026-01-24 at 5.52.48 PM.png Views:	0 Size:	150.3 KB ID:	341015


    p_umg_get() runs in the 100ms task, it acquires the latest value from the ambient pressure sensor via the AD channel, performs error checking (via p_umg_diag()), builds a variable to send p_umg over CAN, etc.

    Click image for larger version  Name:	Screenshot 2026-01-24 at 5.54.31 PM.png Views:	0 Size:	144.6 KB ID:	341016


    p_umg_hoehe_ber() runs in the background task and calculates the current estimated height above sea level based on current ambient pressure.

    Click image for larger version  Name:	Screenshot 2026-01-24 at 5.57.20 PM.png Views:	0 Size:	69.6 KB ID:	341017


    p_umg_diag() is called by p_umg_get(). It establishes plausibility of the ambient pressure sensor reading, updates P_UMG_FILTER with either the valid reading, an ersatz (replacement) value, etc. This function is interesting as the 0401 version contains a bunch of additional logic. In the event that when the DME starts it is unable to acquire a plausible reading from the ambient sensor it will use, if it is error free, the MAP pressure as an ersatz (replacement) value for P_UMG. The reason it can do this is that on first start up, before the engine is running, the manifold pressure is the same as ambient. This means that while the engine is running the ersatz value isn't able to be updated, but under a lot of conditions it will still be more accurate than just falling back to K_P_UMG_ERSATZ (955mbar).

    Click image for larger version  Name:	Screenshot 2026-01-24 at 6.01.10 PM.png Views:	0 Size:	160.4 KB ID:	341018
    Click image for larger version  Name:	Screenshot 2026-01-24 at 6.01.21 PM.png Views:	0 Size:	214.2 KB ID:	341019

    Edit: If you're wondering there is some method to my madness. I'm, looking at the air mass functions and wanted to be 100% sure about how p_umg was/wasn't used, hence the side quest into the p_umg functions.
    Last edited by karter16; 01-23-2026, 09:14 PM.

    Leave a comment:


  • bmwfnatic
    replied
    Originally posted by terra View Post

    Yeah, there's clearly more out there than is publicly available. Though I would argue the MSS5x are understood well enough for there already to be no point in hoarding files - most tuners are doing little more than editing the main ignition and fueling tables.

    I do wonder if BMW gives some definitions on the motorsport side of things since I imagine those cars are recalibrated pretty often. Though I don't know if I've ever seen an MSS54 in the motorsports parts listing (MSS60 yes though)
    It mentions ECU 406 and ECU 400 and a separate VANOS ECU in the P54B32 catalog, nothing explicitly about the MSS indeed.

    Leave a comment:


  • terra
    replied
    Originally posted by bmwfnatic View Post

    This will 100% happen one day, we know it's out there, and people love to gate keep until there's no point anymore.
    Yeah, there's clearly more out there than is publicly available. Though I would argue the MSS5x are understood well enough for there already to be no point in hoarding files - most tuners are doing little more than editing the main ignition and fueling tables.

    I do wonder if BMW gives some definitions on the motorsport side of things since I imagine those cars are recalibrated pretty often. Though I don't know if I've ever seen an MSS54 in the motorsports parts listing (MSS60 yes though)

    Leave a comment:


  • bmwfnatic
    replied
    Originally posted by karter16 View Post

    I have this horrible nagging feeling that one day I'm going to declare my efforts "complete" and the next day someone will be like "oh btw, here's the source code for the CSL" lol. There's definitely a couple of people out there who have more CSL-specific info.
    This will 100% happen one day, we know it's out there, and people love to gate keep until there's no point anymore.

    Leave a comment:


  • karter16
    replied
    Originally posted by terra View Post
    Sure would be nice if we could get access to some MSS54 ELFs
    I have this horrible nagging feeling that one day I'm going to declare my efforts "complete" and the next day someone will be like "oh btw, here's the source code for the CSL" lol. There's definitely a couple of people out there who have more CSL-specific info.

    Leave a comment:


  • terra
    replied
    Yeah hard to say for sure. I also have a suspicion that the some of the CSL stuff was borrowed from the MSS6x project given the development timelines, but the two projects very well could have had different naming conventions. Though a lot of names are shared, so it might just be their convention is a little more fluid and it more came down to whichever engineer started writing the code.

    As far as m vs mzyl -- I think they probably would have noted that the value is a per cylinder calculation in the naming scheme, though perhaps m_zyl would have been the convention on the MSS5x

    Sure would be nice if we could get access to some MSS54 ELFs

    Leave a comment:


  • karter16
    replied
    Here's mzyl_berech(). This is what I'd previously identified as m_calc(). I'm not 100% sure that the function/parameter/variable names that I've pulled through from MSS65 are what BMW ACTUALLY used in the MSS54 code. I think it's more likely that PSAU is p_saug for example, in line with the way other pressure and temp variables were named in the MSS54. I think too that MZYL was possibly just M, etc. but I'm definitely going to opt for known actual names over made up names, so have pulled through the MSS65 naming where there wasn't already a 100% known name from MSS54. ? at the end of a variable name represent where I don't have a definitive name, not necessarily that I have any uncertainty about what it is/does.

    Click image for larger version  Name:	Screenshot 2026-01-23 at 7.12.58 PM.png Views:	0 Size:	159.6 KB ID:	340845
    Click image for larger version  Name:	Screenshot 2026-01-23 at 7.13.05 PM.png Views:	0 Size:	10.8 KB ID:	340844

    Leave a comment:


  • karter16
    replied
    Ahh this is so satisfying for my brain.

    I've gone through rg_berech() (MSS65) and compared it to rg_m_calc() (my MSS54 disassembly) and the rg (rest-gas) calculation is effectively the same. I've been able to match everything up and identify the actual names for the maps and parameters. This confirms that my understanding of how it was working was pretty much on the money.

    The only significant difference between the two (aside from MSS65's bank handling, and differences in base units) is that the MSS65 function includes a lookup to a table which gives a delta adjustment based on expected intake manifold pressure. This isn't included in the MSS54 function although I haven't yet figured out whether it's effectively accounted for elsewhere in the calculation path.

    The other thing of note is that the MSS54 has an unused option to just lookup rg mass from a lookup (KF_RG_M) the equivalent lookup doesn't exist in the MSS65 code.


    MSS54 rg_berech()

    Click image for larger version  Name:	Screenshot 2026-01-20 at 8.10.18 PM.png Views:	32 Size:	179.9 KB ID:	340440
    Click image for larger version  Name:	Screenshot 2026-01-20 at 8.10.25 PM.png Views:	33 Size:	221.5 KB ID:	340439
    Click image for larger version  Name:	Screenshot 2026-01-20 at 8.10.31 PM.png Views:	33 Size:	189.6 KB ID:	340438
    Last edited by karter16; 01-21-2026, 11:50 AM.

    Leave a comment:


  • karter16
    replied
    Originally posted by terra View Post
    If I had to guess, the name for the CSL one would be something to the effect of KF_RF_SOLL (which now I see is something you came up with as well) or perhaps KF_AQ_REL_SOLL(_RF?)

    The MSS6x seems to handle things a little differently. The MSS65 v113 prototype seems to have KF_EGAS_SOLL_DK (rf target from throttle opening area). There's also a KF_EGAS_SOLL_LLS (rf target from idle valve opening) -- presumably the two outputs are added together. The MSS5x instead generates an aq_rel from the throttle valve and idle valve openings and then that's fed into the big map. I imagine the extra processing power on the MSS6x made them try separate maps rather than combining the two air sources. These maps sit on the ignition processor like the "standard" RF map on the non-CSL. As far as I can tell there's no similar map on the injection side -- I suspect on the CSL it moved to master/injection side for processing speed purposes.
    Yeah agreed - the MSS65 has a different approach to RF calculation. In V113 it's actually configured to use an HFM to assist in the calculation of base RF before applying the air mass calculations. The path where KF_EGAS_SOLL_DK/LLS is used to calculate rf_aq and rf_mzyl_ml_aq isn't actually followed given what K_MZYL_CFG is set to.

    You're right it could be kf_rf_soll, I certainly think it's likely that the variable that it drives is rf_soll, I'd kinda followed the standard naming convention to get KF_RF_N_DR_REL but absolutely could be kf_rf_soll or even kf_rf_soll_n_dr_rel.

    Leave a comment:


  • terra
    replied
    If I had to guess, the name for the CSL one would be something to the effect of KF_RF_SOLL (which now I see is something you came up with as well) or perhaps KF_AQ_REL_SOLL(_RF?)

    The MSS6x seems to handle things a little differently. The MSS65 v113 prototype seems to have KF_EGAS_SOLL_DK (rf target from throttle opening area). There's also a KF_EGAS_SOLL_LLS (rf target from idle valve opening) -- presumably the two outputs are added together. The MSS5x instead generates an aq_rel from the throttle valve and idle valve openings and then that's fed into the big map. I imagine the extra processing power on the MSS6x made them try separate maps rather than combining the two air sources. These maps sit on the ignition processor like the "standard" RF map on the non-CSL. As far as I can tell there's no similar map on the injection side -- I suspect on the CSL it moved to master/injection side for processing speed purposes.

    Closest equivalent on the MSS60 prototype (which is likely pretty close to final MSS65 code) is KF_EGAS_SOLL_AQ. There's also a KL_AQ_ABS_LLS- it seems like they went back to the concept of just transforming the idle valve opening as 'adding to' the throttle opening, and just stuck with units of area instead of generating an "aq_rel" value (though as you've found, an aq_rel value is ultimately generated to do stuff on the injection side)

    I feel relatively confident the psau object and associated naming convention is pretty close to what's in the CSL (minus bank1 / bank2 stuff probably) though I need to dust off my binaries and disassemblies and look closer. Reproduced relevant stuff below

    Code:
     .std_appl 000608c4 00000084 ..\..\output\inj\obj\psau.obj
    K_PSAU_STEIGUNG 000608c4 00000002
    K_PSAU_OFFSET 000608c6 00000002
    K_PSAU_DIAG_MAX 000608c8 00000002
    K_PSAU_DIAG_MIN 000608ca 00000002
    K_PSAU_ERSATZ 000608cc 00000002
    K_PSAU_ADAPT_MAX 000608ce 00000002
    K_PSAU_ADAPT_MIN 000608d0 00000002
    K_PSAU_TAU 000608d2 00000001
    K_PSAU_MZYL_A 000608d4 00000002
    K_PSAU_MZYL_E 000608d8 00000002
    K_PSAU_MRG_A 000608dc 00000002
    K_PSAU_MRG_E 000608e0 00000002
    KL_PSAU_ZAHN_OFFSET 000608e2 0000002a
    KL_PSAU_MZYL_DASP 0006090c 0000001e
    KL_PSAU_WF_DASP 0006092a 0000001e[
    
    .text 00033398 000009a8 ..\..\output\inj\obj\psau.obj
    psau_diag 00033398 000000c8
    psau_ausw_10ms 00033460 00000120
    psau_init 00033580 00000128
    psau_10ms 000336a8 00000054
    psau_adaption 000336fc 00000080
    get_qidx 0003377c 00000034
    get_mw 000337b0 0000007c
    psau_ausw 0003382c 00000504
    psau_auf_bank1 00033d30 00000008
    psau_auf_bank2 00033d38 00000008
    
    psau                            .vars       .std_vars      ..\..\output\inj\obj\wf_fkt.obj
                                                                      ..\..\output\inj\obj\ti_fkt.obj
                                                                      ..\..\output\inj\obj\rps.obj
                                                                      ..\..\output\inj\obj\rg.obj
                                                                      ..\..\output\inj\obj\rf.obj
                                                                    * ..\..\output\inj\obj\psau.obj
                                                                      ..\..\output\inj\obj\mzyl.obj
                                                                      ..\..\output\inj\obj\hfm.obj​
    ​

    Leave a comment:


  • karter16
    replied
    Okay exciting.

    We now have the definitive name for what I termed aq_rel_rf!

    It's dr_rel_roh (drossel-relativ) relative throttle signal.

    In the MSS65 it's calculated in aq_5ms_bank:

    Click image for larger version  Name:	Screenshot 2026-01-19 at 7.58.57 PM.png Views:	0 Size:	172.8 KB ID:	340338

    The factor is obtained from KL_AQ_REL_MAX_ENTDR (what I'd called kl_aq_rel_rf_fakt). Super satisfying to know what actual name for this is. It also gives us a bit more insight into exactly what it's intended to correct. Essentially it's accounting for the fact that a given aq_rel at low RPM has a different effect compared to at a high RPM due to flow and manifold dynamics.


    Edit - by extension this also presumably gives us the correct name for the CSL AlphaN table.

    The standard table for the M3 (the lower resolution one) is KF_RF_N_AQ_REL. That means the CSL one is presumably KF_RF_N_DR_REL.
    Last edited by karter16; 01-18-2026, 11:33 PM.

    Leave a comment:

Working...
X