     1                                   ;*********************************************************************
     2                                  ;*   MLIMAGE2.ASM                                                    *
     3                                  ;*                                                                   *
     4                                  ;*   By:            Michael Devore                                   *
     5                                  ;*   Date:          12/31/92                                         *
     6                                  ;*   Model:         Small                                            *
     7                                  ;*   Version:       2.5                                              *
     8                                  ;*   Assembler:     MASM 5.0                                         *
     9                                  ;*   Environment:   MS-DOS 2.x+                                      *
    10                                  ;*                                                                   *
    11                                  ;*   memory image routines,part 2                                    *
    12                                  ;*                                                                   *
    13                                  ;*********************************************************************
    14                                  
    15                                  ;TITLE   WARPLINK mlimage2
    16                                  ;PAGE    50,80
    17                                  
    18                                  ;.MODEL  SMALL
    19                                  
    20                                  ;*****************************
    21                                  ;* Include files             *
    22                                  ;*****************************
    23                                  
    24                                  [list -]
    14                              <1> [list -]
    26                                  [list -]
    31                                  
    32                                  ;*****************************
    33                                  ;* Public declarations       *
    34                                  ;*****************************
    35                                  
    36                                  ; procedures
    37                                  PUBLIC  zero_mem_image,create_temp_file,update_temp_file
    38                                  PUBLIC  temp_file_write,dump_temp_file,make_temp_fbk
    39                                  PUBLIC  ems_tempfile_create,ems_tempfile_write
    40                                  PUBLIC	delete_temp_file
    41                                  
    42                                  ; variables
    43                                  PUBLIC  temp_file_name,temp_file_pages,temp_page_ptr
    44                                  PUBLIC  xms_tmp_handle
    45                                  public	skip_length
    46                                  
    47                                  ;*****************************
    48                                  ;* Data begins               *
    49                                  ;*****************************
    50                                  
    51                                  .DATA
    52                                  
    53                                  ;*****************************
    54                                  ;* External declarations     *
    55                                  ;*****************************
    56                                  
    57                                  extern	check_com_cut
    58                                  
    59                                  ; variables
    60                                  EXTRN   data_offset:DWORD,exe_handle:WORD
    61                                  EXTRN   ems_first_avail:WORD,ems_trans_block:WORD
    62                                  EXTRN   ems_pages_flushed:BYTE
    63                                  
    64                                  ; initialized local variables
    65                                  
    66                                  ; word values
    67                                  EVEN
    68 00000000 0000                    lru_counter DW  0   ; LRU counter value, used for figure which temp file page to swap to disk
    69 00000002 0000                    skip_length:	dw 0
    70                                  
    71                                  ; dword values
    72 00000004 00000000                tmp_ems_pos     DD  0       ; current EMS write position (analogous to file position)
    73                                  
    74                                  ; byte strings
    75                                  
    76 00000008 2E5C564D2E544D5000-     temp_file_name  DB  '.\VM.TMP',0,119 DUP (?)    ; default temporary file name
    76 00000011 <res 77h>          
    77                                  
    78                                  ; structures
    79                                  PAGE_CONTROL_STRUC  STRUC
    80 00000000 ??                          used    DB  ?   ; nonzero if page used
    81 00000001 ????                        counter DW  ?   ; LRU counter value of page
    82 00000003 ????????                    range   DD  ?   ; beginning range of 4K page
    83                                  PAGE_CONTROL_STRUC  ENDS
    84                                  
    85                                  ; array of 15 page control structures, init'ed to zero values
    86                                  page_control:
    87                                  istruc PAGE_CONTROL_STRUC
    88                                  at used
    89 00000088 00                      page_control.used:	db 0
    90                                  at counter
    91 00000089 0000                    page_control.counter:	dw 0
    92                                  at range
    93 0000008B 00000000                page_control.range:	dd 0
    94                                  iend
    95                                  %rep 14
    96                                  istruc PAGE_CONTROL_STRUC
    97                                  iend
    98                                  %endrep
    96                              <1> istruc PAGE_CONTROL_STRUC
    97 0000008F 00<rep 7h>          <1> iend
    96                              <1> istruc PAGE_CONTROL_STRUC
    97 00000096 00<rep 7h>          <1> iend
    96                              <1> istruc PAGE_CONTROL_STRUC
    97 0000009D 00<rep 7h>          <1> iend
    96                              <1> istruc PAGE_CONTROL_STRUC
    97 000000A4 00<rep 7h>          <1> iend
    96                              <1> istruc PAGE_CONTROL_STRUC
    97 000000AB 00<rep 7h>          <1> iend
    96                              <1> istruc PAGE_CONTROL_STRUC
    97 000000B2 00<rep 7h>          <1> iend
    96                              <1> istruc PAGE_CONTROL_STRUC
    97 000000B9 00<rep 7h>          <1> iend
    96                              <1> istruc PAGE_CONTROL_STRUC
    97 000000C0 00<rep 7h>          <1> iend
    96                              <1> istruc PAGE_CONTROL_STRUC
    97 000000C7 00<rep 7h>          <1> iend
    96                              <1> istruc PAGE_CONTROL_STRUC
    97 000000CE 00<rep 7h>          <1> iend
    96                              <1> istruc PAGE_CONTROL_STRUC
    97 000000D5 00<rep 7h>          <1> iend
    96                              <1> istruc PAGE_CONTROL_STRUC
    97 000000DC 00<rep 7h>          <1> iend
    96                              <1> istruc PAGE_CONTROL_STRUC
    97 000000E3 00<rep 7h>          <1> iend
    96                              <1> istruc PAGE_CONTROL_STRUC
    97 000000EA 00<rep 7h>          <1> iend
    99                                  
   100                                  .DATA?
   101                                  
   102                                  ; uninitialized local variables
   103                                  
   104                                  ; byte values
   105                                  EVEN
   106 00000000 ??                      temp_file_pages DB  ?       ; number of temporary file pages (1 to 15)
   107 00000001 ??                      EVEN
   108 00000002 ??                      unused_page DB  ?           ; pointer to unused page, 255 if none
   109 00000003 ??                      EVEN
   110                                  
   111                                  ; word values
   112 00000004 ????                    zero_block_size DW  ?       ; size of block of zero bytes written to temporary file
   113 00000006 ????                    temp_page_ptr   DW  ?       ; segment pointer to 4K pages
   114 00000008 ????                    data_remainder  DW  ?       ; data_offset modulo 0fffh
   115 0000000A ????                    bytes_to_write  DW  ?       ; number of bytes to write to temp file
   116 0000000C ????                    temp_buffer_size    DW  ?   ; size of temporary buffer
   117 0000000E ????                    temp_buffer_base    DW  ?   ; segment pointer to start of temporary buffer
   118 00000010 ????                    temp_path_end   DW  ?       ; end of temporary file path
   119 00000012 ????                    ems_first_tmp   DW  ?       ; first EMS logical page used by temporary file
   120 00000014 ????                    xms_tmp_handle  DW  ?       ; handle for temporary file in XMS
   121 00000016 ????                    tempname:	dw ?
   122                                  
   123                                  ; doubleword values
   124 00000018 ????????                data_page   DD  ?           ; data_offset 4K page value (updated by data writes crossing page boundary)
   125                                  
   126                                  ; structures
   127                                  EMPB_STRUC  STRUC
   128 00000000 ????????                    es_len  DD  ?           ; length of block in bytes
   129 00000004 ????                        es_src_handle   DW  ?   ; source EMB handle
   130 00000006 ????????                    es_src_offset   DD  ?   ; source offset
   131 0000000A ????                        es_dest_handle  DW  ?   ; destination EMB handle
   132 0000000C ????????                    es_dest_offset  DD  ?   ; destination offset
   133                                  EMPB_STRUC  ENDS
   134                                  
   135                                  
   136                                  .DATA
   137 000000F1 00                      EVEN
   138                                  tmp_empb:
   139                                  istruc EMPB_STRUC
   140                                  at es_len
   141                                  tmp_empb.es_len:
   142 000000F2 00<rep 4h>              at es_src_handle
   143                                  tmp_empb.es_src_handle:
   144 000000F6 00<rep 2h>              at es_src_offset
   145                                  tmp_empb.es_src_offset:
   146 000000F8 00<rep 4h>              at es_dest_handle
   147                                  tmp_empb.es_dest_handle:
   148 000000FC 00<rep 2h>              at es_dest_offset
   149                                  tmp_empb.es_dest_offset:
   150 000000FE 00<rep 4h>              iend
   151                                  
   152                                  ;*****************************
   153                                  ;* Constant data             *
   154                                  ;*****************************
   155                                  
   156                                  .CONST
   157                                  
   158                                  EVEN
   159 00000000 45                      temptext_len    DB  temptext_stop-temp_file_text
   160 00000001 0D0A46696C6520696D-     temp_file_text  DB  CR,LF,'File image size exceeds available memory.'
   160 0000000A 6167652073697A6520-
   160 00000013 657863656564732061-
   160 0000001C 7661696C61626C6520-
   160 00000025 6D656D6F72792E     
   161 0000002C 0D0A54656D706F7261-                     DB  CR,LF,'Temporary file created: '
   161 00000035 72792066696C652063-
   161 0000003E 7265617465643A20   
   162                                  temptext_stop   equ   $
   163                                  
   164 00000046 1C0D0A54656D706F72-     msg_wllist_preserve_1:	counted 13,10,"Temporary file preserved, "
   164 0000004F 6172792066696C6520-
   164 00000058 707265736572766564-
   164 00000061 2C20               
   165 00000063 106C697374206F6620-     msg_wllist_preserve_2:	counted "list of labels: "
   165 0000006C 6C6162656C733A20   
   166 00000074 0D6F626A6563742066-     msg_wllist_preserve_3:	counted "object file: "
   166 0000007D 696C653A20         
   167 00000082 020D0A                  msg_wllist_preserve_linebreak:	counted 13,10
   168                                  
   169 00000085 544D503D                tmptext         DB  'TMP='      ; environment string to check for temporary file path
   170 00000089 54454D503D              temptext:	db "TEMP="
   171 0000008E 564D2E544D5000          def_tempname    DB  'VM.TMP',0  ; default temporary file name
   172 00000095 776C6C69737424242E-     def_wllist_tempname:	asciz "wllist$$.tmp"
   172 0000009E 746D7000           
   173 000000A2 776C6C746D7024242E-     def_wllist_objname:	asciz "wlltmp$$.obj"
   173 000000AB 6F626A00           
   174                                  
   175                                  
   176                                  ;*****************************
   177                                  ;* Code begins               *
   178                                  ;*****************************
   179                                  
   180                                  .CODE
   181                                  
   182                                  ;*****************************
   183                                  ;* External declarations     *
   184                                  ;*****************************
   185                                  
   186                                  ; procedures
   187                                  EXTRN   dos_error:NEAR,link_error:NEAR
   188                                  EXTRN   map_ems_page:NEAR,restore_ems_map:NEAR,convert_to_page:NEAR
   189                                  EXTRN   check_xms_error:NEAR,safe_xms_addr:NEAR
   190                                  EXTRN	read_to_ems:NEAR
   191                                  
   192                                  ;*****************************
   193                                  ;* CREATE_TEMP_FILE          *
   194                                  ;*****************************
   195                                  
   196                                  ; create temporary file to hold executable image of 'image_size' size
   197                                  ; upon entry bx has number of free paragraphs (minimum of 500h, 20K's worth)
   198                                  ; destroys ax,bx,cx,dx,si,di,es
   199                                  
   200                                  create_temp_file    PROC
   201 00000000 E86008                      call    ems_tempfile_create ; create temporary file in EMS/XMS, if possible
   202 00000003 803E[0000]00                cmp byte [tmp_in_emsxms],0     ; see if temporary file in EMS/XMS
   203 00000008 7404                        je  ctf_2               ; no, create file
   204 0000000A E89400                      call    make_temp_pages ; get temp file memory pages for EMS pseudo-disk swapping
   205 0000000D C3                          ret
   206                                  
   207                                  ctf_2:
   208 0000000E 81FB0008                    cmp bx,800h             ; check if more than 800h free paragraphs (32K)
   209 00000012 7603                        jbe ctf_3               ; no
   210 00000014 BB0008                      mov bx,800h             ; allocate only up to 32K for temporary disk write
   211                                  
   212                                  ctf_3:
   213 00000017 B448                        mov ah,48h              ; allocate memory
   214 00000019 CD21                        int 21h
   215 0000001B 7303                        jnc ctf_4               ; should be successful, since using <= previous max value
   216 0000001D E9(0000)                    jmp NEAR PTR dos_error  ; any error is fatal
   217                                  
   218                                  ctf_4:
   219 00000020 8EC0                        mov es,ax               ; es -> allocated block
   220 00000022 31D2                        xor dx,dx               ; zap high word of block size in bytes
   221 00000024 D1E3                        shl bx,1                ; x2
   222 00000026 D1E3                        shl bx,1                ; x4
   223 00000028 D1E3                        shl bx,1                ; x8
   224 0000002A D1E3                        shl bx,1                ; x16, dx:bx contain block size in bytes (dx always zero, max 32K value)
   225 0000002C 891E[0400]                  mov [zero_block_size],bx  ; save the block size of zero bytes
   226 00000030 E8E206                      call    zero_mem_image  ; zero the bytes in the block
   227                                  
   228 00000033 E8B400                      call    make_temp_fbk   ; make temporary file and give feedback
   229                                  
   230                                  ; write image_size number of bytes to program in zero_block_size chunks
   231 00000036 8B1E[0000]                  mov bx,[image_handle]
   232 0000003A 8B36[0000]                  mov si,WORD PTR [image_size]  ; get low word
   233 0000003E 8B3E[0200]                  mov di,WORD PTR [image_size+2]    ; get high word
   234 00000042 31D2                        xor dx,dx               ; zero offset of write buffer
   235                                  
   236                                  ; di:si contain number of bytes to write, bx == file handle
   237                                  ctf_write_file:
   238 00000044 09FF                        or  di,di               ; see if byte count to write is 64K or more
   239 00000046 7506                        jne ctf_7               ; yes, write a zero_block_size chunk
   240 00000048 3B36[0400]                  cmp si,[zero_block_size]  ; see if byte count is at least zero_block_size
   241 0000004C 722F                        jb  ctf_9               ; no, exit zero_block_size writing loop
   242                                  
   243                                  ctf_7:
   244 0000004E 8B0E[0400]                  mov cx,[zero_block_size]  ; number of bytes to write
   245 00000052 1E                          push    ds              ; save ds, critical register
   246 00000053 8CC0                        mov ax,es
   247 00000055 8ED8                        mov ds,ax               ; ds -> segment to start write
   248 00000057 B440                        mov ah,40h              ; write to file
   249 00000059 CD21                        int 21h
   250 0000005B E8(0000)                    call    restore_ems_map
   251 0000005E 1F                          pop ds                  ; restore ds -> warplink data
   252 0000005F 7306                        jnc ctf_8               ; no DOS errors
   253                                  
   254                                  ctf_write_err:
   255 00000061 BA[0800]                    mov dx,OFFSET temp_file_name wrt DGROUP
   256 00000064 E9(0000)                    jmp NEAR PTR dos_error  ; error writing to file
   257                                  
   258                                  ctf_8:
   259 00000067 39C8                        cmp ax, cx			; see if out of disk space
   260 00000069 7409                        je ctf_8a              ; no
   261                                  
   262                                  ; out of disk space for temporary file
   263                                  ctf_diskspace:
   264 0000006B B83B00                      mov ax,TMP_DISK_FULL_ERR
   265 0000006E BA[0800]                    mov dx,OFFSET temp_file_name wrt DGROUP
   266 00000071 E9(0000)                    jmp NEAR PTR link_error ; transfer to error handler
   267                                  
   268                                  ctf_8a:
   269 00000074 2B36[0400]                  sub si,[zero_block_size]  ; back off number of bytes written from bytes to write
   270 00000078 83DF00                      sbb di,0                ; borrow to high word
   271 0000007B EBC7                        jmp SHORT ctf_write_file    ; loop for next write
   272                                  
   273                                  ; transfer leftover bytes (file size modulo zero_block_size)
   274                                  ctf_9:
   275 0000007D 89F1                        mov cx,si               ; cx holds bytes to write
   276 0000007F E313                        jcxz    ctf_free        ; no bytes to write, close file
   277 00000081 1E                          push    ds              ; save ds, critical register
   278 00000082 8CC0                        mov ax,es
   279 00000084 8ED8                        mov ds,ax               ; ds -> segment to start write
   280 00000086 B440                        mov ah,40h              ; write to file
   281 00000088 CD21                        int 21h
   282 0000008A E8(0000)                    call    restore_ems_map
   283 0000008D 1F                          pop ds                  ; restore ds -> warplink data
   284 0000008E 72D1                        jc  ctf_write_err       ; error writing to file
   285                                  
   286 00000090 39C8                        cmp ax, cx			; see if out of disk space
   287 00000092 75D7                        jne  ctf_diskspace        ; yes
   288                                  
   289                                  ; free allocated block
   290                                  ctf_free:
   291 00000094 B449                        mov ah,49h              ; release memory
   292 00000096 CD21                        int 21h
   293 00000098 7303                        jnc ctf_10              ; no errors
   294 0000009A E9(0000)                    jmp NEAR PTR dos_error  ; error releasing memory
   295                                  
   296                                  ctf_10:
   297 0000009D E80100                      call    make_temp_pages ; get temp file pages for disk swapping
   298                                  
   299                                  ctf_ret:
   300 000000A0 C3                          ret
   301                                  create_temp_file    ENDP
   302                                  
   303                                  ;*****************************
   304                                  ;* MAKE_TEMP_PAGES           *
   305                                  ;*****************************
   306                                  
   307                                  ; allocate 4K pages to swap to disk
   308                                  ; destroys ax,bx
   309                                  
   310                                  make_temp_pages PROC
   311 000000A1 B448                        mov ah,48h              ; allocate memory
   312 000000A3 BBFFFF                      mov bx,0ffffh           ; force request to fail, function will return largest available block
   313 000000A6 CD21                        int 21h
   314 000000A8 83F808                      cmp ax,8                ; insufficient memory error is expected
   315 000000AB 7403                        je mtp_2
   316 000000AD E9(0000)                    jmp NEAR PTR dos_error  ; other errors are fatal
   317                                  
   318                                  mtp_2:
   319 000000B0 81FB0005                    cmp bx,500h             ; must be at least 20K free memory
   320 000000B4 7303                        jae mtp_3               ; okay
   321 000000B6 E9(0000)                    jmp NEAR PTR dos_error  ; ax still has insufficient memory error value
   322                                  
   323                                  mtp_3:
   324 000000B9 81EB0004                    sub bx,400h             ; subtract off 16K for use by other procedures
   325                                  
   326                                  ; bh holds count of 4K blocks available
   327 000000BD 80FF03                      cmp bh,3                ; if 3 or less blocks available use all of them
   328 000000C0 7615                        jbe mtp_4
   329 000000C2 88F8                        mov al,bh               ; get count of available 4K blocks
   330 000000C4 B703                        mov bh,3                ; default blocks to 3
   331 000000C6 D0E8                        shr al,1                ; /2
   332 000000C8 D0E8                        shr al,1                ; /4, only allocate up to 25% of blocks available
   333 000000CA 3C03                        cmp al,3                ; allocate larger of 25% of blocks available or 3
   334 000000CC 7609                        jbe mtp_4               ; 3 blocks or less
   335 000000CE 88C7                        mov bh,al
   336 000000D0 80FF0F                      cmp bh,15               ; don't allocate more than 15 4K blocks (60K, 0f00h paragraphs)
   337 000000D3 7602                        jbe mtp_4               ; 15 or fewer 4K blocks available
   338 000000D5 B70F                        mov bh,15               ; set at maximum
   339                                  
   340                                  mtp_4:
   341 000000D7 883E[0000]                  mov [temp_file_pages],bh  ; save count of 4K blocks
   342 000000DB 30DB                        xor bl,bl               ; zap low byte of paragraphs available (round down to nearest 4K block)
   343 000000DD B448                        mov ah,48h              ; allocate memory
   344 000000DF CD21                        int 21h
   345 000000E1 7303                        jnc mtp_5
   346 000000E3 E9(0000)                    jmp NEAR PTR dos_error  ; error allocating memory
   347                                  
   348                                  mtp_5:
   349 000000E6 A3[0600]                    mov [temp_page_ptr],ax    ; save pointer to block
   350                                  
   351                                  mtp_ret:
   352 000000E9 C3                          ret
   353                                  make_temp_pages ENDP
   354                                  
   355                                  ;*****************************
   356                                  ;* MAKE_TEMP_FBK             *
   357                                  ;*****************************
   358                                  
   359                                  ; make the temporary file and give appropriate feedback
   360                                  ; destroys ax,bx,cx,dx
   361                                  
   362                                  make_temp_fbk   PROC
   363 000000EA BA[0800]                    mov dx,OFFSET temp_file_name wrt DGROUP ; ds:dx -> ASCIIZ path spec
   364 000000ED 31C9                        xor cx,cx               ; create normal file
   365 000000EF 803E[0000]00                cmp byte [is_tempfile],0       ; see if temporary file specified
   366 000000F4 7531                        jne mtf_2               ; yes, use it
   367                                  
   368 000000F6 89D0                        mov ax,dx
   369 000000F8 83C002                      add ax,2                ; point to first char past default path
   370 000000FB A3[1000]                    mov [temp_path_end],ax    ; save pointer to memory variable
   371 000000FE BE[8E00]                    mov si,OFFSET def_tempname wrt DGROUP   ; ds:si -> default file name
   372 00000101 8916[1600]                  mov word [tempname], dx
   373 00000105 E85D00                      call    check_tmp_var   ; check if TMP environment variable to use
   374                                  
   375 00000108 BA[0800]                    mov dx,OFFSET temp_file_name wrt DGROUP ; ds:dx -> ASCIIZ path spec
   376 0000010B 31C9                        xor cx,cx               ; create normal file
   377 0000010D 803E[0000]02                cmp byte [dos_version],2       ; see if we can use create temporary file dos function
   378 00000112 7413                        je  mtf_2               ; no, using DOS 2.x
   379                                  
   380                                  ; use DOS 3.x create temporary file function
   381 00000114 8B1E[1000]                  mov bx,[temp_path_end]
   382 00000118 C60700                      mov BYTE PTR [bx],0     ; reduce name to path only
   383 0000011B B45A                        mov ah,5ah              ; create temporary file
   384 0000011D CD21                        int 21h
   385 0000011F E8(0000)                    call    restore_ems_map
   386 00000122 730F                        jnc mtf_3               ; no errors
   387 00000124 E9(0000)                    jmp NEAR PTR dos_error  ; error creating file
   388                                  
   389                                  ; use DOS 2.x create or truncate file (VM.TMP) function
   390                                  mtf_2:
   391 00000127 B43C                        mov ah,3ch              ; create or truncate file
   392 00000129 CD21                        int 21h
   393 0000012B E8(0000)                    call    restore_ems_map
   394 0000012E 7303                        jnc mtf_3
   395 00000130 E9(0000)                    jmp NEAR PTR dos_error  ; error creating file
   396                                  
   397                                  mtf_3:
   398 00000133 A3[0000]                    mov [image_handle],ax     ; save handle of temporary file
   399                                  
   400                                  ; print temporary file created feedback
   401 00000136 BB[0100]                    mov bx,OFFSET temp_file_text wrt DGROUP
   402 00000139 8A4FFF                      mov cl,[bx-1]           ; get length of string to print
   403 0000013C 89DA                        mov dx,bx               ; ds:dx -> string
   404 0000013E 30ED                        xor ch,ch               ; zap high byte of cx
   405 00000140 BB0100                      mov bx,STDOUT           ; write to standard output device
   406 00000143 B440                        mov ah,40h              ; write to device
   407 00000145 CD21                        int 21h
   408 00000147 E8(0000)                    call    restore_ems_map
   409                                  
   410                                  ; print name of temporary file
   411 0000014A BA[0800]                    mov dx,OFFSET temp_file_name wrt DGROUP
   412 0000014D 89D3                        mov bx,dx
   413 0000014F 31C9                        xor cx,cx               ; cx will contain number of chars in file name
   414                                  
   415                                  ; mtf_loop computes number of chars in file name
   416                                  mtf_loop:
   417 00000151 803F00                      cmp BYTE PTR [bx],0     ; see if zero terminator in file name found
   418 00000154 7404                        je  mtf_print_name      ; yes
   419 00000156 41                          inc cx                  ; bump count of chars in string
   420 00000157 43                          inc bx                  ; move to next char slot to test
   421 00000158 EBF7                        jmp SHORT mtf_loop      ; loop back to test next char
   422                                  
   423                                  mtf_print_name:
   424 0000015A BB0100                      mov bx,STDOUT           ; write to standard output device
   425 0000015D B440                        mov ah,40h              ; write to device
   426 0000015F CD21                        int 21h
   427 00000161 E8(0000)                    call    restore_ems_map
   428 00000164 C3                          ret
   429                                  make_temp_fbk   ENDP
   430                                  
   431                                  ;*****************************
   432                                  ;* CHECK_TMP_VAR             *
   433                                  ;*****************************
   434                                  
   435                                  ; check TMP environment variable when creating temporary file
   436                                  ; use it if it exists and is valid
   437                                  ; upon entry ds:dx -> default ASCIIZ file name, temp_path_end -> end of default name
   438                                  ; si -> default name to append
   439                                  ; updates temp_path_end
   440                                  ; destroys ax,bx,cx,dx,si,di
   441                                  
   442                                  check_tmp_var   PROC
   443 00000165 06                          push    es              ; save critical register
   444 00000166 56                      	push si
   445                                  
   446                                  ; check for a TMP= in the environment
   447 00000167 BB[8500]                    mov bx,OFFSET tmptext wrt DGROUP    ; bx holds target string address for compares
   448 0000016A A1[0000]                    mov ax,[psp]
   449 0000016D 8EC0                        mov es,ax               ; es -> warplink's PSP
   450 0000016F 26A12C00                    mov ax,[es:2ch]         ; get environment segment from offset 2ch in PSP
   451 00000173 85C0                    	test ax, ax		; environment valid ?
   452 00000175 7475                    	jz ctv_ret		; no -->
   453 00000177 8EC0                        mov es,ax               ; es -> environment segment
   454                                  ctv_repeat:
   455 00000179 31F6                        xor si,si               ; starting location for target string check
   456                                  
   457                                  ctv_find_path:
   458 0000017B 31FF                        xor di,di               ; offset into target string
   459                                  
   460                                  ctv_loop:
   461 0000017D 268A04                      mov al,[es:si]          ; get byte from environment string
   462 00000180 46                          inc si                  ; point to next char in environment
   463 00000181 3A01                        cmp al,[bx+di]          ; does environment char match TMP string char
   464 00000183 7412                        je  ctv_byte_match      ; yes, try next location
   465 00000185 260A04                      or  al,[es:si]          ; two zero values in a row mean the end of the environment
   466 00000188 7402                        je @F             ; all done searching environment, no TMP variable
   467 0000018A EBEF                        jmp SHORT ctv_find_path ; not at end of environment, keep searching
   468                                  
   469                                  @@:
   470 0000018C 81FB[8500]              	cmp bx, tmptext
   471 00000190 755A                    	jne ctv_ret
   472 00000192 BB[8900]                	mov bx, temptext
   473 00000195 EBE2                    	jmp ctv_repeat
   474                                  
   475                                  ; check that TMP is not part of another environment string
   476                                  ctv_byte_match:
   477 00000197 09FF                        or  di,di               ; di is zero if first char is matched
   478 00000199 750C                        jne ctv_2               ; not first char, test already done
   479 0000019B 83FE01                      cmp si,1                ; si equals one if TMP is first string in environment block
   480 0000019E 7407                        je  ctv_2               ; no previous environment string
   481 000001A0 26807CFE00                  cmp BYTE PTR [es:si-2],0    ; check if char before TMP was nonzero
   482 000001A5 75D4                        jne ctv_find_path       ; yes, TMP is a subset of another string, keep looking
   483                                  
   484                                  ctv_2:
   485 000001A7 47                          inc di                  ; a match, move to next byte of target string
   486 000001A8 3C3D                        cmp al, '='                ; check if all bytes matched
   487 000001AA 75D1                        jne ctv_loop            ; not yet, keep comparing
   488                                  
   489                                  ; es:si -> temporary file path
   490                                  ctv_path_found:
   491 000001AC 8CDB                        mov bx,ds               ; save -> warplink data
   492 000001AE 8CC0                        mov ax,es
   493 000001B0 8ED8                        mov ds,ax
   494 000001B2 89F2                        mov dx,si               ; ds:dx -> temporary file path
   495 000001B4 B80043                      mov ax,4300h            ; get file attribute
   496 000001B7 CD21                        int 21h
   497 000001B9 E8(0000)                    call    restore_ems_map
   498 000001BC 7304                        jnc ctv_path_good       ; path was okay
   499 000001BE 8EDB                        mov ds,bx               ; restore ds -> warplink data
   500 000001C0 EB2A                        jmp SHORT ctv_ret       ; error accessing directory, return
   501                                  
   502                                  ctv_path_good:
   503 000001C2 89D6                        mov si,dx               ; ds:si -> temporary file path
   504 000001C4 8EC3                        mov es,bx
   505 000001C6 268B3E[1600]                mov di, word [es:tempname]	; es:di -> fully pathed temporary file name
   506                                  
   507                                  ctv_tranloop:
   508 000001CB AC                          lodsb                   ; get char of path
   509 000001CC 08C0                        or  al,al               ; check if zero terminator
   510 000001CE 7403                        je  ctv_3               ; yes, end transfer
   511 000001D0 AA                          stosb                   ; transfer char
   512 000001D1 EBF8                        jmp SHORT ctv_tranloop  ; loop until complete
   513                                  
   514                                  ; done transferring path
   515                                  ctv_3:
   516 000001D3 8EDB                        mov ds,bx               ; ds -> warplink data
   517 000001D5 807DFF5C                    cmp BYTE PTR [di-1],'\' ; see if directory char is last char
   518 000001D9 7404                        je  ctv_4               ; yes
   519                                  
   520 000001DB C6055C                      mov BYTE PTR [di],'\'   ; add directory char prior to adding file name
   521 000001DE 47                          inc di                  ; point past directory '\' char
   522                                  
   523                                  ctv_4:
   524 000001DF 893E[1000]                  mov [temp_path_end],di    ; update pointer to end of path
   525 000001E3 5E                      	pop si
   526                                  @@:
   527 000001E4 A4                      	movsb
   528 000001E5 807CFF00                	cmp byte [si - 1], 0
   529 000001E9 75F9                    	jne @B
   530 000001EB A8                      	db __TEST_IMM8		; skip pop
   531                                  ctv_ret:
   532 000001EC 5E                      	pop si
   533 000001ED 07                          pop     es              ; restore critical register
   534 000001EE C3                          ret
   535                                  check_tmp_var   ENDP
   536                                  
   537                                  ;*****************************
   538                                  ;* TEMP_FILE_WRITE           *
   539                                  ;*****************************
   540                                  
   541                                  ; write bytes to temporary file
   542                                  ; upon entry [es:si] -> buffer to write from, cx == number of bytes to write,
   543                                  ; data_offset == offset from start of program
   544                                  ; updates si
   545                                  ; destroys ax,bx,cx,dx,di
   546                                  
   547                                  temp_file_write PROC
   548 000001EF A1[0200]                    mov ax,WORD PTR [data_offset+2]   ; get high word of offset
   549 000001F2 A3[1A00]                    mov WORD PTR [data_page+2],ax     ; save to page high word
   550 000001F5 A1[0000]                    mov ax,WORD PTR [data_offset]     ; get low word of offset
   551 000001F8 89C3                        mov bx,ax               ; save value
   552 000001FA 2500F0                      and ax,0f000h           ; round to 4K page
   553 000001FD A3[1800]                    mov WORD PTR [data_page],ax   ; save page low word value
   554 00000200 89D8                        mov ax,bx               ; get offset low word value
   555 00000202 25FF0F                      and ax,0fffh            ; convert to page remainder
   556 00000205 A3[0800]                    mov [data_remainder],ax   ; save to memory variable
   557 00000208 BB0010                      mov bx,1000h
   558 0000020B 29C3                        sub bx,ax               ; compute bytes left to write on page
   559 0000020D 39D9                        cmp cx,bx               ; check if bytes to write exceed bytes left on page
   560 0000020F 7707                        ja  tfw_2               ; yes
   561                                  
   562                                  tfw_last_write:
   563 00000211 89C8                        mov ax,cx               ; get number of bytes to write in ax for page_write procedure
   564 00000213 E82700                      call    temp_page_write ; write bytes to page
   565 00000216 EB24                        jmp SHORT tfw_ret       ; done
   566                                  
   567                                  tfw_2:
   568 00000218 29D9                        sub cx,bx               ; subtract bytes written (to be written) from total to write
   569 0000021A 89D8                        mov ax,bx               ; get bytes that can be written on page in ax
   570 0000021C E81E00                      call    temp_page_write ; write bytes to page
   571                                  
   572 0000021F C706[0800]0000              mov word [data_remainder],0    ; zero data remainder (all bytes on subsequent pages can be written to)
   573                                  
   574                                  tfw_write_loop:
   575 00000225 B80010                      mov ax,1000h
   576 00000228 0106[1800]                  add WORD PTR [data_page],ax   ; bump to next page
   577 0000022C 8316[1A00]00                adc WORD [data_page+2],0  ; carry to high word
   578 00000231 39C1                        cmp cx,ax               ; see if more than one page to write
   579 00000233 76DC                        jbe tfw_last_write      ; no
   580 00000235 29C1                        sub cx,ax               ; subtract bytes written (to be written)
   581 00000237 E80300                      call    temp_page_write ; write 4K bytes to page
   582 0000023A EBE9                        jmp SHORT tfw_write_loop    ; loop till no more bytes to write
   583                                  
   584                                  tfw_ret:
   585 0000023C C3                          ret
   586                                  temp_file_write ENDP
   587                                  
   588                                  ;*****************************
   589                                  ;* TEMP_PAGE_WRITE           *
   590                                  ;*****************************
   591                                  
   592                                  ; write bytes to temp file page
   593                                  ; upon entry [es:si] -> buffer to write from, ax == number of bytes to write
   594                                  ; destroys ax,bx,dx,di
   595                                  
   596                                  temp_page_write PROC
   597 0000023D 51                          push    cx              ; save critical register
   598 0000023E A3[0A00]                    mov [bytes_to_write],ax   ; save number of bytes to write
   599 00000241 C606[0200]FF                mov byte [unused_page],255     ; init unused page pointer to not valid value
   600 00000246 30ED                        xor ch,ch
   601 00000248 8A0E[0000]                  mov cl,[temp_file_pages]  ; get number of pages to loop through
   602 0000024C FF06[0000]                  inc word [lru_counter]         ; bump LRU counter value
   603 00000250 7510                        jnz tpw_2               ; didn't wrap
   604                                  
   605                                  ; reset values on all page control counter bytes
   606 00000252 89CA                        mov dx,cx               ; save number of pages
   607 00000254 31C0                        xor ax,ax
   608 00000256 BB[8900]                    mov bx,OFFSET page_control.counter wrt DGROUP   ; point to first structure's counter word
   609                                  
   610                                  tpw_counter_loop:
   611 00000259 8907                        mov [bx],ax             ; zero it
   612 0000025B 83C307                      add bx,7                ; point to next counter byte
   613 0000025E E2F9                        loop    tpw_counter_loop    ; zero all structure's counter words
   614 00000260 89D1                        mov cx,dx               ; restore number of pages to cx
   615                                  
   616                                  tpw_2:
   617 00000262 BFFFFF                      mov di,65535            ; init counter value to check against
   618 00000265 BA0100                      mov dx,1                ; init page containing lowest counter value, relative 1
   619 00000268 89C8                        mov ax,cx               ; get number of pages
   620 0000026A 48                          dec ax                  ; make relative zero
   621 0000026B 89C3                        mov bx,ax               ; save value
   622 0000026D D1E0                        shl ax,1                ; x2
   623 0000026F D1E0                        shl ax,1                ; x4
   624 00000271 D1E0                        shl ax,1                ; x8
   625 00000273 29D8                        sub ax,bx               ; x7
   626 00000275 BB[8800]                    mov bx,OFFSET page_control wrt DGROUP   ; point to first page control structure
   627 00000278 01C3                        add bx,ax               ; bx -> last page control structure
   628                                  
   629                                  tpw_page_loop:
   630 0000027A 803F00                      cmp BYTE PTR [bx],0     ; see if page used
   631 0000027D 742E                        je  tpw_unused_page     ; no
   632 0000027F A1[1800]                    mov ax,WORD PTR [data_page]   ; get low word of page to write to
   633 00000282 3B4703                      cmp ax,[bx+3]           ; see if page matches
   634 00000285 751A                        jne tpw_nomatch         ; no
   635 00000287 A1[1A00]                    mov ax,WORD PTR [data_page+2] ; get high word of page to write to
   636 0000028A 3B4705                      cmp ax,[bx+5]           ; see if page matches
   637 0000028D 7512                        jne tpw_nomatch         ; no
   638 0000028F 89CA                        mov dx,cx               ; dx holds page number
   639 00000291 4A                          dec dx                  ; make relative zero
   640 00000292 88D6                        mov dh,dl               ; register move does effective x256 value multiply
   641 00000294 30D2                        xor dl,dl               ; zero low byte
   642 00000296 D0E6                        shl dh,1                ; x512
   643 00000298 D0E6                        shl dh,1                ; x1024
   644 0000029A D0E6                        shl dh,1                ; x2048
   645 0000029C D0E6                        shl dh,1                ; x4096, dx holds offset to proper page from page base
   646 0000029E E91201                      jmp NEAR PTR tpw_write_bytes    ; yes, write the bytes to the page
   647                                  
   648                                  ; page to write to does not match page found
   649                                  tpw_nomatch:
   650 000002A1 3B7F01                      cmp di,[bx+1]           ; see if new low counter value
   651 000002A4 760B                        jbe tpw_toloop          ; no
   652 000002A6 8B7F01                      mov di,[bx+1]           ; update new low counter value
   653 000002A9 89CA                        mov dx,cx               ; update page containing lowest counter value
   654 000002AB EB04                        jmp SHORT tpw_toloop
   655                                  
   656                                  ; page found is unused
   657                                  tpw_unused_page:
   658 000002AD 880E[0200]                  mov [unused_page],cl      ; save pointer to unused page
   659                                  
   660                                  tpw_toloop:
   661 000002B1 83EB07                      sub bx,7                ; drop bx to next page control structure
   662 000002B4 E2C4                        loop    tpw_page_loop   ; loop back for next page
   663                                  
   664                                  ; loop drops through, no matching pages were found
   665 000002B6 8A0E[0200]                  mov cl,[unused_page]
   666 000002BA 80F9FF                      cmp cl,255              ; see if an unused page was found
   667 000002BD 7573                        jne tpw_update          ; yes
   668                                  
   669                                  ; no unused page found, no pages match page to write to
   670                                  ; swap the least recently used page (in dx) to disk
   671 000002BF 89D7                        mov di,dx               ; save page swapped out in di
   672                                  
   673                                  ; seek to proper file position to write to
   674 000002C1 4A                          dec dx                  ; make page number relative zero
   675 000002C2 89D3                        mov bx,dx               ; bx == number of page to write to
   676                                  
   677                                  ; convert page number in bx to 7-byte offset
   678 000002C4 D1E3                        shl bx,1                ; x2
   679 000002C6 D1E3                        shl bx,1                ; x4
   680 000002C8 D1E3                        shl bx,1                ; x8
   681 000002CA 29D3                        sub bx,dx               ; x7
   682 000002CC 81C3[8800]                  add bx,OFFSET page_control wrt DGROUP   ; bx -> proper page control structure for page
   683 000002D0 8B4F05                      mov cx,[bx+5]           ; MSW of file offset
   684 000002D3 8B5703                      mov dx,[bx+3]           ; LSW of file
   685                                  
   686 000002D6 803E[0000]00                cmp byte [tmp_in_emsxms],0     ; see if temporary file in EMS/XMS
   687 000002DB 7405                        je  tpw_fileseek        ; no
   688 000002DD E89306                      call    ems_tempfile_seek
   689 000002E0 EB14                        jmp SHORT tpw_file_write
   690                                  
   691                                  tpw_fileseek:
   692 000002E2 8B1E[0000]                  mov bx,[image_handle]     ; get handle of temporary file
   693 000002E6 B80042                      mov ax,4200h            ; move file pointer, offset from start
   694 000002E9 CD21                        int 21h
   695 000002EB E8(0000)                    call    restore_ems_map
   696 000002EE 7306                        jnc tpw_file_write     ; no errors in seek
   697                                  
   698                                  tpw_file_err:
   699 000002F0 BA[0800]                    mov dx,OFFSET temp_file_name wrt DGROUP
   700 000002F3 E9(0000)                    jmp NEAR PTR dos_error  ; DOS file error
   701                                  
   702                                  ; write old page to file
   703                                  tpw_file_write:
   704 000002F6 89FA                        mov dx,di               ; get page swapped out
   705 000002F8 4A                          dec dx                  ; make page number relative zero
   706 000002F9 88D6                        mov dh,dl               ; register move does effective x256 value multiply
   707 000002FB 30D2                        xor dl,dl               ; zero low byte
   708 000002FD D0E6                        shl dh,1                ; x512
   709 000002FF D0E6                        shl dh,1                ; x1024
   710 00000301 D0E6                        shl dh,1                ; x2048
   711 00000303 D0E6                        shl dh,1                ; x4096, dx holds offset to proper page from page base
   712 00000305 B90010                      mov cx,4096             ; write 4K bytes
   713 00000308 A1[0600]                    mov ax,[temp_page_ptr]    ; get page base
   714 0000030B 1E                          push    ds              ; save critical register
   715                                  
   716 0000030C 803E[0000]00                cmp byte [tmp_in_emsxms],0     ; see if temporary file in EMS/XMS
   717 00000311 740A                        je  tpw_filewrite       ; no
   718 00000313 8ED8                        mov ds,ax               ; ds:dx -> buffer area to write
   719 00000315 E84207                      call    ems_tempfile_write
   720 00000318 1F                          pop ds                  ; restore critical register
   721 00000319 89F9                        mov cx,di               ; cx == page to write to (page just swapped out)
   722 0000031B EB15                        jmp SHORT tpw_update
   723                                  
   724                                  tpw_filewrite:
   725 0000031D 8ED8                        mov ds,ax               ; ds:dx -> buffer area to write
   726 0000031F B440                        mov ah,40h              ; write to file
   727 00000321 CD21                        int 21h
   728 00000323 E8(0000)                    call    restore_ems_map
   729 00000326 1F                          pop ds                  ; restore critical register
   730 00000327 72C7                        jc  tpw_file_err        ; error writing to file
   731 00000329 39C8                    	cmp ax, cx
   732 0000032B B82700                  	mov ax, 27h			; insufficient disk space error
   733 0000032E 75C0                    	jne tpw_file_err
   734 00000330 89F9                        mov cx,di               ; cx == page to write to (page just swapped out)
   735                                  
   736                                  ; update page control structure
   737                                  tpw_update:
   738 00000332 49                          dec cx                  ; make page number relative zero
   739 00000333 89CF                        mov di,cx               ; save page number relative 0 in di
   740 00000335 89CB                        mov bx,cx               ; bx == number of page to write to
   741                                  
   742                                  ; convert page number in bx to 7-byte offset
   743 00000337 D1E3                        shl bx,1                ; x2
   744 00000339 D1E3                        shl bx,1                ; x4
   745 0000033B D1E3                        shl bx,1                ; x8
   746 0000033D 29CB                        sub bx,cx               ; x7
   747 0000033F 81C3[8800]                  add bx,OFFSET page_control wrt DGROUP   ; bx -> proper page control structure for page
   748 00000343 C60701                      mov BYTE PTR [bx],1     ; flag page is used
   749 00000346 A1[0000]                    mov ax,[lru_counter]
   750 00000349 894701                      mov [bx+1],ax           ; update counter in appropriate page control structure
   751 0000034C A1[1800]                    mov ax,WORD PTR [data_page]
   752 0000034F 894703                      mov [bx+3],ax           ; update low word of range
   753 00000352 89C2                        mov dx,ax               ; save as LSW of file offset
   754 00000354 A1[1A00]                    mov ax,WORD PTR [data_page+2]
   755 00000357 894705                      mov [bx+5],ax           ; update high word of range
   756 0000035A 89C1                        mov cx,ax               ; save as MSW of file offset
   757                                  
   758                                  ; seek to new page in file
   759 0000035C 803E[0000]00                cmp byte [tmp_in_emsxms],0     ; see if temporary file in EMS/XMS
   760 00000361 7405                        je  tpw_fileseek2       ; no
   761 00000363 E80D06                      call    ems_tempfile_seek
   762 00000366 EB11                        jmp SHORT tpw_readpage
   763                                  
   764                                  tpw_fileseek2:
   765 00000368 8B1E[0000]                  mov bx,[image_handle]     ; get handle of temporary file
   766 0000036C B80042                      mov ax,4200h            ; move file pointer, offset from start
   767 0000036F CD21                        int 21h
   768 00000371 E8(0000)                    call    restore_ems_map
   769                                  
   770                                  to_tpw_file_err_CY:
   771 00000374 7303E977FF                  jc  tpw_file_err        ; error seeking to new position
   772                                  
   773                                  ; read page in from file
   774                                  tpw_readpage:
   775 00000379 89FA                        mov dx,di               ; get page number (relative zero) to read in from file
   776 0000037B 88D6                        mov dh,dl               ; register move does effective x256 value multiply
   777 0000037D 30D2                        xor dl,dl               ; zero low byte
   778 0000037F D0E6                        shl dh,1                ; x512
   779 00000381 D0E6                        shl dh,1                ; x1024
   780 00000383 D0E6                        shl dh,1                ; x2048
   781 00000385 D0E6                        shl dh,1                ; x4096, dx holds offset to proper page from page base
   782 00000387 B90010                      mov cx,4096             ; read 4K bytes
   783 0000038A A1[0600]                    mov ax,[temp_page_ptr]    ; get page base
   784 0000038D 1E                          push    ds              ; save critical register
   785                                  
   786 0000038E 803E[0000]00                cmp byte [tmp_in_emsxms],0     ; see if temporary file in EMS/XMS
   787 00000393 7408                        je  tpw_fileread        ; no
   788 00000395 8ED8                        mov ds,ax               ; ds:dx -> buffer area to read into
   789 00000397 E8E205                      call    ems_tempfile_read
   790 0000039A 1F                          pop ds                  ; restore critical register
   791 0000039B EB16                        jmp SHORT tpw_write_bytes
   792                                  
   793                                  tpw_fileread:
   794 0000039D 8ED8                        mov ds,ax               ; ds:dx -> buffer area to read into
   795 0000039F B43F                        mov ah,3fh              ; read file
   796 000003A1 CD21                        int 21h
   797 000003A3 E8(0000)                    call    restore_ems_map
   798 000003A6 1F                          pop ds                  ; restore critical register
   799 000003A7 72CB                        jc  to_tpw_file_err_CY     ; error reading from file
   800 000003A9 39C8                    	cmp ax, cx
   801 000003AB B8FEFF                  	mov ax, -2		; short read code
   802 000003AE 7403E93DFF              	jne tpw_file_err
   803                                  
   804                                  ; write bytes to memory page
   805                                  tpw_write_bytes:
   806 000003B3 8CC3                        mov bx,es
   807 000003B5 8B3E[0800]                  mov di,[data_remainder]   ; get page position to start writing
   808 000003B9 01D7                        add di,dx               ; add in page offset from base
   809 000003BB A1[0600]                    mov ax,[temp_page_ptr]
   810 000003BE 8EC0                        mov es,ax               ; es:di -> location in memory image to place data
   811 000003C0 8B0E[0A00]                  mov cx,[bytes_to_write]   ; get number of bytes to transfer in cx
   812 000003C4 1E                          push    ds              ; save critical register
   813 000003C5 8EDB                        mov ds,bx               ; ds:si -> source buffer
   814                                  
   815 000003C7 89F0                        mov ax,si               ; get offset of source
   816 000003C9 01C8                        add ax,cx               ; add in number of bytes to write
   817 000003CB 7204                        jc  tpw_buff_wrap       ; overflow, buffer will wrap
   818 000003CD 39E8                        cmp ax,bp               ; see if past buffer end for total bytes written
   819 000003CF 7616                        jbe tpw_no_buff_wrap    ; no
   820                                  
   821                                  tpw_buff_wrap:
   822 000003D1 89CA                        mov dx,cx               ; save old byte count to write
   823 000003D3 89E9                        mov cx,bp               ; get buffer end
   824 000003D5 29F1                        sub cx,si               ; compute bytes to buffer end
   825 000003D7 89C8                        mov ax,cx               ; save byte count written this pass
   826 000003D9 D1E9                        shr cx,1                ; convert byte count to write to words
   827 000003DB F3A5                        rep movsw               ; move the string
   828 000003DD D1D1                        rcl cx,1                ; pick up carry
   829 000003DF F3A4                        rep movsb               ; transfer leftover byte, if any
   830 000003E1 31F6                        xor si,si               ; wrap source offset to start of i/o buffer
   831 000003E3 29C2                        sub dx,ax               ; update total count, subtracting off byte count written
   832 000003E5 89D1                        mov cx,dx               ; get new total in cx
   833                                  
   834                                  tpw_no_buff_wrap:
   835 000003E7 D1E9                        shr cx,1                ; convert byte count to write to words
   836 000003E9 F3A5                        rep movsw               ; move the string
   837 000003EB D1D1                        rcl cx,1                ; pick up carry
   838 000003ED F3A4                        rep movsb               ; transfer leftover byte, if any
   839                                  
   840                                  tpw_ret:
   841 000003EF 8CD8                        mov ax,ds
   842 000003F1 8EC0                        mov es,ax               ; restore es -> file buffer
   843 000003F3 1F                          pop ds                  ; restore critical register
   844                                  
   845 000003F4 59                          pop cx
   846 000003F5 C3                          ret
   847                                  temp_page_write ENDP
   848                                  
   849                                  ;*****************************
   850                                  ;* UPDATE_TEMP_FILE          *
   851                                  ;*****************************
   852                                  
   853                                  ; flush pages to disk
   854                                  ; destroys ax,bx
   855                                  
   856                                  update_temp_file PROC
   857 000003F6 E80F00                      call    flush_temp_pages    ; flush temp file pages to disk
   858 000003F9 A1[0600]                    mov ax,[temp_page_ptr]    ; get page base segment pointer
   859 000003FC 8EC0                        mov es,ax               ; es -> memory block to be released
   860 000003FE B449                        mov ah,49h              ; release memory
   861 00000400 CD21                        int 21h
   862 00000402 7303                        jnc cltp_ret            ; no errors releasing memory
   863 00000404 E9(0000)                    jmp NEAR PTR dos_error
   864                                  
   865                                  cltp_ret:
   866 00000407 C3                          ret
   867                                  update_temp_file ENDP
   868                                  
   869                                  ;*****************************
   870                                  ;* FLUSH_TEMP_PAGES          *
   871                                  ;*****************************
   872                                  
   873                                  ; flush temporary file pages to disk
   874                                  ; destroys ax,bx,cx,dx,di
   875                                  
   876                                  flush_temp_pages    PROC
   877 00000408 BB[8800]                    mov bx,OFFSET page_control wrt DGROUP   ; point to first page control structure
   878 0000040B 31FF                        xor di,di               ; init page number to zero
   879 0000040D 30ED                        xor ch,ch
   880 0000040F 8A0E[0000]                  mov cl,[temp_file_pages]  ; get number of pages to loop through
   881                                  
   882                                  ftp_loop:
   883 00000413 51                          push    cx              ; save loop counter
   884 00000414 53                          push    bx              ; save bx -> page control structures
   885 00000415 803F00                      cmp BYTE PTR [bx],0     ; see if page used
   886 00000418 746F                        je  ftp_2               ; no
   887                                  
   888                                  ; seek to proper file position to write to
   889 0000041A 89FB                        mov bx,di               ; get page number, relative zero
   890                                  
   891                                  ; convert page number in bx to 7-byte offset
   892 0000041C D1E3                        shl bx,1                ; x2
   893 0000041E D1E3                        shl bx,1                ; x4
   894 00000420 D1E3                        shl bx,1                ; x8
   895 00000422 29FB                        sub bx,di               ; x7
   896 00000424 81C3[8800]                  add bx,OFFSET page_control wrt DGROUP   ; bx -> proper page control structure for page
   897 00000428 8B4F05                      mov cx,[bx+5]           ; MSW of file offset
   898 0000042B 8B5703                      mov dx,[bx+3]           ; LSW of file
   899                                  
   900 0000042E 803E[0000]00                cmp byte [tmp_in_emsxms],0     ; see if temporary file in EMS/XMS
   901 00000433 7405                        je  ftp_fileseek        ; no
   902 00000435 E83B05                      call    ems_tempfile_seek
   903 00000438 EB14                        jmp SHORT ftp_file_write
   904                                  
   905                                  ftp_fileseek:
   906 0000043A 8B1E[0000]                  mov bx,[image_handle]     ; get handle of temporary file
   907 0000043E B80042                      mov ax,4200h            ; move file pointer, offset from start
   908 00000441 CD21                        int 21h
   909 00000443 E8(0000)                    call    restore_ems_map
   910 00000446 7306                        jnc ftp_file_write     ; no errors in seek
   911                                  
   912                                  ftp_file_err:
   913 00000448 BA[0800]                    mov dx,OFFSET temp_file_name wrt DGROUP
   914 0000044B E9(0000)                    jmp NEAR PTR dos_error  ; DOS file error
   915                                  
   916                                  ; write to file
   917                                  ftp_file_write:
   918 0000044E 89FA                        mov dx,di               ; get page number relative zero
   919 00000450 88D6                        mov dh,dl               ; register move does effective x256 value multiply
   920 00000452 30D2                        xor dl,dl               ; zero low byte
   921 00000454 D0E6                        shl dh,1                ; x512
   922 00000456 D0E6                        shl dh,1                ; x1024
   923 00000458 D0E6                        shl dh,1                ; x2048
   924 0000045A D0E6                        shl dh,1                ; x4096, dx holds offset to proper page from page base
   925 0000045C B90010                      mov cx,4096             ; write 4K bytes
   926 0000045F 8B1E[0000]                  mov bx,[image_handle]     ; get handle of temporary file
   927 00000463 A1[0600]                    mov ax,[temp_page_ptr]    ; get page base
   928 00000466 1E                          push    ds              ; save critical register
   929                                  
   930 00000467 803E[0000]00                cmp byte [tmp_in_emsxms],0     ; see if temporary file in EMS/XMS
   931 0000046C 7408                        je  ftp_filewrite       ; no
   932 0000046E 8ED8                        mov ds,ax               ; ds:dx -> buffer area to write
   933 00000470 E8E705                      call    ems_tempfile_write
   934 00000473 1F                          pop ds                  ; restore critical register
   935 00000474 EB13                        jmp SHORT ftp_2
   936                                  
   937                                  ftp_filewrite:
   938 00000476 8ED8                        mov ds,ax               ; ds:dx -> buffer area to write
   939 00000478 B440                        mov ah,40h              ; write to file
   940 0000047A CD21                        int 21h
   941 0000047C E8(0000)                    call    restore_ems_map
   942 0000047F 1F                          pop ds                  ; restore critical register
   943 00000480 72C6                        jc  ftp_file_err        ; error writing to file
   944 00000482 39C8                    	cmp ax, cx
   945 00000484 B82700                  	mov ax, 27h			; insufficient disk space error
   946 00000487 75BF                    	jne ftp_file_err
   947                                  
   948                                  ftp_2:
   949 00000489 5B                          pop bx                  ; restore bx -> page control structures
   950 0000048A 59                          pop cx                  ; restore loop counter
   951 0000048B 83C307                      add bx,7                ; point to next page control structure
   952 0000048E 47                          inc di                  ; bump page number
   953 0000048F E282                        loop    ftp_loop        ; loop till complete
   954 00000491 C3                          ret
   955                                  flush_temp_pages    ENDP
   956                                  
   957                                  ;*****************************
   958                                  ;* DUMP_TEMP_FILE            *
   959                                  ;*****************************
   960                                  
   961                                  ; dump temporary file bytes to executable file
   962                                  ; upon entry di:si contain number of bytes to write to executable file
   963                                  ; destroys ax,bx,cx,dx,di,si
   964                                  
   965                                  dump_temp_file  PROC
   966 00000492 803E[0000]00                cmp byte [tmp_in_xms],0        ; see if XMS used to hold temporary file
   967 00000497 750E                        jne to_dte              ; yes
   968 00000499 803E[0000]00                cmp byte [is_no_ems],0         ; see if EMS used
   969 0000049E 751F                        jne dtf_1               ; no
   970 000004A0 803E[0000]00                cmp byte [tmp_in_emsxms],0     ; see if temporary file in EMS (known not in XMS)
   971 000004A5 7403                        je  dtf_use_ems         ; no, use EMS for buffering
   972                                  
   973                                  to_dte:
   974 000004A7 E9A802                      jmp NEAR PTR dump_tempfile_ems  ; dump temporary file in EMS
   975                                  
   976                                  ; tempory file not in EMS, but EMS is used,
   977                                  ; by definition it's okay to use physical page 0 for i/o buffer
   978                                  dtf_use_ems:
   979 000004AA 31DB                        xor bx,bx
   980 000004AC 88D8                        mov al,bl
   981 000004AE E8(0000)                    call    map_ems_page    ; map page 0
   982                                  %if 0 ;COMMENT #
   983                                      inc bx
   984                                      mov al,bl
   985                                      call    map_ems_page    ; map page 1
   986                                      inc bx
   987                                      mov al,bl
   988                                      call    map_ems_page    ; map page 2
   989                                      inc bx
   990                                      mov al,bl
   991                                      call    map_ems_page    ; map page 3
   992                                      mov ax,0fff0h
   993                                  END COMMENT #
   994                                  %endif
   995                                  
   996 000004B1 B80040                  	mov	ax,16384
   997 000004B4 A3[0C00]                    mov [temp_buffer_size],ax ; keep size of temporary buffer
   998 000004B7 A1[0000]                    mov ax,[ems_base]         ; use base of EMS memory as temporary base
   999 000004BA A3[0E00]                    mov [temp_buffer_base],ax
  1000 000004BD EB31                        jmp SHORT dtf_4a
  1001                                  
  1002                                  dtf_1:
  1003 000004BF B448                        mov ah,48h              ; allocate memory
  1004 000004C1 BBFFFF                      mov bx,0ffffh           ; force request to fail, function will return largest available block
  1005 000004C4 CD21                        int 21h
  1006 000004C6 83F808                      cmp ax,8                ; insufficient memory error is expected
  1007 000004C9 7403                        je dtf_2
  1008 000004CB E9(0000)                    jmp NEAR PTR dos_error  ; other errors are fatal
  1009                                  
  1010                                  dtf_2:
  1011 000004CE 81FBFF0F                    cmp bx,0fffh            ; check if more than 0fffh free paragraphs (64K-16 bytes)
  1012 000004D2 7603                        jbe dtf_3               ; no
  1013 000004D4 BBFF0F                      mov bx,0fffh            ; allocate only up to 64K-16 for temporary disk write
  1014                                  
  1015                                  dtf_3:
  1016 000004D7 89D8                        mov ax,bx
  1017 000004D9 D1E0                        shl ax,1                ; convert paragraphs allocated to bytes, x2
  1018 000004DB D1E0                        shl ax,1                ; x4
  1019 000004DD D1E0                        shl ax,1                ; x8
  1020 000004DF D1E0                        shl ax,1                ; x16
  1021 000004E1 A3[0C00]                    mov [temp_buffer_size],ax ; keep size of temporary buffer
  1022 000004E4 B448                        mov ah,48h              ; allocate memory
  1023 000004E6 CD21                        int 21h
  1024 000004E8 7303                        jnc dtf_4               ; should be successful, since using <= previous max value
  1025 000004EA E9(0000)                    jmp NEAR PTR dos_error  ; any error is fatal
  1026                                  
  1027                                  dtf_4:
  1028 000004ED A3[0E00]                    mov [temp_buffer_base],ax ; save address of temporary buffer
  1029                                  
  1030                                  dtf_4a:
  1031 000004F0 8B1E[0000]                  mov bx,[image_handle]
  1032 000004F4 31C9                        xor cx,cx               ; move file pointer to start of file
  1033 000004F6 31D2                        xor dx, dx
  1034 000004F8 B80042                      mov ax,4200h            ; move file pointer, offset from file start
  1035 000004FB CD21                        int 21h
  1036 000004FD E8(0000)                    call    restore_ems_map
  1037 00000500 7306                        jnc @F			; no errors in seek
  1038                                  
  1039                                  dtf_temp_err:
  1040 00000502 BA[0800]                    mov dx,OFFSET temp_file_name wrt DGROUP
  1041 00000505 E9(0000)                    jmp NEAR PTR dos_error  ; DOS file error
  1042                                  
  1043                                  @@:
  1044 00000508 8B16[0200]              	mov dx, word [skip_length]
  1045 0000050C 29D6                    	sub si, dx
  1046 0000050E 19CF                    	sbb di, cx
  1047 00000510 7309                    	jae @F
  1048 00000512 B93400                      mov cx, 52              ; internal error value
  1049                                  .internal:
  1050 00000515 B80000                      mov ax,INTERNAL_ERR     ; put warplink error code in ax
  1051 00000518 E9(0000)                    jmp NEAR PTR link_error ; transfer control to error handler
  1052                                  @@:
  1053 0000051B 89D1                    	mov cx, dx
  1054 0000051D E32D                    	jcxz .nocheck
  1055 0000051F 3B0E[0C00]              	cmp cx, [temp_buffer_size]
  1056 00000523 7605                    	jbe @F
  1057 00000525 B93600                      mov cx, 54              ; internal error value
  1058 00000528 EBEB                    	jmp .internal
  1059                                  
  1060                                  @@:
  1061 0000052A A1[0E00]                	mov ax, [temp_buffer_base]
  1062 0000052D 50                      	push ax
  1063 0000052E 1E                      	push ds
  1064 0000052F 8ED8                    	mov ds, ax
  1065 00000531 31D2                    	xor dx, dx		; -> buffer
  1066 00000533 B43F                        mov ah,3fh              ; read file
  1067 00000535 CD21                        int 21h
  1068 00000537 E8(0000)                    call    restore_ems_map
  1069 0000053A 1F                      	pop ds
  1070 0000053B 72C5                    	jc dtf_temp_err
  1071 0000053D 39C8                    	cmp ax, cx
  1072 0000053F B8FEFF                  	mov ax, -2		; short read code
  1073 00000542 75BE                    	jne dtf_temp_err
  1074 00000544 58                      	pop ax			; => buffer
  1075 00000545 06                      	push es
  1076 00000546 8EC0                    	mov es, ax		; => buffer
  1077 00000548 E8(0000)                	call check_com_cut
  1078 0000054B 07                      	pop es
  1079                                  .nocheck:
  1080                                  
  1081                                  dtf_5:
  1082 0000054C 8B0E[0C00]                  mov cx,[temp_buffer_size] ; number of bytes to read
  1083 00000550 85FF                        test di,di               ; see if byte count to write is 64K or more
  1084 00000552 7508                        jne dtf_6               ; yes, write a zero_block_size chunk
  1085 00000554 39CE                        cmp si, cx ; see if byte count is at least temp_buffer_size
  1086 00000556 7304                        jae dtf_6               ; no, exit temp_buffer_size writing loop
  1087                                  
  1088                                  ; transfer leftover bytes (file size modulo temp_buffer_size)
  1089 00000558 89F1                        mov cx,si               ; cx holds bytes to write
  1090 0000055A E35A                        jcxz    dtf_release     ; no bytes to write, release memory, close files
  1091                                  
  1092                                  dtf_6:
  1093 0000055C 51                      	push cx
  1094 0000055D 31D2                        xor dx,dx               ; zero offset into buffer
  1095 0000055F 8B1E[0000]                  mov bx,[image_handle]
  1096 00000563 A1[0E00]                    mov ax,[temp_buffer_base]
  1097 00000566 1E                          push    ds              ; save ds, critical register
  1098                                  
  1099 00000567 3B06[0000]              	cmp	ax,[ems_base]			; see if reading to EMS
  1100 0000056B 8ED8                        mov ds,ax               ; ds -> segment to start write, DON'T MODIFY FLAGS
  1101 0000056D 7508                    	jne	dtf_fileread1		; no
  1102 0000056F E8(0000)                	call	read_to_ems		; call read to EMS code
  1103 00000572 1F                          pop ds                  ; restore ds -> warplink data
  1104 00000573 728D                        jc  dtf_temp_err        ; error reading from file
  1105 00000575 EB14                    	jmp	SHORT dtf_readdone1
  1106                                  
  1107                                  dtf_fileread1:
  1108 00000577 B43F                        mov ah,3fh              ; read file
  1109 00000579 CD21                        int 21h
  1110 0000057B E8(0000)                    call    restore_ems_map
  1111 0000057E 1F                          pop ds                  ; restore ds -> warplink data
  1112 0000057F 7281                        jc  dtf_temp_err        ; error reading from file
  1113 00000581 39C8                    	cmp ax, cx
  1114 00000583 B8FEFF                  	mov ax, -2		; short read code
  1115 00000586 7403E977FF              	jne dtf_temp_err
  1116                                  dtf_readdone1:
  1117                                  
  1118                                  dtf_6a:
  1119 0000058B 59                      	pop cx
  1120 0000058C 31D2                        xor dx,dx               ; zero offset into buffer
  1121 0000058E 8B1E[0000]                  mov bx,[exe_handle]
  1122 00000592 A1[0E00]                    mov ax,[temp_buffer_base]
  1123 00000595 1E                          push    ds              ; save ds, critical register
  1124 00000596 8ED8                        mov ds,ax               ; ds -> segment to start write
  1125 00000598 B440                        mov ah,40h              ; write to file
  1126 0000059A CD21                        int 21h
  1127 0000059C E8(0000)                    call    restore_ems_map
  1128 0000059F 1F                          pop ds                  ; restore ds -> warplink data
  1129 000005A0 7207                        jc  dtf_exe_err         ; error occurred
  1130                                  
  1131                                  dtf_7:
  1132 000005A2 39C8                        cmp ax, cx			; see if out of disk space
  1133 000005A4 7409                        je dtf_7a              ; no
  1134                                  
  1135                                  ; out of disk space for executable file
  1136                                  dtf_diskspace:
  1137 000005A6 B83A00                      mov ax,DISK_FULL_ERR
  1138                                  
  1139                                  dtf_exe_err:
  1140 000005A9 BA[0000]                    mov dx,OFFSET exe_name wrt DGROUP
  1141 000005AC E9(0000)                    jmp NEAR PTR link_error ; transfer to error handler
  1142                                  
  1143                                  dtf_7a:
  1144 000005AF 29CE                        sub si, cx		; back off number of bytes written from bytes to write
  1145 000005B1 83DF00                      sbb di,0                ; borrow to high word
  1146 000005B4 EB96                        jmp SHORT dtf_5         ; loop for next write
  1147                                  
  1148                                  ; release temporary buffer back to dos if not thru EMS
  1149                                  dtf_release:
  1150                                  
  1151 000005B6 803E[0000]00                cmp byte [is_no_ems],0         ; see if EMS used for i/o buffer
  1152 000005BB 740A                        je  dtf_close           ; yes, no memory to release
  1153                                  
  1154 000005BD 8E06[0E00]                  mov es,[temp_buffer_base]
  1155 000005C1 B449                        mov ah,49h              ; release memory
  1156 000005C3 CD21                        int 21h
  1157 000005C5 72E2                        jc  dtf_exe_err         ; error occurred in memory release
  1158                                  
  1159                                  ; done read from temporary file, close and delete it if not in EMS
  1160                                  dtf_close:
  1161 000005C7 E82701                  	call	delete_temp_file
  1162 000005CA C3                          ret
  1163                                  dump_temp_file  ENDP
  1164                                  
  1165                                  
  1166                                   global create_wllist_temps
  1167                                  create_wllist_temps:
  1168 000005CB D006[0000]              	rol byte [is_wllist_enabled], 1
  1169 000005CF 7338                    	jnc .ret
  1170                                  
  1171 000005D1 BA[0000]                    mov dx,OFFSET _wllist_temp_file_name wrt DGROUP ; ds:dx -> ASCIIZ path spec
  1172 000005D4 BE[9500]                    mov si,OFFSET def_wllist_tempname wrt DGROUP   ; ds:si -> default file name
  1173 000005D7 E83000                      call .create
  1174 000005DA A3[0000]                    mov [_wllist_temp_handle],ax     ; save handle of temporary file
  1175 000005DD F616[FFFF]              	not byte [_wllist_temp_file_name - 1]
  1176                                  
  1177 000005E1 BA[0000]                    mov dx,OFFSET _wllist_obj_file_name wrt DGROUP ; ds:dx -> ASCIIZ path spec
  1178 000005E4 BE[A200]                    mov si,OFFSET def_wllist_objname wrt DGROUP   ; ds:si -> default file name
  1179 000005E7 E82000                      call .create
  1180 000005EA A3[0000]                    mov [_wllist_obj_handle],ax     ; save handle of temporary file
  1181 000005ED F616[FFFF]              	not byte [_wllist_obj_file_name - 1]
  1182                                  
  1183                                   extern parfilename, no_extension, save_obj_name
  1184 000005F1 1E                      	push ds
  1185 000005F2 07                      	pop es
  1186 000005F3 BF[0000]                	mov di, parfilename
  1187 000005F6 BE[0000]                	mov si, _wllist_obj_file_name
  1188                                  @@:
  1189 000005F9 A4                      	movsb
  1190 000005FA 807CFF00                	cmp byte [si - 1], 0
  1191 000005FE 75F9                    	jne @B
  1192 00000600 C606[0000]00            	mov byte [no_extension], 0
  1193 00000605 E8(0000)                	call save_obj_name
  1194 00000608 C3                      	retn
  1195                                  
  1196                                  .ret:
  1197 00000609 C3                      	retn
  1198                                  
  1199                                  .create:
  1200 0000060A 31C9                        xor cx,cx               ; create normal file
  1201 0000060C 89D3                    	mov bx, dx
  1202 0000060E 807FFE00                    cmp byte [bx - 2],0       ; see if temporary file specified
  1203 00000612 7531                        jne .2               ; yes, use it
  1204                                  
  1205 00000614 C7072E5C                	mov word [bx], ".\"
  1206 00000618 89D0                        mov ax,dx
  1207 0000061A 83C002                      add ax,2                ; point to first char past default path
  1208 0000061D A3[1000]                    mov [temp_path_end],ax    ; save pointer to memory variable
  1209 00000620 8916[1600]                  mov word [tempname], dx
  1210 00000624 52                          push dx
  1211 00000625 E83DFB                      call    check_tmp_var   ; check if TMP environment variable to use
  1212 00000628 5A                          pop dx
  1213 00000629 31C9                        xor cx,cx               ; create normal file
  1214 0000062B 803E[0000]02                cmp byte [dos_version],2       ; see if we can use create temporary file dos function
  1215 00000630 7413                        je  .2               ; no, using DOS 2.x
  1216                                  
  1217                                  ; use DOS 3.x create temporary file function
  1218 00000632 8B1E[1000]                  mov bx,[temp_path_end]
  1219 00000636 C60700                      mov BYTE PTR [bx],0     ; reduce name to path only
  1220 00000639 B45A                        mov ah,5ah              ; create temporary file
  1221 0000063B CD21                        int 21h
  1222 0000063D E8(0000)                    call    restore_ems_map
  1223 00000640 730F                        jnc .3               ; no errors
  1224 00000642 E9(0000)                    jmp NEAR PTR dos_error  ; error creating file
  1225                                  
  1226                                  ; use DOS 2.x create or truncate file (VM.TMP) function
  1227                                  .2:
  1228 00000645 B43C                        mov ah,3ch              ; create or truncate file
  1229 00000647 CD21                        int 21h
  1230 00000649 E8(0000)                    call    restore_ems_map
  1231 0000064C 7303                        jnc .3
  1232 0000064E E9(0000)                    jmp NEAR PTR dos_error  ; error creating file
  1233                                  
  1234                                  .3:
  1235 00000651 C3                      	retn
  1236                                  
  1237                                  
  1238                                   global delete_wllist_temps
  1239                                  delete_wllist_temps:
  1240 00000652 D006[0000]              	rol byte [is_wllist_enabled], 1
  1241 00000656 734E                    	jnc @FF
  1242 00000658 50                      	push ax
  1243                                  		; close both handles first
  1244 00000659 BBFFFF                  	mov bx, -1
  1245 0000065C 871E[0000]              	xchg bx, [_wllist_temp_handle]
  1246 00000660 B43E                    	mov ah, 3Eh
  1247 00000662 CD21                    	int 21h
  1248 00000664 E8(0000)                    call    restore_ems_map
  1249 00000667 BBFFFF                  	mov bx, -1
  1250 0000066A 871E[0000]              	xchg bx, [_wllist_obj_handle]
  1251 0000066E B43E                    	mov ah, 3Eh
  1252 00000670 CD21                    	int 21h
  1253 00000672 E8(0000)                    call    restore_ems_map
  1254                                  		; want to preserve files ?
  1255 00000675 D006[0000]              	rol byte [is_wllist_preserve_enabled], 1
  1256 00000679 722C                    	jc .display
  1257 0000067B 58                      	pop ax
  1258                                  		; no, delete
  1259 0000067C BB[0000]                	mov bx, _wllist_temp_file_name
  1260 0000067F 31C0                    	xor ax, ax
  1261 00000681 8647FF                  	xchg al, byte [bx - 1]
  1262 00000684 84C0                    	test al, al
  1263 00000686 7409                    	jz @F
  1264 00000688 89DA                    	mov dx, bx
  1265 0000068A B441                    	mov ah, 41h
  1266 0000068C CD21                    	int 21h
  1267 0000068E E8(0000)                    call    restore_ems_map
  1268                                  @@:
  1269 00000691 BB[0000]                	mov bx, _wllist_obj_file_name
  1270 00000694 31C0                    	xor ax, ax
  1271 00000696 8647FF                  	xchg al, byte [bx - 1]
  1272 00000699 84C0                    	test al, al
  1273 0000069B 7409                    	jz @F
  1274 0000069D 89DA                    	mov dx, bx
  1275 0000069F B441                    	mov ah, 41h
  1276 000006A1 CD21                    	int 21h
  1277 000006A3 E8(0000)                    call    restore_ems_map
  1278                                  @@:
  1279 000006A6 C3                      	retn
  1280                                  
  1281                                  .display:
  1282 000006A7 BE[4600]                	mov si, msg_wllist_preserve_1
  1283 000006AA E82A00                  	call cmsg
  1284 000006AD BE[6300]                	mov si, msg_wllist_preserve_2
  1285 000006B0 E82400                  	call cmsg
  1286 000006B3 BE[0000]                	mov si, _wllist_temp_file_name
  1287 000006B6 E82B00                  	call zmsg
  1288 000006B9 BE[4600]                	mov si, msg_wllist_preserve_1
  1289 000006BC E81800                  	call cmsg
  1290 000006BF BE[7400]                	mov si, msg_wllist_preserve_3
  1291 000006C2 E81200                  	call cmsg
  1292 000006C5 BE[0000]                	mov si, _wllist_obj_file_name
  1293 000006C8 E81900                  	call zmsg
  1294 000006CB 58                      	pop ax
  1295 000006CC 84C0                    	test al, al
  1296 000006CE 7406                    	jz .retn
  1297 000006D0 BE[8200]                	mov si, msg_wllist_preserve_linebreak
  1298 000006D3 E80100                  	call cmsg
  1299                                  .retn:
  1300 000006D6 C3                      	retn
  1301                                  
  1302                                   global cmsg, zmsg
  1303                                  cmsg:
  1304 000006D7 AC                      	lodsb
  1305 000006D8 98                      	cbw
  1306 000006D9 91                      	xchg cx, ax
  1307 000006DA 89F2                    	mov dx, si
  1308                                  .write:
  1309 000006DC BB0100                  	mov bx, 1
  1310 000006DF B440                    	mov ah, 40h
  1311 000006E1 CD21                    	int 21h
  1312 000006E3 C3                      	retn
  1313                                  
  1314                                  zmsg:
  1315 000006E4 89F2                    	mov dx, si
  1316 000006E6 31C9                    	xor cx, cx
  1317                                  @@:
  1318 000006E8 41                      	inc cx
  1319 000006E9 AC                      	lodsb
  1320 000006EA 84C0                    	test al, al
  1321 000006EC 75FA                    	jnz @B
  1322 000006EE 49                      	dec cx
  1323 000006EF EBEB                    	jmp cmsg.write
  1324                                  
  1325                                  
  1326                                  ;*****************************
  1327                                  ;* DELETE_TEMP_FILE          *
  1328                                  ;*****************************
  1329                                  
  1330                                  ; delete temporary file from disk, if it exists
  1331                                  ; destroys ax,bx,dx
  1332                                  
  1333                                  delete_temp_file	PROC
  1334 000006F1 31C0                    	xor	ax,ax
  1335 000006F3 3806[0000]                  cmp [is_ondisk],al		; check if temporary file
  1336 000006F7 741B                        je  dlf_ret				; no
  1337                                  
  1338 000006F9 3806[0000]                  cmp [tmp_in_emsxms],al	; see if temporary file is in EMS/XMS
  1339 000006FD 7515                        jne dlf_ret				; yes
  1340                                  
  1341                                  ; close and delete temporary file, no longer needed
  1342 000006FF 8B1E[0000]                  mov bx,[image_handle]
  1343 00000703 B43E                        mov ah,3eh              ; close file
  1344 00000705 CD21                        int 21h
  1345 00000707 E8(0000)                    call    restore_ems_map
  1346                                  
  1347 0000070A BA[0800]                    mov dx,OFFSET temp_file_name wrt DGROUP
  1348 0000070D B441                        mov ah,41h              ; delete file
  1349 0000070F CD21                        int 21h
  1350 00000711 E8(0000)                    call    restore_ems_map
  1351                                  
  1352                                  dlf_ret:
  1353 00000714 C3                      	ret
  1354                                  delete_temp_file	ENDP
  1355                                  
  1356                                  ;*****************************
  1357                                  ;* ZERO_MEM_IMAGE            *
  1358                                  ;*****************************
  1359                                  
  1360                                  ; zero executable memory image
  1361                                  ; upon entry ax contains segment of memory image
  1362                                  ; dx:bx contain count of bytes to zero
  1363                                  ; destroys ax,di
  1364                                  
  1365                                  zero_mem_image  PROC
  1366 00000715 06                          push    es              ; save critical register
  1367 00000716 53                          push    bx
  1368 00000717 52                          push    dx
  1369 00000718 8EC0                        mov es,ax               ; es -> memory image
  1370 0000071A 89D8                        mov ax,bx
  1371 0000071C 09D0                        or  ax,dx               ; make sure that memory image size is nonzero
  1372 0000071E 742E                        je  zmi_ret             ; zero memory image size
  1373                                  
  1374                                  zmi_loop:
  1375 00000720 31FF                        xor di,di               ; zero offset into block
  1376 00000722 89F8                        mov ax,di               ; zero word to store
  1377 00000724 09D2                        or  dx,dx               ; see if high word set
  1378 00000726 7506                        jne zmi_2               ; yes, a 32K can be zero'ed
  1379 00000728 81FB0080                    cmp bx,32768            ; see if 32K chunk to zero out in low word
  1380 0000072C 7216                        jb  zmi_3               ; no, zero out leftover amount
  1381                                  
  1382                                  zmi_2:
  1383 0000072E 81EB0080                    sub bx,32768            ; subtract bytes zero'd
  1384 00000732 83DA00                      sbb dx,0                ; borrow to high word
  1385 00000735 B90040                      mov cx,16384            ; zero 16K words (32K bytes)
  1386 00000738 F3AB                        rep stosw               ; do it
  1387 0000073A 8CC1                        mov cx,es
  1388 0000073C 81C10008                    add cx,800h             ; adjust past 32K block zero'd (800h paragraphs)
  1389 00000740 8EC1                        mov es,cx               ; update segment pointer
  1390 00000742 EBDC                        jmp SHORT zmi_loop      ; loop back for next chunk to zero
  1391                                  
  1392                                  zmi_3:
  1393 00000744 89D9                        mov cx,bx               ; get byte count in cx
  1394 00000746 D1E9                        shr cx,1                ; convert byte count to zero to words
  1395 00000748 F3AB                        rep stosw               ; store zeros
  1396 0000074A D1D1                        rcl cx,1                ; pick up carry
  1397 0000074C F3AA                        rep stosb               ; zero leftover byte, if any
  1398                                  
  1399                                  zmi_ret:
  1400 0000074E 5A                          pop dx                  ; restore critical register
  1401 0000074F 5B                          pop bx
  1402 00000750 07                          pop es
  1403 00000751 C3                          ret
  1404                                  zero_mem_image  ENDP
  1405                                  
  1406                                  ;*****************************
  1407                                  ;* DUMP_TEMPFILE_EMS         *
  1408                                  ;*****************************
  1409                                  
  1410                                  ; dump temporary file bytes EMS/XMS to executable file
  1411                                  ; upon entry di:si contain number of bytes to write to executable file
  1412                                  ; destroys ax,bx,cx,dx,di,si,bp
  1413                                  
  1414                                  dump_tempfile_ems   PROC
  1415 00000752 803E[0000]00                cmp byte [tmp_in_xms],0        ; see if temporary file in XMS
  1416 00000757 7402                        je  dte_ems             ; no
  1417 00000759 EB69                        jmp NEAR PTR dump_tempfile_xms  ; dump temporary file to XMS
  1418                                  
  1419                                  dte_ems:
  1420 0000075B 31ED                        xor bp,bp
  1421 0000075D 032E[1200]                  add bp,[ems_first_tmp]    ; bp holds current EMS page of temp file
  1422                                  
  1423                                  dte_writeloop:
  1424 00000761 B90040                      mov cx,16384            ; get bytes to write chunk
  1425 00000764 09FF                        or  di,di               ; see if byte count to write is 64K or more
  1426 00000766 7506                        jne dte_mapin           ; yes, write a 16K chunk
  1427 00000768 39CE                        cmp si,cx               ; see if byte count left is at least 16K
  1428 0000076A 7302                        jae dte_mapin           ; yes, use 16K
  1429 0000076C 89F1                        mov cx,si               ; no, use amount left to write
  1430                                  
  1431                                  dte_mapin:
  1432 0000076E E353                        jcxz    dte_ret         ; no more bytes to write
  1433 00000770 89EB                        mov bx,bp               ; get logical page
  1434 00000772 30C0                        xor al,al               ; map in EMS physical page 0
  1435 00000774 E8(0000)                    call    map_ems_page
  1436                                  
  1437 00000777 31D2                        xor dx,dx               ; zero offset into buffer
  1438 00000779 51                      	push cx
  1439 0000077A 8716[0200]              	xchg dx, word [skip_length]	; reset for next iteration, dx -> data
  1440 0000077E 29D1                    	sub cx, dx			; skip this part
  1441 00000780 7309                    	jae @F				; if not negative -->
  1442 00000782 B80000                      mov ax,INTERNAL_ERR     ; put warplink error code in ax
  1443 00000785 B93200                      mov cx, 50              ; internal error value
  1444 00000788 E9(0000)                    jmp NEAR PTR link_error ; transfer control to error handler
  1445                                  
  1446                                  @@:
  1447 0000078B 85D2                    	test dx, dx
  1448 0000078D 740D                    	jz @F
  1449 0000078F 51                      	push cx
  1450 00000790 06                      	push es
  1451 00000791 89D1                    	mov cx, dx
  1452 00000793 8E06[0000]              	mov es, [ems_base]
  1453 00000797 E8(0000)                	call check_com_cut
  1454 0000079A 07                      	pop es
  1455 0000079B 59                      	pop cx
  1456                                  @@:
  1457 0000079C 8B1E[0000]                  mov bx,[exe_handle]
  1458 000007A0 A1[0000]                    mov ax,[ems_base]
  1459 000007A3 1E                          push    ds              ; save ds, critical register
  1460 000007A4 8ED8                        mov ds,ax               ; ds -> segment to start write
  1461 000007A6 B440                        mov ah,40h              ; write to file
  1462 000007A8 CD21                        int 21h
  1463 000007AA 1F                          pop ds                  ; restore ds -> warplink data
  1464 000007AB 7207                        jc  dte_doserr          ; error occurred
  1465                                  
  1466 000007AD 39C8                        cmp ax, cx			; see if out of disk space
  1467 000007AF 7409                        je dte_2               ; no
  1468                                  
  1469                                  ; out of disk space for executable file
  1470 000007B1 B83A00                      mov ax,DISK_FULL_ERR
  1471                                  
  1472                                  dte_doserr:
  1473 000007B4 BA[0000]                    mov dx,OFFSET exe_name wrt DGROUP
  1474 000007B7 E9(0000)                    jmp NEAR PTR link_error ; transfer to error handler
  1475                                  
  1476                                  dte_2:
  1477 000007BA 58                      	pop ax
  1478 000007BB 29C6                        sub si,ax               ; back off number of bytes written from bytes to write
  1479 000007BD 83DF00                      sbb di,0                ; borrow to high word
  1480 000007C0 45                          inc bp                  ; bump logical page
  1481 000007C1 EB9E                        jmp SHORT dte_writeloop ; loop for next write
  1482                                  
  1483                                  dte_ret:
  1484 000007C3 C3                          ret
  1485                                  dump_tempfile_ems   ENDP
  1486                                  
  1487                                  ;*****************************
  1488                                  ;* DUMP_TEMPFILE_XMS         *
  1489                                  ;*****************************
  1490                                  
  1491                                  ; dump temporary file bytes EMS/XMS to executable file
  1492                                  ; upon entry di:si contain number of bytes to write to executable file
  1493                                  ; destroys ax,bx,cx,dx,di,si,bp
  1494                                  
  1495                                  dump_tempfile_xms   PROC
  1496 000007C4 31C0                        xor ax,ax
  1497 000007C6 A3[F800]                    mov WORD PTR [tmp_empb.es_src_offset],ax  ; zero init the XMS offset in parameter block
  1498 000007C9 A3[FA00]                    mov WORD PTR [tmp_empb.es_src_offset+2],ax
  1499 000007CC A3[F400]                    mov WORD PTR [tmp_empb.es_len+2],ax   ; zero high word of block length
  1500 000007CF A3[FC00]                    mov [tmp_empb.es_dest_handle],ax  ; zero handle (conventional memory destination)
  1501 000007D2 A3[FE00]                    mov WORD PTR [tmp_empb.es_dest_offset],ax ; zero offset
  1502                                  
  1503 000007D5 A1[1400]                    mov ax,[xms_tmp_handle]
  1504 000007D8 A3[F600]                    mov [tmp_empb.es_src_handle],ax   ; source is XMS
  1505 000007DB A1[0000]                    mov ax,[ems_trans_block]
  1506 000007DE A3[0001]                    mov WORD PTR [tmp_empb.es_dest_offset+2],ax   ; destination segment
  1507 000007E1 89F5                        mov bp,si               ; get low word of bytes to write in bp
  1508                                  
  1509                                  dtx_xloop:
  1510 000007E3 09FF                        or  di,di               ; see if high word of bytes to write is nonzero
  1511 000007E5 750A                        jne dtx_2               ; nonzero, write 16K block
  1512 000007E7 89E9                        mov cx,bp               ; get low word of bytes to write
  1513 000007E9 E371                        jcxz    dtx_ret         ; no bytes to write, done
  1514 000007EB 81F90040                    cmp cx,16384            ; only write up to 16K
  1515 000007EF 7203                        jb  dtx_3               ; below 16K
  1516                                  
  1517                                  dtx_2:
  1518 000007F1 B90040                      mov cx,16384            ; write 16K block
  1519                                  
  1520                                  dtx_3:
  1521 000007F4 89C8                        mov ax,cx
  1522 000007F6 40                          inc ax
  1523 000007F7 24FE                        and al,0feh             ; round to word boundary for XMM acceptable length
  1524 000007F9 A3[F200]                    mov WORD PTR [tmp_empb.es_len],ax ; length of block to transfer low word
  1525                                  
  1526 000007FC B40B                        mov ah,0bh              ; move extend memory block
  1527 000007FE BE[F200]                    mov si,OFFSET tmp_empb wrt DGROUP   ; ds:si -> parameter block
  1528 00000801 FF1E[0000]                  call    far [xms_addr]
  1529 00000805 E8(0000)                    call    check_xms_error ; see if error occurred
  1530                                  
  1531 00000808 8B1E[0000]                  mov bx,[exe_handle]
  1532 0000080C 31D2                        xor dx,dx               ; zero offset into buffer
  1533 0000080E 51                      	push cx
  1534 0000080F 8716[0200]              	xchg dx, word [skip_length]	; reset for next iteration, dx -> data
  1535 00000813 29D1                    	sub cx, dx			; skip this part
  1536 00000815 7309                    	jae @F				; if not negative -->
  1537 00000817 B80000                      mov ax,INTERNAL_ERR     ; put warplink error code in ax
  1538 0000081A B93300                      mov cx, 51              ; internal error value
  1539 0000081D E9(0000)                    jmp NEAR PTR link_error ; transfer control to error handler
  1540                                  
  1541                                  @@:
  1542 00000820 85D2                    	test dx, dx
  1543 00000822 740D                    	jz @F
  1544 00000824 51                      	push cx
  1545 00000825 06                      	push es
  1546 00000826 89D1                    	mov cx, dx
  1547 00000828 8E06[0000]              	mov es, [ems_trans_block]
  1548 0000082C E8(0000)                	call check_com_cut
  1549 0000082F 07                      	pop es
  1550 00000830 59                      	pop cx
  1551                                  @@:
  1552 00000831 1E                          push    ds              ; save critical register
  1553 00000832 8E1E[0000]                  mov ds,[ems_trans_block]  ; ds:dx -> write buffer
  1554 00000836 B440                        mov ah,40h              ; write file
  1555 00000838 CD21                        int 21h
  1556 0000083A 1F                          pop ds                  ; restore ds -> warplink data
  1557 0000083B E8(0000)                    call    restore_ems_map
  1558 0000083E 721D                        jc  dtx_doserr          ; error writing file
  1559 00000840 39C8                    	cmp ax, cx
  1560 00000842 B82700                  	mov ax, 27h			; insufficient disk space error
  1561 00000845 7516                    	jne dtx_doserr
  1562 00000847 59                      	pop cx
  1563                                  
  1564 00000848 010E[F800]                  add WORD PTR [tmp_empb.es_src_offset],cx  ; bump dword offset in XMS
  1565 0000084C 8316[FA00]00                adc WORD [tmp_empb.es_src_offset+2],0 ; carry to high word
  1566 00000851 29CD                        sub bp,cx               ; subtract off bytes written
  1567 00000853 83DF00                      sbb di,0                ; borrow to high word
  1568 00000856 89E8                        mov ax,bp
  1569 00000858 09F8                        or  ax,di               ; see if written all bytes in temporary file
  1570 0000085A 7587                        jne dtx_xloop           ; not done yet
  1571                                  
  1572                                  dtx_ret:
  1573 0000085C C3                          ret
  1574                                  
  1575                                  dtx_doserr:
  1576 0000085D BA[0000]                    mov dx,OFFSET exe_name wrt DGROUP
  1577 00000860 E9(0000)                    jmp NEAR PTR dos_error  ; error opening file
  1578                                  
  1579                                  dump_tempfile_xms   ENDP
  1580                                  
  1581                                  ;*****************************
  1582                                  ;* EMS_TEMPFILE_CREATE       *
  1583                                  ;*****************************
  1584                                  
  1585                                  ; create temporary file in EMS if there is room, zero fill pages
  1586                                  ; if temporary file successfully placed in EMS, set tmp_in_emsxms flag to nonzero
  1587                                  ; destroys ax,bx,cx,dx,di
  1588                                  
  1589                                  ems_tempfile_create PROC
  1590 00000863 803E[0000]00                cmp byte [is_xms],0            ; see if XMS used
  1591 00000868 7508                        jne etc_getblock        ; yes
  1592 0000086A 803E[0000]00                cmp byte [is_no_ems],0         ; see if EMS is available
  1593 0000086F 7401                        je  etc_getblock        ; yes
  1594 00000871 C3                          ret
  1595                                  
  1596                                  etc_getblock:
  1597 00000872 06                          push    es              ; save critical register
  1598 00000873 57                          push    di
  1599 00000874 56                          push    si
  1600                                  
  1601 00000875 A1[0000]                    mov ax,WORD PTR [image_size]  ; get size of temporary file in bytes
  1602 00000878 8B16[0200]                  mov dx,WORD PTR [image_size+2]
  1603 0000087C 05FF3F                      add ax,16383            ; round up to next page
  1604 0000087F 83D200                      adc dx,0                ; carry to high word
  1605 00000882 E8(0000)                    call    convert_to_page ; convert bytes in dx:ax to 16K blocks in ax
  1606                                  
  1607                                  ; check if enough XMS to save temporary file, priority over EMS
  1608 00000885 803E[0000]00                cmp byte [is_xms],0            ; see if XMS used
  1609 0000088A 7422                        je  etc_chkems          ; no
  1610 0000088C 89C7                        mov di,ax               ; save 16K block count in di
  1611 0000088E D1E0                        shl ax,1                ; *2
  1612 00000890 D1E0                        shl ax,1                ; *4
  1613 00000892 D1E0                        shl ax,1                ; *8
  1614 00000894 D1E0                        shl ax,1                ; *16, ax holds 1K block count
  1615 00000896 89C1                        mov cx,ax               ; save 1K block count
  1616 00000898 B408                        mov ah,8                ; query free extended memory
  1617 0000089A FF1E[0000]                  call    far [xms_addr]
  1618 0000089E E8(0000)                    call    check_xms_error ; see if error occurred
  1619 000008A1 39C8                        cmp ax,cx               ; see if largest free block meets 1K block count
  1620 000008A3 736E                        jae etc_usexms          ; yes, use XMS
  1621                                  
  1622                                  ; not enough XMS to stuff temporary file in it, try EMS
  1623                                  eos_noxms:
  1624 000008A5 803E[0000]00                cmp byte [is_no_ems],0         ; see if EMS used
  1625 000008AA 7563                        jne etc_ret             ; no
  1626 000008AC 89F8                        mov ax,di               ; get 16K block count back in ax
  1627                                  
  1628                                  etc_chkems:
  1629 000008AE 3B06[0000]                  cmp ax,[ems_page_avail]   ; see if enough pages are available to hold temporary file
  1630 000008B2 7621                    	jbe	etc_success			; yes
  1631                                  
  1632                                  ; not enough available pages, see if overlays used, if not, see if flushing will work
  1633 000008B4 833E[0000]00                cmp word [ovl_count],0         ; see if any overlays
  1634 000008B9 7554                        jne etc_ret				; yes
  1635                                  
  1636                                  ; see if flushing will give enough room for temporary file stashing
  1637 000008BB 8B3E[0000]              	mov di,[ems_pagecount]	; get total ems pages
  1638 000008BF 83EF04                  	sub di,4				; subtract amount used for file i/o buffer
  1639 000008C2 39F8                    	cmp ax,di				; see if enough total ems pages allocated to hold temporary file
  1640 000008C4 7749                    	ja  etc_ret				; no, not enough room
  1641                                  
  1642                                  ; flush out stashing of modules
  1643 000008C6 C606[0000]01            	mov byte [ems_pages_flushed],1	; set pages flushed flag
  1644 000008CB C706[0000]0400          	mov word [ems_first_avail],4	; reset first available page flag
  1645 000008D1 893E[0000]              	mov [ems_page_avail],di	; adjust pages available back to pre-module stashed status
  1646                                  
  1647                                  etc_success:
  1648 000008D5 2906[0000]                  sub [ems_page_avail],ax   ; subtract off pages used by temporary file
  1649 000008D9 89C1                        mov cx,ax               ; save temporary file page count
  1650 000008DB A1[0000]                    mov ax,[ems_first_avail]  ; get first available page
  1651 000008DE A3[1200]                    mov [ems_first_tmp],ax    ; save as first used temporary file page
  1652 000008E1 010E[0000]                  add [ems_first_avail],cx  ; bump up first available page past those used by temporary file
  1653 000008E5 C606[0000]01                mov byte [tmp_in_emsxms],1     ; set temporary file in EMS/XMS flag
  1654                                  
  1655 000008EA FF36[0000]                  push    WORD [ems_currmap]    ; save current logical state of physical page 0
  1656 000008EE 8B1E[1200]                  mov bx,[ems_first_tmp]    ; bx holds first EMS logical page for temporary file
  1657 000008F2 8E06[0000]                  mov es,[ems_base]
  1658                                  
  1659                                  etc_loop:
  1660 000008F6 51                          push    cx              ; save pages left to map in and zero
  1661 000008F7 30C0                        xor al,al
  1662 000008F9 E8(0000)                    call    map_ems_page    ; map in proper page
  1663 000008FC 31FF                        xor di,di               ; es:di -> EMS page frame physical page zero
  1664 000008FE 89F8                        mov ax,di
  1665 00000900 B90020                      mov cx,8192
  1666 00000903 F3AB                        rep stosw               ; zero 16K page
  1667 00000905 43                          inc bx                  ; bump EMS logical page
  1668 00000906 59                          pop cx                  ; restore pages left
  1669 00000907 E2ED                        loop    etc_loop        ; loop until complete
  1670                                  
  1671                                  ; restore previous logical state of physical page 0
  1672 00000909 30C0                        xor al,al
  1673 0000090B 5B                          pop bx
  1674 0000090C E8(0000)                    call    map_ems_page
  1675                                  
  1676                                  etc_ret:
  1677 0000090F 5E                          pop si                  ; restore critical register
  1678 00000910 5F                          pop di
  1679 00000911 07                          pop es
  1680 00000912 C3                          ret
  1681                                  
  1682                                  etc_usexms:
  1683 00000913 89CA                        mov dx,cx               ; get blocks to allocate in K
  1684 00000915 B409                        mov ah,9                ; allocate extended memory block
  1685 00000917 FF1E[0000]                  call    far [xms_addr]
  1686 0000091B E8(0000)                    call    check_xms_error ; see if error occurred
  1687 0000091E 8916[1400]                  mov [xms_tmp_handle],dx   ; save xms handle
  1688 00000922 8916[FC00]                  mov [tmp_empb.es_dest_handle],dx  ; save in parameter block
  1689                                  
  1690 00000926 31C0                        xor ax,ax
  1691 00000928 A3[FE00]                    mov WORD PTR [tmp_empb.es_dest_offset],ax ; zero init the XMS offset in parameter block
  1692 0000092B A3[0001]                    mov WORD PTR [tmp_empb.es_dest_offset+2],ax
  1693 0000092E A3[F400]                    mov WORD PTR [tmp_empb.es_len+2],ax   ; zero high word of block length
  1694 00000931 A3[F600]                    mov [tmp_empb.es_src_handle],ax   ; zero handle (conventional memory source)
  1695 00000934 A3[F800]                    mov WORD PTR [tmp_empb.es_src_offset],ax  ; zero offset
  1696                                  
  1697 00000937 FEC0                        inc al
  1698 00000939 A2[0000]                    mov [tmp_in_emsxms],al    ; set temporary file in EMS/XMS flag
  1699 0000093C A2[0000]                    mov [tmp_in_xms],al       ; set temporary file in XMS only flag
  1700                                  
  1701 0000093F B80040                      mov ax,16384
  1702 00000942 A3[F200]                    mov WORD PTR [tmp_empb.es_len],ax ; length of block to transfer low word
  1703 00000945 A1[0000]                    mov ax,[ems_trans_block]
  1704 00000948 A3[FA00]                    mov WORD PTR [tmp_empb.es_src_offset+2],ax    ; source segment
  1705                                  
  1706                                  ; zero the source 16K transfer block
  1707 0000094B 89FB                        mov bx,di               ; save count of 16K pages in bx
  1708 0000094D 8EC0                        mov es,ax
  1709 0000094F 31FF                        xor di,di
  1710 00000951 B90020                      mov cx,8192             ; 8K words
  1711 00000954 31C0                        xor ax,ax
  1712 00000956 F3AB                        rep stosw
  1713                                  
  1714                                  ; transfer to XMS
  1715                                  etc_xmstrans:
  1716 00000958 B40B                        mov ah,0bh              ; move extend memory block
  1717 0000095A BE[F200]                    mov si,OFFSET tmp_empb wrt DGROUP   ; ds:si -> parameter block
  1718 0000095D E8(0000)                    call    safe_xms_addr
  1719 00000960 E8(0000)                    call    check_xms_error ; see if error occurred
  1720                                  
  1721 00000963 8106[FE00]0040              add WORD [tmp_empb.es_dest_offset],16384  ; bump dword offset in XMS
  1722 00000969 8316[0001]00                adc WORD [tmp_empb.es_dest_offset+2],0    ; carry to high word
  1723                                  
  1724 0000096E 4B                          dec bx                  ; drop count of pages to read
  1725 0000096F 75E7                        jne etc_xmstrans        ; not done yet
  1726 00000971 EB9C                        jmp SHORT etc_ret
  1727                                  
  1728                                  ems_tempfile_create ENDP
  1729                                  
  1730                                  ;*****************************
  1731                                  ;* EMS_TEMPFILE_SEEK         *
  1732                                  ;*****************************
  1733                                  
  1734                                  ; seek to temporary file page/position in EMS
  1735                                  ; analogous to seek from start of file, function 4200h
  1736                                  ; upon entry cx:dx -> absolute file position
  1737                                  ; destroys ax,bx,cx,dx
  1738                                  
  1739                                  ems_tempfile_seek   PROC
  1740 00000973 8916[0400]                  mov WORD PTR [tmp_ems_pos],dx
  1741 00000977 890E[0600]                  mov WORD PTR [tmp_ems_pos+2],cx   ; carry to high word
  1742 0000097B C3                          ret
  1743                                  ems_tempfile_seek   ENDP
  1744                                  
  1745                                  ;*****************************
  1746                                  ;* EMS_TEMPFILE_READ         *
  1747                                  ;*****************************
  1748                                  
  1749                                  ; read bytes from temporary file in EMS/XMS at tmp_ems_pos
  1750                                  ; ds:dx -> read buffer, cx holds bytes to read
  1751                                  ; do NOT assume ds -> DGROUP upon entry
  1752                                  ; destroys ax,bx,cx
  1753                                  
  1754                                  ems_tempfile_read   PROC
  1755 0000097C 52                          push    dx              ; save critical register
  1756 0000097D 56                          push    si
  1757 0000097E 57                          push    di
  1758 0000097F 06                          push    es
  1759                                  
  1760 00000980 8CDB                        mov bx,ds               ; save -> write buffer
  1761 00000982 B8[ssss]                    mov ax,DGROUP
  1762 00000985 8ED8                        mov ds,ax               ; ds -> warplink data
  1763                                  
  1764 00000987 803E[0000]00                cmp byte [tmp_in_xms],0        ; see if temporary file in XMS
  1765 0000098C 7405                        je  etr_ems             ; no, in EMS
  1766 0000098E E87200                      call    xms_tmp_read    ; read in XMS
  1767 00000991 EB6B                        jmp SHORT etr_ret
  1768                                  
  1769                                  etr_ems:
  1770 00000993 FF36[0000]                  push    WORD [ems_currmap]    ; save current logical state of physical page 0
  1771 00000997 53                          push    bx              ; save -> write buffer segment on stack
  1772                                  
  1773 00000998 89D7                        mov di,dx               ; di -> read buffer
  1774 0000099A 8B16[0600]                  mov dx,WORD PTR [tmp_ems_pos+2]
  1775 0000099E A1[0400]                    mov ax,WORD PTR [tmp_ems_pos]
  1776 000009A1 89C6                        mov si,ax
  1777 000009A3 81E6FF3F                    and si,16383            ; si offsets into EMS page
  1778 000009A7 E8(0000)                    call    convert_to_page ; ax holds 16K page of position
  1779                                  
  1780 000009AA 010E[0400]                  add WORD PTR [tmp_ems_pos],cx     ; adjust for bytes read
  1781 000009AE 8316[0600]00                adc WORD [tmp_ems_pos+2],0    ; carry to high word
  1782 000009B3 0306[1200]                  add ax,[ems_first_tmp]    ; adjust for first page used
  1783                                  
  1784 000009B7 89C3                        mov bx,ax               ; bx holds EMS logical page
  1785 000009B9 30C0                        xor al,al
  1786 000009BB E8(0000)                    call    map_ems_page    ; map in proper page
  1787 000009BE 07                          pop es                  ; es:di -> read buffer
  1788                                  
  1789 000009BF 8E1E[0000]                  mov ds,[ems_base]         ; ds:si -> source buffer in EMS
  1790                                  
  1791                                  eor_readloop:
  1792 000009C3 89F0                        mov ax,si               ; check if read from more than one page
  1793 000009C5 01C8                        add ax,cx
  1794 000009C7 720F                        jc  eor_offpage         ; carry implies read off page
  1795 000009C9 3D0040                      cmp ax,16384            ; check page limit
  1796 000009CC 770A                        ja  eor_offpage         ; off of page
  1797 000009CE D1E9                        shr cx,1                ; convert byte count to read to words
  1798 000009D0 F3A5                        rep movsw               ; move the string
  1799 000009D2 D1D1                        rcl cx,1                ; pick up carry
  1800 000009D4 F3A4                        rep movsb               ; transfer leftover byte, if any
  1801 000009D6 EB1C                        jmp SHORT eor_2
  1802                                  
  1803                                  eor_offpage:
  1804 000009D8 B80040                      mov ax,16384
  1805 000009DB 29F0                        sub ax,si               ; ax holds bytes to read on page
  1806 000009DD 91                          xchg    ax,cx           ; cx holds bytes to read on page, ax holds total bytes
  1807 000009DE 29C8                        sub ax,cx               ; ax holds bytes to read beside current page
  1808 000009E0 D1E9                        shr cx,1                ; convert byte count to read to words
  1809 000009E2 F3A5                        rep movsw               ; move the string
  1810 000009E4 D1D1                        rcl cx,1                ; pick up carry
  1811 000009E6 F3A4                        rep movsb               ; transfer leftover byte, if any
  1812 000009E8 89C1                        mov cx,ax               ; update total bytes to read
  1813 000009EA 31F6                        xor si,si               ; position to start of next page
  1814 000009EC 43                          inc bx
  1815 000009ED 30C0                        xor al,al
  1816 000009EF E8(0000)                    call    map_ems_page    ; map in next page
  1817 000009F2 EBCF                        jmp SHORT eor_readloop  ; loop to read more bytes
  1818                                  
  1819                                  eor_2:
  1820 000009F4 8CC0                        mov ax,es               ; get read buffer segment
  1821 000009F6 8ED8                        mov ds,ax               ; restore ds to entry value
  1822                                  
  1823                                  ; restore previous logical state of physical page 0
  1824 000009F8 30C0                        xor al,al
  1825 000009FA 5B                          pop bx                  ; get previous logical state from stack
  1826 000009FB E8(0000)                    call    map_ems_page
  1827                                  
  1828                                  etr_ret:
  1829 000009FE 07                          pop es                  ; restore critical register
  1830 000009FF 5F                          pop di
  1831 00000A00 5E                          pop si
  1832 00000A01 5A                          pop dx
  1833 00000A02 C3                          ret
  1834                                  ems_tempfile_read   ENDP
  1835                                  
  1836                                  ;*****************************
  1837                                  ;* XMS_TMP_READ              *
  1838                                  ;*****************************
  1839                                  
  1840                                  ; read bytes from temporary file in XMS at tmp_ems_pos
  1841                                  ; bx:dx -> read buffer, cx holds bytes to read
  1842                                  ; safe to assume ds -> DGROUP upon entry
  1843                                  ; destroys ax,bx,cx,dx,si
  1844                                  
  1845                                  xms_tmp_read    PROC
  1846                                  
  1847                                  xtr_loop:
  1848 00000A03 89C8                        mov ax,cx
  1849 00000A05 24FE                        and al,0feh             ; round down to word boundary for XMM acceptable length
  1850 00000A07 A3[F200]                    mov WORD PTR [tmp_empb.es_len],ax ; length of block to transfer low word
  1851 00000A0A A1[1400]                    mov ax,[xms_tmp_handle]
  1852 00000A0D A3[F600]                    mov [tmp_empb.es_src_handle],ax   ; source is XMS memory
  1853 00000A10 A1[0400]                    mov ax,WORD PTR [tmp_ems_pos]     ; compute source offset
  1854 00000A13 A3[F800]                    mov WORD PTR [tmp_empb.es_src_offset],ax
  1855 00000A16 A1[0600]                    mov ax,WORD PTR [tmp_ems_pos+2]
  1856 00000A19 A3[FA00]                    mov WORD PTR [tmp_empb.es_src_offset+2],ax
  1857 00000A1C 31C0                        xor ax,ax
  1858 00000A1E A3[F400]                    mov WORD PTR [tmp_empb.es_len+2],ax   ; zero high word of block length
  1859 00000A21 A3[FC00]                    mov [tmp_empb.es_dest_handle],ax  ; destination is conventional memory
  1860 00000A24 8916[FE00]                  mov WORD PTR [tmp_empb.es_dest_offset],dx
  1861 00000A28 891E[0001]                  mov WORD PTR [tmp_empb.es_dest_offset+2],bx
  1862                                  
  1863 00000A2C B40B                        mov ah,0bh              ; move extend memory block
  1864 00000A2E BE[F200]                    mov si,OFFSET tmp_empb wrt DGROUP   ; ds:si -> parameter block
  1865 00000A31 E8(0000)                    call    safe_xms_addr
  1866 00000A34 E8(0000)                    call    check_xms_error ; see if error occurred
  1867                                  
  1868 00000A37 010E[0400]                  add WORD PTR [tmp_ems_pos],cx ; adjust for bytes read
  1869 00000A3B 8316[0600]00                adc WORD [tmp_ems_pos+2],0    ; carry to high word
  1870 00000A40 01CA                        add dx,cx               ; update destination offset
  1871 00000A42 83E101                      and cx,1                ; see if extra byte to transfer
  1872 00000A45 7410                        je  xtr_ret             ; no
  1873 00000A47 832E[0400]02                sub WORD [tmp_ems_pos],2  ; back up one byte not written, back up one byte for rewrite
  1874 00000A4C 831E[0600]00                sbb WORD [tmp_ems_pos+2],0    ; carry to high word
  1875 00000A51 83EA02                      sub dx,2                ; adjust back one byte, back one for byte not written
  1876 00000A54 41                          inc cx                  ; two bytes to write
  1877 00000A55 EBAC                        jmp SHORT xtr_loop      ; write the bytes
  1878                                  
  1879                                  xtr_ret:
  1880 00000A57 8EDB                        mov ds,bx               ; restore ds -> write buffer
  1881 00000A59 C3                          ret
  1882                                  xms_tmp_read    ENDP
  1883                                  
  1884                                  ;*****************************
  1885                                  ;* EMS_TEMPFILE_WRITE        *
  1886                                  ;*****************************
  1887                                  
  1888                                  ; write bytes to temporary file in EMS/XMS at tmp_ems_pos
  1889                                  ; ds:dx -> write buffer, cx holds bytes to write
  1890                                  ; do NOT assume ds -> DGROUP upon entry
  1891                                  ; destroys ax,bx,cx,dx
  1892                                  
  1893                                  ems_tempfile_write  PROC
  1894 00000A5A 56                          push    si              ; save critical register
  1895 00000A5B 57                          push    di
  1896 00000A5C 06                          push    es
  1897                                  
  1898 00000A5D 8CDB                        mov bx,ds               ; save -> write buffer
  1899 00000A5F B8[ssss]                    mov ax,DGROUP
  1900 00000A62 8ED8                        mov ds,ax               ; ds -> warplink data
  1901                                  
  1902 00000A64 803E[0000]00                cmp byte [tmp_in_xms],0        ; see if temporary file in XMS
  1903 00000A69 7405                        je  etw_ems             ; no, in EMS
  1904 00000A6B E87B00                      call    xms_tmp_write   ; write in XMS
  1905 00000A6E EB75                        jmp SHORT etw_ret
  1906                                  
  1907                                  etw_ems:
  1908 00000A70 FF36[0000]                  push    WORD [ems_currmap]    ; save current logical state of physical page 0
  1909 00000A74 53                          push    bx              ; save -> write buffer on stack
  1910                                  
  1911 00000A75 89D6                        mov si,dx               ; si -> write buffer
  1912 00000A77 8B16[0600]                  mov dx,WORD PTR [tmp_ems_pos+2]
  1913 00000A7B A1[0400]                    mov ax,WORD PTR [tmp_ems_pos]
  1914 00000A7E 89C7                        mov di,ax
  1915 00000A80 81E7FF3F                    and di,16383            ; di offsets into EMS page
  1916 00000A84 E8(0000)                    call    convert_to_page ; ax holds 16K page of position
  1917                                  
  1918 00000A87 010E[0400]                  add WORD PTR [tmp_ems_pos],cx    ; adjust for bytes written
  1919 00000A8B 8316[0600]00                adc WORD [tmp_ems_pos+2],0   ; carry to high word
  1920 00000A90 0306[1200]                  add ax,[ems_first_tmp]    ; adjust for first page used
  1921                                  
  1922 00000A94 89C3                        mov bx,ax               ; bx holds EMS logical page
  1923 00000A96 30C0                        xor al,al
  1924 00000A98 E8(0000)                    call    map_ems_page    ; map in proper page
  1925                                  
  1926 00000A9B 8E06[0000]                  mov es,[ems_base]         ; es:di -> destination EMS buffer
  1927 00000A9F 1F                          pop ds                  ; ds:si -> write buffer
  1928                                  
  1929                                  eow_writeloop:
  1930 00000AA0 89F8                        mov ax,di               ; check if write to more than one page
  1931 00000AA2 01C8                        add ax,cx
  1932 00000AA4 720F                        jc  eow_offpage         ; carry implies write off page
  1933 00000AA6 3D0040                      cmp ax,16384            ; check page limit
  1934 00000AA9 770A                        ja  eow_offpage         ; off of page
  1935 00000AAB D1E9                        shr cx,1                ; convert byte count to write to words
  1936 00000AAD F3A5                        rep movsw               ; move the string
  1937 00000AAF D1D1                        rcl cx,1                ; pick up carry
  1938 00000AB1 F3A4                        rep movsb               ; transfer leftover byte, if any
  1939 00000AB3 EB23                        jmp SHORT eow_2
  1940                                  
  1941                                  eow_offpage:
  1942 00000AB5 B80040                      mov ax,16384
  1943 00000AB8 29F8                        sub ax,di               ; ax holds bytes to write on page
  1944 00000ABA 91                          xchg    ax,cx           ; cx holds bytes to write on page, ax holds total bytes
  1945 00000ABB 29C8                        sub ax,cx               ; ax holds bytes to write beside current page
  1946 00000ABD D1E9                        shr cx,1                ; convert byte count to write to words
  1947 00000ABF F3A5                        rep movsw               ; move the string
  1948 00000AC1 D1D1                        rcl cx,1                ; pick up carry
  1949 00000AC3 F3A4                        rep movsb               ; transfer leftover byte, if any
  1950 00000AC5 89C1                        mov cx,ax               ; update total bytes to write
  1951 00000AC7 31FF                        xor di,di               ; position to start of next page
  1952 00000AC9 1E                          push    ds              ; save ds -> write buffer
  1953 00000ACA B8[ssss]                    mov ax,DGROUP
  1954 00000ACD 8ED8                        mov ds,ax               ; ds -> warplink data for map_ems_page
  1955 00000ACF 43                          inc bx
  1956 00000AD0 30C0                        xor al,al
  1957 00000AD2 E8(0000)                    call    map_ems_page    ; map in next page
  1958 00000AD5 1F                          pop ds                  ; restore ds -> write buffer
  1959 00000AD6 EBC8                        jmp SHORT eow_writeloop ; loop to read more bytes
  1960                                  
  1961                                  eow_2:
  1962 00000AD8 5B                          pop bx                  ; bx holds previous logical page of EMS page 0
  1963 00000AD9 1E                          push    ds              ; save ds -> write buffer
  1964 00000ADA B8[ssss]                    mov ax,DGROUP
  1965 00000ADD 8ED8                        mov ds,ax               ; ds -> warplink data
  1966                                  
  1967                                  ; restore previous logical state of EMS physical page 0
  1968 00000ADF 30C0                        xor al,al
  1969 00000AE1 E8(0000)                    call    map_ems_page
  1970 00000AE4 1F                          pop ds                  ; restore ds -> write buffer
  1971                                  
  1972                                  etw_ret:
  1973 00000AE5 07                          pop es                  ; restore critical register
  1974 00000AE6 5F                          pop di
  1975 00000AE7 5E                          pop si
  1976 00000AE8 C3                          ret
  1977                                  ems_tempfile_write  ENDP
  1978                                  
  1979                                  ;*****************************
  1980                                  ;* XMS_TMP_WRITE             *
  1981                                  ;*****************************
  1982                                  
  1983                                  ; write bytes to temporary file in XMS at tmp_ems_pos
  1984                                  ; bx:dx -> write buffer, cx holds bytes to write
  1985                                  ; ds -> DGROUP upon entry
  1986                                  ; destroys ax,bx,cx,dx,si
  1987                                  
  1988                                  xms_tmp_write   PROC
  1989 00000AE9 83F901                      cmp cx,1                ; see if bytes to write is one byte
  1990 00000AEC 7501                        jne xtw_loop            ; no
  1991 00000AEE 41                          inc cx                  ; round to two byte minimum
  1992                                  
  1993                                  xtw_loop:
  1994 00000AEF 89C8                        mov ax,cx
  1995 00000AF1 24FE                        and al,0feh             ; round down to word boundary for XMM acceptable length
  1996 00000AF3 A3[F200]                    mov WORD PTR [tmp_empb.es_len],ax ; length of block to transfer low word
  1997 00000AF6 31C0                        xor ax,ax
  1998 00000AF8 A3[F400]                    mov WORD PTR [tmp_empb.es_len+2],ax
  1999 00000AFB A3[F600]                    mov [tmp_empb.es_src_handle],ax   ; source is conventional memory
  2000 00000AFE 8916[F800]                  mov WORD PTR [tmp_empb.es_src_offset],dx
  2001 00000B02 891E[FA00]                  mov WORD PTR [tmp_empb.es_src_offset+2],bx
  2002 00000B06 A1[1400]                    mov ax,[xms_tmp_handle]
  2003 00000B09 A3[FC00]                    mov [tmp_empb.es_dest_handle],ax  ; destination is XMS memory
  2004 00000B0C A1[0400]                    mov ax,WORD PTR [tmp_ems_pos]     ; compute destination offset
  2005 00000B0F A3[FE00]                    mov WORD PTR [tmp_empb.es_dest_offset],ax
  2006 00000B12 A1[0600]                    mov ax,WORD PTR [tmp_ems_pos+2]
  2007 00000B15 A3[0001]                    mov WORD PTR [tmp_empb.es_dest_offset+2],ax
  2008                                  
  2009 00000B18 B40B                        mov ah,0bh              ; move extended memory block
  2010 00000B1A BE[F200]                    mov si,OFFSET tmp_empb wrt DGROUP   ; ds:si -> parameter block
  2011 00000B1D E8(0000)                    call    safe_xms_addr
  2012 00000B20 E8(0000)                    call    check_xms_error ; see if error occurred
  2013                                  
  2014 00000B23 010E[0400]                  add WORD PTR [tmp_ems_pos],cx ; adjust for bytes read
  2015 00000B27 8316[0600]00                adc WORD [tmp_ems_pos+2],0    ; carry to high word
  2016 00000B2C 01CA                        add dx,cx               ; update destination offset
  2017 00000B2E 83E101                      and cx,1                ; see if extra byte to transfer
  2018 00000B31 7410                        je  xtw_ret             ; no
  2019 00000B33 832E[0400]02                sub WORD [tmp_ems_pos],2  ; back up one byte not written, back up one byte for rewrite
  2020 00000B38 831E[0600]00                sbb WORD [tmp_ems_pos+2],0    ; carry to high word
  2021 00000B3D 83EA02                      sub dx,2                ; adjust back one byte, back one for byte not written
  2022 00000B40 41                          inc cx                  ; two bytes to write
  2023 00000B41 EBAC                        jmp SHORT xtw_loop      ; write the bytes
  2024                                  
  2025                                  xtw_ret:
  2026 00000B43 8EDB                        mov ds,bx               ; restore ds -> write buffer
  2027 00000B45 C3                          ret
  2028                                  xms_tmp_write   ENDP
  2029                                  
  2030                                  END
