Subversion Repositories Kolibri OS

Rev

Rev 7132 | 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: 7586 $
  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.         ; bios 0x1A timer runs at ~18 ticks per second
  834.         sub     ax, 18*PREBOOT_TIMEOUT
  835. end if
  836.         jae     .timergo
  837.         neg     ax
  838.         add     ax, 18-1
  839.         mov     bx, 18
  840.         xor     dx, dx
  841.         div     bx
  842. if lang eq ru
  843. ; подождите 5 секунд, 4/3/2 секунды, 1 секунду
  844.         cmp     al, 5
  845.         mov     cl, ' '
  846.         jae     @f
  847.         cmp     al, 1
  848.         mov     cl, 0xE3 ; 'у' in cp866
  849.         jz      @f
  850.         mov     cl, 0xEB ; 'ы' in cp866
  851. @@:
  852.         mov     [time_str+9], cl
  853. else if lang eq et
  854.         cmp     al, 1
  855.         ja      @f
  856.         mov     byte [time_str+9], ' '
  857.         mov     byte [time_str+10], ' '
  858. @@:
  859. else if lang eq sp
  860. ; esperar 5/4/3/2 segundos, 1 segundo
  861.         cmp     al, 1
  862.         mov     cl, 's'
  863.         ja      @f
  864.         mov     cl, ' '
  865. @@:
  866.         mov     [time_str+10], cl
  867. else
  868. ; wait 5/4/3/2 seconds, 1 second
  869.         cmp     al, 1
  870.         mov     cl, 's'
  871.         ja      @f
  872.         mov     cl, ' '
  873. @@:
  874.         mov     [time_str+9], cl
  875. end if
  876.         add     al, '0'
  877.         mov     [time_str+1], al
  878.         mov     si, time_msg
  879.         _setcursor 7,0
  880.         call    print
  881.         _setcursor 25,0
  882.         popad
  883.         pop     ds
  884.         iret
  885. .timergo:
  886.         push    0
  887.         pop     es
  888.         mov     eax, [.oldtimer]
  889.         mov     [es:8*4], eax
  890.         mov     sp, 0EC00h
  891. .continue:
  892.         sti
  893.         _setcursor 6,0
  894.         mov     si, space_msg
  895.         call    printplain
  896.         call    printplain
  897.         _setcursor 6,0
  898.         mov     si, loading_msg
  899.         call    print
  900.         _setcursor 16,0
  901. if ~ defined extended_primary_loader
  902.         cmp     [.bSettingsChanged], 0
  903.         jz      .load
  904.         cmp     [.loader_block], -1
  905.         jz      .load
  906.         les     bx, [.loader_block]
  907.         mov     eax, [es:bx+3]
  908.         push    ds
  909.         pop     es
  910.         test    eax, eax
  911.         jz      .load
  912.         push    eax
  913.         mov     si, save_quest
  914.         call    print
  915. .waityn:
  916.         mov     ah, 0
  917.         int     16h
  918.         or      al, 20h
  919.         cmp     al, 'n'
  920.         jz      .loadc
  921.         if lang eq sp
  922.         cmp     al, 's'
  923.         else
  924.         cmp     al, 'y'
  925.         end if
  926.         jnz     .waityn
  927.         call    putchar
  928.         mov     byte [space_msg+80], 186
  929.  
  930.         pop     eax
  931.         push    cs
  932.         push    .cont
  933.         push    eax
  934.         retf                          ;call back
  935. .loadc:
  936.         pop     eax
  937. .cont:
  938.         push    cs
  939.         pop     ds
  940.         mov     si, space_msg
  941.         mov     byte [si+80], 0
  942.         _setcursor 16,0
  943.         call    printplain
  944.         _setcursor 16,0
  945. .load:
  946. end if
  947. ; \end{diamond}[02.12.2005]
  948.  
  949. ; ASK GRAPHICS MODE
  950.  
  951.         call    set_vmode
  952.  
  953. ; GRAPHICS ACCELERATION
  954. ; force yes
  955.         mov     [es:BOOT_LO.mtrr], byte 1
  956.  
  957. ; DMA ACCESS TO HD
  958.  
  959.         mov     al, [preboot_dma]
  960.         mov     [es:BOOT_LO.dma], al
  961.  
  962. ; Set kernel DEBUG mode - if nonzero, duplicates debug output to the screen.
  963.         mov     al, [preboot_debug]
  964.         mov     [es:BOOT_LO.debug_print], al       ;// 0x901E
  965.  
  966. ; Start the first app (right now it's LAUNCHER) after kernel is loaded?
  967.         mov     al, [preboot_launcher]
  968.         mov     [es:BOOT_LO.launcher_start], al    ;// 0x901D        
  969.  
  970. ; BOOT DEVICE
  971.  
  972.         mov     al, [preboot_device]
  973.         dec     al
  974.         mov     [es:BOOT_LO.dev], al
  975.  
  976. ; GET MEMORY MAP
  977. include '../detect/biosmem.inc'
  978.  
  979. ; READ DISKETTE TO MEMORY
  980.  
  981.         cmp     byte [es:BOOT_LO.dev], 0
  982.         jne     no_sys_on_floppy
  983.         mov     si, diskload
  984.         call    print
  985.         xor     ax, ax            ; reset drive
  986.         xor     dx, dx
  987.         int     0x13
  988. ; do we boot from CD-ROM?
  989.         mov     ah, 41h
  990.         mov     bx, 55AAh
  991.         xor     dx, dx
  992.         int     0x13
  993.         jc      .nocd
  994.         cmp     bx, 0AA55h
  995.         jnz     .nocd
  996.         mov     ah, 48h
  997.         push    ds
  998.         push    es
  999.         pop     ds
  1000.         mov     si, 0xa000
  1001.         mov     word [si], 30
  1002.         int     0x13
  1003.         pop     ds
  1004.         jc      .nocd
  1005.         push    ds
  1006.         lds     si, [es:si+26]
  1007.         test    byte [ds:si+10], 40h
  1008.         pop     ds
  1009.         jz      .nocd
  1010. ; yes - read all floppy by 18 sectors
  1011.  
  1012. ; TODO: !!!! read only first sector and set variables !!!!!
  1013. ; ...
  1014. ; TODO: !!! then read flippy image track by track
  1015.        
  1016.         mov     cx, 0x0001      ; startcyl,startsector
  1017. .a1:
  1018.         push    cx dx
  1019.         mov     al, 18
  1020.         mov     bx, 0xa000
  1021.         call    boot_read_floppy
  1022.         mov     si, movedesc
  1023.         push    es
  1024.         push    ds
  1025.         pop     es
  1026.         mov     cx, 256*18
  1027.         mov     ah, 0x87
  1028.         int     0x15
  1029.         pop     es
  1030.         pop     dx cx
  1031.         test    ah, ah
  1032.         jnz     sayerr_floppy
  1033.         add     dword [si+8*3+2], 512*18
  1034.         inc     dh
  1035.         cmp     dh, 2
  1036.         jnz     .a1
  1037.         mov     dh, 0
  1038.         inc     ch
  1039.         cmp     ch, 80
  1040.         jae     ok_sys_on_floppy
  1041.         pusha
  1042.         mov     al, ch
  1043.         shr     ch, 2
  1044.         add     al, ch
  1045.         aam
  1046.         xchg    al, ah
  1047.         add     ax, '00'
  1048.         mov     si, pros
  1049.         mov     [si], ax
  1050.         call    printplain
  1051.         popa
  1052.         jmp     .a1
  1053. .nocd:
  1054. ; no - read only used sectors from floppy
  1055. ; now load floppy image to memory
  1056. ; at first load boot sector and first FAT table
  1057.  
  1058. ; read only first sector and fill variables
  1059.         mov     cx, 0x0001      ; first logical sector
  1060.         xor     dx, dx          ; head = 0, drive = 0 (a:)
  1061.         mov     al, 1           ; read one sector
  1062.         mov     bx, 0xB000      ; es:bx -> data area
  1063.         call    boot_read_floppy
  1064. ; fill the necessary parameters to work with a floppy
  1065.         mov     ax, word [es:bx+24]
  1066.         mov     word [BPB_SecPerTrk], ax
  1067.         mov     ax, word [es:bx+26]
  1068.         mov     word [BPB_NumHeads], ax
  1069.         mov     ax, word [es:bx+17]
  1070.         mov     word [BPB_RootEntCnt], ax
  1071.         mov     ax, word [es:bx+14]
  1072.         mov     word [BPB_RsvdSecCnt], ax
  1073.         mov     ax, word [es:bx+19]
  1074.         mov     word [BPB_TotSec16], ax
  1075.         mov     al, byte [es:bx+13]
  1076.         mov     byte [BPB_SecPerClus], al
  1077.         mov     al, byte [es:bx+16]
  1078.         mov     byte [BPB_NumFATs], al
  1079. ;<Lrz> 18.11.2008
  1080.         mov     ax, word [es:bx+22]
  1081.         mov     word [BPB_FATSz16], ax
  1082.         mov     cx, word [es:bx+11]
  1083.         mov     word [BPB_BytsPerSec], cx
  1084.  
  1085. ; count of clusters in FAT12 ((size_of_FAT*2)/3)
  1086. ;        mov     ax, word [BPB_FATSz16]
  1087. ;        mov     cx, word [BPB_BytsPerSec]
  1088. ;end <Lrz> 18.11.2008
  1089.         xor     dx, dx
  1090.         mul     cx
  1091.         shl     ax, 1
  1092.         mov     cx, 3
  1093.         div     cx              ; now ax - number of clusters in FAT12
  1094.         mov     word [end_of_FAT], ax
  1095.  
  1096. ; load first FAT table
  1097.         mov     cx, 0x0002      ; startcyl,startsector          ; TODO!!!!!
  1098.         xor     dx, dx          ; starthead,drive
  1099.         mov     al, byte [BPB_FATSz16]     ; no of sectors to read
  1100.         add     bx, word [BPB_BytsPerSec]  ; es:bx -> data area
  1101.         call    boot_read_floppy
  1102.         mov     bx, 0xB000
  1103.  
  1104. ; and copy them to extended memory
  1105.         mov     si, movedesc
  1106.         mov     [si+8*2+3], bh          ; from
  1107.        
  1108.         mov     ax, word [BPB_BytsPerSec]
  1109.         shr     ax, 1                   ; words per sector
  1110.         mov     cx, word [BPB_RsvdSecCnt]
  1111.         add     cx, word [BPB_FATSz16]
  1112.         mul     cx
  1113.         push    ax                      ; save to stack count of words in boot+FAT
  1114.         xchg    ax, cx
  1115.        
  1116.         push    es
  1117.         push    ds
  1118.         pop     es
  1119.         mov     ah, 0x87
  1120.         int     0x15
  1121.         pop     es
  1122.         test    ah, ah
  1123.         jz      @f
  1124. sayerr_floppy:
  1125.         mov     dx, 0x3f2
  1126.         mov     al, 0
  1127.         out     dx, al
  1128. sayerr_memmove:
  1129.         mov     si, memmovefailed
  1130.         jmp     sayerr_plain
  1131. @@:
  1132.         pop     ax                      ; restore from stack count of words in boot+FAT
  1133.         shl     ax, 1                   ; make bytes count from count of words
  1134.         and     eax, 0ffffh
  1135.         add     dword [si+8*3+2], eax
  1136.  
  1137. ; copy first FAT to second copy
  1138. ; TODO: BPB_NumFATs !!!!!
  1139.         add     bx, word [BPB_BytsPerSec]       ; !!! TODO: may be need multiply by BPB_RsvdSecCnt !!!
  1140.         mov     byte [si+8*2+3], bh     ; bx - begin of FAT
  1141.        
  1142.         mov     ax, word [BPB_BytsPerSec]
  1143.         shr     ax, 1                   ; words per sector
  1144.         mov     cx, word [BPB_FATSz16]
  1145.         mul     cx
  1146.         mov     cx, ax                  ; cx - count of words in FAT
  1147.  
  1148.         push    es
  1149.         push    ds
  1150.         pop     es
  1151.         mov     ah, 0x87
  1152.         int     0x15
  1153.         pop     es
  1154.         test    ah, ah
  1155.         jnz     sayerr_floppy
  1156.        
  1157.         mov     ax, cx
  1158.         shl     ax, 1
  1159.         and     eax, 0ffffh             ; ax - count of bytes in FAT
  1160.         add     dword [si+8*3+2], eax
  1161.        
  1162. ; reading RootDir
  1163. ; TODO: BPB_NumFATs
  1164.         add     bx, ax
  1165.         add     bx, 100h
  1166.         and     bx, 0ff00h                      ; bx - place in buffer to write RootDir
  1167.         push    bx
  1168.  
  1169.         mov     bx, word [BPB_BytsPerSec]
  1170.         shr     bx, 5                           ; divide bx by 32
  1171.         mov     ax, word [BPB_RootEntCnt]
  1172.         xor     dx, dx
  1173.         div     bx
  1174.         push    ax                              ; ax - count of RootDir sectors
  1175.  
  1176.         mov     ax, word [BPB_FATSz16]
  1177.         xor     cx, cx
  1178.         mov     cl, byte [BPB_NumFATs]
  1179.         mul     cx
  1180.         add     ax, word [BPB_RsvdSecCnt]       ; ax - first sector of RootDir
  1181.  
  1182.         mov     word [FirstDataSector], ax
  1183.         pop     bx
  1184.         push    bx
  1185.         add     word [FirstDataSector], bx      ; Begin of data region of floppy
  1186.        
  1187. ; read RootDir
  1188.         call    conv_abs_to_THS
  1189.         pop     ax
  1190.         pop     bx                              ; place in buffer to write
  1191.         push    ax
  1192.         call    boot_read_floppy                ; read RootDir into buffer
  1193. ; copy RootDir
  1194.         mov     byte [si+8*2+3], bh             ; from buffer
  1195.         pop     ax                              ; ax = count of RootDir sectors
  1196.         mov     cx, word [BPB_BytsPerSec]
  1197.         mul     cx
  1198.         shr     ax, 1
  1199.         mov     cx, ax                          ; count of words to copy
  1200.         push    es
  1201.         push    ds
  1202.         pop     es
  1203.         mov     ah, 0x87
  1204.         int     0x15
  1205.         pop     es
  1206.  
  1207.         mov     ax, cx
  1208.         shl     ax, 1
  1209.         and     eax, 0ffffh             ; ax - count of bytes in RootDir
  1210.         add     dword [si+8*3+2], eax   ; add count of bytes copied
  1211.  
  1212. ; Reading data clusters from floppy
  1213.         mov     byte [si+8*2+3], bh
  1214.         push    bx
  1215.  
  1216.         mov     di, 2                   ; First data cluster
  1217. .read_loop:
  1218.         mov     bx, di
  1219.         shr     bx, 1                   ; bx+di = di*1.5
  1220.         jnc     .even
  1221.         test    word [es:bx+di+0xB200], 0xFFF0  ; TODO: may not be 0xB200 !!!
  1222.         jmp     @f
  1223. .even:
  1224.         test    word [es:bx+di+0xB200], 0xFFF   ; TODO: may not be 0xB200 !!!
  1225.  
  1226. @@:
  1227.         jz      .skip
  1228. ; read cluster di
  1229. ;.read:
  1230.         ;conv cluster di to abs. sector ax
  1231.         ; ax = (N-2) * BPB_SecPerClus + FirstDataSector
  1232.         mov     ax, di
  1233.         sub     ax, 2
  1234.         xor     bx, bx
  1235.         mov     bl, byte [BPB_SecPerClus]
  1236.         mul     bx
  1237.         add     ax, word [FirstDataSector]
  1238.         call    conv_abs_to_THS
  1239.         pop     bx
  1240.         push    bx
  1241.         mov     al, byte [BPB_SecPerClus]       ; number of sectors in cluster
  1242.         call    boot_read_floppy
  1243.         push    es
  1244.         push    ds
  1245.         pop     es
  1246.         pusha
  1247. ;
  1248.         mov     ax, word [BPB_BytsPerSec]
  1249.         xor     cx, cx
  1250.         mov     cl, byte [BPB_SecPerClus]
  1251.         mul     cx
  1252.         shr     ax, 1                           ; ax = (BPB_BytsPerSec * BPB_SecPerClus)/2
  1253.         mov     cx, ax                          ; number of words to copy (count words in cluster)
  1254. ;
  1255.         mov     ah, 0x87
  1256.         int     0x15                            ; copy data
  1257.         test    ah, ah
  1258.         popa
  1259.         pop     es
  1260.         jnz     sayerr_floppy
  1261. ; skip cluster di
  1262. .skip:
  1263.         mov     ax, word [BPB_BytsPerSec]
  1264.         xor     cx, cx
  1265.         mov     cl, byte [BPB_SecPerClus]
  1266.         mul     cx
  1267.         and     eax, 0ffffh             ; ax - count of bytes in cluster
  1268.         add     dword [si+8*3+2], eax
  1269.  
  1270.         mov     ax, word [end_of_FAT]   ; max cluster number
  1271.         pusha
  1272. ; draw percentage
  1273. ; total clusters: ax
  1274. ; read clusters: di
  1275.         xchg    ax, di
  1276.         mov     cx, 100
  1277.         mul     cx
  1278.         div     di
  1279.         aam
  1280.         xchg    al, ah
  1281.         add     ax, '00'
  1282.         mov     si, pros
  1283.         cmp     [si], ax
  1284.         jz      @f
  1285.         mov     [si], ax
  1286.         call    printplain
  1287. @@:
  1288.         popa
  1289.         inc     di
  1290.         cmp     di, word [end_of_FAT]   ; max number of cluster
  1291.         jnz     .read_loop
  1292.         pop     bx                      ; clear stack
  1293.  
  1294. ok_sys_on_floppy:
  1295.         mov     si, backspace2
  1296.         call    printplain
  1297.         mov     si, okt
  1298.         call    printplain
  1299. no_sys_on_floppy:
  1300.         xor     ax, ax          ; reset drive
  1301.         xor     dx, dx
  1302.         int     0x13
  1303.         mov     dx, 0x3f2       ; floppy motor off
  1304.         mov     al, 0
  1305.         out     dx, al
  1306.  
  1307. if defined extended_primary_loader
  1308.         cmp     [es:BOOT_LO.dev], 1
  1309.         jne     no_sys_from_primary
  1310. ; load kolibri.img using callback from primary loader
  1311.         and     word [movedesc + 24 + 2], 0
  1312.         mov     byte [movedesc + 24 + 4], 10h
  1313. ; read in blocks of 64K until file is fully loaded
  1314.         mov     ax, 1
  1315. .repeat:
  1316.         mov     di, image_file_struct
  1317.         call    [bootcallback]
  1318.         push    cs
  1319.         pop     ds
  1320.         push    cs
  1321.         pop     es
  1322.         cmp     bx, 1
  1323.         ja      sayerr_badsect
  1324.         push    bx
  1325.         mov     si, movedesc
  1326.         and     word [si + 16 + 2], 0
  1327.         mov     byte [si + 16 + 4], 4
  1328.         mov     ah, 87h
  1329.         mov     cx, 8000h
  1330.         int     15h
  1331.         pop     bx
  1332.         test    ah, ah
  1333.         jnz     sayerr_memmove
  1334.         inc     byte [si + 24 + 4]
  1335.         test    bx, bx
  1336.         jz      no_sys_from_primary
  1337.         mov     ax, 2
  1338.         jmp     .repeat
  1339. no_sys_from_primary:
  1340. end if
  1341.  
  1342. ; SET GRAPHICS
  1343.  
  1344.         xor     ax, ax
  1345.         mov     es, ax
  1346.  
  1347.         mov     ax, [es:BOOT_LO.vesa_mode]         ; vga & 320x200
  1348.         mov     bx, ax
  1349.         cmp     ax, 0x13
  1350.         je      setgr
  1351.         cmp     ax, 0x12
  1352.         je      setgr
  1353.         mov     ax, 0x4f02              ; Vesa
  1354. setgr:
  1355.         int     0x10
  1356.         test    ah, ah
  1357.         mov     si, fatalsel
  1358.         jnz     v_mode_error
  1359. ; set mode 0x12 graphics registers:
  1360.         cmp     bx, 0x12
  1361.         jne     gmok2
  1362.  
  1363.         mov     al, 0x05
  1364.         mov     dx, 0x03ce
  1365.         push    dx
  1366.         out     dx, al      ; select GDC mode register
  1367.         mov     al, 0x02
  1368.         inc     dx
  1369.         out     dx, al      ; set write mode 2
  1370.  
  1371.         mov     al, 0x02
  1372.         mov     dx, 0x03c4
  1373.         out     dx, al      ; select VGA sequencer map mask register
  1374.         mov     al, 0x0f
  1375.         inc     dx
  1376.         out     dx, al      ; set mask for all planes 0-3
  1377.  
  1378.         mov     al, 0x08
  1379.         pop     dx
  1380.         out     dx, al      ; select GDC bit mask register
  1381.                            ; for writes to 0x03cf
  1382. gmok2:
  1383.         push    ds
  1384.         pop     es
  1385.