@REM ============================================================================
@REM CreateS19_SrecCat_V2.bat - S19 File Generator using srec_cat for TC23X/TC33X/TC36X
@REM ============================================================================
@REM Version: V3 - Uses srec_cat with pre-CRC FlashDriver files
@REM            - Output address space: Non-cached (0xA0XXXXXX)
@REM            - Maps cacheable 0x80 data to non-cacheable 0xA0 output
@REM ============================================================================
@REM
@REM This script uses srec_cat to generate S19 files with CRC32 checksums.
@REM It uses pre-calculated CRC FlashDriver files (*_CRC.hex) from FlashDriver\
@REM directory. srec_cat only calculates PFlash CRC (RAM CRC is pre-calculated).
@REM
@REM ============================================================================
@REM
@REM Usage:
@REM   CreateS19_SrecCat_V2.bat <ProjDirPath> <BuildArtifactFileBaseName> <WorkspaceLoc> [ConfigName] [ChipType]
@REM
@REM Parameters:
@REM   %1 - Project directory path (ADS: ${ProjDirPath})
@REM   %2 - Build artifact base name without extension (ADS: ${BuildArtifactFileBaseName})
@REM   %3 - Workspace root directory path (ADS: ${workspace_loc})
@REM   %4 - Build configuration directory name (ADS: ${ConfigName}), default: Debug
@REM   %5 - Chip type (TC23X/TC33X/TC36X), auto-detected from ADS CPU field if not specified
@REM
@REM ADS Post-build steps configuration example:
@REM   TC23X: cmd /c "${workspace_loc}\S19_gen\CreateS19_SrecCat_V2.bat" "${ProjDirPath}" "${BuildArtifactFileBaseName}" "${workspace_loc}" "${ConfigName}" "TC23X"
@REM   TC33X: cmd /c "${workspace_loc}\S19_gen\CreateS19_SrecCat_V2.bat" "${ProjDirPath}" "${BuildArtifactFileBaseName}" "${workspace_loc}" "${ConfigName}" "TC33X"
@REM   TC36X: cmd /c "${workspace_loc}\S19_gen\CreateS19_SrecCat_V2.bat" "${ProjDirPath}" "${BuildArtifactFileBaseName}" "${workspace_loc}" "${ConfigName}" "TC36X"
@REM
@REM ============================================================================

@echo off
@REM Use call :main to isolate parameter expansion from parsing context
call :main %*
exit /b %errorlevel%

:main
setlocal enabledelayedexpansion

@REM ============================================================================
@REM Capture all parameters at the very beginning of :main subroutine
@REM ============================================================================
set "ARG1=%~1"
set "ARG2=%~2"
set "ARG3=%~3"
set "ARG4=%~4"
set "ARG5=%~5"

@REM ============================================================================
@REM Parameter validation - using goto instead of if blocks
@REM ============================================================================
if not "!ARG1!"=="" goto :arg1_ok
echo [ERROR] Missing parameter: Project directory path
echo.
echo Usage:
echo   CreateS19_SrecCat_V2.bat ^<ProjDirPath^> ^<BuildArtifactFileBaseName^> ^<WorkspaceLoc^> [ConfigName] [ChipType]
echo.
echo ADS Post-build steps example:
echo   cmd /c "${workspace_loc}\S19_gen\CreateS19_SrecCat_V2.bat" "${ProjDirPath}" "${BuildArtifactFileBaseName}" "${workspace_loc}" "${ConfigName}" "TC23X"
exit /b 1
:arg1_ok

if not "!ARG2!"=="" goto :arg2_ok
echo [ERROR] Missing parameter: Build artifact base name
exit /b 1
:arg2_ok

if not "!ARG3!"=="" goto :arg3_ok
echo [ERROR] Missing parameter: Workspace root directory
exit /b 1
:arg3_ok

@REM ============================================================================
@REM Path configuration
@REM ============================================================================
set "PROJ_DIR=!ARG1!"
set "BUILD_NAME=!ARG2!"
set "WORKSPACE=!ARG3!"

