     1                                  ;*********************************************************************
     2                                  ;*   MLLIB1.ASM                                                      *
     3                                  ;*                                                                   *
     4                                  ;*   By:            Michael Devore                                   *
     5                                  ;*   Date:          02/04/93                                         *
     6                                  ;*   Model:         Small                                            *
     7                                  ;*   Version:       2.5                                              *
     8                                  ;*   Assembler:     MASM 5.0                                         *
     9                                  ;*   Environment:   MS-DOS 2.x+                                      *
    10                                  ;*                                                                   *
    11                                  ;*   library processing part 1                                       *
    12                                  ;*                                                                   *
    13                                  ;*********************************************************************
    14                                  
    15                                  ;TITLE   WARPLINK mllib1
    16                                  ;PAGE    50,80
    17                                  
    18                                  ;.MODEL  SMALL
    19                                  
    20                                  ;*****************************
    21                                  ;* Include files             *
    22                                  ;*****************************
    23                                  
    24                                  [list -]
    29                                       
    30                                  ;*****************************
    31                                  ;* Public declarations       *
    32                                  ;*****************************
    33                                  
    34                                  ; procedures     
    35                                  PUBLIC  proc1_libs,lib_router,get_lib_sys_info,remove_dup_pages
    36                                  PUBLIC  make_libmod_entry
    37                                  PUBLIC	sort_lib_pages
    38                                  
    39                                  ; variables
    40                                  PUBLIC  lib_handle,use_libs,lib_page_size,lib_page_num,lib_block_ptr
    41                                  PUBLIC  dir_pages,lib_pages_count,dir_offset
    42                                  
    43                                  ;*****************************
    44                                  ;* Data begins               *
    45                                  ;*****************************
    46                                  
    47                                  .DATA
    48                                  
    49                                  ;*****************************
    50                                  ;* External declarations     *
    51                                  ;*****************************
    52                                  
    53                                  EXTRN   filename:BYTE,name_field:BYTE,module_flag:BYTE
    54                                  EXTRN   ems_first_avail:WORD,obj_handle:WORD,lib_read_amt:WORD
    55                                  EXTRN	writing_qlk_flag:BYTE,rsp_line:BYTE,pos_in_list:WORD
    56                                  EXTRN	reading_qlk_flag:BYTE,no_qlk_modules:BYTE
    57                                  
    58                                  ; initialized local variables
    59                                  
    60                                  ; byte values
    61                                  EVEN                        ; maximize speed on 8086 and better
    62 00000000 00                      use_libs    DB  0           ; nonzero if libs used (not merely present)
    63 00000001 00                      EVEN
    64                                  
    65                                  .DATA?
    66                                  
    67                                  ; uninitialized local variables
    68                                  
    69                                  ; byte values
    70                                  EVEN
    71 00000000 ??                      all_resolved    DB  ?       ; nonzero if total symbols == public symbols
    72 00000001 ??                      EVEN
    73 00000002 ??                      new_lib DB  ?               ; nonzero if new library being processed
    74                                  
    75                                  .DATA
    76                                  EVEN
    77 00000002 00                      proc_flag   DB  0           ; nonzero if all pass 1 libraries processed at least once (for module processing)
    78                                  
    79                                  .DATA?
    80 00000003 ??                      EVEN
    81                                  
    82                                  ; word values
    83 00000004 ????                    lib_handle  DW  ?           ; handle of currently open library
    84 00000006 ????                    lib_block_ptr   DW  ?       ; segment of current object module name block
    85 00000008 ????                    lib_page_size   DW  ?       ; library page size
    86 0000000A ????                    lib_page_num    DW  ?       ; library page number of public entry
    87 0000000C ????                    dir_pages   DW  ?           ; number of directory pages
    88 0000000E ????                    directory_size  DW  ?       ; size of file i/o buffer dedicated to library directory pages in paragraphs
    89 00000010 ????                    dir_buffer_size DW  ?       ; paragraph size of buffer for directory pages in file i/o buffer
    90 00000012 ????                    dir_buff_bysize DW  ?       ; byte size of buffer for directory pages in file i/o buffer
    91 00000014 ????                    dir_buff_end    DW  ?       ; byte location of last used buffer address for directory pages
    92 00000016 ????                    dir_paras_read  DW  ?       ; number of directory paragraphs read
    93 00000018 ????                    lib_pages_count     DW  ?   ; number of library page pointers stored in lib_page_storage
    94 0000001A ????                    lib_modlen_ptr  DW  ?       ; segment pointer to current library module file length
    95                                  
    96                                  ; doubleword values
    97 0000001C ????????                prev_sym_count  DD  ?       ; count of public symbols prior to all passes of all libraries
    98 00000020 ????????                lib_1pass_sym   DD  ?       ; count of total symbols prior to one pass of single library
    99 00000024 ????????                lib_allpass_sym DD  ?       ; count of total symbols prior to one pass of all libraries
   100 00000028 ????????                dir_offset  DD  ?           ; directory offset in library file
   101                                  
   102                                  ;*****************************
   103                                  ;* Code begins               *
   104                                  ;*****************************
   105                                  
   106                                  .CODE
   107                                  
   108                                  ;*****************************
   109                                  ;* External declarations     *
   110                                  ;*****************************
   111                                  
   112                                  EXTRN   link_error:NEAR,dos_error:NEAR,load_file:NEAR,get_hash:NEAR
   113                                  EXTRN   load_buffer:NEAR,get_name:NEAR,alloc_memory:NEAR,pass1_obj_proc:NEAR
   114                                  EXTRN   pass2_lib_proc:NEAR,get_curr_lib:NEAR
   115                                  EXTRN   load_libmod:NEAR,print_link_info:NEAR
   116                                  EXTRN   decrypt:NEAR,setup_incinfo:NEAR,read_to_ems:NEAR
   117                                  EXTRN   restore_ems_map:NEAR,map_ems_page:NEAR
   118                                  EXTRN	write_qlk_libname:NEAR,write_qlk_mod_info:NEAR,write_qlk_lib_info:NEAR
   119                                  EXTRN	read_qlk_libname:NEAR,read_qlk_mod_info:NEAR,read_qlk_unres:NEAR
   120                                  
   121                                  %IFNDEF DEMO
   122                                  EXTRN	ddl_lib_pass:NEAR
   123                                  %ENDIF
   124                                  
   125                                  ;*****************************
   126                                  ;* PROC1_LIBS                *
   127                                  ;*****************************
   128                                  
   129                                  ; main driver for pass 1 processing of libraries
   130                                  ; all registers destroyed except for ds
   131                                  
   132                                  proc1_libs      PROC
   133                                  
   134                                  %IFNDEF DEMO
   135 00000000 803E[0000]02                cmp byte [udl_proc_pass],2     ; see if pass 2 udl processing
   136 00000005 7503                        jne pl_2                ; no
   137 00000007 E9(0000)                    jmp NEAR PTR ddl_lib_pass   ; specially process udl library modules
   138                                  %ENDIF
   139                                  
   140                                  pl_2:
   141 0000000A 833E[0000]00                cmp word [lib_count],0         ; see if any libraries to process
   142 0000000F 7501                        jne pl_trylibs          ; yes
   143 00000011 C3                          ret                     ; no libraries to process
   144                                  
   145                                  pl_trylibs:
   146 00000012 C606[0000]00                mov byte [all_resolved],0      ; zero init all symbols resolved flag
   147 00000017 C406[0000]                  les ax,[pub_sym_count]    ; get count of public symbols prior to library processing
   148 0000001B A3[1C00]                    mov WORD PTR [prev_sym_count],ax  ; save count for later comparison
   149 0000001E 8C06[1E00]                  mov WORD PTR [prev_sym_count+2],es
   150                                  
   151 00000022 B001                        mov al,1                ; give lib_router procedure pass 1 flag
   152 00000024 E81900                      call    lib_router      ; initialize data and route to proper library code
   153                                  
   154 00000027 A1[1E00]                    mov ax,WORD PTR [prev_sym_count+2]
   155 0000002A 3B06[0200]                  cmp ax,WORD PTR [pub_sym_count+2] ; see if high word count of public symbols has changed
   156 0000002E 770A                        ja  pl_uselibs          ; yes, libraries are used
   157 00000030 A1[1C00]                    mov ax,WORD PTR [prev_sym_count]
   158 00000033 3B06[0000]                  cmp ax,WORD PTR [pub_sym_count]  ; see if low word count of public symbols has changed
   159 00000037 7501                        jne pl_uselibs          ; yes
   160 00000039 C3                          ret                     ; no, leave use_libs flag zero
   161                                  
   162                                  pl_uselibs:
   163 0000003A C606[0000]01                mov byte [use_libs],1          ; flag to use libraries
   164 0000003F C3                          ret
   165                                  proc1_libs      ENDP
   166                                  
   167                                  ;*****************************
   168                                  ;* LIB_ROUTER                *
   169                                  ;*****************************
   170                                  
   171                                  ; initialize and route to proper library code for the two passes
   172                                  ; upon entry al contains pass number (1 or 2)
   173                                  ; all registers destroyed except for ds
   174                                  
   175                                  lib_router  PROC
   176 00000040 30E4                        xor ah,ah
   177 00000042 8826[0000]                  mov [tmod_name],ah        ; zero out library t-module name
   178 00000046 C606[0000]01                mov byte [is_inlib],1          ; flag that processing libraries
   179                                  
   180                                  %IFNDEF DEMO
   181 0000004B 803E[0000]01                cmp byte [udl_proc_pass],1     ; see if udl processing
   182 00000050 7406                        je  lr_chkpass          ; yes
   183 00000052 3826[0000]                  cmp [any_ddl],ah          ; see if creating/using DDL's
   184 00000056 7515                        jne lr_init             ; yes, bypass regular library stuff
   185                                  %ENDIF
   186                                  
   187                                  lr_chkpass:
   188 00000058 3C01                        cmp al,1                ; see if pass one processing
   189 0000005A 7406                        je  lr_lib_pass         ; yes
   190                                  
   191 0000005C E8(0000)                    call    pass2_lib_proc  ; perform pass 2 library processing
   192 0000005F E93301                      jmp NEAR PTR lr_ret     ; and return
   193                                  
   194                                  lr_lib_pass:
   195 00000062 C406[0000]                  les ax,[tot_sym_count]    ; get count of total symbols prior to one pass on all libraries
   196 00000066 A3[2400]                    mov WORD PTR [lib_allpass_sym],ax ; save count for later comparison
   197 00000069 8C06[2600]                  mov WORD PTR [lib_allpass_sym+2],es
   198                                  
   199                                  lr_init:
   200 0000006D C706[0000]0000              mov word [current_lib],0       ; init current library module number
   201 00000073 A1[0000]                    mov ax,[first_libblk_ptr]
   202 00000076 A3[0600]                    mov [lib_block_ptr],ax    ; init current block pointer to first block
   203                                  
   204                                  lr_new_lib:
   205 00000079 C606[0200]01                mov byte [new_lib],1           ; set new library flag
   206 0000007E 803E[0000]00            	cmp	byte [reading_qlk_flag],0	; see if reading library modules from QLK file
   207 00000083 7423                    	je	lr_no_qlk			; no
   208                                  
   209                                  ; reading from QLK file
   210 00000085 E8(0000)                	call	read_qlk_libname	; get the library
   211 00000088 720A                    	jc	lr_qlkexh			; done processing libraries
   212 0000008A 803E[0000]00            	cmp	byte [no_qlk_modules],0	; see if any modules in QLK file for library
   213 0000008F 741A                    	je	lr_showname			; yes
   214 00000091 E9B800                  	jmp	NEAR PTR lr_inclib	; no, try next library
   215                                  
   216                                  ; qlk libraries are exhausted, see if done processing
   217                                  lr_qlkexh:
   218 00000094 E8(0000)                	call	read_qlk_unres
   219 00000097 31C0                        xor ax,ax
   220 00000099 A3[2400]                	mov	WORD PTR [lib_allpass_sym],ax	; zero in case of later passes needed
   221 0000009C A3[2600]                	mov	WORD PTR [lib_allpass_sym+2],ax
   222 0000009F 3806[0000]              	cmp	[reading_qlk_flag],al	; see if still reading from QLK
   223 000000A3 7417                    	je	to_lr_inclib		; no, now writing to QLK file
   224                                  
   225                                  ; done processing, successful
   226 000000A5 E9E200                  	jmp	NEAR PTR lr_pass1_done
   227                                  
   228                                  lr_no_qlk:
   229 000000A8 E8(0000)                    call    get_curr_lib    ; get current library in filename, re/set library module flag
   230                                  
   231                                  lr_showname:
   232 000000AB E8(0000)                    call    print_link_info ; print library name, if applicable
   233                                  
   234                                  ; check if library module, if so, don't process if not first processing pass
   235 000000AE 30C0                        xor al,al
   236 000000B0 3806[0000]                  cmp [module_flag],al      ; see if library module
   237 000000B4 7409                        je  lr_openlib          ; no
   238 000000B6 3806[0200]                  cmp [proc_flag],al        ; see if first processing pass
   239 000000BA 7403                    	je	lr_openlib			; yes
   240                                  
   241                                  to_lr_inclib:
   242 000000BC E98D00                  	jmp	NEAR PTR lr_inclib	; no, don't reprocess library module
   243                                  
   244                                  lr_openlib:
   245 000000BF BA[0000]                    mov dx,OFFSET filename wrt DGROUP   ; DS:DX -> ASCIIZ file specification
   246 000000C2 B43D                        mov ah,3dh              ; open file with read access
   247 000000C4 CD21                        int 21h
   248 000000C6 E8(0000)                    call    restore_ems_map
   249 000000C9 7303                        jnc lr_lib_open         ; no errors
   250 000000CB E9(0000)                    jmp NEAR PTR dos_error  ; error occurred
   251                                  
   252                                  lr_lib_open:
   253 000000CE A3[0400]                    mov [lib_handle],ax       ; save library file handle
   254 000000D1 803E[0000]00            	cmp	byte [writing_qlk_flag],0	; see if creating qlk file
   255 000000D6 7403                    	je	lr_modchk			; no
   256 000000D8 E8(0000)                	call	write_qlk_libname	; yes, write the just opened file name
   257                                  
   258                                  lr_modchk:
   259 000000DB 803E[0000]00            	cmp	byte [reading_qlk_flag],0	; see if reading library module info from QLK file
   260 000000E0 7507                    	jne	lr_ismod			; yes
   261 000000E2 803E[0000]00                cmp byte [module_flag],0       ; see if library module
   262 000000E7 7405                        je  lr_same_lib         ; no
   263                                  
   264                                  ; library module processing
   265                                  lr_ismod:
   266 000000E9 E8AF00                      call    lib_mod_proc    ; perform pass 1 library module processing
   267 000000EC EB53                        jmp SHORT lr_closelib   ; bypass regular library code
   268                                  
   269                                  lr_same_lib:
   270                                  %IFNDEF DEMO
   271 000000EE 803E[0000]00                cmp byte [any_ddl],0           ; see if creating/using DDL's
   272 000000F3 7417                        je  lr_noddl            ; no
   273 000000F5 803E[0000]01                cmp byte [udl_proc_pass],1     ; see if udl processing
   274 000000FA 7410                        je  lr_noddl            ; yes, process normally
   275                                  
   276                                  ; DDL processing
   277 000000FC A1[0400]                    mov ax,[lib_handle]       ; get file handle of open library
   278 000000FF A3[0000]                    mov [obj_handle],ax       ; save into obj_handle for load_file proc
   279 00000102 89C3                        mov bx,ax               ; get file handle into bx for load_buffer proc
   280 00000104 E8(0000)                    call    load_buffer     ; load library into i/o buffer
   281 00000107 E8(0000)                    call    pass1_obj_proc  ; pass 1 process loaded library module
   282 0000010A EB35                        jmp SHORT lr_closelib
   283                                  %ENDIF
   284                                  
   285                                  lr_noddl:
   286 0000010C C406[0000]                  les ax,[tot_sym_count]    ; get count of total symbols prior to pass on single library
   287 00000110 8C06[2200]                  mov WORD PTR [lib_1pass_sym+2],es
   288 00000114 A3[2000]                    mov WORD PTR [lib_1pass_sym],ax   ; save count for later comparison
   289                                  
   290 00000117 E82601                      call    pass1_lib_proc  ; perform pass 1 library processing
   291 0000011A 31C0                        xor ax,ax
   292                                  
   293 0000011C 3806[0000]                  cmp [all_resolved],al     ; see if all symbols resolved by library
   294 00000120 7406                        je  lr_notres           ; no
   295 00000122 3806[0200]                  cmp [proc_flag],al        ; see if first processing pass
   296 00000126 7562                        jne lr_pass1_done       ; no, library modules are all processed
   297                                  
   298                                  lr_notres:
   299 00000128 A1[2200]                    mov ax,WORD PTR [lib_1pass_sym+2]
   300 0000012B 3B06[0200]                  cmp ax,WORD PTR [tot_sym_count+2] ; see if high word count of total symbols has changed
   301 0000012F 77BD                        ja  lr_same_lib         ; yes, libraries modules were used pass of one library
   302 00000131 A1[2000]                    mov ax,WORD PTR [lib_1pass_sym]
   303 00000134 3B06[0000]                  cmp ax,WORD PTR [tot_sym_count]   ; see if low word count of total symbols has changed
   304 00000138 75B4                        jne lr_same_lib         ; yes
   305                                  
   306 0000013A 833E[0000]01                cmp word [lib_count],1         ; see if only one library
   307 0000013F 7449                        je  lr_pass1_done       ; yes, skip useless closing and reopening it
   308                                  
   309                                  lr_closelib:
   310 00000141 8B1E[0400]                  mov bx,[lib_handle]       ; get file handle of open library
   311 00000145 B43E                        mov ah,3eh              ; close file
   312 00000147 CD21                        int 21h
   313 00000149 E8(0000)                    call    restore_ems_map
   314                                  
   315                                  lr_inclib:
   316 0000014C FF06[0000]                  inc word [current_lib]         ; bump number of current library
   317 00000150 A1[0000]                    mov ax,[lib_count]        ; get total count of libraries
   318 00000153 3B06[0000]                  cmp ax,[current_lib]      ; end loop when current equals total
   319 00000157 7603                        jbe lr_proc_once        ; all libraries processed at least once
   320 00000159 E91DFF                      jmp NEAR PTR lr_new_lib ; not all libraries processed, loop back for next library
   321                                  
   322                                  ; all library processed at least once
   323                                  lr_proc_once:
   324 0000015C 31C0                        xor ax,ax
   325                                  
   326                                  %IFNDEF DEMO
   327 0000015E 803E[0000]01                cmp byte [udl_proc_pass],1     ; see if udl processing
   328 00000163 7406                        je  lr_udl              ; yes
   329 00000165 3806[0000]                  cmp [any_ddl],al          ; see if creating/using DDL's
   330 00000169 751F                        jne lr_pass1_done       ; yes, only one time thru
   331                                  %ENDIF
   332                                  
   333                                  lr_udl:
   334 0000016B A2[0000]                    mov [is_msextlib],al      ; only use extended dictionary once to avoid collisions
   335 0000016E 40                          inc ax
   336 0000016F A2[0200]                    mov [proc_flag],al        ; flag all libraries processed at least once
   337 00000172 A1[2600]                    mov ax,WORD PTR [lib_allpass_sym+2]
   338 00000175 3B06[0200]                  cmp ax,WORD PTR [tot_sym_count+2] ; see if high word count of total symbols has changed
   339 00000179 7403                        je  lr_3                ; no, check low word
   340 0000017B E9E4FE                      jmp NEAR PTR lr_lib_pass    ; yes, libraries modules were used during pass of all library
   341                                  
   342                                  lr_3:
   343 0000017E A1[2400]                    mov ax,WORD PTR [lib_allpass_sym]
   344 00000181 3B06[0000]                  cmp ax,WORD PTR [tot_sym_count]   ; see if low word count of total symbols has changed
   345 00000185 7403                        je  lr_pass1_done       ; no
   346 00000187 E9D8FE                      jmp NEAR PTR lr_lib_pass    ; yes
   347                                  
   348                                  lr_pass1_done:
   349 0000018A 8B1E[0400]                  mov bx,[lib_handle]       ; get file handle of last library
   350 0000018E B43E                        mov ah,3eh              ; close file
   351 00000190 CD21                        int 21h
   352 00000192 E8(0000)                    call    restore_ems_map
   353                                  
   354                                  lr_ret:
   355 00000195 C606[0000]00                mov byte [is_inlib],0          ; done, reset library processing flag
   356 0000019A C3                          ret
   357                                  lib_router  ENDP
   358                                  
   359                                  ;*****************************
   360                                  ;* LIB_MOD_PROC              *
   361                                  ;*****************************
   362                                  
   363                                  ; pass 1 library module processing
   364                                  ; destroys all registers except ds
   365                                  
   366                                  lib_mod_proc    PROC
   367                                  
   368                                  ; get match of library page from library module entries
   369                                  lmp_mainloop:
   370 0000019B C706[0000]0000              mov word [lib_read_amt],0      ; init the library read amount
   371 000001A1 803E[0000]00            	cmp	byte [reading_qlk_flag],0	; see if reading info from QLK file
   372 000001A6 740B                    	je	lmp_notqlk			; no
   373                                  
   374                                  ; reading module info from QLK file
   375                                  lmp_readqlk:
   376 000001A8 E8(0000)                	call	read_qlk_mod_info
   377 000001AB 7301                    	jnc	lmp_modok			; read module info okay
   378 000001AD C3                      	ret						; no more modules for this library
   379                                  
   380                                  ; create an entry for this QLK module
   381                                  lmp_modok:
   382 000001AE E89305                  	call	make_libmod_entry
   383 000001B1 EB15                    	jmp	SHORT lmp_match		; bypass search for proper entry
   384                                  
   385                                  lmp_notqlk:
   386 000001B3 8E06[0000]                  mov es,[first_libent_ptr] ; es -> first library module entry
   387 000001B7 A1[0000]                    mov ax,[current_lib]
   388                                  
   389                                  lmp_searchloop:
   390 000001BA 263B060000                  cmp ax,[es:0]           ; see if current library matches this entry
   391 000001BF 7407                        je  lmp_match           ; yes
   392 000001C1 268E061E00                  mov es,[es:30]          ; es -> next entry
   393 000001C6 EBF2                        jmp SHORT lmp_searchloop
   394                                  
   395                                  lmp_match:
   396 000001C8 26A10400                    mov ax,[es:4]           ; get library page size
   397 000001CC A3[0800]                    mov [lib_page_size],ax
   398 000001CF 26A10200                    mov ax,[es:2]           ; get library page number
   399 000001D3 A3[0A00]                    mov [lib_page_num],ax
   400 000001D6 8C06[1A00]                  mov [lib_modlen_ptr],es   ; save current library module for length update
   401                                  
   402                                  ; call library load and go routine
   403 000001DA E8D403                      call    lib_load_and_go
   404 000001DD 803E[0000]00            	cmp	byte [reading_qlk_flag],0	; see if reading info from QLK file
   405 000001E2 75C4                    	jne	lmp_readqlk			; yes, bypass this other stuff
   406                                  
   407                                  ; copy filename to rsp_line (temporary storage)
   408 000001E4 1E                      	push	ds
   409 000001E5 07                      	pop	es
   410 000001E6 BF[0000]                	mov	di,OFFSET rsp_line wrt DGROUP
   411 000001E9 BE[0000]                	mov	si,OFFSET filename wrt DGROUP
   412                                  
   413                                  lmp_transloop:
   414 000001EC A4                      	movsb
   415 000001ED 807CFF00                	cmp	BYTE PTR [si-1],0	; see if at null terminator
   416 000001F1 75F9                    	jne	lmp_transloop		; not yet, more transferring
   417                                  
   418 000001F3 FF06[0000]                  inc word [current_lib]			; bump number of current library
   419 000001F7 A1[0000]                    mov ax,[lib_count]		; get total count of libraries
   420 000001FA 3B06[0000]                  cmp ax,[current_lib]		; end loop when current equals total
   421 000001FE 763B                    	jbe	lmp_out				; no more
   422 00000200 FF36[0000]              	push	word [pos_in_list]		; save original name lookup values in case next is not a match
   423 00000204 FF36[0600]              	push	word [lib_block_ptr]
   424 00000208 E8(0000)                    call    get_curr_lib    ; get current library in filename, re/set library module flag
   425 0000020B 803E[0000]00                cmp byte [module_flag],0		; see if library module
   426 00000210 750A                    	jne	lmp_ismod			; yes
   427 00000212 8F06[0600]              	pop	word [lib_block_ptr]		; restore name lookup values
   428 00000216 8F06[0000]              	pop	word [pos_in_list]
   429 0000021A EB1F                    	jmp	SHORT lmp_out		; and leave
   430                                  
   431                                  ; both are modules, see if filename is same as old
   432                                  ; NOTE: lib_block_ptr and pos_in_list still on stack
   433                                  lmp_ismod:
   434 0000021C 1E                      	push	ds
   435 0000021D 07                      	pop	es
   436 0000021E BF[0000]                	mov	di,OFFSET rsp_line wrt DGROUP
   437 00000221 BE[0000]                	mov	si,OFFSET filename wrt DGROUP
   438                                  
   439                                  lmp_cmploop:
   440 00000224 A6                      	cmpsb
   441 00000225 750C                    	jne	lmp_nomatch			; file name match failed
   442 00000227 807CFF00                	cmp	BYTE PTR [si-1],0	; see if at null terminator
   443 0000022B 75F7                    	jne	lmp_cmploop			; not yet, more comparing
   444 0000022D 83C404                  	add	sp,4				; throw away name lookup values saved on stack
   445 00000230 E968FF                  	jmp	NEAR PTR lmp_mainloop	; match, process this module without closing and opening
   446                                  
   447                                  lmp_nomatch:
   448 00000233 8F06[0600]              	pop	word [lib_block_ptr]		; restore name lookup values
   449 00000237 8F06[0000]              	pop	word [pos_in_list]
   450                                  
   451                                  lmp_out:
   452 0000023B FF0E[0000]              	dec	word [current_lib]			; adjust current library for main loop increment
   453 0000023F C3                          ret
   454                                  lib_mod_proc    ENDP
   455                                  
   456                                  ;*****************************
   457                                  ;* PASS1_LIB_PROC            *
   458                                  ;*****************************
   459                                  
   460                                  ; main pass 1 library processing
   461                                  ; destroys ax,bx,cx,dx,di,si,es
   462                                  
   463                                  pass1_lib_proc  PROC
   464 00000240 A1[0000]                    mov ax,[buffer_base]      ; get i/o buffer segment
   465 00000243 8EC0                        mov es,ax               ; es -> i/o buffer
   466 00000245 31F6                        xor si,si               ; si offsets into i/o buffer
   467                                  
   468 00000247 803E[0200]00                cmp byte [new_lib],0           ; see if new library being processed
   469 0000024C 750C                        jne p1_lib_bytes        ; yes
   470 0000024E A1[1000]                    mov ax,[dir_buffer_size]  ; get the buffer allocated to directory pages
   471 00000251 3B06[0E00]                  cmp ax,[directory_size]   ; compare to actual directory size
   472 00000255 7246                        jb  p1_init_pos         ; reread in first part of directory
   473                                  
   474                                  ; no need to reread directory
   475                                  p1_toscan:
   476 00000257 E98A00                      jmp NEAR PTR p1_scan_pubs
   477                                  
   478                                  p1_lib_bytes:
   479 0000025A E8C600                      call    get_lib_sys_info    ; get library system information
   480                                  
   481 0000025D 803E[0000]00                cmp byte [is_no_ems],0         ; see if EMS used
   482 00000262 7512                        jne p1_noems            ; no
   483                                  
   484                                  ; EMS used, fit directory to 16K page
   485 00000264 3D000C                      cmp ax,0c00h            ; see if more than 3 EMS pages
   486 00000267 7605                        jbe p1_emsfulldir       ; no
   487 00000269 B80004                      mov ax,0400h            ; make directory buffer 1 16K page
   488 0000026C EB21                        jmp SHORT p1_dir2
   489                                  
   490                                  ; round directory up to next 16K page, keep it there
   491                                  p1_emsfulldir:
   492 0000026E 05FF03                      add ax,3ffh
   493 00000271 2500FC                      and ax,0fc00h           ; round to 16K page boundary
   494 00000274 EB19                        jmp SHORT p1_dir2
   495                                  
   496                                  p1_noems:
   497 00000276 050001                      add ax,100h             ; adjust for 4K minimum library file buffer size
   498 00000279 7206                        jc  p1_dir_nofit        ; all of directory won't fit in file buffer
   499 0000027B 3B06[0000]                  cmp ax,[buffer_size]      ; see if directory and 4K minimum lib buffer exceeds buffer size
   500 0000027F 760B                        jbe p1_dir_position     ; no, directory will fit
   501                                  
   502                                  ; all of directory including 4K minimum lib buffer won't fit in file buffer
   503                                  p1_dir_nofit:
   504 00000281 A1[0000]                    mov ax,[buffer_size]      ; get current buffer size
   505 00000284 2D0001                      sub ax,100h             ; back off library file buffer
   506 00000287 83E0E0                      and ax,0ffe0h           ; round to lowest 512-byte boundary
   507 0000028A EB03                        jmp SHORT p1_dir2       ; bypass re-adjustment
   508                                  
   509                                  ; position to directory entries in lib file
   510                                  p1_dir_position:
   511 0000028C 2D0001                      sub ax,100h             ; subtract off 4K adjustment
   512                                  
   513                                  p1_dir2:
   514 0000028F A3[1000]                    mov [dir_buffer_size],ax  ; save directory buffer size in paragraphs
   515 00000292 D1E0                        shl ax,1                ; convert paragraphs of directory buffer size to bytes
   516 00000294 D1E0                        shl ax,1
   517 00000296 D1E0                        shl ax,1
   518 00000298 D1E0                        shl ax,1
   519 0000029A A3[1200]                    mov [dir_buff_bysize],ax
   520                                  
   521                                  p1_init_pos:
   522 0000029D C706[1600]0000              mov word [dir_paras_read],0    ; init paragraphs of directory read
   523 000002A3 8B16[2800]                  mov dx,WORD PTR [dir_offset]  ; dx has LSW of file offset
   524 000002A7 8B0E[2A00]                  mov cx,WORD PTR [dir_offset+2]    ; cx has MSW of file offset
   525                                  
   526                                  p1_dir_loop:
   527 000002AB 8B1E[0400]                  mov bx,[lib_handle]       ; get handle of library file in bx
   528 000002AF B80042                      mov ax,4200h            ; move file pointer, from beginning of file
   529 000002B2 CD21                        int 21h
   530 000002B4 E8(0000)                    call    restore_ems_map
   531                                  
   532 000002B7 8B0E[1200]                  mov cx,[dir_buff_bysize]  ; get number of directory bytes to read
   533                                  
   534 000002BB A1[0E00]                    mov ax,[directory_size]
   535 000002BE 2B06[1600]                  sub ax,[dir_paras_read]   ; get total number of bytes left to read
   536 000002C2 3B06[1000]                  cmp ax,[dir_buffer_size]  ; compare to directory buffer read size
   537 000002C6 730A                        jae p1_read             ; greater than or equal, use directory buffer read size
   538 000002C8 D1E0                        shl ax,1                ; convert paras to bytes, x2
   539 000002CA D1E0                        shl ax,1
   540 000002CC D1E0                        shl ax,1
   541 000002CE D1E0                        shl ax,1                ; x16
   542 000002D0 89C1                        mov cx,ax               ; use number of bytes left to read
   543                                  
   544                                  p1_read:
   545 000002D2 890E[1400]                  mov [dir_buff_end],cx     ; save number of bytes until read end
   546 000002D6 31D2                        xor dx,dx
   547 000002D8 1E                          push    ds              ; save ds -> warplink data
   548 000002D9 8E1E[0000]                  mov ds,[buffer_base]      ; DS:DX -> segment:offset of buffer area
   549                                  
   550 000002DD E8(0000)                    call    read_to_ems
   551                                  
   552 000002E0 1F                          pop ds                  ; restore ds -> warplink data
   553                                  
   554                                  p1_checkdec:
   555 000002E1 E8(0000)                    call    decrypt         ; decrypt if SmartMem library
   556                                  
   557                                  p1_scan_pubs:
   558 000002E4 E88600                      call    scan_pub_entries    ; scan public entries for matches to unresolved externals
   559 000002E7 803E[0000]00                cmp byte [all_resolved],0      ; see if all symbols resolved by library
   560 000002EC 7402                        je  p1_dir_chk          ; no
   561 000002EE EB32                        jmp SHORT p1_ret        ; yes
   562                                  
   563                                  ; see if all directory pages processed in library
   564                                  p1_dir_chk:
   565 000002F0 A1[1000]                    mov ax,[dir_buffer_size]  ; get number of paragraphs already processed
   566 000002F3 0306[1600]                  add ax,[dir_paras_read]   ; add in previous number processed
   567 000002F7 7229                        jc  p1_ret              ; overflow, assume complete
   568 000002F9 A3[1600]                    mov [dir_paras_read],ax   ; update number processed
   569 000002FC 3B06[0E00]                  cmp ax,[directory_size]   ; compare to total number of paragraphs to process
   570 00000300 7320                        jae p1_ret              ; all done
   571                                  
   572                                  ; more directory pages to process
   573 00000302 31DB                        xor bx,bx
   574 00000304 D1E0                        shl ax,1                ; convert paragraphs to bytes in bx,ax
   575 00000306 D1D3                        rcl bx,1
   576 00000308 D1E0                        shl ax,1
   577 0000030A D1D3                        rcl bx,1
   578 0000030C D1E0                        shl ax,1
   579 0000030E D1D3                        rcl bx,1
   580 00000310 D1E0                        shl ax,1
   581 00000312 D1D3                        rcl bx,1
   582 00000314 8B16[2800]                  mov dx,WORD PTR [dir_offset]  ; dx has LSW of file offset
   583 00000318 8B0E[2A00]                  mov cx,WORD PTR [dir_offset+2]    ; cx has MSW of file offset
   584 0000031C 01C2                        add dx,ax               ; update low word of offset
   585 0000031E 11D9                        adc cx,bx               ; update high word including any carry
   586 00000320 EB89                        jmp SHORT p1_dir_loop   ; loop until complete
   587                                  
   588                                  p1_ret:
   589 00000322 C3                          ret
   590                                  pass1_lib_proc  ENDP
   591                                  
   592                                  ;*****************************
   593                                  ;* GET_LIB_SYS_INFO          *
   594                                  ;*****************************
   595                                  
   596                                  ; get library system information, save to variables
   597                                  ; upon entry es:si -> start of i/o buffer
   598                                  ; destroys ax,bx,cx,dx,si
   599                                  
   600                                  get_lib_sys_info    PROC
   601                                  
   602                                  ; load first nine bytes of lib file into i/o buffer
   603 00000323 8B1E[0400]                  mov bx,[lib_handle]       ; get handle of library file
   604 00000327 B90900                      mov cx,9                ; read first nine bytes of lib file
   605 0000032A 1E                          push    ds              ; save ds -> warplink data
   606 0000032B 8E1E[0000]                  mov ds,[buffer_base]      ; DS:DX -> segment:offset of buffer area
   607 0000032F 31D2                        xor dx,dx
   608                                  
   609 00000331 E8(0000)                    call    read_to_ems
   610                                  
   611 00000334 1F                          pop ds                  ; restore ds -> warplink data
   612                                  
   613 00000335 E8(0000)                    call    decrypt         ; decrypt if SmartMem library
   614 00000338 26AC                    	es lodsb ; get first record type of lib file
   615 0000033A 3CF0                        cmp al,MSLIBR           ; see if appropriate type
   616 0000033C 7409                        je  p1_3                ; yes
   617                                  
   618                                  ; bad library format error
   619 0000033E BA[0000]                    mov dx,OFFSET filename wrt DGROUP
   620 00000341 B83300                      mov ax,LIB_FORMAT_ERR   ; library format error
   621 00000344 E9(0000)                    jmp NEAR PTR link_error ; error occurred
   622                                  
   623                                  p1_3:
   624 00000347 26AD                    	es lodsw ; get record length
   625 00000349 83C003                      add ax,3                ; library page size is record length plus 3
   626 0000034C A3[0800]                    mov [lib_page_size],ax    ; save library page size to memory variable
   627                                  
   628 0000034F 26AD                    	es lodsw ; get directory offset low word
   629 00000351 A3[2800]                    mov WORD PTR [dir_offset],ax  ; save to memory variable
   630 00000354 26AD                    	es lodsw ; get directory offset high word
   631 00000356 A3[2A00]                    mov WORD PTR [dir_offset+2],ax    ; save to memory variable
   632                                  
   633 00000359 268B04                      mov ax,[es:si]          ; get directory pages
   634 0000035C A3[0C00]                    mov [dir_pages],ax        ; save to memory variable
   635                                  
   636                                  ; convert 512-byte pages to paragraphs
   637 0000035F D1E0                        shl ax,1                ; x2
   638 00000361 D1E0                        shl ax,1                ; x4
   639 00000363 D1E0                        shl ax,1                ; x8
   640 00000365 D1E0                        shl ax,1                ; x16
   641 00000367 D1E0                        shl ax,1                ; x32
   642 00000369 A3[0E00]                    mov [directory_size],ax   ; save to memory variable
   643 0000036C C3                          ret
   644                                  get_lib_sys_info    ENDP
   645                                  
   646                                  ;*****************************
   647                                  ;* SCAN_PUB_ENTRIES          *
   648                                  ;*****************************
   649                                  
   650                                  ; scan public entries in library for matches to unresolved externals
   651                                  ; duplicates some separate procedures, but more tightly optimized
   652                                  ; if found, seek to proper page and pass 1 process object records
   653                                  ; destroys ax,bx,cx,dx,di,si
   654                                  
   655                                  scan_pub_entries    PROC
   656 0000036D C706[1800]0000              mov word [lib_pages_count],0   ; init count of stored library page pointers
   657 00000373 8CC0                        mov ax,es
   658 00000375 8CDA                        mov dx,ds
   659 00000377 8ED8                        mov ds,ax
   660 00000379 8EC2                        mov es,dx               ; swap es and ds for duration
   661 0000037B 31DB                        xor bx,bx               ; bx offsets into public pointer array
   662                                  
   663                                  spe_loop:
   664 0000037D 8A07                        mov al,[bx]             ; get public pointer array element value
   665 0000037F 08C0                        or  al,al               ; check if nonzero entry
   666 00000381 751A                        jne spe_nonzero         ; nonzero
   667                                  
   668                                  spe_next_entry:
   669 00000383 43                          inc bx                  ; point to next element of array
   670 00000384 80FB25                      cmp bl,37               ; check entry count of page (lower byte of bx never exceeds 37)
   671 00000387 72F4                        jb  spe_loop            ; not done yet, keep looking at public entries
   672                                  
   673                                  spe_2:
   674 00000389 81E300FE                    and bx,0fe00h           ; bx -> first entry of next page (zero lower 511 bytes)
   675 0000038D 81C30002                    add bx,512              ; move to next directory page
   676 00000391 7207                        jc  to_spe_ret          ; overflowed, no more directory pages in buffer
   677 00000393 263B1E[1400]                cmp bx,[es:dir_buff_end]  ; see if past end of directory
   678                                  
   679 00000398 72E3                        jb  spe_loop            ; no
   680                                  
   681                                  to_spe_ret:
   682 0000039A E92101                      jmp NEAR PTR spe_ret    ; yes, done with bytes in buffer
   683                                  
   684                                  spe_nonzero:
   685 0000039D 30E4                        xor ah,ah               ; zap high byte
   686 0000039F D1E0                        shl ax,1                ; convert to offset into directory page
   687 000003A1 89DA                        mov dx,bx
   688 000003A3 81E200FE                    and dx,0fe00h           ; get page value of bx
   689 000003A7 08F4                        or  ah,dh               ; merge into bx offset value for true offset
   690 000003A9 89C6                        mov si,ax               ; ds:si -> public name
   691                                  
   692 000003AB 8A0C                        mov cl,[si]             ; get 1-byte length of name
   693 000003AD 30ED                        xor ch,ch               ; zap high byte
   694 000003AF E3D2                        jcxz    spe_next_entry  ; zero length name, ignore it
   695 000003B1 51                          push    cx              ; save count of chars
   696 000003B2 46                          inc si                  ; point to first char of name
   697                                  
   698                                  spe_3:
   699 000003B3 BF[0000]                    mov di,OFFSET name_field wrt DGROUP
   700 000003B6 31D2                        xor dx,dx               ; dx==hashcode, init to zero
   701 000003B8 30E4                        xor ah,ah               ; zero high byte of char value
   702 000003BA 26803E[0000]00              cmp byte [es:is_casesense],0   ; check to see if string should go to all caps
   703 000003C0 7408                        je spe_4                ; not case sensitive, convert string chars to caps
   704                                  
   705                                  %IFNDEF DEMO
   706                                  ; names are case sensitive, no alteration (to all caps) of chars occurs
   707                                  spe_3a:
   708 000003C2 AC                          lodsb                   ; get byte to check
   709 000003C3 AA                          stosb                   ; store in name_field
   710 000003C4 01C2                        add dx,ax               ; add in character value byte, ignore overflow
   711 000003C6 E2FA                        loop    spe_3a
   712 000003C8 EB10                        jmp SHORT spe_6         ; bypass case insensitive code
   713                                  %ENDIF
   714                                  
   715                                  ; names are NOT case sensitive, convert string chars to caps
   716                                  spe_4:
   717 000003CA AC                          lodsb                   ; get byte to check
   718 000003CB 3C61                        cmp al,'a'              ; check lowercase lower boundary
   719 000003CD 7206                        jb  spe_5               ; not a lowercase letter
   720 000003CF 3C7A                        cmp al,'z'              ; check lowercase upper boundary
   721 000003D1 7702                        ja  spe_5               ; not a lowercase letter
   722 000003D3 2C20                        sub al,20h              ; convert to uppercase
   723                                  
   724                                  spe_5:
   725 000003D5 AA                          stosb                   ; store in name_field
   726 000003D6 01C2                        add dx,ax               ; add in character value byte, ignore overflow
   727 000003D8 E2F0                        loop    spe_4
   728                                  
   729                                  ; dx holds 16-bit hashcode value
   730                                  spe_6:
   731 000003DA AD                          lodsw                   ; get library page number
   732 000003DB AB                          stosw                   ; store in name field
   733 000003DC 81E2FF03                    and dx,03ffh            ; make hash code a 10-bit value
   734 000003E0 59                          pop cx                  ; get length of string
   735                                  
   736                                  ; see if hash code for name is used
   737 000003E1 BE[0000]                    mov si,OFFSET pubdecl_hash wrt DGROUP   ; si -> base of hash pointers to public declaration entries
   738 000003E4 D1E2                        shl dx,1                ; convert dx to word offset
   739 000003E6 01D6                        add si,dx               ; si points to proper name hash code entry
   740 000003E8 26833C00                    cmp WORD PTR [es:si],0  ; is hash code used (nonzero value)
   741 000003EC 7495                        je  spe_next_entry      ; no, name not found
   742                                  
   743                                  ; hash code used, check for hash collision
   744 000003EE 1E                          push    ds              ; save ds -> directory buffer
   745 000003EF 8CC0                        mov ax,es
   746 000003F1 8ED8                        mov ds,ax               ; ds -> warplink data
   747 000003F3 8B04                        mov ax,[si]             ; get segment pointer to pubdef declaration entry
   748 000003F5 BF[0000]                    mov di,OFFSET name_field wrt DGROUP
   749 000003F8 57                          push    di              ; save pointer to first char of converted string
   750                                  
   751                                  spe_testloop:
   752 000003F9 5E                          pop si                  ; si -> name
   753 000003FA 56                          push    si              ; put it back on stack
   754 000003FB 8EC0                        mov es,ax               ; es -> segment of pubdef declaration entry testing name against
   755 000003FD 89C2                        mov dx,ax               ; save entry segment in dx
   756 000003FF 26A10600                    mov ax,[es:6]           ; get segment of pubdef name in pubdef names block
   757 00000403 268B3E0400                  mov di,[es:4]           ; get offset of pubdef name in pubdef names block
   758 00000408 8EC0                        mov es,ax               ; extra segment holds pubdef name segment
   759 0000040A 51                          push    cx              ; save count of chars in string
   760                                  
   761                                  ; ds:si -> name, es:di -> name to test against
   762                                  spe_byteloop:
   763 0000040B A6                          cmpsb                   ; compare a nonzero byte in the two names
   764 0000040C 7508                        jne spe_nomatch         ; not equal, test for greater or less than
   765 0000040E E2FB                        loop    spe_byteloop    ; test thru all chars
   766 00000410 26803D00                    cmp BYTE PTR [es:di],0  ; name testing against should be zero terminated for match
   767 00000414 741D                        je spe_match            ; successful match
   768                                  
   769                                  spe_nomatch:
   770 00000416 59                          pop cx                  ; restore count of chars in string
   771 00000417 8EC2                        mov es,dx               ; get pubdef declaration entry segment value
   772 00000419 7206                        jc  spe_7               ; old name greater than new name
   773                                  
   774                                  ; new name greater than old name
   775 0000041B 26A10C00                    mov ax,[es:12]          ; get entry having a greater name
   776 0000041F EB04                        jmp SHORT spe_null_chk  ; check for null pointer
   777                                  
   778                                  ; old name greater than new name
   779                                  spe_7:
   780 00000421 26A10A00                    mov ax,[es:10]          ; get entry having a lesser name
   781                                  
   782                                  spe_null_chk:
   783 00000425 09C0                        or  ax,ax               ; check if a null pointer (ax=0)
   784 00000427 75D0                        jne spe_testloop        ; no, loop back for next name check
   785 00000429 5E                          pop si                  ; restore stack
   786 0000042A 1F                          pop ds
   787 0000042B B8[ssss]                    mov ax,DGROUP
   788 0000042E 8EC0                        mov es,ax               ; restore es -> warplink data
   789 00000430 E950FF                      jmp NEAR PTR spe_next_entry ; try next public array entry
   790                                  
   791                                  ; names match
   792                                  spe_match:
   793 00000433 59                          pop cx                  ; pull count of string chars off of stack
   794 00000434 8EC2                        mov es,dx               ; get pubdef declaration entry segment value
   795 00000436 26A00E00                    mov al,[es:14]          ; get definitions flag
   796 0000043A 2403                        and al,3                ; only keep pubdef/extdef/comdef/absolute field
   797                                  
   798                                  ; only match if unresolved external, otherwise ignore
   799 0000043C 3C02                        cmp al,2                ; check if previous entry was a pubdef/absolute
   800 0000043E 720D                        jb  spe_found           ; no
   801                                  
   802                                  spe_ignore:
   803 00000440 5E                          pop si                  ; pull pointer to name off of stack
   804 00000441 1F                          pop ds
   805 00000442 C60700                      mov BYTE PTR [bx],0     ; zero out pointer in the directory buffer for quick rescan
   806 00000445 B8[ssss]                    mov ax,DGROUP
   807 00000448 8EC0                        mov es,ax               ; restore es -> warplink data
   808 0000044A E936FF                      jmp NEAR PTR spe_next_entry ; try next public array entry
   809                                  
   810                                  ; a matching entry in the library was found, use it if not a comdef and not weak extdef
   811                                  spe_found:
   812                                  
   813 0000044D 26F6060F0040                test    BYTE PTR [es:15],40h    ; see if comdef
   814 00000453 75EB                        jne spe_ignore          ; yes, don't bring in pubdef from library then
   815                                  
   816 00000455 08C0                        or  al,al               ; see if weak extdef
   817 00000457 74E7                        je  spe_ignore          ; yes, don't bring in pubdef from library
   818                                  
   819 00000459 8B04                        mov ax,[si]             ; get page number value of public entry
   820 0000045B A3[0A00]                    mov [lib_page_num],ax     ; save to memory variable
   821 0000045E 5E                          pop si                  ; get public name pointer off of stack
   822                                  
   823                                  ; at this point the directory buffer pointer is still on the stack
   824                                  
   825                                  ; check if store another library page or process stored pages
   826 0000045F 813E[1800]0004              cmp word [lib_pages_count],1024    ; see if storage is full
   827 00000465 731E                        jae spe_destore         ; yes, process the stored pages
   828                                  
   829                                  ; store the library page
   830                                  spe_store_page:
   831 00000467 A1[1800]                    mov ax,[lib_pages_count]
   832 0000046A D1E0                        shl ax,1                ; convert to word offset
   833 0000046C BE[0000]                    mov si,OFFSET lib_page_storage wrt DGROUP   ; si -> base of stored pages
   834 0000046F 01C6                        add si,ax               ; si -> proper array to store library page number
   835 00000471 A1[0A00]                    mov ax,[lib_page_num]
   836 00000474 8904                        mov [si],ax             ; store page
   837 00000476 FF06[1800]                  inc word [lib_pages_count]     ; bump count of library pages stored
   838 0000047A 8CD8                        mov ax,ds
   839 0000047C 8EC0                        mov es,ax               ; es -> warplink's data
   840 0000047E 1F                          pop ds                  ; ds -> directory buffer
   841 0000047F C60700                      mov BYTE PTR [bx],0     ; zero out pointer in the directory buffer for quick rescan
   842 00000482 E9FEFE                      jmp NEAR PTR spe_next_entry ; loop until complete
   843                                  
   844                                  spe_destore:
   845 00000485 E86100                      call    remove_dup_pages    ; remove duplicate pages in storage
   846                                  
   847 00000488 813E[1800]0003              cmp word [lib_pages_count],768 ; see if storage is at 75% levels
   848 0000048E 72D7                        jb  spe_store_page      ; no, continue storing pages
   849                                  
   850 00000490 C606[0000]00                mov byte [is_msextlib],0       ; fail further use of extended library dictionary
   851 00000495 C60700                      mov BYTE PTR [bx],0     ; zero out pointer in the directory buffer for quick rescan
   852 00000498 07                          pop es                  ; pull directory pointer off of stack into es
   853                                  
   854 00000499 E87D00                      call    proc_stored_pages   ; process the stored library pages
   855                                  
   856                                  ; see if total symbols matches public symbols as result of library processing
   857 0000049C 26A1[0000]                  mov ax,WORD PTR [es:pub_sym_count]    ; get low word of public symbols count
   858 000004A0 263B06[0000]                cmp ax,WORD PTR [es:tot_sym_count]    ; compare to low word of total symbols count
   859 000004A5 7403                        je  spe_8               ; okay so far
   860 000004A7 E9D9FE                      jmp NEAR PTR spe_next_entry ; not the same, library didn't resolve all externals
   861                                  
   862                                  spe_8:
   863 000004AA 26A1[0200]                  mov ax,WORD PTR [es:pub_sym_count+2]  ; get high word of public symbols count
   864 000004AE 263B06[0200]                cmp ax,WORD PTR [es:tot_sym_count+2]  ; compare to high word of total symbols count
   865 000004B3 7403                        je  spe_all_res         ; all symbols resolved
   866 000004B5 E9CBFE                      jmp NEAR PTR spe_next_entry ; not the same, library didn't resolve all externals
   867                                  
   868                                  spe_all_res:
   869 000004B8 26C606[0000]01              mov byte [es:all_resolved],1   ; flag that total symbols == public symbols
   870                                  
   871                                  spe_ret:
   872 000004BE 26833E[1800]00              cmp word [es:lib_pages_count],0    ; see if any library pages left to process
   873 000004C4 7403                        je  spe_ret2            ; no
   874 000004C6 E85000                      call    proc_stored_pages
   875                                  
   876                                  spe_ret2:
   877 000004C9 8CC0                        mov ax,es
   878 000004CB 8CD9                        mov cx,ds
   879 000004CD 8ED8                        mov ds,ax               ; restore ds -> warplink data
   880 000004CF 8EC1                        mov es,cx               ; restore es
   881                                  
   882                                  ; see if total symbols matches public symbols as result of library processing
   883 000004D1 A1[0000]                    mov ax,WORD PTR [pub_sym_count]   ; get low word of public symbols count
   884 000004D4 3B06[0000]                  cmp ax,WORD PTR [tot_sym_count]   ; compare to low word of total symbols count
   885 000004D8 750E                        jne spe_exit            ; not the same, library didn't resolve all externals
   886                                  
   887 000004DA A1[0200]                    mov ax,WORD PTR [pub_sym_count+2] ; get high word of public symbols count
   888 000004DD 3B06[0200]                  cmp ax,WORD PTR [tot_sym_count+2] ; compare to high word of total symbols count
   889 000004E1 7505                        jne spe_exit            ; not the same, library didn't resolve all externals
   890                                  
   891 000004E3 C606[0000]01                mov byte [all_resolved],1      ; flag that total symbols == public symbols
   892                                  
   893                                  spe_exit:
   894 000004E8 C3                          ret
   895                                  scan_pub_entries    ENDP
   896                                  
   897                                  ;*****************************
   898                                  ;* REMOVE_DUP_PAGES          *
   899                                  ;*****************************
   900                                  
   901                                  ; remove duplicate pages in library page storage
   902                                  ; keeping nonduplicate entries in contiguous, sorted order
   903                                  ; destroys ax,cx,dx,si
   904                                  
   905                                  remove_dup_pages    PROC
   906 000004E9 57                          push    di              ; save critical register
   907 000004EA 833E[1800]01                cmp word [lib_pages_count],1   ; see if only one page to process
   908 000004EF 7626                        jbe rdp_ret             ; yes, no duplicate pages to remove
   909 000004F1 E82302                      call    sort_lib_pages  ; sort library pages
   910 000004F4 BE[0000]                    mov si,OFFSET lib_page_storage wrt DGROUP   ; si -> base of sorted stored pages
   911 000004F7 89F7                        mov di,si
   912 000004F9 83C702                      add di,2                ; di -> second entry
   913 000004FC 8B0E[1800]                  mov cx,[lib_pages_count]  ; get number of page entries to compare
   914 00000500 49                          dec cx                  ; start comparing with second entry
   915                                  
   916                                  rdp_loop:
   917 00000501 8B05                        mov ax,[di]             ; get entry
   918 00000503 3B04                        cmp ax,[si]             ; see if matches previous entry
   919 00000505 7407                        je  rdp_match           ; yes
   920 00000507 83C602                      add si,2                ; move to next entry slot
   921 0000050A 8904                        mov [si],ax             ; save nonmatching value
   922 0000050C EB04                        jmp SHORT rdp_next      ; try next entry
   923                                  
   924                                  rdp_match:
   925 0000050E FF0E[1800]                  dec word [lib_pages_count]     ; drop count of library pages stored (ignore duplicate)
   926                                  
   927                                  rdp_next:
   928 00000512 83C702                      add di,2                ; move to next slot to match
   929 00000515 E2EA                        loop    rdp_loop        ; loop until complete
   930                                  
   931                                  rdp_ret:
   932 00000517 5F                          pop di                  ; restore critical register
   933 00000518 C3                          ret
   934                                  remove_dup_pages    ENDP
   935                                  
   936                                  ;*****************************
   937                                  ;* PROC_STORED_PAGES         *
   938                                  ;*****************************
   939                                  
   940                                  ; process library pages stored in lib_page_storage array
   941                                  ; destroys ax,bx,cx,dx,di,si
   942                                  ; modifies es and ds to point to warplink data and directory buffer, respectively
   943                                  
   944                                  proc_stored_pages   PROC
   945 00000519 B8[ssss]                    mov ax,DGROUP
   946 0000051C 8ED8                        mov ds,ax               ; temporarily make ds -> warplink data
   947 0000051E 8E06[0000]                  mov es,[buffer_base]      ; temporarily make es -> directory buffer
   948                                  
   949 00000522 A1[1000]                    mov ax,[dir_buffer_size]  ; get size of directory buffer in paragraphs
   950 00000525 0106[0000]                  add [buffer_base],ax      ; temporarily adjust file i/o buffer base
   951 00000529 A1[1200]                    mov ax,[dir_buff_bysize]  ; get size of directory buffer in bytes
   952 0000052C 2906[0000]                  sub [buffer_end],ax       ; temporarily adjust file i/o buffer end
   953                                  
   954                                  %IFNDEF DEMO
   955 00000530 E8EE00                      call    check_ext_dict  ; check use of and process extended library dictionary
   956                                  %ENDIF
   957                                  
   958                                  ; sort the pages in ascending order (array small enough for sleazy bubble sort)
   959 00000533 E8E101                      call    sort_lib_pages
   960                                  
   961 00000536 BE[0000]                    mov si,OFFSET lib_page_storage wrt DGROUP   ; init si -> base of sorted stored pages
   962                                  
   963                                  psp_procloop:
   964 00000539 C706[0000]0000              mov word [lib_read_amt],0      ; init the library read amount
   965 0000053F 8B04                        mov ax,[si]             ; get library page number
   966 00000541 81FE[0000]                  cmp si,OFFSET lib_page_storage wrt DGROUP   ; check if first time thru loop
   967 00000545 741A                        je  psp_proc2           ; yes
   968 00000547 3B44FE                      cmp ax,[si-2]           ; see if this entry matched previous entry
   969 0000054A 7420                        je  psp_next_page       ; yes, don't process again
   970                                  
   971 0000054C 2B44FE                      sub ax,[si-2]           ; ax holds difference in page numbers
   972 0000054F F726[0800]                  mul word [lib_page_size]       ; dx:ax has byte count of difference
   973 00000553 09D2                        or  dx,dx               ; see if byte count >64K
   974 00000555 7508                        jne psp_defread         ; yes, use default library read amount
   975 00000557 3D0010                      cmp ax,LIB_MAX_READ     ; see if byte count difference >= default read amount
   976 0000055A 7303                        jae psp_defread         ; yes, used default
   977 0000055C A3[0000]                    mov [lib_read_amt],ax     ; save updated library read amount
   978                                  
   979                                  psp_defread:
   980 0000055F 8B04                        mov ax,[si]             ; get library page number back in ax
   981                                  
   982                                  psp_proc2:
   983 00000561 56                          push    si              ; save si -> stored page offset
   984 00000562 A3[0A00]                    mov [lib_page_num],ax     ; store in memory variable
   985 00000565 E8DC01                      call    make_libmod_entry   ; make library module entry
   986                                  
   987 00000568 E84600                      call    lib_load_and_go
   988 0000056B 5E                          pop si                  ; restore si -> stored page offset
   989                                  
   990                                  psp_next_page:
   991 0000056C 83C602                      add si,2                ; point to next entry in array
   992 0000056F 89F0                        mov ax,si
   993 00000571 2D[0000]                    sub ax,OFFSET lib_page_storage wrt DGROUP   ; subtract off offset in memory
   994 00000574 D1E8                        shr ax,1                ; convert word offset back to byte count
   995 00000576 3B06[1800]                  cmp ax,[lib_pages_count]  ; see if all stored pages used
   996 0000057A 72BD                        jb  psp_procloop        ; no, loop back and process next entry
   997                                  
   998                                  psp_done_proc:
   999 0000057C A1[1000]                    mov ax,[dir_buffer_size]  ; get size of directory buffer in paragraphs
  1000 0000057F 2906[0000]                  sub [buffer_base],ax      ; restore file i/o buffer base to original state
  1001 00000583 A1[1200]                    mov ax,[dir_buff_bysize]  ; get size of directory buffer in bytes
  1002 00000586 0106[0000]                  add [buffer_end],ax       ; restore file i/o buffer end to original state
  1003                                  
  1004                                  ; see if total symbols matches public symbols as result of library processing
  1005 0000058A A1[0000]                    mov ax,WORD PTR [pub_sym_count]   ; get low word of public symbols count
  1006 0000058D 3B06[0000]                  cmp ax,WORD PTR [tot_sym_count]   ; compare to low word of total symbols count
  1007 00000591 750E                        jne psp_ret             ; not the same, library didn't resolve all externals
  1008                                  
  1009 00000593 A1[0200]                    mov ax,WORD PTR [pub_sym_count+2] ; get high word of public symbols count
  1010 00000596 3B06[0200]                  cmp ax,WORD PTR [tot_sym_count+2] ; compare to high word of total symbols count
  1011 0000059A 7505                        jne psp_ret             ; not the same, library didn't resolve all externals
  1012                                  
  1013                                  ; all symbols resolved
  1014 0000059C C606[0000]01                mov byte [all_resolved],1      ; flag that total symbols == public symbols
  1015                                  
  1016                                  psp_ret:
  1017 000005A1 C706[1800]0000              mov word [lib_pages_count],0   ; re-init number of stored pages
  1018 000005A7 B8[ssss]                    mov ax,DGROUP
  1019 000005AA 8EC0                        mov es,ax               ; make es -> warplink data
  1020 000005AC 8E1E[0000]                  mov ds,[buffer_base]      ; make ds -> directory buffer
  1021 000005B0 C3                          ret
  1022                                  proc_stored_pages   ENDP
  1023                                  
  1024                                  ;*****************************
  1025                                  ;* LIB_LOAD_AND_GO           *
  1026                                  ;*****************************
  1027                                  
  1028                                  ; load library module and process it
  1029                                  ; destroys all registers except ds
  1030                                  
  1031                                  lib_load_and_go PROC
  1032 000005B1 E8(0000)                    call    load_libmod     ; load library module
  1033 000005B4 8E06[0000]                  mov es,[buffer_base]      ; es -> library file i/o buffer
  1034 000005B8 A1[0000]                    mov ax,[current_lib]      ; get current library value
  1035 000005BB 0D0080                      or  ax,8000h            ; set high bit
  1036 000005BE A3[0200]                    mov WORD PTR [lib_id+2],ax    ; save as high word of library id
  1037 000005C1 A1[0A00]                    mov ax,[lib_page_num]     ; get page number (location in lib file)
  1038 000005C4 A3[0000]                    mov WORD PTR [lib_id],ax  ; save as low word of library id
  1039                                  
  1040 000005C7 803E[0000]00            	cmp	byte [writing_qlk_flag],0	; see if writing to qlk file
  1041 000005CC 740F                    	je	lla_3				; no
  1042 000005CE 53                      	push	bx				; save bx==file handle
  1043 000005CF 803E[0200]00            	cmp	byte [new_lib],0			; see if new library
  1044 000005D4 7403                    	je	lla_2				; no
  1045 000005D6 E8(0000)                	call	write_qlk_lib_info	; save library system info
  1046                                  
  1047                                  lla_2:
  1048 000005D9 E8(0000)                	call	write_qlk_mod_info	; save library module info
  1049 000005DC 5B                      	pop	bx					; restore bx==file handle
  1050                                  
  1051                                  lla_3:
  1052 000005DD 31C0                    	xor	ax,ax
  1053 000005DF A2[0200]                    mov [new_lib],al			; reset new library flag
  1054 000005E2 3806[0000]                  cmp [is_clpinc],al		; see if clipper incremental link specified
  1055 000005E6 7403                        je  psp_notinc          ; no
  1056 000005E8 E8(0000)                    call    setup_incinfo   ; setup incremental info for file
  1057                                  
  1058                                  psp_notinc:
  1059 000005EB E8(0000)                    call    pass1_obj_proc  ; pass 1 process loaded library module
  1060                                  
  1061 000005EE 46                          inc si                  ; bump past checksum so second pass won't load buffer
  1062 000005EF A1[0000]                    mov ax,WORD PTR [file_pos_adj]
  1063 000005F2 8B1E[0200]                  mov bx,WORD PTR [file_pos_adj+2]
  1064 000005F6 2B06[0000]                  sub ax,WORD PTR [lib_pos_adj]
  1065 000005FA 89C1                        mov cx,ax
  1066 000005FC 1B1E[0200]                  sbb bx,WORD PTR [lib_pos_adj+2]   ; bx:ax holds read beyond buffer
  1067 00000600 09D8                        or  ax,bx               ; see if read beside buffer amount
  1068 00000602 7413                        je  psp_chkems          ; no, use offset in si for module length
  1069 00000604 01CE                        add si,cx               ; add in previous amount low word
  1070 00000606 720A                        jc  psp_use60k          ; overflow, use 60k for read amount
  1071 00000608 09DB                        or  bx,bx               ; see if file position besides buffer exceeds 64K
  1072 0000060A 7506                        jne psp_use60k          ; yes, use 60k for read amount
  1073 0000060C 81FE00F0                    cmp si,0f000h           ; see if more than 60K
  1074 00000610 7605                        jbe psp_savelen         ; no, use it
  1075                                  
  1076                                  psp_use60k:
  1077 00000612 BE00F0                      mov si,0f000h           ; make library read 60K
  1078 00000615 EB00                        jmp SHORT psp_savelen   ; bypass EMS stuff
  1079                                  
  1080                                  ; check if not library module and EMS available,
  1081                                  ; if so and enough pages available, stash library pages in EMS
  1082                                  psp_chkems:
  1083                                  ;***    cmp module_flag,0       ; see if library module
  1084                                  ;***    jne psp_savelen         ; yes, don't stash in EMS
  1085                                  ;***    call    lib_ems_mapout  ; map library module pages out to EMS, if possible
  1086                                  
  1087                                  psp_savelen:
  1088 00000617 8E06[1A00]                  mov es,[lib_modlen_ptr]   ; es -> entry for library module
  1089 0000061B 2689360600                  mov [es:6],si           ; save amount to read
  1090                                  
  1091 00000620 C3                          ret
  1092                                  lib_load_and_go ENDP
  1093                                  
  1094                                  %if 0 ;COMMENT #
  1095                                  
  1096                                  ;*****************************
  1097                                  ;* LIB_EMS_MAPOUT            *
  1098                                  ;*****************************
  1099                                  
  1100                                  ; map pages out to EMS if possible
  1101                                  ; upon entry si holds byte count of buffer, es -> buffer base
  1102                                  ; destroys ax,bx,cx,dx,di,es
  1103                                  
  1104                                  lib_ems_mapout  PROC
  1105                                      push    si              ; save critical register
  1106                                      cmp byte [is_no_ems],0         ; see if EMS used
  1107                                      jne lem_ret             ; no
  1108                                  
  1109                                      cmp word [ems_page_avail],4    ; must have over four free pages
  1110                                      jbe lem_ret             ; not enough
  1111                                  
  1112                                      mov dx,es               ; get buffer base
  1113                                      sub dx,[ems_base]         ; get paragraphs beyond base
  1114                                      mov ax,dx
  1115                                  
  1116                                      and dx,0c00h            ; dx holds extra page count in bits 10,11
  1117                                      xchg dl,dh
  1118                                      shr dl,1                ; dl holds extra page count x 2, word offset
  1119                                  
  1120                                      and ax,3ffh             ; get page leftover
  1121                                  
  1122                                      shl ax,1                ; x2
  1123                                      shl ax,1                ; x4
  1124                                      shl ax,1                ; x8
  1125                                      shl ax,1                ; x16
  1126                                      mov cx,si               ; get byte count of library module
  1127                                      add cx,ax               ; add in overflow from page
  1128                                      mov cl,ch
  1129                                      xor ch,ch               ; /256
  1130                                      and cl,0c0h
  1131                                      rol cl,1
  1132                                      rol cl,1                ; /16384, cl==0 -> 3
  1133                                      inc cx                  ; make cl page count relative 1
  1134                                  
  1135                                      mov ax,[ems_page_avail]   ; get count of free pages
  1136                                      sub ax,4                ; back off four free pages
  1137                                      sub ax,cx               ; see if enough free pages to save this obj in ems
  1138                                      jc  lem_ret             ; no
  1139                                  
  1140                                  ; map obj to ems pages, bring in free pages
  1141                                      add ax,4                ; adjust back for four free pages
  1142                                      mov [ems_page_avail],ax   ; save new count of free pages
  1143                                  
  1144                                      mov si,OFFSET ems_currmap wrt DGROUP    ; ds:si -> physical page entries
  1145                                      add si,dx               ; adjust past only dictionary pages
  1146                                  
  1147                                      mov ax,es               ; get buffer base
  1148                                      mov es,[lib_modlen_ptr]
  1149                                      mov di,10               ; es:di -> library module first ems page entry
  1150                                      mov [es:18],ax          ; save buffer base
  1151                                      mov ax,cx               ; save count of pages mapped out
  1152                                      rep movsw               ; save all used physical pages
  1153                                  
  1154                                      mov cx,ax               ; restore count of pages mapped out
  1155                                      mov al,dl               ; get dictionary pages to scan past
  1156                                      shr al,1                ; convert to byte value from word offset
  1157                                  
  1158                                  lem_loop:
  1159                                      push    ax              ; save physical page
  1160                                      mov bx,[ems_first_avail]  ; map in first available free page
  1161                                      inc word [ems_first_avail]     ; bump first available page
  1162                                      call    map_ems_page
  1163                                      pop ax                  ; restore physical page
  1164                                      inc al                  ; bump physical page
  1165                                      loop    lem_loop        ; loop until all free pages are mapped in
  1166                                  
  1167                                  lem_ret:
  1168                                      pop si                  ; restore  critical register
  1169                                      ret
  1170                                  lib_ems_mapout  ENDP
  1171                                  
  1172                                  END COMMENT #
  1173                                  %endif
  1174                                  
  1175                                  %IFNDEF DEMO
  1176                                  
  1177                                  ;*****************************
  1178                                  ;* CHECK_EXT_DICT            *
  1179                                  ;*****************************
  1180                                  
  1181                                  ; check if should use extended dictionary, process if so
  1182                                  ; destroys ax,cx,dx,di,si
  1183                                  
  1184                                  ; Microsoft-compatible library comes on the page immediately following the
  1185                                  ; directory page and has the following format:
  1186                                  ;
  1187                                  ; BYTE, value 0F2h -- extended dictionary identifier
  1188                                  ; WORD, number of bytes in dictionary following this word
  1189                                  ; WORD, number of entries in dictionary
  1190                                  ; start of 2-word dictionary entries, each entry has the following format:
  1191                                  ;   WORD, library page that entry is on
  1192                                  ;   WORD, offset to list of needed entries from start of entries
  1193                                  ;   <repeated for as many entries as is in dictionary
  1194                                  ; needed entry lists, with the following format:
  1195                                  ;   WORD, number of needed entries, each entry having the following format:
  1196                                  ;       WORD, dictionary entry needed, count relative 0
  1197                                  ;       < repeated for number of needed entries>
  1198                                  ;   <repeated for number of entry lists>
  1199                                  
  1200                                  check_ext_dict  PROC
  1201 00000621 06                          push    es              ; save critical register
  1202 00000622 53                          push    bx
  1203 00000623 803E[0000]00                cmp byte [is_msextlib],0       ; see if extended dictionary option is tripped
  1204 00000628 7409                        je  to_ced_ret          ; no, return
  1205 0000062A A1[0E00]                    mov ax,[directory_size]   ; get total size of directory
  1206 0000062D 3B06[1000]                  cmp ax,[dir_buffer_size]  ; compare to directory size in buffer
  1207 00000631 7403                        je  ced_read_five       ; they match, entire directory processed in one pass
  1208                                  
  1209                                  to_ced_ret:
  1210 00000633 E9DE00                      jmp NEAR PTR ced_ret    ; the entire directory was not processed in one pass, don't use dictionary
  1211                                  
  1212                                  ; read five bytes after directory, file pointer should be properly positioned from directory read
  1213                                  ced_read_five:
  1214 00000636 B90500                      mov cx,5
  1215 00000639 31D2                        xor dx,dx
  1216 0000063B 8B1E[0400]                  mov bx,[lib_handle]       ; get handle of library file in bx
  1217 0000063F 1E                          push    ds              ; save ds -> warplink data
  1218 00000640 8E1E[0000]                  mov ds,[buffer_base]      ; DS:DX -> segment:offset of buffer area
  1219                                  
  1220 00000644 E8(0000)                    call    read_to_ems
  1221                                  
  1222 00000647 1F                          pop ds                  ; restore ds -> warplink data
  1223                                  
  1224                                  ced_2:
  1225 00000648 E8(0000)                    call    decrypt         ; decrypt if SmartMem library
  1226 0000064B 8E06[0000]                  mov es,[buffer_base]      ; es -> read in bytes
  1227 0000064F 26803E0000F2                cmp BYTE PTR [es:0],MSEXTDICT   ; see if extended dictionary identifier
  1228 00000655 75DC                        jne to_ced_ret          ; no, return
  1229 00000657 268B0E0100                  mov cx,[es:1]           ; get number of bytes in dictionary
  1230 0000065C 83E902                      sub cx,2                ; adjust for number of entries word
  1231 0000065F 268B3E0300                  mov di,[es:3]           ; get number of entries in dictionary
  1232 00000664 3B0E[0000]                  cmp cx,[buffer_end]       ; see if enough room to read dictionary into file buffer
  1233 00000668 7622                        jbe ced_read_dict       ; yes
  1234                                  
  1235                                  ; not enough room to read dictionary into file buffer, see if free memory is big enough
  1236 0000066A A1[0000]                    mov ax,[allocation_top]
  1237 0000066D 2B06[0000]                  sub ax,[allocation_base]  ; ax holds number of free paragraphs
  1238 00000671 D1E0                        shl ax,1                ; convert to bytes, x2
  1239 00000673 7213                        jc  ced_3               ; overflow, enough free memory for dictionary
  1240 00000675 D1E0                        shl ax,1                ; x4
  1241 00000677 720F                        jc  ced_3
  1242 00000679 D1E0                        shl ax,1                ; x8
  1243 0000067B 720B                        jc  ced_3
  1244 0000067D D1E0                        shl ax,1                ; x16
  1245 0000067F 7207                        jc  ced_3
  1246 00000681 39C8                        cmp ax,cx               ; compare free bytes to bytes needed
  1247 00000683 7303                        jae ced_3               ; enough free bytes to load dictionary
  1248 00000685 E98C00                      jmp NEAR PTR ced_ret    ; not enough room in free memory for dictionary either
  1249                                  
  1250                                  ; enough room in free memory to read in dictionary
  1251                                  ced_3:
  1252 00000688 8E06[0000]                  mov es,[allocation_base]  ; es -> buffer to read in dictionary
  1253                                  
  1254                                  ced_read_dict:
  1255 0000068C 1E                          push    ds              ; save ds -> WarpLink data
  1256 0000068D 8CC0                        mov ax,es
  1257 0000068F 8ED8                        mov ds,ax               ; ds:dx -> buffer area
  1258                                  
  1259 00000691 E8(0000)                    call    read_to_ems
  1260                                  
  1261 00000694 1F                          pop ds                  ; restore ds -> WarpLink data
  1262                                  
  1263                                  ced_4:
  1264 00000695 E851FE                      call    remove_dup_pages    ; remove duplicate pages in storage
  1265                                  
  1266 00000698 89F9                        mov cx,di               ; cx holds count of entries in dictionary
  1267 0000069A D1E1                        shl cx,1
  1268 0000069C D1E1                        shl cx,1                ; convert to byte count of entries (each entry 2 words)
  1269 0000069E 8B16[1800]                  mov dx,[lib_pages_count]  ; dx holds count of stored pages
  1270 000006A2 D1E2                        shl dx,1                ; convert to byte count of pages (each page entry is 1 word)
  1271 000006A4 BB[0000]                    mov bx,OFFSET lib_page_storage wrt DGROUP   ; bx -> base of sorted stored pages
  1272 000006A7 01DA                        add dx,bx               ; adjust stored pages byte count for start of base
  1273                                  
  1274                                  ced_storeloop:
  1275 000006A9 31FF                        xor di,di               ; di will offset into dictionary entries
  1276 000006AB 39D3                        cmp bx,dx               ; see if checked to end of stored pages
  1277 000006AD 7365                        jae ced_ret             ; yes, done
  1278 000006AF 8B07                        mov ax,[bx]             ; get stored page
  1279                                  
  1280                                  ced_dictloop:
  1281 000006B1 263B05                      cmp ax,[es:di]          ; see if matches dictionary entry
  1282 000006B4 740E                        je  ced_match           ; yes, check needed entry list
  1283 000006B6 7207                        jb  ced_next_page       ; not found, try next stored page
  1284 000006B8 83C704                      add di,4                ; move to next dictionary entry
  1285 000006BB 39CF                        cmp di,cx               ; see if any more dictionary entries
  1286 000006BD 72F2                        jb  ced_dictloop        ; yes, try next entry
  1287                                  
  1288                                  ced_next_page:
  1289 000006BF 83C302                      add bx,2                ; bump to next stored page entry
  1290 000006C2 EBE5                        jmp SHORT ced_storeloop ; loop through all stored pages
  1291                                  
  1292                                  ; stored page entry matched dictionary entry
  1293                                  ced_match:
  1294 000006C4 813E[1800]0004              cmp word [lib_pages_count],1024    ; see if any room to add new entry
  1295 000006CA 7348                        jae ced_ret             ; no
  1296 000006CC 51                          push    cx              ; save critical register
  1297 000006CD 57                          push    di
  1298 000006CE 26C7050000                  mov WORD PTR [es:di],0  ; zap entry's page so won't be reused
  1299 000006D3 268B7D02                    mov di,[es:di+2]        ; get offset to needed entry list
  1300 000006D7 268B0D                      mov cx,[es:di]          ; get number of needed entries
  1301 000006DA E334                        jcxz    ced_5           ; no needed entries
  1302                                  
  1303                                  ced_needloop:
  1304 000006DC 83C702                      add di,2                ; position to needed entry in list
  1305 000006DF 268B35                      mov si,[es:di]          ; get needed entry number
  1306 000006E2 D1E6                        shl si,1
  1307 000006E4 D1E6                        shl si,1                ; convert to byte offset
  1308 000006E6 268B04                      mov ax,[es:si]          ; get library page
  1309 000006E9 09C0                        or  ax,ax               ; check if already used
  1310 000006EB 7419                        je  ced_next_needed     ; yes, try next needed entry
  1311                                  
  1312                                  ; see if library page is already in storage
  1313                                  ; since pages at end can be unsorted don't use binary search
  1314                                  ; brute force compare from start of array will be fast enough
  1315 000006ED BE[0000]                    mov si,OFFSET lib_page_storage wrt DGROUP   ; si -> base of sorted stored pages
  1316                                  
  1317                                  ced_checkloop:
  1318 000006F0 3B04                        cmp ax,[si]             ; see if this page entry matches one to add
  1319 000006F2 7412                        je  ced_next_needed     ; page already stored, try next
  1320 000006F4 83C602                      add si,2                ; move to next entry
  1321 000006F7 39D6                        cmp si,dx               ; see if any more entries
  1322 000006F9 72F5                        jb  ced_checkloop       ; yes, check them  
  1323                                  
  1324                                  ; new entry, update lib_page_storage and continue
  1325 000006FB 89D6                        mov si,dx               ; si -> entry following last entry
  1326 000006FD 8904                        mov [si],ax             ; save new page
  1327 000006FF 83C202                      add dx,2                ; bump byte count in storage
  1328 00000702 FF06[1800]                  inc word [lib_pages_count]     ; bump count of library pages in storage
  1329                                  
  1330                                  ced_next_needed:
  1331 00000706 813E[1800]0004              cmp word [lib_pages_count],1024    ; see if any room to add new entries
  1332 0000070C 7306                        jae ced_ret             ; no, stop trying
  1333 0000070E E2CC                        loop    ced_needloop    ; loop through all needed entries in list
  1334                                  
  1335                                  ced_5:
  1336 00000710 5F                          pop di                  ; restore critical register
  1337 00000711 59                          pop cx
  1338 00000712 EBAB                        jmp SHORT ced_next_page ; try next page entry, if any
  1339                                  
  1340                                  ced_ret:
  1341 00000714 5B                          pop bx                  ; restore critical register
  1342 00000715 07                          pop es
  1343 00000716 C3                          ret
  1344                                  check_ext_dict  ENDP
  1345                                  
  1346                                  %ENDIF
  1347                                  
  1348                                  ;*****************************
  1349                                  ;* SORT_LIB_PAGES            *
  1350                                  ;*****************************
  1351                                  
  1352                                  ; sort library pages in ascending order
  1353                                  ; destroys ax,cx,dx,si
  1354                                  
  1355                                  sort_lib_pages  PROC
  1356 00000717 53                          push    bx              ; save critical register
  1357 00000718 833E[1800]01                cmp word [lib_pages_count],1   ; see if only one page to process
  1358 0000071D 7423                        je  slb_ret             ; yes, don't sort
  1359                                  
  1360                                  psp_sort1:
  1361 0000071F BE[0000]                    mov si,OFFSET lib_page_storage wrt DGROUP   ; init si -> base of stored pages
  1362 00000722 8B0E[1800]                  mov cx,[lib_pages_count]
  1363 00000726 49                          dec cx                  ; loop n-1 times where n == number of elements
  1364 00000727 30D2                        xor dl,dl               ; nonzero dl flags swap this pass
  1365                                  
  1366                                  psp_sort2:
  1367 00000729 8B04                        mov ax,[si]             ; get array element
  1368 0000072B 8B5C02                      mov bx,[si+2]           ; get next high array element
  1369 0000072E 39D8                        cmp ax,bx               ; compare lower element to higher
  1370 00000730 7607                        jbe psp_sort3           ; less than or equal to, don't swap elements
  1371                                  
  1372                                  ; swap the array elements
  1373 00000732 894402                      mov [si+2],ax
  1374 00000735 891C                        mov [si],bx
  1375 00000737 B201                        mov dl,1                ; flag that swap occurred
  1376                                  
  1377                                  psp_sort3:
  1378 00000739 83C602                      add si,2                ; move to next array element
  1379 0000073C E2EB                        loop    psp_sort2
  1380 0000073E 08D2                        or  dl,dl               ; check if swap occurred this pass
  1381 00000740 75DD                        jne psp_sort1           ; yes
  1382                                  
  1383                                  slb_ret:
  1384 00000742 5B                          pop bx                  ; restore critical register
  1385 00000743 C3                          ret
  1386                                  sort_lib_pages  ENDP
  1387                                  
  1388                                  ;*****************************
  1389                                  ;* MAKE_LIBMOD_ENTRY         *
  1390                                  ;*****************************
  1391                                  
  1392                                  ; make a library module entry
  1393                                  ; returns es -> entry
  1394                                  ; destroys ax,bx,dx,es
  1395                                  
  1396                                  make_libmod_entry   PROC
  1397 00000744 8B16[0000]                  mov dx,[first_libent_ptr] ; save pointer to first library module entry
  1398 00000748 BB0200                      mov bx,LIB_MODENT_SIZE  ; number of paragraphs to allocate
  1399 0000074B E8(0000)                    call    alloc_memory    ; get memory for block allocation
  1400                                  
  1401 0000074E 09D2                        or  dx,dx               ; see if previously allocated entry
  1402 00000750 7503                        jne mle_2               ; yes
  1403 00000752 A3[0000]                    mov [first_libent_ptr],ax ; no, init first allocated entry pointer
  1404                                  
  1405                                  mle_2:
  1406 00000755 8B16[0000]                  mov dx,[alloc_libent_ptr] ; save pointer to previous last allocated entry, if any
  1407 00000759 A3[0000]                    mov [alloc_libent_ptr],ax ; update last allocated entry pointer
  1408 0000075C 8EC0                        mov es,ax               ; es -> current entry
  1409 0000075E 26C7061E000000              mov WORD PTR [es:30],0  ; zero next entry pointer
  1410 00000765 A1[0000]                    mov ax,[current_lib]      ; get current library
  1411 00000768 26A30000                    mov [es:0],ax           ; update entry
  1412 0000076C A1[0800]                    mov ax,[lib_page_size]    ; get library page size
  1413 0000076F 26A30400                    mov [es:4],ax           ; update entry
  1414 00000773 A1[0A00]                    mov ax,[lib_page_num]     ; get library page number
  1415 00000776 26A30200                    mov [es:2],ax           ; update entry
  1416                                  
  1417 0000077A 8CC0                        mov ax,es
  1418 0000077C A3[1A00]                    mov [lib_modlen_ptr],ax
  1419                                  
  1420 0000077F 09D2                        or  dx,dx               ; see if previous entry to update
  1421 00000781 740A                        je  mle_3               ; no
  1422                                  
  1423                                  ; update previous entry to point to this entry
  1424 00000783 8CC0                        mov ax,es               ; ax holds segment of current entry
  1425 00000785 8EC2                        mov es,dx               ; es -> previous entry
  1426 00000787 26A31E00                    mov [es:30],ax          ; previous entry -> current entry
  1427 0000078B 8EC0                        mov es,ax               ; restore es -> current entry
  1428                                  
  1429                                  mle_3:
  1430                                  ;***    mov ax,-1               ; init ems pages to -1 to show unused
  1431                                  ;***    mov [es:10],ax
  1432                                  ;***    mov [es:12],ax
  1433                                  ;***    mov [es:14],ax
  1434                                  ;***    mov [es:16],ax
  1435                                  
  1436                                  mle_ret:
  1437 0000078D C3                          ret
  1438                                  make_libmod_entry   ENDP
  1439                                  
  1440                                  END
