     1                                  ;*********************************************************************
     2                                  ;*   MLDDL1.ASM                                                      *
     3                                  ;*                                                                   *
     4                                  ;*   By:            Michael Devore                                   *
     5                                  ;*   Date:          04/04/93                                         *
     6                                  ;*   Model:         Small                                            *
     7                                  ;*   Version:       2.5                                              *
     8                                  ;*   Assembler:     MASM 5.0                                         *
     9                                  ;*   Environment:   MS-DOS 2.x+                                      *
    10                                  ;*                                                                   *
    11                                  ;*   DDL specific code, part 1                                       *
    12                                  ;*                                                                   *
    13                                  ;*********************************************************************
    14                                  
    15                                  ;TITLE   WARPLINK mlddl1
    16                                  ;PAGE    50,80
    17                                  
    18                                  ;.MODEL  SMALL
    19                                  
    20                                  ;*****************************
    21                                  ;* Equates                   *
    22                                  ;*****************************
    23                                  
    24                                  DDL_HEADER_SIZE EQU 128     ; size of DDL header (on 16-byte boundary)
    25                                  MOD_HEADER_SIZE EQU 64      ; size of module header in DDL file (rounded to 16-byte boundary)
    26                                  BIN_HEADER_SIZE EQU 20      ; size of segment binary header
    27                                  
    28                                  ;*****************************
    29                                  ;* Include files             *
    30                                  ;*****************************
    31                                  
    32                                  [list -]
    37                                       
    38                                  ;*****************************
    39                                  ;* Public declarations       *
    40                                  ;*****************************
    41                                  
    42                                  ; procedures
    43                                  PUBLIC  proc_ddl,create_ddl,write_ddl_module,save_module_type
    44                                  PUBLIC  parse_ddl_option,reinit_variables
    45                                  PUBLIC  ddl_fixupp,ddl_datarec,ddl_pad
    46                                  
    47                                  ; variables
    48                                  PUBLIC  ddl_header,mod_header
    49                                  
    50                                  ;*****************************
    51                                  ;* Data begins               *
    52                                  ;*****************************
    53                                  
    54                                  .DATA
    55                                  
    56                                  ;*****************************
    57                                  ;* External declarations     *
    58                                  ;*****************************
    59                                  
    60                                  EXTRN   exe_handle:WORD,libmod_obj_flag:BYTE
    61                                  EXTRN   first_udlent_ptr:WORD
    62                                  EXTRN   first_lnamesblk_ptr:WORD,first_pdnameblk_ptr:WORD
    63                                  EXTRN   objtext:BYTE,mod_alloc_base:WORD
    64                                  EXTRN	ddl_depend_count:BYTE
    65                                  
    66                                  ; initialized variables
    67                                  EVEN
    68 00000000 0000                    module_id   DW  0           ; current module identifier
    69 00000002 0000                    first_ddl_fpos  DW  0       ; segment of first allocated ddl module file position block
    70 00000004 0000                    alloc_ddl_fpos  DW  0       ; segment of last allocated ddl module file position block
    71 00000006 0000                    pubcount    DW  0           ; count of publics in module
    72 00000008 0000                    comcount    DW  0           ; count of communals in module
    73 0000000A 0000                    extcount    DW  0           ; count of externals in module
    74 0000000C 0000                    modend_ptr  DW  0           ; pointer to block that holds MODEND info
    75                                  
    76                                  ; structures
    77                                  DDL_HEADER_STRUC    STRUC
    78 00000000 ??                          dh_sig1 DB  ?           ; DDL file signature bytes
    79 00000001 ??                          dh_sig2 DB  ?
    80 00000002 ??                          dh_sig3 DB  ?
    81 00000003 ??                          dh_sig4 DB  ?
    82 00000004 ??                          dh_majorver DB  ?       ; major version number
    83 00000005 ??                          dh_minor1   DB  ?       ; minor version number 1
    84 00000006 ??                          dh_minor2   DB  ?       ; minor version number 2
    85 00000007 ??                          dh_minor3   DB  ?       ; minor version alpha
    86 00000008 ????                        dh_hdrsize  DW  ?       ; size of module header
    87 0000000A ????                        dh_loadsize DW  ?       ; size of DDL loader
    88 0000000C ????????                    dh_loadstart    DD  ?   ; file position of start of loader
    89 00000010 ????????                    dh_flags    DD  ?       ; DDL flags
    90                                                              ; bit 0==main module flag
    91                                                              ; bit 1==required root modules flag
    92                                                              ; bit 2==required overlay modules flag
    93                                                              ; bit 3==elective root modules flag
    94                                                              ; bit 4==elective overlay modules flag
    95                                                              ; bit 5==DOSSEG flag
    96                                                              ; bit 6==contains pre-loading routine
    97 00000014 ????????                    dh_op       DD  ?       ; /op option value
    98 00000018 ????                        dh_st       DW  ?       ; /st option value
    99 0000001A ????                        dh_as       DW  ?       ; /as option value
   100 0000001C ????                        dh_os       DW  ?       ; /os option value
   101 0000001E ????                        dh_ol       DW  ?       ; /ol option value
   102 00000020 ??                          dh_mem      DB  ?       ; 0==free mem op, nonzero==alloc mem op
   103 00000021 ??                          dh_minop    DB  ?       ; 0==normal /op, 1==/op:m
   104 00000022 ??                          dh_ox       DB  ?       ; 0==regular memory for op, nonzero==EMS page frame for op
   105 00000023 ??                          dh_r        DB  ?       ; /r option setting
   106 00000024 ??                          dh_cla      DB  ?       ; /cla option setting
   107 00000025 ??                          dh_ou       DB  ?       ; /ou option setting
   108 00000026 ??                          dh_ort      DB  ?       ; /ort setting
   109 00000027 ??                          dh_orp      DB  ?       ; /orp setting
   110 00000028 ????                        dh_modcount DW  ?       ; module count in DDL
   111 0000002A ????                        dh_ddlcount DW  ?       ; count of DDL's in dependency list (for main module)
   112 0000002C ????                        dh_reqroot  DW  ?       ; count of required root modules in DDL
   113 0000002E ????                        dh_reqovl   DW  ?       ; count of required overlay modules in DDL
   114 00000030 ????                        dh_elecroot DW  ?       ; count of elective root modules in DDL
   115 00000032 ????                        dh_elecovl  DW  ?       ; count of elective overlay modules in DDL
   116 00000034 ????????                    dh_ddlstart DD  ?       ; file position of start of DDL dependency list
   117 00000038 ????????                    dh_preload  DD  ?       ; file position of pre-load module
   118 0000003C ????????                    dh_modstart DD  ?       ; file position of start of DDL module file position dword entries
   119 00000040 ????????                    dh_dictstart    DD  ?   ; file position of start of DDL dictionary
   120                                  
   121 00000044 ??                      	dh_ohp3		DB	?		; flag ohp3 use
   122 00000045 ??                      	dh_ohp_flag	DB	?		; nonzero if /ohp allocate to amount flag set
   123 00000046 ??                      	dh_oht_flag	DB	?		; nonzero if /oht allocate to amount flag set
   124 00000047 ??                      	dh_pad		DB	?		; pad value
   125 00000048 ????                    	dh_ohp		DW	?		; /ohp size in K
   126 0000004A ????                    	dh_oht		DW	?		; /oht size in K
   127                                  
   128 0000004C ????????                    dh_reser3   DD  ?       ; reserved for future
   129 00000050 ????????                    dh_reser4   DD  ?       ; reserved for future
   130 00000054 <res 20h>                   dh_oxevar   DB  32 DUP (?)  ; specified /ox environment variable
   131                                  DDL_HEADER_STRUC    ENDS
   132                                  
   133                                  ddl_header:
   134                                  istruc DDL_HEADER_STRUC
   135                                  at dh_sig1
   136 0000000E 4D                      ddl_header.dh_sig1:	db 'M'
   137                                  at dh_sig2
   138 0000000F 44                      ddl_header.dh_sig2:	db 'D'
   139                                  at dh_sig3
   140 00000010 44                      ddl_header.dh_sig3:	db 'D'
   141                                  at dh_sig4
   142 00000011 4C                      ddl_header.dh_sig4:	db 'L'
   143                                  at dh_majorver
   144 00000012 32                      ddl_header.dh_majorver:	db '2'
   145                                  at dh_minor1
   146 00000013 30                      ddl_header.dh_minor1:	db '0'
   147                                  at dh_minor2
   148 00000014 30                      ddl_header.dh_minor2:	db '0'
   149                                  at dh_minor3
   150 00000015 61                      ddl_header.dh_minor3:	db 'a'
   151                                  at dh_hdrsize
   152 00000016 0000                    ddl_header.dh_hdrsize:	dw 0
   153                                  at dh_loadsize
   154 00000018 0000                    ddl_header.dh_loadsize:	dw 0
   155                                  at dh_loadstart
   156 0000001A 00000000                ddl_header.dh_loadstart:	dd 0
   157                                  at dh_flags
   158 0000001E 00000000                ddl_header.dh_flags:	dd 0
   159                                  at dh_op
   160 00000022 00000000                ddl_header.dh_op:	dd 0
   161                                  at dh_st
   162 00000026 0000                    ddl_header.dh_st:	dw 0
   163                                  at dh_as
   164 00000028 0000                    ddl_header.dh_as:	dw 0
   165                                  at dh_os
   166 0000002A 0000                    ddl_header.dh_os:	dw 0
   167                                  at dh_ol
   168 0000002C 0000                    ddl_header.dh_ol:	dw 0
   169                                  at dh_mem
   170 0000002E 00                      ddl_header.dh_mem:	db 0
   171                                  at dh_minop
   172 0000002F 00                      ddl_header.dh_minop:	db 0
   173                                  at dh_ox
   174 00000030 00                      ddl_header.dh_ox:	db 0
   175                                  at dh_r
   176 00000031 00                      ddl_header.dh_r:	db 0
   177                                  at dh_cla
   178 00000032 00                      ddl_header.dh_cla:	db 0
   179                                  at dh_ou
   180 00000033 00                      ddl_header.dh_ou:	db 0
   181                                  at dh_ort
   182 00000034 00                      ddl_header.dh_ort:	db 0
   183                                  at dh_orp
   184 00000035 00                      ddl_header.dh_orp:	db 0
   185                                  at dh_modcount
   186 00000036 0000                    ddl_header.dh_modcount:	dw 0
   187                                  at dh_ddlcount
   188 00000038 0000                    ddl_header.dh_ddlcount:	dw 0
   189                                  at dh_reqroot
   190 0000003A 0000                    ddl_header.dh_reqroot:	dw 0
   191                                  at dh_reqovl
   192 0000003C 0000                    ddl_header.dh_reqovl:	dw 0
   193                                  at dh_elecroot
   194 0000003E 0000                    ddl_header.dh_elecroot:	dw 0
   195                                  at dh_elecovl
   196 00000040 0000                    ddl_header.dh_elecovl:	dw 0
   197                                  at dh_ddlstart
   198 00000042 00000000                ddl_header.dh_ddlstart:	dd 0
   199                                  at dh_preload
   200 00000046 00000000                ddl_header.dh_preload:	dd 0
   201                                  at dh_modstart
   202                                  ddl_header.dh_modstart:
   203 0000004A 00<rep 4h>              at dh_dictstart
   204                                  ddl_header.dh_dictstart:
   205 0000004E 00<rep 4h>              at dh_ohp3
   206                                  ddl_header.dh_ohp3:
   207 00000052 00                      at dh_ohp_flag
   208                                  ddl_header.dh_ohp_flag:
   209 00000053 00                      at dh_oht_flag
   210                                  ddl_header.dh_oht_flag:
   211 00000054 00                      at dh_pad
   212                                  ddl_header.dh_pad:
   213 00000055 00                      at dh_ohp
   214                                  ddl_header.dh_ohp:
   215 00000056 00<rep 2h>              at dh_oht
   216                                  ddl_header.dh_oht:
   217 00000058 00<rep 2h>              at dh_reser3
   218                                  ddl_header.dh_reser3:
   219 0000005A 00<rep 4h>              at dh_reser4
   220                                  ddl_header.dh_reser4:
   221 0000005E 00<rep 4h>              at dh_oxevar
   222                                  ddl_header.dh_oxevar:
   223 00000062 00<rep 20h>             iend
   224                                  
   225                                  MOD_HEADER_STRUC    STRUC
   226 00000000 ????????                    mh_flags    DD  ?       ; module flags
   227                                                              ; bit 0==main module flag
   228                                                              ; bit 1==required root module flag
   229                                                              ; bit 2==required overlay module flag
   230                                                              ; bit 3==elective root module flag
   231                                                              ; bit 4==elective overlay module flag
   232                                                              ; bit 6==pre-load module
   233                                                              ; bit 7==contains communal variables (COMDEFs)
   234 00000004 ????                        mh_id       DW  ?       ; module identifier
   235 00000006 ????                        mh_segcount DW  ?       ; count of segments in module
   236 00000008 ????                        mh_grpcount DW  ?       ; count of groups in module
   237 0000000A ????                        mh_pubcount DW  ?       ; count of publics
   238 0000000C ????                        mh_comcount DW  ?       ; count of communals
   239 0000000E ????                        mh_extcount DW  ?       ; count of externals
   240 00000010 ????????                    mh_lnames   DD  ?       ; file position of start of lnames name block
   241 00000014 ????????                    mh_segdef   DD  ?       ; file position of start of segment entries
   242 00000018 ????????                    mh_grpdef   DD  ?       ; file position of start of group entries
   243 0000001C ????????                    mh_symbols  DD  ?       ; file position of start of symbols (pub/ext/comdef) name block
   244 00000020 ????????                    mh_pubdef   DD  ?       ; file position of start of pubdef entries
   245 00000024 ????????                    mh_comdef   DD  ?       ; file position of start of comdef entries
   246 00000028 ????????                    mh_extdef   DD  ?       ; file position of start of extdef entries
   247 0000002C ????????                    mh_binary   DD  ?       ; file position of start of binary data
   248 00000030 ??????????????              mh_startup  DB  7 DUP (?)   ; start address if main module in fixup notation
   249 00000037 ??                          mh_pad      DB  ?       ; pad to keep at dword boundary
   250 00000038 ????????                    mh_binfpos  DD  ?       ; file position of each binary entry file position table
   251 0000003C ????????                    mh_reser2   DD  ?       ; reserved for future
   252                                  MOD_HEADER_STRUC    ENDS
   253                                  
   254                                  mod_header:
   255                                  istruc MOD_HEADER_STRUC
   256                                  at mh_flags
   257 00000082 00000000                mod_header.mh_flags:	dd 0
   258                                  at mh_id
   259 00000086 0000                    mod_header.mh_id:	dw 0
   260                                  at mh_segcount
   261 00000088 0000                    mod_header.mh_segcount:	dw 0
   262                                  at mh_grpcount
   263 0000008A 0000                    mod_header.mh_grpcount:	dw 0
   264                                  at mh_pubcount
   265 0000008C 0000                    mod_header.mh_pubcount:	dw 0
   266                                  at mh_comcount
   267 0000008E 0000                    mod_header.mh_comcount:	dw 0
   268                                  at mh_extcount
   269 00000090 0000                    mod_header.mh_extcount:	dw 0
   270                                  at mh_lnames
   271 00000092 00000000                mod_header.mh_lnames:	dd 0
   272                                  at mh_segdef
   273 00000096 00000000                mod_header.mh_segdef:	dd 0
   274                                  at mh_grpdef
   275 0000009A 00000000                mod_header.mh_grpdef:	dd 0
   276                                  at mh_symbols
   277 0000009E 00000000                mod_header.mh_symbols:	dd 0
   278                                  at mh_pubdef
   279 000000A2 00000000                mod_header.mh_pubdef:	dd 0
   280                                  at mh_comdef
   281 000000A6 00000000                mod_header.mh_comdef:	dd 0
   282                                  at mh_extdef
   283 000000AA 00000000                mod_header.mh_extdef:	dd 0
   284                                  at mh_binary
   285 000000AE 00000000                mod_header.mh_binary:	dd 0
   286                                  at mh_startup
   287 000000B2 00                      mod_header.mh_startup:	db 0
   288 000000B3 00<rep 6h>              at mh_pad
   289 000000B9 00                      mod_header.mh_pad:	db 0
   290                                  at mh_binfpos
   291 000000BA 00000000                mod_header.mh_binfpos:	dd 0
   292                                  at mh_reser2
   293 000000BE 00000000                mod_header.mh_reser2:	dd 0
   294                                  iend
   295                                  
   296                                  BIN_HEADER_STRUC    STRUC
   297 00000000 ????????                    bhs_flags   DD  ?       ; flags
   298                                                              ; bit 0==overlay class flag
   299 00000004 ????                        bhs_segind  DW  ?       ; segment index
   300 00000006 ????                        bhs_length  DW  ?       ; length of segment binary data (not necessarily segment length)
   301 00000008 ????????                    bhs_fixptr  DD  ?       ; file position of start of fixups for segment (0 if none)
   302 0000000C ????????                    bhs_nextptr DD  ?       ; file position of next binary block (0 if last)
   303 00000010 ????                        bhs_offset  DW  ?       ; start offset within segment
   304 00000012 ????                        bhs_truelen DW  ?       ; true length of segment
   305                                  BIN_HEADER_STRUC    ENDS
   306                                  
   307                                  bin_header:
   308                                  istruc BIN_HEADER_STRUC
   309                                  at bhs_flags
   310 000000C2 00000000                bin_header.bhs_flags:	dd 0
   311                                  at bhs_segind
   312 000000C6 0000                    bin_header.bhs_segind:	dw 0
   313                                  at bhs_length
   314 000000C8 0000                    bin_header.bhs_length:	dw 0
   315                                  at bhs_fixptr
   316 000000CA 00000000                bin_header.bhs_fixptr:	dd 0
   317                                  at bhs_nextptr
   318 000000CE 00000000                bin_header.bhs_nextptr:	dd 0
   319                                  at bhs_offset
   320 000000D2 0000                    bin_header.bhs_offset:	dw 0
   321                                  at bhs_truelen
   322                                  bin_header.bhs_truelen:
   323 000000D4 00<rep 2h>              iend
   324                                  
   325                                  FIXUP_HEADER_STRUC  STRUC
   326 00000000 ????                        fhs_lowcount    DW  ?   ; count of low-order byte fixups
   327 00000002 ????????                    fhs_lowinfo     DD  ?   ; file position of low-order byte fixup info entries
   328 00000006 ????????                    fhs_lowloc      DD  ?   ; file position of low-order byte fixup locations
   329 0000000A ????                        fhs_nearcount   DW  ?   ; count of near fixups
   330 0000000C ????????                    fhs_nearinfo    DD  ?   ; file position of near fixup information entries
   331 00000010 ????????                    fhs_nearloc     DD  ?   ; file position of near fixup locations
   332 00000014 ????                        fhs_farcount    DW  ?   ; count of far fixups
   333 00000016 ????????                    fhs_farinfo     DD  ?   ; file position of far fixup information entries
   334 0000001A ????????                    fhs_farloc      DD  ?   ; file position of far fixup locations
   335                                  FIXUP_HEADER_STRUC  ENDS
   336                                  
   337                                  .DATA?
   338                                  
   339                                  ; uninitialized local variables
   340                                  
   341                                  ; byte values
   342                                  EVEN
   343 00000000 ??                      pubcom_flag DB  ?           ; nonzero if parsing communal entries
   344 00000001 ??                      EVEN
   345                                  ;***block_flag  DB  ?           ; ==2 if parsing public block, ==1 if parsing communal block
   346                                  EVEN
   347 00000002 ??                      save_fixup  DB  ?           ; nonzero if save fixup to disk
   348 00000003 ??                      EVEN
   349 00000004 ??                      frame_method    DB  ?       ; fixup frame method
   350 00000005 ??                      EVEN
   351 00000006 ??                      target_method   DB  ?       ; fixup target method
   352 00000007 ??                      EVEN
   353 00000008 ??                      fixdat  DB  ?               ; fixdat byte
   354 00000009 ??                      EVEN
   355 0000000A ??                      is_loc  DB  ?               ; nonzero if parsing LIDATA fixups for location, zero if for info
   356 0000000B ??                      EVEN
   357 0000000C ??                      pass_count  DB  ?           ; count of fixup parsing pass
   358                                  
   359                                  ; word values
   360 0000000D ??                      EVEN
   361 0000000E ????                    frame_datum DW  ?           ; fixup frame datum/index
   362 00000010 ????                    target_datum    DW  ?       ; fixup target datum/index
   363 00000012 ????                    data_rec_off    DW  ?       ; fixup data record offset
   364 00000014 ????                    iter_data_off   DW  ?       ; iterated data offset
   365 00000016 ????                    sort_buff_bound DW  ?       ; sort buffer upper boundary
   366 00000018 ????                    proc_segment    DW  ?       ; number of segment with binary data being processed
   367 0000001A ????                    lobyte_count    DW  ?       ; count of low-order fixups
   368 0000001C ????                    near_count      DW  ?       ; count of near (offset) fixups
   369 0000001E ????                    far_count       DW  ?       ; count of far (segment) fixups
   370 00000020 ????                    binary_fpos DW  ?           ; segment of binary file position table
   371 00000022 ????                    curr_segdefent_ptr  DW  ?   ; pointer to current segdef entry being processed for binary/fixups
   372 00000024 ????                    seg_truelen     DW  ?       ; true length of segment saved to binary header
   373                                  
   374                                  ;***repeat_count    DW  ?       ; LIDATA iterated data block repeat count field
   375                                  ;***block_count     DW  ?       ; LIDATA iterated data block block count field
   376                                  
   377                                  ; doubleword values
   378 00000026 ????????                ddl_filesize    DD  ?       ; current DDL size
   379 0000002A ????????                module_start    DD  ?       ; file position of start of module (all file positions within relative to it)
   380 0000002E ????????                currbin_start   DD  ?       ; file position of current binary block
   381 00000032 ????????                binfpos_table   DD  ?       ; file position of binary file position table
   382                                  
   383                                  ; byte strings
   384 00000036 <res Dh>                bare_exe_name   DB  13 DUP (?)  ; EXE name without path
   385                                  
   386                                  ;*****************************
   387                                  ;* Constant data             *
   388                                  ;*****************************
   389                                  
   390                                  .CONST
   391                                  
   392                                  EVEN
   393 00000000 44444C4D47522E4441-     dat_default DB  'DDLMGR.DAT',0  ; default DDL manager data file name
   393 00000009 5400               
   394 0000000B 4D5A8B010200000020-     loader_hdr  DB  4Dh,5Ah,8Bh,1,2,0,0,0,20h,00,00,00,0FFh,0FFh
   394 00000014 000000FFFF         
   395 00000019 EB16                    loader_code DB  0EBh,16h
   396 0000001B 4E4F4E414D452E4444-     lc_ddlname  DB  'NONAME.DDL',0,0,0
   396 00000024 4C000000           
   397 00000028 44444C504154483D00      lc_ddlpath  DB  'DDLPATH=',0
   398 00000031 1E0E1FBA0200B800                    DB  1Eh,0Eh,1Fh,0BAh,2,0,0B8h,0
   399 00000039 3DCD217203E90B013D-                 DB  3Dh,0CDh,21h,72h,3,0E9h,0Bh,1,3Dh,2,0,74h,0Ah,3Dh,3,0
   399 00000042 0200740A3D0300     
   400 00000049 74053D0500756926A1-                 DB  74h,5,3Dh,5,0,75h,69h,26h,0A1h,2,0,2Dh,8,0,8Eh,0D8h
   400 00000052 02002D08008ED8     
   401 00000059 0626A12C008EC0B430-                 DB  06h,26h,0A1h,2Ch,0,8Eh,0C0h,0B4h,30h,0CDh,21h,3Ch,2,76h,56h,6
   401 00000062 CD213C02765606     
   402 00000069 1E071F33F6AC0A0475-                 DB  1Eh,7,1Fh,33h,0F6h,0ACh,0Ah,4,75h,0FBh,83h,0C6h,3,8Bh,0FEh,0ACh
   402 00000072 FB83C6038BFEAC     
   403 00000079 0AC074083C5C75F78B-                 DB  0Ah,0C0h,74h,8,3Ch,5Ch,75h,0F7h,8Bh,0DEh,0EBh,0F3h,8Bh,0F7h,33h,0FFh
   403 00000082 DEEBF38BF733FF     
   404 00000089 A43BF375FB8CDB0E1F-                 DB  0A4h,3Bh,0F3h,75h,0FBh,8Ch,0DBh,0Eh,1Fh,0BEh,2,0,0A4h,80h,7Ch,0FFh
   404 00000092 BE0200A4807CFF     
   405 00000099 0075F9061F33D2B800-                 DB  0,75h,0F9h,6,1Fh,33h,0D2h,0B8h,0,43h,0CDh,21h,72h,3,0E9h,9Ah
   405 000000A2 43CD217203E99A     
   406 000000A9 003D0200740D3D0300-                 DB  0,3Dh,2,0,74h,0Dh,3Dh,3,0,74h,8,3Dh,5,0,74h,3
   406 000000B2 74083D05007403     
   407 000000B9 E9E4008EC3BB0F0033-                 DB  0E9h,0E4h,0,8Eh,0C3h,0BBh,0Fh,0,33h,0F6h,33h,0FFh,26h,8Ah,4,46h
   407 000000C2 F633FF268A0446     
   408 000000C9 2E3A01740A260A0475-                 DB  2Eh,3Ah,1,74h,0Ah,26h,0Ah,4,75h,0F0h,0B8h,2,0,0EBh,0E1h,0Bh
   408 000000D2 F0B80200EBE10B     
   409 000000D9 FF750C83FE01740726-                 DB  0FFh,75h,0Ch,83h,0FEh,1,74h,7,26h,80h,7Ch,0FEh,0,75h,0DBh,47h
   409 000000E2 807CFE0075DB47     
   410 000000E9 83FF0872D733FF268A-                 DB  83h,0FFh,8,72h,0D7h,33h,0FFh,26h,8Ah,4,3Ch,3Bh,74h,0Ah,3Ch,20h
   410 000000F2 043C3B740A3C20     
   411 000000F9 720688054746EBEF56-                 DB  72h,6,88h,5,47h,46h,0EBh,0EFh,56h,0BEh,2,0,80h,7Dh,0FFh,5Ch
   411 00000102 BE0200807DFF5C     
   412 00000109 7404C6055C472E8A04-                 DB  74h,4,0C6h,5,5Ch,47h,2Eh,8Ah,4,88h,5,0Ah,0C0h,74h,4,46h
   412 00000112 88050AC0740446     
   413 00000119 47EBF3B80043CD2173-                 DB  47h,0EBh,0F3h,0B8h,0,43h,0CDh,21h,73h,20h,3Dh,2,0,74h,0Ah,3Dh
   413 00000122 203D0200740A3D     
   414 00000129 030074053D05007587-                 DB  03h,0,74h,5,3Dh,5,0,75h,87h,5Eh,32h,0C0h,26h,38h,4,74h
   414 00000132 5E32C026380474     
   415 00000139 9926384401749346EB-                 DB  99h,26h,38h,44h,1,74h,93h,46h,0EBh,0ABh,58h,0B8h,0,3Dh,0CDh,21h
   415 00000142 AB58B8003DCD21     
   416 00000149 7255078BD826A10200-                 DB  72h,55h,7,8Bh,0D8h,26h,0A1h,2,0,2Dh,1,0,8Eh,0D8h,33h,0D2h
   416 00000152 2D01008ED833D2     
   417 00000159 B91000B43FCD21723E-                 DB  0B9h,10h,0,0B4h,3Fh,0CDh,21h,72h,3Eh,8Bh,16h,0Ch,0,8Bh,0Eh,0Eh
   417 00000162 8B160C008B0E0E     
   418 00000169 00B80042CD21722F8B-                 DB  0,0B8h,0,42h,0CDh,21h,72h,2Fh,8Bh,0Eh,0Ah,0,8Bh,0D1h,83h,0C2h
   418 00000172 0E0A008BD183C2     
   419 00000179 0FD1EAD1EAD1EAD1EA-                 DB  0Fh,0D1h,0EAh,0D1h,0EAh,0D1h,0EAh,0D1h,0EAh,26h,0A1h,2,0,2Bh,0C2h,8Eh
   419 00000182 26A102002BC28E     
   420 00000189 D833D2B43FCD21720E-                 DB  0D8h,33h,0D2h,0B4h,3Fh,0CDh,21h,72h,0Eh,90h,90h,90h,90h,90h,90h,8Ch
   420 00000192 9090909090908C     
   421 00000199 D81F5033C050CBB44C-                 DB  0D8h,1Fh,50h,33h,0C0h,50h,0CBh,0B4h,4Ch,0CDh,21h
   421 000001A2 CD21               
   422                                  
   423                                  ;*****************************
   424                                  ;* Code begins               *
   425                                  ;*****************************
   426                                  
   427                                  .CODE
   428                                  
   429                                  ;*****************************
   430                                  ;* External declarations     *
   431                                  ;*****************************
   432                                  
   433                                  ; procedures
   434                                  EXTRN   dos_error:NEAR,restore_ems_map:NEAR,alloc_memory:NEAR
   435                                  EXTRN   link_error:NEAR,load_file:NEAR,save_thread:NEAR
   436                                  EXTRN   check_libobj_path:NEAR,write_ddl_dict:NEAR
   437                                  EXTRN	file_not_found:NEAR
   438                                  
   439                                  ;*****************************
   440                                  ;* CREATE_DDL                *
   441                                  ;*****************************
   442                                  
   443                                  ; create the DDL file, write header info, write dependency list
   444                                  ; destroys ax,bx,cx,dx,di
   445                                  
   446                                  create_ddl  PROC
   447 00000000 BA[0000]                    mov dx,OFFSET exe_name wrt DGROUP   ; DS:DX -> ASCIIZ file specification
   448 00000003 B43C                        mov ah,3ch              ; create/truncate file
   449 00000005 31C9                        xor cx,cx               ; normal file attribute
   450 00000007 CD21                        int 21h
   451 00000009 7231                        jc  cd_error            ; error occurred
   452                                  
   453                                  ; write the DDL header info
   454 0000000B A3[0000]                    mov [exe_handle],ax       ; keep file handle of DDL file
   455 0000000E 89C3                        mov bx,ax
   456 00000010 B88000                      mov ax,DDL_HEADER_SIZE  ; get size of DDL header
   457 00000013 A3[1600]                    mov [ddl_header.dh_hdrsize],ax    ; save it
   458 00000016 89C1                        mov cx,ax               ; bytes to write
   459 00000018 BA[0E00]                    mov dx,OFFSET ddl_header wrt DGROUP ; ds:dx -> write buffer area
   460 0000001B B440                        mov ah,40h              ; write to file
   461 0000001D CD21                        int 21h
   462 0000001F 721B                        jc  cd_error            ; error writing to file
   463 00000021 39C8                    	cmp ax, cx
   464 00000023 B82700                  	mov ax, 27h			; insufficient disk space error
   465 00000026 7514                    	jne cd_error
   466                                  
   467 00000028 E83E00                      call    write_ddl_mgr       ; read in DDL manager data file, write it
   468 0000002B E89C00                      call    update_ddl_size ; update the DDL file size
   469                                  
   470                                  ; save start of DDL dependency list
   471 0000002E A3[4200]                    mov WORD PTR [ddl_header.dh_ddlstart],ax
   472 00000031 8916[4400]                  mov WORD PTR [ddl_header.dh_ddlstart+2],dx
   473                                  
   474 00000035 E80700                      call    write_ddl_depend    ; write dependency list
   475 00000038 E88F00                      call    update_ddl_size ; update the DDL file size
   476                                  
   477 0000003B C3                          ret
   478                                  
   479                                  cd_error:
   480 0000003C E9(0000)                    jmp NEAR PTR dos_error  ; error opening file
   481                                  
   482                                  create_ddl  ENDP
   483                                  
   484                                  ;*****************************
   485                                  ;* WRITE_DDL_DEPEND          *
   486                                  ;*****************************
   487                                  
   488                                  ; write DDL dependency list
   489                                  ; upon entry bx==DDL file handle
   490                                  ; destroys ax,cx,dx,es
   491                                  
   492                                  write_ddl_depend    PROC
   493                                  
   494                                  ; write as many names as are on dependency list, every 80 bytes
   495 0000003F A1[0000]                    mov ax,[first_udlent_ptr] ; init to first name on list, if any
   496 00000042 BA0200                      mov dx,2                ; point past pointer first two bytes
   497 00000045 B95000                      mov cx,80              	; write 80 bytes
   498                                  
   499                                  wdd_loop:
   500 00000048 09C0                        or  ax,ax               ; see if any more names to write
   501 0000004A 7414                        je  wdd_listdone        ; no
   502 0000004C 8ED8                        mov ds,ax
   503 0000004E B440                        mov ah,40h              ; write to file
   504 00000050 CD21                        int 21h
   505 00000052 7212                        jc  wdd_error           ; error writing to file
   506 00000054 39C8                    	cmp ax, cx
   507 00000056 B82700                  	mov ax, 27h			; insufficient disk space error
   508 00000059 750B                    	jne wdd_error
   509                                  
   510 0000005B A10000                      mov ax,[0]           ; get pointer to next name
   511 0000005E EBE8                        jmp SHORT wdd_loop      ; write it
   512                                  
   513                                  wdd_listdone:
   514 00000060 B8[ssss]                    mov ax,DGROUP
   515 00000063 8ED8                        mov ds,ax               ; restore ds -> warplink data
   516                                  
   517                                  wdd_ret:
   518 00000065 C3                          ret
   519                                  
   520                                  wdd_error:
   521 00000066 E9(0000)                    jmp NEAR PTR dos_error  ; error opening file
   522                                  
   523                                  write_ddl_depend    ENDP
   524                                  
   525                                  ;*****************************
   526                                  ;* WRITE_DDL_MGR             *
   527                                  ;*****************************
   528                                  
   529                                  ; read DDL loader from manager data file, write to DDL file
   530                                  ; upon entry bx==DDL file handle
   531                                  ; destroys ax,cx,dx
   532                                  
   533                                  write_ddl_mgr   PROC
   534 00000069 E85E00                      call    update_ddl_size ; update the DDL file size
   535                                  
   536                                  ; update manager file position pointer (place at end of file)
   537 0000006C A3[1A00]                    mov WORD PTR [ddl_header.dh_loadstart],ax
   538 0000006F 8916[1C00]                  mov WORD PTR [ddl_header.dh_loadstart+2],dx
   539                                  
   540 00000073 53                          push    bx              ; save DDL file handle
   541 00000074 BF[0000]                    mov di,OFFSET ddldat_filename wrt DGROUP
   542 00000077 30C0                        xor al,al
   543 00000079 3805                        cmp [di],al             ; see if DDL manager data file exists
   544 0000007B 7503                        jne wdg_2               ; yes
   545 0000007D BF[0000]                    mov di,OFFSET dat_default wrt DGROUP    ; no, use default manager file name
   546                                  
   547                                  wdg_2:
   548 00000080 89FA                        mov dx,di
   549 00000082 B8003D                      mov ax,3d00h            ; open file with read access
   550 00000085 CD21                        int 21h
   551 00000087 730B                        jnc wdg_3               ; no errors
   552 00000089 E8(0000)                	call	file_not_found	; check for file not found error
   553                                  
   554                                  ; DDLMGR file not found in current directory, search OBJ environment string
   555                                  wdg_find_mgr:
   556 0000008C BB[0000]                    mov bx,OFFSET objtext wrt DGROUP    ; bx holds target string address for compares
   557 0000008F E8(0000)                    call    check_libobj_path   ; check e-var, error if not found, return di-> path+name
   558 00000092 EBEC                        jmp SHORT wdg_2
   559                                  
   560                                  wdg_3:
   561 00000094 89C3                        mov bx,ax               ; save file handle
   562 00000096 31D2                        xor dx,dx
   563 00000098 B90080                      mov cx,32768            ; DDL manager size always less than 32K
   564 0000009B 1E                          push    ds
   565 0000009C 8E1E[0000]                  mov ds,[buffer_base]      ; ds:dx -> buffer area to load into
   566 000000A0 B43F                        mov ah,3fh              ; read from file (no short read error)
   567 000000A2 CD21                        int 21h
   568 000000A4 72C0                        jc  wdd_error           ; error occurred
   569 000000A6 1F                          pop ds
   570 000000A7 A3[1800]                    mov [ddl_header.dh_loadsize],ax   ; save count of bytes read
   571 000000AA 89C1                        mov cx,ax
   572                                  
   573 000000AC B43E                        mov ah,3eh              ; close DDL manager file
   574 000000AE CD21                        int 21h
   575 000000B0 72B4                        jc  wdd_error           ; error occurred
   576                                  
   577 000000B2 5B                          pop bx                  ; restore DDL file handle
   578 000000B3 1E                          push    ds
   579 000000B4 8E1E[0000]                  mov ds,[buffer_base]      ; ds:dx -> buffer area to read from
   580 000000B8 B440                        mov ah,40h              ; write to file
   581 000000BA CD21                        int 21h
   582 000000BC 72A8                        jc  wdd_error           ; error occurred
   583 000000BE 39C8                    	cmp ax, cx
   584 000000C0 B82700                  	mov ax, 27h			; insufficient disk space error
   585 000000C3 75A1                    	jne wdd_error
   586 000000C5 1F                          pop ds
   587 000000C6 E84611                      call    ddl_pad         ; pad out to even paragraph boundary
   588                                  
   589 000000C9 C3                          ret
   590                                  write_ddl_mgr   ENDP
   591                                  
   592                                  ;*****************************
   593                                  ;* UPDATE_DDL_SIZE           *
   594                                  ;*****************************
   595                                  
   596                                  ; seek to end of file, update DDL size variable
   597                                  ; destroys ax,bx,cx,dx
   598                                  ; returns bx==DDL file handle, filesize in dx:ax
   599                                  
   600                                  update_ddl_size PROC
   601 000000CA 8B1E[0000]                  mov bx,[exe_handle]
   602 000000CE 31C9                        xor cx,cx
   603 000000D0 89CA                        mov dx,cx
   604 000000D2 B80242                      mov ax,4202h            ; move file pointer from end of file
   605 000000D5 CD21                        int 21h
   606 000000D7 A3[2600]                    mov WORD PTR [ddl_filesize],ax    ; save low word of DDL file size
   607 000000DA 8916[2800]                  mov WORD PTR [ddl_filesize+2],dx  ; save high word
   608 000000DE C3                          ret
   609                                  update_ddl_size ENDP
   610                                  
   611                                  ;*****************************
   612                                  ;* PROC_DDL                  *
   613                                  ;*****************************
   614                                  
   615                                  ; main DDL driver to process raw DDL file into final DDL file
   616                                  ; destroys ax,bx,cx,dx,si,di,es
   617                                  
   618                                  proc_ddl    PROC
   619 000000DF E88C01                      call    write_ddl_modpos    ; write DDL module file position entries at end of DDL file
   620                                  
   621 000000E2 A1[0000]                    mov ax,[module_count]
   622 000000E5 3D0004                      cmp ax,1024             ; no more than 1024 modules/DDL file
   623 000000E8 771B                        ja  pd_moderr           ; too many modules
   624 000000EA A3[3600]                    mov [ddl_header.dh_modcount],ax   ; save count of modules in DDL file
   625                                  
   626 000000ED E8(0000)                    call    write_ddl_dict  ; write DDL dictionary
   627 000000F0 8B1E[0000]                  mov bx,[exe_handle]
   628 000000F4 31C9                        xor cx,cx
   629 000000F6 89CA                        mov dx,cx
   630 000000F8 B80042                      mov ax,4200h            ; move file pointer from start of file
   631 000000FB CD21                        int 21h                 ; rewind file
   632 000000FD E8(0000)                    call    restore_ems_map
   633 00000100 7309                        jnc pd_2                ; no error
   634 00000102 E9(0000)                    jmp NEAR PTR dos_error
   635                                  
   636                                  pd_moderr:
   637 00000105 B84900                      mov ax,DDLMOD_COUNT_ERR ; error value
   638 00000108 E9(0000)                    jmp NEAR PTR link_error ; transfer control to error handler
   639                                  
   640                                  pd_2:
   641 0000010B A0[0000]                    mov al,[ddl_depend_count]	; get ddl dependency count
   642 0000010E 30E4                        xor ah,ah               ; one byte value for now
   643 00000110 A3[3800]                    mov [ddl_header.dh_ddlcount],ax
   644                                  
   645                                  ; merge in flag bits
   646 00000113 30E4                        xor ah,ah
   647 00000115 A0[0000]                    mov al,[is_ddl]           ; see if creating DDL or using one
   648 00000118 08C0                        or  al,al
   649 0000011A 7503                        jne pd_useddl           ; creating DDL
   650 0000011C 80CC01                      or  ah,1                ; set main module flag
   651                                  
   652                                  pd_useddl:
   653                                  
   654 0000011F A0[0000]                    mov al,[is_dosseg]        ; see if DOSSEG flag set
   655 00000122 08C0                        or  al,al
   656 00000124 7403                        je  pd_nodosseg         ; no
   657 00000126 80CC20                      or  ah,20h              ; set DOSSEG flag
   658                                  
   659                                  pd_nodosseg:
   660 00000129 88E0                        mov al,ah
   661 0000012B A2[1E00]                    mov BYTE PTR [ddl_header.dh_flags],al ; save flags
   662                                  
   663                                  ; save pertinent linker settings
   664 0000012E A1[0000]                    mov ax,WORD PTR [ovl_pool]    ; /op setting
   665 00000131 A3[2200]                    mov WORD PTR [ddl_header.dh_op],ax
   666 00000134 A1[0200]                    mov ax,WORD PTR [ovl_pool+2]
   667 00000137 A3[2400]                    mov WORD PTR [ddl_header.dh_op+2],ax
   668 0000013A A1[0000]                    mov ax,[stack_value]      ; /st setting
   669 0000013D A3[2600]                    mov [ddl_header.dh_st],ax
   670 00000140 A1[0000]                    mov ax,[maxpar_value]     ; /as setting
   671 00000143 A3[2800]                    mov [ddl_header.dh_as],ax
   672 00000146 A1[0000]                    mov ax,[ovl_stack]        ; /os setting
   673 00000149 A3[2A00]                    mov [ddl_header.dh_os],ax
   674 0000014C A1[0000]                    mov ax,[ovl_max_load]     ; /ol setting
   675 0000014F A3[2C00]                    mov [ddl_header.dh_ol],ax
   676 00000152 A0[0000]                    mov al,[ovl_mem_alloc]    ; /op +- setting
   677 00000155 A2[2E00]                    mov [ddl_header.dh_mem],al
   678 00000158 A0[0000]                    mov al,[is_ems_ovlpool]   ; /ox setting
   679 0000015B A2[3000]                    mov [ddl_header.dh_ox],al
   680 0000015E A0[0000]                    mov al,[is_reload]        ; /r setting
   681 00000161 A2[3100]                    mov [ddl_header.dh_r],al
   682 00000164 A0[0000]                    mov al,[is_clarion]       ; /cla setting
   683 00000167 A2[3200]                    mov [ddl_header.dh_cla],al
   684 0000016A A0[0000]                    mov al,[is_min_pool]      ; /op:m setting
   685 0000016D A2[2F00]                    mov [ddl_header.dh_minop],al
   686                                  
   687 00000170 A0[0000]                	mov	al,[is_umb]
   688 00000173 A2[3300]                	mov	[ddl_header.dh_ou],al	; /ou setting
   689 00000176 A0[0000]                	mov	al,[ems3_flag]
   690 00000179 A2[5200]                	mov	[ddl_header.dh_ohp3],al	; /ohp3 setting
   691 0000017C A1[0000]                	mov	ax,[ovl_ohp_size]
   692 0000017F A3[5600]                	mov	[ddl_header.dh_ohp],ax	; /ohp size
   693 00000182 A1[0000]                	mov	ax,[ovl_oht_size]
   694 00000185 A3[5800]                	mov	[ddl_header.dh_oht],ax	; /oht size
   695 00000188 A0[0000]                	mov	al,[ovl_ohp_alloc]
   696 0000018B A2[5300]                	mov	[ddl_header.dh_ohp_flag],al	; /ohp alloc flag
   697 0000018E A0[0000]                	mov	al,[ovl_oht_alloc]
   698 00000191 A2[5400]                	mov	[ddl_header.dh_oht_flag],al	; /oht alloc flag
   699 00000194 31C0                    	xor	ax,ax
   700 00000196 3806[0000]              	cmp	[is_ohp],al			; see if ohp set
   701 0000019A 7503                    	jne	pd_3				; yes
   702 0000019C A3[5600]                	mov	[ddl_header.dh_ohp],ax	; zero it out
   703                                  
   704                                  pd_3:
   705 0000019F 3806[0000]              	cmp	[is_oht],al			; see if oht set
   706 000001A3 7503                    	jne	pd_4				; yes
   707 000001A5 A3[5800]                	mov	[ddl_header.dh_oht],ax	; zero it out
   708                                  
   709                                  pd_4:
   710 000001A8 BE[0000]                    mov si,OFFSET ovl_ox_evar wrt DGROUP    ; /ox environment variable
   711 000001AB BF[6200]                    mov di,OFFSET ddl_header.dh_oxevar wrt DGROUP
   712 000001AE 1E                      	push	ds
   713 000001AF 1F                      	pop	ds
   714 000001B0 B91000                      mov cx,16               ; e-var storage is 32 bytes
   715 000001B3 F3A5                        rep movsw
   716                                  
   717 000001B5 BA[0E00]                    mov dx,OFFSET ddl_header wrt DGROUP ; ds:dx -> write buffer area
   718 000001B8 B98000                      mov cx,DDL_HEADER_SIZE  ; size of DDL header
   719 000001BB B440                        mov ah,40h              ; write to file
   720 000001BD CD21                        int 21h
   721 000001BF E8(0000)                    call    restore_ems_map
   722 000001C2 720F                        jc  pd_error            ; error writing to file
   723 000001C4 39C8                    	cmp ax, cx
   724 000001C6 B82700                  	mov ax, 27h			; insufficient disk space error
   725 000001C9 7508                    	jne pd_error
   726                                  
   727 000001CB B43E                        mov ah,3eh              ; close DDL file
   728 000001CD CD21                        int 21h
   729                                  
   730 000001CF E80400                      call    write_ddl_loader    ; create loader exe file
   731 000001D2 C3                          ret
   732                                  
   733                                  pd_error:
   734 000001D3 E9(0000)                    jmp NEAR PTR dos_error  ; error opening file
   735                                  
   736                                  proc_ddl    ENDP
   737                                  
   738                                  ;*****************************
   739                                  ;* WRITE_DDL_LOADER          *
   740                                  ;*****************************
   741                                  
   742                                  ; create the loader exe file
   743                                  ; destroys ax,bx,cx,dx,di,si
   744                                  
   745                                  write_ddl_loader    PROC
   746 000001D6 A1[3A00]                    mov ax,[ddl_header.dh_reqroot]    ; make EXE loader only if required modules
   747 000001D9 0B06[3C00]                  or  ax,[ddl_header.dh_reqovl]
   748 000001DD 7501                        jne wdl_2
   749 000001DF C3                          ret                     ; no required modules, make no EXE loader
   750                                  
   751                                  ; find '.' of extension in exe_name, add EXE after
   752                                  wdl_2:
   753 000001E0 BE[0000]                    mov si,OFFSET exe_name wrt DGROUP
   754 000001E3 89F2                        mov dx,si               ; save dx -> name for later file open
   755                                  
   756                                  wdl_loop:
   757 000001E5 AC                          lodsb                   ; get char of exe_name
   758 000001E6 08C0                        or  al,al               ; see if at null terminator
   759 000001E8 75FB                        jne wdl_loop            ; no
   760                                  
   761 000001EA 4E                          dec si                  ; si -> null terminator
   762 000001EB FD                          std                     ; make searches go backwards
   763                                  
   764                                  wdl_loop2:
   765 000001EC AC                          lodsb
   766 000001ED 3C2E                        cmp al,'.'              ; see if at extension mark
   767 000001EF 75FB                        jne wdl_loop2           ; no
   768                                  
   769 000001F1 89F3                        mov bx,si               ; save -> search position
   770 000001F3 46                          inc si                  ; adjust si so no unchecked chars
   771                                  
   772                                  wdl_loop3:
   773 000001F4 AC                          lodsb                   ; backup char
   774 000001F5 3C5C                        cmp al,'\'              ; see if at pathspec
   775 000001F7 740B                        je  wdl_savename        ; yes, save name
   776 000001F9 3C3A                        cmp al,':'              ; see if drivespec
   777 000001FB 7407                        je  wdl_savename        ; yes, save name
   778 000001FD 81FE[0000]                  cmp si,OFFSET exe_name wrt DGROUP   ; see if backed up to start of name
   779 00000201 73F1                        jae wdl_loop3           ; no
   780 00000203 4E                          dec si                  ; yes, adjust si -> 2 chars before name
   781                                  
   782                                  ; si -> 2 chars before start of name
   783                                  wdl_savename:
   784 00000204 83C602                      add si,2                ; si -> start of name
   785 00000207 FC                          cld                     ; reset string operations to auto-increment
   786 00000208 B90600                      mov cx,6                ; transfer 12 bytes of name (even if not 12 chars long)
   787 0000020B BF[1B00]                    mov di,OFFSET lc_ddlname wrt DGROUP ; di -> destination of name chars
   788                                  
   789                                  wdl_transloop:
   790 0000020E AD                          lodsw                   ; get 2 chars of name to transfer
   791 0000020F 8905                        mov [di],ax             ; transfer it
   792 00000211 47                          inc di
   793 00000212 47                          inc di
   794 00000213 E2F9                        loop    wdl_transloop   ; loop until done
   795                                  
   796 00000215 B045                        mov al,'E'              ; add EXE extension, bx -> char before '.'
   797 00000217 884702                      mov [bx+2],al
   798 0000021A C6470358                    mov BYTE PTR [bx+3],'X'
   799 0000021E 884704                      mov [bx+4],al
   800                                  
   801 00000221 B43C                        mov ah,3ch              ; create/truncate file
   802 00000223 31C9                        xor cx,cx               ; normal file attribute
   803 00000225 CD21                        int 21h
   804 00000227 7242                        jc  wdl_error           ; error occurred
   805                                  
   806 00000229 89C3                        mov bx,ax               ; save file handle in bx
   807 0000022B B90E00                      mov cx,14               ; write nonzero EXE header bytes
   808 0000022E BA[0B00]                    mov dx,OFFSET loader_hdr wrt DGROUP
   809 00000231 B440                        mov ah,40h              ; write to file
   810 00000233 CD21                        int 21h
   811 00000235 7234                        jc  wdl_error           ; error occurred
   812 00000237 39C8                    	cmp ax, cx
   813 00000239 B82700                  	mov ax, 27h			; insufficient disk space error
   814 0000023C 752D                    	jne wdl_error
   815                                  
   816 0000023E B9F201                      mov cx,498              ; write zero EXE header bytes
   817 00000241 BA[0000]                    mov dx,OFFSET zero_table wrt DGROUP
   818 00000244 B440                        mov ah,40h              ; write to file
   819 00000246 CD21                        int 21h
   820 00000248 7221                        jc  wdl_error           ; error occurred
   821 0000024A 39C8                    	cmp ax, cx
   822 0000024C B82700                  	mov ax, 27h			; insufficient disk space error
   823 0000024F 751A                    	jne wdl_error
   824                                  
   825 00000251 B98B01                      mov cx,18bh             ; write loader code
   826 00000254 BA[1900]                    mov dx,OFFSET loader_code wrt DGROUP
   827 00000257 B440                        mov ah,40h              ; write to file
   828 00000259 CD21                        int 21h
   829 0000025B 720E                        jc  wdl_error           ; error occurred
   830 0000025D 39C8                    	cmp ax, cx
   831 0000025F B82700                  	mov ax, 27h			; insufficient disk space error
   832 00000262 7507                    	jne wdl_error
   833                                  
   834 00000264 B43E                        mov ah,3eh              ; close file
   835 00000266 CD21                        int 21h
   836 00000268 7201                        jc  wdl_error           ; error occurred
   837 0000026A C3                          ret
   838                                  
   839                                  wdl_error:
   840 0000026B E9(0000)                    jmp NEAR PTR dos_error  ; error opening file
   841                                  
   842                                  write_ddl_loader    ENDP
   843                                  
   844                                  ;*****************************
   845                                  ;* WRITE_DDL_MODPOS          *
   846                                  ;*****************************
   847                                  
   848                                  ; write DDL module file position entries at end of DDL file
   849                                  ; destroys ax,bx,cx,dx,es
   850                                  
   851                                  write_ddl_modpos    PROC
   852 0000026E E859FE                      call    update_ddl_size ; update the DDL file size
   853                                  
   854                                  ; update module file position pointer (place at end of file)
   855 00000271 A3[4A00]                    mov WORD PTR [ddl_header.dh_modstart],ax
   856 00000274 8916[4C00]                  mov WORD PTR [ddl_header.dh_modstart+2],dx
   857                                  
   858 00000278 A1[0200]                    mov ax,[first_ddl_fpos]   ; init ax to first DLL module position
   859                                  
   860                                  wmp_loop:
   861 0000027B 09C0                        or  ax,ax               ; see if valid block
   862 0000027D 741A                        je  wmp_ret             ; no
   863                                  
   864 0000027F 8ED8                        mov ds,ax               ; ds -> block
   865 00000281 BA0200                      mov dx,2                ; ds:dx -> start of file position entries in block
   866 00000284 B90001                      mov cx,256              ; write 64 dword entries (may not all be used)
   867 00000287 B440                        mov ah,40h              ; write to file (bx already == handle)
   868 00000289 CD21                        int 21h
   869 0000028B 72DE                        jc  wdl_error           ; error writing to file
   870 0000028D 39C8                    	cmp ax, cx
   871 0000028F B82700                  	mov ax, 27h			; insufficient disk space error
   872 00000292 75D7                    	jne wdl_error
   873 00000294 A10000                      mov ax,[0]           ; get pointer to next file block, if any
   874 00000297 EBE2                        jmp SHORT wmp_loop      ; write it if it exists
   875                                  
   876                                  wmp_ret:
   877 00000299 B8[ssss]                    mov ax,DGROUP
   878 0000029C 8ED8                        mov ds,ax               ; restore ds -> warplink data
   879 0000029E C3                          ret
   880                                  write_ddl_modpos    ENDP
   881                                  
   882                                  ;*****************************
   883                                  ;* SAVE_MODULE_TYPE          *
   884                                  ;*****************************
   885                                  
   886                                  ; set appropriate main DDL and module flags
   887                                  ; increment appropriate DDL module type counter
   888                                  ; destroys ax
   889                                  
   890                                  save_module_type    PROC
   891 0000029F 803E[0000]01                cmp byte [udl_proc_pass],1     ; see if pass 1 udl processing
   892 000002A4 7501                        jne smt_okay            ; no
   893 000002A6 C3                          ret                     ; yes, no processing to complete
   894                                  
   895                                  ; module is elective if in library list and libmod_obj_flag variable not set
   896                                  ; AND not processing udl
   897                                  smt_okay:
   898 000002A7 31C0                        xor ax,ax
   899 000002A9 803E[0000]02                cmp byte [udl_proc_pass],2     ; see if second pass of udl
   900 000002AE 7422                        je  smt_required        ; yes, always required module
   901 000002B0 3806[0000]                  cmp [is_inlib],al         ; see if in library
   902 000002B4 741C                        je  smt_required        ; no
   903 000002B6 3806[0000]                  cmp [libmod_obj_flag],al  ; see if library module as object module flag set
   904 000002BA 7516                        jne smt_required        ; yes
   905 000002BC 3806[0000]                  cmp [obj_ovl_flag],al     ; see if in an overlay
   906 000002C0 7508                        jne smt_elecovl         ; yes
   907                                  
   908                                  ; elective, in root
   909 000002C2 FF06[3E00]                  inc word [ddl_header.dh_elecroot]
   910 000002C6 B008                        mov al,8
   911 000002C8 EB1C                        jmp SHORT smt_setflags
   912                                  
   913                                  ; elective, in overlay
   914                                  smt_elecovl:
   915 000002CA FF06[4000]                  inc word [ddl_header.dh_elecovl]
   916 000002CE B010                        mov al,10h
   917 000002D0 EB14                        jmp SHORT smt_setflags
   918                                  
   919                                  ; module is required if in object module list
   920                                  ; OR in library list and libmod_obj_flag is set
   921                                  smt_required:
   922 000002D2 3806[0000]                  cmp [obj_ovl_flag],al     ; see if in an overlay
   923 000002D6 7508                        jne smt_reqovl          ; yes
   924                                  
   925                                  ; required, in root
   926 000002D8 FF06[3A00]                  inc word [ddl_header.dh_reqroot]
   927 000002DC B002                        mov al,2
   928 000002DE EB06                        jmp SHORT smt_setflags
   929                                  
   930                                  ; required, in overlay
   931                                  smt_reqovl:
   932 000002E0 FF06[3C00]                  inc word [ddl_header.dh_reqovl]
   933 000002E4 B004                        mov al,4
   934                                  
   935                                  smt_setflags:
   936 000002E6 0806[1E00]                  or  BYTE PTR [ddl_header.dh_flags],al
   937 000002EA 0806[8200]                  or  BYTE PTR [mod_header.mh_flags],al
   938 000002EE C3                          ret
   939                                  save_module_type    ENDP
   940                                  
   941                                  ;*****************************
   942                                  ;* WRITE_DDL_MODULE          *
   943                                  ;*****************************
   944                                  
   945                                  ; write DDL module info
   946                                  ; destroys ax,bx,dx,di
   947                                  
   948                                  write_ddl_module    PROC
   949 000002EF 803E[0000]01                cmp byte [udl_proc_pass],1     ; see if pass 1 udl processing
   950 000002F4 7501                        jne wdm_okay            ; no
   951 000002F6 C3                          ret                     ; yes, no processing to complete
   952                                  
   953                                  wdm_okay:
   954 000002F7 E87D11                      call    ddl_modend      ; save the MODEND info
   955 000002FA 51                          push    cx              ; save critical register
   956 000002FB 56                          push    si
   957 000002FC 06                          push    es
   958 000002FD E8CAFD                      call    update_ddl_size ; update the DDL file size
   959 00000300 52                          push    dx              ; save high word of file size
   960 00000301 50                          push    ax              ; save low word
   961 00000302 A3[2A00]                    mov WORD PTR [module_start],ax    ; save low word module start
   962 00000305 8916[2C00]                  mov WORD PTR [module_start+2],dx  ; save high word module start
   963                                  
   964                                  ; write dummy module header
   965 00000309 E82A0F                      call    write_ddl_modhead
   966                                  
   967                                  ; write dummy dword entries for each segment (segment count*4 bytes)
   968 0000030C E84D01                      call    write_binary_fpos
   969                                  
   970                                  ; pad to paragraph length with zeros
   971 0000030F E8FD0E                      call    ddl_pad
   972                                  
   973                                  ; write consolidated lnames block
   974 00000312 E8A20B                      call    write_lnames_block
   975                                  
   976                                  ; write segment entries
   977 00000315 E8A001                      call    write_segdef_block
   978                                  
   979                                  ; write group entries
   980 00000318 E85F02                      call    write_grpdef_block
   981                                  
   982                                  ; write consolidated symbol names block
   983 0000031B E8FF0B                      call    write_symbols_block
   984                                  
   985                                  ; write pubdef entries
   986 0000031E E8620C                      call    write_pubdef_block
   987                                  
   988                                  ; write comdef entries
   989 00000321 E81F0E                      call    write_comdef_block
   990                                  
   991                                  ; write extdef entries
   992 00000324 E8440E                      call    write_extdef_block
   993                                  
   994                                  ; translate and write binary/fixup data
   995 00000327 E81603                      call    write_binary_block
   996                                  
   997                                  ; translate modend and keep start address, if any
   998 0000032A E8D802                      call    write_modend_info
   999                                  
  1000                                  ; pad to paragraph length with zeros
  1001 0000032D E8DF0E                      call    ddl_pad
  1002                                  
  1003                                  ; seek back to binary file position table
  1004 00000330 8B16[3200]                  mov dx,WORD PTR [binfpos_table]
  1005 00000334 8B0E[3400]                  mov cx,WORD PTR [binfpos_table+2]
  1006 00000338 B80042                      mov ax,4200h            ; move file pointer, offset from start
  1007 0000033B CD21                        int 21h
  1008                                  
  1009 0000033D 8B0E[0000]                  mov cx,[current_segdef]   ; get count of segments
  1010 00000341 D1E1                        shl cx,1                ; x2
  1011 00000343 D1E1                        shl cx,1                ; x4, count of bytes to write
  1012 00000345 E316                        jcxz    wdm_1           ; no bytes to write
  1013 00000347 31D2                        xor dx,dx
  1014 00000349 8E1E[2000]                  mov ds,[binary_fpos]      ; ds:dx -> write buffer
  1015 0000034D B440                        mov ah,40h              ; write to device
  1016 0000034F CD21                        int 21h
  1017 00000351 7303                        jnc .checkspace
  1018                                  .error:
  1019 00000353 E9(0000)                    jmp NEAR PTR dos_error  ; error writing to file
  1020                                  
  1021                                  .checkspace:
  1022 00000356 39C8                    	cmp ax, cx
  1023 00000358 B82700                  	mov ax, 27h			; insufficient disk space error
  1024 0000035B 75F6                    	jne .error
  1025                                  wdm_1:
  1026 0000035D B8[ssss]                    mov ax,DGROUP
  1027 00000360 8ED8                        mov ds,ax
  1028 00000362 A1[0000]                    mov ax,[mod_alloc_base]   ; get memory allocation base prior to module use
  1029 00000365 A3[0000]                    mov [allocation_base],ax  ; restore pre-module memory allocation base
  1030                                  
  1031                                  ; save module file position
  1032 00000368 A1[0400]                    mov ax,[alloc_ddl_fpos]   ; get segment of DDL module file position table
  1033 0000036B 8EC0                        mov es,ax
  1034 0000036D 09C0                        or  ax,ax               ; see if exists
  1035 0000036F 7516                        jne wdm_2               ; yes
  1036                                  
  1037                                  ; file position table does not exist, build it
  1038 00000371 BB1100                      mov bx,11h              ; each table is 272 bytes (64 dword entries, 1 system paragraph
  1039 00000374 E8(0000)                    call    alloc_memory    ; get memory for block allocation
  1040 00000377 A3[0200]                    mov [first_ddl_fpos],ax   ; set first allocation pointer
  1041                                  
  1042                                  wdm_init:
  1043 0000037A 8EC0                        mov es,ax               ; es -> table
  1044 0000037C A3[0400]                    mov [alloc_ddl_fpos],ax   ; update last allocation pointer
  1045 0000037F 31C0                        xor ax,ax
  1046 00000381 26A30000                    mov [es:0],ax           ; zero out pointer
  1047 00000385 EB18                        jmp SHORT wdm_3         ; ax holds entry within new block
  1048                                  
  1049                                  wdm_2:
  1050 00000387 A1[0000]                    mov ax,[module_id]
  1051 0000038A 83E03F                      and ax,3fh              ; see if need to start a new block
  1052 0000038D 7510                        jne wdm_3               ; no
  1053                                  
  1054                                  ; need to allocate new block, update old block to point to it
  1055 0000038F BB1100                      mov bx,11h
  1056 00000392 E8(0000)                    call    alloc_memory
  1057 00000395 8E06[0400]                  mov es,[alloc_ddl_fpos]   ; es -> old block
  1058 00000399 26A30000                    mov [es:0],ax           ; save pointer to new block
  1059 0000039D EBDB                        jmp SHORT wdm_init      ; transfer to initialization code
  1060                                  
  1061                                  wdm_3:
  1062 0000039F D1E0                        shl ax,1                ; x2
  1063 000003A1 D1E0                        shl ax,1                ; x4, ax holds dword offset
  1064 000003A3 83C002                      add ax,2                ; bump past system pointer word
  1065 000003A6 89C3                        mov bx,ax
  1066 000003A8 5A                          pop dx                  ; get low word of file position off of stack
  1067 000003A9 59                          pop cx                  ; get high word
  1068 000003AA 268917                      mov [es:bx],dx          ; save it to file position table
  1069 000003AD 26894F02                    mov [es:bx+2],cx
  1070 000003B1 A1[0000]                    mov ax,[allocation_base]
  1071 000003B4 A3[0000]                    mov [mod_alloc_base],ax   ; update allocation base to restore to past file position table entries
  1072                                  
  1073 000003B7 A1[0000]                    mov ax,[module_id]
  1074 000003BA 40                          inc ax                  ; update module identifier
  1075 000003BB A3[0000]                    mov [module_id],ax
  1076 000003BE A3[8600]                    mov [mod_header.mh_id],ax ; save to module header info
  1077 000003C1 A1[0000]                    mov ax,[current_segdef]   ; get count of segments
  1078 000003C4 A3[8800]                    mov [mod_header.mh_segcount],ax   ; save it
  1079 000003C7 A1[0000]                    mov ax,[current_grpdef]   ; get count of groups
  1080 000003CA A3[8A00]                    mov [mod_header.mh_grpcount],ax   ; save it
  1081 000003CD A1[0000]                    mov ax,[communal_count]   ; see if any communals
  1082 000003D0 08E0                        or  al,ah               ; al nonzero if any communals
  1083 000003D2 7405                        je  wdm_seek            ; no communals
  1084 000003D4 800E[8200]80                or  BYTE [mod_header.mh_flags],80h    ; flag communals exist
  1085                                  
  1086                                  ; seek back to start of module
  1087                                  wdm_seek:
  1088 000003D9 8B1E[0000]                  mov bx,[exe_handle]
  1089 000003DD B80042                      mov ax,4200h            ; move file pointer, absolute byte offset
  1090 000003E0 CD21                        int 21h
  1091 000003E2 E8510E                      call    write_ddl_modhead   ; write updated module header info
  1092 000003E5 E80400                      call    reinit_variables
  1093                                  
  1094 000003E8 07                          pop es                  ; restore critical register
  1095 000003E9 5E                          pop si
  1096 000003EA 59                          pop cx
  1097 000003EB C3                          ret
  1098                                  write_ddl_module    ENDP
  1099                                  
  1100                                  ;*****************************
  1101                                  ;* REINIT_VARIABLES          *
  1102                                  ;*****************************
  1103                                  
  1104                                  ; reinitialize variables for DDLs
  1105                                  ; destroys ax,cx,di,es
  1106                                  
  1107                                  reinit_variables    PROC
  1108 000003EC 31C0                        xor ax,ax               ; re-init total symbol count
  1109 000003EE A3[8200]                    mov WORD PTR [mod_header.mh_flags],ax ; zero out flags
  1110 000003F1 A3[0000]                    mov [first_pdeclblk_ptr],ax   ; zero out block pointers
  1111 000003F4 A3[0000]                    mov [alloc_pdeclblk_ptr],ax
  1112 000003F7 A3[0000]                    mov [first_cdeclblk_ptr],ax
  1113 000003FA A3[0000]                    mov [alloc_cdeclblk_ptr],ax
  1114 000003FD A3[0000]                    mov [first_pdnameblk_ptr],ax
  1115 00000400 A3[0000]                    mov [alloc_pdnameblk_ptr],ax
  1116 00000403 A3[0000]                    mov [first_lnamesblk_ptr],ax
  1117 00000406 A3[0000]                    mov [alloc_lnamesblk_ptr],ax
  1118 00000409 A3[0000]                    mov [first_segdefblk_ptr],ax
  1119 0000040C A3[0000]                    mov [alloc_segdefblk_ptr],ax
  1120 0000040F A3[0000]                    mov [first_grpblk_ptr],ax
  1121 00000412 A3[0000]                    mov [alloc_grpblk_ptr],ax
  1122 00000415 A3[0000]                    mov [alloc_segpartblk_ptr],ax
  1123 00000418 A3[0000]                    mov [alloc_relblk_ptr],ax
  1124 0000041B A3[0000]                    mov [alloc_libent_ptr],ax
  1125                                  ;***	mov first_local_ptr,ax
  1126 0000041E A3[0000]                    mov [alloc_ovlpubblk_ptr],ax
  1127 00000421 A3[0000]                    mov [first_fixblk_ptr],ax
  1128 00000424 A3[0000]                    mov [alloc_fixblk_ptr],ax
  1129 00000427 A3[0000]                    mov [first_binblk_ptr],ax
  1130 0000042A A3[0000]                    mov [alloc_binblk_ptr],ax
  1131 0000042D A3[0C00]                    mov [modend_ptr],ax
  1132 00000430 A3[0600]                    mov [pubcount],ax
  1133 00000433 A3[0800]                    mov [comcount],ax
  1134 00000436 A3[0A00]                    mov [extcount],ax
  1135                                  
  1136                                  ; zero out hashed pointers
  1137 00000439 1E                          push    ds
  1138 0000043A 07                          pop es                  ; es -> warplink data
  1139 0000043B B90004                      mov cx,HASH_ARRAY_SIZE
  1140 0000043E BF[0000]                    mov di,OFFSET pubdecl_hash wrt DGROUP
  1141 00000441 31C0                        xor ax,ax
  1142 00000443 F3AB                        rep stosw
  1143 00000445 B90004                      mov cx,HASH_ARRAY_SIZE
  1144 00000448 BF[0000]                    mov di,OFFSET segdef_hash wrt DGROUP
  1145 0000044B 31C0                        xor ax,ax
  1146 0000044D F3AB                        rep stosw
  1147 0000044F B90004                      mov cx,HASH_ARRAY_SIZE
  1148 00000452 D1E1                        shl cx,1                ; adjust for dword entries
  1149 00000454 BF[0000]                    mov di,OFFSET lnames_hash wrt DGROUP
  1150 00000457 31C0                        xor ax,ax
  1151 00000459 F3AB                        rep stosw
  1152 0000045B C3                          ret
  1153                                  reinit_variables    ENDP
  1154                                  
  1155                                  ;*****************************
  1156                                  ;* WRITE_BINARY_FPOS         *
  1157                                  ;*****************************
  1158                                  
  1159                                  ; allocate room and write dummy file position for each segment
  1160                                  ; destroys ax,bx,cx,dx
  1161                                  
  1162                                  write_binary_fpos   PROC
  1163 0000045C E86BFC                      call    update_ddl_size ; get start of binary file position block (EOF)
  1164 0000045F A3[3200]                    mov WORD PTR [binfpos_table],ax   ; save pointer to absolute file position
  1165 00000462 8916[3400]                  mov WORD PTR [binfpos_table+2],dx
  1166 00000466 2B06[2A00]                  sub ax,WORD PTR [module_start]    ; adjust relative to start of module
  1167 0000046A 1B16[2C00]                  sbb dx,WORD PTR [module_start+2]  ; adjust high word
  1168 0000046E A3[BA00]                    mov WORD PTR [mod_header.mh_binfpos],ax   ; save pointer to start within module
  1169 00000471 8916[BC00]                  mov WORD PTR [mod_header.mh_binfpos+2],dx
  1170 00000475 8B1E[0000]                  mov bx,[current_segdef]   ; get count of segments
  1171 00000479 89D9                        mov cx,bx
  1172 0000047B 83C303                      add bx,3                ; round up to next para
  1173 0000047E D1EB                        shr bx,1                ; /2
  1174 00000480 D1EB                        shr bx,1                ; /4, dword entries converted to paragraphs
  1175 00000482 E8(0000)                    call    alloc_memory    ; get memory for block allocation
  1176 00000485 A3[2000]                    mov [binary_fpos],ax      ; save memory segment
  1177                                  
  1178 00000488 D1E1                        shl cx,1                ; x2
  1179 0000048A 89CA                        mov dx,cx               ; save words to write
  1180 0000048C D1E1                        shl cx,1                ; x4, count of bytes to write
  1181 0000048E 8B1E[0000]                  mov bx,[exe_handle]
  1182 00000492 8ED8                        mov ds,ax               ; ds -> binary file position storage
  1183 00000494 87D1                        xchg    dx,cx           ; dx== byte count, cx==word count
  1184 00000496 8EC0                        mov es,ax
  1185 00000498 31FF                        xor di,di               ; es:di -> binary file position storage
  1186 0000049A 89F8                        mov ax,di
  1187 0000049C F3AB                        rep stosw               ; zero out each entry
  1188 0000049E 89D1                        mov cx,dx               ; restore byte count to cx
  1189                                  
  1190 000004A0 31D2                        xor dx,dx               ; ds:dx -> binary file position storage
  1191 000004A2 B440                        mov ah,40h              ; write to device
  1192 000004A4 CD21                        int 21h
  1193 000004A6 7303                        jnc .checkspace		; no errors
  1194                                  .error:
  1195 000004A8 E9(0000)                    jmp NEAR PTR dos_error  ; error writing to file
  1196                                  
  1197                                  .checkspace:
  1198 000004AB 39C8                    	cmp ax, cx
  1199 000004AD B82700                  	mov ax, 27h			; insufficient disk space error
  1200 000004B0 75F6                    	jne .error
  1201                                  wbf_ret:
  1202 000004B2 B8[ssss]                    mov ax,DGROUP
  1203 000004B5 8ED8                        mov ds,ax
  1204 000004B7 C3                          ret
  1205                                  write_binary_fpos   ENDP
  1206                                  
  1207                                  ;*****************************
  1208                                  ;* WRITE_SEGDEF_BLOCK        *
  1209                                  ;*****************************
  1210                                  
  1211                                  ; write all segdef blocks into one big segdef block for DDL module
  1212                                  ; destroys ax,bx,cx,dx,si,es
  1213                                  
  1214                                  write_segdef_block  PROC
  1215 000004B8 E80FFC                      call    update_ddl_size ; get start of segdef block (EOF)
  1216 000004BB 2B06[2A00]                  sub ax,WORD PTR [module_start]    ; adjust relative to start of module
  1217 000004BF 1B16[2C00]                  sbb dx,WORD PTR [module_start+2]  ; adjust high word
  1218 000004C3 A3[9600]                    mov WORD PTR [mod_header.mh_segdef],ax   ; save pointer to start
  1219 000004C6 8916[9800]                  mov WORD PTR [mod_header.mh_segdef+2],dx
  1220 000004CA A1[0000]                    mov ax,[first_segdefblk_ptr]
  1221                                  
  1222                                  wsb_loop:
  1223 000004CD 09C0                        or  ax,ax               ; see if valid segdef block
  1224 000004CF 7506                        jne wsb_2               ; yes
  1225                                  
  1226                                  wsb_done:
  1227 000004D1 B8[ssss]                    mov ax,DGROUP
  1228 000004D4 8ED8                        mov ds,ax               ; restore ds -> warplink data
  1229 000004D6 C3                          ret
  1230                                  
  1231                                  wsb_2:
  1232 000004D7 8ED8                        mov ds,ax               ; ds -> segdef block
  1233 000004D9 8B0E0000                    mov cx,[0]           ; get count of entries in block
  1234 000004DD 40                          inc ax
  1235 000004DE 8ED8                        mov ds,ax               ; ds -> first entry in segdef block
  1236 000004E0 31F6                        xor si,si               ; si offsets into block
  1237                                  
  1238 000004E2 09C9                        or  cx,cx               ; see if any entries in block    
  1239 000004E4 7503                        jne wsb_3               ; yes
  1240 000004E6 E98300                      jmp NEAR PTR wsb_nextblk    ; no entries in block
  1241                                  
  1242                                  wsb_3:
  1243 000004E9 51                          push    cx              ; save count of entries
  1244                                  
  1245                                  ; translate segment name seg:off to file position
  1246                                  wsb_transloop:
  1247 000004EA 8B440A                      mov ax,[si+seg_namblk_ptr]   ; get segment of segment name
  1248 000004ED BF[0000]                    mov di,OFFSET ddl_symbol_lookup wrt DGROUP  ; di -> start of lookup table
  1249 000004F0 BA[ssss]                    mov dx,DGROUP
  1250 000004F3 8EC2                        mov es,dx               ; es -> warplink data
  1251                                  
  1252                                  wsb_searchloop:
  1253 000004F5 AF                          scasw                   ; search for segment entry in lookup table
  1254 000004F6 7405                        je  wsb_found           ; found the entry
  1255 000004F8 83C704                      add di,4                ; bump to next lookup entry
  1256 000004FB EBF8                        jmp SHORT wsb_searchloop    ; keep looking
  1257                                  
  1258                                  wsb_found:
  1259 000004FD 268B05                      mov ax,[es:di]          ; get low word of file position
  1260 00000500 268B7D02                    mov di,[es:di+2]        ; get high word
  1261                                  
  1262                                  ; file position corresponding to segment name in di:ax
  1263 00000504 034408                      add ax,[si+seg_nament_ptr]   ; add in segment name offset
  1264 00000507 83D700                      adc di,0                ; carry to high word
  1265 0000050A 83E804                      sub ax,4                ; adjust for 2 system info words not written
  1266 0000050D 83DF00                      sbb di,0                ; borrow to high word
  1267                                  
  1268 00000510 262B06[9200]                sub ax,WORD PTR [es:mod_header.mh_lnames] ; make relative to start of lnames block
  1269 00000515 261B3E[9400]                sbb di,WORD PTR [es:mod_header.mh_lnames+2]
  1270                                  
  1271 0000051A 894408                      mov [si+seg_nament_ptr],ax  ; save low file position
  1272 0000051D 897C0A                      mov [si+seg_namblk_ptr],di  ; save high file position
  1273                                  
  1274                                  ; translate class name seg:off to file position
  1275 00000520 8B440E                      mov ax,[si+class_namblk_ptr] ; get segment of segment name
  1276 00000523 BF[0000]                    mov di,OFFSET ddl_symbol_lookup wrt DGROUP  ; di -> start of lookup table
  1277                                  
  1278                                  wsb_search2:
  1279 00000526 AF                          scasw                   ; search for segment entry in lookup table
  1280 00000527 7405                        je  wsb_found2          ; found the entry
  1281 00000529 83C704                      add di,4                ; bump to next lookup entry
  1282 0000052C EBF8                        jmp SHORT wsb_search2   ; keep looking
  1283                                  
  1284                                  wsb_found2:
  1285 0000052E 268B05                      mov ax,[es:di]          ; get low word of file position
  1286 00000531 268B7D02                    mov di,[es:di+2]        ; get high word
  1287                                  
  1288                                  ; file position corresponding to segment name in di:ax
  1289 00000535 03440C                      add ax,[si+class_nament_ptr] ; add in segment name offset
  1290 00000538 83D700                      adc di,0                ; carry to high word
  1291 0000053B 83E804                      sub ax,4                ; adjust for 2 system info words not written
  1292 0000053E 83DF00                      sbb di,0                ; borrow to high word
  1293                                  
  1294 00000541 262B06[9200]                sub ax,WORD PTR [es:mod_header.mh_lnames] ; make relative to start of lnames block
  1295 00000546 261B3E[9400]                sbb di,WORD PTR [es:mod_header.mh_lnames+2]
  1296                                  
  1297 0000054B 89440C                      mov [si+class_nament_ptr],ax    ; save low file position
  1298 0000054E 897C0E                      mov [si+class_namblk_ptr],di    ; save high file position
  1299                                  
  1300                                  wsb_nextent:
  1301 00000551 83C620                      add si,32               ; move to next entry
  1302 00000554 E294                        loop    wsb_transloop   ; loop until all entries translated
  1303                                  
  1304 00000556 58                          pop ax                  ; get count of entries
  1305 00000557 B120                        mov cl,32
  1306 00000559 F6E1                        mul cl                  ; get byte count of entries
  1307 0000055B 89C1                        mov cx,ax               ; cx holds bytes to write
  1308 0000055D 31D2                        xor dx,dx
  1309 0000055F B440                        mov ah,40h              ; write to device
  1310 00000561 CD21                        int 21h
  1311 00000563 7212                        jc  wsb_error
  1312 00000565 39C8                    	cmp ax, cx
  1313 00000567 B82700                  	mov ax, 27h			; insufficient disk space error
  1314 0000056A 750B                    	jne wsb_error
  1315                                  
  1316                                  wsb_nextblk:
  1317 0000056C 8CD8                        mov ax,ds               ; get -> first entry in block
  1318 0000056E 48                          dec ax                  ; back up to -> block start
  1319 0000056F 8ED8                        mov ds,ax               ; ds -> block
  1320 00000571 A10200                      mov ax,[2]           ; get pointer to next block, if any
  1321 00000574 E956FF                      jmp NEAR PTR wsb_loop   ; loop back and write it
  1322                                  
  1323                                  wsb_error:
  1324 00000577 E9(0000)                    jmp NEAR PTR dos_error  ; error opening file
  1325                                  
  1326                                  write_segdef_block  ENDP
  1327                                  
  1328                                  ;*****************************
  1329                                  ;* WRITE_GRPDEF_BLOCK        *
  1330                                  ;*****************************
  1331                                  
  1332                                  ; write all grpdef blocks into one big grpdef block for DDL module
  1333                                  
  1334                                  write_grpdef_block  PROC
  1335 0000057A E84DFB                      call    update_ddl_size ; get start of segdef block (EOF)
  1336 0000057D 2B06[2A00]                  sub ax,WORD PTR [module_start]    ; adjust relative to start of module
  1337 00000581 1B16[2C00]                  sbb dx,WORD PTR [module_start+2]  ; adjust high word
  1338 00000585 A3[9A00]                    mov WORD PTR [mod_header.mh_grpdef],ax   ; save pointer to start
  1339 00000588 8916[9C00]                  mov WORD PTR [mod_header.mh_grpdef+2],dx
  1340 0000058C A1[0000]                    mov ax,[first_grpblk_ptr]
  1341                                  
  1342                                  wgb_loop:
  1343 0000058F 09C0                        or  ax,ax               ; see if valid segdef block
  1344 00000591 7506                        jne wgb_2               ; yes
  1345                                  
  1346                                  wgb_done:
  1347 00000593 B8[ssss]                    mov ax,DGROUP
  1348 00000596 8ED8                        mov ds,ax               ; restore ds -> warplink data
  1349 00000598 C3                          ret
  1350                                  
  1351                                  wgb_2:
  1352 00000599 8ED8                        mov ds,ax               ; ds -> grpdef block
  1353 0000059B 8B0E0000                    mov cx,[0]           ; get count of entries in block
  1354 0000059F 40                          inc ax
  1355 000005A0 8ED8                        mov ds,ax               ; ds -> first entry in segdef block
  1356 000005A2 31F6                        xor si,si               ; si offsets into block
  1357 000005A4 E355                        jcxz    wgb_nextblk     ; no entries in block
  1358                                  
  1359 000005A6 51                          push    cx              ; save count of entries
  1360                                  
  1361                                  ; translate group name seg:off to file position
  1362                                  wgb_transloop:
  1363 000005A7 8B4406                      mov ax,[si+ges_grp_namblk_ptr]   ; get segment of group name
  1364 000005AA BF[0000]                    mov di,OFFSET ddl_symbol_lookup wrt DGROUP  ; di -> start of lookup table
  1365 000005AD BA[ssss]                    mov dx,DGROUP
  1366 000005B0 8EC2                        mov es,dx               ; es -> warplink data
  1367                                  
  1368                                  wgb_searchloop:
  1369 000005B2 AF                          scasw                   ; search for segment entry in lookup table
  1370 000005B3 7405                        je  wgb_found           ; found the entry
  1371 000005B5 83C704                      add di,4                ; bump to next lookup entry
  1372 000005B8 EBF8                        jmp SHORT wgb_searchloop    ; keep looking
  1373                                  
  1374                                  wgb_found:
  1375 000005BA 268B05                      mov ax,[es:di]          ; get low word of file position
  1376 000005BD 268B7D02                    mov di,[es:di+2]        ; get high word
  1377                                  
  1378                                  ; file position corresponding to segment name in di:ax
  1379 000005C1 034404                      add ax,[si+ges_grp_nament_ptr]   ; add in group name offset
  1380 000005C4 83D700                      adc di,0                ; carry to high word
  1381 000005C7 83E804                      sub ax,4                ; adjust for 2 system info words not written
  1382 000005CA 83DF00                      sbb di,0                ; borrow to high word
  1383                                  
  1384 000005CD 262B06[9200]                sub ax,WORD PTR [es:mod_header.mh_lnames] ; make relative to start of lnames block
  1385 000005D2 261B3E[9400]                sbb di,WORD PTR [es:mod_header.mh_lnames+2]
  1386                                  
  1387 000005D7 894404                      mov [si+ges_grp_nament_ptr],ax  ; save low file position
  1388 000005DA 897C06                      mov [si+ges_grp_namblk_ptr],di  ; save high file position
  1389                                  
  1390                                  wgb_nextent:
  1391 000005DD 83C610                      add si,16               ; move to next entry
  1392 000005E0 E2C5                        loop    wgb_transloop   ; loop until all entries translated
  1393                                  
  1394 000005E2 58                          pop ax                  ; get count of entries
  1395 000005E3 B110                        mov cl,16
  1396 000005E5 F6E1                        mul cl                  ; get byte count of entries
  1397 000005E7 89C1                        mov cx,ax               ; cx holds bytes to write
  1398 000005E9 31D2                        xor dx,dx
  1399 000005EB B440                        mov ah,40h              ; write to device
  1400 000005ED CD21                        int 21h
  1401 000005EF 7286                        jc  wsb_error
  1402 000005F1 39C8                    	cmp ax, cx
  1403 000005F3 B82700                  	mov ax, 27h			; insufficient disk space error
  1404 000005F6 7403E97CFF              	jne wsb_error
  1405                                  
  1406                                  wgb_nextblk:
  1407 000005FB 8CD8                        mov ax,ds               ; get -> first entry in block
  1408 000005FD 48                          dec ax                  ; back up to -> block start
  1409 000005FE 8ED8                        mov ds,ax               ; ds -> block
  1410 00000600 A10200                      mov ax,[2]           ; get pointer to next block, if any
  1411 00000603 EB8A                        jmp SHORT wgb_loop      ; loop back and write it
  1412                                  
  1413                                  write_grpdef_block  ENDP
  1414                                  
  1415                                  ;*****************************
  1416                                  ;* WRITE_MODEND_INFO         *
  1417                                  ;*****************************
  1418                                  
  1419                                  ; translate modend start address, if any, and store it in mh_startup
  1420                                  ; destroys ax,bx,dx,di,si,es
  1421                                  
  1422                                  write_modend_info   PROC
  1423 00000605 B8[ssss]                    mov ax,DGROUP
  1424 00000608 8EC0                        mov es,ax
  1425 0000060A BF[B200]                    mov di,OFFSET mod_header.mh_startup wrt DGROUP
  1426 0000060D 8E1E[0C00]                  mov ds,[modend_ptr]
  1427 00000611 31F6                        xor si,si
  1428 00000613 AC                          lodsb                   ; get first byte of modend record
  1429 00000614 2440                        and al,40h              ; see if contains start address
  1430 00000616 7422                        je  wmi_ret             ; no
  1431                                  
  1432 00000618 26800E[8200]01              or  BYTE [es:mod_header.mh_flags],1   ; set main module flag
  1433 0000061E A4                          movsb                   ; transfer end dat field
  1434                                  
  1435 0000061F 30E4                        xor ah,ah
  1436 00000621 AC                          lodsb                   ; get first byte of frame datum
  1437 00000622 A880                        test    al,80h          ; see if two byte index
  1438 00000624 7405                        je  wmi_2               ; no
  1439 00000626 247F                        and al,7fh              ; strip high bit
  1440 00000628 88C4                        mov ah,al               ; move value to high byte
  1441 0000062A AC                          lodsb                   ; get frame datum/index second byte
  1442                                  
  1443                                  wmi_2:
  1444 0000062B AB                          stosw                   ; save frame datum
  1445                                  
  1446 0000062C 30E4                        xor ah,ah
  1447 0000062E AC                          lodsb                   ; get first byte of target datum
  1448 0000062F A880                        test    al,80h          ; see if two byte index
  1449 00000631 7405                        je  wmi_3               ; no
  1450 00000633 247F                        and al,7fh              ; strip high bit
  1451 00000635 88C4                        mov ah,al               ; move value to high byte
  1452 00000637 AC                          lodsb                   ; get target datum/index second byte
  1453                                  
  1454                                  wmi_3:
  1455 00000638 AB                          stosw                   ; save target datum
  1456 00000639 A5                          movsw                   ; transfer target displacement
  1457                                  
  1458                                  wmi_ret:
  1459 0000063A B8[ssss]                    mov ax,DGROUP
  1460 0000063D 8ED8                        mov ds,ax
  1461 0000063F C3                          ret
  1462                                  write_modend_info   ENDP
  1463                                  
  1464                                  ;*****************************
  1465                                  ;* WRITE_BINARY_BLOCK        *
  1466                                  ;*****************************
  1467                                  
  1468                                  ; translate and write binary/fixup data
  1469                                  ; destroys ax,bx,cx,dx,di,si,es
  1470                                  
  1471                                  write_binary_block  PROC
  1472 00000640 E887FA                      call    update_ddl_size ; get start of binary blocks (EOF)
  1473 00000643 2B06[2A00]                  sub ax,WORD PTR [module_start]    ; adjust relative to start of module
  1474 00000647 1B16[2C00]                  sbb dx,WORD PTR [module_start+2]  ; adjust high word
  1475 0000064B A3[AE00]                    mov WORD PTR [mod_header.mh_binary],ax   ; save pointer to start
  1476 0000064E 8916[B000]                  mov WORD PTR [mod_header.mh_binary+2],dx
  1477                                  
  1478 00000652 833E[0000]00                cmp word [first_binblk_ptr],0  ; see if first binary block exists
  1479 00000657 7501                        jne wbb_2               ; yes
  1480 00000659 C3                          ret                     ; no binary data in this module
  1481                                  
  1482                                  wbb_2:
  1483 0000065A 55                          push    bp              ; save critical register
  1484 0000065B C706[1800]0100              mov word [proc_segment],1      ; init number of segment being processed for binary data
  1485 00000661 A1[0000]                    mov ax,[first_segdefblk_ptr]  ; get pointer to first segdef block
  1486                                  
  1487                                  wbb_blkloop:
  1488 00000664 89C5                        mov bp,ax               ; save -> block
  1489 00000666 40                          inc ax                  ; ax -> first entry in block
  1490                                  
  1491                                  wbb_entloop:
  1492 00000667 8EC0                        mov es,ax               ; es -> entry in segdef block
  1493 00000669 A3[2200]                    mov [curr_segdefent_ptr],ax   ; save -> to current segdef entry
  1494 0000066C 06                          push    es              ; save es -> segdef entry
  1495 0000066D 26A01A00                    mov al,[es:sdes_acbp_byte]  ; get acbp byte
  1496 00000671 24E0                        and al,0e0h             ; get align field
  1497 00000673 7413                        je  to_wbb_zeroseg      ; absolute segment, no bytes to save
  1498 00000675 268E061600                  mov es,[es:seg_partent_firstptr]    ; es -> first segment partition entry
  1499 0000067A 26A00B00                    mov al,[es:spes_acbp_byte]  ; get acbp byte
  1500 0000067E 83E002                      and ax,2                ; get Big bit (zero high byte)
  1501 00000681 260B060C00                  or  ax,[es:spes_part_len]   ; merge in length of segment
  1502 00000686 7503                        jne wbb_nonzero         ; nonzero length segment
  1503                                  
  1504                                  to_wbb_zeroseg:
  1505 00000688 E98300                      jmp NEAR PTR wbb_zeroseg    ; zero, no data to write
  1506                                  
  1507                                  ; segment has nonzero length, check the binary blocks and see if any data was
  1508                                  ; specified for the segment
  1509                                  wbb_nonzero:
  1510 0000068B 26A10C00                    mov ax,[es:spes_part_len]
  1511 0000068F A3[2400]                    mov [seg_truelen],ax      ; save length of overlaid segment
  1512 00000692 A1[0000]                    mov ax,[buffer_base]      ; ax -> i/o buffer
  1513 00000695 2DFF0F                      sub ax,0fffh            ; ax -> 64K-16 area below i/o buffer (work i/o buffer)
  1514 00000698 3B06[0000]                  cmp ax,[allocation_base]  ; make sure haven't rammed into allocations building up
  1515 0000069C 7306                        jae wbb_workbuff        ; no
  1516                                  
  1517 0000069E B80800                      mov ax,8                ; force out of memory error
  1518 000006A1 E9(0000)                    jmp NEAR PTR dos_error
  1519                                  
  1520                                  wbb_workbuff:
  1521 000006A4 8EC0                        mov es,ax               ; es -> work i/o buffer
  1522 000006A6 31C0                        xor ax,ax
  1523 000006A8 89C7                        mov di,ax               ; offset within i/o buffer
  1524 000006AA BE[C200]                    mov si,OFFSET bin_header wrt DGROUP
  1525 000006AD AB                          stosw                   ; init flags
  1526 000006AE 8904                        mov [si],ax          ; init for binary header structure too
  1527 000006B0 AB                          stosw
  1528 000006B1 894402                      mov [si+2],ax
  1529 000006B4 A1[1800]                    mov ax,[proc_segment]     ; get segment number
  1530 000006B7 AB                          stosw                   ; init segment number
  1531 000006B8 894404                      mov [si+4],ax
  1532 000006BB 31C0                        xor ax,ax
  1533 000006BD B90700                      mov cx,7                ; zero init next 7 words (word and 3 dwords)
  1534 000006C0 F3AB                        rep stosw
  1535 000006C2 894406                      mov [si+6],ax
  1536 000006C5 894408                      mov [si+8],ax
  1537 000006C8 89440A                      mov [si+10],ax
  1538 000006CB 89440C                      mov [si+12],ax
  1539 000006CE 89440E                      mov [si+14],ax
  1540 000006D1 894410                      mov [si+16],ax
  1541 000006D4 894412                      mov [si+18],ax
  1542                                  
  1543 000006D7 A1[0000]                    mov ax,[first_binblk_ptr] ; get pointer to first binary block
  1544                                  
  1545                                  wbb_searchloop:
  1546 000006DA BE0C00                      mov si,12               ; si-> start of L?DATA record image
  1547 000006DD 8ED8                        mov ds,ax               ; ds -> binary block
  1548 000006DF 8B0E0300                    mov cx,[3]           ; get record length-checksum
  1549 000006E3 AC                          lodsb                   ; get segment index of block
  1550 000006E4 49                          dec cx                  ; adjust for first segment index byte
  1551 000006E5 A880                        test    al,80h          ; see if high bit set
  1552 000006E7 7402                        je  wbb_3               ; no
  1553 000006E9 AC                          lodsb                   ; get true index number
  1554 000006EA 49                          dec cx                  ; adjust for second segment index byte
  1555                                  
  1556                                  wbb_3:
  1557 000006EB A20700                      mov [7],al           ; save segment index
  1558 000006EE 89360800                    mov [8],si           ; save start of iterated or enumerated data block-2
  1559 000006F2 8306080002                  add WORD PTR [8],2   ; adjust for data offset
  1560 000006F7 890E0A00                    mov [10],cx          ; save record length not counting segment index
  1561 000006FB 263A060400                  cmp al,BYTE PTR [es:bhs_segind] ; see if segment indices match
  1562 00000700 7527                        jne wbb_nextblk         ; no
  1563                                  
  1564                                  ; this block of binary data belongs to this segment
  1565 00000702 A00000                      mov al,[0]           ; get type of record (LEDATA or LIDATA)
  1566 00000705 3CA0                        cmp al,LEDATA           ; see if LEDATA
  1567 00000707 751D                        jne wbb_lidata          ; no, LIDATA
  1568                                  
  1569 00000709 E81B06                      call    ddl_proc_ledata ; process LEDATA record
  1570 0000070C EB1B                        jmp SHORT wbb_nextblk
  1571                                  
  1572                                  ; zero length segment, or no initialized data
  1573                                  wbb_zeroseg:
  1574 0000070E B8[ssss]                    mov ax,DGROUP
  1575 00000711 8ED8                        mov ds,ax               ; restore ds -> warplink data
  1576 00000713 8B3E[1800]                  mov di,[proc_segment]     ; get segment being processed
  1577 00000717 4F                          dec di                  ; make relative zero
  1578 00000718 D1E7                        shl di,1                ; convert to dword offset
  1579 0000071A D1E7                        shl di,1
  1580 0000071C 8E06[2000]                  mov es,[binary_fpos]
  1581 00000720 31C0                        xor ax,ax
  1582 00000722 AB                          stosw
  1583 00000723 AB                          stosw                   ; zero binary file position entry in table to show no init'ed data
  1584 00000724 EB65                        jmp SHORT wbb_nextseg   ; try next segment
  1585                                  
  1586                                  wbb_lidata:
  1587 00000726 E85D06                      call    ddl_proc_lidata ; process LIDATA record
  1588                                  
  1589                                  ; move to next binary block, if any
  1590                                  wbb_nextblk:
  1591 00000729 A10100                      mov ax,[1]           ; get pointer to next block
  1592 0000072C 09C0                        or  ax,ax               ; see if exists
  1593 0000072E 75AA                        jne wbb_searchloop      ; yes
  1594                                  
  1595 00000730 268B0E0600                  mov cx,[es:bhs_length]  ; get length of init'ed binary data
  1596 00000735 E3D7                        jcxz    wbb_zeroseg     ; zero, ignore
  1597                                  
  1598 00000737 B8[ssss]                    mov ax,DGROUP
  1599 0000073A 8ED8                        mov ds,ax
  1600 0000073C 268B361000                  mov si,[es:bhs_offset]
  1601 00000741 8936[D200]                  mov [bin_header.bhs_offset],si   ; save offset of binary data
  1602 00000745 890E[C800]                  mov [bin_header.bhs_length],cx ; save length of binary data
  1603                                  
  1604 00000749 A1[2400]                    mov ax,[seg_truelen]
  1605 0000074C A3[D400]                    mov [bin_header.bhs_truelen],ax  ; save true length of segment (for DDL overlay manager)
  1606                                  
  1607 0000074F 83C114                      add cx,20               ; add in system words
  1608 00000752 89CE                        mov si,cx
  1609 00000754 E873F9                      call    update_ddl_size ; get start of binary block (EOF)
  1610 00000757 89F1                        mov cx,si               ; restore byte count
  1611 00000759 A3[2E00]                    mov WORD PTR [currbin_start],ax   ; save pointer to start
  1612 0000075C 8916[3000]                  mov WORD PTR [currbin_start+2],dx
  1613 00000760 8B36[1800]                  mov si,[proc_segment]     ; get segment being processed
  1614 00000764 4E                          dec si                  ; make relative zero
  1615 00000765 D1E6                        shl si,1                ; convert to dword offset
  1616 00000767 D1E6                        shl si,1
  1617 00000769 8E1E[2000]                  mov ds,[binary_fpos]
  1618 0000076D 8904                        mov [si],ax          ; save start of binary block to file position table
  1619 0000076F 895402                      mov [si+2],dx
  1620 00000772 06                          push    es
  1621 00000773 1F                          pop ds
  1622 00000774 31D2                        xor dx,dx               ; ds:dx -> i/o buffer
  1623 00000776 B440                        mov ah,40h              ; write to file (bx already == handle)
  1624 00000778 CD21                        int 21h
  1625 0000077A 7238                        jc  wbb_error           ; error writing to file
  1626 0000077C 39C8                    	cmp ax, cx
  1627 0000077E B82700                  	mov ax, 27h			; insufficient disk space error
  1628 00000781 7531                    	jne wbb_error
  1629                                  
  1630                                  ; check if fixups/write them if they exist, update binary file position info
  1631 00000783 E83100                      call    ddl_proc_fixupp ; process FIXUPP records for segment, if any
  1632                                  
  1633                                  wbb_nextent:
  1634 00000786 B8[ssss]                    mov ax,DGROUP
  1635 00000789 8ED8                        mov ds,ax               ; restore ds -> warplink data
  1636                                  
  1637                                  wbb_nextseg:
  1638 0000078B 07                          pop es                  ; restore es -> segdef entry
  1639 0000078C A1[1800]                    mov ax,[proc_segment]     ; get number of segment last processed
  1640 0000078F 40                          inc ax                  ; bump to next
  1641 00000790 3B06[0000]                  cmp ax,[current_segdef]   ; see if past number of segments
  1642 00000794 771C                        ja  wbb_ret             ; yes
  1643 00000796 A3[1800]                    mov [proc_segment],ax     ; update segment being processed
  1644 00000799 8CC0                        mov ax,es               ; ax -> current segdef entry
  1645 0000079B 40                          inc ax                  ; move to next entry in block
  1646 0000079C 40                          inc ax                  ; 32 bytes/entry
  1647 0000079D 89C3                        mov bx,ax
  1648 0000079F 29EB                        sub bx,bp               ; get difference between new entry and start of block
  1649 000007A1 83FB41                      cmp bx,SEG_DEFBLK_SIZE  ; see if all entries in block used
  1650 000007A4 7303                        jae wbb_getnext         ; yes
  1651 000007A6 E9BEFE                      jmp NEAR PTR wbb_entloop    ; no, keep pulling them
  1652                                  
  1653                                  wbb_getnext:
  1654 000007A9 8EC5                        mov es,bp               ; es -> block
  1655 000007AB 26A10200                    mov ax,[es:2]           ; get -> next block
  1656 000007AF E9B2FE                      jmp NEAR PTR wbb_blkloop; process it
  1657                                  
  1658                                  wbb_ret:
  1659 000007B2 5D                          pop bp                  ; restore critical register
  1660 000007B3 C3                          ret
  1661                                  
  1662                                  wbb_error:
  1663 000007B4 E9(0000)                    jmp NEAR PTR dos_error  ; error opening file
  1664                                  
  1665                                  write_binary_block  ENDP
  1666                                  
  1667                                  ;*****************************
  1668                                  ;* DDL_PROC_FIXUPP           *
  1669                                  ;*****************************
  1670                                  
  1671                                  ; see if fixup records for current segment, process them if so
  1672                                  ; upon entry es -> i/o buffer
  1673                                  ; destroys ax,bx,cx,dx,di,si,es,ds
  1674                                  
  1675                                  ddl_proc_fixupp PROC
  1676 000007B7 B8[ssss]                    mov ax,DGROUP
  1677 000007BA 8ED8                        mov ds,ax               ; restore ds -> warplink data
  1678 000007BC 31C0                        xor ax,ax
  1679 000007BE A3[1A00]                    mov [lobyte_count],ax     ; zero counters
  1680 000007C1 A3[1C00]                    mov [near_count],ax
  1681 000007C4 A3[1E00]                    mov [far_count],ax
  1682 000007C7 E800F9                      call    update_ddl_size ; get start of fixupp block (EOF)
  1683 000007CA A3[CA00]                    mov WORD PTR [bin_header.bhs_fixptr],ax   ; update fixup block file position
  1684 000007CD 8916[CC00]                  mov WORD PTR [bin_header.bhs_fixptr+2],dx
  1685 000007D1 8B0E[1800]                  mov cx,[proc_segment]     ; get segment index currently being processed
  1686                                  
  1687 000007D5 A1[0000]                    mov ax,[first_fixblk_ptr]
  1688 000007D8 09C0                        or  ax,ax               ; see if any fixups
  1689 000007DA 7557                        jne dpf_2               ; yes
  1690                                  
  1691                                  ; update binary header, seek back to end of file
  1692                                  dpf_update:
  1693 000007DC B8[ssss]                    mov ax,DGROUP
  1694 000007DF 8ED8                        mov ds,ax               ; restore ds -> warplink data
  1695 000007E1 E8E6F8                      call    update_ddl_size ; get next binary file position
  1696 000007E4 A3[CE00]                    mov WORD PTR [bin_header.bhs_nextptr],ax  ; update next binary block file position
  1697 000007E7 8916[D000]                  mov WORD PTR [bin_header.bhs_nextptr+2],dx
  1698                                  
  1699 000007EB 8E06[2200]                  mov es,[curr_segdefent_ptr]   ; es -> current segdef entry
  1700 000007EF 26A01B00                    mov al,[es:27]          ; save overlay flag byte
  1701 000007F3 A2[C200]                    mov BYTE PTR [bin_header.bhs_flags],al
  1702                                  
  1703 000007F6 A1[1A00]                    mov ax,[lobyte_count]
  1704 000007F9 0B06[1C00]                  or  ax,[near_count]
  1705 000007FD 0B06[1E00]                  or  ax,[far_count]        ; see if any fixups
  1706 00000801 750C                        jne dpf_hdrseek         ; yes
  1707 00000803 A3[CA00]                    mov WORD PTR [bin_header.bhs_fixptr],ax   ; zero out fixup pointer
  1708 00000806 A3[CC00]                    mov WORD PTR [bin_header.bhs_fixptr+2],ax
  1709 00000809 A1[2400]                    mov ax,[seg_truelen]
  1710 0000080C A3[D400]                    mov [bin_header.bhs_truelen],ax   ; save true length of segment (for DDL overlay manager)
  1711                                  
  1712                                  ; seek back to binary header
  1713                                  dpf_hdrseek:
  1714 0000080F 8B16[2E00]                  mov dx,WORD PTR [currbin_start]
  1715 00000813 8B0E[3000]                  mov cx,WORD PTR [currbin_start+2]
  1716 00000817 B80042                      mov ax,4200h            ; move file pointer, offset from start
  1717 0000081A CD21                        int 21h
  1718                                  
  1719                                  ; write updated binary header
  1720 0000081C B91400                      mov cx,BIN_HEADER_SIZE  ; size of binary header
  1721 0000081F BA[C200]                    mov dx,OFFSET bin_header wrt DGROUP ; ds:dx -> source
  1722 00000822 B440                        mov ah,40h              ; write to file (bx already == handle)
  1723 00000824 CD21                        int 21h
  1724 00000826 728C                        jc  wbb_error           ; error writing to file
  1725 00000828 39C8                    	cmp ax, cx
  1726 0000082A B82700                  	mov ax, 27h			; insufficient disk space error
  1727 0000082D 7585                    	jne wbb_error
  1728                                  
  1729 0000082F E898F8                      call    update_ddl_size ; seek to end of file
  1730 00000832 C3                          ret
  1731                                  
  1732                                  ; update binary header info
  1733                                  dpf_2:
  1734 00000833 31FF                        xor di,di               ; zero offset in buffer
  1735 00000835 89C2                        mov dx,ax               ; save -> first fixup block
  1736                                  
  1737                                  ; init fixup file position info to start of fixup block
  1738 00000837 A1[CA00]                    mov ax,WORD PTR [bin_header.bhs_fixptr]
  1739 0000083A 26A30200                    mov WORD PTR [es:fhs_lowinfo],ax
  1740 0000083E 26A30600                    mov WORD PTR [es:fhs_lowloc],ax
  1741 00000842 26A30C00                    mov WORD PTR [es:fhs_nearinfo],ax
  1742 00000846 26A31000                    mov WORD PTR [es:fhs_nearloc],ax
  1743 0000084A 26A31600                    mov WORD PTR [es:fhs_farinfo],ax
  1744 0000084E 26A31A00                    mov WORD PTR [es:fhs_farloc],ax
  1745 00000852 A1[CC00]                    mov ax,WORD PTR [bin_header.bhs_fixptr+2]
  1746 00000855 26A30400                    mov WORD PTR [es:fhs_lowinfo+2],ax
  1747 00000859 26A30800                    mov WORD PTR [es:fhs_lowloc+2],ax
  1748 0000085D 26A30E00                    mov WORD PTR [es:fhs_nearinfo+2],ax
  1749 00000861 26A31200                    mov WORD PTR [es:fhs_nearloc+2],ax
  1750 00000865 26A31800                    mov WORD PTR [es:fhs_farinfo+2],ax
  1751 00000869 26A31C00                    mov WORD PTR [es:fhs_farloc+2],ax
  1752 0000086D 31C0                        xor ax,ax               ; zero init counts
  1753 0000086F 26A30000                    mov [es:fhs_lowcount],ax
  1754 00000873 26A30A00                    mov [es:fhs_nearcount],ax
  1755 00000877 26A31400                    mov [es:fhs_farcount],ax
  1756                                  
  1757 0000087B BF1E00                      mov di,30               ; 3 sets of word/dword/dword
  1758 0000087E B506                        mov ch,6                ; six fixup passes needed; info for low-byte, near, far
  1759                                                              ; and location for low-byte, near, and far
  1760 00000880 89D0                        mov ax,dx               ; restore ax -> first fixup block
  1761                                  
  1762                                  dpf_typeloop:
  1763 00000882 8ED8                        mov ds,ax               ; ds -> fixup block
  1764 00000884 89C2                        mov dx,ax               ; save -> fixup block
  1765 00000886 A10200                      mov ax,[2]           ; get owning L?DATA block, if any
  1766 00000889 09C0                        or  ax,ax
  1767 0000088B 7422                        je  dpf_nextblk         ; no owner (thread fixup)
  1768 0000088D 8ED8                        mov ds,ax               ; ds -> owning L?DATA block
  1769 0000088F 3A0E0700                    cmp cl,[7]           ; see if segment index matches current segment
  1770 00000893 751A                        jne dpf_nextblk         ; no
  1771                                  
  1772                                  ; this fixup block goes with the current segment, save appropriate fixups
  1773 00000895 8A0E0000                    mov cl,[0]           ; get LEDATA/LIDATA fixup status
  1774 00000899 8B1E0500                    mov bx,[5]           ; get data offset
  1775 0000089D B8[ssss]                    mov ax,DGROUP
  1776 000008A0 8ED8                        mov ds,ax               ; ds -> warplink data
  1777 000008A2 80FD04                      cmp ch,4                ; see if info pass
  1778 000008A5 7205                        jb  dpf_3               ; no
  1779                                  
  1780                                  ; info pass, keep fixup information, no discrimination between LIDATA and LEDATA
  1781 000008A7 E8C100                      call    save_fixup_info
  1782 000008AA EB03                        jmp SHORT dpf_nextblk
  1783                                  
  1784                                  dpf_3:
  1785 000008AC E8CF03                      call    lxdata_fixupp   ; save fixups for LEDATA/LIDATA
  1786                                  
  1787                                  dpf_nextblk:
  1788 000008AF B8[ssss]                    mov ax,DGROUP
  1789 000008B2 8ED8                        mov ds,ax
  1790 000008B4 8A0E[1800]                  mov cl,BYTE PTR [proc_segment]    ; get segment index currently being processed in cl
  1791                                  
  1792 000008B8 8EDA                        mov ds,dx               ; ds -> fixup block
  1793 000008BA A10000                      mov ax,[0]           ; get -> next block
  1794 000008BD 09C0                        or  ax,ax               ; see if valid
  1795 000008BF 75C1                        jne dpf_typeloop        ; yes
  1796                                  
  1797                                  ; all through fixups this pass
  1798                                  ; update appropriate fixup info
  1799 000008C1 B8[ssss]                    mov ax,DGROUP
  1800 000008C4 8ED8                        mov ds,ax
  1801 000008C6 80FD06                      cmp ch,6                ; see if low-byte info
  1802 000008C9 7520                        jne dpf_ni              ; no
  1803 000008CB A1[1A00]                    mov ax,[lobyte_count]     ; update low-byte fixup info
  1804 000008CE 26A30000                    mov [es:fhs_lowcount],ax
  1805 000008D2 26830602001E                add WORD PTR [es:fhs_lowinfo],30    ; update low-byte location
  1806 000008D8 268316040000                adc WORD PTR [es:fhs_lowinfo+2],0   ; carry to high word
  1807 000008DE 26013E0C00                  add WORD PTR [es:fhs_nearinfo],di   ; update next (near fixup) info
  1808 000008E3 2683160E0000                adc WORD PTR [es:fhs_nearinfo+2],0  ; carry to high word
  1809 000008E9 EB54                        jmp SHORT dpf_passchk
  1810                                  
  1811                                  dpf_ni:
  1812 000008EB 80FD05                      cmp ch,5                ; see if near info
  1813 000008EE 7514                        jne dpf_fi              ; no
  1814 000008F0 A1[1C00]                    mov ax,[near_count]       ; update near fixup info
  1815 000008F3 26A30A00                    mov [es:fhs_nearcount],ax
  1816 000008F7 26013E1600                  add WORD PTR [es:fhs_farinfo],di    ; update start of next field
  1817 000008FC 268316180000                adc WORD PTR [es:fhs_farinfo+2],0   ; carry to high word
  1818 00000902 EB3B                        jmp SHORT dpf_passchk
  1819                                  
  1820                                  dpf_fi:
  1821 00000904 80FD04                      cmp ch,4                ; see if far info
  1822 00000907 7514                        jne dpf_ll              ; no
  1823 00000909 A1[1E00]                    mov ax,[far_count]        ; update far fixup info
  1824 0000090C 26A31400                    mov [es:fhs_farcount],ax
  1825 00000910 26013E0600                  add WORD PTR [es:fhs_lowloc],di ; update start of next field
  1826 00000915 268316080000                adc WORD PTR [es:fhs_lowloc+2],0    ; carry to high word
  1827 0000091B EB22                        jmp SHORT dpf_passchk
  1828                                  
  1829                                  dpf_ll:
  1830 0000091D 80FD03                      cmp ch,3                ; see if low-byte location
  1831 00000920 750D                        jne dpf_nl              ; no
  1832 00000922 26013E1000                  add WORD PTR [es:fhs_nearloc],di    ; update start of next field
  1833 00000927 268316120000                adc WORD PTR [es:fhs_nearloc+2],0   ; carry to high word
  1834 0000092D EB10                        jmp SHORT dpf_passchk
  1835                                  
  1836                                  dpf_nl:
  1837 0000092F 80FD02                      cmp ch,2                ; see if near location
  1838 00000932 750B                        jne dpf_passchk         ; no
  1839 00000934 26013E1A00                  add WORD PTR [es:fhs_farloc],di ; update start of next field
  1840 00000939 2683161C0000                adc WORD PTR [es:fhs_farloc+2],0    ; carry to high word
  1841                                  
  1842                                  dpf_passchk:
  1843 0000093F A1[0000]                    mov ax,[first_fixblk_ptr] ; reset pointer to start of fixup block
  1844 00000942 FECD                        dec ch                  ; see if done with all passes
  1845 00000944 7403                        je  dpf_write           ; done
  1846 00000946 E939FF                      jmp NEAR PTR dpf_typeloop   ; more fixup passes to perform
  1847                                  
  1848                                  ; write the saved fixups
  1849                                  dpf_write:
  1850 00000949 8B1E[0000]                  mov bx,[exe_handle]
  1851 0000094D 06                          push    es
  1852 0000094E 1F                          pop ds                  ; ds -> i/o buffer
  1853 0000094F 89F9                        mov cx,di               ; get count of bytes to write
  1854 00000951 83F91E                      cmp cx,30               ; see if only fixup header (no fixups)
  1855 00000954 760F                        jbe dbf_to_update       ; yes, don't bother writing empty header
  1856 00000956 31D2                        xor dx,dx
  1857 00000958 B440                        mov ah,40h              ; write to device
  1858 0000095A CD21                        int 21h
  1859 0000095C 720A                        jc  dpf_error
  1860 0000095E 39C8                    	cmp ax, cx
  1861 00000960 B82700                  	mov ax, 27h			; insufficient disk space error
  1862 00000963 7503                    	jne dpf_error
  1863                                  
  1864                                  dbf_to_update:
  1865 00000965 E974FE                      jmp NEAR PTR dpf_update ; update binary header with new info
  1866                                  
  1867                                  dpf_error:
  1868 00000968 E9(0000)                    jmp NEAR PTR dos_error  ; error writing to file
  1869                                  
  1870                                  ddl_proc_fixupp ENDP
  1871                                  
  1872                                  ;*****************************
  1873                                  ;* SAVE_FIXUP_INFO           *
  1874                                  ;*****************************
  1875                                  
  1876                                  ; save fixup information from FIXUPP record
  1877                                  ; upon entry ch holds pass number(4-6), dx-> fixup block
  1878                                  ; cl holds L?DATA record type
  1879                                  ; es:di -> destination buffer
  1880                                  ; destroys ax,bx,si,ds
  1881                                  
  1882                                  save_fixup_info PROC
  1883 0000096B 52                          push    dx
  1884 0000096C 55                          push    bp
  1885 0000096D 51                          push    cx
  1886 0000096E B8[ssss]                    mov ax,DGROUP
  1887 00000971 8ED8                        mov ds,ax               ; ds -> warplink data
  1888 00000973 88EB                        mov bl,ch               ; save pass number in bl
  1889                                  
  1890                                  ; get the state of FIXUPP thread fields when using this fixupp record
  1891 00000975 8CC0                        mov ax,es
  1892 00000977 1E                          push    ds
  1893 00000978 07                          pop es                  ; es -> warplink data
  1894 00000979 8EDA                        mov ds,dx               ; ds -> fixupp record
  1895 0000097B 57                          push    di              ; save position in i/o buffer
  1896 0000097C BE0600                      mov si,6                ; ds:si -> saved thread method and index info
  1897 0000097F BF[0000]                    mov di,OFFSET frame_thrd_meth wrt DGROUP
  1898 00000982 A5                          movsw                   ; get four frame thread method bytes
  1899 00000983 A5                          movsw
  1900 00000984 BF[0000]                    mov di,OFFSET target_thrd_meth wrt DGROUP
  1901 00000987 A5                          movsw                   ; get four target thread method bytes
  1902 00000988 A5                          movsw
  1903 00000989 B90400                      mov cx,4                ; four index words
  1904 0000098C BF[0000]                    mov di,OFFSET frame_thrd_index wrt DGROUP
  1905 0000098F F3A5                        rep movsw               ; get frame thread index
  1906 00000991 B90400                      mov cx,4                ; four index words
  1907 00000994 BF[0000]                    mov di,OFFSET target_thrd_index wrt DGROUP
  1908 00000997 F3A5                        rep movsw               ; get target thread index
  1909 00000999 5F                          pop di                  ; restore position in i/o buffer
  1910 0000099A 8EC0                        mov es,ax               ; es -> i/o buffer
  1911                                  
  1912 0000099C 8B0E0400                    mov cx,[4]           ; get record length
  1913                                  
  1914                                  sfi_loop:
  1915 000009A0 8CDA                        mov dx,ds               ; save -> fixupp record
  1916 000009A2 AC                          lodsb                   ; get first byte of thread or fixup field
  1917 000009A3 49                          dec cx                  ; decrement record length to parse
  1918 000009A4 A880                        test    al,80h          ; fixup field if high bit set
  1919 000009A6 7506                        jne sfi_fix             ; fixup field
  1920                                  
  1921                                  ; thread field, parse it out
  1922 000009A8 E8660A                      call    ddl_save_thread
  1923 000009AB E96C01                      jmp NEAR PTR sfi_chkcheck   ; check if at checksum byte
  1924                                  
  1925                                  ; fixup field
  1926                                  sfi_fix:
  1927 000009AE 26C60500                    mov BYTE PTR [es:di],0  ; zero out modified fixdat field
  1928 000009B2 BD[ssss]                    mov bp,DGROUP
  1929 000009B5 8EDD                        mov ds,bp               ; ds -> warplink data
  1930 000009B7 88C7                        mov bh,al
  1931 000009B9 80E71C                      and bh,1ch              ; get loc field
  1932                                  
  1933                                  ; bh holds loc field ==0 if low-order, ==4 if offset, ==8 if segment
  1934                                  ; == 0ch if seg:off, ==14h if offset, others invalid
  1935 000009BC 750D                        jne sfi_notlow          ; loc field nonzero
  1936                                  
  1937                                  ; low-order byte fixup
  1938 000009BE 80FB06                      cmp bl,6                ; see if low-order fixup pass
  1939 000009C1 754D                        jne sfi_cont            ; no, leave bh==0 to flag not to save fixup
  1940 000009C3 FEC7                        inc bh                  ; bh!=0 flags save fixup
  1941 000009C5 FF06[1A00]                  inc word [lobyte_count]        ; bump count of low-byte fixups
  1942 000009C9 EB45                        jmp SHORT sfi_cont
  1943                                  
  1944                                  sfi_notlow:
  1945 000009CB 80FF04                      cmp bh,4                ; see if offset
  1946 000009CE 740F                        je  sfi_offset          ; yes
  1947 000009D0 80FF14                      cmp bh,14h              ; see if offset
  1948 000009D3 740A                        je  sfi_offset          ; yes
  1949 000009D5 80FF0C                      cmp bh,0ch              ; see if potentially offset
  1950 000009D8 7514                        jne sfi_segment         ; no
  1951                                  
  1952                                  ; pointer fixup, only keep as offset if pass 5 (near pass)
  1953 000009DA 80FB05                      cmp bl,5                ; see if near fixup pass
  1954 000009DD 750F                        jne sfi_segment         ; no
  1955                                  
  1956                                  sfi_offset:
  1957 000009DF 30FF                        xor bh,bh               ; init save fixup flag
  1958 000009E1 80FB05                      cmp bl,5                ; see if near fixup pass
  1959 000009E4 752A                        jne sfi_cont            ; no
  1960 000009E6 FEC7                        inc bh                  ; flag save fixup
  1961 000009E8 FF06[1C00]                  inc word [near_count]          ; bump count of near fixups
  1962 000009EC EB22                        jmp SHORT sfi_cont
  1963                                  
  1964                                  sfi_segment:
  1965 000009EE 80FF08                      cmp bh,8                ; see if segment
  1966 000009F1 740C                        je  sfi_far             ; yes
  1967 000009F3 80FF0C                      cmp bh,0ch              ; see if potentially segment
  1968 000009F6 7516                        jne sfi_nosave          ; no
  1969                                  
  1970                                  ; pointer fixup, only keep as segment if pass 4 (far pass)
  1971 000009F8 80FB04                      cmp bl,4                ; see if far fixup pass
  1972 000009FB 7511                        jne sfi_nosave          ; no
  1973 000009FD EB09                        jmp SHORT sfi_pointer   ; keep bh at 0ch to flag segment portion of pointer fixup
  1974                                  
  1975                                  sfi_far:
  1976 000009FF 30FF                        xor bh,bh               ; init save fixup flag
  1977 00000A01 80FB04                      cmp bl,4                ; see if far fixup pass
  1978 00000A04 750A                        jne sfi_cont            ; no
  1979 00000A06 FEC7                        inc bh                  ; flag save fixup
  1980                                  
  1981                                  sfi_pointer:
  1982 00000A08 FF06[1E00]                  inc word [far_count]           ; bump count of far fixups
  1983 00000A0C EB02                        jmp SHORT sfi_cont
  1984                                  
  1985                                  sfi_nosave:
  1986 00000A0E 30FF                        xor bh,bh               ; flag no save of fixup
  1987                                  
  1988                                  sfi_cont:
  1989 00000A10 883E[0200]                  mov [save_fixup],bh       ; set status of save fixup flag
  1990 00000A14 88C7                        mov bh,al               ; get locat low-byte
  1991 00000A16 80E740                      and bh,40h              ; get M-bit value
  1992 00000A19 D0E7                        shl bh,1                ; shift to MSB
  1993 00000A1B 26883D                      mov [es:di],bh          ; save modified fix dat MSB
  1994                                  
  1995 00000A1E 88C4                        mov ah,al               ; save first byte of locat field
  1996 00000A20 8EDA                        mov ds,dx               ; ds -> fixupp record
  1997 00000A22 AC                          lodsb                   ; get second byte of locat field
  1998 00000A23 BD[ssss]                    mov bp,DGROUP
  1999 00000A26 8EDD                        mov ds,bp               ; ds -> warplink data
  2000 00000A28 49                          dec cx                  ; decrement record length to parse
  2001 00000A29 80E403                      and ah,3                ; ax holds data record offset
  2002 00000A2C 803E[0200]0C                cmp byte [save_fixup],0ch      ; see if segment part of pointer fixup
  2003 00000A31 7503                        jne sfi_notpoint        ; no
  2004 00000A33 83C002                      add ax,2                ; bump 2 past offset to segment portion
  2005                                  
  2006                                  sfi_notpoint:
  2007 00000A36 A3[1200]                    mov [data_rec_off],ax     ; save data record offset for LIDATA fixup
  2008 00000A39 8EDA                        mov ds,dx               ; ds -> fixupp record
  2009 00000A3B AC                          lodsb                   ; get fix dat field
  2010 00000A3C 49                          dec cx
  2011 00000A3D 88C2                        mov dl,al               ; save fix dat value
  2012                                  
  2013 00000A3F A880                        test    al,80h          ; check if thread field for frame (fbit)
  2014 00000A41 7438                        je  sfi_notframe        ; no
  2015                                  
  2016                                  ; thread field for frame
  2017 00000A43 D0E8                        shr al,1                ; make frame field value relative zero
  2018 00000A45 D0E8                        shr al,1
  2019 00000A47 D0E8                        shr al,1
  2020 00000A49 D0E8                        shr al,1
  2021 00000A4B 2407                        and al,7                ; mask off F bit
  2022                                  
  2023 00000A4D 8CDD                        mov bp,ds               ; save -> fixupp record
  2024 00000A4F BB[ssss]                    mov bx,DGROUP
  2025 00000A52 8EDB                        mov ds,bx               ; ds -> warplink data
  2026                                  
  2027 00000A54 30E4                        xor ah,ah               ; zap high byte
  2028 00000A56 BB[0000]                    mov bx,OFFSET frame_thrd_meth wrt DGROUP    ; bx -> frame thread method array base
  2029 00000A59 01C3                        add bx,ax               ; bx -> proper byte array element
  2030 00000A5B 8A1F                        mov bl,[bx]             ; get frame method
  2031 00000A5D D0E3                        shl bl,1                ; shift to frame field
  2032 00000A5F D0E3                        shl bl,1
  2033 00000A61 D0E3                        shl bl,1
  2034 00000A63 D0E3                        shl bl,1
  2035 00000A65 80E20F                      and dl,0fh              ; mask off F-bit, frame bits
  2036 00000A68 08DA                        or  dl,bl               ; merge in frame bits from thread
  2037                                  
  2038 00000A6A D1E0                        shl ax,1                ; convert to word offset
  2039 00000A6C BB[0000]                    mov bx,OFFSET frame_thrd_index wrt DGROUP   ; bx -> frame thread index array base
  2040 00000A6F 01C3                        add bx,ax               ; bx -> proper word array element
  2041 00000A71 8B07                        mov ax,[bx]             ; get frame index
  2042 00000A73 26894501                    mov [es:di+1],ax        ; save frame index
  2043                                  
  2044 00000A77 8EDD                        mov ds,bp               ; restore ds -> fixupp record
  2045 00000A79 EB1E                        jmp SHORT sfi_targ
  2046                                  
  2047                                  ; no thread field for frame
  2048                                  sfi_notframe:
  2049 00000A7B 26C745010000                mov WORD PTR [es:di+1],0    ; zero init frame datum field (frame index)
  2050 00000A81 2470                        and al,70h              ; get frame field
  2051 00000A83 3C20                        cmp al,20h              ; see if frame datum/index exists
  2052 00000A85 7712                        ja  sfi_targ            ; no
  2053                                  
  2054                                  ; frame datum/index exists
  2055 00000A87 30E4                        xor ah,ah               ; zap high byte
  2056 00000A89 AC                          lodsb                   ; get frame datum/index first byte
  2057 00000A8A 49                          dec cx                  ; decrement record length to parse
  2058 00000A8B 3C80                        cmp al,80h              ; see if two byte field
  2059 00000A8D 7206                        jb  sfi_frame           ; no
  2060 00000A8F 247F                        and al,7fh              ; strip high bit
  2061 00000A91 88C4                        mov ah,al               ; move value to high byte
  2062 00000A93 AC                          lodsb                   ; scan past frame datum/index second byte
  2063 00000A94 49                          dec cx
  2064                                  
  2065                                  sfi_frame:
  2066 00000A95 26894501                    mov [es:di+1],ax        ; save frame datum/index
  2067                                  
  2068                                  sfi_targ:
  2069 00000A99 26C745030000                mov WORD PTR [es:di+3],0    ; zero init target datum field (target index)
  2070 00000A9F 88D0                        mov al,dl               ; get fix dat field
  2071 00000AA1 A808                        test    al,8            ; check if thread field for target (T bit)
  2072 00000AA3 7512                        jne sfi_thrdtarg        ; yes
  2073                                  
  2074                                  ; no thread field for target
  2075 00000AA5 30E4                        xor ah,ah               ; zap high byte
  2076 00000AA7 AC                          lodsb                   ; get target datum first byte
  2077 00000AA8 49                          dec cx
  2078 00000AA9 3C80                        cmp al,80h              ; see if two byte field
  2079 00000AAB 7206                        jb  sfi_savetarg        ; no
  2080 00000AAD 247F                        and al,7fh              ; strip high bit
  2081 00000AAF 88C4                        mov ah,al               ; move value to high byte
  2082 00000AB1 AC                          lodsb                   ; get target datum second byte
  2083 00000AB2 49                          dec cx
  2084                                  
  2085                                  sfi_savetarg:
  2086 00000AB3 8CDD                        mov bp,ds               ; bp -> fixupp record
  2087 00000AB5 EB20                        jmp SHORT sfi_2
  2088                                  
  2089                                  ; thread field for target
  2090                                  sfi_thrdtarg:
  2091 00000AB7 8CDD                        mov bp,ds               ; save -> fixupp record
  2092 00000AB9 BB[ssss]                    mov bx,DGROUP
  2093 00000ABC 8EDB                        mov ds,bx               ; ds -> warplink data
  2094                                  
  2095 00000ABE 2403                        and al,3                ; get targt field value in al
  2096 00000AC0 30E4                        xor ah,ah               ; zap high byte
  2097 00000AC2 BB[0000]                    mov bx,OFFSET target_thrd_meth wrt DGROUP   ; bx -> target thread method array base
  2098 00000AC5 01C3                        add bx,ax               ; bx -> proper byte array element
  2099 00000AC7 8A1F                        mov bl,[bx]             ; get target method
  2100 00000AC9 80E2FC                      and dl,0fch             ; mask off targt bits
  2101 00000ACC 08DA                        or  dl,bl               ; merge in target bits from thread
  2102                                  
  2103 00000ACE D1E0                        shl ax,1                ; convert to word offset
  2104 00000AD0 BB[0000]                    mov bx,OFFSET target_thrd_index wrt DGROUP  ; bx -> target thread index array base
  2105 00000AD3 01C3                        add bx,ax               ; bx -> proper word array element
  2106 00000AD5 8B07                        mov ax,[bx]             ; get target index
  2107                                  
  2108                                  sfi_2:
  2109 00000AD7 26884503                    mov [es:di+3],al        ; save target index low
  2110 00000ADB D0E4                        shl ah,1                ; merge in target index high
  2111 00000ADD D0E4                        shl ah,1
  2112 00000ADF D0E4                        shl ah,1
  2113 00000AE1 D0E4                        shl ah,1                ; high 4 bits
  2114 00000AE3 26086502                    or  [es:di+2],ah
  2115                                  
  2116 00000AE7 8EDD                        mov ds,bp               ; restore ds -> fixupp record
  2117                                  
  2118                                  sfi_pbit:
  2119 00000AE9 88D0                        mov al,dl               ; get fix dat field
  2120 00000AEB 2404                        and al,4                ; get P bit field
  2121 00000AED 7504                        jne sfi_savefix         ; set, no target displacement
  2122                                  
  2123                                  ; P bit is zero, scan past target displacement field
  2124 00000AEF 46                          inc si                  ; gobble target displacement word
  2125 00000AF0 46                          inc si
  2126 00000AF1 49                          dec cx
  2127 00000AF2 49                          dec cx
  2128                                  
  2129                                  ; check if should save fixup, if so, just increment di+5 so no overwrite next fixup
  2130                                  sfi_savefix:
  2131 00000AF3 8CDD                        mov bp,ds
  2132 00000AF5 B8[ssss]                    mov ax,DGROUP
  2133 00000AF8 8ED8                        mov ds,ax               ; ds -> warplink data
  2134 00000AFA 803E[0200]00                cmp byte [save_fixup],0        ; see if should save fixup
  2135 00000AFF 7413                        je  sfi_flagoff         ; no
  2136 00000B01 260815                      or  [es:di],dl          ; merge in updated fix dat (save M bit status)
  2137 00000B04 58                          pop ax                  ; get cx entry value in ax (al holds L?DATA record type)
  2138 00000B05 50                          push    ax              ; restore to stack
  2139 00000B06 3CA0                        cmp al,LEDATA           ; see if LEDATA
  2140 00000B08 7405                        je  sif_nextslot        ; yes
  2141                                  
  2142                                  ; LIDATA record, multiple fixups
  2143 00000B0A E81F00                      call    lidata_multfix_info ; need to save info on multiple fixups
  2144 00000B0D EB05                        jmp SHORT sfi_flagoff
  2145                                  
  2146                                  sif_nextslot:
  2147 00000B0F 83C704                      add di,4
  2148 00000B12 7212                        jc  sfi_memerr          ; buffer overflow
  2149                                  
  2150                                  sfi_flagoff:
  2151 00000B14 8EDD                        mov ds,bp               ; restore ds -> fixupp record
  2152 00000B16 5B                          pop bx                  ; get cx entry value in bx, bh holds pass number
  2153 00000B17 53                          push    bx              ; restore to stack
  2154 00000B18 88FB                        mov bl,bh               ; get pass number in bl
  2155                                  
  2156                                  ; see if at checksum
  2157                                  sfi_chkcheck:
  2158 00000B1A 83F901                      cmp cx,1                ; check if at checksum byte
  2159 00000B1D 7603                        jbe sfi_out             ; yes
  2160 00000B1F E97EFE                      jmp NEAR PTR sfi_loop   ; no, loop back for next fixup/thread field
  2161                                  
  2162                                  sfi_out:
  2163 00000B22 59                          pop cx
  2164 00000B23 5D                          pop bp
  2165 00000B24 5A                          pop dx
  2166 00000B25 C3                          ret
  2167                                  
  2168                                  sfi_memerr:
  2169 00000B26 B80800                      mov ax,8                ; force out of memory error
  2170 00000B29 E9(0000)                    jmp NEAR PTR dos_error
  2171                                  
  2172                                  save_fixup_info ENDP
  2173                                  
  2174                                  ;*****************************
  2175                                  ;* LIDATA_MULTFIX_INFO       *
  2176                                  ;*****************************
  2177                                  
  2178                                  ; save info for fixups occurring multiple times in LIDATA record
  2179                                  ; upon entry es:di -> fixup info storage, currently at 4-byte entry
  2180                                  ; to save as many times as fixup occurs
  2181                                  ; ah holds information pass (4-6, low-byte, near, or far)
  2182                                  ; ds -> DGROUP
  2183                                  ; bp -> fixupp record
  2184                                  ; data_rec_off has data record offset
  2185                                  ; destroys ax,bx,dx
  2186                                  
  2187                                  lidata_multfix_info PROC
  2188 00000B2C 51                          push    cx
  2189 00000B2D 56                          push    si
  2190 00000B2E 1E                          push    ds
  2191 00000B2F 80FC06                      cmp ah,6                ; see if low-byte info pass
  2192 00000B32 7506                        jne lmi_notlow          ; no
  2193 00000B34 FF0E[1A00]                  dec word [lobyte_count]        ; drop count of low-byte fixups incremented during LEDATA shared code
  2194 00000B38 EB0F                        jmp SHORT lmi_2
  2195                                  
  2196                                  lmi_notlow:
  2197 00000B3A 80FC05                      cmp ah,5                ; see if near info pass
  2198 00000B3D 7506                        jne lmi_far             ; no
  2199 00000B3F FF0E[1C00]                  dec word [near_count]          ; drop count of near fixups incremented during LEDATA shared code
  2200 00000B43 EB04                        jmp SHORT lmi_2
  2201                                  
  2202                                  lmi_far:
  2203 00000B45 FF0E[1E00]                  dec word [far_count]           ; drop count of far fixups incremented during LEDATA shared code
  2204                                  
  2205                                  lmi_2:
  2206 00000B49 8826[0C00]                  mov [pass_count],ah       ; save pass count information
  2207 00000B4D 8EDD                        mov ds,bp               ; ds -> fixupp record
  2208 00000B4F 8E1E0200                    mov ds,[2]           ; ds -> owner LIDATA record
  2209 00000B53 1E                          push    ds              ; save -> LIDATA record
  2210 00000B54 8B1E0500                    mov bx,[5]           ; get iterated data offset
  2211 00000B58 A10800                      mov ax,[8]           ; get start of iterated data block
  2212 00000B5B 8B0E0A00                    mov cx,[10]          ; get length of record after segment index byte
  2213 00000B5F 83E902                      sub cx,2                ; adjust for data offset word
  2214 00000B62 BA[ssss]                    mov dx,DGROUP
  2215 00000B65 8EDA                        mov ds,dx               ; ds -> warplink data
  2216 00000B67 0106[1200]                  add [data_rec_off],ax     ; add start of iterated data block to data record offset
  2217 00000B6B 89C6                        mov si,ax               ; start scanning at iterated data block
  2218 00000B6D 891E[1400]                  mov [iter_data_off],bx    ; save iterated data offset
  2219 00000B71 C606[0A00]00                mov byte [is_loc],0            ; zero location parsing flag
  2220                                  
  2221 00000B76 268A05                      mov al,[es:di]          ; get fixdat value
  2222 00000B79 A2[0800]                    mov [fixdat],al           ; save it
  2223 00000B7C 268B4501                    mov ax,[es:di+1]        ; get frame datum
  2224                                  
  2225 00000B80 80E40F                      and ah,0fh              ; mask off high bits of target
  2226 00000B83 A3[0E00]                    mov [frame_datum],ax      ; save it
  2227                                  
  2228 00000B86 268A4503                    mov al,[es:di+3]        ; get target datum low byte
  2229 00000B8A 268A6502                    mov ah,[es:di+2]        ; get high byte
  2230 00000B8E D0EC                        shr ah,1
  2231 00000B90 D0EC                        shr ah,1
  2232 00000B92 D0EC                        shr ah,1
  2233 00000B94 D0EC                        shr ah,1                ; convert 4 MSB to proper value
  2234 00000B96 A3[1000]                    mov [target_datum],ax     ; save it
  2235                                  
  2236 00000B99 1F                          pop ds                  ; ds -> LIDATA record
  2237                                  
  2238                                  lmi_3:
  2239 00000B9A E305                        jcxz    lmi_ret         ; no more fixups
  2240 00000B9C E84400                      call    fixup_recurse   ; save fixup info for LIDATA record
  2241 00000B9F EBF9                        jmp SHORT lmi_3         ; loop until no more bytes
  2242                                  
  2243                                  lmi_ret:
  2244 00000BA1 1F                          pop ds
  2245 00000BA2 5E                          pop si
  2246 00000BA3 59                          pop cx
  2247 00000BA4 C3                          ret
  2248                                  lidata_multfix_info ENDP
  2249                                  
  2250                                  ;*****************************
  2251                                  ;* LIDATA_MULTFIX_LOC        *
  2252                                  ;*****************************
  2253                                  
  2254                                  ; save location of fixups occurring multiple times in LIDATA record
  2255                                  ; upon entry es:di -> fixup info storage
  2256                                  ; ds -> fixup record
  2257                                  ; ax == data record offset + LIDATA record (iterated) offset
  2258                                  ; bp == LIDATA data offset
  2259                                  ; destroys ax,bx,dx
  2260                                  
  2261                                  lidata_multfix_loc  PROC
  2262 00000BA5 51                          push    cx
  2263 00000BA6 56                          push    si
  2264 00000BA7 55                          push    bp
  2265 00000BA8 1E                          push    ds
  2266                                  
  2267 00000BA9 29E8                        sub ax,bp               ; get data record offset in ax
  2268 00000BAB 89C5                        mov bp,ax               ; save data record offset in bp
  2269                                  
  2270 00000BAD 8E1E0200                    mov ds,[2]           ; ds -> owner LIDATA record
  2271 00000BB1 1E                          push    ds              ; save -> LIDATA record
  2272 00000BB2 8B1E0500                    mov bx,[5]           ; get iterated data offset
  2273 00000BB6 A10800                      mov ax,[8]           ; get start of iterated data block
  2274 00000BB9 8B0E0A00                    mov cx,[10]          ; get length of record after segment index byte
  2275 00000BBD 83E902                      sub cx,2                ; adjust for data offset word
  2276 00000BC0 BA[ssss]                    mov dx,DGROUP
  2277 00000BC3 8EDA                        mov ds,dx               ; ds -> warplink data
  2278 00000BC5 01C5                        add bp,ax               ; add start of iterated data block to data record offset
  2279 00000BC7 892E[1200]                  mov [data_rec_off],bp     ; save it
  2280 00000BCB 89C6                        mov si,ax               ; start scanning at iterated data block
  2281 00000BCD 891E[1400]                  mov [iter_data_off],bx    ; save iterated data offset
  2282 00000BD1 C606[0A00]01                mov byte [is_loc],1            ; flag fixup location parsing
  2283                                  
  2284 00000BD6 1F                          pop ds                  ; ds -> LIDATA record
  2285                                  
  2286                                  lml_2:
  2287 00000BD7 E305                        jcxz    lml_ret         ; no more fixups
  2288 00000BD9 E80700                      call    fixup_recurse   ; save fixup info for LIDATA record
  2289 00000BDC EBF9                        jmp SHORT lml_2         ; loop until no more bytes
  2290                                  
  2291                                  lml_ret:
  2292 00000BDE 1F                          pop ds
  2293 00000BDF 5D                          pop bp
  2294 00000BE0 5E                          pop si
  2295 00000BE1 59                          pop cx
  2296 00000BE2 C3                          ret
  2297                                  lidata_multfix_loc  ENDP
  2298                                  
  2299                                  ;*****************************
  2300                                  ;* FIXUP_RECURSE             *
  2301                                  ;*****************************
  2302                                  
  2303                                  ; use recursion to get all fixups out of lidata record
  2304                                  ; upon entry [ds:si] -> current data byte (initially iterated data block),
  2305                                  ; cx == size of data block,
  2306                                  ; [es:di] -> destination
  2307                                  ; destroys ax,bx,cx,dx
  2308                                  
  2309                                  fixup_recurse   PROC
  2310 00000BE3 AD                          lodsw                   ; get repeat count
  2311 00000BE4 49                          dec cx                  ; decrement record length to parse
  2312 00000BE5 49                          dec cx
  2313 00000BE6 89C3                        mov bx,ax               ; save repeat count
  2314                                  
  2315 00000BE8 AD                          lodsw                   ; get block count
  2316 00000BE9 49                          dec cx                  ; decrement record length to parse
  2317 00000BEA 49                          dec cx
  2318 00000BEB 89C2                        mov dx,ax               ; save block count
  2319                                  
  2320 00000BED 56                          push    si              ; save buffer position
  2321 00000BEE 51                          push    cx              ; save record iterated data block length
  2322                                  
  2323                                  fxr_reploop:
  2324 00000BEF 59                          pop cx                  ; restore record length
  2325 00000BF0 5E                          pop si                  ; restore buffer position
  2326 00000BF1 56                          push    si              ; restore values to stack
  2327 00000BF2 51                          push    cx
  2328                                  
  2329 00000BF3 09D2                        or  dx,dx               ; see if nested iterated data blocks
  2330 00000BF5 7410                        je  fxr_data            ; no
  2331                                  
  2332                                  ; nested iterated data blocks
  2333 00000BF7 89D0                        mov ax,dx               ; get total number of blocks to loop through
  2334                                  fxr_blkloop:
  2335 00000BF9 50                          push    ax              ; save current number of blocks left to loop thru
  2336 00000BFA 53                          push    bx              ; save repeat value
  2337 00000BFB 52                          push    dx              ; save block value
  2338 00000BFC E8E4FF                      call    fixup_recurse   ; nest down one level
  2339 00000BFF 5A                          pop dx                  ; restore block value
  2340 00000C00 5B                          pop bx                  ; restore repeat value
  2341 00000C01 58                          pop ax                  ; restore number of blocks left to loop thru
  2342 00000C02 48                          dec ax                  ; one iteration completed
  2343 00000C03 75F4                        jne fxr_blkloop         ; loop is not complete, using Z flag from previous decrement
  2344 00000C05 EB67                        jmp SHORT fxr_end_reploop   ; loop is complete, end this iteration of the repeat loop
  2345                                  
  2346                                  ; block size is zero, data follows
  2347                                  fxr_data:
  2348 00000C07 AC                          lodsb                   ; get length of data to write
  2349 00000C08 49                          dec cx                  ; decrement record length to parse
  2350                                  
  2351                                  ; write the data bytes
  2352 00000C09 51                          push    cx              ; save record's total data length (in case of repeat loop termination)
  2353 00000C0A 88C1                        mov cl,al               ; get data bytes to write in cl
  2354 00000C0C 30ED                        xor ch,ch               ; zap high byte
  2355 00000C0E 51                          push    cx              ; save data bytes written
  2356                                  
  2357 00000C0F 1E                          push    ds              ; save ds -> lidata record
  2358 00000C10 B8[ssss]                    mov ax,DGROUP
  2359 00000C13 8ED8                        mov ds,ax               ; ds -> warplink data
  2360                                  
  2361                                  fxr_loop:
  2362 00000C15 3B36[1200]                  cmp si,[data_rec_off]     ; see if matches fixup location
  2363 00000C19 7546                        jne fxr_cont            ; no
  2364                                  
  2365 00000C1B 803E[0A00]00                cmp byte [is_loc],0            ; see if parsing fixup for location
  2366 00000C20 753B                        jne fxr_loc             ; yes
  2367                                  
  2368 00000C22 A0[0800]                    mov al,[fixdat]           ; save fixup info
  2369 00000C25 AA                          stosb
  2370 00000C26 A1[0E00]                    mov ax,[frame_datum]
  2371 00000C29 AB                          stosw
  2372                                  
  2373 00000C2A A0[1100]                    mov al,BYTE PTR [target_datum+1]
  2374 00000C2D D0E0                        shl al,1
  2375 00000C2F D0E0                        shl al,1
  2376 00000C31 D0E0                        shl al,1
  2377 00000C33 D0E0                        shl al,1                ; convert to high bits
  2378 00000C35 260845FF                    or  [es:di-1],al        ; merge into frame datum high byte
  2379                                  
  2380 00000C39 A0[1000]                    mov al,BYTE PTR [target_datum]    ; save low byte of target datum
  2381 00000C3C AA                          stosb
  2382                                  
  2383 00000C3D 803E[0C00]06                cmp byte [pass_count],6        ; see if low-byte info pass
  2384 00000C42 7506                        jne fxr_notlow          ; no
  2385 00000C44 FF06[1A00]                  inc word [lobyte_count]        ; bump count of low-byte fixups
  2386 00000C48 EB17                        jmp SHORT fxr_cont
  2387                                  
  2388                                  fxr_notlow:
  2389 00000C4A 803E[0C00]05                cmp byte [pass_count],5        ; see if near info pass
  2390 00000C4F 7506                        jne fxr_far             ; no
  2391 00000C51 FF06[1C00]                  inc word [near_count]          ; bump count of near fixups
  2392 00000C55 EB0A                        jmp SHORT fxr_cont
  2393                                  
  2394                                  fxr_far:
  2395 00000C57 FF06[1E00]                  inc word [far_count]           ; bump count of far fixups
  2396 00000C5B EB04                        jmp SHORT fxr_cont
  2397                                  
  2398                                  fxr_loc:
  2399 00000C5D A1[1400]                    mov ax,[iter_data_off]    ; get current location of fixup
  2400 00000C60 AB                          stosw
  2401                                  
  2402                                  fxr_cont:
  2403 00000C61 46                          inc si                  ; move to next byte of record
  2404 00000C62 FF06[1400]                  inc word [iter_data_off]       ; bump location
  2405 00000C66 49                          dec cx                  ; drop count of data bytes to parse
  2406 00000C67 75AC                        jne fxr_loop            ; not done yet
  2407                                  
  2408 00000C69 1F                          pop ds                  ; restore ds -> lidata record
  2409                                  
  2410 00000C6A 58                          pop ax                  ; get data bytes written
  2411 00000C6B 59                          pop cx                  ; restore record's total data length (in case of repeat loop termination)
  2412 00000C6C 29C1                        sub cx,ax               ; subtract off data bytes written
  2413                                  
  2414                                  fxr_end_reploop:
  2415 00000C6E 4B                          dec bx                  ; an iteration of the repeat loop was completed
  2416 00000C6F 7403                        je  fxr_end             ; repeat loop completed
  2417 00000C71 E97BFF                      jmp NEAR PTR fxr_reploop    ; not complete, go back for next iteration
  2418                                  
  2419                                  fxr_end:
  2420 00000C74 83C404                      add sp,4                ; trash old record length and buffer position values on stack
  2421 00000C77 C3                          ret                     ; repeat loop complete, return to next highest level or proc2_lidata
  2422                                  
  2423                                  fxr_memerr:
  2424 00000C78 B80800                      mov ax,8                ; force out of memory error
  2425                                  
  2426                                  fxr_error:
  2427 00000C7B E9(0000)                    jmp NEAR PTR dos_error
  2428                                  
  2429                                  fixup_recurse   ENDP
  2430                                  
  2431                                  ;*****************************
  2432                                  ;* LXDATA_FIXUPP             *
  2433                                  ;*****************************
  2434                                  
  2435                                  ; save fixups for L?DATA record
  2436                                  ; upon entry ch holds pass number(1-3), dx -> fixup block
  2437                                  ; es:di -> destination buffer,
  2438                                  ; cl holds L?DATA record type
  2439                                  ; bx holds L?DATA data offset
  2440                                  ; destroys ax,bx,si,ds
  2441                                  
  2442                                  lxdata_fixupp   PROC
  2443 00000C7E 52                          push    dx
  2444 00000C7F 55                          push    bp
  2445 00000C80 51                          push    cx
  2446 00000C81 8EDA                        mov ds,dx
  2447 00000C83 BE1E00                      mov si,30               ; ds:si -> fixupp record
  2448 00000C86 89DD                        mov bp,bx               ; save data offset in bp
  2449 00000C88 88EB                        mov bl,ch               ; save pass number in bl
  2450 00000C8A 8B0E0400                    mov cx,[4]           ; get record length
  2451                                  
  2452                                  lef_loop:
  2453 00000C8E AC                          lodsb                   ; get first byte of thread or fixup field
  2454 00000C8F 49                          dec cx                  ; decrement record length to parse
  2455 00000C90 A880                        test    al,80h          ; fixup field if high bit set
  2456 00000C92 7506                        jne lef_fix             ; fixup field
  2457                                  
  2458                                  ; thread field, parse it out
  2459 00000C94 E87A07                      call    ddl_save_thread
  2460 00000C97 E98100                      jmp NEAR PTR lef_chkcheck   ; check if at checksum byte
  2461                                  
  2462                                  ; fixup field, scan past it
  2463                                  lef_fix:
  2464 00000C9A 1E                          push    ds
  2465 00000C9B BA[ssss]                    mov dx,DGROUP
  2466 00000C9E 8EDA                        mov ds,dx               ; ds -> warplink data
  2467 00000CA0 88C4                        mov ah,al               ; save low byte of locat field
  2468 00000CA2 241C                        and al,1ch              ; get loc field
  2469                                  
  2470                                  ; al holds loc field ==0 if low-order, ==4 if offset, ==8 if segment
  2471                                  ; == 0ch if seg:off, ==14h if offset, others invalid
  2472 00000CA4 7509                        jne lef_notlow          ; loc field nonzero
  2473                                  
  2474                                  ; low-order byte fixup
  2475 00000CA6 80FB03                      cmp bl,3                ; see if low-order fixup pass
  2476 00000CA9 753C                        jne lef_cont            ; no, leave bh==0 to flag not to save fixup
  2477 00000CAB FEC0                        inc al                  ; al!=0 flags save fixup
  2478 00000CAD EB38                        jmp SHORT lef_cont
  2479                                  
  2480                                  lef_notlow:
  2481 00000CAF 3C04                        cmp al,4                ; see if offset
  2482 00000CB1 740D                        je  lef_offset          ; yes
  2483 00000CB3 3C14                        cmp al,14h              ; see if offset
  2484 00000CB5 7409                        je  lef_offset          ; yes
  2485 00000CB7 3C0C                        cmp al,0ch              ; see if potentially offset
  2486 00000CB9 7510                        jne lef_segment         ; no
  2487                                  
  2488                                  ; pointer fixup, only keep as offset if pass 2 (near pass)
  2489 00000CBB 80FB02                      cmp bl,2                ; see if near fixup pass
  2490 00000CBE 750B                        jne lef_segment         ; no
  2491                                  
  2492                                  lef_offset:
  2493 00000CC0 30C0                        xor al,al               ; init save fixup flag
  2494 00000CC2 80FB02                      cmp bl,2                ; see if near fixup pass
  2495 00000CC5 7520                        jne lef_cont            ; no
  2496 00000CC7 FEC0                        inc al                  ; flag save fixup
  2497 00000CC9 EB1C                        jmp SHORT lef_cont
  2498                                  
  2499                                  lef_segment:
  2500 00000CCB 3C08                        cmp al,8                ; see if segment
  2501 00000CCD 740B                        je  lef_far             ; yes
  2502 00000CCF 3C0C                        cmp al,0ch              ; see if potentially segment
  2503 00000CD1 7512                        jne lef_nosave          ; no
  2504                                  
  2505                                  ; pointer fixup, only keep as segment if pass 1 (far pass)
  2506 00000CD3 80FB01                      cmp bl,1                ; see if far fixup pass
  2507 00000CD6 750D                        jne lef_nosave          ; no
  2508 00000CD8 EB0D                        jmp SHORT lef_cont      ; keep flag as 0ch to show segment in pointer location (offset 2)
  2509                                  
  2510                                  lef_far:
  2511 00000CDA 30C0                        xor al,al               ; init save fixup flag
  2512 00000CDC 80FB01                      cmp bl,1                ; see if far fixup pass
  2513 00000CDF 7506                        jne lef_cont            ; no
  2514 00000CE1 FEC0                        inc al                  ; flag save fixup
  2515 00000CE3 EB02                        jmp SHORT lef_cont
  2516                                  
  2517                                  lef_nosave:
  2518 00000CE5 30C0                        xor al,al               ; flag no save of fixup
  2519                                  
  2520                                  lef_cont:
  2521 00000CE7 88C2                        mov dl,al               ; set status of save fixup flag
  2522 00000CE9 1F                          pop ds                  ; ds -> fixupp record
  2523 00000CEA AC                          lodsb                   ; get second byte of locat field
  2524 00000CEB 49                          dec cx                  ; decrement record length to parse
  2525                                  
  2526 00000CEC 80E403                      and ah,3                ; ax holds data record offset
  2527 00000CEF 01E8                        add ax,bp               ; add in L?DATA data offset
  2528 00000CF1 08D2                        or  dl,dl               ; see if should save location
  2529 00000CF3 7415                        je  lef_scan            ; no
  2530 00000CF5 80FA0C                      cmp dl,0ch              ; see if segment part of pointer fixup
  2531 00000CF8 7503                        jne lef_saveit          ; no
  2532 00000CFA 83C002                      add ax,2                ; bump 2 past offset to segment portion
  2533                                  
  2534                                  lef_saveit:
  2535 00000CFD 5A                          pop dx                  ; get cx entry value in dx (dl holds L?DATA record type)
  2536 00000CFE 52                          push    dx              ; restore to stack
  2537 00000CFF 80FAA0                      cmp dl,LEDATA           ; see if LEDATA
  2538 00000D02 7405                        je  lef_lesave          ; yes
  2539                                  
  2540                                  ; LIDATA record, multiple fixups
  2541 00000D04 E89EFE                      call    lidata_multfix_loc  ; need to save location of multiple fixups
  2542 00000D07 EB01                        jmp SHORT lef_scan
  2543                                  
  2544                                  lef_lesave:
  2545 00000D09 AB                          stosw                   ; save location
  2546                                  
  2547                                  lef_scan:
  2548 00000D0A E8DB06                      call    scan_to_targ_disp   ; scan to target displacement field, if any
  2549                                  
  2550 00000D0D 88D0                        mov al,dl               ; get fix dat field
  2551 00000D0F 2404                        and al,4                ; get P bit field
  2552 00000D11 7504                        jne lef_nodisp          ; set, no target displacement
  2553                                  
  2554                                  ; P bit is zero, scan past target displacement field
  2555 00000D13 46                          inc si                  ; gobble target displacement word
  2556 00000D14 46                          inc si
  2557 00000D15 49                          dec cx
  2558 00000D16 49                          dec cx
  2559                                  
  2560                                  lef_nodisp:
  2561 00000D17 5B                          pop bx                  ; get cx entry value in bx, bh holds pass number
  2562 00000D18 53                          push    bx              ; restore to stack
  2563 00000D19 88FB                        mov bl,bh               ; get pass number in bl
  2564                                  
  2565                                  ; see if at checksum
  2566                                  lef_chkcheck:
  2567 00000D1B 83F901                      cmp cx,1                ; check if at checksum byte
  2568 00000D1E 7603                        jbe lef_ret             ; yes
  2569 00000D20 E96BFF                      jmp NEAR PTR lef_loop   ; no, loop back for next fixup/thread field
  2570                                  
  2571                                  lef_ret:
  2572 00000D23 59                          pop cx
  2573 00000D24 5D                          pop bp
  2574 00000D25 5A                          pop dx
  2575 00000D26 C3                          ret
  2576                                  lxdata_fixupp   ENDP
  2577                                  
  2578                                  ;*****************************
  2579                                  ;* DDL_PROC_LEDATA           *
  2580                                  ;*****************************
  2581                                  
  2582                                  ; process a LEDATA record
  2583                                  ; upon entry ds:si -> enumerated data offset of LEDATA record image,
  2584                                  ; es:di -> current i/o buffer position, cx holds data bytes+2 (enumerated data offset)
  2585                                  ; updates di,si
  2586                                  ; destroys ax,bx,cx,dx
  2587                                  
  2588                                  ddl_proc_ledata PROC
  2589 00000D27 AD                          lodsw                   ; get enumerated data offset
  2590 00000D28 49                          dec cx
  2591 00000D29 49                          dec cx                  ; adjust for enumerated data offset bytes
  2592 00000D2A 26FF360600                  push    word [es:bhs_length] ; save old length
  2593                                  
  2594 00000D2F 263B060600                  cmp ax,[es:bhs_length]  ; see if matches current length of segment
  2595 00000D34 7418                        je  dple_2              ; yes
  2596 00000D36 770F                        ja  dple_fill           ; no, fill
  2597                                  
  2598                                  ; offset is LESS than current segment length, reduce current segment length
  2599 00000D38 268B160600                  mov dx,[es:bhs_length]
  2600 00000D3D 29C2                        sub dx,ax
  2601 00000D3F 29D7                        sub di,dx               ; back up i/o buffer position
  2602 00000D41 26A30600                    mov [es:bhs_length],ax
  2603 00000D45 EB07                        jmp SHORT dple_2
  2604                                  
  2605                                  ; must zero fill to current offset
  2606                                  dple_fill:
  2607 00000D47 26A31000                    mov [es:bhs_offset],ax  ; save starting offset
  2608 00000D4B E8DB00                      call    ddl_zero_fill
  2609                                  
  2610                                  ; ax == current length of segment (data offset)
  2611                                  ; cx holds count of data bytes
  2612                                  ; es:di -> destination
  2613                                  ; ds:si -> source
  2614                                  dple_2:
  2615 00000D4E A30500                      mov [5],ax           ; save data offset for fixups
  2616 00000D51 01C8                        add ax,cx               ; add in bytes to add to segment
  2617 00000D53 26A30600                    mov [es:bhs_length],ax  ; update segment length
  2618 00000D57 7227                        jc  dple_memerr         ; overflow, force out of memory error
  2619 00000D59 83F8DC                      cmp ax,0fff0h-20        ; see if buffer will overflow (20 system bytes)
  2620 00000D5C 7722                        ja  dple_memerr         ; yes, force out of memory error
  2621                                  
  2622                                  ; put any fixup target displacement value in record
  2623 00000D5E E8E000                      call    proc_targ_disp  ; process fixup target displacements into binary data
  2624                                  
  2625 00000D61 D1E9                        shr cx,1                ; convert byte count to write to words
  2626 00000D63 F3A5                        rep movsw               ; move the string
  2627 00000D65 D1D1                        rcl cx,1                ; pick up carry
  2628 00000D67 F3A4                        rep movsb               ; transfer leftover byte, if any
  2629                                  
  2630 00000D69 58                          pop ax                  ; get old segment length
  2631 00000D6A 263B060600                  cmp ax,[es:bhs_length]  ; see if <=new length
  2632 00000D6F 7701                        ja  dple_adjust         ; no, use old length
  2633 00000D71 C3                          ret
  2634                                  
  2635                                  dple_adjust:
  2636 00000D72 268B1E0600                  mov bx,[es:bhs_length]  ; get new segment length (less than old)
  2637 00000D77 26A30600                    mov [es:bhs_length],ax  ; restore old segment length
  2638 00000D7B 29D8                        sub ax,bx               ; get amount to adjust di
  2639 00000D7D 01C7                        add di,ax               ; adjust di back to end of old segment
  2640 00000D7F C3                          ret
  2641                                  
  2642                                  dple_memerr:
  2643 00000D80 B80800                      mov ax,8                ; force out of memory error
  2644 00000D83 E9(0000)                    jmp NEAR PTR dos_error
  2645                                  
  2646                                  ddl_proc_ledata ENDP
  2647                                  
  2648                                  ;*****************************
  2649                                  ;* DDL_PROC_LIDATA           *
  2650                                  ;*****************************
  2651                                  
  2652                                  ; process a LIDATA record
  2653                                  ; upon entry ds:si -> iterated data offset of LIDATA record image,
  2654                                  ; es:di -> current i/o buffer position, cx holds data bytes+2 (iterated data offset)
  2655                                  ; updates di,si
  2656                                  ; destroys ax,bx,cx,dx
  2657                                  
  2658                                  ddl_proc_lidata PROC
  2659 00000D86 AD                          lodsw                   ; get iterated data offset
  2660 00000D87 49                          dec cx
  2661 00000D88 49                          dec cx                  ; adjust for iterated data offset bytes
  2662 00000D89 26FF360600                  push    word [es:bhs_length] ; save old length
  2663                                  
  2664 00000D8E 263B060600                  cmp ax,[es:bhs_length]  ; see if matches current length of segment
  2665 00000D93 741C                        je  dpli_2              ; yes
  2666 00000D95 770F                        ja  dpli_fill           ; no, fill
  2667                                  
  2668                                  ; offset is LESS than current segment length, reduce current segment length
  2669 00000D97 268B160600                  mov dx,[es:bhs_length]
  2670 00000D9C 29C2                        sub dx,ax
  2671 00000D9E 29D7                        sub di,dx               ; back up i/o buffer position
  2672 00000DA0 26A30600                    mov [es:bhs_length],ax
  2673 00000DA4 EB0B                        jmp SHORT dpli_2
  2674                                  
  2675                                  ; must zero fill to current offset
  2676                                  dpli_fill:
  2677 00000DA6 26A31000                    mov [es:bhs_offset],ax  ; save starting offset
  2678 00000DAA E87C00                      call    ddl_zero_fill
  2679 00000DAD 26A30600                    mov [es:bhs_length],ax  ; update segment length
  2680                                  
  2681                                  ; ax == current length of segment (data offset)
  2682                                  ; cx == size of iterated data block
  2683                                  ; ds:si -> source
  2684                                  ; es:di -> destination
  2685                                  dpli_2:
  2686 00000DB1 A30500                      mov [5],ax           ; save data offset for fixups
  2687                                  
  2688                                  ; put any fixup target displacement value in record
  2689 00000DB4 E88A00                      call    proc_targ_disp  ; process fixup target displacements into binary data
  2690                                  
  2691                                  dpli_3:
  2692 00000DB7 E305                        jcxz    dpli_4
  2693 00000DB9 E81900                      call    ddl_recurse_lidata  ; parse out the lidata record
  2694 00000DBC EBF9                        jmp SHORT dpli_3        ; loop until no more bytes
  2695                                  
  2696                                  dpli_4:
  2697 00000DBE 58                          pop ax                  ; get old segment length
  2698 00000DBF 263B060600                  cmp ax,[es:bhs_length]  ; see if <=new length
  2699 00000DC4 7701                        ja  dpli_adjust         ; no, use old length
  2700 00000DC6 C3                          ret
  2701                                  
  2702                                  dpli_adjust:
  2703 00000DC7 268B1E0600                  mov bx,[es:bhs_length]  ; get new segment length (less than old)
  2704 00000DCC 26A30600                    mov [es:bhs_length],ax  ; restore old segment length
  2705 00000DD0 29D8                        sub ax,bx               ; get amount to adjust di
  2706 00000DD2 01C7                        add di,ax               ; adjust di back to end of old segment
  2707 00000DD4 C3                          ret
  2708                                  ddl_proc_lidata ENDP
  2709                                  
  2710                                  ;*****************************
  2711                                  ;* DDL_RECURSE_LIDATA        *
  2712                                  ;*****************************
  2713                                  
  2714                                  ; use recursion to get all data out of lidata record
  2715                                  ; upon entry [ds:si] -> current data byte, cx == size of data block,
  2716                                  ; [es:di] -> destination
  2717                                  ; destroys ax,bx,cx,dx
  2718                                  
  2719                                  ddl_recurse_lidata  PROC
  2720 00000DD5 AD                          lodsw                   ; get repeat count
  2721 00000DD6 49                          dec cx                  ; decrement record length to parse
  2722 00000DD7 49                          dec cx
  2723 00000DD8 89C3                        mov bx,ax               ; save repeat count
  2724                                  
  2725 00000DDA AD                          lodsw                   ; get block count
  2726 00000DDB 49                          dec cx                  ; decrement record length to parse
  2727 00000DDC 49                          dec cx
  2728 00000DDD 89C2                        mov dx,ax               ; save block count
  2729                                  
  2730 00000DDF 56                          push    si              ; save buffer position
  2731 00000DE0 51                          push    cx              ; save record iterated data block length
  2732                                  
  2733                                  drl_reploop:
  2734 00000DE1 59                          pop cx                  ; restore record length
  2735 00000DE2 5E                          pop si                  ; restore buffer position
  2736 00000DE3 56                          push    si              ; restore values to stack
  2737 00000DE4 51                          push    cx
  2738                                  
  2739 00000DE5 09D2                        or  dx,dx               ; see if nested iterated data blocks
  2740 00000DE7 7410                        je  drl_data            ; no
  2741                                  
  2742                                  ; nested iterated data blocks
  2743 00000DE9 89D0                        mov ax,dx               ; get total number of blocks to loop through
  2744                                  drl_blkloop:
  2745 00000DEB 50                          push    ax              ; save current number of blocks left to loop thru
  2746 00000DEC 53                          push    bx              ; save repeat value
  2747 00000DED 52                          push    dx              ; save block value
  2748 00000DEE E8E4FF                      call    ddl_recurse_lidata  ; nest down one level
  2749 00000DF1 5A                          pop dx                  ; restore block value
  2750 00000DF2 5B                          pop bx                  ; restore repeat value
  2751 00000DF3 58                          pop ax                  ; restore number of blocks left to loop thru
  2752 00000DF4 48                          dec ax                  ; one iteration completed
  2753 00000DF5 75F4                        jne drl_blkloop         ; loop is not complete, using Z flag from previous decrement
  2754 00000DF7 EB23                        jmp SHORT drl_end_reploop   ; loop is complete, end this iteration of the repeat loop
  2755                                  
  2756                                  ; block size is zero, data follows
  2757                                  drl_data:
  2758 00000DF9 AC                          lodsb                   ; get length of data to write
  2759 00000DFA 49                          dec cx                  ; decrement record length to parse
  2760                                  
  2761                                  ; write the data bytes
  2762 00000DFB 51                          push    cx              ; save record's total data length (in case of repeat loop termination)
  2763 00000DFC 88C1                        mov cl,al               ; get data bytes to write in cl
  2764 00000DFE 30ED                        xor ch,ch               ; zap high byte
  2765 00000E00 51                          push    cx              ; save data bytes written
  2766 00000E01 26010E0600                  add [es:bhs_length],cx  ; update segment length
  2767 00000E06 721B                        jc  drl_memerr          ; overflow, force out of memory error
  2768 00000E08 26833E0600DC                cmp WORD PTR [es:bhs_length],0fff0h-20  ; see if buffer will overflow (20 system bytes)
  2769 00000E0E 7713                        ja  drl_memerr          ; yes, force out of memory error
  2770                                  
  2771                                  ; write the data bytes to destination (i/o buffer)
  2772                                  ; updates di,si
  2773 00000E10 D1E9                        shr cx,1                ; convert byte count to zero to words
  2774 00000E12 F3A5                        rep movsw               ; transfer the string
  2775 00000E14 D1D1                        rcl cx,1                ; pick up carry
  2776 00000E16 F3A4                        rep movsb               ; transfer leftover byte, if any
  2777                                  
  2778 00000E18 58                          pop ax                  ; get data bytes written
  2779 00000E19 59                          pop cx                  ; restore record's total data length (in case of repeat loop termination)
  2780 00000E1A 29C1                        sub cx,ax               ; subtract off data bytes written
  2781                                  
  2782                                  drl_end_reploop:
  2783 00000E1C 4B                          dec bx                  ; an iteration of the repeat loop was completed
  2784 00000E1D 75C2                        jne drl_reploop         ; not complete, go back for next iteration
  2785                                  
  2786                                  drl_end:
  2787 00000E1F 83C404                      add sp,4                ; trash old record length and buffer position values on stack
  2788 00000E22 C3                          ret                     ; repeat loop complete, return to next highest level or proc2_lidata
  2789                                  
  2790                                  drl_memerr:
  2791 00000E23 B80800                      mov ax,8                ; force out of memory error
  2792                                  
  2793                                  drl_error:
  2794 00000E26 E9(0000)                    jmp NEAR PTR dos_error
  2795                                  
  2796                                  ddl_recurse_lidata  ENDP
  2797                                  
  2798                                  ;*****************************
  2799                                  ;* DDL_ZERO_FILL             *
  2800                                  ;*****************************
  2801                                  
  2802                                  ; zero fill segment image until matches current offset
  2803                                  ; upon es:di -> current i/o buffer position, ax holds offset
  2804                                  ; updates di,si
  2805                                  ; destroys dx
  2806                                  
  2807                                  ddl_zero_fill   PROC
  2808 00000E29 50                          push    ax              ; save critical register
  2809 00000E2A 89CA                        mov dx,cx               ; save cx count
  2810 00000E2C 89C1                        mov cx,ax
  2811 00000E2E 262B0E0600                  sub cx,[es:bhs_length]  ; get difference between data offset and last segment stop
  2812 00000E33 31C0                        xor ax,ax               ; zero fill
  2813 00000E35 D1E9                        shr cx,1                ; convert byte count to zero to words
  2814 00000E37 F3AB                        rep stosw               ; zero the string
  2815 00000E39 D1D1                        rcl cx,1                ; pick up carry
  2816 00000E3B F3AA                        rep stosb               ; zero leftover byte, if any
  2817 00000E3D 89D1                        mov cx,dx               ; restore cx count
  2818 00000E3F 58                          pop ax                  ; restore critical register
  2819 00000E40 C3                          ret
  2820                                  ddl_zero_fill   ENDP
  2821                                  
  2822                                  ;*****************************
  2823                                  ;* PROC_TARG_DISP            *
  2824                                  ;*****************************
  2825                                  
  2826                                  ; process target displacements in fixupp records directly into binary data
  2827                                  ; upon entry ds holds segment of L?DATA record to match in fixup entry
  2828                                  ; ds:si -> data field (LEDATA) or data block (LIDATA)
  2829                                  ; destroys ax,bx,dx
  2830                                  
  2831                                  proc_targ_disp  PROC
  2832 00000E41 53                          push    bx
  2833 00000E42 51                          push    cx
  2834 00000E43 57                          push    di
  2835 00000E44 56                          push    si
  2836 00000E45 55                          push    bp
  2837 00000E46 8CDD                        mov bp,ds               ; get segment to match
  2838 00000E48 89F7                        mov di,si               ; save -> start of data
  2839 00000E4A B8[ssss]                    mov ax,DGROUP
  2840 00000E4D 8ED8                        mov ds,ax               ; ds -> warplink data
  2841 00000E4F A1[0000]                    mov ax,[first_fixblk_ptr]
  2842                                  
  2843                                  ptd_blkloop:
  2844 00000E52 09C0                        or  ax,ax               ; see if valid fixup block
  2845 00000E54 7459                        je  ptd_ret             ; no, done
  2846                                  
  2847 00000E56 8ED8                        mov ds,ax               ; ds -> block
  2848 00000E58 3B2E0200                    cmp bp,[2]           ; see if owner block matches current L?DATA record
  2849 00000E5C 754C                        jne ptd_nextblk         ; no
  2850                                  
  2851                                  ; owner block matches current L?DATA record, add any target displacments from fixups
  2852 00000E5E 8B0E0400                    mov cx,[4]           ; get record length
  2853 00000E62 BE1E00                      mov si,30               ; si -> start of fixupp record
  2854                                  
  2855                                  ptd_fixloop:
  2856 00000E65 AC                          lodsb                   ; get first byte of thread or fixup field
  2857 00000E66 49                          dec cx                  ; decrement record length to parse
  2858 00000E67 A880                        test    al,80h          ; fixup field if high bit set
  2859 00000E69 7505                        jne ptd_fix             ; fixup field
  2860                                  
  2861                                  ; thread field, parse it out
  2862 00000E6B E8A305                      call    ddl_save_thread
  2863 00000E6E EB35                        jmp SHORT ptd_chkcheck  ; check if at checksum byte
  2864                                  
  2865                                  ptd_fix:
  2866 00000E70 8A24                        mov ah,[si]          ; get high byte of locat field
  2867 00000E72 46                          inc si
  2868 00000E73 49                          dec cx                  ; decrement record length to parse
  2869 00000E74 89C3                        mov bx,ax               ; save locat field value
  2870                                  
  2871 00000E76 E86F05                      call    scan_to_targ_disp   ; scan to target displacement field, if any
  2872                                  
  2873 00000E79 88D0                        mov al,dl               ; get fix dat field
  2874 00000E7B 2404                        and al,4                ; get P bit field
  2875 00000E7D 7526                        jne ptd_chkcheck        ; set, no target displacement
  2876                                  
  2877                                  ; P bit is zero, target displacement field exists
  2878 00000E7F AD                          lodsw                   ; get target displacement word
  2879 00000E80 49                          dec cx
  2880 00000E81 49                          dec cx
  2881 00000E82 89DA                        mov dx,bx               ; save locat field
  2882 00000E84 80E303                      and bl,3                ; get 2 MSBs of data record offset
  2883 00000E87 86FB                        xchg    bh,bl           ; bx holds data record offset
  2884                                  
  2885 00000E89 80E21C                      and dl,1ch              ; get loc field
  2886 00000E8C 7407                        je  ptd_low
  2887 00000E8E 80FA08                      cmp dl,8                ; see if base fixup
  2888 00000E91 7412                        je  ptd_chkcheck        ; yes, don't add in target displacement
  2889 00000E93 EB08                        jmp SHORT ptd_notlow    ; offset or pointer
  2890                                  
  2891                                  ; low-order byte location
  2892                                  ptd_low:
  2893 00000E95 8CDA                        mov dx,ds               ; save flag value from 'and', save -> fixupp record
  2894 00000E97 8EDD                        mov ds,bp               ; save flag value from 'and', ds-> L?DATA record
  2895 00000E99 0001                        add [bx+di],al          ; add in low byte of target displacement
  2896 00000E9B EB06                        jmp SHORT ptd_2
  2897                                  
  2898                                  ; any type of location other than low-order
  2899                                  ptd_notlow:
  2900 00000E9D 8CDA                        mov dx,ds               ; save flag value from 'and', save -> fixupp record
  2901 00000E9F 8EDD                        mov ds,bp               ; save flag value from 'and', ds-> L?DATA record
  2902 00000EA1 0101                        add [bx+di],ax          ; add in target displacement word
  2903                                  
  2904                                  ptd_2:
  2905 00000EA3 8EDA                        mov ds,dx               ; restore ds -> fixupp record
  2906                                  
  2907                                  ; see if at checksum
  2908                                  ptd_chkcheck:
  2909 00000EA5 83F901                      cmp cx,1                ; check if at checksum byte
  2910 00000EA8 77BB                        ja  ptd_fixloop         ; no, loop back for next fixup/thread field
  2911                                  
  2912                                  
  2913                                  ptd_nextblk:
  2914 00000EAA A10000                      mov ax,[0]           ; get pointer to next block
  2915 00000EAD EBA3                        jmp SHORT ptd_blkloop   ; loop back and check it
  2916                                  
  2917                                  ptd_ret:
  2918 00000EAF 8EDD                        mov ds,bp               ; restore ds -> L?DATA record
  2919 00000EB1 5D                          pop bp
  2920 00000EB2 5E                          pop si
  2921 00000EB3 5F                          pop di
  2922 00000EB4 59                          pop cx
  2923 00000EB5 5B                          pop bx
  2924 00000EB6 C3                          ret
  2925                                  proc_targ_disp  ENDP
  2926                                  
  2927                                  ;*****************************
  2928                                  ;* WRITE_LNAMES_BLOCK        *
  2929                                  ;*****************************
  2930                                  
  2931                                  ; write all lnames blocks into one big lnames block for DDL module
  2932                                  ; destroys ax,bx,cx,dx
  2933                                  
  2934                                  write_lnames_block  PROC
  2935 00000EB7 E810F2                      call    update_ddl_size ; get start of lnames block (EOF)
  2936 00000EBA BF[0000]                    mov di,OFFSET ddl_symbol_lookup wrt DGROUP
  2937 00000EBD 2B06[2A00]                  sub ax,WORD PTR [module_start]    ; adjust relative to start of module
  2938 00000EC1 1B16[2C00]                  sbb dx,WORD PTR [module_start+2]  ; adjust high word
  2939 00000EC5 894502                      mov [di+2],ax           ; save low word of file position for lookup
  2940 00000EC8 895504                      mov [di+4],dx           ; save high word for lookup
  2941 00000ECB A3[9200]                    mov WORD PTR [mod_header.mh_lnames],ax   ; save pointer to start
  2942 00000ECE 8916[9400]                  mov WORD PTR [mod_header.mh_lnames+2],dx
  2943                                  
  2944 00000ED2 1E                          push    ds
  2945 00000ED3 07                          pop es                  ; es -> warplink data
  2946 00000ED4 A1[0000]                    mov ax,[first_lnamesblk_ptr]
  2947                                  
  2948                                  wlb_loop:
  2949 00000ED7 09C0                        or  ax,ax               ; see if valid lnames block
  2950 00000ED9 7439                        je  wlb_done            ; no, done
  2951                                  
  2952 00000EDB 268905                      mov [es:di],ax          ; save segment for lookup
  2953 00000EDE BA0400                      mov dx,4                ; start at offset 4 in block past 2 system words
  2954 00000EE1 B95C05                      mov cx,16*LNAMES_BLK_SIZE-4 ; write entire block except system words
  2955 00000EE4 8ED8                        mov ds,ax               ; ds:dx -> write buffer
  2956 00000EE6 2B0E0000                    sub cx,[0]           ; subtract off unused space
  2957 00000EEA B440                        mov ah,40h              ; write to device
  2958 00000EEC CD21                        int 21h
  2959 00000EEE 722A                        jc  wlb_error           ; error writing to file
  2960 00000EF0 50                      	push ax
  2961 00000EF1 39C8                    	cmp ax, cx
  2962 00000EF3 B82700                  	mov ax, 27h			; insufficient disk space error
  2963 00000EF6 7522                    	jne wlb_error
  2964 00000EF8 58                      	pop ax
  2965                                  
  2966 00000EF9 26034502                    add ax,[es:di+2]        ; compute next lookup file position
  2967 00000EFD 26894508                    mov [es:di+8],ax        ; save it
  2968 00000F01 268B4504                    mov ax,[es:di+4]
  2969 00000F05 83D000                      adc ax,0                ; carry to high word
  2970 00000F08 2689450A                    mov [es:di+10],ax
  2971 00000F0C 83C706                      add di,6                ; move to next lookup position
  2972 00000F0F A10200                      mov ax,[2]           ; get pointer to next block, if any
  2973 00000F12 EBC3                        jmp SHORT wlb_loop      ; loop back and write it
  2974                                  
  2975                                  wlb_done:
  2976 00000F14 B8[ssss]                    mov ax,DGROUP
  2977 00000F17 8ED8                        mov ds,ax               ; restore ds -> warplink data
  2978 00000F19 C3                          ret
  2979                                  
  2980                                  wlb_error:
  2981 00000F1A E9(0000)                    jmp NEAR PTR dos_error  ; error writing to file
  2982                                  
  2983                                  write_lnames_block  ENDP
  2984                                  
  2985                                  ;*****************************
  2986                                  ;* WRITE_SYMBOLS_BLOCK       *
  2987                                  ;*****************************
  2988                                  
  2989                                  ; write all pubdef (symbol) names blocks into one big symbols block for DDL module
  2990                                  ; destroys ax,bx,cx,dx,di,es
  2991                                  
  2992                                  write_symbols_block PROC
  2993 00000F1D E8AAF1                      call    update_ddl_size ; get start of symbol names block (EOF)
  2994 00000F20 BF[0000]                    mov di,OFFSET ddl_symbol_lookup wrt DGROUP
  2995 00000F23 2B06[2A00]                  sub ax,WORD PTR [module_start]    ; adjust relative to start of module
  2996 00000F27 1B16[2C00]                  sbb dx,WORD PTR [module_start+2]  ; adjust high word
  2997 00000F2B 894502                      mov [di+2],ax           ; save low word of file position for lookup
  2998 00000F2E 895504                      mov [di+4],dx           ; save high word for lookup
  2999 00000F31 A3[9E00]                    mov WORD PTR [mod_header.mh_symbols],ax   ; save pointer to start
  3000 00000F34 8916[A000]                  mov WORD PTR [mod_header.mh_symbols+2],dx
  3001                                  
  3002 00000F38 1E                          push    ds
  3003 00000F39 07                          pop es                  ; es -> warplink data
  3004 00000F3A A1[0000]                    mov ax,[first_pdnameblk_ptr]
  3005                                  
  3006                                  wsym_loop:
  3007 00000F3D 09C0                        or  ax,ax               ; see if valid lnames block
  3008 00000F3F 7439                        je  wsym_done           ; no, done
  3009                                  
  3010 00000F41 268905                      mov [es:di],ax          ; save segment for lookup
  3011 00000F44 BA0400                      mov dx,4                ; start at offset 4 in block past 2 system words
  3012 00000F47 B90C0A                      mov cx,16*PUB_NAMBLK_SIZE-4 ; write entire block except system words
  3013 00000F4A 8ED8                        mov ds,ax               ; ds:dx -> write buffer
  3014 00000F4C 2B0E0000                    sub cx,[0]           ; subtract off unused space
  3015 00000F50 B440                        mov ah,40h              ; write to device
  3016 00000F52 CD21                        int 21h
  3017 00000F54 722A                        jc  wsym_error          ; error writing to file
  3018 00000F56 50                      	push ax
  3019 00000F57 39C8                    	cmp ax, cx
  3020 00000F59 B82700                  	mov ax, 27h			; insufficient disk space error
  3021 00000F5C 7522                    	jne wsym_error
  3022 00000F5E 58                      	pop ax
  3023                                  
  3024 00000F5F 26034502                    add ax,[es:di+2]        ; compute next lookup file position
  3025 00000F63 26894508                    mov [es:di+8],ax        ; save it
  3026 00000F67 268B4504                    mov ax,[es:di+4]
  3027 00000F6B 83D000                      adc ax,0                ; carry to high word
  3028 00000F6E 2689450A                    mov [es:di+10],ax
  3029 00000F72 83C706                      add di,6                ; move to next lookup position
  3030 00000F75 A10200                      mov ax,[2]           ; get pointer to next block, if any
  3031 00000F78 EBC3                        jmp SHORT wsym_loop     ; loop back and write it
  3032                                  
  3033                                  wsym_done:
  3034 00000F7A B8[ssss]                    mov ax,DGROUP
  3035 00000F7D 8ED8                        mov ds,ax               ; restore ds -> warplink data
  3036 00000F7F C3                          ret
  3037                                  
  3038                                  wsym_error:
  3039 00000F80 E9(0000)                    jmp NEAR PTR dos_error  ; error writing to file
  3040                                  
  3041                                  write_symbols_block ENDP
  3042                                  
  3043                                  ;*****************************
  3044                                  ;* WRITE_PUBDEF_BLOCK        *
  3045                                  ;*****************************
  3046                                  
  3047                                  ; write pubdefs into one block, update high/low, name pointers
  3048                                  ; destroys ax,bx,cx,dx,di,si,es
  3049                                  
  3050                                  write_pubdef_block  PROC
  3051 00000F83 E844F1                      call    update_ddl_size ; get start of pubdef block (EOF)
  3052 00000F86 2B06[2A00]                  sub ax,WORD PTR [module_start]    ; adjust relative to start of module
  3053 00000F8A 1B16[2C00]                  sbb dx,WORD PTR [module_start+2]  ; adjust high word
  3054 00000F8E A3[A200]                    mov WORD PTR [mod_header.mh_pubdef],ax   ; save pointer to start
  3055 00000F91 8916[A400]                  mov WORD PTR [mod_header.mh_pubdef+2],dx
  3056                                  
  3057 00000F95 C606[0000]00                mov byte [pubcom_flag],0       ; flag parsing publics
  3058 00000F9A E8B600                      call    sort_pubdefs
  3059 00000F9D 8B0E[0600]                  mov cx,[pubcount]         ; get count of entries in sort buffer
  3060 00000FA1 890E[8C00]                  mov [mod_header.mh_pubcount],cx   ; save count of publics
  3061 00000FA5 09C9                        or  cx,cx
  3062 00000FA7 7501                        jne wpb_altent          ; entries exist
  3063 00000FA9 C3                          ret                     ; no entries
  3064                                  
  3065                                  ; alternate entry for code shared with write_comdef_block
  3066                                  wpb_altent:
  3067 00000FAA BE[0000]                    mov si,OFFSET ddl_hold_buff wrt DGROUP  ; si -> holding buffer for pubdefs prior to write
  3068 00000FAD 31DB                        xor bx,bx               ; bx offsets into sort buffer
  3069                                  
  3070                                  wpb_mainloop:
  3071 00000FAF 8E06[0000]                  mov es,[allocation_base]
  3072 00000FB3 268E07                      mov es,[es:bx]          ; es -> symbol pubdef entry
  3073 00000FB6 8CC2                        mov dx,es               ; save -> entry
  3074 00000FB8 26A10600                    mov ax,[es:6]           ; get segment of pubdef name
  3075 00000FBC BF[0000]                    mov di,OFFSET ddl_symbol_lookup wrt DGROUP  ; di -> start of lookup table
  3076 00000FBF 1E                          push    ds
  3077 00000FC0 07                          pop es                  ; es -> warplink data
  3078                                  
  3079                                  wpb_searchloop:
  3080 00000FC1 AF                          scasw                   ; search for segment entry in lookup table
  3081 00000FC2 7405                        je  wpb_found           ; found the entry
  3082 00000FC4 83C704                      add di,4                ; bump to next lookup entry
  3083 00000FC7 EBF8                        jmp SHORT wpb_searchloop    ; keep looking
  3084                                  
  3085                                  wpb_found:
  3086 00000FC9 268B05                      mov ax,[es:di]          ; get low word of file position
  3087 00000FCC 268B7D02                    mov di,[es:di+2]        ; get high word
  3088                                  
  3089                                  ; file position corresponding to segment in di:ax
  3090 00000FD0 8EC2                        mov es,dx               ; restore es -> block entry
  3091 00000FD2 2603060400                  add ax,[es:4]           ; add in pubdef name offset
  3092 00000FD7 83D700                      adc di,0                ; carry to high word
  3093 00000FDA 83E804                      sub ax,4                ; adjust for 2 system info words not written
  3094 00000FDD 83DF00                      sbb di,0                ; borrow to high word
  3095                                  
  3096 00000FE0 2B06[9E00]                  sub ax,WORD PTR [mod_header.mh_symbols]    ; make relative to start of symbols block
  3097 00000FE4 1B3E[A000]                  sbb di,WORD PTR [mod_header.mh_symbols+2]
  3098                                  
  3099 00000FE8 894404                      mov [si+4],ax           ; save low file position
  3100 00000FEB 897C06                      mov [si+6],di           ; save high file position
  3101 00000FEE 26A10000                    mov ax,[es:0]           ; save segment index (not pointer since DDL)
  3102 00000FF2 8904                        mov [si],ax
  3103 00000FF4 26A10200                    mov ax,[es:2]           ; save frame number/group index/communal length high word
  3104 00000FF8 894402                      mov [si+2],ax
  3105 00000FFB 26A10800                    mov ax,[es:8]           ; save public offset/communal length low word
  3106 00000FFF 894408                      mov [si+8],ax
  3107 00001002 26A10E00                    mov ax,[es:14]          ; save definition and general flags
  3108 00001006 89440E                      mov [si+14],ax
  3109                                  
  3110                                  ; update symbol name low segment pointer at [es:10],
  3111                                  ; symbol name high segment pointer at [es:12]
  3112                                  ; pointers must be converted by dividing by 6 and multiplying by 16 (10h)
  3113 00001009 8E06[0000]                  mov es,[allocation_base]
  3114 0000100D 268B4702                    mov ax,[es:bx+2]        ; get low pointer
  3115 00001011 31D2                        xor dx,dx
  3116 00001013 BF0600                      mov di,6
  3117 00001016 F7F7                        div di                  ; adjust for sort buffer 6 byte entry pointers
  3118 00001018 D1E0                        shl ax,1                ; adjust for symbol entry length of 16 bytes, x2
  3119 0000101A D1E0                        shl ax,1                ; x4
  3120 0000101C D1E0                        shl ax,1                ; x8
  3121 0000101E D1E0                        shl ax,1                ; x16
  3122 00001020 89440A                      mov [si+10],ax          ; save adjusted low pointer
  3123 00001023 268B4704                    mov ax,[es:bx+4]        ; get high pointer
  3124 00001027 31D2                        xor dx,dx
  3125 00001029 F7F7                        div di                  ; adjust for sort buffer 6 byte entry pointers
  3126 0000102B D1E0                        shl ax,1                ; adjust for symbol entry length of 16 bytes, x2
  3127 0000102D D1E0                        shl ax,1                ; x4
  3128 0000102F D1E0                        shl ax,1                ; x8
  3129 00001031 D1E0                        shl ax,1                ; x16
  3130 00001033 89440C                      mov [si+12],ax          ; save adjusted high pointer
  3131 00001036 80640FF5                    and BYTE PTR [si+15],0f5h   ; shut off extdef/comdef flag, overlay class bits
  3132                                  
  3133 0000103A 83C306                      add bx,6                ; move to next position in sort buffer
  3134 0000103D 83C610                      add si,16               ; move to next position in holding buffer
  3135 00001040 81FE[F207]                  cmp si,2034+OFFSET ddl_hold_buff wrt DGROUP ; see if holding buffer is full
  3136 00001044 7203                        jb  wpb_nextent         ; no
  3137                                  
  3138 00001046 E8A201                      call    flush_hold_buff ; flush the holding buffer
  3139                                  
  3140                                  wpb_nextent:
  3141 00001049 49                          dec cx
  3142 0000104A E303                        jcxz    wpb_out         ; done with all entries
  3143 0000104C E960FF                      jmp NEAR PTR wpb_mainloop   ; loop until all entries in sort table are finished
  3144                                  
  3145                                  wpb_out:
  3146 0000104F E89901                      call    flush_hold_buff ; flush the pubdef block to the DDL file
  3147                                  
  3148                                  wpb_ret:
  3149 00001052 C3                          ret
  3150                                  write_pubdef_block  ENDP
  3151                                  
  3152                                  ;*****************************
  3153                                  ;* SORT_PUBDEFS              *
  3154                                  ;*****************************
  3155                                  
  3156                                  ; sort all the public or communal declarations into 3-word entries
  3157                                  ;  [segment pointer][low name pointer][high name pointer]
  3158                                  ; destroys ax,bx,cx,dx,di,si,es
  3159                                  
  3160                                  sort_pubdefs    PROC
  3161                                  
  3162                                  ; compute upper boundary of sort area
  3163 00001053 A1[0000]                    mov ax,[allocation_top]
  3164 00001056 2B06[0000]                  sub ax,[allocation_base]  ; compute free memory segments
  3165 0000105A D1E0                        shl ax,1                ; convert to bytes, x2
  3166 0000105C 720C                        jc  sp_over             ; overflow, set ax boundary to highest possible
  3167 0000105E D1E0                        shl ax,1                ; x4
  3168 00001060 7208                        jc  sp_over
  3169 00001062 D1E0                        shl ax,1                ; x8
  3170 00001064 7204                        jc  sp_over
  3171 00001066 D1E0                        shl ax,1                ; x16
  3172 00001068 7303                        jnc sp_2                ; ax holds upper boundary of free memory
  3173                                  
  3174                                  sp_over:
  3175 0000106A B8FAFF                      mov ax,65530            ; set boundary to highest possible
  3176                                  
  3177                                  sp_2:
  3178 0000106D A3[1600]                    mov [sort_buff_bound],ax  ; save sort buffer boundary
  3179 00001070 31DB                        xor bx,bx               ; init offset into sort buffer
  3180                                  ;**    mov block_flag,2        ; init to public entry parsing
  3181                                  
  3182                                  sp_mainloop:
  3183 00001072 A1[0000]                    mov ax,[first_pdeclblk_ptr]   ; get pointer to first public declarations block
  3184                                  
  3185                                  sp_blkloop:
  3186 00001075 09C0                        or  ax,ax               ; see if valid block
  3187 00001077 743B                        je  sp_done             ; no
  3188                                  
  3189 00001079 8EC0                        mov es,ax               ; es -> declarations block
  3190 0000107B 50                          push    ax              ; save -> declarations block
  3191 0000107C 268B0E0000                  mov cx,[es:0]           ; get count of entries in block
  3192 00001081 E32A                        jcxz    sp_nextblock    ; no entries
  3193 00001083 40                          inc ax
  3194 00001084 89C2                        mov dx,ax               ; dx -> first entry in block
  3195                                  
  3196                                  sp_entloop:
  3197 00001086 8EC2                        mov es,dx               ; es -> block entry
  3198 00001088 26A00F00                    mov al,[es:15]          ; get general flags
  3199 0000108C 88C4                        mov ah,al               ; save status
  3200                                  
  3201 0000108E 26A00E00                    mov al,[es:14]          ; get definitions flag
  3202 00001092 2403                        and al,3                ; mask off unneeded bits
  3203 00001094 803E[0000]00                cmp byte [pubcom_flag],0       ; see if parsing publics or communals
  3204 00001099 740B                        je  sp_public           ; publics
  3205                                  
  3206                                  ; parsing communals
  3207 0000109B 3C01                        cmp al,1                ; see if communal/extdef
  3208 0000109D 750B                        jne sp_nextent          ; no
  3209 0000109F 80E440                      and ah,40h              ; see if communal
  3210 000010A2 7406                        je  sp_nextent          ; no
  3211 000010A4 EB0F                        jmp SHORT sp_match      ; yes
  3212                                  
  3213                                  ; parsing publics
  3214                                  sp_public:
  3215 000010A6 3C02                        cmp al,2                ; see if public or absolute
  3216 000010A8 730B                        jae sp_match            ; yes
  3217                                  
  3218                                  sp_nextent:
  3219 000010AA 42                          inc dx                  ; move to next entry in block
  3220 000010AB E2D9                        loop    sp_entloop      ; go through all entries in loop
  3221                                  
  3222                                  sp_nextblock:
  3223 000010AD 07                          pop es                  ; restore es -> declarations block
  3224 000010AE 26A10200                    mov ax,[es:2]           ; get pointer to next block, if any
  3225 000010B2 EBC1                        jmp SHORT sp_blkloop
  3226                                  
  3227                                  sp_done:
  3228                                  
  3229                                  sp_ret:
  3230 000010B4 C3                          ret
  3231                                  
  3232                                  ; matched communal or public, update count and sort buffer
  3233                                  sp_match:
  3234 000010B5 803E[0000]00                cmp byte [pubcom_flag],0       ; see if parsing publics or communals
  3235 000010BA 7406                        je  sp_bumppub          ; public, bump public count
  3236                                  
  3237 000010BC FF06[0800]                  inc word [comcount]            ; bump count of communal in module
  3238 000010C0 EB04                        jmp SHORT sp_3
  3239                                  
  3240                                  sp_bumppub:
  3241 000010C2 FF06[0600]                  inc word [pubcount]            ; bump count of publics in module
  3242                                  
  3243                                  sp_3:
  3244 000010C6 268B3E0600                  mov di,[es:6]           ; get segment of name pointer
  3245 000010CB 268B360400                  mov si,[es:4]           ; get offset of name pointer
  3246 000010D0 8E06[0000]                  mov es,[allocation_base]  ; es:bx -> sort buffer entry
  3247 000010D4 268917                      mov [es:bx],dx          ; save -> this entry
  3248 000010D7 31C0                        xor ax,ax
  3249 000010D9 26894702                    mov WORD PTR [es:bx+2],ax   ; zero low/high pointers
  3250 000010DD 26894704                    mov WORD PTR [es:bx+4],ax
  3251 000010E1 8CC0                        mov ax,es               ; ax holds allocation base
  3252 000010E3 51                          push    cx              ; save critical register
  3253 000010E4 09DB                        or  bx,bx               ; see if first entry
  3254 000010E6 7443                        je  sp_saved            ; yes, no binary tree to search
  3255                                  
  3256                                  ; di:si -> name, place in binary tree in sort buffer
  3257 000010E8 8EDF                        mov ds,di               ; ds:si -> name
  3258 000010EA 31FF                        xor di,di               ; di == search offset in sort buffer
  3259                                  
  3260                                  sp_searchloop:
  3261 000010EC 56                          push    si              ; save -> start of name
  3262 000010ED 57                          push    di              ; save sort buffer search offset
  3263 000010EE 268E05                      mov es,[es:di]          ; es -> entry in tree
  3264 000010F1 26C43E0400                  les di,[es:4]           ; es:di -> name to compare against
  3265                                  
  3266                                  sp_byteloop:
  3267 000010F6 A6                          cmpsb                   ; compare new name and search entry namec
  3268 000010F7 74FD                        je  sp_byteloop         ; bytes match, loop for next byte test
  3269 000010F9 7204                        jc  sp_setlow           ; old name greater than new name
  3270 000010FB B101                        mov cl,1                ; set higher flag
  3271 000010FD EB02                        jmp SHORT sp_chkflag
  3272                                  
  3273                                  sp_setlow:
  3274 000010FF 30C9                        xor cl,cl               ; set lower flag
  3275                                  
  3276                                  sp_chkflag:
  3277 00001101 5F                          pop di
  3278 00001102 5E                          pop si
  3279                                  
  3280 00001103 8EC0                        mov es,ax               ; es:di -> last searched sort buffer entry
  3281 00001105 08C9                        or  cl,cl               ; see if name was lower or higher than search entry
  3282 00001107 7412                        je  sp_low              ; lower
  3283                                  
  3284                                  ; new name was higher than search entry
  3285                                  sp_high:
  3286 00001109 268B4D04                    mov cx,[es:di+4]        ; get pointer to high name
  3287 0000110D 09C9                        or  cx,cx               ; make sure valid pointer
  3288 0000110F 7404                        je  sp_savehiptr        ; no, save pointer to current entry as high pointer
  3289 00001111 89CF                        mov di,cx               ; di -> next entry to try
  3290 00001113 EBD7                        jmp SHORT sp_searchloop
  3291                                  
  3292                                  sp_savehiptr:
  3293 00001115 26895D04                    mov [es:di+4],bx        ; update search entry high pointer to current
  3294 00001119 EB10                        jmp SHORT sp_saved
  3295                                  
  3296                                  ; new name was lower than search entry
  3297                                  sp_low:
  3298 0000111B 268B4D02                    mov cx,[es:di+2]        ; get pointer to low name
  3299 0000111F 09C9                        or  cx,cx               ; make sure valid pointer
  3300 00001121 7404                        je  sp_saveloptr        ; no, save pointer to current entry as low pointer
  3301 00001123 89CF                        mov di,cx               ; di -> next entry to try
  3302 00001125 EBC5                        jmp SHORT sp_searchloop
  3303                                  
  3304                                  sp_saveloptr:
  3305 00001127 26895D02                    mov [es:di+2],bx        ; update search entry low pointer to current
  3306                                  
  3307                                  sp_saved:
  3308 0000112B 59                          pop cx                  ; restore critical register
  3309 0000112C B8[ssss]                    mov ax,DGROUP
  3310 0000112F 8ED8                        mov ds,ax               ; restore ds -> warplink data
  3311 00001131 83C306                      add bx,6                ; bump to next
  3312 00001134 3B1E[1600]                  cmp bx,[sort_buff_bound]  ; make sure sort buffer has not overflowed
  3313 00001138 7303                        jae sp_memerr           ; overflow
  3314 0000113A E96DFF                      jmp NEAR PTR sp_nextent ; move to next entry
  3315                                  
  3316                                  ; overflow of boundary, too many publics
  3317                                  sp_memerr:
  3318 0000113D B80800                      mov ax,8                ; force out of memory error
  3319 00001140 E9(0000)                    jmp NEAR PTR dos_error
  3320                                  
  3321                                  sort_pubdefs    ENDP
  3322                                  
  3323                                  ;*****************************
  3324                                  ;* WRITE_COMDEF_BLOCK        *
  3325                                  ;*****************************
  3326                                  
  3327                                  ; write comdefs into one block, update high/low, name pointers
  3328                                  ; destroys ax,bx,cx,dx,di,si,es
  3329                                  
  3330                                  write_comdef_block  PROC
  3331 00001143 E884EF                      call    update_ddl_size ; get start of comdef block (EOF)
  3332 00001146 2B06[2A00]                  sub ax,WORD PTR [module_start]    ; adjust relative to start of module
  3333 0000114A 1B16[2C00]                  sbb dx,WORD PTR [module_start+2]  ; adjust high word
  3334 0000114E A3[A600]                    mov WORD PTR [mod_header.mh_comdef],ax   ; save pointer to start
  3335 00001151 8916[A800]                  mov WORD PTR [mod_header.mh_comdef+2],dx
  3336                                  
  3337 00001155 C606[0000]01                mov byte [pubcom_flag],1       ; flag parsing communals
  3338 0000115A E8F6FE                      call    sort_pubdefs
  3339 0000115D 8B0E[0800]                  mov cx,[comcount]         ; get count of entries in sort buffer
  3340 00001161 890E[8E00]                  mov [mod_header.mh_comcount],cx   ; save count of communals
  3341 00001165 E303                        jcxz    wcb_ret         ; no entries
  3342 00001167 E940FE                      jmp NEAR PTR wpb_altent ; go to code shared with write_pubdef_block
  3343                                  
  3344                                  wcb_ret:
  3345 0000116A C3                          ret
  3346                                  write_comdef_block  ENDP
  3347                                  
  3348                                  ;*****************************
  3349                                  ;* WRITE_EXTDEF_BLOCK        *
  3350                                  ;*****************************
  3351                                  
  3352                                  ; write extdefs into one block, update name pointers
  3353                                  ; destroys ax,bx,cx,dx,di,si,es
  3354                                  
  3355                                  write_extdef_block  PROC
  3356 0000116B E85CEF                      call    update_ddl_size ; get start of extdef block (EOF)
  3357 0000116E 2B06[2A00]                  sub ax,WORD PTR [module_start]    ; adjust relative to start of module
  3358 00001172 1B16[2C00]                  sbb dx,WORD PTR [module_start+2]  ; adjust high word
  3359 00001176 A3[AA00]                    mov WORD PTR [mod_header.mh_extdef],ax   ; save pointer to start
  3360 00001179 8916[AC00]                  mov WORD PTR [mod_header.mh_extdef+2],dx
  3361 0000117D BE[0000]                    mov si,OFFSET ddl_hold_buff wrt DGROUP  ; si -> holding buffer for extdefs prior to write
  3362                                  
  3363 00001180 BB[0000]                    mov bx,OFFSET ext_defent_indptr wrt DGROUP  ; index into extdef/comdef entries
  3364 00001183 8B0E[0000]                  mov cx,[current_extdef]   ; get total count of entries in array
  3365 00001187 E358                        jcxz    web_done        ; no entries
  3366                                  
  3367                                  web_entloop:
  3368 00001189 8E07                        mov es,[bx]          ; es -> entry's public declaration
  3369                                  
  3370                                  ; valid extdef (or comdef), keep it
  3371 0000118B 2680260F00FD                and BYTE PTR [es:15],0fdh   ; shut off extdef/comdef flag bit
  3372 00001191 FF06[0A00]                  inc word [extcount]            ; bump count of externals in module
  3373 00001195 26A10600                    mov ax,[es:6]           ; get segment of extdef name
  3374 00001199 BF[0000]                    mov di,OFFSET ddl_symbol_lookup wrt DGROUP  ; di -> start of lookup table
  3375 0000119C 1E                          push    ds
  3376 0000119D 07                          pop es                  ; es -> warplink data
  3377                                  
  3378                                  web_searchloop:
  3379 0000119E AF                          scasw                   ; search for segment entry in lookup table
  3380 0000119F 7405                        je  web_found           ; found the entry
  3381 000011A1 83C704                      add di,4                ; bump to next lookup entry
  3382 000011A4 EBF8                        jmp SHORT web_searchloop    ; keep looking
  3383                                  
  3384                                  web_found:
  3385 000011A6 268B05                      mov ax,[es:di]          ; get low word of file position
  3386 000011A9 268B7D02                    mov di,[es:di+2]        ; get high word
  3387                                  
  3388                                  ; file position corresponding to segment in di:ax
  3389 000011AD 8E07                        mov es,[bx]          ; restore es -> block entry
  3390 000011AF 2603060400                  add ax,[es:4]           ; add in extdef name offset
  3391 000011B4 83D700                      adc di,0                ; carry to high word
  3392 000011B7 83E804                      sub ax,4                ; adjust for 2 system info words not written
  3393 000011BA 83DF00                      sbb di,0                ; borrow to high word
  3394                                  
  3395 000011BD 2B06[9E00]                  sub ax,WORD PTR [mod_header.mh_symbols]    ; make relative to start of symbols block
  3396 000011C1 1B3E[A000]                  sbb di,WORD PTR [mod_header.mh_symbols+2]
  3397                                  
  3398 000011C5 8904                        mov [si],ax             ; save low file position
  3399 000011C7 897C02                      mov [si+2],di           ; save high file position
  3400 000011CA 26A10E00                    mov ax,[es:14]          ; get flag bytes
  3401 000011CE 894404                      mov [si+4],ax           ; save them
  3402                                  
  3403 000011D1 83C606                      add si,6                ; move to next position in holding buffer
  3404 000011D4 81FE[FC07]                  cmp si,2044+OFFSET ddl_hold_buff wrt DGROUP ; see if holding buffer is full
  3405 000011D8 7203                        jb  web_nextent         ; no
  3406                                  
  3407 000011DA E80E00                      call    flush_hold_buff ; flush the holding buffer
  3408                                  
  3409                                  web_nextent:
  3410 000011DD 43                          inc bx                  ; move to next word entry in block
  3411 000011DE 43                          inc bx
  3412 000011DF E2A8                        loop    web_entloop     ; go through all entries in loop
  3413                                  
  3414                                  web_done:
  3415 000011E1 E80700                      call    flush_hold_buff ; flush the extdef block to the DDL file
  3416 000011E4 A1[0A00]                    mov ax,[extcount]
  3417 000011E7 A3[9000]                    mov [mod_header.mh_extcount],ax   ; save count of externals
  3418 000011EA C3                          ret
  3419                                  write_extdef_block  ENDP
  3420                                  
  3421                                  ;*****************************
  3422                                  ;* FLUSH_HOLD_BUFF           *
  3423                                  ;*****************************
  3424                                  
  3425                                  ; flush the holding block to DDL file
  3426                                  ; destroys ax,si
  3427                                  ; returns si -> start of hold buffer
  3428                                  
  3429                                  flush_hold_buff PROC
  3430 000011EB 53                          push    bx              ; save critical register
  3431 000011EC 51                          push    cx
  3432 000011ED 52                          push    dx
  3433                                  
  3434 000011EE BA[0000]                    mov dx,OFFSET ddl_hold_buff wrt DGROUP
  3435 000011F1 29D6                        sub si,dx               ; compute bytes to write
  3436 000011F3 89F1                        mov cx,si
  3437 000011F5 E311                        jcxz    feb_out         ; no bytes to write
  3438 000011F7 8B1E[0000]                  mov bx,[exe_handle]
  3439 000011FB B440                        mov ah,40h              ; write to device
  3440 000011FD CD21                        int 21h
  3441 000011FF 7232                        jc  dp_error            ; error writing to file
  3442 00001201 39C8                    	cmp ax, cx
  3443 00001203 B82700                  	mov ax, 27h			; insufficient disk space error
  3444 00001206 752B                    	jne dp_error
  3445                                  
  3446                                  feb_out:
  3447 00001208 BE[0000]                    mov si,OFFSET ddl_hold_buff wrt DGROUP  ; reset di -> start of holding buffer
  3448 0000120B 5A                          pop dx                  ; restore critical register
  3449 0000120C 59                          pop cx
  3450 0000120D 5B                          pop bx
  3451 0000120E C3                          ret
  3452                                  flush_hold_buff ENDP
  3453                                  
  3454                                  ;*****************************
  3455                                  ;* DDL_PAD                   *
  3456                                  ;*****************************
  3457                                  
  3458                                  ; pad a module out to 16-byte boundary with zeros
  3459                                  ; returns bx==file handle
  3460                                  ; destroys ax,bx,cx,dx
  3461                                  
  3462                                  ddl_pad PROC
  3463 0000120F E8B8EE                      call    update_ddl_size ; get current file size
  3464 00001212 8B0E[2600]                  mov cx,WORD PTR [ddl_filesize]    ; get low word of file size
  3465 00001216 83E10F                      and cx,15               ; get remainder from sixteen byte boundary
  3466 00001219 E317                        jcxz    dp_ret          ; no padding needed
  3467 0000121B B81000                      mov ax,16
  3468 0000121E 29C8                        sub ax,cx               ; ax holds padding necessary
  3469 00001220 89C1                        mov cx,ax               ; get bytes to write in cx
  3470 00001222 BA[0000]                    mov dx,OFFSET zero_table wrt DGROUP
  3471 00001225 B440                        mov ah,40h
  3472 00001227 CD21                        int 21h
  3473 00001229 7208                        jc  dp_error            ; error writing to file
  3474 0000122B 39C8                    	cmp ax, cx
  3475 0000122D B82700                  	mov ax, 27h			; insufficient disk space error
  3476 00001230 7501                    	jne dp_error
  3477                                  
  3478                                  dp_ret:
  3479 00001232 C3                          ret
  3480                                  
  3481                                  dp_error:
  3482 00001233 E9(0000)                    jmp NEAR PTR dos_error  ; error writing to file
  3483                                  
  3484                                  ddl_pad ENDP
  3485                                  
  3486                                  ;*****************************
  3487                                  ;* WRITE_DDL_MODHEAD         *
  3488                                  ;*****************************
  3489                                  
  3490                                  ; write module header to DDL file
  3491                                  ; destroys ax,bx,cx,dx
  3492                                  
  3493                                  write_ddl_modhead   PROC
  3494 00001236 8B1E[0000]                  mov bx,[exe_handle]
  3495 0000123A BA[8200]                    mov dx,OFFSET mod_header wrt DGROUP ; ds:dx -> write buffer area
  3496 0000123D B94000                      mov cx,MOD_HEADER_SIZE  ; size of module header
  3497 00001240 B440                        mov ah,40h              ; write to file
  3498 00001242 CD21                        int 21h
  3499 00001244 72ED                        jc  dp_error            ; error writing to file
  3500 00001246 39C8                    	cmp ax, cx
  3501 00001248 B82700                  	mov ax, 27h			; insufficient disk space error
  3502 0000124B 75E6                    	jne dp_error
  3503                                  
  3504 0000124D C3                          ret
  3505                                  write_ddl_modhead   ENDP
  3506                                  
  3507                                  ;*****************************
  3508                                  ;* PARSE_DDL_OPTION          *
  3509                                  ;*****************************
  3510                                  
  3511                                  ; parse DDL option
  3512                                  ; ds:si -> second  char of option (past 'D')
  3513                                  ; cx -> start of option
  3514                                  ; destroys ax,dx,di,es
  3515                                  ; updates si
  3516                                  
  3517                                  parse_ddl_option    PROC
  3518 0000124E 8A24                        mov ah,[si]             ; peek at next char
  3519 00001250 80FC44                      cmp ah,'D'              ; see if possible /ddl option
  3520 00001253 7413                        je  pdo_chkddl          ; possible
  3521 00001255 80FC64                      cmp ah,'d'              ; check lowercase option
  3522 00001258 740E                        je  pdo_chkddl          ; possible
  3523 0000125A 80FC4D                      cmp ah,'M'              ; see if /dm option
  3524 0000125D 741D                        je  pdo_chkdbm          ; possible
  3525 0000125F 80FC6D                      cmp ah,'m'              ; check lowercase option
  3526 00001262 7418                        je  pdo_chkdbm          ; possible
  3527                                  
  3528                                  ; assume DOSSEG option
  3529 00001264 A2[0000]                    mov [is_dosseg],al        ; set dosseg segment ordering flag
  3530 00001267 C3                          ret
  3531                                  
  3532                                  pdo_chkddl:
  3533 00001268 AC                          lodsb                   ; gobble 'd'
  3534 00001269 AC                          lodsb                   ; get char following 'dd'
  3535 0000126A 3C4C                        cmp al,'L'              ; see if /ddl option
  3536 0000126C 7404                        je  pdo_ddl             ; yes
  3537 0000126E 3C6C                        cmp al,'l'              ; check lowercase option
  3538 00001270 7504                        jne pdo_bad             ; no, bad option
  3539                                  
  3540                                  pdo_ddl:
  3541 00001272 A2[0000]                    mov [is_ddl],al           ; flag ddl creation
  3542 00001275 C3                          ret
  3543                                  
  3544                                  pdo_bad:                    ; bad DDL option specified
  3545 00001276 B80500                      mov ax,BAD_OPTION_ERR   ; error value
  3546 00001279 E9(0000)                    jmp NEAR PTR link_error ; transfer control to error handler
  3547                                  
  3548                                  pdo_chkdbm:
  3549 0000127C AC                          lodsb                   ; gobble 'B' or 'M'
  3550 0000127D 80E4DF                      and ah,0dfh             ; force option char to uppercase
  3551 00001280 AC                          lodsb                   ; get colon following DDL option char
  3552 00001281 3C3A                        cmp al,':'              ; must be colon
  3553 00001283 75F1                        jne pdo_bad             ; not a colon
  3554                                  
  3555 00001285 80FC4D                      cmp ah,'M'              ; see if DDL manager name
  3556 00001288 7400                        je  pdo_getfile         ; yes
  3557                                  
  3558                                  ; DDL manager data file name
  3559                                  pdo_getfile:
  3560 0000128A 8CD8                        mov ax,ds
  3561 0000128C 8EC0                        mov es,ax               ; es -> warplink data segment
  3562 0000128E BF[0000]                    mov di,OFFSET ddldat_filename wrt DGROUP    ; es:di -> place for DDL manager name
  3563 00001291 89FA                        mov dx,di               ; ds:dx -> file spec
  3564                                  
  3565                                  pdo_loop:
  3566 00001293 AC                          lodsb                   ; get name char
  3567 00001294 3C20                        cmp al,' '              ; see if whitespace char
  3568 00001296 761B                        jbe pdo_done            ; yes, done
  3569 00001298 3C2C                        cmp al,','              ; see if comma
  3570 0000129A 7417                        je  pdo_done            ; done
  3571 0000129C 3C2F                        cmp al,'/'              ; see if option char
  3572 0000129E 7413                        je  pdo_done            ; done
  3573 000012A0 3C28                        cmp al,'('              ; see if left paren, begin overlay
  3574 000012A2 740F                        je  pdo_done            ; done
  3575 000012A4 3C29                        cmp al,')'              ; see if right paren, end overlay
  3576 000012A6 740B                        je  pdo_done            ; done
  3577 000012A8 3C40                        cmp al,'@'              ; see if @ (response file)
  3578 000012AA 7407                        je  pdo_done            ; done
  3579 000012AC 3C3B                        cmp al,';'              ; see if semicolon terminator
  3580 000012AE 7403                        je  pdo_done            ; done
  3581                                  
  3582 000012B0 AA                          stosb                   ; name char, transfer it
  3583 000012B1 EBE0                        jmp SHORT pdo_loop      ; get next char
  3584                                  
  3585                                  pdo_done:
  3586 000012B3 4E                          dec si                  ; drop si back to -> terminating char
  3587 000012B4 30C0                        xor al,al               ; null terminate string
  3588 000012B6 AA                          stosb                   ; transfer it
  3589 000012B7 B80043                      mov ax,4300h            ; get file attributes (check for file existence)
  3590 000012BA CD21                        int 21h
  3591 000012BC 7201                        jc  pdo_notfound        ; didn't find manager file/DOS error
  3592 000012BE C3                          ret                     ; done
  3593                                  
  3594                                  pdo_notfound:
  3595 000012BF E9(0000)                    jmp NEAR PTR dos_error  ; no, dos error
  3596                                  
  3597                                  parse_ddl_option    ENDP
  3598                                  
  3599                                  ;*****************************
  3600                                  ;* DDL_DATAREC               *
  3601                                  ;*****************************
  3602                                  
  3603                                  ; process LEDATA, LIDATA records for DDL module
  3604                                  ; upon entry cx=record length,bp=buffer_end
  3605                                  ; si -> first byte of record past record length word
  3606                                  ; destroys ax,bx,dx,di,es
  3607                                  ; updates si,cx
  3608                                  
  3609                                  ddl_datarec PROC
  3610 000012C2 803E[0000]01                cmp byte [udl_proc_pass],1     ; see if pass 1 udl processing
  3611 000012C7 7501                        jne dd_okay             ; no
  3612 000012C9 C3                          ret                     ; yes, no processing to complete
  3613                                  
  3614                                  dd_okay:
  3615 000012CA 88C2                        mov dl,al               ; save type of record
  3616 000012CC 89CB                        mov bx,cx               ; get record length
  3617 000012CE 83F901                      cmp cx,1                ; return if blank record
  3618 000012D1 7656                        jbe dd_ret
  3619                                  
  3620                                  ; adjust for checksum byte(-1), record type byte, record length,
  3621                                  ; next block pointer word, data offset word, segment index byte,
  3622                                  ; start of iterated/enumerated data, record length-segment index byte(s),
  3623                                  ; round to next para
  3624 000012D3 83C31A                      add bx,26
  3625 000012D6 D1EB                        shr bx,1                ; convert to paragraphs
  3626 000012D8 D1EB                        shr bx,1
  3627 000012DA D1EB                        shr bx,1
  3628 000012DC D1EB                        shr bx,1
  3629 000012DE E8(0000)                    call    alloc_memory    ; get memory for block allocation
  3630 000012E1 89C3                        mov bx,ax               ; bx -> new block
  3631 000012E3 A1[0000]                    mov ax,[alloc_binblk_ptr] ; see if there was a previous block
  3632 000012E6 09C0                        or  ax,ax
  3633 000012E8 7506                        jne dd_prevblk          ; previous block existed
  3634 000012EA 891E[0000]                  mov [first_binblk_ptr],bx ; save -> first block
  3635 000012EE EB07                        jmp SHORT dd_2          ; bypass previous block code
  3636                                  
  3637                                  dd_prevblk:
  3638 000012F0 8EC0                        mov es,ax               ; es -> previous block
  3639 000012F2 26891E0100                  mov [es:1],bx           ; save -> new block
  3640                                  
  3641                                  dd_2:
  3642 000012F7 891E[0000]                  mov [alloc_binblk_ptr],bx ; update last allocated block
  3643 000012FB 8EC3                        mov es,bx               ; es -> new block
  3644 000012FD 2688160000                  mov [es:0],dl           ; save type of block
  3645 00001302 31C0                        xor ax,ax
  3646 00001304 26A30100                    mov [es:1],ax           ; zero -> next block
  3647 00001308 89C8                        mov ax,cx               ; get record length
  3648 0000130A 48                          dec ax                  ; adjust for checksum byte
  3649 0000130B 26A30300                    mov [es:3],ax           ; save record length
  3650                                  
  3651                                  ; move the L?DATA record -> buffer_base:si into newly allocated block
  3652 0000130F 8E1E[0000]                  mov ds,[buffer_base]
  3653 00001313 BF0C00                      mov di,12               ; es:di -> newly allocated block
  3654                                  
  3655                                  dd_loop:
  3656 00001316 A4                          movsb                   ; move byte of record into block
  3657 00001317 49                          dec cx                  ; decrement record length
  3658 00001318 39EE                        cmp si,bp               ; check boundary conditions
  3659 0000131A 7203                        jb  dd_3                ; okay
  3660 0000131C E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
  3661                                  dd_3:
  3662 0000131F 83F901                      cmp cx,1                ; see if at end of record
  3663 00001322 77F2                        ja  dd_loop             ; no
  3664                                  
  3665 00001324 B8[ssss]                    mov ax,DGROUP
  3666 00001327 8ED8                        mov ds,ax               ; restore ds -> warplink data
  3667                                  
  3668                                  dd_ret:
  3669 00001329 C3                          ret
  3670                                  ddl_datarec ENDP
  3671                                  
  3672                                  ;*****************************
  3673                                  ;* DDL_FIXUPP                *
  3674                                  ;*****************************
  3675                                  
  3676                                  ; process FIXUPP records for DDL module
  3677                                  ; upon entry cx=record length,bp=buffer_end
  3678                                  ; si -> first byte of record past record length word
  3679                                  ; destroys ax,bx,dx,di,es
  3680                                  ; updates si,cx
  3681                                  
  3682                                  ddl_fixupp  PROC
  3683 0000132A 803E[0000]01                cmp byte [udl_proc_pass],1     ; see if pass 1 udl processing
  3684 0000132F 7501                        jne df_okay             ; no
  3685 00001331 C3                          ret                     ; yes, no processing to complete
  3686                                  
  3687                                  df_okay:
  3688 00001332 89CB                        mov bx,cx               ; get record length
  3689 00001334 83F901                      cmp cx,1                ; return if blank record
  3690 00001337 767E                        jbe df_ret
  3691                                  
  3692                                  ; adjust for checksum byte(-1), record length, next block pointer word, pointer to owner L?DATA block,
  3693                                  ; 4 frame fixup method bytes, 4 target fixup method bytes,
  3694                                  ; 4 frame fixup thread index words, 4 target fixup thread index words, round to next para
  3695 00001339 83C32C                      add bx,44
  3696 0000133C D1EB                        shr bx,1                ; convert to paragraphs
  3697 0000133E D1EB                        shr bx,1
  3698 00001340 D1EB                        shr bx,1
  3699 00001342 D1EB                        shr bx,1
  3700 00001344 E8(0000)                    call    alloc_memory    ; get memory for block allocation
  3701 00001347 89C3                        mov bx,ax               ; bx -> new block
  3702 00001349 A1[0000]                    mov ax,[alloc_fixblk_ptr] ; see if there was a previous block
  3703 0000134C 09C0                        or  ax,ax
  3704 0000134E 7506                        jne df_prevblk          ; previous block existed
  3705 00001350 891E[0000]                  mov [first_fixblk_ptr],bx ; save -> first block
  3706 00001354 EB07                        jmp SHORT df_2          ; bypass previous block code
  3707                                  
  3708                                  df_prevblk:
  3709 00001356 8EC0                        mov es,ax               ; es -> previous block
  3710 00001358 26891E0000                  mov [es:0],bx           ; save -> new block
  3711                                  
  3712                                  df_2:
  3713 0000135D 891E[0000]                  mov [alloc_fixblk_ptr],bx ; update last allocated block
  3714 00001361 8EC3                        mov es,bx               ; es -> new block
  3715 00001363 31C0                        xor ax,ax
  3716 00001365 26A30000                    mov [es:0],ax           ; zero -> next block
  3717 00001369 A1[0000]                    mov ax,[alloc_binblk_ptr] ; get last allocated block (owning L?DATA record)
  3718 0000136C 26A30200                    mov [es:2],ax
  3719 00001370 89C8                        mov ax,cx               ; get record length
  3720 00001372 48                          dec ax                  ; adjust for checksum byte
  3721 00001373 26A30400                    mov [es:4],ax           ; save record length
  3722                                  
  3723                                  ; save the current state of FIXUPP thread fields
  3724 00001377 56                          push    si              ; save si-> source block
  3725 00001378 89CA                        mov dx,cx               ; save record length
  3726 0000137A BF0600                      mov di,6
  3727 0000137D BE[0000]                    mov si,OFFSET frame_thrd_meth wrt DGROUP
  3728 00001380 A5                          movsw                   ; save four frame thread method bytes
  3729 00001381 A5                          movsw
  3730 00001382 BE[0000]                    mov si,OFFSET target_thrd_meth wrt DGROUP
  3731 00001385 A5                          movsw                   ; save four target thread method bytes
  3732 00001386 A5                          movsw
  3733 00001387 B90400                      mov cx,4                ; four index words
  3734 0000138A BE[0000]                    mov si,OFFSET frame_thrd_index wrt DGROUP
  3735 0000138D F3A5                        rep movsw               ; save frame thread index
  3736 0000138F B90400                      mov cx,4                ; four index words
  3737 00001392 BE[0000]                    mov si,OFFSET target_thrd_index wrt DGROUP
  3738 00001395 F3A5                        rep movsw               ; save target thread index
  3739 00001397 89D1                        mov cx,dx               ; restore record length
  3740 00001399 5E                          pop si                  ; restore si-> source
  3741                                  
  3742                                  ; move the FIXUPP record -> buffer_base:si into newly allocated block
  3743 0000139A 8E1E[0000]                  mov ds,[buffer_base]
  3744 0000139E BF1E00                      mov di,30               ; es:di -> newly allocated block
  3745                                  
  3746                                  df_loop:
  3747 000013A1 A4                          movsb                   ; move byte of record into block
  3748 000013A2 49                          dec cx                  ; decrement record length
  3749 000013A3 39EE                        cmp si,bp               ; check boundary conditions
  3750 000013A5 7203                        jb  df_3                ; okay
  3751 000013A7 E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
  3752                                  df_3:
  3753 000013AA 83F901                      cmp cx,1                ; see if at end of record
  3754 000013AD 77F2                        ja  df_loop             ; no
  3755                                  
  3756                                  ; save new thread field values, if any, by parsing through fixupp record
  3757 000013AF E80600                      call    ddl_parse_fixupp
  3758                                  
  3759 000013B2 B8[ssss]                    mov ax,DGROUP
  3760 000013B5 8ED8                        mov ds,ax               ; restore ds -> warplink data
  3761                                  
  3762                                  df_ret:
  3763 000013B7 C3                          ret
  3764                                  ddl_fixupp  ENDP
  3765                                  
  3766                                  ;*****************************
  3767                                  ;* DDL_PARSE_FIXUPP          *
  3768                                  ;*****************************
  3769                                  
  3770                                  ; parse fixupp record looking for thread fields
  3771                                  ; upon entry es-> fixupp block,dx holds record length
  3772                                  ; destroys ax,bx,dx,di,es,ds
  3773                                  
  3774                                  ddl_parse_fixupp    PROC
  3775 000013B8 56                          push    si              ; save critical register
  3776 000013B9 51                          push    cx
  3777                                  
  3778 000013BA 06                      	push	es
  3779 000013BB 1F                      	pop	ds					; ds -> fixupp block
  3780 000013BC BE1E00                      mov si,30               ; ds:si -> start of fixupp record
  3781 000013BF B8[ssss]                    mov ax,DGROUP
  3782 000013C2 8EC0                        mov es,ax               ; es -> warplink data
  3783 000013C4 89D1                        mov cx,dx               ; cx == record length
  3784                                  
  3785                                  dpr_loop:
  3786 000013C6 AC                          lodsb                   ; get first byte of thread or fixup field
  3787 000013C7 49                          dec cx                  ; decrement record length to parse
  3788 000013C8 A880                        test    al,80h          ; fixup field if high bit set
  3789 000013CA 7505                        jne dpr_fix             ; fixup field
  3790                                  
  3791                                  ; thread field, parse it out
  3792 000013CC E84200                      call    ddl_save_thread
  3793 000013CF EB0F                        jmp SHORT dpr_chkcheck  ; check if at checksum byte
  3794                                  
  3795                                  ; fixup field, scan past it
  3796                                  dpr_fix:
  3797 000013D1 46                          inc si                  ; scan past second byte of locat field
  3798 000013D2 49                          dec cx                  ; decrement record length to parse
  3799                                  
  3800 000013D3 E81200                      call    scan_to_targ_disp   ; scan to target displacement field, if any
  3801                                  
  3802 000013D6 88D0                        mov al,dl               ; get fix dat field
  3803 000013D8 2404                        and al,4                ; get P bit field
  3804 000013DA 7504                        jne dpr_chkcheck        ; set, no target displacement
  3805                                  
  3806                                  ; P bit is zero, scan past target displacement field
  3807 000013DC 46                          inc si                  ; gobble target displacement word
  3808 000013DD 46                          inc si
  3809 000013DE 49                          dec cx
  3810 000013DF 49                          dec cx
  3811                                  
  3812                                  ; see if at checksum
  3813                                  dpr_chkcheck:
  3814 000013E0 83F901                      cmp cx,1                ; check if at checksum byte
  3815 000013E3 77E1                        ja  dpr_loop            ; no, loop back for next fixup/thread field
  3816                                  
  3817 000013E5 59                          pop cx
  3818 000013E6 5E                          pop si                  ; restore critical register
  3819 000013E7 C3                          ret
  3820                                  ddl_parse_fixupp    ENDP
  3821                                  
  3822                                  ;*****************************
  3823                                  ;* SCAN_TO_TARG_DISP         *
  3824                                  ;*****************************
  3825                                  
  3826                                  ; scan from fix dat field to target displacement field, if any
  3827                                  ; upon entry ds:si -> fix dat field, cx holds record length
  3828                                  ; returns dl==fix dat field
  3829                                  ; destroys ax,dx
  3830                                  ; updates si,cx
  3831                                  
  3832                                  scan_to_targ_disp   PROC
  3833 000013E8 AC                          lodsb                   ; get fix dat field
  3834 000013E9 49                          dec cx
  3835 000013EA 88C2                        mov dl,al               ; save fix dat value
  3836 000013EC 88C6                        mov dh,al               ; dh == fix dat
  3837 000013EE 80E670                      and dh,70h              ; get frame field in dh
  3838 000013F1 A880                        test    al,80h          ; check if thread field for frame (fbit)
  3839 000013F3 750D                        jne stt_2               ; yes, no frame data bytes
  3840                                  
  3841                                  ; no thread field for frame
  3842 000013F5 80FE20                      cmp dh,20h              ; see if index specified for this frame
  3843 000013F8 7708                        ja  stt_2               ; no
  3844                                  
  3845                                  ; index specified for this field
  3846 000013FA AC                          lodsb                   ; get frame datum first byte
  3847 000013FB 49                          dec cx                  ; decrement record length to parse
  3848 000013FC 3C80                        cmp al,80h              ; see if two byte field
  3849 000013FE 7202                        jb  stt_2               ; no
  3850 00001400 AC                          lodsb                   ; scan past frame datum second byte
  3851 00001401 49                          dec cx
  3852                                  
  3853                                  stt_2:
  3854 00001402 88D0                        mov al,dl               ; get fix dat field
  3855 00001404 A808                        test    al,8            ; check if thread field for target (tbit)
  3856 00001406 7508                        jne stt_ret             ; yes (no target data bytes)
  3857                                  
  3858                                  ; no thread field for target, scan past target data bytes
  3859 00001408 AC                          lodsb                   ; get target datum first byte
  3860 00001409 49                          dec cx
  3861 0000140A 3C80                        cmp al,80h              ; see if two byte field
  3862 0000140C 7202                        jb  stt_ret             ; no
  3863 0000140E AC                          lodsb                   ; scan past target datum second byte
  3864 0000140F 49                          dec cx
  3865                                  
  3866                                  stt_ret:
  3867 00001410 C3                          ret
  3868                                  scan_to_targ_disp   ENDP
  3869                                  
  3870                                  ;*****************************
  3871                                  ;* DDL_SAVE_THREAD           *
  3872                                  ;*****************************
  3873                                  
  3874                                  ; parse and save thread information
  3875                                  ; upon entry ds:si -> source, es-> warplink data, al holds thread data byte
  3876                                  ; destroys ax,dx
  3877                                  
  3878                                  ddl_save_thread PROC
  3879 00001411 55                          push    bp              ; save critical register
  3880 00001412 53                          push    bx
  3881 00001413 57                          push    di
  3882 00001414 88C3                        mov bl,al               ; save thread data byte
  3883 00001416 241C                        and al,1ch              ; break out thread method
  3884 00001418 D0E8                        shr al,1
  3885 0000141A D0E8                        shr al,1                ; adjust method value to relative zero (right justify bit field)
  3886 0000141C 50                          push    ax              ; save thread method value
  3887                                  
  3888 0000141D 30E4                        xor ah,ah               ; zero high byte of thread index
  3889 0000141F AC                          lodsb                   ; get thread index byte low byte
  3890 00001420 49                          dec cx                  ; decrement record length to parse
  3891 00001421 3C80                        cmp al,80h              ; see if two byte field
  3892 00001423 7206                        jb  st_2                ; no
  3893 00001425 247F                        and al,7fh              ; strip high bit
  3894 00001427 88C4                        mov ah,al               ; move value to high byte
  3895 00001429 AC                          lodsb                   ; get thread index second byte
  3896 0000142A 49                          dec cx                  ; decrement record length to parse
  3897                                  
  3898                                  st_2:
  3899 0000142B 89C5                        mov bp,ax               ; save thread index value
  3900 0000142D 88DA                        mov dl,bl
  3901 0000142F 80E203                      and dl,3                ; get thread number in dl
  3902 00001432 30F6                        xor dh,dh               ; zap high byte
  3903 00001434 80E340                      and bl,40h              ; get D bit field value in bl
  3904 00001437 7425                        je  st_targ             ; D bit reset, target thread field
  3905                                  
  3906                                  ; frame thread field
  3907 00001439 89D3                        mov bx,dx               ; bx -> proper array element (thread number'th)
  3908 0000143B 89D7                        mov di,dx               ; di -> proper array element (thread number'th)
  3909 0000143D 01FF                    	add	di,di				; convert to word offset
  3910 0000143F 58                          pop ax                  ; get thread method value
  3911 00001440 268887[0000]                mov [es:bx+OFFSET frame_thrd_meth wrt DGROUP],al	; save method type in array
  3912 00001445 2689AD[0000]                mov [es:di+OFFSET frame_thrd_index wrt DGROUP],bp	; save index type to array
  3913                                  
  3914 0000144A BB0600                      mov bx,6				; bx -> storage for frame thread method within fixup entry
  3915 0000144D BF0E00                      mov di,14				; di -> storage for frame thread index within fixup entry
  3916                                  
  3917                                  ; ax == thread method value, ds -> fixupp block
  3918                                  st_array_save:
  3919 00001450 01D3                        add bx,dx               ; bx -> proper array element (thread number'th)
  3920 00001452 8807                        mov [bx],al          ; save method type in array
  3921 00001454 01D2                        add dx,dx               ; convert dx to word offset
  3922 00001456 01D7                        add di,dx               ; di -> proper array element (thread number'th)
  3923 00001458 892D                        mov [di],bp          ; save index type to array
  3924                                  
  3925 0000145A 5F                          pop di
  3926 0000145B 5B                          pop bx
  3927 0000145C 5D                          pop bp                  ; restore critical register
  3928 0000145D C3                          ret
  3929                                  
  3930                                  ; target thread field
  3931                                  st_targ:
  3932 0000145E 89D3                        mov bx,dx               ; bx -> proper array element (thread number'th)
  3933 00001460 89D7                        mov di,dx               ; di -> proper array element (thread number'th)
  3934 00001462 01FF                    	add	di,di				; convert to word offset
  3935 00001464 58                          pop ax                  ; get thread method value
  3936 00001465 268887[0000]                mov [es:bx+OFFSET target_thrd_meth wrt DGROUP],al	; save method type in array
  3937 0000146A 2689AD[0000]                mov [es:di+OFFSET target_thrd_index wrt DGROUP],bp	; save index type to array
  3938                                  
  3939 0000146F BB0A00                      mov bx,10				; bx -> storage for target thread method within fixup entry
  3940 00001472 BF1600                      mov di,22				; di -> storage for target thread index within fixup entry
  3941 00001475 EBD9                        jmp SHORT st_array_save ; save thread method and index to arrays
  3942                                  
  3943                                  ddl_save_thread ENDP 
  3944                                  
  3945                                  ;*****************************
  3946                                  ;* DDL_MODEND                *
  3947                                  ;*****************************
  3948                                  
  3949                                  ; process MODEND record for DDL module
  3950                                  ; upon entry cx=record length,bp=buffer_end
  3951                                  ; si -> first byte of record past record length word
  3952                                  ; destroys ax,bx,dx,di
  3953                                  ; updates si,cx
  3954                                  
  3955                                  ddl_modend  PROC
  3956 00001477 06                          push    es              ; save critical register
  3957 00001478 89CB                        mov bx,cx               ; get record length
  3958                                  
  3959 0000147A 83C30E                      add bx,14               ; round up to next paragraph, adjust for checksum byte
  3960 0000147D D1EB                        shr bx,1                ; convert to paragraphs
  3961 0000147F D1EB                        shr bx,1
  3962 00001481 D1EB                        shr bx,1
  3963 00001483 D1EB                        shr bx,1
  3964 00001485 E8(0000)                    call    alloc_memory    ; get memory for block allocation
  3965 00001488 A3[0C00]                    mov [modend_ptr],ax       ; save -> modend block
  3966 0000148B 8EC0                        mov es,ax               ; es -> new block
  3967                                  
  3968                                  ; move the MODEND record -> buffer_base:si into newly allocated block
  3969 0000148D 8E1E[0000]                  mov ds,[buffer_base]
  3970 00001491 31FF                        xor di,di               ; es:di -> newly allocated block
  3971                                  
  3972                                  dm_loop:
  3973 00001493 A4                          movsb                   ; move byte of record into block
  3974 00001494 49                          dec cx                  ; decrement record length
  3975 00001495 39EE                        cmp si,bp               ; check boundary conditions
  3976 00001497 7203                        jb  dm_2                ; okay
  3977 00001499 E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
  3978                                  dm_2:
  3979 0000149C 83F901                      cmp cx,1                ; see if at end of record
  3980 0000149F 77F2                        ja  dm_loop             ; no
  3981                                  
  3982 000014A1 B8[ssss]                    mov ax,DGROUP
  3983 000014A4 8ED8                        mov ds,ax               ; restore ds -> warplink data
  3984                                  
  3985                                  dm_ret:
  3986 000014A6 07                          pop es                  ; restore critical register
  3987 000014A7 C3                          ret
  3988                                  ddl_modend  ENDP
  3989                                  
  3990                                  END
