Metropoli BBS
VIEWER: c0pm.asm MODE: TEXT (CP437)
; Quickie startup code to interface PMODE v3.0 with Borland C++ 4.0 for Win32.
; By Tran (a.k.a. Thomas Pytel).

.386p
locals

STACKLEN	= 4000h 		; size of stack in bytes

PMODE_TEXT      segment para public use16 'CODE'
PMODE_TEXT      ends
_TEXT           segment byte public use32 'CODE'
_TEXT           ends
_DATA           segment dword public use32 'DATA'
_DATA           ends
_BSS            segment dword public use32 'BSS'
_BSS            ends
EXE_STACK       segment para stack use16 'STACK'
EXE_STACK       ends

DGROUP          group   _DATA, _BSS
assume  cs:_TEXT, ds:DGROUP

extrn   _pm_info:far, _pm_init:far

PMODE_TEXT      segment para public use16 'CODE'
assume  cs:PMODE_TEXT, ds:PMODE_TEXT

;═════════════════════════════════════════════════════════════════════════════
align 2
errmsgtbl       dw      errmsg0,errmsg1,errmsg2,errmsg3
                dw      errmsg4,errmsg5,errmsg6

errmsg0         db      'Not enough low memory!',13,10,36
errmsg1         db      '80386 or better not detected!',13,10,36
errmsg2         db      'System already in protected mode and no VCPI or DPMI found!',13,10,36
errmsg3         db      'DPMI host is not 32bit!',13,10,36
errmsg4         db      'Could not enable A20 gate!',13,10,36
errmsg5         db      'Could not enter DPMI 32bit protected mode!',13,10,36
errmsg6         db      'Could not allocate needed DPMI selectors!',13,10,36

;═════════════════════════════════════════════════════════════════════════════
start:
	push cs 			; DS = CS
        pop ds

	call _pm_info			; get information
	jnc short @@startf0		; if no error, go on

@@startf1:
	mov si,ax			; print error message for code AX
        add si,ax
        mov dx,errmsgtbl[si]
        mov ah,9
        int 21h
        mov ax,4cffh
        int 21h

@@startf0:
	xor ax,ax			; check low memory and allocate low
	mov cx,ss			;  buffer needed for protected mode
	add cx,STACKLEN
        movzx edx,word ptr es:[2]
        sub dx,cx
        cmp dx,bx
        jb @@startf1
        mov es,cx

	movzx ecx,cx			; calculate base and size of free low
	shl ecx,4			;  memory and push to stack
        push ecx
        sub dx,bx
        shl edx,4
        push edx

	call _pm_init			; enter protected mode
	jc @@startf1			; if error, go to error message

	mov cx,1			; allocate 1 descriptor
        xor ax,ax
        int 31h

	mov bx,ax			; BX = descriptor allocated

        mov dx,0ffffh                   ; set size to 4G
        mov cx,dx
        mov ax,8
        int 31h

	mov edx,_TEXT			; base address = 32bit code segment
        shl edx,4
        shld ecx,edx,16
        mov ax,7
        int 31h

	mov ax,cs			; set descriptor type to 32bit code
	lar cx,ax			;  at the current CPL
        mov cl,ch
        mov ch,0c0h
        mov ax,9
        int 31h

	mov bp,bx			; preserve selector

	mov bx,ds			; BX = current data selector

        mov dx,0ffffh                   ; set size to 4G
        mov cx,dx
        mov ax,8
        int 31h

	mov edx,DGROUP			; base address = 32bit data segment
        shl edx,4
        shld ecx,edx,16
        mov ax,7
        int 31h

        cli                             ; we don't want to be interrupted
					;  while changing SS:ESP
	mov ds,bx			; set all segment registers to data
	mov es,bx			;  selector
        mov fs,bx
        mov gs,bx
        mov ss,bx

assume  ds:DGROUP

	mov eax,EXE_STACK		; adjust ESP for new base of stack
        mov ebx,DGROUP
        sub eax,ebx
        shl eax,4
        add esp,eax

        sti

	mov _lowbase,edx		; base address of 32bit data segment
	pop _lowheaplen 		; relative base of free low memory
	pop _lowheapbase		; size of free low memory

	push ebp			; push target CS:EIP in 32bit code
        db 66h,68h
        dd offset start32

	db 66h				; 32bit RETF to 32bit code
        retf

PMODE_TEXT      ends

extrn   _PMmain:near

_TEXT           segment byte public use32 'CODE'
assume  cs:_TEXT

;═════════════════════════════════════════════════════════════════════════════
start32:
	call _PMmain			; call C code

	mov ah,4ch			; exit to DOS
        int 21h

_TEXT           ends

public  _lowbase, _lowheapbase, _lowheaplen

_BSS            segment dword public use32 'BSS'

_lowbase	dd	?		; base address of 32bit data segment
_lowheapbase	dd	?		; relative base of free low memory
_lowheaplen	dd	?		; size of free low memory

_BSS            ends

EXE_STACK       segment para stack use16 'STACK'
                db      STACKLEN dup(?)
EXE_STACK       ends

end     start

[ RETURN TO DIRECTORY ]