;*************************************************************************
;***                   ABACUS' "PC UNDERGROUND"                        ***
;***                  ================================                 ***
;***                                                                   ***
;***                  Unit for using the Flat Model                    ***
;***                                                                   ***
;*** The unit makes routines available with which the entire memory    ***
;*** of can be accessed in Real mode.                                  ***
;*** Memory managers such as EMM386 or QEMM CANNOT be installed.       ***
;*** HIMEM.SYS is required !                                           ***
;***                                                                   ***
;*** Author          : Boris Bertelsons  (InspirE)                     ***
;*** Filename        : RMEM.PAS                                        ***
;*** Last Update     : 04/28/94                                        ***
;*** Version         : 1.0                                             ***
;*** Compiler        : Turbo Pascal 6.0 and above                      ***
;*************************************************************************

.386P
.model tpascal

.data
extrn GDT_Off         : byte
extrn GDT             : byte

.code
extrn xms_enable_a20  : far

public mem_read
public mem_Write
public Enable_4Giga
public Multitasker_active


;*************************************************************************
;***                                                                   ***
;***   Checks whether a multitasker like QEMM or EMM386 is active      ***
;***                                                                   ***
;*************************************************************************
Multitasker_active proc pascal
   mov eax,cr0
   and ax,1
   ret
Multitasker_active endp

;*************************************************************************
;***                                                                   ***
;***      Copies a block from RMEM to RAM                              ***
;***                                                                   ***
;*************************************************************************
mem_read proc pascal sourcep:dword,destinationofs : word,destinationseg : word,length1:word
         call xms_Enable_A20
         mov  ax,destinationseg           ; RAM-addy to ES:SI
         mov  es,ax
         mov  di,destinationofs
         xor  ax,ax                ; RMEM source address to GS:EAX
         mov  gs,ax
         mov  eax,sourcep
         mov  cx,length1
lloop:   mov  bl,byte ptr gs:[eax] ; copy bytes
         mov  es:[di],bl
         inc  eax
         inc  di
         loop lloop
         ret
mem_read endp


;*************************************************************************
;***                                                                   ***
;***       Copies a block from RAM to RMEM                             ***
;***                                                                   ***
;*************************************************************************

mem_Write proc pascal sourcep:dword, destinationofs:word, destinationseg:word, length1:word
         call xms_Enable_A20
         mov  ax,destinationseg           ; RAM-addy to ES:SI
         mov  es,ax
         mov  di,destinationofs
         xor  ax,ax                ; RMEM source address to GS:EAX
         mov  gs,ax
         mov  eax,sourcep
         mov  cx,length1
nloop:
         mov  bl,es:[di]           ; copy bytes
         mov  byte ptr gs:[eax],bl
         inc  eax
         inc  di
         loop nloop
         ret
mem_Write endp

;*************************************************************************
;***                                                                   ***
;***            Switches the processor to Flat - Model                 ***
;***                                                                   ***
;*************************************************************************
Enable_4Giga proc pascal
	mov GDT_Off[0],16
	mov eax,seg GDT
	shl eax,4
	mov bx,offset GDT
	movzx ebx,bx
	add eax,ebx
	mov dword ptr GDT_Off[2],eax
	lgdt pword ptr GDT_Off         ; load GDT

	mov bx,08h                     ;  bx points to 1st entry of GDT
	push ds
	cli                            ; disable interrupts
	mov eax,cr0                    ; switch to Protected mode
	or eax,1
	mov cr0,eax
	jmp To_Protectedmode       ; clear execution pipe
	To_Protectedmode:
	mov gs,bx                      ; adapt segments to 4 gigabytes
	mov fs,bx
	mov es,bx
	mov ds,bx
	and al,0FEh                    ; switch back to Real mode, without 
	mov cr0,eax                    ; resetting the processor
	jmp To_Realmode            ; clear execution pipe
	To_Realmode:
	sti                            ; enable interrupts again
	pop ds
  ret
Enable_4Giga endp

END

