;
;(**********************************************************************
;
;    :Program.    TurboFiles.asm
;    :Contents.   The assemblerpart of the Module TurboFiles
;    :Author.     Stefan Salewski
;    :Address.    Stefan Salewski, Stolper Weg 3, D-2160 Stade
;    :Copyright.  FD
;    :Language.   68000-Assembler
;    :Translator. A68k-Assembler V2.61
;    :History.    V2.0     12-06-91
;    :Remark.     Now all Assembler-Procedures respects the Amiga-Dos-
;    :Remark.     Register-Conventions: This means that the Procedures
;    :Remark.     changes only D0,D1,A0,A1. The other Registers remain
;    :Remark.     unchanged.
;
;**********************************************************************)
; The public assembler-procedures:

  XDEF TurboReadChar
  XDEF TurboReadBytes
  XDEF TurboRead
  XDEF TurboWriteChar
  XDEF TurboWriteBytes
  XDEF TurboWrite
  XDEF TurboSetPos
  XDEF TurboGetPos
  XDEF TurboSize

;-------------------------------------------------------------------
;CONST (* Error-Codes = file.res *)
done         EQU 0;
notdone      EQU 1;
notOpen      EQU 2;
openError    EQU 3;
readError    EQU 4;
writeError   EQU 5;
seekError    EQU 6;
endOfFile    EQU 7;
outOfMem     EQU 8;
notExists    EQU 9;
;-------------------------------------------------------------------
;Modes of Dos.Seek
Dos_beginning  EQU    -1
Dos_current    EQU     0
Dos_end        EQU     1
;-------------------------------------------------------------------
;Modes for SetPos
beginning      EQU     Dos_beginning
current        EQU     Dos_current
end            EQU     Dos_end
;-------------------------------------------------------------------
;The offsets of the Dos-functions:
_Seek          EQU    -66
_Write         EQU    -48
_Read          EQU    -42
;-------------------------------------------------------------------
;The BOOLEAN constants:
TRUE           EQU     -1
FALSE          EQU     0
;-------------------------------------------------------------------
;The OBERON-Datastructure:
;File* = RECORD
;          fhPtr:Dos.FileHandlePtr;
;          dosBase:Exec.ADDRESS;
;          base:Exec.ADDRESS;
;          top:Exec.ADDRESS;
;          filePos:LONGINT;
;          startLength:LONGINT;
;          act:Exec.ADDRESS;
;          readTop:Exec.ADDRESS;
;          writeBase:Exec.ADDRESS;
;          writeTop:Exec.ADDRESS;
;          open:BOOLEAN;
;          res*:SHORTINT;
;        END;
;The offsets in the File-Variable:
_fhPtr          EQU     0
_dosBase        EQU     4
_base           EQU     8
_top            EQU     12
_filePos        EQU     16
_startLength    EQU     20
_act            EQU     24
_readTop        EQU     28
_writeBase      EQU     32
_writeTop       EQU     36
_open           EQU     40
_res            EQU     41
;*******************************************************************
;-------------------------------------------------------------------
;PROCEDURE TurboSize(VAR f{A0}:File):LONGINT;
;-------------------------------------------------------------------
TurboSize:
\f      EQUR  A0; ADDRESS (The address of the file-variable)
;-------------------------------------------------------------------
\Start:
       TST.B  _open(\f)
       BEQ.S   \Error
       TST.B  _res(\f)
       BNE.S   \Error
       MOVE.L  _filePos(\f),D0
       ADD.L   _act(\f),D0
       SUB.L   _readTop(\f),D0
       MOVE.L  _startLength(\f),D1
       CMP.L   D1,D0
       BGE.S   \TheEnd
       MOVE.L  D1,D0
       BRA.S   \TheEnd
\Error:
       MOVEQ.L #-1,D0
\TheEnd:
       RTS
;*******************************************************************
;-------------------------------------------------------------------
;PROCEDURE TurboGetPos(VAR f{A0}:File):LONGINT;
;-------------------------------------------------------------------
TurboGetPos:
\f      EQUR  A0; ADDRESS (The address of the file-variable)
;-------------------------------------------------------------------
\Start:
       TST.B  _open(\f)
       BEQ.S   \Error
       TST.B  _res(\f)
       BNE.S   \Error
       MOVE.L  _filePos(\f),D0
       ADD.L   _act(\f),D0
       SUB.L   _readTop(\f),D0
       BRA.S   \TheEnd
\Error:
       MOVEQ.L #-1,D0
\TheEnd:
       RTS
