Subversion Repositories Kolibri OS

Rev

Rev 7129 | Rev 8089 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
  4. ;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa      ;;
  5. ;; Distributed under terms of the GNU General Public License    ;;
  6. ;;                                                              ;;
  7. ;;  BOOTCODE.INC                                                ;;
  8. ;;                                                              ;;
  9. ;;  KolibriOS 16-bit loader,                                    ;;
  10. ;;                        based on bootcode for MenuetOS        ;;
  11. ;;                                                              ;;
  12. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  13.  
  14. $Revision: 7132 $
  15.  
  16.  
  17. ;==========================================================================
  18. ;
  19. ;                           16 BIT FUNCTIONS
  20. ;
  21. ;==========================================================================
  22.  
  23.  
  24. putchar:
  25. ; in: al=character
  26.         mov     ah, 0Eh
  27.         mov     bh, 0
  28.         int     10h
  29.         ret
  30.  
  31. print:
  32. ; in: si->string
  33.         mov     al, 186
  34.         call    putchar
  35.         mov     al, ' '
  36.         call    putchar
  37.  
  38. printplain:
  39. ; in: si->string
  40.         pusha
  41.         lodsb
  42. @@:
  43.         call    putchar
  44.         lodsb
  45.         test    al, al
  46.         jnz     @b
  47.         popa
  48.         ret
  49.  
  50. getkey:                         ; Use BIOS INT 16h to read a key from the keyboard
  51. ; get number in range [bl,bh] (bl,bh in ['0'..'9'])
  52. ; in: bx=range
  53. ; out: ax=digit (1..9, 10 for 0)
  54.         mov     ah, 0       ; If 'int 16h' is called with 'ah' equal to zero, the BIOS will not return control to the caller
  55.         int     16h         ; until a key is available in the system type ahead buffer. On return, 'al' contains the ASCII
  56.         cmp     al, 27      ; code for the key read from the buffer and 'ah' contains the keyboard scan code. (27=>ESC)
  57.         jz      @f          ; If ESC is pressed, return (user doesn't want to change any value).
  58.         cmp     al, bl      ; Compare 'al' (ASCII code of key pressed) with 'bl' (lowest accepted char from the range).
  59.         jb      getkey      ; ASCII code is below lowest accepted value => continue waiting for another key.
  60.         cmp     al, bh      ; Compare 'al' (ASCII code of key pressed) with 'bh' (highest accepted char from the range).
  61.         ja      getkey      ; ASCII code is above highest accepted value => continue waiting for another key.
  62.         push    ax          ; If the pressed key is in the accepted range, save it on the stack and echo to screen.
  63.         call    putchar
  64.         pop     ax
  65.         and     ax, 0Fh     ; Convert ASCII code to number: '1'->1, '2'->2, etc. 0Fh=1111b.
  66.         jnz     @f          ; ASCII code for '0' is 48 (110000b). (110000b AND 1111b) = 0
  67.         mov     al, 10      ; So if key '0' was entered, return 10 in 'ax'
  68. @@:
  69.         ret
  70.  
  71. setcursor:
  72. ; in: dl=column, dh=row
  73.         mov     ah, 2
  74.         mov     bh, 0
  75.         int     10h
  76.         ret
  77.  
  78. macro _setcursor row,column
  79. {
  80.         mov     dx, row*256 + column
  81.         call    setcursor
  82. }
  83.  
  84. macro _ask_question question,range,variable_to_set
  85. {
  86.         _setcursor 16,0
  87.         mov     si, question    ; Print the question
  88.         call    print
  89.         mov     bx, range       ; range accepted for answer
  90.         call    getkey
  91.         cmp     al, 27          ; If ESC was pressed, do not change the value
  92.         jz      .esc_pressed
  93.         mov     [variable_to_set], al
  94. }
  95.  
  96. boot_read_floppy:
  97.         push    si
  98.         xor     si, si
  99.         mov     ah, 2   ; read
  100. @@:
  101.         push    ax
  102.         int     0x13
  103.         pop     ax
  104.         jnc     @f
  105.         inc     si
  106.         cmp     si, 10
  107.         jb      @b
  108. sayerr_badsect:
  109.         mov     si, badsect
  110. sayerr_plain:
  111.         call    printplain
  112.         jmp     $
  113. @@:
  114.         pop     si
  115.         ret
  116.  
  117. ; convert abs. sector number (AX) to BIOS T:H:S
  118. ; sector number = (abs.sector%BPB_SecPerTrk)+1
  119. ; pre.track number = (abs.sector/BPB_SecPerTrk)
  120. ; head number = pre.track number%BPB_NumHeads
  121. ; track number = pre.track number/BPB_NumHeads
  122. ; Return: cl - sector number
  123. ;         ch - track number
  124. ;         dl - drive number (0 = a:)
  125. ;         dh - head number
  126. conv_abs_to_THS:
  127.         push    bx
  128.         mov     bx, word [BPB_SecPerTrk]
  129.         xor     dx, dx
  130.         div     bx
  131.         inc     dx
  132.         mov     cl, dl                          ; cl = sector number
  133.         mov     bx, word [BPB_NumHeads]
  134.         xor     dx, dx
  135.         div     bx
  136.         ; !!!!!!! ax = track number, dx = head number
  137.         mov     ch, al                          ; ch=track number
  138.         xchg    dh, dl                          ; dh=head number
  139.         mov     dl, 0                           ; dl=0 (drive 0 (a:))
  140.         pop     bx
  141.         retn
  142. ; needed variables
  143. BPB_SecPerTrk   dw      0                       ; sectors per track
  144. BPB_NumHeads    dw      0                       ; number of heads
  145. BPB_FATSz16     dw      0                       ; size of FAT
  146. BPB_RootEntCnt  dw      0                       ; count of root dir. entries
  147. BPB_BytsPerSec  dw      0                       ; bytes per sector
  148. BPB_RsvdSecCnt  dw      0                       ; number of reserved sectors
  149. BPB_TotSec16    dw      0                       ; count of the sectors on the volume
  150. BPB_SecPerClus  db      0                       ; number of sectors per cluster
  151. BPB_NumFATs     db      0                       ; number of FAT tables
  152. abs_sector_adj  dw      0                       ; adjustment to make abs. sector number
  153. end_of_FAT      dw      0                       ; end of FAT table
  154. FirstDataSector dw      0                       ; begin of data
  155.  
  156. ;=========================================================================
  157. ;
  158. ;                           16 BIT CODE
  159. ;
  160. ;=========================================================================
  161.  
  162. include 'bootvesa.inc'                 ;Include source for boot vesa
  163. if defined extended_primary_loader
  164. include 'parsers.inc'
  165. end if
  166.  
  167. start_of_code:
  168.  
  169. if defined extended_primary_loader
  170. ; save data from primary loader
  171.         mov     word [cs:bootcallback], si
  172.         mov     word [cs:bootcallback+2], ds
  173.         push    cs
  174.         pop     ds
  175.         mov     [bootdevice], ax
  176.         mov     [bootfs], bx
  177.  
  178. ; set up stack
  179.         mov     ax, (TMP_STACK_TOP and 0xF0000) shr 4
  180.         mov     ss, ax
  181.         mov     sp, TMP_STACK_TOP and 0xFFFF
  182.  
  183. ; try to load configuration file
  184.         mov     ax, 1
  185.         mov     di, config_file_struct
  186.         call    [bootcallback]
  187.         cld
  188.         push    cs
  189.         pop     es
  190. ; bx=0 - ok, bx=1 - part of file loaded, assume this is ok
  191.         cmp     bx, 1
  192.         ja      .config_bad
  193. ; configuration file was loaded, parse
  194. ; if length is too big, use first 0FFFFh bytes
  195.         test    dx, dx
  196.         jz      @f
  197.         mov     ax, 0FFFFh
  198. @@:
  199. ; ds:si will be pointer to current data, dx = limit
  200.         xchg    ax, dx
  201.         push    4000h
  202.         pop     ds
  203.         xor     si, si
  204. .parse_loop:
  205. ; skip spaces
  206.         cmp     si, dx
  207.         jae     .parse_done
  208.         lodsb
  209.         cmp     al, ' '
  210.         jbe     .parse_loop
  211.         dec     si
  212. ; loop over all possible configuration values
  213.         mov     bx, config_file_variables
  214. .find_variant:
  215. ; get length
  216.         mov     cx, [es:bx]
  217. ; zero length = end of list
  218.         jecxz   .find_newline
  219. ; skip over length
  220.         inc     bx
  221.         inc     bx
  222.         mov     di, bx
  223. ; skip over string
  224.         add     bx, cx
  225. ; test whether we have at least cx symbols left
  226.         mov     ax, cx
  227.         add     ax, si
  228.         jc      .next_variant1
  229.         cmp     ax, dx
  230.         jae     .next_variant1
  231. ; save current position
  232.         push    si
  233. ; compare strings
  234.         repz cmpsb
  235.         jnz     .next_variant2
  236. ; strings are equal; look for "=" with possible spaces before and after
  237. @@:
  238.         cmp     si, dx
  239.         jae     .next_variant2
  240.         lodsb
  241.         cmp     al, ' '
  242.         jbe     @b
  243.         cmp     al, '='
  244.         jnz     .next_variant2
  245. ; ok, we found the true variant
  246. ; ignore saved position on the stack
  247.         pop     ax
  248. ; call the parser
  249.         call    word [es:bx]
  250. ; line parsed, find next
  251. .find_newline:
  252.         cmp     si, dx
  253.         jae     .parse_done
  254.         lodsb
  255.         cmp     al, 13
  256.         jz      .parse_loop
  257.         cmp     al, 10
  258.         jz      .parse_loop
  259.         jmp     .find_newline
  260. .next_variant2:
  261. ; continue to the next variant, restoring current position
  262.         pop     si
  263. .next_variant1:
  264. ; continue to the next variant
  265. ; skip over the parser
  266.         inc     bx
  267.         inc     bx
  268.         jmp     .find_variant
  269. .parse_done:
  270. .config_bad:
  271.  
  272. ; set up segment registers
  273.         push    cs
  274.         pop     ds
  275. else
  276.         cld
  277.         push    0
  278.         pop     es
  279. ; \begin{diamond}[02.12.2005]
  280. ; if bootloader sets ax = 'KL', then ds:si points to loader block
  281.         cmp     ax, 'KL'
  282.         jnz     @f
  283.         mov     word [cs:cfgmanager.loader_block], si
  284.         mov     word [cs:cfgmanager.loader_block+2], ds
  285.         mov     word [es:BOOT_LO.kernel_restart], kernel_restart_bootblock
  286. @@:
  287. ; \end{diamond}[02.12.2005]
  288.  
  289. ; if bootloader sets cx = 'HA' and dx = 'RD', then bx contains identifier of source disk
  290. ; (see comment to BOOT_LO.bx_from_load and loader_doc.txt)
  291.         mov     word [es:BOOT_LO.bx_from_load], 'r1'  ; default value: /rd/1
  292.         cmp     cx, 'HA'
  293.         jnz     no_hd_load
  294.         cmp     dx, 'RD'
  295.         jnz     no_hd_load
  296.         mov     [es:BOOT_LO.bx_from_load], bx
  297. no_hd_load:
  298.  
  299. ; set up stack
  300.         mov     ax, (TMP_STACK_TOP and 0xF0000) shr 4
  301.         mov     ss, ax
  302.         mov     sp, TMP_STACK_TOP and 0xFFFF
  303. ; set up segment registers
  304.         push    cs
  305.         pop     ds
  306.         push    cs
  307.         pop     es
  308. end if
  309.  
  310. ; set videomode
  311.         mov     ax, 3
  312.         int     0x10
  313.  
  314. if lang eq ru
  315.  ; Load & set russian VGA font (RU.INC)
  316.         mov     bp, RU_FNT1             ; RU_FNT1 - First part
  317.         mov     bx, 1000h               ; 768 bytes
  318.         mov     cx, 30h                 ; 48 symbols
  319.         mov     dx, 80h                 ; 128 - position of first symbol
  320.         mov     ax, 1100h
  321.         int     10h
  322.  
  323.         mov     bp, RU_FNT2             ; RU_FNT2 -Second part
  324.         mov     bx, 1000h               ; 512 bytes
  325.         mov     cx, 20h                 ; 32 symbols
  326.         mov     dx, 0E0h                ; 224 - position of first symbol
  327.         mov     ax, 1100h
  328.         int     10h
  329.  ; End set VGA russian font
  330. else if lang eq et
  331.         mov     bp, ET_FNT              ; ET_FNT1
  332.         mov     bx, 1000h               ;
  333.         mov     cx, 255                 ; 256 symbols
  334.         xor     dx, dx                  ; 0 - position of first symbol
  335.         mov     ax, 1100h
  336.         int     10h
  337. end if
  338.  
  339. ; draw frames
  340.         push    0xb800
  341.         pop     es
  342.         xor     di, di
  343.         mov     ah, 1*16+15
  344.  
  345. ; draw top
  346.         mov     si, d80x25_top
  347.         mov     cx, d80x25_top_num * 80
  348. @@:
  349.         lodsb
  350.         stosw
  351.         loop    @b
  352. ; draw spaces
  353.         mov     si, space_msg
  354.         mov     dx, 25 - d80x25_top_num - d80x25_bottom_num
  355. dfl1:
  356.         push    si
  357.         mov     cx, 80
  358. @@:
  359.         lodsb
  360.         stosw
  361.         loop    @b
  362.         pop     si
  363.         dec     dx
  364.         jnz     dfl1
  365. ; draw bottom
  366.         mov     si, d80x25_bottom
  367.         mov     cx, d80x25_bottom_num * 80
  368. @@:
  369.         lodsb
  370.         stosw
  371.         loop    @b
  372.  
  373.         mov     byte [space_msg+80], 0    ; now space_msg is null terminated
  374.  
  375.         _setcursor d80x25_top_num,0
  376.  
  377.  
  378. ; TEST FOR 386+
  379.  
  380.         mov     bx, 0x4000
  381.         pushf
  382.         pop     ax
  383.         mov     dx, ax
  384.         xor     ax, bx
  385.         push    ax
  386.         popf
  387.         pushf
  388.         pop     ax
  389.         and     ax, bx
  390.         and     dx, bx
  391.         cmp     ax, dx
  392.         jnz     cpugood
  393.         mov     si, not386
  394. sayerr:
  395.         call    print
  396.         jmp     $
  397.      cpugood:
  398.  
  399.         push    0
  400.         popf
  401.  
  402. ; set up esp
  403.         movzx   esp, sp
  404.  
  405.         push    0
  406.         pop     es
  407.  
  408.         xor     cx, cx
  409. @@:
  410.         in      al, 64h
  411.         test    al, 2
  412.         loopnz  @b
  413.  
  414.         mov     al, 0xf6        ; Сброс клавиатуры, разрешить сканирование
  415.         out     0x60, al
  416.         xor     cx, cx
  417. @@:
  418.         in      al, 64h
  419.         test    al, 1
  420.         loopz   @b
  421.         in      al, 0x60
  422.  
  423. ;;;/diamond today   5.02.2008
  424. ; set keyboard typematic rate & delay
  425.         mov     al, 0xf3
  426.         out     0x60, al
  427.         xor     cx, cx
  428. @@:
  429.         in      al, 64h
  430.         test    al, 1
  431.         loopz   @b
  432.         in      al, 0x60
  433.         mov     al, 0
  434.         out     0x60, al
  435.         xor     cx, cx
  436. @@:
  437.         in      al, 64h
  438.         test    al, 1
  439.         loopz   @b
  440.         in      al, 0x60
  441. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  442.         sti
  443. ; --------------- APM ---------------------
  444.         and     word [es:BOOT_LO.apm_version], 0     ; ver = 0.0 (APM not found)
  445.         mov     ax, 0x5300
  446.         xor     bx, bx
  447.         int     0x15
  448.         jc      apm_end                 ; APM not found
  449.         test    cx, 2
  450.         jz      apm_end                 ; APM 32-bit protected-mode interface not supported
  451.         mov     [es:BOOT_LO.apm_version], ax         ; Save APM Version
  452.         mov     [es:BOOT_LO.apm_flags], cx           ; Save APM flags
  453.  
  454.         ; Write APM ver ----
  455.         and     ax, 0xf0f
  456.         add     ax, '00'
  457.         mov     si, msg_apm
  458.         mov     [si + 5], ah
  459.         mov     [si + 7], al
  460.         _setcursor 0, 3
  461.         call    printplain
  462.         ; ------------------
  463.  
  464.         mov     ax, 0x5304              ; Disconnect interface
  465.         xor     bx, bx
  466.         int     0x15
  467.         mov     ax, 0x5303              ; Connect 32 bit mode interface
  468.         xor     bx, bx
  469.         int     0x15
  470.  
  471.         mov     [es:BOOT_LO.apm_entry], ebx
  472.         mov     [es:BOOT_LO.apm_code_32], ax
  473.         mov     [es:BOOT_LO.apm_code_16], cx
  474.         mov     [es:BOOT_LO.apm_data_16], dx
  475.  
  476. apm_end:
  477.         _setcursor d80x25_top_num, 0
  478.  
  479. if ~ defined extended_primary_loader
  480. ;CHECK current of code
  481.         cmp     [cfgmanager.loader_block], -1
  482.         jz      noloaderblock
  483.         les     bx, [cfgmanager.loader_block]
  484.         cmp     byte [es:bx], 1
  485.         mov     si, loader_block_error
  486.         jnz     sayerr
  487.         push    0
  488.         pop     es
  489. end if
  490.  
  491. noloaderblock:
  492. ; DISPLAY VESA INFORMATION
  493.         call    print_vesa_info
  494.         call    calc_vmodes_table
  495.         call    check_first_parm   ;check and enable cursor_pos
  496.  
  497. ; \begin{diamond}[30.11.2005]
  498. cfgmanager:
  499. ; settings:
  500. ; a) preboot_graph = graphical mode
  501. ;    preboot_gprobe = probe this mode?
  502. ; b) preboot_biosdisk  = use BIOS disks through V86 emulation? // (earlier was: preboot_dma  = use DMA access?)
  503. ; c) preboot_debug = duplicates kernel debug output to the screen
  504. ; d) preboot_launcher = start the first app (right now it's LAUNCHER) after kernel is loaded?
  505. ; e) preboot_device = from where to boot?
  506.  
  507. ; determine default settings
  508. if ~ defined extended_primary_loader
  509.         mov     [.bSettingsChanged], 0
  510. end if
  511.  
  512. ;.preboot_gr_end:
  513.         mov     di, preboot_device
  514. ; if image in memory is present and [preboot_device] is uninitialized,
  515. ; set it to use this preloaded image
  516.         cmp     byte [di], 0
  517.         jnz     .preboot_device_inited
  518. if defined extended_primary_loader
  519.         inc     byte [di]
  520.         cmp     byte [bootdevice], 'f' ; floppy?
  521.         jz      .preboot_device_inited
  522.         inc     byte [di]
  523. else
  524.         cmp     [.loader_block], -1
  525.         jz      @f
  526.         les     bx, [.loader_block]
  527.         test    byte [es:bx+1], 1
  528.         jz      @f
  529.         mov     byte [di], 3
  530.         jmp     .preboot_device_inited
  531. @@:
  532. ; otherwise, set [preboot_device] to 1 (default value - boot from floppy)
  533.         mov     byte [di], 1
  534. end if
  535. .preboot_device_inited:
  536. ; following 4 lines set variables to 1 if its current value is 0
  537.         cmp     byte [di+preboot_dma-preboot_device], 1
  538.         adc     byte [di+preboot_dma-preboot_device], 0
  539.         cmp     byte [di+preboot_launcher-preboot_device], 1        ; Start LAUNCHER by default
  540.         adc     byte [di+preboot_launcher-preboot_device], 0
  541.         _setcursor 5,2
  542.  
  543.         mov     si, linef
  544.         call    printplain
  545.         mov     si, start_msg
  546.         call    print
  547.         mov     si, time_msg
  548.         call    print
  549. ; get start time
  550.         call    .gettime
  551.         mov     [.starttime], eax
  552.         mov     word [.timer], .newtimer
  553.         mov     word [.timer+2], cs
  554. .printcfg:
  555.  
  556.         _setcursor 9,0
  557.         mov     si, current_cfg_msg
  558.         call    print
  559.         mov     si, curvideo_msg
  560.         call    print
  561.  
  562.         call    draw_current_vmode
  563.  
  564.         mov     si, usebd_msg
  565.         cmp     [preboot_biosdisk], 1
  566.         call    .say_on_off
  567.         mov     si, debug_mode_msg
  568.         cmp     [preboot_debug], 1
  569.         call    .say_on_off
  570.         mov     si, launcher_msg
  571.         cmp     [preboot_launcher], 1
  572.         call    .say_on_off
  573.         mov     si, preboot_device_msg
  574.         call    print
  575.         mov     al, [preboot_device]
  576. if defined extended_primary_loader
  577.         and     eax, 3
  578. else
  579.         and     eax, 7
  580. end if
  581.         mov     si, [preboot_device_msgs+eax*2]
  582.         call    printplain
  583. .show_remarks:
  584. ; show remarks in gray color
  585.         mov     di, ((21-num_remarks)*80 + 2)*2
  586.         push    0xB800
  587.         pop     es
  588.         mov     cx, num_remarks
  589.         mov     si, remarks
  590. .write_remarks:
  591.         lodsw
  592.         push    si
  593.         xchg    ax, si
  594.         mov     ah, 1*16+7      ; background: blue (1), foreground: gray (7)
  595.         push    di
  596. .write_remark:
  597.         lodsb
  598.         test    al, al
  599.         jz      @f
  600.         stosw
  601.         jmp     .write_remark
  602. @@:
  603.         pop     di
  604.         pop     si
  605.         add     di, 80*2
  606.         loop    .write_remarks
  607. .wait:
  608.         _setcursor 25,0         ; out of screen
  609. ; set timer interrupt handler
  610.         cli
  611.         push    0
  612.         pop     es
  613.         push    dword [es:8*4]
  614.         pop     dword [.oldtimer]
  615.         push    dword [.timer]
  616.         pop     dword [es:8*4]
  617. ;        mov     eax, [es:8*4]
  618. ;        mov     [.oldtimer], eax
  619. ;        mov     eax, [.timer]
  620. ;        mov     [es:8*4], eax
  621.         sti
  622. ; wait for keypressed
  623.         xor     ax, ax
  624.         int     16h
  625.         push    ax
  626. ; restore timer interrupt
  627. ;        push    0
  628. ;        pop     es
  629.         mov     eax, [.oldtimer]
  630.         mov     [es:8*4], eax
  631.         mov     [.timer], eax
  632.  
  633.         _setcursor 7,0
  634.         mov     si, space_msg
  635.         call    printplain
  636. ; clear remarks and restore normal attributes
  637.         push    es
  638.         mov     di, ((21-num_remarks)*80 + 2)*2
  639.         push    0xB800
  640.         pop     es
  641.         mov     cx, num_remarks
  642.         mov     ax, ' ' + (1*16 + 15)*100h
  643. @@:
  644.         push    cx
  645.         mov     cx, 76
  646.         rep stosw
  647.         pop     cx
  648.         add     di, 4*2
  649.         loop    @b
  650.         pop     es
  651.         pop     ax
  652. ; switch on key
  653.         cmp     al, 13
  654.         jz      .continue
  655.         or      al, 20h
  656.         cmp     al, 'a'         ; select graphical mode
  657.         jz      .change_a
  658.         cmp     al, 'q'         ; Trick to make 'A' key on azerty keyboard work
  659.         je      .change_a
  660.         cmp     al, 'b'         ; use BIOS disks? // (selecting YES will make BIOS disks visible as /bd)
  661.         jz      .change_b
  662.         cmp     al, 'c'         ; load kernel in debug mode?
  663.         jz      .change_c
  664.         cmp     al, 'd'         ; start launcher after kernel is loaded?
  665.         jz      .change_d
  666.         cmp     al, 'e'         ; select boot origin
  667.         jnz     .show_remarks
  668. ; e) preboot_device = from where to boot?
  669. if defined extended_primary_loader
  670.         _ask_question bdev,'12',preboot_device              ; range accepted for answer: 1-2
  671. else
  672.         _ask_question bdev,'14',preboot_device              ; range accepted for answer: 1-4
  673. end if
  674.         _setcursor 14,0
  675.  
  676. .d:
  677. if ~ defined extended_primary_loader
  678.         mov     [.bSettingsChanged], 1
  679. end if
  680. .esc_pressed:
  681.         call    clear_vmodes_table             ;clear vmodes_table
  682.         jmp     .printcfg
  683.  
  684. .change_a:
  685.         call    clear_vmodes_table             ;clear vmodes_table
  686.  
  687.         mov     si, word [cursor_pos]
  688.         mov     word [cursor_pos_old], si
  689. .loops:
  690.         call    draw_vmodes_table
  691.         _setcursor 25,0         ; out of screen
  692.         xor     ax, ax
  693.         int     0x16
  694. ;        call    clear_table_cursor             ;clear current position of cursor
  695.  
  696.         mov     si, word [cursor_pos]
  697.  
  698.         cmp     al, 27              ; If ESC was pressed, do not change the value
  699.         jnz     @f                   ; Just exit the resolution selection box
  700.  
  701.         mov     si, word [cursor_pos_old]
  702.         mov     word [cursor_pos], si
  703.         jmp     .esc_pressed
  704. @@:
  705.         cmp     ah, 0x48;x,0x48E0               ; up
  706.         jne     .down
  707.         cmp     si, modes_table
  708.         jbe     .loops
  709.         sub     word [cursor_pos], size_of_step
  710.         jmp     .loops
  711.  
  712. .down:
  713.         cmp     ah, 0x50;x,0x50E0               ; down
  714.         jne     .pgup
  715.         cmp     word[es:si+10], -1
  716.         je      .loops
  717.         add     word [cursor_pos], size_of_step
  718.         jmp     .loops
  719.  
  720. .pgup:
  721.         cmp     ah, 0x49                ; page up
  722.         jne     .pgdn
  723.         sub     si, size_of_step*long_v_table
  724.         cmp     si, modes_table
  725.         jae     @f
  726.         mov     si, modes_table
  727. @@:
  728.         mov     word [cursor_pos], si
  729.         mov     si, word [home_cursor]
  730.         sub     si, size_of_step*long_v_table
  731.         cmp     si, modes_table
  732.         jae     @f
  733.         mov     si, modes_table
  734. @@:
  735.         mov     word [home_cursor], si
  736.         jmp     .loops
  737.  
  738. .pgdn:
  739.         cmp     ah, 0x51                ; page down
  740.         jne     .enter
  741.         mov     ax, [end_cursor]
  742.         add     si, size_of_step*long_v_table
  743.         cmp     si, ax
  744.         jb      @f
  745.         mov     si, ax
  746.         sub     si, size_of_step
  747. @@:
  748.         mov     word [cursor_pos], si
  749.         mov     si, word [home_cursor]
  750.         sub     ax, size_of_step*long_v_table
  751.         add     si, size_of_step*long_v_table
  752.         cmp     si, ax
  753.         jb      @f
  754.         mov     si, ax
  755. @@:
  756.         mov     word [home_cursor], si
  757.         jmp     .loops
  758.  
  759. .enter:
  760.         cmp     al, 0x0D;x,0x1C0D               ; enter
  761.         jne     .loops
  762.         push    word [cursor_pos]
  763.         pop     bp
  764.         push    word [es:bp]
  765.         pop     word [x_save]
  766.         push    word [es:bp+2]
  767.         pop     word [y_save]
  768.         push    word [es:bp+6]
  769.         pop     word [number_vm]
  770.         mov     word [preboot_graph], bp          ;save choose
  771.        
  772.         jmp     .d
  773.  
  774. .change_b:                      ; b) preboot_biosdisk  = use BIOS disks through V86 emulation?
  775. ;        _setcursor 16,0
  776. ;        mov     si, ask_dma    // (earlier was: preboot_dma  = use DMA access?)
  777. ;        call    print
  778. ;        mov     bx, '13'       ; range accepted for answer: 1-3
  779. ;        call    getkey
  780. ;        mov     [preboot_dma], al
  781.         _ask_question ask_bd,'12',preboot_biosdisk              ; range accepted for answer: 1-2
  782.         _setcursor 11,0
  783.         jmp     .d
  784. .change_c:                      ; c) preboot_debug = duplicates kernel debug output to the screen
  785.         _ask_question ask_debug,'12',preboot_debug              ; range accepted for answer: 1-2
  786.         _setcursor 12,0
  787.         jmp     .d
  788. .change_d:                      ; d) preboot_launcher = start the first app (right now it's LAUNCHER) after kernel is loaded?
  789.         _ask_question ask_launcher,'12',preboot_launcher        ; range accepted for answer: 1-2
  790.         _setcursor 13,0
  791.         jmp     .d
  792. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  793. .say_on_off:
  794.         pushf
  795.         call    print
  796.         mov     si, on_msg
  797.         popf
  798.         jz      @f
  799.         mov     si, off_msg
  800. @@:
  801.         jmp     printplain
  802. ; novesa and vervesa strings are not used at the moment of executing this code
  803. virtual at novesa
  804. .oldtimer dd ?
  805. .starttime dd ?
  806. if ~ defined extended_primary_loader
  807. .bSettingsChanged db ?
  808. end if
  809. .timer dd ?
  810. end virtual
  811. if ~ defined extended_primary_loader
  812. .loader_block dd -1
  813. end if
  814. .gettime:
  815.         mov     ah, 0
  816.         int     1Ah
  817.         xchg    ax, cx
  818.         shl     eax, 10h
  819.         xchg    ax, dx
  820.         ret
  821. .newtimer:
  822.         push    ds
  823.         push    cs
  824.         pop     ds
  825.         pushf
  826.         call    [.oldtimer]
  827.         pushad
  828.         call    .gettime
  829.         sub     eax, [.starttime]
  830. if defined extended_primary_loader
  831.         sub     ax, [preboot_timeout]
  832. else
  833.         sub     ax, 18*5
  834. end if
  835.         jae     .timergo
  836.         neg     ax
  837.         add     ax, 18-1
  838.         mov     bx, 18
  839.         xor     dx, dx
  840.         div     bx
  841. if lang eq ru
  842. ; подождите 5 секунд, 4/3/2 секунды, 1 секунду
  843.         cmp     al, 5
  844.         mov     cl, ' '
  845.         jae     @f
  846.         cmp     al, 1
  847.         mov     cl, 0xE3 ; 'у' in cp866
  848.         jz      @f
  849.         mov     cl, 0xEB ; 'ы' in cp866
  850. @@:
  851.         mov     [time_str+9], cl
  852. else if lang eq et
  853.         cmp     al, 1
  854.         ja      @f
  855.         mov     byte [time_str+9], ' '
  856.         mov     byte [time_str+10], ' '
  857. @@:
  858. else if lang eq sp
  859. ; esperar 5/4/3/2 segundos, 1 segundo
  860.         cmp     al, 1
  861.         mov     cl, 's'
  862.         ja      @f
  863.         mov     cl, ' '
  864. @@:
  865.         mov     [time_str+10], cl
  866. else
  867. ; wait 5/4/3/2 seconds, 1 second
  868.         cmp     al, 1
  869.         mov     cl, 's'
  870.         ja      @f
  871.         mov     cl, ' '
  872. @@:
  873.         mov     [time_str+9], cl
  874. end if
  875.         add     al, '0'
  876.         mov     [time_str+1], al
  877.         mov     si, time_msg
  878.         _setcursor 7,0
  879.         call    print
  880.         _setcursor 25,0
  881.         popad
  882.         pop     ds
  883.         iret
  884. .timergo:
  885.         push    0
  886.         pop     es
  887.         mov     eax, [.oldtimer]
  888.         mov     [es:8*4], eax
  889.         mov     sp, 0EC00h
  890. .continue:
  891.         sti
  892.         _setcursor 6,0
  893.         mov     si, space_msg
  894.         call    printplain
  895.         call    printplain
  896.         _setcursor 6,0
  897.         mov     si, loading_msg
  898.         call    print
  899.         _setcursor 16,0
  900. if ~ defined extended_primary_loader
  901.         cmp     [.bSettingsChanged], 0
  902.         jz      .load
  903.         cmp     [.loader_block], -1
  904.         jz      .load
  905.         les     bx, [.loader_block]
  906.         mov     eax, [es:bx+3]
  907.         push    ds
  908.         pop     es
  909.         test    eax, eax
  910.         jz      .load
  911.         push    eax
  912.         mov     si, save_quest
  913.         call    print
  914. .waityn:
  915.         mov     ah, 0
  916.         int     16h
  917.         or      al, 20h
  918.         cmp     al, 'n'
  919.         jz      .loadc
  920.         if lang eq sp
  921.         cmp     al, 's'
  922.         else
  923.         cmp     al, 'y'
  924.         end if
  925.         jnz     .waityn
  926.         call    putchar
  927.         mov     byte [space_msg+80], 186
  928.  
  929.         pop     eax
  930.         push    cs
  931.         push    .cont
  932.         push    eax
  933.         retf                          ;call back
  934. .loadc:
  935.         pop     eax
  936. .cont:
  937.         push    cs
  938.         pop     ds
  939.         mov     si, space_msg
  940.         mov     byte [si+80], 0
  941.         _setcursor 16,0
  942.         call    printplain
  943.         _setcursor 16,0
  944. .load:
  945. end if
  946. ; \end{diamond}[02.12.2005]
  947.  
  948. ; ASK GRAPHICS MODE
  949.  
  950.         call    set_vmode
  951.  
  952. ; GRAPHICS ACCELERATION
  953. ; force yes
  954.         mov     [es:BOOT_LO.mtrr], byte 1
  955.  
  956. ; DMA ACCESS TO HD
  957.  
  958.         mov     al, [preboot_dma]
  959.         mov     [es:BOOT_LO.dma], al
  960.  
  961. ; Set kernel DEBUG mode - if nonzero, duplicates debug output to the screen.
  962.         mov     al, [preboot_debug]
  963.         mov     [es:BOOT_LO.debug_print], al       ;// 0x901E
  964.  
  965. ; Start the first app (right now it's LAUNCHER) after kernel is loaded?
  966.         mov     al, [preboot_launcher]
  967.         mov     [es:BOOT_LO.launcher_start], al    ;// 0x901D        
  968.  
  969. ; BOOT DEVICE
  970.  
  971.         mov     al, [preboot_device]
  972.         dec     al
  973.         mov     [es:BOOT_LO.dev], al
  974.  
  975. ; GET MEMORY MAP
  976. include '../detect/biosmem.inc'
  977.  
  978. ; READ DISKETTE TO MEMORY
  979.  
  980.         cmp     byte [es:BOOT_LO.dev], 0
  981.         jne     no_sys_on_floppy
  982.         mov     si, diskload
  983.         call    print
  984.         xor     ax, ax            ; reset drive
  985.         xor     dx, dx
  986.         int     0x13
  987. ; do we boot from CD-ROM?
  988.         mov     ah, 41h
  989.         mov     bx, 55AAh
  990.         xor     dx, dx
  991.         int     0x13
  992.         jc      .nocd
  993.         cmp     bx, 0AA55h
  994.         jnz     .nocd
  995.         mov     ah, 48h
  996.         push    ds
  997.         push    es
  998.         pop     ds
  999.         mov     si, 0xa000
  1000.         mov     word [si], 30
  1001.         int     0x13
  1002.         pop     ds
  1003.         jc      .nocd
  1004.         push    ds
  1005.         lds     si, [es:si+26]
  1006.         test    byte [ds:si+10], 40h
  1007.         pop     ds
  1008.         jz      .nocd
  1009. ; yes - read all floppy by 18 sectors
  1010.  
  1011. ; TODO: !!!! read only first sector and set variables !!!!!
  1012. ; ...
  1013. ; TODO: !!! then read flippy image track by track
  1014.        
  1015.         mov     cx, 0x0001      ; startcyl,startsector
  1016. .a1:
  1017.         push    cx dx
  1018.         mov     al, 18
  1019.         mov     bx, 0xa000
  1020.         call    boot_read_floppy
  1021.         mov     si, movedesc
  1022.         push    es
  1023.         push    ds
  1024.         pop     es
  1025.         mov     cx, 256*18
  1026.         mov     ah, 0x87
  1027.         int     0x15
  1028.         pop     es
  1029.         pop     dx cx
  1030.         test    ah, ah
  1031.         jnz     sayerr_floppy
  1032.         add     dword [si+8*3+2], 512*18
  1033.         inc     dh
  1034.         cmp     dh, 2
  1035.         jnz     .a1
  1036.         mov     dh, 0
  1037.         inc     ch
  1038.         cmp     ch, 80
  1039.         jae     ok_sys_on_floppy
  1040.         pusha
  1041.         mov     al, ch
  1042.         shr     ch, 2
  1043.         add     al, ch
  1044.         aam
  1045.         xchg    al, ah
  1046.         add     ax, '00'
  1047.         mov     si, pros
  1048.         mov     [si], ax
  1049.         call    printplain
  1050.         popa
  1051.         jmp     .a1
  1052. .nocd:
  1053. ; no - read only used sectors from floppy
  1054. ; now load floppy image to memory
  1055. ; at first load boot sector and first FAT table
  1056.  
  1057. ; read only first sector and fill variables
  1058.         mov     cx, 0x0001      ; first logical sector
  1059.         xor     dx, dx          ; head = 0, drive = 0 (a:)
  1060.         mov     al, 1           ; read one sector
  1061.         mov     bx, 0xB000      ; es:bx -> data area
  1062.         call    boot_read_floppy
  1063. ; fill the necessary parameters to work with a floppy
  1064.         mov     ax, word [es:bx+24]
  1065.         mov     word [BPB_SecPerTrk], ax
  1066.         mov     ax, word [es:bx+26]
  1067.         mov     word [BPB_NumHeads], ax
  1068.         mov     ax, word [es:bx+17]
  1069.         mov     word [BPB_RootEntCnt], ax
  1070.         mov     ax, word [es:bx+14]
  1071.         mov     word [BPB_RsvdSecCnt], ax
  1072.         mov     ax, word [es:bx+19]
  1073.         mov     word [BPB_TotSec16], ax
  1074.         mov     al, byte [es:bx+13]
  1075.         mov     byte [BPB_SecPerClus], al
  1076.         mov     al, byte [es:bx+16]
  1077.         mov     byte [BPB_NumFATs], al
  1078. ;<Lrz> 18.11.2008
  1079.         mov     ax, word [es:bx+22]
  1080.         mov     word [BPB_FATSz16], ax
  1081.         mov     cx, word [es:bx+11]
  1082.         mov     word [BPB_BytsPerSec], cx
  1083.  
  1084. ; count of clusters in FAT12 ((size_of_FAT*2)/3)
  1085. ;        mov     ax, word [BPB_FATSz16]
  1086. ;        mov     cx, word [BPB_BytsPerSec]
  1087. ;end <Lrz> 18.11.2008
  1088.         xor     dx, dx
  1089.         mul     cx
  1090.         shl     ax, 1
  1091.         mov     cx, 3
  1092.         div     cx              ; now ax - number of clusters in FAT12
  1093.         mov     word [end_of_FAT], ax
  1094.  
  1095. ; load first FAT table
  1096.         mov     cx, 0x0002      ; startcyl,startsector          ; TODO!!!!!
  1097.         xor     dx, dx          ; starthead,drive
  1098.         mov     al, byte [BPB_FATSz16]     ; no of sectors to read
  1099.         add     bx, word [BPB_BytsPerSec]  ; es:bx -> data area
  1100.         call    boot_read_floppy
  1101.         mov     bx, 0xB000
  1102.  
  1103. ; and copy them to extended memory
  1104.         mov     si, movedesc
  1105.         mov     [si+8*2+3], bh          ; from
  1106.        
  1107.         mov     ax, word [BPB_BytsPerSec]
  1108.         shr     ax, 1                   ; words per sector
  1109.         mov     cx, word [BPB_RsvdSecCnt]
  1110.         add     cx, word [BPB_FATSz16]
  1111.         mul     cx
  1112.         push    ax                      ; save to stack count of words in boot+FAT
  1113.         xchg    ax, cx
  1114.        
  1115.         push    es
  1116.         push    ds
  1117.         pop     es
  1118.         mov     ah, 0x87
  1119.         int     0x15
  1120.         pop     es
  1121.         test    ah, ah
  1122.         jz      @f
  1123. sayerr_floppy:
  1124.         mov     dx, 0x3f2
  1125.         mov     al, 0
  1126.         out     dx, al
  1127. sayerr_memmove:
  1128.         mov     si, memmovefailed
  1129.         jmp     sayerr_plain
  1130. @@:
  1131.         pop     ax                      ; restore from stack count of words in boot+FAT
  1132.         shl     ax, 1                   ; make bytes count from count of words
  1133.         and     eax, 0ffffh
  1134.         add     dword [si+8*3+2], eax
  1135.  
  1136. ; copy first FAT to second copy
  1137. ; TODO: BPB_NumFATs !!!!!
  1138.         add     bx, word [BPB_BytsPerSec]       ; !!! TODO: may be need multiply by BPB_RsvdSecCnt !!!
  1139.         mov     byte [si+8*2+3], bh     ; bx - begin of FAT
  1140.        
  1141.         mov     ax, word [BPB_BytsPerSec]
  1142.         shr     ax, 1                   ; words per sector
  1143.         mov     cx, word [BPB_FATSz16]
  1144.         mul     cx
  1145.         mov     cx, ax                  ; cx - count of words in FAT
  1146.  
  1147.         push    es
  1148.         push    ds
  1149.         pop     es
  1150.         mov     ah, 0x87
  1151.         int     0x15
  1152.         pop     es
  1153.         test    ah, ah
  1154.         jnz     sayerr_floppy
  1155.        
  1156.         mov     ax, cx
  1157.         shl     ax, 1
  1158.         and     eax, 0ffffh             ; ax - count of bytes in FAT
  1159.         add     dword [si+8*3+2], eax
  1160.        
  1161. ; reading RootDir
  1162. ; TODO: BPB_NumFATs
  1163.         add     bx, ax
  1164.         add     bx, 100h
  1165.         and     bx, 0ff00h                      ; bx - place in buffer to write RootDir
  1166.         push    bx
  1167.  
  1168.         mov     bx, word [BPB_BytsPerSec]
  1169.         shr     bx, 5                           ; divide bx by 32
  1170.         mov     ax, word [BPB_RootEntCnt]
  1171.         xor     dx, dx
  1172.         div     bx
  1173.         push    ax                              ; ax - count of RootDir sectors
  1174.  
  1175.         mov     ax, word [BPB_FATSz16]
  1176.         xor     cx, cx
  1177.         mov     cl, byte [BPB_NumFATs]
  1178.         mul     cx
  1179.         add     ax, word [BPB_RsvdSecCnt]       ; ax - first sector of RootDir
  1180.  
  1181.         mov     word [FirstDataSector], ax
  1182.         pop     bx
  1183.         push    bx
  1184.         add     word [FirstDataSector], bx      ; Begin of data region of floppy
  1185.        
  1186. ; read RootDir
  1187.         call    conv_abs_to_THS
  1188.         pop     ax
  1189.         pop     bx                              ; place in buffer to write
  1190.         push    ax
  1191.         call    boot_read_floppy                ; read RootDir into buffer
  1192. ; copy RootDir
  1193.         mov     byte [si+8*2+3], bh             ; from buffer
  1194.         pop     ax                              ; ax = count of RootDir sectors
  1195.         mov     cx, word [BPB_BytsPerSec]
  1196.         mul     cx
  1197.         shr     ax, 1
  1198.         mov     cx, ax                          ; count of words to copy
  1199.         push    es
  1200.         push    ds
  1201.         pop     es
  1202.         mov     ah, 0x87
  1203.         int     0x15
  1204.         pop     es
  1205.  
  1206.         mov     ax, cx
  1207.         shl     ax, 1
  1208.         and     eax, 0ffffh             ; ax - count of bytes in RootDir
  1209.         add     dword [si+8*3+2], eax   ; add count of bytes copied
  1210.  
  1211. ; Reading data clusters from floppy
  1212.         mov     byte [si+8*2+3], bh
  1213.         push    bx
  1214.  
  1215.         mov     di, 2                   ; First data cluster
  1216. .read_loop:
  1217.         mov     bx, di
  1218.         shr     bx, 1                   ; bx+di = di*1.5
  1219.         jnc     .even
  1220.         test    word [es:bx+di+0xB200], 0xFFF0  ; TODO: may not be 0xB200 !!!
  1221.         jmp     @f
  1222. .even:
  1223.         test    word [es:bx+di+0xB200], 0xFFF   ; TODO: may not be 0xB200 !!!
  1224.  
  1225. @@:
  1226.         jz      .skip
  1227. ; read cluster di
  1228. ;.read:
  1229.         ;conv cluster di to abs. sector ax
  1230.         ; ax = (N-2) * BPB_SecPerClus + FirstDataSector
  1231.         mov     ax, di
  1232.         sub     ax, 2
  1233.         xor     bx, bx
  1234.         mov     bl, byte [BPB_SecPerClus]
  1235.         mul     bx
  1236.         add     ax, word [FirstDataSector]
  1237.         call    conv_abs_to_THS
  1238.         pop     bx
  1239.         push    bx
  1240.         mov     al, byte [BPB_SecPerClus]       ; number of sectors in cluster
  1241.         call    boot_read_floppy
  1242.         push    es
  1243.         push    ds
  1244.         pop     es
  1245.         pusha
  1246. ;
  1247.         mov     ax, word [BPB_BytsPerSec]
  1248.         xor     cx, cx
  1249.         mov     cl, byte [BPB_SecPerClus]
  1250.         mul     cx
  1251.         shr     ax, 1                           ; ax = (BPB_BytsPerSec * BPB_SecPerClus)/2
  1252.         mov     cx, ax                          ; number of words to copy (count words in cluster)
  1253. ;
  1254.         mov     ah, 0x87
  1255.         int     0x15                            ; copy data
  1256.         test    ah, ah
  1257.         popa
  1258.         pop     es
  1259.         jnz     sayerr_floppy
  1260. ; skip cluster di
  1261. .skip:
  1262.         mov     ax, word [BPB_BytsPerSec]
  1263.         xor     cx, cx
  1264.         mov     cl, byte [BPB_SecPerClus]
  1265.         mul     cx
  1266.         and     eax, 0ffffh             ; ax - count of bytes in cluster
  1267.         add     dword [si+8*3+2], eax
  1268.  
  1269.         mov     ax, word [end_of_FAT]   ; max cluster number
  1270.         pusha
  1271. ; draw percentage
  1272. ; total clusters: ax
  1273. ; read clusters: di
  1274.         xchg    ax, di
  1275.         mov     cx, 100
  1276.         mul     cx
  1277.         div     di
  1278.         aam
  1279.         xchg    al, ah
  1280.         add     ax, '00'
  1281.         mov     si, pros
  1282.         cmp     [si], ax
  1283.         jz      @f
  1284.         mov     [si], ax
  1285.         call    printplain
  1286. @@:
  1287.         popa
  1288.         inc     di
  1289.         cmp     di, word [end_of_FAT]   ; max number of cluster
  1290.         jnz     .read_loop
  1291.         pop     bx                      ; clear stack
  1292.  
  1293. ok_sys_on_floppy:
  1294.         mov     si, backspace2
  1295.         call    printplain
  1296.         mov     si, okt
  1297.         call    printplain
  1298. no_sys_on_floppy:
  1299.         xor     ax, ax          ; reset drive
  1300.         xor     dx, dx
  1301.         int     0x13
  1302.         mov     dx, 0x3f2       ; floppy motor off
  1303.         mov     al, 0
  1304.         out     dx, al
  1305.  
  1306. if defined extended_primary_loader
  1307.         cmp     [es:BOOT_LO.dev], 1
  1308.         jne     no_sys_from_primary
  1309. ; load kolibri.img using callback from primary loader
  1310.         and     word [movedesc + 24 + 2], 0
  1311.         mov     byte [movedesc + 24 + 4], 10h
  1312. ; read in blocks of 64K until file is fully loaded
  1313.         mov     ax, 1
  1314. .repeat:
  1315.         mov     di, image_file_struct
  1316.         call    [bootcallback]
  1317.         push    cs
  1318.         pop     ds
  1319.         push    cs
  1320.         pop     es
  1321.         cmp     bx, 1
  1322.         ja      sayerr_badsect
  1323.         push    bx
  1324.         mov     si, movedesc
  1325.         and     word [si + 16 + 2], 0
  1326.         mov     byte [si + 16 + 4], 4
  1327.         mov     ah, 87h
  1328.         mov     cx, 8000h
  1329.         int     15h
  1330.         pop     bx
  1331.         test    ah, ah
  1332.         jnz     sayerr_memmove
  1333.         inc     byte [si + 24 + 4]
  1334.         test    bx, bx
  1335.         jz      no_sys_from_primary
  1336.         mov     ax, 2
  1337.         jmp     .repeat
  1338. no_sys_from_primary:
  1339. end if
  1340.  
  1341. ; SET GRAPHICS
  1342.  
  1343.         xor     ax, ax
  1344.         mov     es, ax
  1345.  
  1346.         mov     ax, [es:BOOT_LO.vesa_mode]         ; vga & 320x200
  1347.         mov     bx, ax
  1348.         cmp     ax, 0x13
  1349.         je      setgr
  1350.         cmp     ax, 0x12
  1351.         je      setgr
  1352.         mov     ax, 0x4f02              ; Vesa
  1353. setgr:
  1354.         int     0x10
  1355.         test    ah, ah
  1356.         mov     si, fatalsel
  1357.         jnz     v_mode_error
  1358. ; set mode 0x12 graphics registers:
  1359.         cmp     bx, 0x12
  1360.         jne     gmok2
  1361.  
  1362.         mov     al, 0x05
  1363.         mov     dx, 0x03ce
  1364.         push    dx
  1365.         out     dx, al      ; select GDC mode register
  1366.         mov     al, 0x02
  1367.         inc     dx
  1368.         out     dx, al      ; set write mode 2
  1369.  
  1370.         mov     al, 0x02
  1371.         mov     dx, 0x03c4
  1372.         out     dx, al      ; select VGA sequencer map mask register
  1373.         mov     al, 0x0f
  1374.         inc     dx
  1375.         out     dx, al      ; set mask for all planes 0-3
  1376.  
  1377.         mov     al, 0x08
  1378.         pop     dx
  1379.         out     dx, al      ; select GDC bit mask register
  1380.                            ; for writes to 0x03cf
  1381. gmok2:
  1382.         push    ds
  1383.         pop     es
  1384.