@REM Build configuration directory name (default: Debug)
set "CONFIG_NAME=!ARG4!"
if "!CONFIG_NAME!"=="" set "CONFIG_NAME=Debug"

@REM Convert forward slashes to backslashes (ADS uses forward slashes)
set "PROJ_DIR=!PROJ_DIR:/=\!"
set "WORKSPACE=!WORKSPACE:/=\!"

@REM ============================================================================
@REM Chip type detection - using goto instead of if/else if chain
@REM Priority: explicit parameter > ADS .cproject CPU field
@REM ============================================================================
set "CHIP_TYPE="

@REM Priority 1: explicit parameter (TC23X/TC33X/TC36X format)
if /i "!ARG5!"=="TC23X" set "CHIP_TYPE=TC23X" & goto :chip_detected
if /i "!ARG5!"=="TC33X" set "CHIP_TYPE=TC33X" & goto :chip_detected
if /i "!ARG5!"=="TC36X" set "CHIP_TYPE=TC36X" & goto :chip_detected

@REM Priority 2: detect from ADS .cproject file CPU field
@REM Use piped findstr to avoid echo issues with XML special characters (< > &)
set "CPROJECT_FILE=!PROJ_DIR!\.cproject"
if not exist "!CPROJECT_FILE!" goto :chip_detect_failed

findstr /i "com.tasking.ctc.cpu" "!CPROJECT_FILE!" 2>nul | findstr /i "value=\"tc23x\"" >nul
if !errorlevel! equ 0 set "CHIP_TYPE=TC23X" & goto :chip_detected
findstr /i "com.tasking.ctc.cpu" "!CPROJECT_FILE!" 2>nul | findstr /i "value=\"tc33x\"" >nul
if !errorlevel! equ 0 set "CHIP_TYPE=TC33X" & goto :chip_detected
findstr /i "com.tasking.ctc.cpu" "!CPROJECT_FILE!" 2>nul | findstr /i "value=\"tc36x\"" >nul
if !errorlevel! equ 0 set "CHIP_TYPE=TC36X" & goto :chip_detected

:chip_detect_failed
echo [ERROR] Cannot detect chip type. Please specify as 5th parameter ^(TC23X/TC33X/TC36X^) or ensure ADS .cproject file exists with CPU field.
exit /b 1

:chip_detected
echo [INFO] Chip type: !CHIP_TYPE!

@REM Generate S19 header string: YYYY/MM/DD Username
for /f "tokens=2 delims==" %%a in ('wmic os get localdatetime /value') do set "DT=%%a"
set "S19_HEADER=!DT:~0,4!/!DT:~4,2!/!DT:~6,2! %USERNAME%"

@REM ============================================================================
@REM Chip-specific configuration - using goto instead of if/else if
@REM Uses pre-CRC FlashDriver files (*_CRC.hex suffix)
@REM ============================================================================
goto :config_!CHIP_TYPE!

:config_TC23X
set "FLS_DRV_NAME=Tc234_Project_FLS_CRC.hex"
set "DUAL_PFLASH=0"
set "DFLASH_SECTOR_COUNT=16"
set "DS_0=0xAF000000 0xAF002000 0xAF001FFC"
set "DS_1=0xAF002000 0xAF004000 0xAF003FFC"
set "DS_2=0xAF004000 0xAF006000 0xAF005FFC"
set "DS_3=0xAF006000 0xAF008000 0xAF007FFC"
set "DS_4=0xAF008000 0xAF00A000 0xAF009FFC"
set "DS_5=0xAF00A000 0xAF00C000 0xAF00BFFC"
set "DS_6=0xAF00C000 0xAF00E000 0xAF00DFFC"
set "DS_7=0xAF00E000 0xAF010000 0xAF00FFFC"
set "DS_8=0xAF010000 0xAF012000 0xAF011FFC"
set "DS_9=0xAF012000 0xAF014000 0xAF013FFC"
set "DS_10=0xAF014000 0xAF016000 0xAF015FFC"
set "DS_11=0xAF016000 0xAF018000 0xAF017FFC"
set "DS_12=0xAF018000 0xAF01A000 0xAF019FFC"
set "DS_13=0xAF01A000 0xAF01C000 0xAF01BFFC"
set "DS_14=0xAF01C000 0xAF01E000 0xAF01DFFC"
set "DS_15=0xAF01E000 0xAF020000 0xAF01FFFC"
goto :config_done

