There are multiple interesting files bundled in the DIRECTOR firmware update tool.
The findings here are so far limited to the old version "1.77 / 2.11 (DSP PC-Tool 4.75a to 4.80c)". I didn't realize I downloaded the older one until writing this (oops). That said most of this is probably still valid, but firmware "3.00 (DSP PC-Tool 5 or higher)" is likely to have support/params for more models.
Extracing the 1.77 installer, these files look interesting:
599 Dec 19 2018 Bootloader_gfx.tcl
602 Dec 19 2018 Bootloader_gfx_aco.tcl
613 Jul 17 2017 Bootloader_gfx_custom.tcl
616 Aug 24 2018 Bootloader_gfx_custom_aco.tcl
29 Oct 15 2021 Bootloader_inst.ucon
197800 Dec 19 2018 Director_GFX.bin
197800 Feb 18 2020 Director_GFX_custom.bin
167452 Oct 1 2021 Director.bin
167388 Oct 1 2021 Director_custom.bin
160044 Nov 23 2021 acoDirector.bin
160044 Nov 23 2021 acoDirector_custom.bin
The .tcl files are short scripts that write one of the _GFX.bin files to a region in NandFlash, and one of the plain .bin files to Flash.
The .ucon file contains a few lines with numbers, not really sure what this is.
The _GFX.bin files I'm assuming only contain graphical/image data.
The plain .bin files are the actual firmware.
The _custom suffix probably refers to the custom logo upload functionality of the firmware update program. I compared the Director.bin and Director_custom.bin firmwares and didn't find any material changes in the places I was looking, so there's probably just a small change somewhere to load the logo graphic from a different place.
The rest of this doc only looks at Director.bin. I haven't yet looked at acoDirector.bin. If i had to guess it's probably some early version of the "3.00" firmware.
Some sort of ARM Cortex chip. I don't actually own a Helix controller nor DSP yet so idk which one.
These are the important memory map regions I loaded into Ghidra:
- vectable @ 0x00000000 (aliased to the first few hundred bytes of flash region)
- flash @ 0x00400000 ("Flash" write address in the .tcl scripts, initialized to
Director.bin) - SRAM @ 0x20000000 (from datasheet, uninitialized)
- peripheral @ 0x40000000 (from datasheet, initialized)
This is the main datasheet I referred to. It stood out because it lists the 0x400e1400 peripheral address as Reset Controller, and that address is referenced both at the end of the bootloader flash script as well as in reset-related logic found in the firmware. The other peripheral registers seemed to line up well once I imported an SVD file I found for one of the listed chips.
There's not much rhyme or reason here, it's basically just an endless game of sudoku via xrefs. The more addresses/functions/types/structs you label the more sense surrounding things eventually make.
A few good entrypoints:
- Main function (nested inside reset address func in vectable)
- Interrupt routines for UART0, USART0, USART1 (see vectable) - handles part of the response read loop for commands. USART0 seems to be the port of interest going to the DSP. The other ones are related/possibly exist for debugging.
- References to UART/other peripherals of interest
- Strings and UI related functions
AI is also decent at analyzing confusing assembly and decompiler output, as long as you can detect when it starts hallucinating or making random assumptions. It helped a lot in identifying stdlib function implementations, and explaining pieces of the UART writing/reading machinery which is super ugly and scattered in the compiled firmware.
Seems to be a synchronous request-response format, over UART.
Baud rate is dynamic. FWICT it starts at 19200 but probably upgrades to 192000 for most things, and occasionally 250000 or 230400 in a specific routine for some models (not sure what it does, seems like a mass upload loop either for settings or firmware).
42 LL NN 01 { XX ... } ZZ
Header region:
- 42 = constant
'B'- AI surmises this stands for "Befehl" which is "Command" in German :p - LL =
payload_length + 1(+1 is for checksum byte) - NN =
~(payload_length + 1)(bitwise inverse of above) - 01 = constant
'\x01'(unknown; maybe protocol version/mode or status byte)
{} denotes "payload" region, containing:
- XX = Command/operation id
- ... = Command args
Checksum byte:
- ZZ =
sum(payload_bytes) & 0xFF
43 LL NN 01 { RR ... } ZZ
Similar format to above
Header region:
- 43 = constant
C - LL =
data_length + 1 - NN =
~(data_length + 1) - 01 = constant
\x01(if this doesn't match then the request is retried up to 10 times. if that still fails, it aborts and restarts the initial device detection/connection sequence)
Data region:
- RR = Command/operation id, mirrors XX in request
- ... = Response data
Checksum byte:
- ZZ =
sum(payload_bytes) & 0xFF
Request payload (8 bytes... or maybe 4+N bytes*)
{ 02 SS XX XX 00 00 00 00 }
- SS = Unknown, possibly memory bank or device selector. This is 00 in all callsites FWICT.
- XX XX = 16-bit remote address or offset, big-endian
Response payload (8 bytes... or maybe 4+N bytes*)
{ 02 SS XX XX YY YY YY YY}
- 02 SS XX XX = echoed portion of request
- YY YY YY YY = the read value, big-endian
*it's possible this command also supports variable-length reads based on the findings below, but the only usage I found so far reads single 32-bit/4 byte values,
Request payload (5+N bytes)
{ 03 SS 01 XX XX ... }
- SS = see above. I think there was a niche callsite i found at some point that loops over non-zero values here but idk what it does. For most usages including the 4 main volume registers this is 00.
- 01 = constant
'\x01', not sure what this is
Response payload (5 bytes)
{ ?? ?? ?? ?? ?? }
unknown
See bottom of this doc for incomplete decompiler output from a couple functions that set model id & global flags.
This is used to calculate volume level used in above commands.
The values on the screen range from -60 to 0, or -40 to 0 for subwoofer.
These values are converted to a volume value between 0 and 1 using the formula 10^(x/20):
https://www.desmos.com/calculator/mdgmagh5kb
https://www.desmos.com/calculator/mhvltmyqtg
Lastly this value is multiplied by g_DSP_Reference_Volume_Level for the connected model, and sent to one of the below addresses.
e.g. if g_DSP_Reference_Volume_Level = 0x1000000, this is the value when volume is maxed out. 0x0 is muted.
Remote address for Master volume level
Remote address for Subwoofer volume level
Remote address for Digital volume level
Remote address for HEC/AUX volume level
"Max out master volume"
Given:
- g_DSP_Reference_Volume_Level = 0x1000000;
- g_DSP_channel_idx_lookup_for_volume[0] = 0xc10;
Full packet: 42 0A F5 01 03 00 01 0C 10 01 00 00 00 21
42 LL NN 01 ZZ
{ 03 SS 01 XX XX .. .. .. .. }
Note: all names are guessed/hand-labeled. Anything not listed below is low-confidence and most likely wrong.
void SetParamsForDspModel(void)
{
switch(g_DSP_MODEL_ID) {
case 4:
g_useFixedPointForAddonVolume = 0;
DAT_20000e9a = 0;
DAT_20000ea3 = 3;
DAT_20000ea4 = 8;
DAT_20000ea6 = 0;
g_DSP_Reference_Volume_Level = 0x800000;
DAT_20000eb0 = 0x4e;
g_someRemoteAddressUsedIn0x2cmd = 0;
DAT_200010b6 = 1;
g_DSP_channel_idx_lookup_for_volume[0] = 0xf;
g_DSP_channel_idx_lookup_for_volume[1] = 0x10;
g_DSP_channel_idx_lookup_for_volume[2] = 0xe;
g_DSP_channel_idx_lookup_for_volume[3] = 0;
DAT_200010c0 = 0x2f;
g_baud_192000 = 0x4b00;
g_baud_rate_for_upload_routine = 0x38400;
g_unknown_48000_or_96000_model_based = 48000;
DAT_200011dc = 0;
g_Override_Volume_Level_For_SetVolume_B = 0;
g_unknown_channel_idx_lookup[2] = 0x11;
DAT_2000124c = 0x25a;
DAT_2000124e = 0x20f;
DAT_20001250 = 0x1c4;
DAT_20001252 = 0x179;
DAT_20001254 = 0x2a5;
DAT_20001256 = 0x2f0;
DAT_20001258 = 0;
DAT_2000125a = 0;
DAT_2000125c = 0;
DAT_2000125e = 0;
uRam20001260 = 0;
uRam20001262 = 0;
uRam20001264 = 0;
uRam20001266 = 0;
uRam20001268 = 0;
uRam2000126a = 0;
g_Supported_DSP_OS_Version = 0x31;
g_short_120_or_0_depending_on_model = 0x78;
return;
default:
goto switchD_0040111a_caseD_5;
case 7:
g_useFixedPointForAddonVolume = 0x3a;
DAT_20000e9a = 0;
g_addonVolumeChannelAddress_2_BoomBoxMode? = 0;
g_addonVolumeChannelAddress_1 = 0x11;
DAT_20000ea3 = 3;
DAT_20000ea4 = 8;
DAT_20000ea6 = 0x3c;
g_DSP_Reference_Volume_Level = 0x800000;
DAT_20000eb0 = 0x42;
g_someRemoteAddressUsedIn0x2cmd = 0x1240;
DAT_200010b6 = 1;
g_DSP_channel_idx_lookup_for_volume[0] = 0xf;
g_DSP_channel_idx_lookup_for_volume[1] = 0x10;
g_DSP_channel_idx_lookup_for_volume[2] = 0;
g_DSP_channel_idx_lookup_for_volume[3] = 0xe;
DAT_200010c0 = 0x2f;
g_baud_192000 = 0x4b00;
g_baud_rate_for_upload_routine = 0x38400;
g_unknown_48000_or_96000_model_based = 48000;
DAT_200011dc = 0;
g_Override_Volume_Level_For_SetVolume_B = 0;
g_unknown_channel_idx_lookup[1] = 0x19;
DAT_2000124c = 0x45c;
DAT_2000124e = 0x411;
DAT_20001250 = 0x3c6;
DAT_20001252 = 0x37b;
DAT_20001254 = 0x29a;
DAT_20001256 = 0x2e5;
DAT_20001258 = 0x330;
DAT_2000125a = 0;
DAT_2000125c = 0;
DAT_2000125e = 0;
uRam20001260 = 0;
uRam20001262 = 0;
uRam20001264 = 0;
uRam20001266 = 0;
uRam20001268 = 0;
uRam2000126a = 0;
g_Supported_DSP_OS_Version = 0x31;
g_short_120_or_0_depending_on_model = 0x78;
return;
case 8:
g_useFixedPointForAddonVolume = 0x42;
DAT_20000e9a = 0;
g_addonVolumeChannelAddress_1 = 0x17;
DAT_20000ea3 = 3;
DAT_20000ea4 = 8;
DAT_20000ea6 = 0x44;
g_DSP_Reference_Volume_Level = 0x800000;
DAT_20000eb0 = 0x4a;
g_someRemoteAddressUsedIn0x2cmd = 0x1240;
DAT_200010b6 = 1;
g_DSP_channel_idx_lookup_for_volume[0] = 0xd;
g_DSP_channel_idx_lookup_for_volume[1] = 0xe;
g_DSP_channel_idx_lookup_for_volume[2] = 0x15;
g_DSP_channel_idx_lookup_for_volume[3] = 0xc;
DAT_200010c0 = 0x2f;
g_baud_192000 = 0x4b00;
g_baud_rate_for_upload_routine = 0x38400;
g_unknown_48000_or_96000_model_based = 48000;
DAT_200011dc = 0;
g_Override_Volume_Level_For_SetVolume_B = 0;
g_unknown_channel_idx_lookup[1] = 0x16;
g_unknown_channel_idx_lookup[2] = 0xf;
DAT_2000124c = 0x222;
DAT_2000124e = 0x1d7;
DAT_20001250 = 0x26d;
DAT_20001252 = 0x2b8;
DAT_20001254 = 0x303;
DAT_20001256 = 0x34e;
DAT_20001258 = 0x399;
DAT_2000125a = 0x3e4;
DAT_2000125c = 0;
DAT_2000125e = 0;
uRam20001260 = 0;
uRam20001262 = 0;
uRam20001264 = 0;
uRam20001266 = 0;
uRam20001268 = 0;
uRam2000126a = 0;
g_Supported_DSP_OS_Version = 0x33;
g_short_120_or_0_depending_on_model = 0x78;
return;
case 0x9[HELIX DSP]:
g_useFixedPointForAddonVolume = 0;
DAT_20000e9a = 0;
DAT_20000ea3 = 3;
DAT_20000ea4 = 8;
DAT_20000ea6 = 0x7b;
g_DSP_Reference_Volume_Level = 0x800000;
DAT_20000eb0 = 0x77;
g_someRemoteAddressUsedIn0x2cmd = 0x1240;
DAT_200010b6 = 1;
g_DSP_channel_idx_lookup_for_volume[0] = 0xf;
g_DSP_channel_idx_lookup_for_volume[1] = 0x10;
g_DSP_channel_idx_lookup_for_volume[2] = 0xe;
g_DSP_channel_idx_lookup_for_volume[3] = 0x12;
DAT_200010c0 = 0x2f;
g_baud_192000 = 0x4b00;
g_baud_rate_for_upload_routine = 0x38400;
g_unknown_48000_or_96000_model_based = 48000;
DAT_200011dc = 0;
g_Override_Volume_Level_For_SetVolume_B = 0;
g_unknown_channel_idx_lookup[1] = 0x14;
g_unknown_channel_idx_lookup[2] = 0x11;
DAT_2000124c = 0x25f;
DAT_2000124e = 0x1c9;
DAT_20001250 = 0x214;
DAT_20001252 = 0x2aa;
DAT_20001254 = 0x3d6;
DAT_20001256 = 0x38b;
DAT_20001258 = 0x340;
DAT_2000125a = 0x2f5;
DAT_2000125c = 0;
DAT_2000125e = 0;
uRam20001260 = 0;
uRam20001262 = 0;
uRam20001264 = 0;
uRam20001266 = 0;
uRam20001268 = 0;
uRam2000126a = 0;
g_Supported_DSP_OS_Version = 0x32;
g_short_120_or_0_depending_on_model = 0x78;
return;
case 10:
case 0x11:
g_useFixedPointForAddonVolume = 0x3e;
DAT_20000e9a = 0;
g_addonVolumeChannelAddress_1 = 0x13;
DAT_20000ea3 = 3;
DAT_20000ea4 = 8;
DAT_20000ea6 = 0x40;
g_DSP_Reference_Volume_Level = 0x800000;
DAT_20000eb0 = 0x38;
g_someRemoteAddressUsedIn0x2cmd = 0x1240;
DAT_200010b6 = 1;
g_DSP_channel_idx_lookup_for_volume[0] = 0xf;
g_DSP_channel_idx_lookup_for_volume[1] = 0x10;
g_DSP_channel_idx_lookup_for_volume[2] = 0;
g_DSP_channel_idx_lookup_for_volume[3] = 0xe;
DAT_200010c0 = 0x33;
g_baud_192000 = 0x4b00;
g_baud_rate_for_upload_routine = 250000;
g_unknown_48000_or_96000_model_based = 48000;
DAT_200011dc = 0;
g_Override_Volume_Level_For_SetVolume_B = 0;
g_unknown_channel_idx_lookup[1] = 0x14;
DAT_2000124c = 0x2b6;
DAT_2000124e = 0x26b;
DAT_20001250 = 0x220;
DAT_20001252 = 0x301;
DAT_20001254 = 0x1d5;
DAT_20001256 = 0x18a;
DAT_20001258 = 0;
DAT_2000125a = 0;
DAT_2000125c = 0;
DAT_2000125e = 0;
uRam20001260 = 0;
uRam20001262 = 0;
uRam20001264 = 0;
uRam20001266 = 0;
uRam20001268 = 0;
uRam2000126a = 0;
g_Supported_DSP_OS_Version = 0x31;
g_short_120_or_0_depending_on_model = 0x78;
return;
case 0xb:
g_useFixedPointForAddonVolume = 0;
DAT_20000e9a = 0x1824;
DAT_20000ea3 = 3;
DAT_20000ea4 = 7;
DAT_20000ea6 = 0;
g_DSP_Reference_Volume_Level = 0x1000000;
DAT_20000eb0 = 0x2314;
DAT_20000fb2 = 0xaedc;
g_someRemoteAddressUsedIn0x2cmd = 0xf533;
DAT_200010b6 = 1;
g_DSP_channel_idx_lookup_for_volume[0] = 0x22f8;
g_DSP_channel_idx_lookup_for_volume[1] = 0x22f7;
g_DSP_channel_idx_lookup_for_volume[2] = 0x22f9;
g_DSP_channel_idx_lookup_for_volume[3] = 0x22fa;
DAT_200010c0 = 0x2f;
g_baud_192000 = 0x4b00;
g_baud_rate_for_upload_routine = 0x38400;
g_unknown_48000_or_96000_model_based = 96000;
DAT_200011dc = 0;
g_Override_Volume_Level_For_SetVolume_B = 6;
g_unknown_channel_idx_lookup[1] = 0x22fc;
g_unknown_channel_idx_lookup[2] = 0x22fb;
DAT_2000124c = 0x1b7c;
DAT_2000124e = 0x1dd4;
DAT_20001250 = 0x1e1f;
DAT_20001252 = 0x1d89;
DAT_20001254 = 0x1d3e;
DAT_20001256 = 0x1cf3;
DAT_20001258 = 0x1ca8;
DAT_2000125a = 0x1c5d;
DAT_2000125c = 0x1c12;
DAT_2000125e = 0x1bc7;
uRam20001260 = 0;
uRam20001262 = 0;
uRam20001264 = 0;
uRam20001266 = 0;
uRam20001268 = 0;
uRam2000126a = 0;
g_Supported_DSP_OS_Version = 0x37;
g_short_120_or_0_depending_on_model = 0;
return;
case 0xc:
g_short_120_or_0_depending_on_model = 0;
g_Supported_DSP_OS_Version = 0x35;
DAT_2000125e = 0;
DAT_2000125c = 0;
DAT_2000125a = 0x9c2;
DAT_20001258 = 0xa0d;
DAT_20001256 = 0xa58;
DAT_20001254 = 0xaa3;
DAT_20001252 = 0xaee;
DAT_20001250 = 0xb39;
DAT_2000124e = 0xb84;
DAT_2000124c = 0x977;
g_unknown_channel_idx_lookup[2] = 0xfc5;
g_unknown_channel_idx_lookup[1] = 0xfc6;
g_Override_Volume_Level_For_SetVolume_B = 6;
g_baud_rate_for_upload_routine = 0x38400;
DAT_200010c0 = 0x2f;
g_DSP_channel_idx_lookup_for_volume[3] = 0xfc4;
g_DSP_channel_idx_lookup_for_volume[2] = 0xfc3;
g_DSP_channel_idx_lookup_for_volume[1] = 0xfc1;
g_DSP_channel_idx_lookup_for_volume[0] = 0xfc2;
g_someRemoteAddressUsedIn0x2cmd = 0xf533;
DAT_20000fb2 = 0x8680;
DAT_20000eb0 = 0xfe6;
g_DSP_Reference_Volume_Level = 0x1000000;
DAT_20000ea6 = 0;
DAT_20000ea4 = 7;
DAT_20000e9a = 0x680;
g_useFixedPointForAddonVolume = 0;
uRam2000126a = 0;
uRam20001268 = 0;
uRam20001266 = 0;
uRam20001264 = 0;
uRam20001262 = 0;
uRam20001260 = 0;
DAT_200011dc = 0;
g_baud_192000 = 0x4b00;
DAT_200010b6 = 1;
DAT_20000ea3 = 3;
g_unknown_48000_or_96000_model_based = 48000;
return;
case 0xd:
g_short_120_or_0_depending_on_model = 0x78;
DAT_20000eb0 = 0x79;
g_Override_Volume_Level_For_SetVolume_B = 0;
g_useFixedPointForAddonVolume = 0x80;
g_DSP_Reference_Volume_Level = 0x800000;
g_DSP_channel_idx_lookup_for_volume[0] = 0xe;
g_DSP_channel_idx_lookup_for_volume[1] = 0xf;
g_DSP_channel_idx_lookup_for_volume[3] = 0xd;
g_DSP_channel_idx_lookup_for_volume[2] = 0;
g_unknown_channel_idx_lookup[1] = 0x12;
g_someRemoteAddressUsedIn0x2cmd = 0x1240;
g_Supported_DSP_OS_Version = 0x33;
g_addonVolumeChannelAddress_1 = 0x10;
g_addonVolumeChannelAddress_2_BoomBoxMode? = 0;
DAT_20000ea6 = 0x8a;
DAT_20000e9a = 0;
DAT_20000ea4 = 8;
DAT_2000124c = 0x40a;
DAT_2000124e = 0x3bf;
DAT_20001250 = 0x374;
DAT_20001252 = 0x329;
DAT_20001254 = 0x1fd;
DAT_20001256 = 0x248;
DAT_20001258 = 0x293;
DAT_2000125a = 0x2de;
break;
case 0xe[HELIX V EIGHT DSP]:
DAT_20000fb2 = 0x99e8;
g_short_120_or_0_depending_on_model = 0;
DAT_20000eb0 = 0xc3a;
g_Override_Volume_Level_For_SetVolume_B = 6;
g_useFixedPointForAddonVolume = 0;
g_DSP_Reference_Volume_Level = 0x1000000;
g_DSP_channel_idx_lookup_for_volume[0] = 0xc10;
g_DSP_channel_idx_lookup_for_volume[1] = 0xc0f;
g_DSP_channel_idx_lookup_for_volume[2] = 0xc11;
g_DSP_channel_idx_lookup_for_volume[3] = 0xc12;
g_unknown_channel_idx_lookup[2] = 0xc13;
g_unknown_channel_idx_lookup[1] = 0xc14;
g_someRemoteAddressUsedIn0x2cmd = 0xf533;
g_Supported_DSP_OS_Version = 0x32;
DAT_20000ea6 = 0;
DAT_20000e9a = 0xa0;
DAT_20000ea4 = 7;
DAT_2000124c = 0x42a;
DAT_2000124e = 0x637;
DAT_20001250 = 0x5ec;
DAT_20001252 = 0x5a1;
DAT_20001254 = 0x556;
DAT_20001256 = 0x50b;
DAT_20001258 = 0x4c0;
DAT_2000125a = 0x475;
DAT_2000125c = 0x682;
DAT_2000125e = 0x6cd;
goto code_r0x00401a28;
case 0xf:
DAT_20000fb2 = 0xa9c4;
DAT_20000eb0 = 0x11fd;
g_DSP_channel_idx_lookup_for_volume[0] = 0x11d9;
g_DSP_channel_idx_lookup_for_volume[1] = 0x11d8;
g_DSP_channel_idx_lookup_for_volume[2] = 0x11da;
g_DSP_channel_idx_lookup_for_volume[3] = 0x11db;
g_unknown_channel_idx_lookup[2] = 0x11dc;
g_unknown_channel_idx_lookup[1] = 0x11dd;
g_Supported_DSP_OS_Version = 0x34;
DAT_20000e9a = 0x870;
DAT_2000124c = 0xb77;
DAT_2000124e = 0xd84;
DAT_20001250 = 0xd39;
DAT_20001252 = 0xcee;
DAT_20001254 = 0xca3;
DAT_20001256 = 0xc58;
DAT_20001258 = 0xc0d;
DAT_2000125a = 0xbc2;
DAT_2000125c = 0;
DAT_2000125e = 0;
goto code_r0x004018ee;
case 0x10:
g_short_120_or_0_depending_on_model = 0;
DAT_20000eb0 = 0x5f;
g_Override_Volume_Level_For_SetVolume_B = 0;
g_useFixedPointForAddonVolume = 0;
g_DSP_Reference_Volume_Level = 0x800000;
g_DSP_channel_idx_lookup_for_volume[0] = 0xe;
g_DSP_channel_idx_lookup_for_volume[1] = 0xf;
g_DSP_channel_idx_lookup_for_volume[2] = 0xd;
g_DSP_channel_idx_lookup_for_volume[3] = 0;
g_unknown_channel_idx_lookup[2] = 0x12;
g_someRemoteAddressUsedIn0x2cmd = 0x1240;
g_Supported_DSP_OS_Version = 0x32;
g_addonVolumeChannelAddress_1 = 0x10;
g_addonVolumeChannelAddress_2_BoomBoxMode? = 0;
DAT_20000ea6 = 0;
DAT_20000e9a = 0;
DAT_20000ea4 = 8;
DAT_2000124c = 0x35b;
DAT_2000124e = 0x310;
DAT_20001250 = 0x2c5;
DAT_20001252 = 0x27a;
DAT_20001254 = 0x199;
DAT_20001256 = 0x1e4;
DAT_20001258 = 0x22f;
DAT_2000125a = 0;
DAT_2000125c = 0;
DAT_2000125e = 0;
goto code_r0x00401a28;
case 0x12:
DAT_20000fb2 = 0x7bc8;
DAT_20000eb0 = 0x1ac7;
g_Override_Volume_Level_For_SetVolume_B = 6;
g_useFixedPointForAddonVolume = 0;
g_short_120_or_0_depending_on_model = 0;
g_DSP_Reference_Volume_Level = 0x1000000;
g_DSP_channel_idx_lookup_for_volume[0] = 0x1aa2;
g_DSP_channel_idx_lookup_for_volume[1] = 0x1aa3;
g_DSP_channel_idx_lookup_for_volume[2] = 0x1aa1;
g_DSP_channel_idx_lookup_for_volume[3] = 0x1aa0;
g_unknown_channel_idx_lookup[2] = 0x1aa4;
g_unknown_channel_idx_lookup[1] = 0x1aa5;
g_someRemoteAddressUsedIn0x2cmd = 0xf533;
g_Supported_DSP_OS_Version = 0x32;
DAT_20000ea6 = 0;
DAT_20000e9a = 0x1144;
DAT_20000ea4 = 7;
DAT_2000124c = 0x145c;
DAT_2000124e = 0x14a7;
DAT_20001250 = 0x14f2;
DAT_20001252 = 0x153d;
DAT_20001254 = 0x1588;
DAT_20001256 = 0x15d3;
DAT_20001258 = 0x161e;
DAT_2000125a = 0x1669;
break;
case 0x13:
DAT_20000fb2 = 0xaee0;
DAT_20000eb0 = 0x2315;
g_DSP_channel_idx_lookup_for_volume[0] = 0x22f8;
g_DSP_channel_idx_lookup_for_volume[1] = 0x22f7;
g_DSP_channel_idx_lookup_for_volume[2] = 0x22f9;
g_DSP_channel_idx_lookup_for_volume[3] = 0x22fa;
g_unknown_channel_idx_lookup[2] = 0x22fb;
g_unknown_channel_idx_lookup[1] = 0x22fc;
g_volumeChannelAddress_Digital:Coax = 0x22ff;
g_Supported_DSP_OS_Version = 0x31;
DAT_20000e9a = 0x1824;
DAT_2000124c = 0x1b7c;
DAT_2000124e = 0x1dd4;
DAT_20001250 = 0x1e1f;
DAT_20001252 = 0x1d89;
DAT_20001254 = 0x1d3e;
DAT_20001256 = 0x1cf3;
DAT_20001258 = 0x1ca8;
DAT_2000125a = 0x1c5d;
DAT_2000125c = 0x1c12;
DAT_2000125e = 0x1bc7;
code_r0x004018ee:
g_short_120_or_0_depending_on_model = 0;
g_Override_Volume_Level_For_SetVolume_B = 6;
g_someRemoteAddressUsedIn0x2cmd = 0xf533;
g_DSP_Reference_Volume_Level = 0x1000000;
DAT_20000ea6 = 0;
DAT_20000ea4 = 7;
g_useFixedPointForAddonVolume = 0;
g_unknown_48000_or_96000_model_based = 96000;
goto code_r0x004018fc;
case 0x14:
DAT_20000fb2 = 0x7f28;
g_short_120_or_0_depending_on_model = 0;
DAT_20000eb0 = 0x1def;
g_Override_Volume_Level_For_SetVolume_B = 6;
g_useFixedPointForAddonVolume = 0;
g_DSP_Reference_Volume_Level = 0x1000000;
g_DSP_channel_idx_lookup_for_volume[0] = 0x1dc9;
g_DSP_channel_idx_lookup_for_volume[1] = 0x1dca;
g_DSP_channel_idx_lookup_for_volume[2] = 0x1dc8;
g_DSP_channel_idx_lookup_for_volume[3] = 0x1dc7;
g_unknown_channel_idx_lookup[2] = 0x1dcb;
g_unknown_channel_idx_lookup[1] = 0x1dcc;
g_someRemoteAddressUsedIn0x2cmd = 0xf533;
g_Supported_DSP_OS_Version = 0x31;
g_addonVolumeChannelAddress_1 = 0;
DAT_20000ea6 = 0;
DAT_20000e9a = 0x1300;
DAT_20000ea4 = 8;
DAT_2000124c = 0x165b;
DAT_2000124e = 0x16a6;
DAT_20001250 = 0x16f1;
DAT_20001252 = 0x173c;
DAT_20001254 = 0x1787;
DAT_20001256 = 0x17d2;
DAT_20001258 = 0x181d;
DAT_2000125a = 0x1868;
DAT_2000125c = 0x18b3;
goto LAB_00401dac;
case 0x15[MATCH UP 7BMW]:
g_Supported_DSP_OS_Version = 0x33;
goto code_r0x00401e30;
case 0x16[MATCH UP 7DSP]:
g_Supported_DSP_OS_Version = 0x34;
code_r0x00401e30:
g_short_120_or_0_depending_on_model = 0;
g_unknown_channel_idx_lookup[2] = 0x143e;
g_unknown_channel_idx_lookup[1] = 0x143f;
g_Override_Volume_Level_For_SetVolume_B = 6;
g_DSP_channel_idx_lookup_for_volume[3] = 0x143a;
g_DSP_channel_idx_lookup_for_volume[2] = 0x143b;
g_DSP_channel_idx_lookup_for_volume[1] = 0x143d;
g_DSP_channel_idx_lookup_for_volume[0] = 0x143c;
g_someRemoteAddressUsedIn0x2cmd = 0xf533;
DAT_20000fb2 = 0x6000;
DAT_20000eb0 = 0x145f;
g_DSP_Reference_Volume_Level = 0x1000000;
g_useFixedPointForAddonVolume = 0;
DAT_20000ea6 = 0;
DAT_20000e9a = 0x6000;
DAT_20000ea4 = 7;
DAT_2000124c = 0x5e7;
DAT_2000124e = 0x632;
DAT_20001250 = 0x2b6;
DAT_20001252 = 0x301;
DAT_20001254 = 0x7d6;
DAT_20001256 = 0x54e;
DAT_20001258 = 0x599;
DAT_2000125a = 0x34c;
}
DAT_2000125c = 0;
LAB_00401dac:
DAT_2000125e = 0;
code_r0x00401a28:
g_unknown_48000_or_96000_model_based = 48000;
code_r0x004018fc:
uRam2000126a = 0;
uRam20001268 = 0;
uRam20001266 = 0;
uRam20001264 = 0;
uRam20001262 = 0;
uRam20001260 = 0;
DAT_200011dc = 0;
g_baud_rate_for_upload_routine = 0x38400;
g_baud_192000 = 0x4b00;
DAT_200010c0 = 0x2f;
DAT_200010b6 = 1;
DAT_20000ea3 = 3;
DAT_200075cf = 1;
switchD_0040111a_caseD_5:
return;
}
DspModelIdEnum
CMD_QueryDspModel_0x8(undefined4 param_1,undefined4 param_2,undefined4 param_3,undefined4 param_4)
{
int iVar1;
DspModelIdEnum model;
undefined4 local_1c;
undefined4 uStack_18;
undefined4 local_14;
model = 0x8;
CMD_BUFFER_OP_ID = 0x8;
local_1c = param_2;
uStack_18 = param_3;
local_14 = param_4;
iVar1 = DSP_Transact_Command(1,174);
if (iVar1 == 0) {
DAT_20000af5 = DAT_20000af5 + 1;
model = ~0xff[DEMO];
if (1 < DAT_20000af5) {
g_some_os_version_or_model_related_bit? = '\x01';
g_some_os_version_B = g_Supported_DSP_OS_Version;
g_some_os_version_A = g_Supported_DSP_OS_Version;
DAT_20006dbc = 1;
strcpy(g_char[16+]_bluetooth?/HEC_module_name,"Helix Bluetooth");
model = 0xff[DEMO];
}
}
else {
g_some_os_version_or_model_related_bit? = USART0_READ_BUF_PAYLOAD&SUM[5];
g_some_os_version_B = USART0_READ_BUF_PAYLOAD&SUM[7];
g_some_os_version_A = USART0_READ_BUF_PAYLOAD&SUM[9];
local_1c._0_1_ = USART0_READ_BUF_PAYLOAD&SUM[0x8e];
local_1c._1_1_ = USART0_READ_BUF_PAYLOAD&SUM[0x8f];
local_1c._2_1_ = USART0_READ_BUF_PAYLOAD&SUM[0x90];
local_1c._3_1_ = USART0_READ_BUF_PAYLOAD&SUM[0x91];
uStack_18._0_1_ = USART0_READ_BUF_PAYLOAD&SUM[0x92];
uStack_18._1_1_ = USART0_READ_BUF_PAYLOAD&SUM[0x93];
uStack_18._2_1_ = USART0_READ_BUF_PAYLOAD&SUM[0x94];
uStack_18._3_1_ = USART0_READ_BUF_PAYLOAD&SUM[0x95];
local_14 = CONCAT31(local_14._1_3_,USART0_READ_BUF_PAYLOAD&SUM[0x96]);
DAT_20000af5 = 0;
iVar1 = strncmp((char *)&local_1c,"DSP-PRO",9);
if (iVar1 == 0) {
CMD_QueryHECBluetoothOrUsbEtcModule_0x13();
model = 0xb;
}
else {
iVar1 = strncmp((char *)&local_1c,"PP52 ",9);
if (iVar1 == 0) {
model = 7;
}
else {
iVar1 = strncmp((char *)&local_1c,"PP82 ",9);
if (iVar1 != 0) {
iVar1 = strncmp((char *)&local_1c,"HELIX ",9);
if (iVar1 == 0) {
model = 0x9[HELIX DSP];
}
else {
iVar1 = strncmp((char *)&local_1c,"P SIX DSP",9);
if (iVar1 == 0) {
CMD_QueryHECBluetoothOrUsbEtcModule_0x13();
model = 0xc;
}
else {
iVar1 = strncmp((char *)&local_1c,"MATCH-DSP",9);
if (iVar1 == 0) {
model = 10;
}
else {
iVar1 = strncmp((char *)&local_1c,"NOX4-DSP ",9);
if (iVar1 == 0) {
model = 4;
}
else {
iVar1 = strncmp((char *)&local_1c,"2PSIX DSP",9);
if (iVar1 == 0) {
CMD_QueryHECBluetoothOrUsbEtcModule_0x13();
model = 0xf;
}
else {
iVar1 = strncmp((char *)&local_1c,"PP62 ",9);
if (iVar1 == 0) {
CMD_QueryHECBluetoothOrUsbEtcModule_0x13();
model = 0xd;
}
else {
iVar1 = strncmp((char *)&local_1c,"M52DSP",6);
if (iVar1 == 0) {
model = 0x10;
}
else {
iVar1 = strncmp((char *)&local_1c,"i-DSP6",6);
if (iVar1 == 0) {
model = 0x11;
}
else {
iVar1 = strncmp((char *)&local_1c,"V8 DSP",6);
if (iVar1 == 0) {
CMD_QueryHECBluetoothOrUsbEtcModule_0x13();
model = 0xe[HELIX V EIGHT DSP];
}
else {
iVar1 = strncmp((char *)&local_1c,"DSP2",4);
if (iVar1 == 0) {
CMD_QueryHECBluetoothOrUsbEtcModule_0x13();
model = 0x12;
}
else {
iVar1 = strncmp((char *)&local_1c,"2DSP-PRO",8);
if (iVar1 == 0) {
CMD_QueryHECBluetoothOrUsbEtcModule_0x13();
model = 0x13;
}
else {
iVar1 = strncmp((char *)&local_1c,"PP86DSP",7);
if (iVar1 == 0) {
CMD_QueryHECBluetoothOrUsbEtcModule_0x13();
model = 0x14;
}
else {
iVar1 = strncmp((char *)&local_1c,"UP7BMW",6);
if (iVar1 == 0) {
CMD_QueryHECBluetoothOrUsbEtcModule_0x13();
model = 0x15[MATCH UP 7BMW];
}
else {
iVar1 = strncmp((char *)&local_1c,"UP7DSP",6);
if (iVar1 == 0) {
CMD_QueryHECBluetoothOrUsbEtcModule_0x13();
model = 0x16[MATCH UP 7DSP];
}
else {
model = 0x17;
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
return model;
}
void System_Info_UI(int param_1)
{
int iVar1;
char *src;
undefined4 uVar2;
char local_138 [32];
undefined1 auStack_118 [256];
iVar1 = FUN_00405738();
if (iVar1 == 0) goto LAB_004088f0;
DAT_200075c2 = 0;
local_138[0] = '\0';
local_138[1] = '\0';
local_138[2] = '\0';
local_138[3] = '\0';
g_RedirectedMenuIdIfSavedMenuIdIs0x29 = g_ActiveMenuID;
if (g_WasPin1LowAtStartup == false) {
uVar2 = 0x41;
}
else {
uVar2 = 0x42;
}
memset(local_138 + 4,0,0x1c);
if (g_DSP_MODEL_ID == 0xe[HELIX V EIGHT DSP]) {
src = "HELIX V EIGHT DSP";
}
else if (g_DSP_MODEL_ID < 0xf) {
if (g_DSP_MODEL_ID == 0x9[HELIX DSP]) {
src = "HELIX DSP";
}
else if (g_DSP_MODEL_ID < 10) {
if (g_DSP_MODEL_ID == 7) {
src = "MATCH PP 52DSP";
}
else if (g_DSP_MODEL_ID < 8) {
if (g_DSP_MODEL_ID == 4) {
src = "BRAX NOX4 DSP";
}
else {
LAB_00408812:
src = "UNKNOWN";
}
}
else {
src = "MATCH PP 82DSP";
}
}
else if (g_DSP_MODEL_ID == 0xb) {
src = "HELIX DSP PRO";
}
else if (g_DSP_MODEL_ID < 0xb) {
src = "MATCH DSP";
}
else if (g_DSP_MODEL_ID == 0xc) {
src = "HELIX P SIX DSP";
}
else {
if (g_DSP_MODEL_ID != 0xd) goto LAB_00408812;
src = "MATCH PP 62DSP";
}
}
else if (g_DSP_MODEL_ID == 0x13) {
src = "HELIX DSP PRO Mk2 ";
}
else if (g_DSP_MODEL_ID < 0x14) {
if (g_DSP_MODEL_ID == 0x10) {
src = "MATCH M5DSP";
}
else if (g_DSP_MODEL_ID < 0x10) {
src = "HELIX P SIX DSP Mk 2";
}
else if (g_DSP_MODEL_ID == 0x11) {
src = "i-DSP6";
}
else {
if (g_DSP_MODEL_ID != 0x12) goto LAB_00408812;
src = "HELIX DSP.2";
}
}
else if (g_DSP_MODEL_ID == 0x15[MATCH UP 7BMW]) {
src = "MATCH UP 7BMW";
}
else if (g_DSP_MODEL_ID < 0x15[MATCH UP 7BMW]) {
src = "MATCH PP86DSP";
}
else if (g_DSP_MODEL_ID == 0x16[MATCH UP 7DSP]) {
src = "MATCH UP 7DSP";
}
else {
if (g_DSP_MODEL_ID != 0xff[DEMO]) goto LAB_00408812;
src = "DEMO";
}
strcpy(local_138,src);
if (DAT_200075cf == '\0') {
if (g_Last_Error == 0) {
UI_draw_paragraph(auStack_118,"%s%s%s%s%s%s%s%s%s%c%s%s%c","System Information:","\n\n",
"Current Firmware Version: ","01.77","\n","Connected Product: ",local_138,
"\n","Supported DSP OS Version: ",g_Supported_DSP_OS_Version,"\n",
"Hardware Version: ",uVar2);
}
else {
UI_draw_paragraph(auStack_118,"%s%s%s%s%s%s%s%s%s%c%s%s%c%s%s%li","System Information:","\n\n"
,"Current Firmware Version: ","01.77","\n","Connected Product: ",local_138,
"\n","Supported DSP OS Version: ",g_Supported_DSP_OS_Version,"\n",
"Hardware Version: ",uVar2,"\n","Last Error: ",g_Last_Error);
}
}
else if (g_Last_Error == 0) {
UI_draw_paragraph(auStack_118,"%s%s%s%s%s%s%s%s%s%c%s%s%c%s%s%4.1f%s%4.1f%s",
"System Information:","\n\n","Current Firmware Version: ","01.77","\n",
"Connected Product: ",local_138,"\n","Supported DSP OS Version: ",
g_Supported_DSP_OS_Version,"\n","Hardware Version: ",uVar2,"\n",&DAT_004209d7)
;
}
else {
UI_draw_paragraph(auStack_118,"%s%s%s%s%s%s%s%s%s%c%s%s%c%s%s%4.1f%s%4.1f%s%s%s%li",
"System Information:","\n\n","Current Firmware Version: ","01.77","\n",
"Connected Product: ",local_138,"\n","Supported DSP OS Version: ",
g_Supported_DSP_OS_Version,"\n","Hardware Version: ",uVar2,"\n",&DAT_004209d7)
;
}
FUN_0040605c();
FUN_00405c88();
UI_draw_header(auStack_118,0xa0,100,&DAT_004250d6,0x1ef0,0xffff,0x12,2);
LAB_004088f0:
FUN_004057d8();
FUN_00405a20();
if (param_1 == 1) {
X_ToggleMute();
}
return;
}