Subversion Repositories pentevo

Rev

Blame | Last modification | View Log | Download | RSS feed | ?url?

  1. /* p2hex.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* Konvertierung von AS-P-Dateien nach Hex                                   */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12. #include <ctype.h>
  13. #include <string.h>
  14. #include <stdarg.h>
  15.  
  16. #include "version.h"
  17. #include "be_le.h"
  18. #include "bpemu.h"
  19. #include "nls.h"
  20. #include "nlmessages.h"
  21. #include "p2hex.rsc"
  22. #ifdef _USE_MSH
  23. # include "p2hex.msh"
  24. #endif
  25. #include "ioerrs.h"
  26. #include "strutil.h"
  27. #include "chunks.h"
  28. #include "stringlists.h"
  29. #include "msg_level.h"
  30. #include "cmdarg.h"
  31.  
  32. #include "toolutils.h"
  33. #include "headids.h"
  34.  
  35. static const char *HexSuffix = ".hex";
  36. #define MaxLineLen 254
  37. #define AVRLEN_DEFAULT 3
  38. #define DefaultCFormat "dSEl"
  39.  
  40. typedef void (*ProcessProc)(
  41. #ifdef __PROTOS__
  42. const char *FileName, LongWord Offset
  43. #endif
  44. );
  45.  
  46. static FILE *TargFile;
  47. static String TargName, CFormat;
  48. static Byte ForceSegment;
  49.  
  50. static LongWord StartAdr[SegCount], StopAdr[SegCount], LineLen, EntryAdr;
  51. static LargeInt Relocate;
  52. static Boolean StartAuto, StopAuto, AutoErase, EntryAdrPresent;
  53. static Word Seg, Ofs;
  54. static LongWord Dummy;
  55. static Byte IntelMode;
  56. static Byte MultiMode;   /* 0=8M, 1=16, 2=8L, 3=8H */
  57. static Byte MinMoto;
  58. static Boolean Rec5;
  59. static Boolean SepMoto;
  60. static LongWord AVRLen;
  61.  
  62. static Boolean RelAdr;
  63.  
  64. static unsigned FormatOccured;
  65. enum
  66. {
  67.   eMotoOccured = (1 << 0),
  68.   eIntelOccured = (1 << 1),
  69.   eMOSOccured = (1 << 2),
  70.   eDSKOccured = (1 << 3),
  71.   eMico8Occured = (1 << 4)
  72. };
  73. static Byte MaxMoto, MaxIntel;
  74.  
  75. static tHexFormat DestFormat;
  76.  
  77. static ChunkList UsedList;
  78.  
  79. static String CTargName;
  80. static unsigned NumCBlocks;
  81.  
  82. static void DefStartStopAdr(LongWord SegMask)
  83. {
  84.   Byte Seg;
  85.  
  86.   for (Seg = 0; Seg < SegCount; Seg++)
  87.     if (SegMask & (1 << Seg))
  88.     {
  89.       StartAdr[Seg] = 0;
  90.       StopAdr[Seg] = (Seg == SegData) ? 0x1fff : 0x7fff;
  91.     }
  92. }
  93.  
  94. static void Filename2CName(char *pDest, const char *pSrc)
  95. {
  96.   char Trans;
  97.   const char *pPos;
  98.   Boolean Written = False;
  99.  
  100.   pPos = strrchr(pSrc, PATHSEP);
  101. #ifdef DRSEP
  102.   if (!pPos)
  103.     pPos = strchr(pSrc, DRSEP);
  104. #endif
  105.   if (pPos)
  106.     pSrc = pPos + 1;
  107.  
  108.   for (; *pSrc; pSrc++)
  109.   {
  110.     Trans = (*pSrc == '-') ? '_' : *pSrc;
  111.     if (isalnum(*pSrc) || (*pSrc == '_'))
  112.     {
  113.       *pDest++ = Trans;
  114.       Written = True;
  115.     }
  116.     else if (Written)
  117.       break;
  118.   }
  119.   *pDest = '\0';
  120. }
  121.  
  122. static void GetCBlockName(char *pDest, size_t DestSize, unsigned Num)
  123. {
  124.   if (Num > 0)
  125.     as_snprintf(pDest, DestSize, "_%u", Num + 1);
  126.   else
  127.     *pDest = '\0';
  128. }
  129.  
  130. static void ParamError(Boolean InEnv, char *Arg)
  131. {
  132.   fprintf(stderr, "%s%s\n", getmessage(InEnv ? Num_ErrMsgInvEnvParam : Num_ErrMsgInvParam), Arg);
  133.   fprintf(stderr, "%s\n", getmessage(Num_ErrMsgProgTerm));
  134. }
  135.  
  136. static void OpenTarget(void)
  137. {
  138.   TargFile = fopen(TargName, "w");
  139.   if (!TargFile)
  140.     ChkIO(TargName);
  141. }
  142.  
  143. static void CloseTarget(void)
  144. {
  145.   if (EOF == fclose(TargFile))
  146.     ChkIO(TargName);
  147.   if (Magic != 0)
  148.     unlink(TargName);
  149. }
  150.  
  151. static void PrCData(FILE *pTargFile, char Ident, const char *pName,
  152.                     const char *pCTargName, const char *pCBlockName, LongWord Value)
  153. {
  154.   const char *pFormat;
  155.  
  156.   if (strchr(CFormat, toupper(Ident)))
  157.     pFormat = "ul";
  158.   else if (strchr(CFormat, tolower(Ident)))
  159.     pFormat = "u";
  160.   else
  161.     return;
  162.  
  163.   chkio_fprintf(pTargFile, TargName, "#define %s%s_%s 0x%08lX%s\n",
  164.                 pCTargName, pCBlockName, pName,
  165.                 LoDWord(Value), pFormat);
  166. }
  167.  
  168. static void ProcessFile(const char *FileName, LongWord Offset)
  169. {
  170.   FILE *SrcFile;
  171.   Word TestID;
  172.   Byte InpHeader, InpCPU, InpSegment, InpGran;
  173.   LongWord InpStart, SumLen;
  174.   Word InpLen, TransLen;
  175.   Boolean doit, FirstBank = 0;
  176.   Boolean CDataLower = !!strchr(CFormat, 'd'),
  177.           CDataUpper = !!strchr(CFormat, 'D');
  178.   Byte Buffer[MaxLineLen];
  179.   Word *WBuffer = (Word *) Buffer;
  180.   LongWord ErgStart,
  181.            ErgStop = 0xfffffffful,
  182.            IntOffset = 0, MaxAdr;
  183.   LongInt NextPos;
  184.   LongWord ValidSegs;
  185.   Word ErgLen = 0, ChkSum = 0, RecCnt, Gran, HSeg;
  186.   String CBlockName;
  187.  
  188.   LongInt z;
  189.  
  190.   Byte MotRecType = 0;
  191.  
  192.   tHexFormat ActFormat;
  193.   const TFamilyDescr *FoundDscr;
  194.  
  195.   SrcFile = fopen(FileName, OPENRDMODE);
  196.   if (!SrcFile) ChkIO(FileName);
  197.  
  198.   if (!Read2(SrcFile, &TestID))
  199.     chk_wr_read_error(FileName);
  200.   if (TestID !=FileMagic)
  201.     FormatError(FileName, getmessage(Num_FormatInvHeaderMsg));
  202.  
  203.   if (msg_level >= e_msg_level_normal)
  204.     chkio_printf(OutName, "%s==>>%s", FileName, TargName);
  205.  
  206.   SumLen = 0;
  207.  
  208.   do
  209.   {
  210.     ReadRecordHeader(&InpHeader, &InpCPU, &InpSegment, &InpGran, FileName, SrcFile);
  211.  
  212.     if (InpHeader == FileHeaderStartAdr)
  213.     {
  214.       if (!Read4(SrcFile, &ErgStart))
  215.         chk_wr_read_error(FileName);
  216.       if (!EntryAdrPresent)
  217.       {
  218.         EntryAdr = ErgStart;
  219.         EntryAdrPresent = True;
  220.       }
  221.     }
  222.  
  223.     else if (InpHeader == FileHeaderDataRec)
  224.     {
  225.       Gran = InpGran;
  226.  
  227.       if ((ActFormat = DestFormat) == eHexFormatDefault)
  228.       {
  229.         FoundDscr = FindFamilyById(InpCPU);
  230.         if (!FoundDscr)
  231.           FormatError(FileName, getmessage(Num_FormatInvRecordHeaderMsg));
  232.         else
  233.           ActFormat = FoundDscr->HexFormat;
  234.       }
  235.  
  236.       if (ForceSegment != SegNone)
  237.         ValidSegs = (1 << ForceSegment);
  238.       else
  239.       {
  240.         ValidSegs = (1 << SegCode);
  241.         if (eHexFormatTiDSK == ActFormat)
  242.           ValidSegs |= (1 << SegData);
  243.       }
  244.  
  245.       switch (ActFormat)
  246.       {
  247.         case eHexFormatMotoS:
  248.         case eHexFormatIntel32:
  249.         case eHexFormatC:
  250.           MaxAdr = 0xfffffffful;
  251.           break;
  252.         case eHexFormatIntel16:
  253.           MaxAdr = 0xffff0ul + 0xffffu;
  254.           break;
  255.         case eHexFormatAtmel:
  256.           MaxAdr = (1 << (AVRLen << 3)) - 1;
  257.           break;
  258.         case eHexFormatMico8:
  259.           MaxAdr = 0xfffffffful;
  260.           break;
  261.         default:
  262.           MaxAdr = 0xffffu;
  263.       }
  264.  
  265.       if (!Read4(SrcFile, &InpStart))
  266.         chk_wr_read_error(FileName);
  267.       if (!Read2(SrcFile, &InpLen))
  268.         chk_wr_read_error(FileName);
  269.  
  270.       NextPos = ftell(SrcFile) + InpLen;
  271.       if (NextPos >= FileSize(SrcFile) - 1)
  272.         FormatError(FileName, getmessage(Num_FormatInvRecordLenMsg));
  273.  
  274.       doit = FilterOK(InpCPU) && (ValidSegs & (1 << InpSegment));
  275.  
  276.       if (doit)
  277.       {
  278.         InpStart += Offset;
  279.         ErgStart = max(StartAdr[InpSegment], InpStart);
  280.         ErgStop = min(StopAdr[InpSegment], InpStart + (InpLen/Gran) - 1);
  281.         doit = (ErgStop >= ErgStart);
  282.         if (doit)
  283.         {
  284.           ErgLen = (ErgStop + 1 - ErgStart) * Gran;
  285.           if (AddChunk(&UsedList, ErgStart, ErgStop - ErgStart + 1, True))
  286.             chkio_fprintf(stderr, OutName, " %s\n", getmessage(Num_ErrMsgOverlap));
  287.         }
  288.       }
  289.  
  290.       if (doit && (ErgStop > MaxAdr))
  291.         chkio_fprintf(stderr, OutName, " %s\n", getmessage(Num_ErrMsgAdrOverflow));
  292.  
  293.       if (doit)
  294.       {
  295.         /* an Anfang interessierender Daten */
  296.  
  297.         if (fseek(SrcFile, (ErgStart - InpStart) * Gran, SEEK_CUR) == -1)
  298.           ChkIO(FileName);
  299.  
  300.         /* Statistik, Anzahl Datenzeilen ausrechnen */
  301.  
  302.         RecCnt = ErgLen / LineLen;
  303.         if ((ErgLen % LineLen) !=0)
  304.           RecCnt++;
  305.  
  306.         /* relative Angaben ? */
  307.  
  308.         if (RelAdr)
  309.           ErgStart -= StartAdr[InpSegment];
  310.  
  311.         /* Auf Zieladressbereich verschieben */
  312.  
  313.         ErgStart += Relocate;
  314.  
  315.         /* Kopf einer Datenzeilengruppe */
  316.  
  317.         switch (ActFormat)
  318.         {
  319.           case eHexFormatMotoS:
  320.             if ((!(FormatOccured & eMotoOccured)) || (SepMoto))
  321.               chkio_fprintf(TargFile, TargName, "S0030000FC\n");
  322.             if ((ErgStop >> 24) != 0)
  323.               MotRecType = 2;
  324.             else if ((ErgStop >> 16) !=0)
  325.               MotRecType = 1;
  326.             else
  327.               MotRecType = 0;
  328.             if (MotRecType < (MinMoto - 1))
  329.               MotRecType = (MinMoto - 1);
  330.             if (MaxMoto < MotRecType)
  331.               MaxMoto = MotRecType;
  332.             if (Rec5)
  333.             {
  334.               ChkSum = Lo(RecCnt) + Hi(RecCnt) + 3;
  335.               chkio_fprintf(TargFile, TargName, "S503%04X%02X\n", LoWord(RecCnt), Lo(ChkSum ^ 0xff));
  336.             }
  337.             FormatOccured |= eMotoOccured;
  338.             break;
  339.           case eHexFormatMOS:
  340.             FormatOccured |= eMOSOccured;
  341.             break;
  342.           case eHexFormatIntel:
  343.             FormatOccured |= eIntelOccured;
  344.             IntOffset = 0;
  345.             break;
  346.           case eHexFormatIntel16:
  347.             FormatOccured |= eIntelOccured;
  348.             IntOffset = (ErgStart * Gran);
  349.             IntOffset -= IntOffset & 0x0f;
  350.             HSeg = IntOffset >> 4;
  351.             ChkSum = 4 + Lo(HSeg) + Hi(HSeg);
  352.             IntOffset /= Gran;
  353.             chkio_fprintf(TargFile, TargName, ":02000002%04X%02X\n", LoWord(HSeg), Lo(0x100 - ChkSum));
  354.             if (MaxIntel < 1)
  355.               MaxIntel = 1;
  356.             break;
  357.           case eHexFormatIntel32:
  358.             FormatOccured |= eIntelOccured;
  359.             IntOffset = (ErgStart * Gran);
  360.             IntOffset -= IntOffset & 0xffff;
  361.             HSeg = IntOffset >> 16;
  362.             ChkSum = 6 + Lo(HSeg) + Hi(HSeg);
  363.             IntOffset /= Gran;
  364.             chkio_fprintf(TargFile, TargName, ":02000004%04X%02X\n", LoWord(HSeg), Lo(0x100 - ChkSum));
  365.             if (MaxIntel < 2)
  366.               MaxIntel = 2;
  367.             FirstBank = False;
  368.             break;
  369.           case eHexFormatTek:
  370.             break;
  371.           case eHexFormatAtmel:
  372.             break;
  373.           case eHexFormatMico8:
  374.             break;
  375.           case eHexFormatTiDSK:
  376.             if (!(FormatOccured & eDSKOccured))
  377.             {
  378.               FormatOccured |= eDSKOccured;
  379.               chkio_fprintf(TargFile, TargName, "%s%s\n", getmessage(Num_DSKHeaderLine), TargName);
  380.             }
  381.             break;
  382.           case eHexFormatC:
  383.             GetCBlockName(CBlockName, sizeof(CBlockName), NumCBlocks);
  384.             PrCData(TargFile, 's', "start", CTargName, CBlockName, ErgStart);
  385.             PrCData(TargFile, 'l', "len", CTargName, CBlockName, ErgLen);
  386.             PrCData(TargFile, 'e', "end", CTargName, CBlockName, ErgStart + ErgLen - 1);
  387.             if (CDataLower || CDataUpper)
  388.               chkio_fprintf(TargFile, TargName, "static const unsigned char %s%s_data[] =\n{\n",
  389.                             CTargName, CBlockName);
  390.             break;
  391.           default:
  392.             break;
  393.         }
  394.  
  395.         /* Datenzeilen selber */
  396.  
  397.         while (ErgLen > 0)
  398.         {
  399.           /* evtl. Folgebank fuer Intel32 ausgeben */
  400.  
  401.           if ((ActFormat == eHexFormatIntel32) && (FirstBank))
  402.           {
  403.             IntOffset += (0x10000 / Gran);
  404.             HSeg = IntOffset >> 16;
  405.             ChkSum = 6 + Lo(HSeg) + Hi(HSeg);
  406.             chkio_fprintf(TargFile, TargName, ":02000004%04X%02X\n", LoWord(HSeg), Lo(0x100 - ChkSum));
  407.             FirstBank = False;
  408.           }
  409.  
  410.           /* Recordlaenge ausrechnen, fuer Intel32 auf 64K-Grenze begrenzen
  411.              Bei Atmel nur 2 Byte pro Zeile!
  412.              Bei Mico8 nur 4 Byte (davon ein Wort=18 Bit) pro Zeile! */
  413.  
  414.           TransLen = min(LineLen, ErgLen);
  415.           if ((ActFormat == eHexFormatIntel32) && ((ErgStart & 0xffff) + (TransLen/Gran) >= 0x10000))
  416.           {
  417.             TransLen = Gran * (0x10000 - (ErgStart & 0xffff));
  418.             FirstBank = True;
  419.           }
  420.           else if (ActFormat == eHexFormatAtmel)
  421.             TransLen = min(2, TransLen);
  422.           else if (ActFormat == eHexFormatMico8)
  423.             TransLen = min(4, TransLen);
  424.  
  425.           /* Start der Datenzeile */
  426.  
  427.           switch (ActFormat)
  428.           {
  429.             case eHexFormatMotoS:
  430.               chkio_fprintf(TargFile, TargName, "S%c%02X", '1' + MotRecType, Lo(TransLen + 3 + MotRecType));
  431.               ChkSum = TransLen + 3 + MotRecType;
  432.               if (MotRecType >= 2)
  433.               {
  434.                 chkio_fprintf(TargFile, TargName, "%02X", Lo(ErgStart >> 24));
  435.                 ChkSum += ((ErgStart >> 24) & 0xff);
  436.               }
  437.               if (MotRecType >= 1)
  438.               {
  439.                 chkio_fprintf(TargFile, TargName, "%02X", Lo(ErgStart >> 16));
  440.                 ChkSum += ((ErgStart >> 16) & 0xff);
  441.               }
  442.               chkio_fprintf(TargFile, TargName, "%04X", LoWord(ErgStart));
  443.               ChkSum += Hi(ErgStart) + Lo(ErgStart);
  444.               break;
  445.             case eHexFormatMOS:
  446.               chkio_fprintf(TargFile, TargName, ";%02X%04X", Lo(TransLen), LoWord(ErgStart));
  447.               ChkSum += TransLen + Lo(ErgStart) + Hi(ErgStart);
  448.               break;
  449.             case eHexFormatIntel:
  450.             case eHexFormatIntel16:
  451.             case eHexFormatIntel32:
  452.             {
  453.               Word WrTransLen;
  454.               LongWord WrErgStart;
  455.  
  456.               WrTransLen = (MultiMode < 2) ? TransLen : (TransLen / Gran);
  457.               WrErgStart = (ErgStart - IntOffset) * ((MultiMode < 2) ? Gran : 1);
  458.               chkio_fprintf(TargFile, TargName, ":%02X%04X00", Lo(WrTransLen), LoWord(WrErgStart));
  459.               ChkSum = Lo(WrTransLen) + Hi(WrErgStart) + Lo(WrErgStart);
  460.  
  461.               break;
  462.             }
  463.             case eHexFormatTek:
  464.               chkio_fprintf(TargFile, TargName, "/%04X%02X%02X", LoWord(ErgStart), Lo(TransLen),
  465.                             Lo(Lo(ErgStart) + Hi(ErgStart) + TransLen));
  466.               ChkSum = 0;
  467.               break;
  468.             case eHexFormatTiDSK:
  469.               chkio_fprintf(TargFile, TargName, "9%04X", LoWord(/*Gran**/ErgStart));
  470.               ChkSum = 0;
  471.               break;
  472.             case eHexFormatAtmel:
  473.               for (z = (AVRLen - 1) << 3; z >= 0; z -= 8)
  474.                 chkio_fprintf(TargFile, TargName, "%02X", Lo(ErgStart >> z));
  475.               if (EOF == fputc(':', TargFile))
  476.                 ChkIO(TargName);
  477.               break;
  478.             case eHexFormatMico8:
  479.               break;
  480.             case eHexFormatC:
  481.               chkio_fprintf(TargFile, TargName, "  ");
  482.               break;
  483.             default:
  484.               break;
  485.           }
  486.  
  487.           /* Daten selber */
  488.  
  489.           if (fread(Buffer, 1, TransLen, SrcFile) !=TransLen)
  490.             chk_wr_read_error(FileName);
  491.           if (MultiMode == 1)
  492.             switch (Gran)
  493.             {
  494.               case 4:
  495.                 DSwap(Buffer, TransLen);
  496.                 break;
  497.               case 2:
  498.                 WSwap(Buffer, TransLen);
  499.                 break;
  500.               case 1:
  501.                 break;
  502.             }
  503.           switch (ActFormat)
  504.           {
  505.             case eHexFormatTiDSK:
  506.               if (HostBigEndian)
  507.                 WSwap(WBuffer, TransLen);
  508.               for (z = 0; z < (TransLen / 2); z++)
  509.               {
  510.                 if (((ErgStart + z >= StartAdr[SegData]) && (ErgStart + z <= StopAdr[SegData]))
  511.                  || (InpSegment == SegData))
  512.                   chkio_fprintf(TargFile, TargName, "M%04X", LoWord(WBuffer[z]));
  513.                 else
  514.                   chkio_fprintf(TargFile, TargName, "B%04X", LoWord(WBuffer[z]));
  515.                 ChkSum += WBuffer[z];
  516.                 SumLen += Gran;
  517.               }
  518.               break;
  519.             case eHexFormatAtmel:
  520.               if (TransLen >= 2)
  521.               {
  522.                 chkio_fprintf(TargFile, TargName, "%04X", LoWord(WBuffer[0]));
  523.                 SumLen += 2;
  524.               }
  525.               else if (TransLen >= 1)
  526.               {
  527.                 chkio_fprintf(TargFile, TargName, "%04X", Lo(WBuffer[0]));
  528.                 SumLen++;
  529.               }
  530.               break;
  531.             case eHexFormatMico8:
  532.               if (TransLen >= 4)
  533.               {
  534.                 chkio_fprintf(TargFile, TargName, "%01X%02X%02X", Buffer[1] & 0x0f, Buffer[2] % 0xff, Buffer[3] & 0xff);
  535.                 SumLen += 4;
  536.               }
  537.               break;
  538.             case eHexFormatC:
  539.               if (CDataLower || CDataUpper)
  540.                 for (z = 0; z < (LongInt)TransLen; z++)
  541.                   if ((MultiMode < 2) || (z % Gran == MultiMode - 2))
  542.                   {
  543.                     chkio_fprintf(TargFile, TargName, CDataLower ? "0x%02x%s" : "0x%02X%s", (unsigned)Buffer[z],
  544.                                   (ErgLen - z > 1) ? "," : "");
  545.                     ChkSum += Buffer[z];
  546.                     SumLen++;
  547.                   }
  548.               break;
  549.             default:
  550.               for (z = 0; z < (LongInt)TransLen; z++)
  551.                 if ((MultiMode < 2) || (z % Gran == MultiMode - 2))
  552.                 {
  553.                   chkio_fprintf(TargFile, TargName, "%02X", Lo(Buffer[z]));
  554.                   ChkSum += Buffer[z];
  555.                   SumLen++;
  556.                 }
  557.           }
  558.  
  559.           /* Ende Datenzeile */
  560.  
  561.           switch (ActFormat)
  562.           {
  563.             case eHexFormatMotoS:
  564.               chkio_fprintf(TargFile, TargName, "%02X\n", Lo(ChkSum ^ 0xff));
  565.               break;
  566.             case eHexFormatMOS:
  567.               chkio_fprintf(TargFile, TargName, "%04X\n", LoWord(ChkSum));
  568.               break;
  569.             case eHexFormatIntel:
  570.             case eHexFormatIntel16:
  571.             case eHexFormatIntel32:
  572.               chkio_fprintf(TargFile, TargName, "%02X\n", Lo(1 + (ChkSum ^ 0xff)));
  573.               break;
  574.             case eHexFormatTek:
  575.               chkio_fprintf(TargFile, TargName, "%02X\n", Lo(ChkSum));
  576.               break;
  577.             case eHexFormatTiDSK:
  578.               chkio_fprintf(TargFile, TargName, "7%04XF\n", LoWord(ChkSum));
  579.               break;
  580.             case eHexFormatAtmel:
  581.             case eHexFormatMico8:
  582.             case eHexFormatC:
  583.               chkio_fprintf(TargFile, TargName, "\n");
  584.               break;
  585.             default:
  586.               break;
  587.           }
  588.  
  589.           /* Zaehler rauf */
  590.  
  591.           ErgLen -= TransLen;
  592.           ErgStart += TransLen/Gran;
  593.         }
  594.  
  595.         /* Ende der Datenzeilengruppe */
  596.  
  597.         switch (ActFormat)
  598.         {
  599.           case eHexFormatMotoS:
  600.             if (SepMoto)
  601.             {
  602.               chkio_fprintf(TargFile, TargName, "S%c%02X", '9' - MotRecType, Lo(3 + MotRecType));
  603.               for (z = 1; z <= 2 + MotRecType; z++)
  604.                 chkio_fprintf(TargFile, TargName, "%02X", 0);
  605.               chkio_fprintf(TargFile, TargName, "%02X\n", Lo(0xff - 3 - MotRecType));
  606.             }
  607.             break;
  608.           case eHexFormatMOS:
  609.             break;
  610.           case eHexFormatIntel:
  611.           case eHexFormatIntel16:
  612.           case eHexFormatIntel32:
  613.             break;
  614.           case eHexFormatTek:
  615.             break;
  616.           case eHexFormatTiDSK:
  617.             break;
  618.           case eHexFormatAtmel:
  619.             break;
  620.           case eHexFormatMico8:
  621.             break;
  622.           case eHexFormatC:
  623.             if (CDataLower || CDataUpper)
  624.             {
  625.               chkio_fprintf(TargFile, TargName, "};\n\n");
  626.               NumCBlocks++;
  627.             }
  628.             break;
  629.           default:
  630.             break;
  631.         };
  632.       }
  633.       if (fseek(SrcFile, NextPos, SEEK_SET) == -1)
  634.         ChkIO(FileName);
  635.     }
  636.     else
  637.       SkipRecord(InpHeader, FileName, SrcFile);
  638.   }
  639.   while (InpHeader !=0);
  640.  
  641.   if (msg_level >= e_msg_level_normal)
  642.   {
  643.     chkio_printf(OutName, " (");
  644.     chkio_printf(OutName, Integ32Format, SumLen);
  645.     chkio_printf(OutName, " %s)\n", getmessage((SumLen == 1) ? Num_Byte : Num_Bytes));
  646.   }
  647.   if (!SumLen)
  648.   {
  649.     if (fputs(getmessage(Num_WarnEmptyFile), stderr) == EOF) ChkIO(OutName);
  650.   }
  651.  
  652.   if (EOF == fclose(SrcFile))
  653.     ChkIO(FileName);
  654. }
  655.  
  656. static ProcessProc CurrProcessor;
  657. static LongWord CurrOffset;
  658.  
  659. static void Callback(char *Name)
  660. {
  661.   CurrProcessor(Name, CurrOffset);
  662. }
  663.  
  664. static void ProcessGroup(const char *GroupName_O, ProcessProc Processor)
  665. {
  666.   String Ext, GroupName;
  667.  
  668.   CurrProcessor = Processor;
  669.   strmaxcpy(GroupName, GroupName_O, STRINGSIZE);
  670.   strmaxcpy(Ext, GroupName, STRINGSIZE);
  671.   if (!RemoveOffset(GroupName, &CurrOffset))
  672.   {
  673.     ParamError(False, Ext);
  674.     exit(1);
  675.   }
  676.   AddSuffix(GroupName, STRINGSIZE, getmessage(Num_Suffix));
  677.  
  678.   if (!DirScan(GroupName, Callback))
  679.     fprintf(stderr, "%s%s%s\n", getmessage(Num_ErrMsgNullMaskA), GroupName, getmessage(Num_ErrMsgNullMaskB));
  680. }
  681.  
  682. static void MeasureFile(const char *FileName, LongWord Offset)
  683. {
  684.   FILE *f;
  685.   Byte Header, InpCPU, InpSegment, Gran;
  686.   Word Length, TestID;
  687.   LongWord Adr, EndAdr;
  688.   LongInt NextPos;
  689.   LongWord ValidSegs;
  690.   Boolean doit;
  691.  
  692.   f = fopen(FileName, OPENRDMODE);
  693.   if (!f)
  694.     ChkIO(FileName);
  695.  
  696.   if (!Read2(f, &TestID))
  697.     chk_wr_read_error(FileName);
  698.   if (TestID !=FileMagic)
  699.     FormatError(FileName, getmessage(Num_FormatInvHeaderMsg));
  700.  
  701.   do
  702.   {
  703.     ReadRecordHeader(&Header, &InpCPU, &InpSegment, &Gran, FileName, f);
  704.  
  705.     if (Header == FileHeaderDataRec)
  706.     {
  707.       if (!Read4(f, &Adr))
  708.         chk_wr_read_error(FileName);
  709.       if (!Read2(f, &Length))
  710.         chk_wr_read_error(FileName);
  711.       NextPos = ftell(f) + Length;
  712.       if (NextPos > FileSize(f))
  713.         FormatError(FileName, getmessage(Num_FormatInvRecordLenMsg));
  714.  
  715.       if (ForceSegment != SegNone)
  716.         ValidSegs = (1 << ForceSegment);
  717.       else
  718.         ValidSegs = (1 << SegCode) | (1 << SegData);
  719.  
  720.       doit = FilterOK(InpCPU) && (ValidSegs & (1 << InpSegment));
  721.  
  722.       if (doit)
  723.       {
  724.         Adr += Offset;
  725.         EndAdr = Adr + (Length/Gran) - 1;
  726.         if (StartAuto)
  727.           if (StartAdr[InpSegment] > Adr)
  728.             StartAdr[InpSegment] = Adr;
  729.         if (StopAuto)
  730.           if (EndAdr > StopAdr[InpSegment])
  731.             StopAdr[InpSegment] = EndAdr;
  732.       }
  733.  
  734.       fseek(f, NextPos, SEEK_SET);
  735.     }
  736.     else
  737.      SkipRecord(Header, FileName, f);
  738.   }
  739.   while(Header !=0);
  740.  
  741.   fclose(f);
  742. }
  743.  
  744. /* ------------------------------------------- */
  745.  
  746. static as_cmd_result_t CMD_AdrRange(Boolean Negate, const char *Arg)
  747. {
  748.   if (Negate)
  749.   {
  750.     DefStartStopAdr(1 << SegCode);
  751.     return e_cmd_ok;
  752.   }
  753.   else
  754.     return CMD_Range(&StartAdr[SegCode], &StopAdr[SegCode],
  755.                      &StartAuto, &StopAuto, Arg);
  756. }
  757.  
  758. static as_cmd_result_t CMD_RelAdr(Boolean Negate, const char *Arg)
  759. {
  760.   UNUSED(Arg);
  761.  
  762.   RelAdr = (!Negate);
  763.   return e_cmd_ok;
  764. }
  765.  
  766. static as_cmd_result_t CMD_AdrRelocate(Boolean Negate, const char *Arg)
  767. {
  768.   Boolean ok;
  769.   UNUSED(Arg);
  770.  
  771.   if (Negate)
  772.   {
  773.     Relocate = 0;
  774.     return e_cmd_ok;
  775.   }
  776.   else
  777.   {
  778.     Relocate = ConstLongInt(Arg, &ok, 10);
  779.     if (!ok) return e_cmd_err;
  780.  
  781.     return e_cmd_arg;
  782.   }
  783. }
  784.  
  785. static as_cmd_result_t CMD_Rec5(Boolean Negate, const char *Arg)
  786. {
  787.   UNUSED(Arg);
  788.  
  789.   Rec5 = (!Negate);
  790.   return e_cmd_ok;
  791. }
  792.  
  793. static as_cmd_result_t CMD_SepMoto(Boolean Negate, const char *Arg)
  794. {
  795.   UNUSED(Arg);
  796.  
  797.   SepMoto = !Negate;
  798.   return e_cmd_ok;
  799. }
  800.  
  801. static as_cmd_result_t CMD_IntelMode(Boolean Negate, const char *Arg)
  802. {
  803.   int Mode;
  804.   Boolean ok;
  805.  
  806.   if (*Arg == '\0')
  807.     return e_cmd_err;
  808.   else
  809.   {
  810.     Mode = ConstLongInt(Arg, &ok, 10);
  811.     if ((!ok) || (Mode < 0) || (Mode > 2))
  812.       return e_cmd_err;
  813.     else
  814.     {
  815.       if (!Negate)
  816.         IntelMode = Mode;
  817.       else if (IntelMode == Mode)
  818.         IntelMode = 0;
  819.       return e_cmd_arg;
  820.     }
  821.   }
  822. }
  823.  
  824. static as_cmd_result_t CMD_MultiMode(Boolean Negate, const char *Arg)
  825. {
  826.   int Mode;
  827.   Boolean ok;
  828.  
  829.   if (*Arg == '\0')
  830.     return e_cmd_err;
  831.   else
  832.   {
  833.     Mode = ConstLongInt(Arg, &ok, 10);
  834.     if ((!ok) || (Mode < 0) || (Mode > 3))
  835.       return e_cmd_err;
  836.     else
  837.     {
  838.       if (!Negate)
  839.         MultiMode = Mode;
  840.       else if (MultiMode == Mode)
  841.         MultiMode = 0;
  842.       return e_cmd_arg;
  843.     }
  844.   }
  845. }
  846.  
  847. static as_cmd_result_t CMD_DestFormat(Boolean Negate, const char *pArg)
  848. {
  849. #define NameCnt (sizeof(Names) / sizeof(*Names))
  850.  
  851.   static const char *Names[] =
  852.   {
  853.     "DEFAULT", "MOTO", "INTEL", "INTEL16", "INTEL32", "MOS", "TEK", "DSK", "ATMEL", "MICO8", "C"
  854.   };
  855.   static tHexFormat Format[] =
  856.   {
  857.     eHexFormatDefault, eHexFormatMotoS, eHexFormatIntel, eHexFormatIntel16,
  858.     eHexFormatIntel32, eHexFormatMOS, eHexFormatTek, eHexFormatTiDSK,
  859.     eHexFormatAtmel, eHexFormatMico8, eHexFormatC
  860.   };
  861.   unsigned z;
  862.   String Arg;
  863.  
  864.   strmaxcpy(Arg, pArg, STRINGSIZE);
  865.   NLS_UpString(Arg);
  866.  
  867.   z = 0;
  868.   while ((z < NameCnt) && (strcmp(Arg, Names[z])))
  869.     z++;
  870.   if (z >= NameCnt)
  871.     return e_cmd_err;
  872.  
  873.   if (!Negate)
  874.     DestFormat = Format[z];
  875.   else if (DestFormat == Format[z])
  876.     DestFormat = eHexFormatDefault;
  877.  
  878.   return e_cmd_arg;
  879. }
  880.  
  881. static as_cmd_result_t CMD_ForceSegment(Boolean Negate,  const char *Arg)
  882. {
  883.   int z = addrspace_lookup(Arg);
  884.  
  885.   if (z >= SegCount)
  886.     return e_cmd_err;
  887.  
  888.   if (!Negate)
  889.     ForceSegment = z;
  890.   else if (ForceSegment == z)
  891.     ForceSegment = SegNone;
  892.  
  893.   return e_cmd_arg;
  894. }
  895.  
  896. static as_cmd_result_t CMD_DataAdrRange(Boolean Negate,  const char *Arg)
  897. {
  898.   fputs(getmessage(Num_WarnDOption), stderr);
  899.   fflush(stdout);
  900.  
  901.   if (Negate)
  902.   {
  903.     DefStartStopAdr(1 << SegData);
  904.     return e_cmd_ok;
  905.   }
  906.   else
  907.   {
  908.     Boolean StartDataAuto, StopDataAuto;
  909.     as_cmd_result_t Ret = CMD_Range(&StartAdr[SegData], &StopAdr[SegData],
  910.                               &StartDataAuto, &StopDataAuto, Arg);
  911.  
  912.     if (StartDataAuto || StopDataAuto)
  913.       Ret = e_cmd_err;
  914.     return Ret;
  915.   }
  916. }
  917.  
  918. static as_cmd_result_t CMD_EntryAdr(Boolean Negate, const char *Arg)
  919. {
  920.   Boolean ok;
  921.  
  922.   if (Negate)
  923.   {
  924.     EntryAdrPresent = False;
  925.     return e_cmd_ok;
  926.   }
  927.   else
  928.   {
  929.     EntryAdr = ConstLongInt(Arg, &ok, 10);
  930.     if ((!ok) || (EntryAdr > 0xffff))
  931.       return e_cmd_err;
  932.     EntryAdrPresent = True;
  933.     return e_cmd_arg;
  934.   }
  935. }
  936.  
  937. static as_cmd_result_t CMD_LineLen(Boolean Negate, const char *Arg)
  938. {
  939.   Boolean ok;
  940.  
  941.   if (Negate)
  942.   {
  943.     if (*Arg !='\0')
  944.       return e_cmd_err;
  945.     else
  946.     {
  947.       LineLen = 16;
  948.       return e_cmd_ok;
  949.     }
  950.   }
  951.   else if (*Arg == '\0')
  952.     return e_cmd_err;
  953.   else
  954.   {
  955.     LineLen = ConstLongInt(Arg, &ok, 10);
  956.     if ((!ok) || (LineLen < 1) || (LineLen > MaxLineLen))
  957.       return e_cmd_err;
  958.     else
  959.     {
  960.       LineLen += LineLen & 1;
  961.       return e_cmd_arg;
  962.     }
  963.   }
  964. }
  965.  
  966. static as_cmd_result_t CMD_MinMoto(Boolean Negate, const char *Arg)
  967. {
  968.   Boolean ok;
  969.  
  970.   if (Negate)
  971.   {
  972.     if (*Arg != '\0')
  973.       return e_cmd_err;
  974.     else
  975.     {
  976.       MinMoto = 0;
  977.       return e_cmd_ok;
  978.     }
  979.   }
  980.   else if (*Arg == '\0')
  981.     return e_cmd_err;
  982.   else
  983.   {
  984.     MinMoto = ConstLongInt(Arg, &ok, 10);
  985.     if ((!ok) || (MinMoto < 1) || (MinMoto > 3))
  986.       return e_cmd_err;
  987.     else
  988.       return e_cmd_arg;
  989.   }
  990. }
  991.  
  992. static as_cmd_result_t CMD_AutoErase(Boolean Negate, const char *Arg)
  993. {
  994.   UNUSED(Arg);
  995.  
  996.   AutoErase = !Negate;
  997.   return e_cmd_ok;
  998. }
  999.  
  1000. static as_cmd_result_t CMD_AVRLen(Boolean Negate, const char *Arg)
  1001. {
  1002.   Word Temp;
  1003.   Boolean ok;
  1004.  
  1005.   if (Negate)
  1006.   {
  1007.     AVRLen = AVRLEN_DEFAULT;
  1008.     return e_cmd_ok;
  1009.   }
  1010.   else
  1011.   {
  1012.     Temp = ConstLongInt(Arg, &ok, 10);
  1013.     if ((!ok) || (Temp < 2) || (Temp > 3))
  1014.       return e_cmd_err;
  1015.     else
  1016.     {
  1017.       AVRLen = Temp;
  1018.       return e_cmd_arg;
  1019.     }
  1020.   }
  1021. }
  1022.  
  1023. static as_cmd_result_t CMD_CFormat(Boolean Negate, const char *pArg)
  1024. {
  1025.   if (Negate)
  1026.   {
  1027.     strcpy(CFormat, DefaultCFormat);
  1028.     return e_cmd_ok;
  1029.   }
  1030.   else
  1031.   {
  1032.     int NumData = 0, NumStart = 0, NumLen = 0, NumEnd = 0;
  1033.     const char *pFormat;
  1034.  
  1035.     for (pFormat = pArg; *pFormat; pFormat++)
  1036.       switch (toupper(*pFormat))
  1037.       {
  1038.         case 'S': NumStart++; break;
  1039.         case 'D': NumData++; break;
  1040.         case 'L': NumLen++; break;
  1041.         case 'E': NumEnd++; break;
  1042.         default: return e_cmd_err;
  1043.       }
  1044.     if ((NumData > 1) || (NumStart > 1) || (NumLen > 1) || (NumEnd > 1))
  1045.       return e_cmd_err;
  1046.     strcpy(CFormat, pArg);
  1047.     return e_cmd_arg;
  1048.   }
  1049. }
  1050.  
  1051. static const as_cmd_rec_t P2HEXParams[] =
  1052. {
  1053.   { "f"        , CMD_FilterList },
  1054.   { "r"        , CMD_AdrRange },
  1055.   { "R"        , CMD_AdrRelocate },
  1056.   { "a"        , CMD_RelAdr },
  1057.   { "i"        , CMD_IntelMode },
  1058.   { "m"        , CMD_MultiMode },
  1059.   { "F"        , CMD_DestFormat },
  1060.   { "5"        , CMD_Rec5 },
  1061.   { "s"        , CMD_SepMoto },
  1062.   { "d"        , CMD_DataAdrRange },
  1063.   { "e"        , CMD_EntryAdr },
  1064.   { "l"        , CMD_LineLen },
  1065.   { "k"        , CMD_AutoErase },
  1066.   { "M"        , CMD_MinMoto },
  1067.   { "SEGMENT"  , CMD_ForceSegment },
  1068.   { "AVRLEN"   , CMD_AVRLen },
  1069.   { "CFORMAT"  , CMD_CFormat }
  1070. };
  1071.  
  1072. static Word ChkSum;
  1073.  
  1074. int main(int argc, char **argv)
  1075. {
  1076.   char *p_target_name;
  1077.   const char *p_src_name;
  1078.   as_cmd_results_t cmd_results;
  1079.   StringRecPtr p_src_run;
  1080.  
  1081.   nls_init();
  1082.   if (!NLS_Initialize(&argc, argv))
  1083.     exit(4);
  1084.  
  1085.   be_le_init();
  1086.   bpemu_init();
  1087.   chunks_init();
  1088.   as_cmdarg_init(*argv);
  1089.   msg_level_init();
  1090.   toolutils_init(*argv);
  1091. #ifdef _USE_MSH
  1092.   nlmessages_init_buffer(p2hex_msh_data, sizeof(p2hex_msh_data), MsgId1, MsgId2);
  1093. #else
  1094.   nlmessages_init_file("p2hex.msg", *argv, MsgId1, MsgId2);
  1095. #endif
  1096.   ioerrs_init(*argv);
  1097.  
  1098.   InitChunk(&UsedList);
  1099.  
  1100.   DefStartStopAdr(0xffff);
  1101.   StartAuto = True;
  1102.   StopAuto = True;
  1103.   EntryAdr = -1;
  1104.   EntryAdrPresent = False;
  1105.   AutoErase = False;
  1106.   RelAdr = False;
  1107.   Rec5 = True;
  1108.   LineLen = 16;
  1109.   AVRLen = AVRLEN_DEFAULT;
  1110.   IntelMode = 0;
  1111.   MultiMode = 0;
  1112.   DestFormat = eHexFormatDefault;
  1113.   MinMoto = 1;
  1114.   *TargName = '\0';
  1115.   Relocate = 0;
  1116.   ForceSegment = SegNone;
  1117.   strcpy(CFormat, DefaultCFormat);
  1118.  
  1119.   as_cmd_register(P2HEXParams, as_array_size(P2HEXParams));
  1120.   if (e_cmd_err == as_cmd_process(argc, argv, "P2HEXCMD", &cmd_results))
  1121.   {
  1122.     ParamError(cmd_results.error_arg_in_env, cmd_results.error_arg);
  1123.     exit(1);
  1124.   }
  1125.  
  1126.   if ((msg_level >= e_msg_level_verbose) || cmd_results.write_version_exit)
  1127.   {
  1128.     String Ver;
  1129.  
  1130.     as_snprintf(Ver, sizeof(Ver), "P2HEX V%s", Version);
  1131.     WrCopyRight(Ver);
  1132.   }
  1133.  
  1134.   if (cmd_results.write_help_exit)
  1135.   {
  1136.     char *ph1, *ph2;
  1137.  
  1138.     chkio_printf(OutName, "%s%s%s\n", getmessage(Num_InfoMessHead1), as_cmdarg_get_executable_name(), getmessage(Num_InfoMessHead2));
  1139.     for (ph1 = getmessage(Num_InfoMessHelp), ph2 = strchr(ph1, '\n'); ph2; ph1 = ph2 + 1, ph2 = strchr(ph1, '\n'))
  1140.     {
  1141.       *ph2 = '\0';
  1142.       chkio_printf(OutName, "%s\n", ph1);
  1143.       *ph2 = '\n';
  1144.     }
  1145.   }
  1146.  
  1147.   if (cmd_results.write_version_exit || cmd_results.write_help_exit)
  1148.     exit(0);
  1149.  
  1150.   if (StringListEmpty(cmd_results.file_arg_list))
  1151.   {
  1152.     fprintf(stderr, "%s: %s\n", as_cmdarg_get_executable_name(), getmessage(Num_ErrMessNoInputFiles));
  1153.     exit(1);
  1154.   }
  1155.  
  1156.   p_target_name = MoveAndCutStringListLast(&cmd_results.file_arg_list);
  1157.   if (!p_target_name || !*p_target_name)
  1158.   {
  1159.     chkio_fprintf(stderr, OutName, "%s\n", getmessage(Num_ErrMsgTargMissing));
  1160.     if (p_target_name) free(p_target_name);
  1161.     p_target_name = NULL;
  1162.     exit(1);
  1163.   }
  1164.  
  1165.   strmaxcpy(TargName, p_target_name, STRINGSIZE);
  1166.   if (!RemoveOffset(TargName, &Dummy))
  1167.   {
  1168.     strmaxcpy(TargName, p_target_name, STRINGSIZE);
  1169.     free(p_target_name); p_target_name = NULL;
  1170.     ParamError(False, TargName);
  1171.   }
  1172.  
  1173.   /* special case: only one argument <name> treated like <name>.p -> <name).hex */
  1174.  
  1175.   if (StringListEmpty(cmd_results.file_arg_list))
  1176.   {
  1177.     AddStringListLast(&cmd_results.file_arg_list, p_target_name);
  1178.     DelSuffix(TargName);
  1179.   }
  1180.   free(p_target_name); p_target_name = NULL;
  1181.   AddSuffix(TargName, STRINGSIZE, HexSuffix);
  1182.   Filename2CName(CTargName, TargName);
  1183.   NumCBlocks = 0;
  1184.  
  1185.   if (StartAuto || StopAuto)
  1186.   {
  1187.     int z;
  1188.     Byte ChkSegment = ForceSegment ? ForceSegment : (Byte)SegCode;
  1189.  
  1190.     if (StartAuto)
  1191.       for (z = 0; z < SegCount; z++)
  1192.         StartAdr[z] = 0xfffffffful;
  1193.     if (StopAuto)
  1194.       for (z = 0; z < SegCount; z++)
  1195.         StopAdr[z] = 0;
  1196.  
  1197.     for (p_src_name = GetStringListFirst(cmd_results.file_arg_list, &p_src_run);
  1198.          p_src_name; p_src_name = GetStringListNext(&p_src_run))
  1199.       if (*p_src_name)
  1200.         ProcessGroup(p_src_name, MeasureFile);
  1201.  
  1202.     if (StartAdr[ChkSegment] > StopAdr[ChkSegment])
  1203.     {
  1204.       chkio_fprintf(stderr, OutName, "%s\n", getmessage(Num_ErrMsgAutoFailed));
  1205.       exit(1);
  1206.     }
  1207.     if (msg_level >= e_msg_level_normal)
  1208.     {
  1209.       printf("%s: 0x%08lX-", getmessage(Num_InfoMessDeducedRange), LoDWord(StartAdr[ChkSegment]));
  1210.       printf("0x%08lX\n", LoDWord(StopAdr[ChkSegment]));
  1211.     }
  1212.   }
  1213.  
  1214.   OpenTarget();
  1215.   FormatOccured = 0;
  1216.   MaxMoto = 0;
  1217.   MaxIntel = 0;
  1218.  
  1219.   if (DestFormat == eHexFormatC)
  1220.   {
  1221.     chkio_fprintf(TargFile, TargName, "#ifndef _%s_H\n#define _%s_H\n\n", CTargName, CTargName);
  1222.     NumCBlocks = 0;
  1223.   }
  1224.  
  1225.   for (p_src_name = GetStringListFirst(cmd_results.file_arg_list, &p_src_run);
  1226.        p_src_name; p_src_name = GetStringListNext(&p_src_run))
  1227.     if (*p_src_name)
  1228.       ProcessGroup(p_src_name, ProcessFile);
  1229.  
  1230.   if ((FormatOccured & eMotoOccured) && (!SepMoto))
  1231.   {
  1232.     chkio_fprintf(TargFile, TargName, "S%c%02X", '9' - MaxMoto, Lo(3 + MaxMoto));
  1233.     ChkSum = 3 + MaxMoto;
  1234.     if (!EntryAdrPresent)
  1235.       EntryAdr = 0;
  1236.     if (MaxMoto >= 2)
  1237.     {
  1238.       chkio_fprintf(TargFile, TargName, "%02X", Lo(EntryAdr >> 24));
  1239.       ChkSum += (EntryAdr >> 24) & 0xff;
  1240.     }
  1241.     if (MaxMoto >= 1)
  1242.     {
  1243.       chkio_fprintf(TargFile, TargName, "%02X", Lo(EntryAdr >> 16));
  1244.       ChkSum += (EntryAdr >> 16) & 0xff;
  1245.     }
  1246.     chkio_fprintf(TargFile, TargName, "%04X", LoWord(EntryAdr & 0xffff));
  1247.     ChkSum += (EntryAdr >> 8) & 0xff;
  1248.     ChkSum += EntryAdr & 0xff;
  1249.     chkio_fprintf(TargFile, TargName, "%02X\n", Lo(0xff - (ChkSum & 0xff)));
  1250.   }
  1251.  
  1252.   if (FormatOccured & eIntelOccured)
  1253.   {
  1254.     Word EndRecAddr = 0;
  1255.  
  1256.     if (EntryAdrPresent)
  1257.     {
  1258.       switch (MaxIntel)
  1259.       {
  1260.         case 2:
  1261.           chkio_fprintf(TargFile, TargName, ":04000005");
  1262.           ChkSum = 4 + 5;
  1263.           chkio_fprintf(TargFile, TargName, "%08lX", LoDWord(EntryAdr));
  1264.           ChkSum += ((EntryAdr >> 24) & 0xff) +
  1265.                     ((EntryAdr >> 16) & 0xff) +
  1266.                     ((EntryAdr >>  8) & 0xff) +
  1267.                     ( EntryAdr        & 0xff);
  1268.           goto WrChkSum;
  1269.  
  1270.         case 1:
  1271.           Seg = (EntryAdr >> 4) & 0xffff;
  1272.           Ofs = EntryAdr & 0x000f;
  1273.           chkio_fprintf(TargFile, TargName, ":04000003%04X%04X", LoWord(Seg), LoWord(Ofs));
  1274.           ChkSum = 4 + 3 + Lo(Seg) + Hi(Seg) + Ofs;
  1275.           goto WrChkSum;
  1276.  
  1277.         default: /* == 0 */
  1278.           EndRecAddr = EntryAdr & 0xffff;
  1279.           break;
  1280.  
  1281.         WrChkSum:
  1282.           chkio_fprintf(TargFile, TargName, "%02X\n", Lo(0x100 - ChkSum));
  1283.       }
  1284.     }
  1285.     errno = 0;
  1286.     switch (IntelMode)
  1287.     {
  1288.       case 0:
  1289.       {
  1290.         ChkSum = 1 + Hi(EndRecAddr) + Lo(EndRecAddr);
  1291.         chkio_fprintf(TargFile, TargName, ":00%04X01%02X\n", LoWord(EndRecAddr), Lo(0x100 - ChkSum));
  1292.         break;
  1293.       }
  1294.       case 1:
  1295.         chkio_fprintf(TargFile, TargName, ":00000001\n");
  1296.         break;
  1297.       case 2:
  1298.         chkio_fprintf(TargFile, TargName, ":0000000000\n");
  1299.         break;
  1300.     }
  1301.   }
  1302.  
  1303.   if (FormatOccured & eMOSOccured)
  1304.     chkio_fprintf(TargFile, TargName, ";0000040004\n");
  1305.  
  1306.   if (FormatOccured & eDSKOccured)
  1307.   {
  1308.     if (EntryAdrPresent)
  1309.       chkio_fprintf(TargFile, TargName, "1%04X7%04XF\n", LoWord(EntryAdr), LoWord(EntryAdr));
  1310.     chkio_fprintf(TargFile, TargName, ":\n");
  1311.   }
  1312.  
  1313.   if (DestFormat == eHexFormatC)
  1314.   {
  1315.     unsigned ThisCBlock;
  1316.     String CBlockName;
  1317.     const char *pFormat;
  1318.  
  1319.     errno = 0;
  1320.     fprintf(TargFile,
  1321.             "typedef struct\n"
  1322.             "{\n");
  1323.     for (pFormat = CFormat; *pFormat; pFormat++)
  1324.       switch (*pFormat)
  1325.       {
  1326.         case 'd':
  1327.         case 'D':
  1328.           chkio_fprintf(TargFile, TargName, "  const char *data;\n"); break;
  1329.         case 's':
  1330.           chkio_fprintf(TargFile, TargName, "  unsigned start;\n"); break;
  1331.         case 'S':
  1332.           chkio_fprintf(TargFile, TargName, "  unsigned long start;\n"); break;
  1333.         case 'l':
  1334.           chkio_fprintf(TargFile, TargName, "  unsigned len;\n"); break;
  1335.         case 'L':
  1336.           chkio_fprintf(TargFile, TargName, "  unsigned long len;\n"); break;
  1337.         case 'e':
  1338.           chkio_fprintf(TargFile, TargName, "  unsigned end;\n"); break;
  1339.         case 'E':
  1340.           chkio_fprintf(TargFile, TargName, "  unsigned long end;\n"); break;
  1341.         default:
  1342.           break;
  1343.       }
  1344.     fprintf(TargFile,
  1345.             "} %s_blk;\n"
  1346.             "static const %s_blk %s_blks[] =\n"
  1347.             "{\n",
  1348.             CTargName, CTargName, CTargName);
  1349.     for (ThisCBlock = 0; ThisCBlock < NumCBlocks; ThisCBlock++)
  1350.     {
  1351.       GetCBlockName(CBlockName, sizeof(CBlockName), ThisCBlock);
  1352.       chkio_fprintf(TargFile, TargName, "  {");
  1353.       for (pFormat = CFormat; *pFormat; pFormat++)
  1354.       {
  1355.         chkio_fprintf(TargFile, TargName, (pFormat != CFormat) ? ", " : " ");
  1356.         switch (toupper(*pFormat))
  1357.         {
  1358.           case 'D': chkio_fprintf(TargFile, TargName, "%s%s_data", CTargName, CBlockName); break;
  1359.           case 'S': chkio_fprintf(TargFile, TargName, "%s%s_start", CTargName, CBlockName); break;
  1360.           case 'L': chkio_fprintf(TargFile, TargName, "%s%s_len", CTargName, CBlockName); break;
  1361.           case 'E': chkio_fprintf(TargFile, TargName, "%s%s_end", CTargName, CBlockName); break;
  1362.           default: break;
  1363.         }
  1364.       }
  1365.       chkio_fprintf(TargFile, TargName, " },\n");
  1366.     }
  1367.     chkio_fprintf(TargFile, TargName, "  {");
  1368.     for (pFormat = CFormat; *pFormat; pFormat++)
  1369.       chkio_fprintf(TargFile, TargName, (pFormat != CFormat) ? ", 0" : " 0");
  1370.     chkio_fprintf(TargFile, TargName, " }\n"
  1371.                       "};\n\n");
  1372.  
  1373.     if (EntryAdrPresent)
  1374.       chkio_fprintf(TargFile, TargName, "#define %s_entry 0x%08lXul\n\n",
  1375.                     CTargName, LoDWord(EntryAdr));
  1376.     chkio_fprintf(TargFile, TargName,
  1377.                   "#endif /* _%s_H */\n",
  1378.                   CTargName);
  1379.   }
  1380.   CloseTarget();
  1381.  
  1382.   if (AutoErase)
  1383.   {
  1384.     for (p_src_name = GetStringListFirst(cmd_results.file_arg_list, &p_src_run);
  1385.          p_src_name; p_src_name = GetStringListNext(&p_src_run))
  1386.       if (*p_src_name)
  1387.         ProcessGroup(p_src_name, EraseFile);
  1388.   }
  1389.  
  1390.   ClearStringList(&cmd_results.file_arg_list);
  1391.  
  1392.   return 0;
  1393. }
  1394.