:config_TC33X
set "FLS_DRV_NAME=Tc334_Project_FLS_CRC.hex"
set "DUAL_PFLASH=0"
goto :config_dflash_tc3xx

:config_TC36X
set "FLS_DRV_NAME=Tc364_Project_FLS_CRC.hex"
set "DUAL_PFLASH=1"
goto :config_dflash_tc3xx

:config_dflash_tc3xx
set "DFLASH_SECTOR_COUNT=32"
set "DS_0=0xAF000000 0xAF001000 0xAF000FFC"
set "DS_1=0xAF001000 0xAF002000 0xAF001FFC"
set "DS_2=0xAF002000 0xAF003000 0xAF002FFC"
set "DS_3=0xAF003000 0xAF004000 0xAF003FFC"
set "DS_4=0xAF004000 0xAF005000 0xAF004FFC"
set "DS_5=0xAF005000 0xAF006000 0xAF005FFC"
set "DS_6=0xAF006000 0xAF007000 0xAF006FFC"
set "DS_7=0xAF007000 0xAF008000 0xAF007FFC"
set "DS_8=0xAF008000 0xAF009000 0xAF008FFC"
set "DS_9=0xAF009000 0xAF00A000 0xAF009FFC"
set "DS_10=0xAF00A000 0xAF00B000 0xAF00AFFC"
set "DS_11=0xAF00B000 0xAF00C000 0xAF00BFFC"
set "DS_12=0xAF00C000 0xAF00D000 0xAF00CFFC"
set "DS_13=0xAF00D000 0xAF00E000 0xAF00DFFC"
set "DS_14=0xAF00E000 0xAF00F000 0xAF00EFFC"
set "DS_15=0xAF00F000 0xAF010000 0xAF00FFFC"
set "DS_16=0xAF010000 0xAF011000 0xAF010FFC"
set "DS_17=0xAF011000 0xAF012000 0xAF011FFC"
set "DS_18=0xAF012000 0xAF013000 0xAF012FFC"
set "DS_19=0xAF013000 0xAF014000 0xAF013FFC"
set "DS_20=0xAF014000 0xAF015000 0xAF014FFC"
set "DS_21=0xAF015000 0xAF016000 0xAF015FFC"
set "DS_22=0xAF016000 0xAF017000 0xAF016FFC"
set "DS_23=0xAF017000 0xAF018000 0xAF017FFC"
set "DS_24=0xAF018000 0xAF019000 0xAF018FFC"
set "DS_25=0xAF019000 0xAF01A000 0xAF019FFC"
set "DS_26=0xAF01A000 0xAF01B000 0xAF01AFFC"
set "DS_27=0xAF01B000 0xAF01C000 0xAF01BFFC"
set "DS_28=0xAF01C000 0xAF01D000 0xAF01CFFC"
set "DS_29=0xAF01D000 0xAF01E000 0xAF01DFFC"
set "DS_30=0xAF01E000 0xAF01F000 0xAF01EFFC"
set "DS_31=0xAF01F000 0xAF020000 0xAF01FFFC"
goto :config_done

:config_done

@REM Common configuration (srec_cat uses half-open intervals [start, end))
@REM Output address space: Non-cacheable (0xA0XXXXXX)
@REM PFlash0: 0xA0010000 to 0xA0200000 (half-open, includes 0xA01fffff)
@REM PFlash0 CRC calculation: 0xA0010000 to 0xA01ffffc (excludes CRC location)
@REM PFlash0 CRC storage: 0xA01ffffc (4 bytes)
set "PFLASH0_START=0xA0010000"
set "PFLASH0_END_OPEN=0xA0200000"
set "PFLASH0_CRC_ADDR=0xA01ffffc"

