dwg_encode (Dwg_Data *restrict dwg, Bit_Chain *restrict dat)
{
  int ckr_missing = 1;
  int error = 0;
  BITCODE_BL i, j;
  long unsigned int section_address;
  unsigned char pvzbit;
  long unsigned int pvzadr;
  long unsigned int pvzadr_2;
  unsigned int ckr;
  unsigned int sec_size = 0;
  long unsigned int last_offset;
  BITCODE_BL last_handle;
  Object_Map *omap;
  Bit_Chain *hdl_dat;

  if (dwg->opts)
    loglevel = dwg->opts & DWG_OPTS_LOGLEVEL;
#ifdef USE_TRACING
  /* Before starting, set the logging level, but only do so once.  */
  if (!env_var_checked_p)
    {
      char *probe = getenv ("LIBREDWG_TRACE");
      if (probe)
        loglevel = atoi (probe);
      env_var_checked_p = true;
    }
#endif /* USE_TRACING */

  bit_chain_alloc (dat);
  hdl_dat = dat;

  /*------------------------------------------------------------
   * Header
   */
  strcpy ((char *)dat->chain,
          version_codes[dwg->header.version]); // Chain version
  if (dwg->header.version != dwg->header.from_version)
    LOG_TRACE ("Encode version %s from version %s\n",
               version_codes[dwg->header.version],
               version_codes[dwg->header.from_version])
  else
    LOG_TRACE ("Encode version %s\n", version_codes[dwg->header.version])
  dat->byte += 6;

  {
    struct Dwg_Header *_obj = &dwg->header;
    Dwg_Object *obj = NULL;
    if (!_obj->dwg_version)
      {
        _obj->is_maint = 0;
        switch (dwg->header.version)
          {
          case R_9:
            _obj->dwg_version = 0x11; // ?
            break;
          case R_10:
            _obj->dwg_version = 0x12; // ?
            break;
          case R_11:
            _obj->dwg_version = 0x13; // ?
            break;
          case R_13:
            _obj->dwg_version = 0x15;
            break;
          case R_14:
            _obj->dwg_version = 0x16;
            break;
          case R_2000:
            _obj->dwg_version = 0x17;
            _obj->is_maint = 0xf;
            break;
          case R_2004:
            _obj->dwg_version = 0x19;
            _obj->is_maint = 0x68;
            break;
          case R_2007:
            _obj->dwg_version = 0x1b;
            _obj->is_maint = 0x32;
            break;
          case R_2010:
            _obj->dwg_version = 0x1d;
            _obj->is_maint = 0x6d;
            break;
          case R_2013:
            _obj->dwg_version = 0x1f;
            _obj->is_maint = 0x7d;
            break;
          case R_2018:
            _obj->dwg_version = 0x21;
            _obj->is_maint = 0x4;
            break;
          case R_INVALID:
          case R_AFTER:
          case R_1_1:
          case R_1_2:
          case R_1_4:
          case R_2_0:
          case R_2_1:
          case R_2_5:
          case R_2_6:
          default:
            break;
          }
        if (!_obj->app_dwg_version)
          _obj->app_dwg_version = _obj->dwg_version;
      }
    if (!_obj->codepage)
      _obj->codepage = 30;

    // clang-format off
    #include "header.spec"
    // clang-format on
  }
  section_address = dat->byte;

#define WE_CAN                                                                \
  "This version of LibreDWG is only capable of encoding "                     \
  "version R13-R2000 (code: AC1012-AC1015) DWG files.\n"

  PRE (R_13)
  {
    // TODO: tables, entities, block entities
    LOG_ERROR (WE_CAN "We don't encode preR13 tables, entities, blocks yet")
#ifndef IS_RELEASE
    return encode_preR13 (dwg, dat);
#endif
  }

  PRE (R_2004)
  {
    /* section 0: header vars
     *         1: class section
     *         2: object map
     *         3: (R13 c3 and later): 2nd header (special table no sentinels)
     *         4: optional: MEASUREMENT
     *         5: optional: AuxHeader
     */
    if (!dwg->header.num_sections) /* Usually 3-5, max 6 */
      {
        dwg->header.num_sections = dwg->header.version < R_2000 ? 5 : 6;
        // minimal DXF:
        if (!dwg->header_vars.HANDSEED || !dwg->header_vars.TDCREATE.days)
          {
            dwg->header.num_sections = 5;
            dat->from_version = R_11; // to trigger IF_ENCODE_FROM_EARLIER defaults
            if (dat->version <= dat->from_version)
              dat->from_version = dat->version - 1;
          }
      }
    LOG_TRACE ("num_sections: " FORMAT_RL " [RL]\n", dwg->header.num_sections);
    bit_write_RL (dat, dwg->header.num_sections);
    if (!dwg->header.section)
      dwg->header.section
          = calloc (dwg->header.num_sections, sizeof (Dwg_Section));
    section_address = dat->byte;                 // save section address
    dat->byte += (dwg->header.num_sections * 9); /* RC + 2*RL */
    bit_write_CRC (dat, 0, 0xC0C1);
    bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_HEADER_END));

    /*------------------------------------------------------------
     * AuxHeader section 5
     * R2000+, mostly redundant file header information
     */
    if (dwg->header.num_sections > 5)
      {
        struct Dwg_AuxHeader *_obj = &dwg->auxheader;
        Dwg_Object *obj = NULL;
        assert (!dat->bit);
        LOG_INFO ("\n=======> AuxHeader: %8u\n",
                  (unsigned)dat->byte); // size: 123

        dwg->header.section[SECTION_AUXHEADER_R2000].number = 5;
        dwg->header.section[SECTION_AUXHEADER_R2000].address = dat->byte;

        if (!_obj->dwg_version)
          {
            BITCODE_RS tmpunknown[] = { 4, 0x565, 0, 0, 2, 1 };
            LOG_TRACE ("Use AuxHeader defaults...\n");
            FIELD_VALUE (aux_intro[0]) = 0xff;
            FIELD_VALUE (aux_intro[1]) = 0x77;
            FIELD_VALUE (aux_intro[2]) = 0x01;
            FIELD_VALUE (minus_1) = -1;
            FIELD_VALUE (dwg_version) = dwg->header.dwg_version;
            FIELD_VALUE (maint_version) = dwg->header.maint_version;
            FIELD_VALUE (dwg_version_1) = dwg->header.dwg_version;
            FIELD_VALUE (dwg_version_2) = dwg->header.dwg_version;
            FIELD_VALUE (maint_version_1) = dwg->header.maint_version;
            FIELD_VALUE (maint_version_2) = dwg->header.maint_version;
            memcpy (FIELD_VALUE (unknown_rs), tmpunknown, sizeof (tmpunknown));
            FIELD_VALUE (TDCREATE) = dwg->header_vars.TDCREATE.value;
            FIELD_VALUE (TDUPDATE) = dwg->header_vars.TDUPDATE.value;
            if (dwg->header_vars.HANDSEED)
              FIELD_VALUE (HANDSEED) = dwg->header_vars.HANDSEED->absolute_ref;
          }

          // clang-format off
        #include "auxheader.spec"
        // clang-format on

        assert (!dat->bit);
        dwg->header.section[SECTION_AUXHEADER_R2000].size
            = dat->byte - dwg->header.section[SECTION_AUXHEADER_R2000].address;
      }
  }

  VERSION (R_2007)
  {
    LOG_ERROR (WE_CAN "We don't encode R2007 sections yet")
    return DWG_ERR_NOTYETSUPPORTED;
  }

  /* r2004 file header (compressed + encrypted) */
  SINCE (R_2004)
  {
    /* System Section */
    typedef union _system_section
    {
      unsigned char data[0x14]; // 20byte: 5*4
      struct
      {
        uint32_t section_type; /* 0x4163043b */
        uint32_t decomp_data_size;
        uint32_t comp_data_size;
        uint32_t compression_type;
        uint32_t checksum; // see section_page_checksum
      } fields;
    } system_section;

    system_section ss;
    Dwg_Section *section;

    Dwg_Object *obj = NULL;
    struct Dwg_R2004_Header *_obj = &dwg->r2004_header;
    const int size = sizeof (struct Dwg_R2004_Header);
    char encrypted_data[size];
    unsigned int rseed = 1;
    uint32_t checksum;

    LOG_ERROR (WE_CAN "We don't encode the R2004_section_map yet")

    if (dwg->header.section_infohdr.num_desc && !dwg->header.section_info)
      dwg->header.section_info = calloc (dwg->header.section_infohdr.num_desc,
                                         sizeof (Dwg_Section_Info));

    dat->byte = 0x80;
    for (i = 0; i < (BITCODE_BL)size; i++)
      {
        rseed *= 0x343fd;
        rseed += 0x269ec3;
        encrypted_data[i] = bit_read_RC (dat) ^ (rseed >> 0x10);
      }
    LOG_TRACE ("\n#### Write 2004 File Header ####\n");
    dat->byte = 0x80;
    if (dat->byte + 0x80 >= dat->size - 1)
      {
        dat->size = dat->byte + 0x80;
        bit_chain_alloc (dat);
      }
    memcpy (&dat->chain[0x80], encrypted_data, size);
    LOG_INFO ("@0x%lx\n", dat->byte);

    // clang-format off
    #include "r2004_file_header.spec"
    // clang-format on

    dwg->r2004_header.checksum = 0;
    dwg->r2004_header.checksum = dwg_section_page_checksum (0, dat, size);

    /*-------------------------------------------------------------------------
     * Section Page Map
     */
    dat->byte = dwg->r2004_header.section_map_address + 0x100;

    LOG_TRACE ("\n=== Write System Section (Section Page Map) ===\n");
#ifndef HAVE_COMPRESS_R2004_SECTION
    dwg->r2004_header.comp_data_size = dwg->r2004_header.decomp_data_size;
    dwg->r2004_header.compression_type = 0;
#endif
    FIELD_RL (section_type, 0); // should be 0x4163043b
    FIELD_RL (decomp_data_size, 0);
    FIELD_RL (comp_data_size, 0);
    FIELD_RL (compression_type, 0);
    dwg_section_page_checksum (dwg->r2004_header.checksum, dat, size);
    FIELD_RL (checksum, 0);
    LOG_TRACE ("\n")

    LOG_WARN ("TODO write_R2004_section_map(dat, dwg)")
    LOG_TRACE ("\n")

    return DWG_ERR_NOTYETSUPPORTED;
  }

  /*------------------------------------------------------------
   * THUMBNAIL preview pictures
   */
  if (!dwg->header.thumbnail_address)
    dwg->header.thumbnail_address = dat->byte;
  dat->bit = 0;
  LOG_TRACE ("\n=======> Thumbnail:       %4u\n", (unsigned)dat->byte);
  // dwg->thumbnail.size = 0; // to disable
  bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_THUMBNAIL_BEGIN));
  if (dwg->thumbnail.size == 0)
    {
      bit_write_RL (dat, 5); // overall size
      LOG_TRACE ("Thumbnail size: 5 [RL]\n");
      bit_write_RC (dat, 0); // num_pictures
      LOG_TRACE ("Thumbnail num_pictures: 0 [RC]\n");
    }
  else
    {
      bit_write_TF (dat, (char *)dwg->thumbnail.chain, dwg->thumbnail.size);
    }
  bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_THUMBNAIL_END));

  {
    BITCODE_RL size;
    dwg_bmp (dwg, &size);
    if (size > dwg->thumbnail.size)
      LOG_ERROR ("BMP size overflow: %i > %lu\n", size, dwg->thumbnail.size);
  }
  LOG_TRACE ("         Thumbnail (end): %4u\n", (unsigned)dat->byte);

  /*------------------------------------------------------------
   * Header Variables
   */
  assert (!dat->bit);
  LOG_INFO ("\n=======> Header Variables:   %4u\n", (unsigned)dat->byte);
  dwg->header.section[0].number = 0;
  dwg->header.section[0].address = dat->byte;
  bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_VARIABLE_BEGIN));

  pvzadr = dat->byte;      // Size position
  bit_write_RL (dat, 540); // Size placeholder
  // if (dat->version >= R_2007)
  //  str_dat = dat;
  dwg_encode_header_variables (dat, hdl_dat, dat, dwg);
  encode_patch_RLsize (dat, pvzadr);
  bit_write_CRC (dat, pvzadr, 0xC0C1);

  // XXX trying to fix CRC 2-byte overflow. Must find actual reason
  // dat->byte -= 2;
  bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_VARIABLE_END));
  assert ((long)dat->byte > (long)dwg->header.section[0].address);
  dwg->header.section[0].size
      = (BITCODE_RL) ((long)dat->byte - (long)dwg->header.section[0].address);
  LOG_TRACE ("         Header Variables (end): %4u\n", (unsigned)dat->byte);

  /*------------------------------------------------------------
   * Classes
   */
  LOG_INFO ("\n=======> Classes: %4u (%d)\n", (unsigned)dat->byte, dwg->num_classes);
  dwg->header.section[SECTION_CLASSES_R13].number = 1;
  dwg->header.section[SECTION_CLASSES_R13].address = dat->byte;
  bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_CLASS_BEGIN));
  pvzadr = dat->byte;    // Size position
  bit_write_RL (dat, 0); // Size placeholder

  for (j = 0; j < dwg->num_classes; j++)
    {
      Dwg_Class *klass;
      klass = &dwg->dwg_class[j];
      bit_write_BS (dat, klass->number);
      bit_write_BS (dat, klass->proxyflag);
      bit_write_TV (dat, klass->appname);
      bit_write_TV (dat, klass->cppname);
      bit_write_TV (dat, klass->dxfname);
      bit_write_B (dat, klass->wasazombie);
      bit_write_BS (dat, klass->item_class_id);
      LOG_TRACE ("Class %d 0x%x %s\n"
                 " %s \"%s\" %d 0x%x\n",
                 klass->number, klass->proxyflag, klass->dxfname,
                 klass->cppname, klass->appname, klass->wasazombie,
                 klass->item_class_id)

      SINCE (R_2007)
      {
        bit_write_BL (dat, klass->num_instances);
        bit_write_BL (dat, klass->dwg_version);
        bit_write_BL (dat, klass->maint_version);
        bit_write_BL (dat, klass->unknown_1);
        bit_write_BL (dat, klass->unknown_2);
        LOG_TRACE (" %d %d\n", (int)klass->num_instances,
                   (int)klass->dwg_version);
      }
    }

  /* Write the size of the section at its beginning
   */
  assert (pvzadr);
  encode_patch_RLsize (dat, pvzadr);
  bit_write_CRC (dat, pvzadr, 0xC0C1);
  bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_CLASS_END));
  dwg->header.section[SECTION_CLASSES_R13].size
      = dat->byte - dwg->header.section[SECTION_CLASSES_R13].address;
  LOG_TRACE ("       Classes (end): %4u\n", (unsigned)dat->byte);

  bit_write_RL (dat, 0x0DCA); // 0xDCA Unknown bitlong inter class and objects
  LOG_TRACE ("unknown: %04X [RL]\n", 0x0DCA);

  /*------------------------------------------------------------
   * Objects
   */

  LOG_INFO ("\n=======> Objects: %4u\n", (unsigned)dat->byte);
  pvzadr = dat->byte;

  /* Sort object-map by ascending handles
   */
  LOG_TRACE ("num_objects: %i\n", dwg->num_objects);
  LOG_TRACE ("num_object_refs: %i\n", dwg->num_object_refs);
  omap = (Object_Map *)calloc (dwg->num_objects, sizeof (Object_Map));
  if (!omap)
    {
      LOG_ERROR ("Out of memory");
      return DWG_ERR_OUTOFMEM;
    }
  if (DWG_LOGLEVEL >= DWG_LOGLEVEL_HANDLE)
    {
      LOG_HANDLE ("\nSorting objects...\n");
      for (i = 0; i < dwg->num_objects; i++)
        fprintf (OUTPUT, "Object(%3i): %4lX / idx: %u\n", i,
                 dwg->object[i].handle.value, dwg->object[i].index);
    }
  // init unsorted
  for (i = 0; i < dwg->num_objects; i++)
    {
      omap[i].index = i; // i.e. dwg->object[j].index
      omap[i].handle = dwg->object[i].handle.value;
    }
  // insertion sort
  for (i = 0; i < dwg->num_objects; i++)
    {
      Object_Map tmap;
      j = i;
      tmap = omap[i];
      while (j > 0 && omap[j - 1].handle > tmap.handle)
        {
          omap[j] = omap[j - 1];
          j--;
        }
      omap[j] = tmap;
    }
  if (DWG_LOGLEVEL >= DWG_LOGLEVEL_HANDLE)
    {
      LOG_HANDLE ("\nSorted handles:\n");
      for (i = 0; i < dwg->num_objects; i++)
        fprintf (OUTPUT, "Handle(%3i): %4lX / idx: %u\n", i, omap[i].handle,
                 omap[i].index);
    }

  /* Write the sorted objects
   */
  for (i = 0; i < dwg->num_objects; i++)
    {
      Dwg_Object *obj;
      BITCODE_BL index = omap[i].index;
      unsigned long hdloff = omap[i].handle - (i ? omap[i - 1].handle : 0);
      int off = dat->byte - (i ? omap[i - 1].address : 0);
      unsigned long address, end_address;
      LOG_TRACE ("\n> Next object: " FORMAT_BL
                 " Handleoff: %lX [UMC] Offset: %d [MC] @%lu\n"
                 "==========================================\n",
                 i, hdloff, off, dat->byte);
      omap[i].address = dat->byte;
      if (index > dwg->num_objects)
        {
          LOG_ERROR ("Invalid object map index " FORMAT_BL ", max " FORMAT_BL
                     ". Skipping",
                     index, dwg->num_objects)
          error |= DWG_ERR_VALUEOUTOFBOUNDS;
          continue;
        }
      obj = &dwg->object[index];
      // change the address to the linearly sorted one
      assert (dat->byte);
      error |= dwg_encode_add_object (obj, dat, dat->byte);

#ifndef NDEBUG
      // check if this object overwrote at address 0
      if (dwg->header.version >= R_1_2)
        {
          assert (dat->chain[0] == 'A');
          assert (dat->chain[1] == 'C');
        }
#endif
      end_address = omap[i].address + (unsigned long)obj->size; // from RL
      if (end_address > dat->size)
        {
          dat->size = end_address;
          bit_chain_alloc (dat);
        }
    }

  if (DWG_LOGLEVEL >= DWG_LOGLEVEL_HANDLE)
    {
      LOG_HANDLE ("\nSorted objects:\n");
      for (i = 0; i < dwg->num_objects; i++)
        LOG_HANDLE ("Object(%d): %lX / Address: %ld / Idx: %d\n", i,
                    omap[i].handle, omap[i].address, omap[i].index);
    }

  /* Unknown CRC between objects and object map
   */
  bit_write_RS (dat, 0);
  LOG_TRACE ("unknown crc?: %04X [RS]\n", 0);

  /*------------------------------------------------------------
   * Object-map
   * split into chunks of max. 2030
   */
  LOG_INFO ("\n=======> Object Map: %4u\n", (unsigned)dat->byte);
  dwg->header.section[SECTION_HANDLES_R13].number = 2;
  dwg->header.section[SECTION_HANDLES_R13].address = dat->byte;

  sec_size = 0;
  pvzadr = dat->byte; // Correct value of section size must be written later
  dat->byte += 2;
  last_offset = 0;
  last_handle = 0;
  for (i = 0; i < dwg->num_objects; i++)
    {
      BITCODE_BL index;
      BITCODE_UMC handleoff;
      BITCODE_MC offset;

      index = omap[i].index;
      handleoff = omap[i].handle - last_handle;
      bit_write_UMC (dat, handleoff);
      LOG_HANDLE ("Handleoff(%3i): %4lX [UMC] (%4lX), ", index, handleoff,
                  omap[i].handle)
      last_handle = omap[i].handle;

      offset = omap[i].address - last_offset;
      bit_write_MC (dat, offset);
      last_offset = omap[i].address;
      LOG_HANDLE ("Offset: %8d [MC] @%lu\n", (int)offset, last_offset);

      ckr_missing = 1;
      if (dat->byte - pvzadr > 2030) // 2029
        {
          ckr_missing = 0;
          sec_size = dat->byte - pvzadr;
          assert (pvzadr);
          // i.e. encode_patch_RS_LE_size
          dat->chain[pvzadr] = sec_size >> 8;
          dat->chain[pvzadr + 1] = sec_size & 0xFF;
          LOG_TRACE ("Handles page size: %u [RS_LE] @%lu\n", sec_size, pvzadr);
          bit_write_CRC_LE (dat, pvzadr, 0xC0C1);

          pvzadr = dat->byte;
          dat->byte += 2;
          last_offset = 0;
          last_handle = 0;
        }
    }
  // printf ("Obj size: %u\n", i);
  if (ckr_missing)
    {
      sec_size = dat->byte - pvzadr;
      assert (pvzadr);
      // i.e. encode_patch_RS_LE_size
      dat->chain[pvzadr] = sec_size >> 8;
      dat->chain[pvzadr + 1] = sec_size & 0xFF;
      LOG_TRACE ("Handles page size: %u [RS_LE] @%lu\n", sec_size, pvzadr);
      bit_write_CRC_LE (dat, pvzadr, 0xC0C1);
    }
  if (dwg->header.version >= R_1_2)
    {
      assert (dat->chain[0] == 'A');
      assert (dat->chain[1] == 'C');
    }
  pvzadr = dat->byte;
  assert (pvzadr);
  bit_write_RS_LE (dat, 2); // last section_size 2
  LOG_TRACE ("Handles page size: %u [RS_LE] @%lu\n", 2, pvzadr);
  bit_write_CRC_LE (dat, pvzadr, 0xC0C1);

  /* Calculate and write the size of the object map
   */
  dwg->header.section[SECTION_HANDLES_R13].size
      = dat->byte - dwg->header.section[SECTION_HANDLES_R13].address;
  free (omap);

  /*------------------------------------------------------------
   * Second header, section 3. R13-R2000 only.
   * But partially also since r2004.
   */
  if (dwg->header.version >= R_13 && dwg->second_header.num_sections > 3)
    {
      struct _dwg_second_header *_obj = &dwg->second_header;
      Dwg_Object *obj = NULL;
      BITCODE_BL vcount;

      assert (dat->byte);
      if (!_obj->address)
        _obj->address = dat->byte;
      dwg->header.section[SECTION_2NDHEADER_R13].number = 3;
      dwg->header.section[SECTION_2NDHEADER_R13].address = _obj->address;
      dwg->header.section[SECTION_2NDHEADER_R13].size = _obj->size;
      LOG_INFO ("\n=======> Second Header: %4u\n", (unsigned)dat->byte);
      bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_SECOND_HEADER_BEGIN));

      pvzadr = dat->byte; // Keep the first address of the section to write its
                          // size later
      LOG_TRACE ("pvzadr: %lx\n", pvzadr);
      if (!_obj->size && !_obj->num_sections)
        {
          LOG_TRACE ("Use second_header defaults...\n");
          strcpy ((char *)&_obj->version[0],
                  &version_codes[dwg->header.version][0]);
          memset (&_obj->version[7], 0, 4);
          _obj->version[11] = '\n';
          _obj->unknown_10 = 0x10;
          _obj->unknown_rc4[0] = 0x84;
          _obj->unknown_rc4[1] = 0x74;
          _obj->unknown_rc4[2] = 0x78;
          _obj->unknown_rc4[3] = 0x1;
          if (dwg->header.version <= R_2000)
            {
              _obj->num_sections = dwg->header.num_sections;
              for (i = 0; i < _obj->num_sections; i++)
                {
                  _obj->section[i].nr = dwg->header.section[i].number;
                  _obj->section[i].address = dwg->header.section[i].address;
                  _obj->section[i].size = dwg->header.section[i].size;
                }
              // TODO handlers
            }
          _obj->junk_r14_1 = 1957593121; //?
          _obj->junk_r14_2 = 2559919056; //?
        }

      FIELD_RL (size, 0);
      if (FIELD_VALUE (address) != (BITCODE_RL) (pvzadr - 16))
        {
          LOG_WARN ("second_header->address %x != %x", FIELD_VALUE (address),
                    (unsigned)(pvzadr - 16));
          FIELD_VALUE (address) = pvzadr - 16;
        }
      FIELD_BLx (address, 0);

      // AC1012, AC1014 or AC1015. This is a char[11], zero padded.
      // with \n at 12.
      bit_write_TF (dat, (char *)_obj->version, 12);
      LOG_TRACE ("version: %s [TFF 12]\n", _obj->version)

      for (i = 0; i < 4; i++)
        FIELD_B (null_b[i], 0);
      FIELD_RC (unknown_10, 0); // 0x10
      for (i = 0; i < 4; i++)
        FIELD_RC (unknown_rc4[i], 0);

      UNTIL (R_2000)
      {
        FIELD_RC (num_sections, 0); // r14: 5, r2000: 6 (auxheader)
        for (i = 0; i < FIELD_VALUE (num_sections); i++)
          {
            FIELD_RC (section[i].nr, 0);
            FIELD_BLx (section[i].address, 0);
            FIELD_BLd (section[i].size, 0);
          }

        FIELD_BS (num_handlers, 0); // 14, resp. 16 in r14
        if (FIELD_VALUE (num_handlers) > 16)
          {
            LOG_ERROR ("Second header num_handlers > 16: %d\n",
                       FIELD_VALUE (num_handlers));
            FIELD_VALUE (num_handlers) = 14;
          }
        for (i = 0; i < FIELD_VALUE (num_handlers); i++)
          {
            FIELD_RC (handlers[i].size, 0);
            FIELD_RC (handlers[i].nr, 0);
            FIELD_VECTOR (handlers[i].data, RC, handlers[i].size, 0);
          }

        _obj->size = encode_patch_RLsize (dat, pvzadr);
        bit_write_CRC (dat, pvzadr, 0xC0C1);

        VERSION (R_14)
        {
          FIELD_RL (junk_r14_1, 0);
          FIELD_RL (junk_r14_2, 0);
        }
      }
      bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_SECOND_HEADER_END));
      dwg->header.section[SECTION_2NDHEADER_R13].size
          = dat->byte - _obj->address;
    }
  else if (dwg->header.num_sections > SECTION_2NDHEADER_R13)
    {
      dwg->header.section[SECTION_2NDHEADER_R13].number = 3;
      dwg->header.section[SECTION_2NDHEADER_R13].address = 0;
      dwg->header.section[SECTION_2NDHEADER_R13].size = 0;
    }

  /*------------------------------------------------------------
   * MEASUREMENT Section 4
   * In a DXF under header_vars
   */
  if (dwg->header.num_sections > SECTION_MEASUREMENT_R13)
    {
      LOG_INFO ("\n=======> MEASUREMENT: %4u\n", (unsigned)dat->byte);
      dwg->header.section[SECTION_MEASUREMENT_R13].number = 4;
      dwg->header.section[SECTION_MEASUREMENT_R13].address = dat->byte;
      dwg->header.section[SECTION_MEASUREMENT_R13].size = 4;
      // 0 - English, 1- Metric
      bit_write_RL (dat, (BITCODE_RL)dwg->header_vars.MEASUREMENT);
      LOG_TRACE ("HEADER.MEASUREMENT: %d [RL]\n", dwg->header_vars.MEASUREMENT);
    }

  /* End of the file
   */
  dat->size = dat->byte;

  /* Write section addresses
   */
  assert (section_address);
  dat->byte = section_address;
  dat->bit = 0;
  LOG_INFO ("\n=======> section addresses: %4u\n", (unsigned)dat->byte);
  for (j = 0; j < dwg->header.num_sections; j++)
    {
      bit_write_RC (dat, dwg->header.section[j].number);
      bit_write_RL (dat, dwg->header.section[j].address);
      bit_write_RL (dat, dwg->header.section[j].size);
      LOG_TRACE ("section[%u].number: %2d [RC]\n", j,
                 (int)dwg->header.section[j].number)
      LOG_TRACE ("section[%u].offset: 0x%x [RLx]\n", j,
                 (unsigned)dwg->header.section[j].address)
      LOG_TRACE ("section[%u].size: %4d [RL]\n", j,
                 (int)dwg->header.section[j].size)
    }

  /* Write CRC's
   */
  bit_write_CRC (dat, 0, 0);
  dat->byte -= 2;
  ckr = bit_read_CRC (dat);
  dat->byte -= 2;
  switch (dwg->header.num_sections)
    {
    case 3:
      ckr ^= 0xA598;
      break;
    case 4:
      ckr ^= 0x8101;
      break;
    case 5:
      ckr ^= 0x3CC4;
      break;
    case 6:
      ckr ^= 0x8461;
      break;
    default:
      break;
    }
  bit_write_RS (dat, ckr);
  LOG_TRACE ("crc: %04X (from 0)\n", ckr);

  return 0;
}
dwg_encode (Dwg_Data *restrict dwg, Bit_Chain *restrict dat)
{
  int ckr_missing = 1;
  int error = 0;
  BITCODE_BL i, j;
  long unsigned int section_address;
  unsigned char pvzbit;
  long unsigned int pvzadr;
  long unsigned int pvzadr_2;
  unsigned int ckr;
  unsigned int sec_size = 0;
  long unsigned int last_offset;
  BITCODE_BL last_handle;
  Object_Map *omap;
  Bit_Chain *hdl_dat;

  if (dwg->opts)
    loglevel = dwg->opts & DWG_OPTS_LOGLEVEL;
#ifdef USE_TRACING
   
  if (!env_var_checked_p)
    {
      char *probe = getenv ("LIBREDWG_TRACE");
      if (probe)
        loglevel = atoi (probe);
      env_var_checked_p = true;
    }
#endif  

  bit_chain_alloc (dat);
  hdl_dat = dat;

   
  strcpy ((char *)dat->chain,
          version_codes[dwg->header.version]);  
  if (dwg->header.version != dwg->header.from_version)
    LOG_TRACE ("Encode version %s from version %s\n",
               version_codes[dwg->header.version],
               version_codes[dwg->header.from_version])
  else
    LOG_TRACE ("Encode version %s\n", version_codes[dwg->header.version])
  dat->byte += 6;

  {
    struct Dwg_Header *_obj = &dwg->header;
    Dwg_Object *obj = NULL;
    if (!_obj->dwg_version)
      {
        _obj->is_maint = 0;
        switch (dwg->header.version)
          {
          case R_9:
            _obj->dwg_version = 0x11;  
            break;
          case R_10:
            _obj->dwg_version = 0x12;  
            break;
          case R_11:
            _obj->dwg_version = 0x13;  
            break;
          case R_13:
            _obj->dwg_version = 0x15;
            break;
          case R_14:
            _obj->dwg_version = 0x16;
            break;
          case R_2000:
            _obj->dwg_version = 0x17;
            _obj->is_maint = 0xf;
            break;
          case R_2004:
            _obj->dwg_version = 0x19;
            _obj->is_maint = 0x68;
            break;
          case R_2007:
            _obj->dwg_version = 0x1b;
            _obj->is_maint = 0x32;
            break;
          case R_2010:
            _obj->dwg_version = 0x1d;
            _obj->is_maint = 0x6d;
            break;
          case R_2013:
            _obj->dwg_version = 0x1f;
            _obj->is_maint = 0x7d;
            break;
          case R_2018:
            _obj->dwg_version = 0x21;
            _obj->is_maint = 0x4;
            break;
          case R_INVALID:
          case R_AFTER:
          case R_1_1:
          case R_1_2:
          case R_1_4:
          case R_2_0:
          case R_2_1:
          case R_2_5:
          case R_2_6:
          default:
            break;
          }
        if (!_obj->app_dwg_version)
          _obj->app_dwg_version = _obj->dwg_version;
      }
    if (!_obj->codepage)
      _obj->codepage = 30;

     
    #include "header.spec"
     
  }
  section_address = dat->byte;

#define WE_CAN                                                                \
  "This version of LibreDWG is only capable of encoding "                     \
  "version R13-R2000 (code: AC1012-AC1015) DWG files.\n"

  PRE (R_13)
  {
     
    LOG_ERROR (WE_CAN "We don't encode preR13 tables, entities, blocks yet")
#ifndef IS_RELEASE
    return encode_preR13 (dwg, dat);
#endif
  }

  PRE (R_2004)
  {
     
    if (!dwg->header.num_sections)  
      {
        dwg->header.num_sections = dwg->header.version < R_2000 ? 5 : 6;
         
        if (!dwg->header_vars.HANDSEED || !dwg->header_vars.TDCREATE.days)
          {
            dwg->header.num_sections = 5;
            dat->from_version = R_11;  
            if (dat->version <= dat->from_version)
              dat->from_version = dat->version - 1;
          }
      }
    LOG_TRACE ("num_sections: " FORMAT_RL " [RL]\n", dwg->header.num_sections);
    bit_write_RL (dat, dwg->header.num_sections);
    if (!dwg->header.section)
      dwg->header.section
          = calloc (dwg->header.num_sections, sizeof (Dwg_Section));
    section_address = dat->byte;                  
    dat->byte += (dwg->header.num_sections * 9);  
    bit_write_CRC (dat, 0, 0xC0C1);
    bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_HEADER_END));

     
    if (dwg->header.num_sections > 5)
      {
        struct Dwg_AuxHeader *_obj = &dwg->auxheader;
        Dwg_Object *obj = NULL;
        assert (!dat->bit);
        LOG_INFO ("\n=======> AuxHeader: %8u\n",
                  (unsigned)dat->byte);  

        dwg->header.section[SECTION_AUXHEADER_R2000].number = 5;
        dwg->header.section[SECTION_AUXHEADER_R2000].address = dat->byte;

        if (!_obj->dwg_version)
          {
            BITCODE_RS tmpunknown[] = { 4, 0x565, 0, 0, 2, 1 };
            LOG_TRACE ("Use AuxHeader defaults...\n");
            FIELD_VALUE (aux_intro[0]) = 0xff;
            FIELD_VALUE (aux_intro[1]) = 0x77;
            FIELD_VALUE (aux_intro[2]) = 0x01;
            FIELD_VALUE (minus_1) = -1;
            FIELD_VALUE (dwg_version) = dwg->header.dwg_version;
            FIELD_VALUE (maint_version) = dwg->header.maint_version;
            FIELD_VALUE (dwg_version_1) = dwg->header.dwg_version;
            FIELD_VALUE (dwg_version_2) = dwg->header.dwg_version;
            FIELD_VALUE (maint_version_1) = dwg->header.maint_version;
            FIELD_VALUE (maint_version_2) = dwg->header.maint_version;
            memcpy (FIELD_VALUE (unknown_rs), tmpunknown, sizeof (tmpunknown));
            FIELD_VALUE (TDCREATE) = dwg->header_vars.TDCREATE.value;
            FIELD_VALUE (TDUPDATE) = dwg->header_vars.TDUPDATE.value;
            if (dwg->header_vars.HANDSEED)
              FIELD_VALUE (HANDSEED) = dwg->header_vars.HANDSEED->absolute_ref;
          }

           
        #include "auxheader.spec"
         

        assert (!dat->bit);
        dwg->header.section[SECTION_AUXHEADER_R2000].size
            = dat->byte - dwg->header.section[SECTION_AUXHEADER_R2000].address;
      }
  }

  VERSION (R_2007)
  {
    LOG_ERROR (WE_CAN "We don't encode R2007 sections yet")
    return DWG_ERR_NOTYETSUPPORTED;
  }

   
  SINCE (R_2004)
  {
     
    typedef union _system_section
    {
      unsigned char data[0x14];  
      struct
      {
        uint32_t section_type;  
        uint32_t decomp_data_size;
        uint32_t comp_data_size;
        uint32_t compression_type;
        uint32_t checksum;  
      } fields;
    } system_section;

    system_section ss;
    Dwg_Section *section;

    Dwg_Object *obj = NULL;
    struct Dwg_R2004_Header *_obj = &dwg->r2004_header;
    const int size = sizeof (struct Dwg_R2004_Header);
    char encrypted_data[size];
    unsigned int rseed = 1;
    uint32_t checksum;

    LOG_ERROR (WE_CAN "We don't encode the R2004_section_map yet")

    if (dwg->header.section_infohdr.num_desc && !dwg->header.section_info)
      dwg->header.section_info = calloc (dwg->header.section_infohdr.num_desc,
                                         sizeof (Dwg_Section_Info));

    dat->byte = 0x80;
    for (i = 0; i < (BITCODE_BL)size; i++)
      {
        rseed *= 0x343fd;
        rseed += 0x269ec3;
        encrypted_data[i] = bit_read_RC (dat) ^ (rseed >> 0x10);
      }
    LOG_TRACE ("\n#### Write 2004 File Header ####\n");
    dat->byte = 0x80;
    if (dat->byte + 0x80 >= dat->size - 1)
      {
        dat->size = dat->byte + 0x80;
        bit_chain_alloc (dat);
      }
    memcpy (&dat->chain[0x80], encrypted_data, size);
    LOG_INFO ("@0x%lx\n", dat->byte);

     
    #include "r2004_file_header.spec"
     

    dwg->r2004_header.checksum = 0;
    dwg->r2004_header.checksum = dwg_section_page_checksum (0, dat, size);

     
    dat->byte = dwg->r2004_header.section_map_address + 0x100;

    LOG_TRACE ("\n=== Write System Section (Section Page Map) ===\n");
#ifndef HAVE_COMPRESS_R2004_SECTION
    dwg->r2004_header.comp_data_size = dwg->r2004_header.decomp_data_size;
    dwg->r2004_header.compression_type = 0;
#endif
    FIELD_RL (section_type, 0);  
    FIELD_RL (decomp_data_size, 0);
    FIELD_RL (comp_data_size, 0);
    FIELD_RL (compression_type, 0);
    dwg_section_page_checksum (dwg->r2004_header.checksum, dat, size);
    FIELD_RL (checksum, 0);
    LOG_TRACE ("\n")

    LOG_WARN ("TODO write_R2004_section_map(dat, dwg)")
    LOG_TRACE ("\n")

    return DWG_ERR_NOTYETSUPPORTED;
  }

   
  if (!dwg->header.thumbnail_address)
    dwg->header.thumbnail_address = dat->byte;
  dat->bit = 0;
  LOG_TRACE ("\n=======> Thumbnail:       %4u\n", (unsigned)dat->byte);
   
  bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_THUMBNAIL_BEGIN));
  if (dwg->thumbnail.size == 0)
    {
      bit_write_RL (dat, 5);  
      LOG_TRACE ("Thumbnail size: 5 [RL]\n");
      bit_write_RC (dat, 0);  
      LOG_TRACE ("Thumbnail num_pictures: 0 [RC]\n");
    }
  else
    {
      bit_write_TF (dat, (char *)dwg->thumbnail.chain, dwg->thumbnail.size);
    }
  bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_THUMBNAIL_END));

  {
    BITCODE_RL size;
    dwg_bmp (dwg, &size);
    if (size > dwg->thumbnail.size)
      LOG_ERROR ("BMP size overflow: %i > %lu\n", size, dwg->thumbnail.size);
  }
  LOG_TRACE ("         Thumbnail (end): %4u\n", (unsigned)dat->byte);

   
  assert (!dat->bit);
  LOG_INFO ("\n=======> Header Variables:   %4u\n", (unsigned)dat->byte);
  dwg->header.section[0].number = 0;
  dwg->header.section[0].address = dat->byte;
  bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_VARIABLE_BEGIN));

  pvzadr = dat->byte;       
  bit_write_RL (dat, 540);  
   
   
  dwg_encode_header_variables (dat, hdl_dat, dat, dwg);
  encode_patch_RLsize (dat, pvzadr);
  bit_write_CRC (dat, pvzadr, 0xC0C1);

   
   
  bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_VARIABLE_END));
  assert ((long)dat->byte > (long)dwg->header.section[0].address);
  dwg->header.section[0].size
      = (BITCODE_RL) ((long)dat->byte - (long)dwg->header.section[0].address);
  LOG_TRACE ("         Header Variables (end): %4u\n", (unsigned)dat->byte);

   
  LOG_INFO ("\n=======> Classes: %4u (%d)\n", (unsigned)dat->byte, dwg->num_classes);
  dwg->header.section[SECTION_CLASSES_R13].number = 1;
  dwg->header.section[SECTION_CLASSES_R13].address = dat->byte;
  bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_CLASS_BEGIN));
  pvzadr = dat->byte;     
  bit_write_RL (dat, 0);  

  for (j = 0; j < dwg->num_classes; j++)
    {
      Dwg_Class *klass;
      klass = &dwg->dwg_class[j];
      bit_write_BS (dat, klass->number);
      bit_write_BS (dat, klass->proxyflag);
      bit_write_TV (dat, klass->appname);
      bit_write_TV (dat, klass->cppname);
      bit_write_TV (dat, klass->dxfname);
      bit_write_B (dat, klass->wasazombie);
      bit_write_BS (dat, klass->item_class_id);
      LOG_TRACE ("Class %d 0x%x %s\n"
                 " %s \"%s\" %d 0x%x\n",
                 klass->number, klass->proxyflag, klass->dxfname,
                 klass->cppname, klass->appname, klass->wasazombie,
                 klass->item_class_id)

      SINCE (R_2007)
      {
        bit_write_BL (dat, klass->num_instances);
        bit_write_BL (dat, klass->dwg_version);
        bit_write_BL (dat, klass->maint_version);
        bit_write_BL (dat, klass->unknown_1);
        bit_write_BL (dat, klass->unknown_2);
        LOG_TRACE (" %d %d\n", (int)klass->num_instances,
                   (int)klass->dwg_version);
      }
    }

   
  assert (pvzadr);
  encode_patch_RLsize (dat, pvzadr);
  bit_write_CRC (dat, pvzadr, 0xC0C1);
  bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_CLASS_END));
  dwg->header.section[SECTION_CLASSES_R13].size
      = dat->byte - dwg->header.section[SECTION_CLASSES_R13].address;
  LOG_TRACE ("       Classes (end): %4u\n", (unsigned)dat->byte);

  bit_write_RL (dat, 0x0DCA);  
  LOG_TRACE ("unknown: %04X [RL]\n", 0x0DCA);

   

  LOG_INFO ("\n=======> Objects: %4u\n", (unsigned)dat->byte);
  pvzadr = dat->byte;

   
  LOG_TRACE ("num_objects: %i\n", dwg->num_objects);
  LOG_TRACE ("num_object_refs: %i\n", dwg->num_object_refs);
  omap = (Object_Map *)calloc (dwg->num_objects, sizeof (Object_Map));
  if (!omap)
    {
      LOG_ERROR ("Out of memory");
      return DWG_ERR_OUTOFMEM;
    }
  if (DWG_LOGLEVEL >= DWG_LOGLEVEL_HANDLE)
    {
      LOG_HANDLE ("\nSorting objects...\n");
      for (i = 0; i < dwg->num_objects; i++)
        fprintf (OUTPUT, "Object(%3i): %4lX / idx: %u\n", i,
                 dwg->object[i].handle.value, dwg->object[i].index);
    }
   
  for (i = 0; i < dwg->num_objects; i++)
    {
      omap[i].index = i;  
      omap[i].handle = dwg->object[i].handle.value;
    }
   
  for (i = 0; i < dwg->num_objects; i++)
    {
      Object_Map tmap;
      j = i;
      tmap = omap[i];
      while (j > 0 && omap[j - 1].handle > tmap.handle)
        {
          omap[j] = omap[j - 1];
          j--;
        }
      omap[j] = tmap;
    }
  if (DWG_LOGLEVEL >= DWG_LOGLEVEL_HANDLE)
    {
      LOG_HANDLE ("\nSorted handles:\n");
      for (i = 0; i < dwg->num_objects; i++)
        fprintf (OUTPUT, "Handle(%3i): %4lX / idx: %u\n", i, omap[i].handle,
                 omap[i].index);
    }

   
  for (i = 0; i < dwg->num_objects; i++)
    {
      Dwg_Object *obj;
      BITCODE_BL index = omap[i].index;
      unsigned long hdloff = omap[i].handle - (i ? omap[i - 1].handle : 0);
      int off = dat->byte - (i ? omap[i - 1].address : 0);
      unsigned long address, end_address;
      LOG_TRACE ("\n> Next object: " FORMAT_BL
                 " Handleoff: %lX [UMC] Offset: %d [MC] @%lu\n"
                 "==========================================\n",
                 i, hdloff, off, dat->byte);
      omap[i].address = dat->byte;
      if (index > dwg->num_objects)
        {
          LOG_ERROR ("Invalid object map index " FORMAT_BL ", max " FORMAT_BL
                     ". Skipping",
                     index, dwg->num_objects)
          error |= DWG_ERR_VALUEOUTOFBOUNDS;
          continue;
        }
      obj = &dwg->object[index];
       
      assert (dat->byte);
      error |= dwg_encode_add_object (obj, dat, dat->byte);

#ifndef NDEBUG
       
      if (dwg->header.version >= R_1_2)
        {
          assert (dat->chain[0] == 'A');
          assert (dat->chain[1] == 'C');
        }
#endif
      end_address = omap[i].address + (unsigned long)obj->size;  
      if (end_address > dat->size)
        {
          dat->size = end_address;
          bit_chain_alloc (dat);
        }
    }

  if (DWG_LOGLEVEL >= DWG_LOGLEVEL_HANDLE)
    {
      LOG_HANDLE ("\nSorted objects:\n");
      for (i = 0; i < dwg->num_objects; i++)
        LOG_HANDLE ("Object(%d): %lX / Address: %ld / Idx: %d\n", i,
                    omap[i].handle, omap[i].address, omap[i].index);
    }

   
  bit_write_RS (dat, 0);
  LOG_TRACE ("unknown crc?: %04X [RS]\n", 0);

   
  LOG_INFO ("\n=======> Object Map: %4u\n", (unsigned)dat->byte);
  dwg->header.section[SECTION_HANDLES_R13].number = 2;
  dwg->header.section[SECTION_HANDLES_R13].address = dat->byte;

  sec_size = 0;
  pvzadr = dat->byte;  
  dat->byte += 2;
  last_offset = 0;
  last_handle = 0;
  for (i = 0; i < dwg->num_objects; i++)
    {
      BITCODE_BL index;
      BITCODE_UMC handleoff;
      BITCODE_MC offset;

      index = omap[i].index;
      handleoff = omap[i].handle - last_handle;
      bit_write_UMC (dat, handleoff);
      LOG_HANDLE ("Handleoff(%3i): %4lX [UMC] (%4lX), ", index, handleoff,
                  omap[i].handle)
      last_handle = omap[i].handle;

      offset = omap[i].address - last_offset;
      bit_write_MC (dat, offset);
      last_offset = omap[i].address;
      LOG_HANDLE ("Offset: %8d [MC] @%lu\n", (int)offset, last_offset);

      ckr_missing = 1;
      if (dat->byte - pvzadr > 2030)  
        {
          ckr_missing = 0;
          sec_size = dat->byte - pvzadr;
          assert (pvzadr);
           
          dat->chain[pvzadr] = sec_size >> 8;
          dat->chain[pvzadr + 1] = sec_size & 0xFF;
          LOG_TRACE ("Handles page size: %u [RS_LE] @%lu\n", sec_size, pvzadr);
          bit_write_CRC_LE (dat, pvzadr, 0xC0C1);

          pvzadr = dat->byte;
          dat->byte += 2;
          last_offset = 0;
          last_handle = 0;
        }
    }
   
  if (ckr_missing)
    {
      sec_size = dat->byte - pvzadr;
      assert (pvzadr);
       
      dat->chain[pvzadr] = sec_size >> 8;
      dat->chain[pvzadr + 1] = sec_size & 0xFF;
      LOG_TRACE ("Handles page size: %u [RS_LE] @%lu\n", sec_size, pvzadr);
      bit_write_CRC_LE (dat, pvzadr, 0xC0C1);
    }
  if (dwg->header.version >= R_1_2)
    {
      assert (dat->chain[0] == 'A');
      assert (dat->chain[1] == 'C');
    }
  pvzadr = dat->byte;
  assert (pvzadr);
  bit_write_RS_LE (dat, 2);  
  LOG_TRACE ("Handles page size: %u [RS_LE] @%lu\n", 2, pvzadr);
  bit_write_CRC_LE (dat, pvzadr, 0xC0C1);

   
  dwg->header.section[SECTION_HANDLES_R13].size
      = dat->byte - dwg->header.section[SECTION_HANDLES_R13].address;
  free (omap);

   
  if (dwg->header.version >= R_13 && dwg->second_header.num_sections > 3)
    {
      struct _dwg_second_header *_obj = &dwg->second_header;
      Dwg_Object *obj = NULL;
      BITCODE_BL vcount;

      assert (dat->byte);
      if (!_obj->address)
        _obj->address = dat->byte;
      dwg->header.section[SECTION_2NDHEADER_R13].number = 3;
      dwg->header.section[SECTION_2NDHEADER_R13].address = _obj->address;
      dwg->header.section[SECTION_2NDHEADER_R13].size = _obj->size;
      LOG_INFO ("\n=======> Second Header: %4u\n", (unsigned)dat->byte);
      bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_SECOND_HEADER_BEGIN));

      pvzadr = dat->byte;  
                           
      LOG_TRACE ("pvzadr: %lx\n", pvzadr);
      if (!_obj->size && !_obj->num_sections)
        {
          LOG_TRACE ("Use second_header defaults...\n");
          strcpy ((char *)&_obj->version[0],
                  &version_codes[dwg->header.version][0]);
          memset (&_obj->version[7], 0, 4);
          _obj->version[11] = '\n';
          _obj->unknown_10 = 0x10;
          _obj->unknown_rc4[0] = 0x84;
          _obj->unknown_rc4[1] = 0x74;
          _obj->unknown_rc4[2] = 0x78;
          _obj->unknown_rc4[3] = 0x1;
          if (dwg->header.version <= R_2000)
            {
              _obj->num_sections = dwg->header.num_sections;
              for (i = 0; i < _obj->num_sections; i++)
                {
                  _obj->section[i].nr = dwg->header.section[i].number;
                  _obj->section[i].address = dwg->header.section[i].address;
                  _obj->section[i].size = dwg->header.section[i].size;
                }
               
            }
          _obj->junk_r14_1 = 1957593121;  
          _obj->junk_r14_2 = 2559919056;  
        }

      FIELD_RL (size, 0);
      if (FIELD_VALUE (address) != (BITCODE_RL) (pvzadr - 16))
        {
          LOG_WARN ("second_header->address %x != %x", FIELD_VALUE (address),
                    (unsigned)(pvzadr - 16));
          FIELD_VALUE (address) = pvzadr - 16;
        }
      FIELD_BLx (address, 0);

       
       
      bit_write_TF (dat, (char *)_obj->version, 12);
      LOG_TRACE ("version: %s [TFF 12]\n", _obj->version)

      for (i = 0; i < 4; i++)
        FIELD_B (null_b[i], 0);
      FIELD_RC (unknown_10, 0);  
      for (i = 0; i < 4; i++)
        FIELD_RC (unknown_rc4[i], 0);

      UNTIL (R_2000)
      {
        FIELD_RC (num_sections, 0);  
        for (i = 0; i < FIELD_VALUE (num_sections); i++)
          {
            FIELD_RC (section[i].nr, 0);
            FIELD_BLx (section[i].address, 0);
            FIELD_BLd (section[i].size, 0);
          }

        FIELD_BS (num_handlers, 0);  
        if (FIELD_VALUE (num_handlers) > 16)
          {
            LOG_ERROR ("Second header num_handlers > 16: %d\n",
                       FIELD_VALUE (num_handlers));
            FIELD_VALUE (num_handlers) = 14;
          }
        for (i = 0; i < FIELD_VALUE (num_handlers); i++)
          {
            FIELD_RC (handlers[i].size, 0);
            FIELD_RC (handlers[i].nr, 0);
            FIELD_VECTOR (handlers[i].data, RC, handlers[i].size, 0);
          }

        _obj->size = encode_patch_RLsize (dat, pvzadr);
        bit_write_CRC (dat, pvzadr, 0xC0C1);

        VERSION (R_14)
        {
          FIELD_RL (junk_r14_1, 0);
          FIELD_RL (junk_r14_2, 0);
        }
      }
      bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_SECOND_HEADER_END));
      dwg->header.section[SECTION_2NDHEADER_R13].size
          = dat->byte - _obj->address;
    }
  else if (dwg->header.num_sections > SECTION_2NDHEADER_R13)
    {
      dwg->header.section[SECTION_2NDHEADER_R13].number = 3;
      dwg->header.section[SECTION_2NDHEADER_R13].address = 0;
      dwg->header.section[SECTION_2NDHEADER_R13].size = 0;
    }

   
  if (dwg->header.num_sections > SECTION_MEASUREMENT_R13)
    {
      LOG_INFO ("\n=======> MEASUREMENT: %4u\n", (unsigned)dat->byte);
      dwg->header.section[SECTION_MEASUREMENT_R13].number = 4;
      dwg->header.section[SECTION_MEASUREMENT_R13].address = dat->byte;
      dwg->header.section[SECTION_MEASUREMENT_R13].size = 4;
       
      bit_write_RL (dat, (BITCODE_RL)dwg->header_vars.MEASUREMENT);
      LOG_TRACE ("HEADER.MEASUREMENT: %d [RL]\n", dwg->header_vars.MEASUREMENT);
    }

   
  dat->size = dat->byte;

   
  assert (section_address);
  dat->byte = section_address;
  dat->bit = 0;
  LOG_INFO ("\n=======> section addresses: %4u\n", (unsigned)dat->byte);
  for (j = 0; j < dwg->header.num_sections; j++)
    {
      bit_write_RC (dat, dwg->header.section[j].number);
      bit_write_RL (dat, dwg->header.section[j].address);
      bit_write_RL (dat, dwg->header.section[j].size);
      LOG_TRACE ("section[%u].number: %2d [RC]\n", j,
                 (int)dwg->header.section[j].number)
      LOG_TRACE ("section[%u].offset: 0x%x [RLx]\n", j,
                 (unsigned)dwg->header.section[j].address)
      LOG_TRACE ("section[%u].size: %4d [RL]\n", j,
                 (int)dwg->header.section[j].size)
    }

   
  bit_write_CRC (dat, 0, 0);
  dat->byte -= 2;
  ckr = bit_read_CRC (dat);
  dat->byte -= 2;
  switch (dwg->header.num_sections)
    {
    case 3:
      ckr ^= 0xA598;
      break;
    case 4:
      ckr ^= 0x8101;
      break;
    case 5:
      ckr ^= 0x3CC4;
      break;
    case 6:
      ckr ^= 0x8461;
      break;
    default:
      break;
    }
  bit_write_RS (dat, ckr);
  LOG_TRACE ("crc: %04X (from 0)\n", ckr);

  return 0;
}