;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  Shutdown for Menuet
;;
;;  Distributed under General Public License
;;  See file COPYING for details.
;;  Copyright 2003 Ville Turjanmaa
;;


system_shutdown:          ; shut down the system

    push 3		; stop playing cd
    pop  eax
    call sys_cd_audio
    cld

    mov  al,[0x2f0000+0x9030]
    cmp  al,1
    jl   no_shutdown_parameter
    cmp  al,4
    jle  yes_shutdown_param
 no_shutdown_parameter:

;    movzx ecx,word [0x2f0000+0x900A]
;    movzx esi,word [0x2f0000+0x900C]
;    imul ecx,esi  ;[0xfe04]
;;    mov  ecx,0x500000/4  ;3fff00/4    ; darken screen
;    push ecx
;    mov  esi,[0xfe80]
;    cmp  esi,32*0x100000
;    jbe  no_darken_screen
;    mov  edi,16*0x100000
;    push esi edi
;  sdnewpix:
;    lodsd
;    shr  eax,1
;    and  eax,0x7f7f7f7f
;    stosd
;    loop sdnewpix
;    pop  ecx
;    pop  esi edi
;    rep  movsd
;  no_darken_screen:

; read shutdown code:
; 1) display shutdown "window"

    mov  eax,[0xfe00]
    shr  eax,1
    lea  esi,[eax+220]		; x end
    sub  eax,220		; x start

    mov  ebx,[0xfe04]
    shr  ebx,1
    mov  [shutdownpos],ebx
    lea  ebp,[ebx+105]		; y end
    sub  ebx,120		; y start

    xor  edi,edi
    inc  edi		; force putpixel & dtext
    mov  ecx,0x0000ff

; vertical loop begin
  sdnewpix1:
    push eax	; save x start

; horizontal loop begin
  sdnewpix2:

    call [putpixel]

    inc  eax
    cmp  eax,esi
    jnz  sdnewpix2
; horizontal loop end

    dec  ecx	; color
    pop  eax	; restore x start

    inc  ebx	; advance y pos
    cmp  ebx,ebp
    jnz  sdnewpix1
; vertical loop end

; 2) display text strings
;    a) version
    mov  eax,[0xfe00]
    shr  eax,1
    shl  eax,16
    mov  ax,word [shutdownpos]
    push eax
    sub  eax,(220-27)*10000h + 105
    mov  ebx,0xffff00
    mov  ecx,version
    push 34
    pop  edx
    call dtext

;    b) variants
    add  eax,105+33
    push 6
    pop  esi
;    mov  ebx,0xffffff
    mov  bl,0xFF
    mov  ecx,shutdowntext
    mov  dl,40
  newsdt:
    call dtext
    add  eax,10
    add  ecx,edx
    dec  esi
    jnz  newsdt

; 3) load & display rose.txt
    mov  eax,rosef          ; load rose.txt
    xor  ebx,ebx
    push 2
    pop  ecx
    mov  edx,0x90000
    push edx
    push 12
    pop  esi
    push edi	; may be destroyed
    call fileread
    pop  edi

    pop  ecx
    inc  ecx	; do not display stars from rose.txt
    pop  eax
    add  eax,20*10000h - 110

    mov  ebx,0x00ff00
    push 27
    pop  edx

   nrl:
    call dtext
    sub  ebx,0x050000
    add  eax,8
    add  ecx,31
    cmp  cx,word 0x0001+25*31
    jnz  nrl

    call checkEgaCga

 yes_shutdown_param:
    cli

    mov  eax,kernel               ; load kernel.mnt to 0x8000:0
    push 12
    pop  esi
    xor  ebx,ebx
    or   ecx,-1
    mov  edx,0x80000
    call fileread

    mov  esi,restart_kernel_4000+0x10000  ; move kernel re-starter to 0x4000:0
    mov  edi,0x40000
    mov  ecx,1000
    rep  movsb

    mov  eax,0x2F0000    ; restore 0x0 - 0xffff
    xor  ebx,ebx
    mov  ecx,0x10000
    call memmove

    call restorefatchain

    mov  word [0x467+0],pr_mode_exit-0x10000
    mov  word [0x467+2],0x1000

    mov  al,0x0F
    out  0x70,al
    mov  al,0x05
    out  0x71,al

    mov  al,0xFE
    out  0x64,al
    hlt