@REM PFlash1: 0xA0300000 to 0xA0500000 (half-open, includes 0xA04fffff)
@REM PFlash1 CRC calculation: 0xA0300000 to 0xA04ffffc (excludes CRC location)
@REM PFlash1 CRC storage: 0xA04ffffc (4 bytes)
set "PFLASH1_START=0xA0300000"
set "PFLASH1_END_OPEN=0xA0500000"
set "PFLASH1_CRC_ADDR=0xA04ffffc"

@REM Cacheable address mapping (0x80) - source data to be remapped to 0xA0
@REM 0x80XXXXXX (cacheable) -> 0xA0XXXXXX (non-cacheable), offset = +0x20000000
set "PFLASH0_START_C=0x80010000"
set "PFLASH0_END_OPEN_C=0x80200000"
set "PFLASH1_START_C=0x80300000"
set "PFLASH1_END_OPEN_C=0x80500000"
set "REMAP_OFFSET=0x20000000"

@REM Note: REMAP_OFFSET is applied to 0x80 data to map to 0xA0 output space
@REM The script handles mixed 0x80+0xA0 addresses automatically

@REM ============================================================================
@REM Base variable setup
@REM ============================================================================
set "SREC_CAT_EXE=%~dp0srecord\srec_cat.exe"
set "SREC_INFO_EXE=%~dp0srecord\srec_info.exe"
set "FLS_DRV_FILE=%~dp0FlashDriver\!FLS_DRV_NAME!"
set "APP_HEX_FILE=!PROJ_DIR!\!CONFIG_NAME!\!BUILD_NAME!.hex"
set "OUTPUT_FILE=!PROJ_DIR!\!CONFIG_NAME!\!BUILD_NAME!.s19"

echo ============================================================================
echo CreateS19 SrecCat V3 - S19 File Generator for !CHIP_TYPE! [srec_cat version]
echo ============================================================================
echo.
echo [INFO] Project directory: "!PROJ_DIR!"
echo [INFO] Build name: "!BUILD_NAME!"
echo [INFO] Workspace: "!WORKSPACE!"
echo [INFO] Config name: "!CONFIG_NAME!"
echo [INFO] Chip type: !CHIP_TYPE!
echo [INFO] Output file: "!OUTPUT_FILE!"
echo.

@REM ============================================================================
@REM File existence check - using goto instead of if blocks
@REM ============================================================================
echo [CHECK] Verifying required files...

if exist "!SREC_CAT_EXE!" goto :srec_cat_ok
echo [ERROR] srec_cat.exe not found: "!SREC_CAT_EXE!"
exit /b 1
:srec_cat_ok
echo [OK] srec_cat.exe found

if exist "!FLS_DRV_FILE!" goto :flsdrv_ok
echo [ERROR] Flash driver file not found: "!FLS_DRV_FILE!"
exit /b 1
:flsdrv_ok
echo [OK] Flash driver file found: !FLS_DRV_NAME! (pre-CRC)

if exist "!APP_HEX_FILE!" goto :apphex_ok
echo [ERROR] Application HEX file not found: "!APP_HEX_FILE!"
exit /b 1
:apphex_ok
echo [OK] Application HEX file found

@REM ============================================================================
@REM Check for PFlash data in HEX file (supports mixed 0x80+0xA0 addresses)
@REM 0x80XXXXXX = cacheable (will remap to 0xA0), 0xA0XXXXXX = non-cacheable (normal)
@REM ============================================================================
set "HAS_PFLASH_80=0"
set "HAS_PFLASH_A0=0"

@REM Check for 0x80 PFlash EA records
findstr /c:":020000048001" "!APP_HEX_FILE!" >nul 2>&1
if !errorlevel! equ 0 set "HAS_PFLASH_80=1"

@REM Check for 0xA0 PFlash EA records
findstr /c:":02000004A0" "!APP_HEX_FILE!" >nul 2>&1
if !errorlevel! equ 0 set "HAS_PFLASH_A0=1"

if "!HAS_PFLASH_80!!HAS_PFLASH_A0!"=="00" goto :pflash_addr_fail
goto :pflash_addr_ok

