$NOLIST
          NAME QuickLoader
      
; This is Os.LdrBfr.ASM

OS_CGROUP GROUP OS_CODE
OS_DGROUP GROUP OS_DATA

  PUBLIC SumBytes
  PUBLIC GetByte
  PUBLIC GetWord
  PUBLIC ReturnAX


  EXTRN OsRead: FAR
  EXTRN LoaderException: NEAR

  ASSUME  CS:OS_CGROUP
  ASSUME  DS:OS_DGROUP

OS_DATA   SEGMENT PUBLIC 'DATA'
  EXTRN loaderChecksum: BYTE
  EXTRN recordLength:   WORD
  EXTRN fileId:         WORD
  EXTRN index:          WORD
  EXTRN bufferPtr:      DWORD
OS_DATA   ENDS


OS_CODE   SEGMENT PUBLIC 'CODE'
       

; SumBytes: PROCEDURE (len);
;   DCL len WORD;
;  
; This will calculate the checksum of
; a string of bytes.  It will form
; a byte result and will store it into
; loaderChecksum.
 
;          constants

evnn   EQU 0                  ; length is evnn
odd    EQU 1                  ; length is odd

len    EQU WORD PTR [BP+6]    ; length parameter


SumBytes PROC NEAR
       PUSH DS
       PUSH BP
       MOV BP,SP
       
       MOV CX, len                 ; get length
       
       JCXZ Done                   ; done if length = 0

       MOV AX, DS                  ; store the DS reg into ES
       MOV ES, AX
       LDS SI, DS:bufferPtr        ; load the buffer ptr
       ADD SI, ES:index            ; point to current byte

       MOV BL, ES:loaderChecksum   ; init checksum       

       MOV DL,evnn                 ; assume evnn
       SHR CX,1                    ; cx := cx/2
       JNC EvenLength
       MOV DL,odd              
       JCXZ DoLastByte             ; done if length = 1

EvenLength:
       CLD                         ;Go forward                   
  
CheckLoop:
       LODSW 
       ADD BL, AL                  ; add low byte
       ADD BL, AH                  ; add high byte
       LOOP CheckLoop


       AND DL,DL                   ; is dl = 0 ?
       JZ  StoreIt
       
DoLastByte:
       MOV AL, BYTE PTR DS:[SI]    ; if odd then add in
       ADD BL, AL

StoreIt:
       MOV ES:loaderChecksum, BL   ; store back the checksum

Done:
       POP BP
       POP DS
       RET 2                       ; 2 bytes of parameters
SumBytes ENDP 
$EJECT


; GetByte: PROCEDURE BYTE;
;  
; This will grab the next byte from the
; data buffer and will return it in the AL
; register.

GetByte PROC NEAR

; Constants

bufferSize      EQU 7E0H
error           EQU WORD PTR [BP-2]


       LES AX, bufferPtr           ;SELECTOR (bufferPtr)
       MOV SI, DS:index            ;grab the index
       MOV AL, ES:[SI]             ;AL = buffer(index)
       DEC recordLength            ;recordLength = recordLength - 1
       CMP SI, bufferSize - 1      ;IF index < bufferSize - 1 THEN
       JNB ReadNewBuffer           

       INC SI                      ;index = index + 1
       MOV DS:index, SI

GetByteDone:
       ADD DS:LoaderChecksum, AL   ;update checksum count
       RET

ReadNewBuffer:
       PUSH BP
       MOV BP, SP
       PUSH CX                     ;Only one local

       PUSH CX                     ;save for GetWord
       PUSH AX                     ;save the return value
       PUSH FileID                 ;Setup for OsRead CALL
       PUSH ES                     ;SELECTOR (bufferPtr)
       MOV AX, 0     
       PUSH AX                     ;OFFSET (bufferPtr)
       MOV AX, bufferSize 
       PUSH AX
       LEA AX, error               ;@error
       PUSH SS
       PUSH AX
       CALL OsRead                 ;Read the new buffer
       
       PUSH error
       CALL LoaderException
       MOV DS:index, 0
       POP AX                      ;get the return value
       POP CX                      ;get CX REG for GetWord!!!
       MOV SP, BP
       POP BP
       JMP GetByteDone

GetByte ENDP
$EJECT

; GetWord: PROCEDURE WORD;
;  
; This will grab the next word from the
; data buffer and will return it in the AX
; register.

GetWord PROC NEAR

  CALL GetByte
  MOV CL, AL                       ;Save the byte
  CALL GetByte
  MOV AH, AL                       ;high order byte
  MOV AL, CL                       ;low order byte

ReturnAX PROC NEAR
  RET 
ReturnAX ENDP
GetWord ENDP

OS_CODE  ENDS
       
       END