use16

pr_mode_exit:
org $-0x10000

; setup stack
	mov	ax, 3000h
	mov	ss, ax
	mov	esp, 0EC00h
; setup ds
	push	cs
	pop	ds

    lidt [old_ints_h-0x10000]
;remap IRQs
    mov  al,0x11
    out  0x20,al
    call rdelay
    out  0xA0,al
    call rdelay
    
    mov  al,0x08
    out  0x21,al
    call rdelay
    mov  al,0x70
    out  0xA1,al
    call rdelay
    
    mov  al,0x04
    out  0x21,al
    call rdelay
    mov  al,0x02
    out  0xA1,al
    call rdelay
    
    mov  al,0x01
    out  0x21,al
    call rdelay
    out  0xA1,al
    call rdelay
    
    mov  al,0
    out  0x21,al
    call rdelay
    out  0xA1,al
    sti

  temp_3456:
    xor  ax,ax
    mov  es,ax
    mov  al,byte [es:0x9030]
    cmp  al,1
    jl   nbw
    cmp  al,4
    jle  nbw32
  
  nbw:
    in   al,0x60
    call pause_key
    cmp  al,6
    jae  nbw
    mov  bl,al
  nbw2:
    in   al,0x60
    call pause_key
    cmp  al,bl
    je   nbw2
    cmp  al,240  ;ax,240
    jne  nbw31
    mov  al,bl
    dec  ax
    jmp  nbw32
  nbw31:
    add  bl,128
    cmp  al,bl
    jne  nbw
    sub  al,129

  nbw32:

    dec  ax	; 1 = write floppy
    js   nbw
    jnz  no_floppy_write
    call floppy_write
    jmp  temp_3456 ;nbw
  no_floppy_write:

    dec  ax	; 2 = power off
    jnz  no_apm_off
    call APM_PowerOff
    jmp  $
  no_apm_off:

    dec  ax	; 3 = reboot
    jnz  restart_kernel		; 4 = restart kernel
    push 0x40
    pop  ds
    mov  word[0x0072],0x1234 
    jmp  0xF000:0xFFF0

    pause_key:
      mov cx,100
    pause_key_1:
      loop  pause_key_1
      ret
org $+0x10000
old_ints_h:
        dw      0x400
        dd      0
        dw      0
org $-0x10000

rdelay:
    ret

iglobal
  kernel  db  'KERNEL  MNT'
;  shutdown_parameter db 0
endg

restart_kernel:

        mov     ax,0x0003      ; set text mode for screen
        int     0x10

        jmp     0x4000:0000


restart_kernel_4000:
        cli

;        mov     di,0x1000      ; load kernel image from 0x8000:0 -> 0x1000:0
;
;      new_kernel_block_move:
;
;        mov     ebx,0
;
;      new_kernel_byte_move:
;
;        mov     ax,di
;        add     ax,0x7000
;        mov     es,ax
;        mov     dl,[es:bx]
;        mov     es,di
;        mov     [es:bx],dl
;
;        inc     ebx
;        cmp     ebx,65536
;        jbe     new_kernel_byte_move
;
;        add     di,0x1000
;        cmp     di,0x2000
;        jbe     new_kernel_block_move
	push	ds
	pop	es
	mov	cx, 0x8000
	push	cx
	mov	ds, cx
	xor	si, si
	xor	di, di
	rep	movsw
	push	0x9000
	pop	ds
	push	0x2000
	pop	es
	pop	cx
	rep	movsw

        wbinvd  ; write and invalidate cache