:pflash_addr_fail
echo [ERROR] No PFlash data found in HEX file.
echo [ERROR] Expected PFlash EA records at 0x80 or 0xA0 address range.
echo [ERROR] Please verify linker configuration. Aborting S19 generation.
exit /b 1

:pflash_addr_ok
if "!HAS_PFLASH_80!"=="1" echo [INFO] PFlash cacheable address ^(0x80^) data detected - will remap to 0xA0
if "!HAS_PFLASH_A0!"=="1" echo [OK] PFlash non-cacheable address ^(0xA0^) data detected

@REM ============================================================================
@REM Verify no PFlash data exists before 0xA0010000 (or 0x80010000)
@REM The application PFlash must start at 0xA0010000, not earlier
@REM ============================================================================
echo [CHECK] Verifying PFlash start address...
set "PFLASH_PREDATA=0"

@REM Check if any data exists in [0x80000000, 0x80010000) - should be empty
"!SREC_INFO_EXE!" "!APP_HEX_FILE!" -Intel -crop 0x80000000 0x80010000 2>nul | findstr /i "Data:" | findstr /v /i "none" >nul 2>&1
if !errorlevel! equ 0 set "PFLASH_PREDATA=1"

@REM Also check non-cacheable mirror [0xA0000000, 0xA0010000)
if "!PFLASH_PREDATA!"=="0" (
    "!SREC_INFO_EXE!" "!APP_HEX_FILE!" -Intel -crop 0xA0000000 0xA0010000 2>nul | findstr /i "Data:" | findstr /v /i "none" >nul 2>&1
    if !errorlevel! equ 0 set "PFLASH_PREDATA=1"
)

if "!PFLASH_PREDATA!"=="1" goto :pflash_start_fail
echo [OK] PFlash start address verified: no data before 0xA0010000
goto :pflash_start_ok

:pflash_start_fail
echo [ERROR] PFlash data found before 0xA0010000.
echo [ERROR] Application PFlash must start at 0xA0010000 (or 0x80010000 before remap).
echo [ERROR] Please check linker configuration. Aborting S19 generation.
exit /b 1

:pflash_start_ok

@REM ============================================================================
@REM Check for DFlash data in HEX file
@REM DFlash address starts with 0xAF, no cache/non-cache mirror, no offset needed
@REM ============================================================================
set "HAS_DFLASH=0"
findstr /c:":02000004AF" "!APP_HEX_FILE!" >nul 2>&1
if !errorlevel! equ 0 set "HAS_DFLASH=1"

if "!HAS_DFLASH!"=="1" echo [OK] DFlash data detected ^(0xAF^)
if "!HAS_DFLASH!"=="0" echo [INFO] No DFlash data in HEX file

@REM ============================================================================
@REM Copy Flash Driver to build output directory
@REM ============================================================================
echo [GENERATE] Creating S19 file with srec_cat...

copy "!FLS_DRV_FILE!" "!PROJ_DIR!\!CONFIG_NAME!\!FLS_DRV_NAME!" >nul
if !errorlevel! equ 0 goto :copy_ok
echo [ERROR] Failed to copy flash driver file
exit /b 1
:copy_ok

@REM ============================================================================
@REM Generate S19 file with srec_cat - using goto for branching
@REM Calculate both RAM CRC and PFlash CRC
@REM ============================================================================
pushd "!PROJ_DIR!\!CONFIG_NAME!"

if "!DUAL_PFLASH!"=="1" goto :run_dual_pflash
goto :run_single_pflash

:run_single_pflash
@REM TC23X/TC33X single PFLASH configuration
@REM Uses pre-CRC FlashDriver - only PFlash CRC calculated here
@REM Two-step process:
@REM   Step 1: Pre-merge 0x80 and 0xA0 PFlash data into temp file (resolves address mirror conflicts)
@REM           Maps 0x80 (cacheable) data to 0xA0 (non-cacheable) output space
@REM   Step 2: Generate S19 from merged data (CRC calculation + FlashDriver + data output)
@REM Note: If either 0x80 or 0xA0 range has no data, crop returns empty (no impact)

