%TITLE          "File Management System Input/Output - CHiPS bv 1998"
;**********************************************************************
;**                                                                  **
;**  Program   : FMSIO                                               **
;**  Purpose   : File Management System Input/Output                 **
;**                                                                  **
;**  Author    : B.F. Schreurs                                       **
;**              Computer High Performance Software (CHiPS) bv       **
;**  Date      : August 17th, 1998                                   **
;**                                                                  **
;**  Calls     : [None]                                              **
;**                                                                  **
;**  Language  : Turbo Assembler                                     **
;**                                                                  **
;**********************************************************************
        IDEAL
        JUMPS

;----------------------------------------------------------------------
;--  Functions which can be called                                   --
;----------------------------------------------------------------------
        PUBLIC  FMSIO



;----------------------------------------------------------------------
;--  Equates                                                         --
;----------------------------------------------------------------------
include ".\equ\dos.equ"
include ".\equ\sysdep.equ"
include ".\equ\fmsio.equ"

;**********************************************************************
SEGMENT SSeg Para Stack 'STACK'
;**********************************************************************

        db        64 dup (0)            ; Stack

ENDS    SSeg

;**********************************************************************
SEGMENT DSeg Word Public 'DATA'
;**********************************************************************

;----------------------------------------------------------------------
;--  Structures                                                      --
;----------------------------------------------------------------------
include ".\str\fmsio.str"

;----------------------------------------------------------------------
;--  Working Storage                                                 --
;----------------------------------------------------------------------
Return_Code                     DW    NULL

FMS_Area_ptr_es                 DW    NULL
FMS_Area_ptr_di                 DW    NULL
Record_Nr                       DW    NULL
Bytes_Read                      DW    NULL
Bytes_To_Write                  DW    NULL
GET_PUT_Data_Buffer             DB    SPACE
PUT_CR_LF_Written               DB    LOGIC_NO
PUT_CR_LF                       DB    CR, LF

ENDS    DSeg



;**********************************************************************
SEGMENT CSeg Word Public 'CODE'
;**********************************************************************



;**********************************************************************
PROC    FMSIO
;**********************************************************************
        ASSUME  cs:CSeg
        ASSUME  ds:DSeg
        mov     ax, DSeg                        ; Initialize DS to address
        mov     ds, ax                          ; of data segment

        mov     bx, sp
        mov     ax, [ss:bx+2]                   ; si
        mov     bx, [ss:bx+4]                   ; ds

        mov     [FMS_Area_ptr_es], bx
        mov     [FMS_Area_ptr_di], ax

        mov     es, bx
        mov     di, ax
        mov     ax, [(FMS_Area ptr di).Record_Nr]
        mov     [Record_Nr], ax

        cmp     [(FMS_Area ptr di).Request], CMD_ACCESS_READNEXT
        je      @@10
        cmp     [(FMS_Area ptr di).Request], CMD_ACCESS_WRITENEXT
        je      @@11
        cmp     [(FMS_Area ptr di).Request], CMD_ACCESS_READ
        je      @@12
        cmp     [(FMS_Area ptr di).Request], CMD_ACCESS_WRITE
        je      @@13
        cmp     [(FMS_Area ptr di).Request], CMD_ACCESS_START
        je      @@14
        cmp     [(FMS_Area ptr di).Request], CMD_ACCESS_DELETE
        je      @@15
        cmp     [(FMS_Area ptr di).Request], CMD_ACCESS_GET
        je      @@20
        cmp     [(FMS_Area ptr di).Request], CMD_ACCESS_PUT
        je      @@21
        cmp     [(FMS_Area ptr di).Request], CMD_OPEN_INPUT
        je      @@30
        cmp     [(FMS_Area ptr di).Request], CMD_OPEN_OUTPUT
        je      @@31
        cmp     [(FMS_Area ptr di).Request], CMD_OPEN_EXTEND
        je      @@32
        cmp     [(FMS_Area ptr di).Request], CMD_OPEN_I_O
        je      @@33
        cmp     [(FMS_Area ptr di).Request], CMD_OPEN_CLOSE
        je      @@40
        cmp     [(FMS_Area ptr di).Request], CMD_OPEN_EXIST
        je      @@41
        cmp     [(FMS_Area ptr di).Request], CMD_OPEN_SCRATCH
        je      @@42
        jmp     @@99

@@10:
        call    FMSACCESS_Readnext
        jmp     @@99

@@11:
        call    FMSACCESS_Writenext
        jmp     @@99

@@12:
        call    FMSACCESS_Read
        jmp     @@99

@@13:
        call    FMSACCESS_Write
        jmp     @@99

@@14:
        call    FMSACCESS_Start
        jmp     @@99

@@15:
        call    FMSACCESS_Delete
        jmp     @@99

@@20:
        call    FMSACCESS_Get
        jmp     @@99

@@21:
        call    FMSACCESS_Put
        jmp     @@99

@@30:
        call    FMSOPEN_Input
        jmp     @@99

@@31:
        call    FMSOPEN_Output
        jmp     @@99

@@32:
        call    FMSOPEN_Extend
        jmp     @@99

@@33:
        call    FMSOPEN_I_O
        jmp     @@99

@@40:
        call    FMSOPEN_Close
        jmp     @@99

@@41:
        call    FMSOPEN_Exist
        jmp     @@99

@@42:
        call    FMSOPEN_Scratch
        jmp     @@99

@@99:
        ret

ENDP    FMSIO



;**********************************************************************
PROC    FMSACCESS_Readnext
;**********************************************************************
        push    ds

        xor     ax, ax
        mov     ah, DOS_READ_FROM_HANDLE
        mov     bx, [(FMS_Area ptr di).Disk_Handler]
        mov     cx, [(FMS_Area ptr di).Record_Size]
        mov     dx, [(FMS_Area ptr di).Data_Address_Lo]
        mov     ds, [(FMS_Area ptr di).Data_Address_Hi]
        int     DOS_SERVICE
        pop     ds
        mov     cx, STATUS_FILE_READ_ERROR
        jc      @@99                            ; Error!
        mov     cx, STATUS_FILE_AT_END_ERROR
        or      ax, ax                          ; End of file?
        jz      @@99                            ; Yes
                                                ; No, so
        mov     cx, STATUS_OK
        inc     [Record_Nr]
        mov     ax, [Record_Nr]
        mov     [(FMS_Area ptr di).Record_Nr], ax

@@99:
        mov     [(FMS_Area ptr di).Status], cx
        ret

ENDP    FMSACCESS_Readnext



;**********************************************************************
PROC    FMSACCESS_Writenext
;**********************************************************************
        push    ds

        xor     ax, ax
        mov     ah, DOS_WRITE_TO_HANDLE
        mov     bx, [(FMS_Area ptr di).Disk_Handler]
        mov     cx, [(FMS_Area ptr di).Record_Size]
        mov     dx, [(FMS_Area ptr di).Data_Address_Lo]
        mov     ds, [(FMS_Area ptr di).Data_Address_Hi]
        int     DOS_SERVICE
        pop     ds
        mov     cx, STATUS_FILE_WRITE_ERROR
        jc      @@99
        mov     cx, STATUS_DISK_FULL_ERROR
        or      ax, ax                          ; Disk Full?
        jz      @@99                            ; Yes
                                                ; No, so
        mov     cx, STATUS_OK
        inc     [Record_Nr]
        mov     ax, [Record_Nr]
        mov     [(FMS_Area ptr di).Record_Nr], ax

@@99:
        mov     [(FMS_Area ptr di).Status], cx
        ret

ENDP    FMSACCESS_Writenext



;**********************************************************************
PROC    FMSACCESS_Start
;**********************************************************************
;
; First position at the correct record number
;
        mov     ax, [(FMS_Area ptr di).Record_Nr]
        dec     ax
        dec     [Record_Nr]
        xor     bx, bx
        mov     cx, [(FMS_Area ptr di).Record_Size]
        xor     dx, dx
        mul     cx

;
; Add offset
;
        add     ax, [(FMS_Area ptr di).Offset]
        jnc     @@10
        inc     dx

@@10:
;
; Start from
;
        mov     cx, dx
        mov     dx, ax
        mov     ah, DOS_MOVE_FILE_POINTER
        mov     al, DOS_MOVE_FILE_POINTER_BEGIN
        mov     bx, [(FMS_Area ptr di).Disk_Handler]
        int     DOS_SERVICE
        mov     cx, STATUS_FILE_START_ERROR
        jc      @@99                            ; Error!

        mov     cx, STATUS_OK
        mov     ax, [Record_Nr]
        mov     [(FMS_Area ptr di).Record_Nr], ax