;*******************************************************************
;-------------------------------------------------------------------
;PROCEDURE TurboSetPos(VAR f{A0}:File;offset{D0}:LONGINT;
;                      mode{D1}:LONGINT):BOOLEAN;
;-------------------------------------------------------------------
TurboSetPos:
\f           EQUR  A2; ADDRESS (The address of the file-variable)
\base        EQUR  A3;
\dosBase     EQUR  A6;
\getPos      EQUR  D2;  | These registers are changed by Seek and Write!!!
\bufTop      EQUR  D3; /
\newPos      EQUR  D4;
\offset      EQUR  D5; VALUE
\mode        EQUR  D6; VALUE
;-------------------------------------------------------------------
\Start:
       MOVEM.L D2-D6/A2/A3/A6,-(A7)
       MOVE.L  A0,\f
       MOVE.L  D0,\offset
       MOVE.L  D1,\mode
       TST.B  _open(\f)
       BEQ     \Error
       TST.B  _res(\f)
       BNE     \Error
       MOVE.L  _base(\f),\base
\GetPosition:
       MOVE.L  _filePos(\f),\getPos
       ADD.L   _act(\f),\getPos
       SUB.L   _readTop(\f),\getPos
\GetFileLength:
       CMP.L   _startLength(\f),\getPos
       BLT.S   \GetBufTop
       MOVE.L  \getPos,_startLength(\f)
\GetBufTop:
       MOVE.L  _readTop(\f),\bufTop
       CMP.L   _writeTop(\f),\bufTop
       BGE.S   \RelOffSet
       MOVE.L  _writeTop(\f),\bufTop
\RelOffSet:
       CMPI.L  #current,\mode
       BEQ.S   \NewPosition
       TST.L   \offset
       BPL.S   \Positiv
       NEG.L   \offset
\Positiv:
       CMPI.L  #beginning,\mode
       BNE.S   \NotBeginning
       SUB.L   \getPos,\offset
       BRA.S   \NewPosition
\NotBeginning:
       NEG.L   \offset
       ADD.L   _startLength(\f),\offset
       SUB.L   \getPos,\offset
\NewPosition:
       MOVE.L  _act(\f),\newPos
       ADD.L   \offset,\newPos
\NewPosInBuffer:
       CMP.L   \base,\newPos
       BLT.S   \NewPosInFile
       CMP.L   \bufTop,\newPos
       BGE.S   \NewPosInFile
       MOVE.L  \newPos,_act(\f)
       MOVEQ   #TRUE,D0
       BRA.S   \TheEnd
\NewPosInFile:
       MOVE.L  \getPos,\newPos
       ADD.L   \offset,\newPos
       TST.L   \newPos
       BMI.S   \SeekErr
       CMP.L   _startLength(\f),\newPos
       BGT.S   \SeekErr
       MOVE.L  _writeTop(\f),D0
       CMP.L   _writeBase(\f),D0
       BLE.S   \BufferNotChanged
\SaveBuffer:
       MOVE.L  _fhPtr(\f),D1
       MOVE.L  _writeBase(\f),D2
       SUB.L   _readTop(\f),D2
       MOVEQ   #Dos_current,D3
       MOVE.L  _dosBase(\f),A6
       JSR     _Seek(A6)
       MOVE.L  _fhPtr(\f),D1
       MOVE.L  _writeBase(\f),D2
       MOVE.L  _writeTop(\f),D3
       SUB.L   _writeBase(\f),D3
       JSR     _Write(A6)
       CMP.L   D0,D3
       BNE.S   \WriteErr
       MOVE.L  \base,_writeTop(\f)
       MOVE.L  _top(\f),_writeBase(\f)
\BufferNotChanged:
       MOVE.L  _fhPtr(\f),D1
       MOVE.L  \newPos,D2
       MOVEQ   #Dos_beginning,D3
       MOVE.L  _dosBase(\f),A6
       JSR     _Seek(A6)
       TST.L   D0 ; not necessary
       BMI.S   \SeekErr
       MOVE.L  \newPos,_filePos(\f)
       MOVE.L  \base,_act(\f)
       MOVE.L  \base,_readTop(\f)
       MOVEQ   #TRUE,D0
       BRA.S   \TheEnd
\WriteErr:
       MOVE.B  #writeError,_res(\f)
       BRA.S   \Error
\SeekErr:
       MOVE.B  #seekError,_res(\f)
\Error:
       MOVEQ   #FALSE,D0
\TheEnd:
       MOVEM.L (A7)+,D2-D6/A2/A3/A6
       RTS