@REM Step 1: Merge 0x80 and 0xA0 PFlash data into temp file (remap 0x80 -> 0xA0)
echo [INFO] Pre-processing: merging cacheable ^(0x80^) to non-cacheable ^(0xA0^) address space...
"!SREC_CAT_EXE!" ^
  "!BUILD_NAME!.hex" -Intel -crop !PFLASH0_START_C! !PFLASH0_END_OPEN_C! -offset !REMAP_OFFSET! ^
  "!BUILD_NAME!.hex" -Intel -crop !PFLASH0_START! !PFLASH0_END_OPEN! ^
  -redundant-bytes=ignore -contradictory-bytes=ignore ^
  -o __temp_pflash0.hex -Intel

if !errorlevel! neq 0 (
    echo [ERROR] Failed to merge PFlash data
    del /f /q __temp_pflash*.hex >nul 2>&1
    popd
    exit /b 1
)

@REM DFlash processing (if DFlash data detected)
set "DFLASH_CMD_ARGS="
if "!HAS_DFLASH!"=="1" call :process_dflash

@REM Step 2: Generate S19 from merged data
"!SREC_CAT_EXE!" ^
  ^( __temp_pflash0.hex -Intel -fill 0xFF !PFLASH0_START! !PFLASH0_END_OPEN! -crop !PFLASH0_START! !PFLASH0_CRC_ADDR! -CRC32_Big_Endian !PFLASH0_CRC_ADDR! -crop !PFLASH0_CRC_ADDR! !PFLASH0_END_OPEN! ^) ^
  "!FLS_DRV_NAME!" -Intel ^
  ^( __temp_pflash0.hex -Intel -fill 0xFF !PFLASH0_START! !PFLASH0_END_OPEN! -exclude !PFLASH0_CRC_ADDR! !PFLASH0_END_OPEN! ^) ^
  !DFLASH_CMD_ARGS! ^
  -o "!BUILD_NAME!.s19" -address-length=4 -obs=32 -header="!S19_HEADER!"

goto :srec_cat_done

:run_dual_pflash
@REM TC36X dual PFLASH configuration
@REM Uses pre-CRC FlashDriver - only PFlash CRC calculated here
@REM Two-step process:
@REM   Step 1: Pre-merge 0x80 and 0xA0 PFlash data into temp files (resolves address mirror conflicts)
@REM           Maps 0x80 (cacheable) data to 0xA0 (non-cacheable) output space
@REM   Step 2: Generate S19 from merged data (CRC calculation + FlashDriver + data output)
@REM Note: If either 0x80 or 0xA0 range has no data, crop returns empty (no impact)

@REM Step 1a: Merge PFlash0 (remap 0x80 -> 0xA0)
echo [INFO] Pre-processing: merging cacheable ^(0x80^) to non-cacheable ^(0xA0^) address space...
"!SREC_CAT_EXE!" ^
  "!BUILD_NAME!.hex" -Intel -crop !PFLASH0_START_C! !PFLASH0_END_OPEN_C! -offset !REMAP_OFFSET! ^
  "!BUILD_NAME!.hex" -Intel -crop !PFLASH0_START! !PFLASH0_END_OPEN! ^
  -redundant-bytes=ignore -contradictory-bytes=ignore ^
  -o __temp_pflash0.hex -Intel

if !errorlevel! neq 0 (
    echo [ERROR] Failed to merge PFlash0 data
    del /f /q __temp_pflash*.hex >nul 2>&1
    popd
    exit /b 1
)

@REM Step 1b: Merge PFlash1 (remap 0x80 -> 0xA0)
"!SREC_CAT_EXE!" ^
  "!BUILD_NAME!.hex" -Intel -crop !PFLASH1_START_C! !PFLASH1_END_OPEN_C! -offset !REMAP_OFFSET! ^
  "!BUILD_NAME!.hex" -Intel -crop !PFLASH1_START! !PFLASH1_END_OPEN! ^
  -redundant-bytes=ignore -contradictory-bytes=ignore ^
  -o __temp_pflash1.hex -Intel

if !errorlevel! neq 0 (
    echo [ERROR] Failed to merge PFlash1 data
    del /f /q __temp_pflash*.hex >nul 2>&1
    popd
    exit /b 1
)

@REM DFlash processing (if DFlash data detected)
set "DFLASH_CMD_ARGS="
if "!HAS_DFLASH!"=="1" call :process_dflash

@REM Step 2: Generate S19 from merged data
"!SREC_CAT_EXE!" ^
  ^( __temp_pflash0.hex -Intel -fill 0xFF !PFLASH0_START! !PFLASH0_END_OPEN! -crop !PFLASH0_START! !PFLASH0_CRC_ADDR! -CRC32_Big_Endian !PFLASH0_CRC_ADDR! -crop !PFLASH0_CRC_ADDR! !PFLASH0_END_OPEN! ^) ^
  ^( __temp_pflash1.hex -Intel -fill 0xFF !PFLASH1_START! !PFLASH1_END_OPEN! -crop !PFLASH1_START! !PFLASH1_CRC_ADDR! -CRC32_Big_Endian !PFLASH1_CRC_ADDR! -crop !PFLASH1_CRC_ADDR! !PFLASH1_END_OPEN! ^) ^
  "!FLS_DRV_NAME!" -Intel ^
  ^( __temp_pflash0.hex -Intel -fill 0xFF !PFLASH0_START! !PFLASH0_END_OPEN! -exclude !PFLASH0_CRC_ADDR! !PFLASH0_END_OPEN! ^) ^
  ^( __temp_pflash1.hex -Intel -fill 0xFF !PFLASH1_START! !PFLASH1_END_OPEN! -exclude !PFLASH1_CRC_ADDR! !PFLASH1_END_OPEN! ^) ^
  !DFLASH_CMD_ARGS! ^
  -o "!BUILD_NAME!.s19" -address-length=4 -obs=32 -header="!S19_HEADER!"

goto :srec_cat_done

:srec_cat_done
if !errorlevel! equ 0 goto :srec_cat_success
del /f /q __temp_pflash*.hex >nul 2>&1
del /f /q !FLS_DRV_NAME! >nul 2>&1
popd
echo [ERROR] Failed to generate S19 file
exit /b 1
:srec_cat_success
@REM Clean up temporary files
del /f /q __temp_pflash0.hex >nul 2>&1
del /f /q __temp_pflash1.hex >nul 2>&1
del /f /q __temp_dflash*.hex >nul 2>&1

@REM Verify S19 file address ranges using srec_info
echo.
echo [VERIFY] S19 file address ranges:
"!SREC_INFO_EXE!" "!BUILD_NAME!.s19"

popd

@REM ============================================================================
@REM Clean up temporary files
@REM ============================================================================
del /f /q "!PROJ_DIR!\!CONFIG_NAME!\!FLS_DRV_NAME!" >nul 2>&1
echo [OK] S19 file generated successfully

@REM ============================================================================
@REM Verify output file - using goto instead of if blocks
@REM ============================================================================
echo.
echo [CHECK] Verifying output file...
if exist "!OUTPUT_FILE!" goto :output_ok
echo [ERROR] Output file was not created: "!OUTPUT_FILE!"
exit /b 1
:output_ok
echo [OK] Output file created successfully

echo.
echo ============================================================================
echo [SUCCESS] S19 file generated successfully for !CHIP_TYPE! using srec_cat
echo [INFO] Used pre-CRC FlashDriver: !FLS_DRV_NAME!
echo Output: "!OUTPUT_FILE!"
echo ============================================================================

endlocal
exit /b 0

@REM ============================================================================
@REM DFlash processing subroutine - Continuous Block CRC mode
@REM Called via "call :process_dflash" from main flow
@REM
@REM Scans all DFlash sectors to find the first and last sectors with data,
@REM then treats the entire range as one continuous block:
@REM   - Fills gaps with 0x00
@REM   - Calculates a single CRC32 Big Endian over the entire block
@REM   - Places CRC at the last 4 bytes of the block
@REM ============================================================================

