added non-dos version
[metatoy] / src / loader.asm
index 41d9452..f1ef659 100644 (file)
@@ -17,27 +17,70 @@ _start:
        mov ds, ax
        mov es, ax
        mov fs, ax      ; this will store the original real mode segment
-       mov ss, ax
        ; modify the return to real mode jump segment
        mov [.jmpcs16 + 3], ax
 
-       xor ax, ax
+       ; put the stack on the next segment, should be free 
+       add ax, 1000h
+       mov ss, ax
+       mov ax, 0xfffe
        mov sp, ax
 
+%ifdef BUG_WARNING
+       call warning    ; issue a warning and allow the user to abort
+%endif
+
        ; check for VM86 and abort
        mov eax, cr0
        test ax, 1
        jz .notvm86
 
+       ; try to return to real mode
+       mov si, str_gemmis
+       call printstr
+
+       xor ax, ax
+       mov bx, ax
+       mov si, ax
+       mov es, ax
+       mov ds, ax
+       mov cx, ax
+       mov dx, ax
+       mov ax, 1605h
+       mov di, 30ah    ; pretend to be windows 3.1
+       int 2fh
+       test cx, cx
+       jnz .vm86abort
+       ; we got a function in ds:si
+       push cs
+       push ds
+       pop es  ; es <- func seg
+       pop ds  ; ds <- cs
+       mov word [vmswitch_seg], es
+       mov word [vmswitch_off], si
+       xor ax, ax      ; return to real mode
+       cli             ; just make sure nothing enabled intr behind out back
+       call far [vmswitch]
+       jc .vm86abort
+
+       ; success
+       mov ax, cs
+       mov ds, ax
+       mov es, ax
+       mov si, msg_okstr
+       call printstr
+       jmp .notvm86
+
+.vm86abort:
+       push cs
+       pop ds
+       mov si, msg_failstr
+       call printstr
        mov si, str_errvm86
        call printstr
        jmp exit
 
 .notvm86:
-%ifdef BUG_WARNING
-       call warning    ; issue a warning and allow the user to abort
-%endif
-
 %ifdef CON_SERIAL
        call setup_serial
 %endif
@@ -70,6 +113,7 @@ _start:
        mov ax, 13h
        int 10h
 
+       cli     ; paranoid
        lgdt [gdt_lim]
 
        mov eax, cr0
@@ -124,17 +168,39 @@ _start:
        mov ss, ax
 
        ; restore real-mode IVT
-       lidt [rmidt]
-       sti
+       o32 lidt [rmidt]
 
+       ; switch back to text mode
        mov ax, 3
        int 10h
+
+       ; if we used GEMMIS to exit vm86, switch back to it
+       cmp dword [vmswitch], 0
+       jz exit
+       mov ax, 1
+       call far [vmswitch]
+       ; broadcast windows exit
+       xor ax, ax
+       mov bx, ax
+       mov si, ax
+       mov es, ax
+       mov ds, ax
+       mov cx, ax
+       mov dx, ax
+       mov ax, 1606h
+       int 2fh
+
 exit:  mov ax, 4c00h
        int 21h
 
-str_errvm86 db 'Error: memory manager detected! Stop it and try again (e.g. emm386 off)',10,0
+str_gemmis db 'Memory manager detected, trying to take control...',0
+str_errvm86 db 'Error: memory manager running. Stop it and try again (e.g. emm386 off)',10,0
 str_enterpm db 'Entering 32bit protected mode ...',10,0
 
+       align 4
+vmswitch:
+vmswitch_off dw 0
+vmswitch_seg dw 0
 
 %ifdef BUG_WARNING
        ; warns the user about the experimental and buggy state of this
@@ -153,7 +219,7 @@ str_warnmsg:
        db 'still in a very early stage of development, and will probably not be able to ',10
        db 'return cleanly to DOS on exit. You might be forced to reboot after quitting!',10
        db 'If this is not acceptable, press ESC now to abort.',10,10
-       db 'Press ESC to abort and return to DOS, any other key to continue...',10,0
+       db 'Press ESC to abort and return to DOS, any other key to continue...',10,10,0
 %endif ; BUG_WARNING
 
 
@@ -172,17 +238,17 @@ enable_a20:
        call enable_a20_fast
        call test_a20
        jnc .done
-       mov si, .failstr
+       mov si, msg_failstr
        call printstr
        mov ax, 4c00h
        int 21h
-.done: mov si, .okstr
+.done: mov si, msg_okstr
        call printstr
 .ret:  ret
 
 .infomsg db 'Enable A20 line:',0
-.failstr db ' failed.',10,0
-.okstr db ' success.',10,0
+msg_failstr db ' failed.',10,0
+msg_okstr db ' success.',10,0
 
        ; CF = 1 if A20 test fails (not enabled)
 test_a20:
@@ -294,7 +360,7 @@ detect_memory:
 str_ok db 'OK',10,0
 str_fail db 'failed',10,0
 memdet_fail_msg db 'Failed to detect available memory!',10,0
-memdet_detram  db 'Detecting RAM '
+memdet_detram  db 'Detecting RAM ',0
 memdet_e820_msg db '(BIOS 15h/0xe820)... ',0
 memdet_e801_msg db '(BIOS 15h/0xe801)... ',0
 memdet_88_msg  db '(BIOS 15h/0x88, max 64mb)... ',0
@@ -567,4 +633,40 @@ gdt:       ; 0: null segment
 rmidt: dw 3ffh         ; IVT limit (1kb / 256 entries)
        dd 0            ; IVT base 0
 
+
+; --- debug ---
+newline:
+       push ax
+       mov al, 13
+       call ser_putchar
+       mov al, 10
+       call ser_putchar
+       pop ax
+       ret
+
+printhex:
+       rol ax, 4
+       call print_hexdigit
+       rol ax, 4
+       call print_hexdigit
+       rol ax, 4
+       call print_hexdigit
+       rol ax, 4
+       call print_hexdigit
+       ret
+
+print_hexdigit:
+       push ax
+       and ax, 0xf
+       cmp al, 0xa
+       jae .hexdig
+       add al, '0'
+       call ser_putchar
+       pop ax
+       ret
+.hexdig:add al, 'a' - 10
+       call ser_putchar
+       pop ax
+       ret
+
 ; vi:set ts=8 sts=8 sw=8 ft=nasm: