;---------------------------------------------------------------
; Retro running under DOS, as a .com program
;
;       Enter p-mode & move kernel to a fixed location above 1M.
;       Expects a CLEAN boot, no himem.sys, emm386 or anything.
;---------------------------------------------------------------
%define START   0x110000
        tib     equ 0x100000            ;Input buffer (grows upward);
        rp0     equ tib+400h            ;Return stack (grows down)
        sp0     equ rp0+100h            ;Data stack (grows down)
        d0      equ sp0+10h             ;Dictionary header space
        h0      equ START+50000

BITS 16
ORG 0x100
;---------------------------------------------------------------
; Enter protected mode
init:
        pushf                   ;Save DOS state
        push ds

        call graphics
        call A20
        mov bx,cs               ;Add CS to flat 32-bit addresses
        mov [_exit.cs],bx
        movzx ebx,bx
        shl ebx,4               ;ebx= linear address of CS
        or [gdt+18h+2],ebx
        or [gdt+20h+2],ebx
        mov dx,gdt
        movzx edx,dx
        add edx,ebx             ;edx= linear GDT address
        mov [gdt+2],edx
        cli                     ;Initialize pmode
        lgdt [gdt]
        mov eax,cr0
        inc ax
	mov cr0,eax
        add dword [.x],ebx
        db 0x66,0xEA            ;32-bit JMP FAR to get into pmode
.x      dd protected
        dw 8h
;---------------------------------------------------------------
BITS 32
protected:
        mov ax,10h              ;flat data segment
        mov ds,ax
        mov es,ax
        mov ss,ax
        mov esp,rp0             ;return stack

        lea esi,[ebx+kernel]
        mov edi,START
        push edi
        mov ecx,(END-kernel)/4
        cld
        rep movsd

        mov esi,sp0             ;data stack
        pop edi
        call edi

_exit:  mov ax,20h
        mov ds,ax
        mov ss,ax
        db 0x66,0xEA            ;16-bit JMP FAR
        dw .pm16,18h
BITS 16
.pm16:                          ;16-bit pmode
    ;Reminder: will need to restore real-mode seg regs (and IDT)
        mov eax,cr0
        dec ax
        mov cr0,eax
        db 0xEA                 ;JMP FAR back to real mode
        dw .real
.cs     dw 0
.real:  mov ax,cs               ;Restore vital registers
        mov es,ax
        mov ss,ax
        mov sp,-6       ;!!!    (well, it works :)
        sti
        pop ds                  ;Restore DOS state
        popf
ret
;---------------------------------------------------------------
align 8
gdt:	dw 0x18
	dd gdt
	dw 0
	dw 0xffff, 0, 0x9a00, 0xcf	;code
	dw 0xffff, 0, 0x9200, 0xcf	;data
;---------------------------------------------------------------
BITS 16
graphics:
%ifdef VESA
        push es
        push word 0x800
        pop es
        xor di,di
        mov ax,0x4F00
        int 10h
        pop es
        cmp ax,0x004F
        jz .vesa
%endif
        mov ax,13h              ;Graphics mode
	int 10h
        ret
%ifdef VESA
.vesa   mov ax,0x4F02
        mov bx,0x101
        int 0x10
        ret
%endif
A20:
        in al,92h               ;PS/2 version
        or al,2
        jmp short $+2
        jmp short $+2
        jmp short $+2
        out 92h,al
        ret
;---------------------------------------------------------------
 align 4
kernel:
incbin "retro"
 align 4
END