;        mov     ax,0x1000
;        mov     es,ax
;        mov     ax,0x3000
;        mov     ss,ax
;        mov     sp,0xec00
; restore timer
	mov	al, 00110100b
	out	43h, al
	jcxz	$+2
	mov	al, 0xFF
	out	40h, al
	jcxz	$+2
	out	40h, al
	jcxz	$+2
        sti

; bootloader interface
	push	0x1000
	pop	ds
	mov	si, .bootloader_block;-0x10000
	mov	ax, 'KL'
        jmp     0x1000:0000

.bootloader_block:
	db	1	; version
	dw	1	; floppy image is in memory
	dd	0	; cannot save parameters

APM_PowerOff:
        mov     ax, 5304h
        xor     bx, bx
        int     15h
;!!!!!!!!!!!!!!!!!!!!!!!!
mov ax,0x5300
xor bx,bx
int 0x15
push ax

mov ax,0x5301
xor bx,bx
int 0x15

mov ax,0x5308
mov bx,1
mov cx,bx
int 0x15

mov ax,0x530E
xor bx,bx
pop cx
int 0x15

mov ax,0x530D
mov bx,1
mov cx,bx
int 0x15

mov ax,0x530F
mov bx,1
mov cx,bx
int 0x15

mov ax,0x5307
mov bx,1
mov cx,3
int 0x15
;!!!!!!!!!!!!!!!!!!!!!!!!
fwwritedone:
        ret
org $+0x10000
flm db 0
org $-0x10000

floppy_write:   ; write diskette image to physical floppy

        cmp  [flm-0x10000],byte 1
        je   fwwritedone
        mov  [flm-0x10000],byte 1

	xor	ax, ax		; reset drive
	xor	dx, dx
        int     0x13

        mov     cx,0x0001               ; startcyl,startsector
;        mov     dx,0x0000               ; starthead,drive
	xor	dx, dx
        mov	ax, 80*2               ; read no of sect

      fwwrites:
	push	ax

        ; move 1mb+ -> 0:a000

	pusha
        mov     si,fwmovedesc -0x10000
        mov     cx,256*18
        mov     ah,0x87
        push	ds
        pop	es
        int     0x15
        add	dword [fwmovedesc-0x10000+0x12], 512*18
        popa

        xor     si,si
        mov	es,si
      fwnewwrite:
        mov     bx,0xa000               ; es:bx -> data area
        mov     ax,0x0300+18            ; read, no of sectors to read
        int     0x13

	test	ah, ah
        jz      fwgoodwrite

	inc	si
        cmp     si,10
        jnz     fwnewwrite

; can't access diskette - return
	pop	ax
        ret

      fwgoodwrite:
        inc     dh
        cmp     dh,2
        jnz     fwbb2
        mov     dh,0
        inc     ch
      fwbb2:
        pop     ax
        dec     ax
        jnz     fwwrites
        ret
org $+0x10000
      fwmovedesc:
        db      0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0
        db      0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0
        db      0xff,0xff,0x0,0x00,0x10,0x93,0x0,0x0
        db      0xff,0xff,0x0,0xa0,0x00,0x93,0x0,0x0
        db      0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0
        db      0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0
        db      0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0
        db      0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0
org $-0x10000
use32
org $+0x10000
uglobal
  shutdownpos dd 0x0
endg

iglobal
if lang eq en
shutdowntext:
    db   "IT'S SAFE TO POWER OFF COMPUTER OR      "
    db   '                                        '
    db   '1) SAVE RAMDISK TO FLOPPY               '
    db   '2) APM - POWEROFF                       '
    db   '3) REBOOT                               '
    db   '4) RESTART KERNEL                       ' 
else
shutdowntext:
    db   "������᭮� �몫�祭�� �������� ���    "
    db   '                                        '
    db   '1) ���࠭��� ࠬ��� �� ��᪥��         '
    db   '2) APM - �몫�祭�� ��⠭��             '
    db   '3) ��१���㧪� ��⥬�                 '
    db   '4) ������ �� �� ���                  '
end if
rosef:
    db 'ROSE    TXT'
endg