;*******************************************************************
;This Routine changes only D0 !!!
;-------------------------------------------------------------------
;PROCEDURE SaveBuffer(VAR f{A0}:File):BOOLEAN;
;-------------------------------------------------------------------
SaveBuffer:
\f     EQUR A2 ; we get f in A0 and copy it to A2
\ok    EQUR D0 ; ok=TRUE if all is ok
;-------------------------------------------------------------------
\Start:
       MOVEM.L D1/D2/D3/A0/A1/A2/A6,-(A7)
       MOVE.L  A0,\f
       MOVE.L  _dosBase(\f),A6
       MOVE.L  _writeBase(\f),D2
       SUB.L   _readTop(\f),D2
       BEQ.S   \D20
       MOVEQ   #Dos_current,D3
       MOVE.L  _fhPtr(\f),D1
       JSR     _Seek(A6)
\D20:
       MOVE.L  _writeTop(\f),D3
       SUB.L   _writeBase(\f),D3
       MOVE.L  _fhPtr(\f),D1
       MOVE.L  _writeBase(\f),D2
       JSR     _Write(A6)
       CMP.L   D0,D3
       BNE.S   \WriteErr
       MOVE.L  _act(\f),D2
       SUB.L   _writeTop(\f),D2
       BEQ.S   \NoSeek
       MOVE.L  _fhPtr(\f),D1
       MOVEQ   #Dos_current,D3
       JSR     _Seek(A6)
\NoSeek:
       MOVE.L  _act(\f),D0
       SUB.L   _readTop(\f),D0
       ADD.L   D0,_filePos(\f)
       MOVE.L  _base(\f),_writeTop(\f)
       MOVE.L  _top(\f),_writeBase(\f)
       MOVEQ   #TRUE,\ok
       BRA.S   \TheEnd
\WriteErr:
       MOVE.B  #writeError,_res(\f)
       MOVEQ   #FALSE,\ok
\TheEnd:
       MOVEM.L (A7)+,D1/D2/D3/A0/A1/A2/A6
       RTS
;*******************************************************************
;-------------------------------------------------------------------
;PROCEDURE TurboReadBytes(VAR f{A0}:File;adr{A1}:ADDRESS;
;                         len{D1}:LONGINT):LONGINT;
;-------------------------------------------------------------------
TurboReadBytes:
;                    D0 is free to use
\len           EQUR  D1; VALUE   (How many bytes to read)
\actual        EQUR  D2;
\f             EQUR  A0; ADDRESS   (The address of the file-variable)
\adr           EQUR  A1; ADDRESS   (The address to put the data)
\tempAct       EQUR  A2;
\dosBase       EQUR  A6;
;-------------------------------------------------------------------
\START:
       MOVEM.L D2/A2,-(A7)
       MOVEQ   #0,\actual
       TST.B  _open(\f)
       BEQ     \TheEnd
       TST.B  _res(\f)
       BNE     \TheEnd
       TST.L   \len
       BLE     \TheEnd
       MOVE.L  _act(\f),\tempAct
\MainLoop:
       CMPA.L  _readTop(\f),\tempAct
       BLT.S   \BufferNotEmpty
       CMPA.L  _writeTop(\f),\tempAct
       BLT.S   \BufferNotEmpty
\FillBuffer:
       MOVE.L  _writeTop(\f),D0
       CMP.L   _writeBase(\f),D0
       BLE.S   \BufferNotChanged
       BSR      SaveBuffer
       TST.L    D0 ; FALSE = 0
       BEQ.S    \TheEnd
\BufferNotChanged:
       MOVEM.L D1/D2/D3/A0/A1/A6,-(A7)
       MOVE.L  _top(\f),D3
       SUB.L   _base(\f),D3
       MOVE.L  _fhPtr(\f),D1
       MOVE.L  _base(\f),D2
       MOVE.L  _dosBase(\f),A6
       JSR     _Read(A6)
       MOVEM.L (A7)+,D1/D2/D3/A0/A1/A6
       TST.L   D0
       BEQ.S   \EOF
       ADD.L   D0,_filePos(\f)
       MOVEA.L _base(\f),\tempAct
       ADD.L   \tempAct,D0
       MOVE.L  D0,_readTop(\f)
\BufferNotEmpty:
       MOVE.L  _readTop(\f),D0
       CMP.L   _writeTop(\f),D0
       BGE.S   \RTGtr
       MOVE.L  _writeTop(\f),D0
