summaryrefslogtreecommitdiff
path: root/stage2/vesa.asm
blob: da7eb81874225926610c7bde489dab7c730ccbae (plain)
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 $