;Assemblerversion of the Procedure ReadBytes from the Module TurboFiles
;This is my "first" Assembler-program, so this can NOT be an example
;for perfect programming; its only a demonstration of translating
;a MODULA-procedure to assembler.

;Created: 3-7.6.89
;Changed: 10.6.89 by
;     Stefan Salewski
;     Stolper Weg 3
;     2160 Stade

;-------------------------------------------------------------------
;The Modula-procedure-header:
;PROCEDURE ReadBytes(VAR f{10}:File;adr{6}:ADDRESS;
;                    len{7}:LONGINT;VAR actual{11}:LONGINT);
;-------------------------------------------------------------------
;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
;-------------------------------------------------------------------
;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.
;-------------------------------------------------------------------
;The variables f, adr, len and actual I get from the Modula program
;in the registers

f           EQUR  A2; ADDRESS (The address of the file-variable)
actual      EQUR  A3; ADDRESS (The address of of the actual-variable)
tempAct     EQUR  D4;
copyOfBase  EQUR  D5; =_base(f)
adr         EQUR  D6; VALUE   (The address to put the data)
len         EQUR  D7; VALUE   (How many bytes to read) 
;-------------------------------------------------------------------

START:
       CLR.L   (actual)
       CMPI.B  #done,_res(f)
       BNE     TheEnd
       TST.L   len
       BLE     TheEnd
       MOVE.L  _act(f),tempAct
MainLoop:
       CMP.L   _readTop(f),tempAct
       BLT.S   BufferNotEmpty
FillBuffer:
       MOVE.L  _base(f),copyOfBase
       CMP.L   _writeTop(f),copyOfBase
       BEQ.S   BufferNotChanged
SaveBuffer:
       MOVE.L  _writeBase(f),D2
       SUB.L   _readTop(f),D2
       MOVEQ   #Dos_Current,D3
       MOVE.L  _fhPtr(f),D1
       MOVE.L  _dosBase(f),A6
       JSR     _Seek(A6)
       MOVE.L  _writeTop(f),D3
       SUB.L   _writeBase(f),D3
       MOVE.L  _fhPtr(f),D1
       MOVE.L  _writeBase(f),D2
       ;MOVE.L  _dosBase(f),A6; not necessary
       JSR     _Write(A6)
       CMP.L   D0,D3
       BNE.S   WriteErr
       MOVE.L  tempAct,D2
       SUB.L   _writeTop(f),D2
       BEQ.S   NoSeek
       MOVE.L  _fhPtr(f),D1
       MOVEQ   #Dos_Current,D3
       JSR     _Seek(A6)
NoSeek:
       MOVE.L  tempAct,D0
       SUB.L   _readTop(f),D0
       ADD.L   D0,_filePos(f)
       MOVE.L  copyOfBase,_writeTop(f)
BufferNotChanged:
       MOVE.L  _top(f),D3
       SUB.L   copyOfBase,D3
       MOVE.L  _fhPtr(f),D1
       MOVE.L  copyOfBase,D2
       MOVE.L  _dosBase(f),A6
       JSR     _Read(A6)
       TST.L   D0
       BEQ.S   EOF
       ADD.L   D0,_filePos(f)
       MOVE.L  copyOfBase,tempAct
       ADD.L   copyOfBase,D0
       MOVE.L  D0,_readTop(f)
BufferNotEmpty:
       MOVE.L  _readTop(f),D0
       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
       MOVE.L  tempAct,A0
       MOVE.L  adr,A1
CopyLoop:
       MOVE.B  (A0)+,(A1)+
       DBRA    D0,CopyLoop
       MOVE.L  A0,tempAct
       MOVE.L  A1,adr
       TST.L   len
       BNE     MainLoop
       MOVE.L  tempAct,_act(f)
       RTS
WriteErr:
       MOVE.B  #writeError,_res(f)
       BRA.S   TheEnd
EOF:
       MOVE.B  #endOfFile,_res(f)
TheEnd:
       MOVE.L  tempAct,_act(f)
       RTS
       END
