;Assemblerversion of the Procedure SetPos from the Module TurboFiles
;Created: 11.6.89 by
;     Stefan Salewski
;     Stolper Weg 3
;     2160 Stade

;-------------------------------------------------------------------
;The Modula-procedure-header:
;PROCEDURE TurboSetPos(VAR f{10}:File;offSet{6}:LONGINT;
;                      mode{7}:TurboMode):BOOLEAN;
;-------------------------------------------------------------------
;TYPE
;Result=(notOpen,done,notdone,openError,readError,writeError,seekError,
;        endOfFile,outOfMem,tooManyFiles);
notOpen        EQU     0
done           EQU     1
notDone        EQU     2
openError      EQU     3
readError      EQU     4
writeError     EQU     5
seekError      EQU     6
endOfFile      EQU     7
outOfMem       EQU     8
tooManyFile    EQU     9
;-------------------------------------------------------------------
;TurboMode=(beginning,current,end); (* for SetPos *)
beginning      EQU     0
current        EQU     1
ende           EQU     2
;-------------------------------------------------------------------
TRUE           EQU     -1
FALSE          EQU     0
;-------------------------------------------------------------------
;Modes of Dos.Seek
Dos_beginning  EQU    -1
Dos_current    EQU     0
Dos_end        EQU     1
;-------------------------------------------------------------------

;The Modula-Datastructure:
;File=RECORD
;       fhPtr:Dos.FileHandlePtr;
;       dosBase:ADDRESS;
;       base:ADDRESS;
;       top:ADDRESS;
;       filePos:LONGINT;
;       startLength:LONGINT;
;       act:CharPtr;
;       readTop:ADDRESS;
;       writeBase:ADDRESS;
;       writeTop:ADDRESS;
;       res:Result;
;     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
_res            EQU     40
;-------------------------------------------------------------------
;The offsets of the Dos-functions:
_Seek           EQU    -66
_Write          EQU    -48
_Read           EQU    -42
;-------------------------------------------------------------------
; We can use all registers except A4, A5 (and A7 of course)
; A0, A1, D0, D1 are not resistent against changes by Dos-Funktions,
; and I changes than too by myself.
; I don't use D0 and D1 as registerparameters in the ProcedureHaeder,
; because they are used to evaluate the Procedure-parameters.
;-------------------------------------------------------------------
;f, offSet and mode I get from the Compiler
;The result is allways given back in D0

f           EQUR  A2; ADDRESS (The address of the file-variable)
base        EQUR  A3;
tempAct     EQUR  D1; \
getPos      EQUR  D2;  | These registers are changed by Seek and Write!!!
bufTop      EQUR  D3; /
newPos      EQUR  D4;
startLength EQUR  D5
offSet      EQUR  D6; VALUE
mode        EQUR  D7; VALUE
;-------------------------------------------------------------------
Start: ;(of SetPos)
       CMPI.B  #done,_res(f)
       BNE     Error
       MOVE.L  _base(f),base
       MOVE.L  _act(f),tempAct
GetPosition:
       MOVE.L  _filePos(f),getPos
       ADD.L   tempAct,getPos
       SUB.L   _readTop(f),getPos
GetFileLength:
       MOVE.L  _startLength(f),startLength
       CMP.L   getPos,startLength
       BGE.S   GetBufTop
       MOVE.L  getPos,startLength
       MOVE.L  startLength,_startLength(f)
GetBufTop:
       MOVE.L  _readTop(f),bufTop
       CMP.L   tempAct,bufTop
       BGE.S   RelOffSet
       MOVE.L  tempAct,bufTop
RelOffSet:
       CMPI.B  #current,mode
       BEQ.S   NewPosition
       TST.L   offset
       BPL.S   Positiv
       NEG.L   offset
Positiv:
       CMPI.B  #beginning,mode
       BNE.S   NotBeginning
       SUB.L   getPos,offset
       BRA.S   NewPosition
NotBeginning:     
       NEG.L   offset
       ADD.L   startLength,offSet
       SUB.L   getPos,offSet
NewPosition:
       MOVE.L  tempAct,newPos
       ADD.L   offSet,newPos
NewPosInBuffer:
       CMP.L   _base(f),newPos
       BLT.S   NewPosInFile
       CMP.L   bufTop,newPos
       BGE.S   NewPosInFile
       MOVE.L  newPos,_act(f)
       MOVEQ   #TRUE,D0
       RTS
NewPosInFile:
       MOVE.L  getPos,newPos
       ADD.L   offSet,newPos
       TST.L   newPos
       BMI.S   SeekErr 
       CMP.L   startLength,newPos
       BGT.S   SeekErr
       CMP.L   _writeTop(f),base
       BEQ.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)
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
       BMI.S   SeekErr
       MOVE.L  newPos,_filePos(f)
       MOVE.L  base,_act(f)
       MOVE.L  base,_readTop(f)
       MOVE.B  TRUE,D0
       RTS
WriteErr:
       MOVE.B  #writeError,_res(f)
       BRA.S   Error
SeekErr:
       MOVE.B  #seekError,_res(f)
Error:
       MOVEQ   #FALSE,D0
TheEnd:
       RTS
       END