@@99:
        mov     [(FMS_Area ptr di).Status], cx
        ret

ENDP    FMSACCESS_Start



;**********************************************************************
PROC    FMSACCESS_Read
;**********************************************************************
        call    FMSACCESS_Start
        call    FMSACCESS_Readnext
        ret

ENDP    FMSACCESS_Read



;**********************************************************************
PROC    FMSACCESS_Write
;**********************************************************************
        call    FMSACCESS_Start
        call    FMSACCESS_Writenext
        ret

ENDP    FMSACCESS_Write



;**********************************************************************
PROC    FMSACCESS_Delete
;**********************************************************************
        call    FMSACCESS_Start

        push    es di

        xor     ax, ax                          ; Reset ax
        mov     al, NULL
        mov     cx, [(FMS_Area ptr di).Record_Size]
        mov     bx, [(FMS_Area ptr di).Data_Address_Lo]
        mov     es, [(FMS_Area ptr di).Data_Address_Hi]
        mov     di, bx
        rep     stosb                           ; Clear record

        pop     di es

        call    FMSACCESS_Writenext

        ret

ENDP    FMSACCESS_Delete



;**********************************************************************
PROC    FMSACCESS_Get
;**********************************************************************
        push    es di

        mov     [Bytes_Read], 0

        mov     bx, [(FMS_Area ptr di).Disk_Handler]
        mov     cx, [(FMS_Area ptr di).Data_Address_Lo]
        mov     es, [(FMS_Area ptr di).Data_Address_Hi]
        mov     di, cx
        mov     dx, offset GET_PUT_Data_Buffer

@@10:
        xor     ax, ax
        mov     ah, DOS_READ_FROM_HANDLE
        mov     cx, 1
        int     DOS_SERVICE
        mov     cx, STATUS_FILE_READ_ERROR
        jc      @@99                            ; Error!
        mov     cx, STATUS_FILE_AT_END_ERROR
        or      ax, ax                          ; End of file?
        jz      @@99                            ; Yes
                                                ; No, so
        mov     cx, STATUS_OK
        inc     [Bytes_Read]
        mov     al, [GET_PUT_Data_Buffer]
        cmp     al, LF                          ; End of line of text reached?
        je      @@99                            ; Yes
                                                ; No, so
        cmp     al, CR                          ; Carriage Return found?
        je      @@10                            ; Yes
                                                ; No, so
        mov     [byte es:di], al
        inc     di
        jmp     @@10

@@99:
        pop     di es
        mov     ax, [Bytes_Read]
        mov     [(FMS_Area ptr di).Record_Size], ax
        mov     [(FMS_Area ptr di).Status], cx

        ret

ENDP    FMSACCESS_Get



;**********************************************************************
PROC    FMSACCESS_Put
;**********************************************************************
        push    es di

        mov     [Bytes_To_Write], 0

        mov     cx, [(FMS_Area ptr di).Record_Size]
        mov     ax, [(FMS_Area ptr di).Data_Address_Lo]
        mov     es, [(FMS_Area ptr di).Data_Address_Hi]
        mov     di, ax

;
; search "down" for nonspace character
;
        add     di, cx
        dec     di
        inc     cx
        std                                     ; Search direction is down
        xor     ax, ax                          ; Reset ax
        mov     al, SPACE                       ; Search for the nonspace char
        repe    scasb                           ; Search uses es:di
        cld                                     ; Cancel the std setting

        pop     di es
        push    es di

        mov     [Bytes_To_Write], cx

        mov     [PUT_CR_LF_Written], LOGIC_NO

        mov     bx, [(FMS_Area ptr di).Disk_Handler]
        mov     cx, [(FMS_Area ptr di).Data_Address_Lo]
        mov     es, [(FMS_Area ptr di).Data_Address_Hi]
        mov     di, cx
        mov     dx, offset GET_PUT_Data_Buffer

@@10:
        mov     cx, STATUS_OK
        mov     al, [byte es:di]
        inc     di
        mov     [GET_PUT_Data_Buffer], al
        cmp     [Bytes_To_Write], 0             ; Still bytes to write?
        jne     @@20                            ; Yes
                                                ; No, so
        cmp     [PUT_CR_LF_Written], LOGIC_YES
        je      @@99

        dec     di
        mov     [PUT_CR_LF_Written], LOGIC_YES
        mov     dx, offset PUT_CR_LF
        mov     cx, 2
        jmp     @@30