\RTGtr:
       SUB.L   \tempAct,D0
       CMP.L   \len,D0
       BLE.S   \ok
       MOVE.L  \len,D0
\ok:
       ADD.L   D0,\actual
       SUB.L   D0,\len
       SUBQ.L  #1,D0
\CopyLoop:
       MOVE.B  (\tempAct)+,(\adr)+
       DBRA.S  D0,\CopyLoop
       MOVE.L  \tempAct,_act(\f)
       TST.L   \len
       BNE.S   \MainLoop
       BRA.S   \TheEnd
\EOF:
       MOVE.B  #endOfFile,_res(\f)
\TheEnd:
       MOVE.L  \actual,D0
       MOVEM.L (A7)+,D2/A2
       RTS
;*******************************************************************
;-------------------------------------------------------------------
;PROCEDURE TurboRead(VAR f:File;VAR to:ARRAY OF BYTE):BOOLEAN;
;-------------------------------------------------------------------
;PROCEDURE TurboReadBytes(VAR f{A0}:File;adr{A1}:ADDRESS;
;                         len{D1}:LONGINT):LONGINT;
;-------------------------------------------------------------------
TurboRead:
\Start:
        MOVEA.L 10(A7),A0       ; ADR(f)
        MOVEA.L 6(A7),A1        ; ADR(to)
        MOVE.W  4(A7),D1        ; LEN(to)
        EXT.L   D1
        BSR     TurboReadBytes
        MOVE.W  4(A7),D1
        EXT.L   D1
        CMP.L   D1,D0
        SEQ     D0
        MOVEA.L (A7)+,A0        ; ReturnAdr
        LEA     10(A7),A7
        JMP     (A0)
;*******************************************************************
;-------------------------------------------------------------------
;PROCEDURE TurboReadChar(VAR f{A0}:File;VAR c{A1}:CHAR):BOOLEAN;
;-------------------------------------------------------------------
TurboReadChar:
;                    D0 is free to use
\f             EQUR  A0; ADDRESS   (The address of the file-variable)
\c             EQUR  A1; ADDRESS   (The address to put the data)
\dosBase       EQUR  A6;
;-------------------------------------------------------------------
\START:
       TST.B  _open(\f)
       BEQ.S   \Error
       TST.B  _res(\f)
       BNE.S   \Error
       MOVE.L  _act(\f),D0
\MainLoop:
       CMP.L   _readTop(\f),D0
       BLT.S   \BufferNotEmpty
       CMP.L   _writeTop(\f),D0
       BLT.S   \BufferNotEmpty
\FillBuffer:
       MOVE.L  _writeTop(\f),D0
       CMP.L   _writeBase(\f),D0
       BLE.S   \BufferNotChanged
       BSR      SaveBuffer
       TST.L    D0 ; FALSE = 0
       BEQ.S    \Error
\BufferNotChanged:
       MOVEM.L D2/D3/A0/A1/A6,-(A7)
       MOVE.L  _top(\f),D3
       SUB.L   _base(\f),D3
       MOVE.L  _base(\f),D2
       MOVE.L  _fhPtr(\f),D1
       MOVE.L  _dosBase(\f),A6
       JSR     _Read(A6)
       MOVEM.L (A7)+,D2/D3/A0/A1/A6
       TST.L   D0
       BEQ.S   \EOF
       ADD.L   D0,_filePos(\f)
       MOVE.L  _base(\f),_act(\f)
       ADD.L   _base(\f),D0
       MOVE.L  D0,_readTop(\f)
\BufferNotEmpty:
       ADDQ.L  #1,_act(\f)
       MOVE.L  _act(\f),\f
       MOVE.B  -(\f),(\c)
       MOVEQ   #TRUE,D0
       RTS
\EOF:
       MOVE.B  #endOfFile,_res(\f)
\Error:
       MOVEQ   #FALSE,D0
\TheEnd:
       RTS

;*******************************************************************
;-------------------------------------------------------------------
;PROCEDURE TurboWriteBytes(VAR f{A0}:File;adr{A1}:ADDRESS;
;                          len{D1}:LONGINT):BOOLEAN;
;-------------------------------------------------------------------
TurboWriteBytes:
;                  D0 is free to use
\len         EQUR  D1; VALUE   (How many bytes to read)
\f           EQUR  A0; ADDRESS (The address of the file-variable)
\adr         EQUR  A1; ADDRESS (The address to take the data from)
\tempAct     EQUR  A2;
;-------------------------------------------------------------------
\START:
       MOVEM.L A2,-(A7)
       TST.B  _open(\f)
       BEQ.S   \Error
       TST.B  _res(\f)
       BNE.S   \Error
       TST.L   \len
       BLE.S   \Error
       MOVE.L  _act(\f),\tempAct
