1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
|
vesa:
; print message
mov ebx, .msg
call print_str
; get vesa bios info
mov eax, dword[.vbe2]
mov dword[VESAINFO], eax ; move "VBE2" to start of vesainfo struct
mov ax, 0x4F00 ; get VESA BIOS information
mov di, VESAINFO ; struct buffer
int 0x10
cmp ax, 0x004F ; check ax for correct magic number
jne .fail_getinfo
mov eax, dword[.vesa]
cmp dword[VESAINFO], eax ; check if "VESA" is at start of stuct
jne .fail_getinfo
; print select message
mov ebx, .select_msg
call print_str
; get segment:offset pointer to video modes into gs:ebx
movzx ebx, word[VESAINFO+14]
mov ax, word[VESAINFO+16]
mov gs, ax
; convert modes to own structure
xor esi, esi ; number of avail modes
.mode_loop:
; get mode info
mov cx, [gs:ebx] ; video mode into cx
cmp cx, 0xFFFF ; 0xFFFF is terminator, no suitable mode has been found
je .mode_done
mov ax, 0x4F01 ; get VESA mode information
mov di, VESAMODE ; vesa mode info struct buffer
int 0x10
cmp ax, 0x004F ; check ax for correct magic number
jne .fail_modeinfo
mov al, byte[VESAMODE] ; get attributes
and al, 0b10000000 ; extract bit 7, indicates linear framebuffer support
jz .mode_next
mov al, byte[VESAMODE+25] ; get bpp (bits per pixel)
cmp al, 32
jne .mode_next
push ebx ; print_dec and print_str modify ebx
mov eax, esi
mov ebx, 12
mul ebx
mov edi, eax
add edi, OWNMODE
mov [edi+10], cx ; copy mode
; print selector
mov al, '['
call print_chr
mov eax, esi
add eax, 'a'
call print_chr
mov al, ']'
call print_chr
mov al, ' '
call print_chr
mov ax, [VESAMODE+16] ; copy pitch
mov [edi+0], ax
movzx eax, word[VESAMODE+18] ; copy width
mov [edi+2], ax
call print_dec
mov al, 'x'
call print_chr
movzx eax, word[VESAMODE+20] ; copy height
mov [edi+4], ax
call print_dec
call newline
mov eax, [VESAMODE+40] ; copy framebuffer
mov [edi+6], eax
pop ebx
inc esi
cmp esi, 'z'-'a' ; only print up to z
jg .mode_done
.mode_next:
add ebx, 2 ; increase mode pointer
jmp .mode_loop ; loop
.mode_done:
cmp esi, 0
je .fail_nomode
.input:
mov ebx, .select_prompt
call print_str
mov ah, 0x00 ; get keypress, blocking
int 0x16
call print_chr ; echo user input
movzx edi, al ; backup al
call newline
sub edi, 'a'
cmp edi, esi
jb .valid ; check validity
mov ebx, .invalid
call print_str
jmp .input
.valid:
; convert selected number to address
mov eax, edi
mov ebx, 12
mul ebx
add eax, OWNMODE
; copy to final gfx info location
mov ebx, [eax+0]
mov [GFXINFO+0], ebx
mov ebx, [eax+4]
mov [GFXINFO+4], ebx
mov bx, [eax+8]
mov [GFXINFO+8], bx
;mov edi, eax
;mov eax, [edi+6]
;call print_hex
;call newline
;mov eax, edi
;jmp $
;ret
; set mode
mov bx, [eax+10] ; video mode in bx (first 13 bits)
or bx, 1 << 14 ; set bit 14: enable linear frame buffer
and bx, 0b0111111111111111 ; clear deprecated bit 15
mov ax, 0x4F02 ; set VBE mode
int 0x10
ret
.msg: db "setting up vesa", 10, 13, 0
.vbe2: db "VBE2"
.vesa: db "VESA"
.select_msg: db "avaliable video modes:", 10, 13, 0
.select_prompt: db "select video mode: ", 0
.invalid: db "invalid input", 10, 13, 0
.fail_getinfo:
mov ebx, .fail_getinfo_msg
jmp .fail
.fail_modeinfo:
mov ebx, .fail_modeinfo_msg
jmp .fail
.fail_nomode:
mov ebx, .fail_nomode_msg
jmp .fail
.fail_getinfo_msg: db "failed getting vesa bios info", 10, 13, 0
.fail_modeinfo_msg: db "failed getting video mode info", 10, 13, 0
.fail_nomode_msg: db "no suitable video modes available", 10, 13, 0
.fail:
call print_str
jmp $
|