@@20:
        dec     [Bytes_To_Write]
        mov     cx, 1

@@30:
        xor     ax, ax
        mov     ah, DOS_WRITE_TO_HANDLE
        int     DOS_SERVICE
        mov     cx, STATUS_FILE_WRITE_ERROR
        jc      @@99
        mov     cx, STATUS_DISK_FULL_ERROR
        or      ax, ax                          ; Disk full?
        jz      @@99                            ; Yes
                                                ; No, so
        jmp     @@10                            ; Write Next

@@99:
        pop     di es
        mov     [(FMS_Area ptr di).Status], cx

        ret

ENDP    FMSACCESS_Put



;**********************************************************************
PROC    FMSOPEN_Input
;**********************************************************************
        push    ds

        mov     ah, DOS_OPEN_FILE
        mov     al, DOS_FILE_READ_ONLY
        mov     dx, [(FMS_Area ptr di).Path_Address_Lo]
        mov     ds, [(FMS_Area ptr di).Path_Address_Hi]
        int     DOS_SERVICE
        pop     ds
        mov     cx, STATUS_OK
        jnc     @@99

;
; Error encountered
;
        mov     cx, STATUS_FILE_OPEN_ERROR
        xor     ax, ax                                  ; No Handler

@@99:
        mov     [(FMS_Area ptr di).Disk_Handler], ax
        mov     [(FMS_Area ptr di).Status], cx

        ret

ENDP    FMSOPEN_Input



;**********************************************************************
PROC    FMSOPEN_Output
;**********************************************************************
        push    ds

        xor     ax, ax
        mov     ah, DOS_CREATE_FILE
        xor     cx, cx                                  ; Normal attributes
        mov     dx, [(FMS_Area ptr di).Path_Address_Lo]
        mov     ds, [(FMS_Area ptr di).Path_Address_Hi]
        int     DOS_SERVICE
        pop     ds
        mov     cx, STATUS_OK
        jnc     @@99

;
; Error encountered
;
        mov     cx, STATUS_FILE_OPEN_ERROR
        xor     ax, ax                                  ; No Handler

@@99:
        mov     [(FMS_Area ptr di).Disk_Handler], ax
        mov     [(FMS_Area ptr di).Status], cx

        ret

ENDP    FMSOPEN_Output



;**********************************************************************
PROC    FMSOPEN_Extend
;**********************************************************************

@@99:
        ret

ENDP    FMSOPEN_Extend



;**********************************************************************
PROC    FMSOPEN_I_O
;**********************************************************************
        push    ds

        mov     ah, DOS_OPEN_FILE
        mov     al, DOS_FILE_READ_WRITE
        mov     dx, [(FMS_Area ptr di).Path_Address_Lo]
        mov     ds, [(FMS_Area ptr di).Path_Address_Hi]
        int     DOS_SERVICE
        pop     ds
        mov     cx, STATUS_OK
        jnc     @@99

;
; Error encountered
;
        mov     cx, STATUS_FILE_OPEN_ERROR
        xor     ax, ax                                  ; No Handler

@@99:
        mov     [(FMS_Area ptr di).Disk_Handler], ax
        mov     [(FMS_Area ptr di).Status], cx

        ret

ENDP    FMSOPEN_I_O



;**********************************************************************
PROC    FMSOPEN_Close
;**********************************************************************
        xor     ax, ax
        mov     ah, DOS_CLOSE_FILE
        mov     bx, [(FMS_Area ptr di).Disk_Handler]
        int     DOS_SERVICE
        mov     cx, STATUS_OK
        jnc     @@99

;
; Error encountered
;
        mov     cx, STATUS_FILE_CLOSE_ERROR

@@99:
        mov     [(FMS_Area ptr di).Status], cx

        ret

ENDP    FMSOPEN_Close



;**********************************************************************
PROC    FMSOPEN_Exist
;**********************************************************************
        call    FMSOPEN_Input
        cmp     [(FMS_Area ptr di).Status], STATUS_OK
        jne     @@99

        call    FMSOPEN_Close

@@99:
        ret

ENDP    FMSOPEN_Exist



;**********************************************************************
PROC    FMSOPEN_Scratch
;**********************************************************************

@@99:
        ret

ENDP    FMSOPEN_Scratch



ENDS    CSeg                                    ; End of Code segment

END                                             ; End of DMS