\MainLoop:
       CMP.L   _top(\f),\tempAct
       BLT.S   \BufferNotFull
\InitBuffer:
       MOVE.L  _writeTop(\f),D0
       CMP.L   _writeBase(\f),D0
       BLE.S   \BufferNotChanged
       BSR      SaveBuffer
       TST.L    D0 ; FALSE = 0
       BEQ.S    \Error
\BufferNotChanged:
       MOVE.L  _base(\f),\tempAct
       MOVE.L  \tempAct,_readTop(\f)
\BufferNotFull:
       CMP.L   _writeBase(\f),\tempAct
       BGE.S   \WriteBaseNotChanged
       MOVE.L  \tempAct,_writeBase(\f)
\WriteBaseNotChanged:
       MOVE.L  _top(\f),D0
       SUB.L   \tempAct,D0
       CMP.L   \len,D0
       BLE.S   \ok
       MOVE.L  \len,D0
\ok:
       SUB.L   D0,\len
       SUBQ.L  #1,D0
\CopyLoop:
       MOVE.B  (\adr)+,(\tempAct)+
       DBRA    D0,\CopyLoop
       CMP.L   _writeTop(\f),\tempAct
       BLE.S   \WriteTopNotChanged
       MOVE.L  \tempAct,_writeTop(\f)
\WriteTopNotChanged:
       MOVE.L  \tempAct,_act(\f)
       TST.L   \len
       BNE.S   \MainLoop
       MOVEQ   #TRUE,D0
       BRA.S   \TheEnd
\Error:
       MOVEQ   #FALSE,D0
\TheEnd:
       MOVEM.L (a7)+,A2
       RTS
;*******************************************************************
;-------------------------------------------------------------------
;PROCEDURE TurboWrite(VAR f:File;from:ARRAY OF BYTE):BOOLEAN;
;-------------------------------------------------------------------
;PROCEDURE TurboWriteBytes(VAR f{A0}:File;adr{A1}:ADDRESS;
;                          len{D1}:LONGINT):BOOLEAN;
;-------------------------------------------------------------------
TurboWrite:
\Start:
        MOVEA.L 10(A7),A0              ;ADR(f)
        MOVEA.L 6(A7),A1               ;ADR(from)
        MOVE.W  4(A7),D1               ;LEN(from)
        EXT.L   D1
        BSR     TurboWriteBytes
        MOVEA.L (A7)+,A0               ;Return-Adr
        LEA     10(A7),A7              ;remove parameters from stack
        JMP     (A0)
;*******************************************************************
;-------------------------------------------------------------------
;PROCEDURE TurboWriteChar(VAR f{A0}:File;c{D1}:CHAR):BOOLEAN;
;-------------------------------------------------------------------
TurboWriteChar:
;                  D0 is free to use
\c           EQUR  D1; VALUE   (The Character )
\f           EQUR  A0; ADDRESS (The address of the file-variable)
\tempAct     EQUR  A1;
;-------------------------------------------------------------------
\START:
       TST.B  _open(\f)
       BEQ.S   \Error
       TST.B  _res(\f)
       BNE.S   \Error
       MOVE.L  _act(\f),\tempAct
\MainLoop:
       CMP.L   _top(\f),\tempAct
       BLT.S   \BufferNotFull
\InitBuffer:
       MOVE.L  _writeTop(\f),D0
       CMP.L   _writeBase(\f),D0
       BLE.S   \BufferNotChanged
       BSR      SaveBuffer
       TST.L    D0 ; FALSE = 0
       BEQ.S    \Error
\BufferNotChanged:
       MOVE.L  _base(\f),\tempAct
       MOVE.L  \tempAct,_readTop(\f)
\BufferNotFull:
       CMP.L   _writeBase(\f),\tempAct
       BGE.S   \WriteBaseNotChanged
       MOVE.L  \tempAct,_writeBase(\f)
\WriteBaseNotChanged:
       MOVE.B  \c,(\tempAct)+
       CMP.L   _writeTop(\f),\tempAct
       BLE.S   \WriteTopNotChanged
       MOVE.L  \tempAct,_writeTop(\f)
\WriteTopNotChanged:
       MOVE.L  \tempAct,_act(\f)
       MOVEQ   #TRUE,D0
       RTS
\Error:
       MOVEQ   #FALSE,D0
\TheEnd:
       RTS

       END