:process_dflash
echo [INFO] Processing DFlash sectors (continuous block mode)...

set /a DFLASH_LAST_INDEX=!DFLASH_SECTOR_COUNT!-1
set "DFLASH_FIRST_SECT=-1"
set "DFLASH_LAST_SECT=-1"

@REM Stage 1: Scan all sectors to find first and last with data
for /L %%i in (0,1,!DFLASH_LAST_INDEX!) do (
    set "FSIZE=0"
    for /f "tokens=1,2" %%a in ("!DS_%%i!") do (
        set "DSECT_START=%%a"
        set "DSECT_END=%%b"
    )
    @REM Crop to DFlash range (exclude UCB 0xAF400000+) then crop to sector
    "!SREC_CAT_EXE!" "!BUILD_NAME!.hex" -Intel -crop 0xAF000000 0xAF020000 -crop !DSECT_START! !DSECT_END! -o __temp_dsect_check.hex -Intel 2>nul
    for %%f in (__temp_dsect_check.hex) do set "FSIZE=%%~zf"
    if !FSIZE! GTR 20 (
        if !DFLASH_FIRST_SECT! EQU -1 set "DFLASH_FIRST_SECT=%%i"
        set "DFLASH_LAST_SECT=%%i"
    )
    if exist __temp_dsect_check.hex del __temp_dsect_check.hex
)

if !DFLASH_FIRST_SECT! EQU -1 (
    echo [INFO] No DFlash sectors with actual data found
    goto :eof
)

@REM Stage 2: Get block boundaries from first/last sector definitions
@REM Uses call to force re-evaluation of DS_%index% variable names
call :get_dflash_block_range

echo [INFO]   DFlash continuous block: sectors !DFLASH_FIRST_SECT! ~ !DFLASH_LAST_SECT!
echo [INFO]   Block range: !BLOCK_START! - !BLOCK_END! ^(CRC at !CRC_ADDR!^)

@REM Stage 3: Generate continuous block with fill + CRC
@REM - crop to DFlash range first (exclude UCB)
@REM - crop to block range, fill gaps with 0x00
@REM - calculate CRC32 Big Endian over [BLOCK_START, CRC_ADDR)
@REM - place CRC at CRC_ADDR (last 4 bytes of block)
"!SREC_CAT_EXE!" ^
  ^( "!BUILD_NAME!.hex" -Intel -crop 0xAF000000 0xAF020000 -crop !BLOCK_START! !BLOCK_END! -fill 0x00 !BLOCK_START! !BLOCK_END! -crop !BLOCK_START! !CRC_ADDR! -CRC32_Big_Endian !CRC_ADDR! -crop !CRC_ADDR! !BLOCK_END! ^) ^
  ^( "!BUILD_NAME!.hex" -Intel -crop 0xAF000000 0xAF020000 -crop !BLOCK_START! !BLOCK_END! -fill 0x00 !BLOCK_START! !BLOCK_END! -exclude !CRC_ADDR! !BLOCK_END! ^) ^
  -o __temp_dflash.hex -Intel

if !errorlevel! neq 0 (
    echo [ERROR] Failed to generate DFlash continuous block with CRC
    set "DFLASH_CMD_ARGS="
    set "GLOBAL_ERROR=1"
    goto :eof
)

set "DFLASH_CMD_ARGS=__temp_dflash.hex -Intel"
echo [INFO] DFlash continuous block processed successfully
goto :eof

:get_dflash_block_range
@REM Extract BLOCK_START from first sector's start address (token 1)
for /f "tokens=1" %%a in ("!DS_%DFLASH_FIRST_SECT%!") do set "BLOCK_START=%%a"
@REM Extract BLOCK_END and CRC_ADDR from last sector's end address (token 2) and CRC address (token 3)
for /f "tokens=2,3" %%a in ("!DS_%DFLASH_LAST_SECT%!") do (
    set "BLOCK_END=%%a"
    set "CRC_ADDR=%%b"
)
goto :eof
