;-------------------------------
; flat.asm
; From  Sami Kantoluoto                                         2:221/319

; Code to set up flat mode using Tran's PMODE 3.04
; This is tested with my DOS-Extender but it should work in Tran's
; too... (since I named my detection/enter pmode routines (and error codes)
; like Tran did... Lame, isn't it? ;) ):

                .386P
STCK_LEN        equ     100h
extrn           _pm_info:far,_pm_init:far
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
_PMODE_TEXT     Segment Para Public Use16 'CODE'
_PMODE_TEXT     EndS
_TEXT           Segment Para Public Use16 'CODE'
_TEXT           EndS
_PMODE32        Segment Para Public Use32 'CODE'
_PMODE32        EndS
_STACK          Segment Para Stack
_STACK          EndS
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
_TEXT           Segment Para Public Use16 'CODE'
                Assume  cs:_TEXT,ds:_TEXT,ss:_STACK
                org     0
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
ErrorTable      dw      Error_1,Error_2,Error_3,Error_4,Error_5,Error_6,Error_7
Error_1         db      "80386 or better not detected.$"
Error_2         db      "System is already in protected mode and no VCPI or DPMI
Error_3         db      "DPMI - host isn't 32-bit.$"
Error_4         db      "Couldn't enable A20 gate.$"
Error_5         db      "DPMI - Couldn't enter into 32-bit protected mode.$"
Error_6         db      "DPMI - Couldn't allocate needed selectors.$"
NoLoMem         db      "Not enough low memory.$"
LineFeed        db      13,10,"$"
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
                align   4
_TEXT_codebase  dd      0
_TEXT_codesel   dw      0               ; Base: _TEXT  Limit: FFFFh  16-bit
_TEXT_datasel   dw      0               ; Base: _TEXT  Limit: FFFFh  32-bit
_TEXT_pspsel    dw      0               ; Base: PSP    Limit: FFh    16-bit
_TEXT_zdatasel  dw      0               ; Base: 0      Limit: 4GB-1  32-bit
_TEXT_dpl       db      0
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Start:          push    cs
                pop     ds
                call    _pm_info
                jnc     s_continue

Error:          mov     bx,ax
                add     bx,ax
                mov     dx,ErrorTable[bx-2]

ErrorMessage:   mov     ah,09h
                int     21h
                mov     dx,offset LineFeed
                int     21h
                mov     ax,4CFEh
                int     21h

s_continue:     mov     cx,_STACK
                add     cx,STCK_LEN
                mov     ax,es:[2]
                sub     ax,cx
                cmp     ax,bx
                mov     dx,offset NoLoMem
                jb      ErrorMessage

                push    cx
                mov     dx,es
                sub     cx,dx
                add     bx,cx
                mov     ah,4Ah
                int     21h
                pop     es

                call    _pm_init
                jc      Error

                mov     eax,_PMODE_TEXT
                mov     dx,cs

                mov     _TEXT_codebase,eax
                mov     _TEXT_codesel,dx
                mov     _TEXT_datasel,ds
                mov     _TEXT_pspsel,es

                lar     ax,dx
                and     ah,60h
                mov     _TEXT_dpl,ah

                mov     ebx,_PMODE32
                shl     ebx,4
                mov     edx,0FFFFFFFFh
                mov     bp,1100000010011010b
                call    alloc_desc

                push    ebx
                push    large offset Start32

                xor     ebx,ebx
                mov     edx,0FFFFFFFFh
                mov     bp,1100000010010010b
                call    alloc_desc
                mov     _TEXT_zdatasel,bx
                mov     fs,bx

                mov     ebx,_PMODE32
                shl     ebx,4
                mov     edx,0FFFFFFFFh
                mov     bp,1100000010010010b
                call    alloc_desc

                mov     ds,bx

                db      66h
                retf
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
alloc_desc:     ; EBX = Base address
                ; EDX = Limit
                ;  BP = Access Rights
                xor     ax,ax
                mov     cx,1
                int     31h
                jc      ad_exit
                push    edx
                mov     dx,bx
                rol     ebx,16
                mov     cx,bx
                mov     bx,ax
                mov     ax,7
                int     31h
                pop     dx cx
                jc      ad_exit

                mov     ax,8
                int     31h
                jc      ad_exit

                mov     ax,9
                mov     cx,bp
                or      cl,_TEXT_dpl
                int     31h
                jc      ad_exit

                ret

ad_exit:        pop     ax
                mov     ax,6
                jmp     Error
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
_TEXT           EndS
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
_PMODE32        Segment Para Public Use32 'CODE'
                Assume  cs:_PMODE32,ds:_PMODE32
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
HexTable        db      "0123456789ABCDEF"
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Start32:        ; OK, we're in 32-bit protected mode:

                ; DS: Selector for _PMODE32 (with limit of 4GB-1, 32-bit)
                ; ES: PSP selector
                ; FS: Data selector with base of 0 and limit of 4GB-1, 32-bit

                push    fs
                pop     es
                mov     cl,0Fh
                mov     edx,01234FEDCh
                mov     edi,0B8000h
                call    PrintHex

exit:           mov     ax,4C00h
                int     21h
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
PrintHex:       ;    EDX = Number
                ;     CL = Color
                ; ES:EDI = Dest...
                cld
                mov     ch,8
                mov     ebx,offset HexTable
PH_MainLoop:    shld    eax,edx,4
                and     eax,0Fh
                xlat
                mov     ah,ch
                stos    word ptr es:[edi]
                dec     ch
                jnz     PH_MainLoop
                ret
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
_PMODE32        EndS
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
_STACK          Segment Para Stack
                db      10h*STCK_LEN dup (0)
_STACK          EndS
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
                End     Start

