aboutsummaryrefslogtreecommitdiffstats
path: root/graphics.inc
blob: 2b8290fcbe3742161b7e7feeee607da59cfe8202 (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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
;; -----------------------------------------------------------------------
;;
;;   Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
;;
;;   This program is free software; you can redistribute it and/or modify
;;   it under the terms of the GNU General Public License as published by
;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
;;   Boston MA 02111-1307, USA; either version 2 of the License, or
;;   (at your option) any later version; incorporated herein by reference.
;;
;; -----------------------------------------------------------------------

; ----------------------------------------------------------------------------
;  VGA splash screen code
; ----------------------------------------------------------------------------

;
; vgadisplayfile:
;	Display a graphical splash screen.
;	The file is already opened on the top of the getc stack.
;
;	Assumes CS == DS == ES.
;
		section .text

vgadisplayfile:
		; This is a cheap and easy way to make sure the screen is
		; cleared in case we were in graphics mode already
		call vgaclearmode
		call vgasetmode
		jnz .error_nz

.graphalready:
		; Load the header.
		mov cx,4+2*2+16*3
		mov di,LSSHeader
.gethdr:
		call getc
		stosb
		loop .gethdr
		jc .error

		; The header WILL be in the first chunk.
		cmp dword [LSSMagic],0x1413f33d	; Magic number
.error_nz:	jne .error

		mov dx,GraphColorMap		; Color map offset
		mov ax,1012h			; Set RGB registers
		xor bx,bx			; First register number
		mov cx,16			; 16 registers
		int 10h

.movecursor:
		mov ax,[GraphYSize]		; Number of pixel rows
		mov dx,[VGAFontSize]
		add ax,dx
		dec ax
		div dl
		xor dx,dx			; Set column to 0
		cmp al,[VidRows]
		jb .rowsok
		mov al,[VidRows]
		dec al
.rowsok:
		mov dh,al
		mov ah,2
		xor bx,bx
		int 10h				; Set cursor below image

		mov cx,[GraphYSize]		; Number of graphics rows
		mov word [VGAPos],0

.drawpixelrow:
		push cx
		mov di,VGARowBuffer
		; Pre-clear the row buffer
		push di
		mov cx,640/4
		xor eax,eax
		rep stosd
		pop di
		push di
		mov cx,[GraphXSize]
		call rledecode			; Decode one row
		pop si
		push es
		mov di,0A000h			; VGA segment
		mov es,di
		mov di,[VGAPos]
		mov bp,640
		call packedpixel2vga
		add word [VGAPos],80
		pop es
		pop cx
		loop .drawpixelrow

.error:
		jmp close			; Tailcall!

;
; rledecode:
;	Decode a pixel row in RLE16 format.
;
; getc stack	-> input
; CX		-> pixel count
; ES:DI		-> output (packed pixel)
;
rledecode:
		xor dx,dx		; DL = last pixel, DH = nybble buffer
.loop:
		call .getnybble
		cmp al,dl
		je .run			; Start of run sequence
		stosb
		mov dl,al
		dec cx
		jnz .loop
.done:
		ret
.run:
		xor bx,bx
		call .getnybble
		or bl,al
		jz .longrun
.dorun:
		push cx
		mov cx,bx
		mov al,dl
		rep stosb
		pop cx
		sub cx,bx
		ja .loop
		jmp short .done
.longrun:
		call .getnybble
		mov bl,al
		call .getnybble
		shl al,4
		or bl,al
		add bx,16
		jmp short .dorun

.getnybble:
		test dh,10h
		jz .low
		and dh,0Fh
		mov al,dh
		ret
.low:
		call getc
		mov dh,al
		shr dh,4
		or dh,10h		; Nybble already read
		and al,0Fh
		ret

;
; packedpixel2vga:
;	Convert packed-pixel to VGA bitplanes
;
; DS:SI -> packed pixel string
; BP    -> pixel count (multiple of 8)
; ES:DI -> output
;
packedpixel2vga:
		mov dx,3C4h	; VGA Sequencer Register select port
		mov al,2	; Sequencer mask
		out dx,al	; Select the sequencer mask
		inc dx		; VGA Sequencer Register data port
		mov al,1
		mov bl,al
.planeloop:
		pusha
		out dx,al
.loop1:
		mov cx,8
.loop2:
		xchg cx,bx
		lodsb
		shr al,cl
		rcl ch,1	; VGA is bigendian.  Sigh.
		xchg cx,bx
		loop .loop2
		mov al,bh
		stosb
		sub bp,byte 8
		ja .loop1
		popa
		inc bl
		shl al,1
		cmp bl,4
		jbe .planeloop
		ret

;
; vgasetmode:
;	Enable VGA graphics, if possible; return ZF=1 on success
;	DS must be set to the base segment; ES is set to DS.
;
vgasetmode:
		push ds
		pop es
		mov al,[UsingVGA]
		cmp al,01h
		je .success		; Nothing to do...
		test al,04h
		jz .notvesa
		; We're in a VESA mode, which means VGA; use VESA call
		; to revert the mode, and then call the conventional
		; mode-setting for good measure...
		mov ax,4F02h
		mov bx,0012h
		int 10h
		jmp .setmode
.notvesa:
		mov ax,1A00h		; Get video card and monitor
		xor bx,bx
		int 10h
		sub bl, 7		; BL=07h and BL=08h OK
		cmp bl, 1
		ja .error		; ZF=0
;		mov bx,TextColorReg
;		mov dx,1009h		; Read color registers
;		int 10h
.setmode:
		mov ax,0012h		; Set mode = 640x480 VGA 16 colors
		int 10h
		mov dx,linear_color
		mov ax,1002h		; Write color registers
		int 10h
		mov [UsingVGA], byte 1

		; Set GXPixCols and GXPixRows
		mov dword [GXPixCols],640+(480 << 16)

		call use_font		; Set graphics font/data
		mov byte [ScrollAttribute], 00h

.success:
		xor ax,ax		; Set ZF
.error:
		ret

;
; vgaclearmode:
;	Disable VGA graphics.  It is not safe to assume any value
;	for DS or ES.
;
vgaclearmode:
		push ds
		push es
		pushad
		mov ax,cs
		mov ds,ax
		mov es,ax
		mov al,[UsingVGA]
		and al,al		; Already in text mode?
		jz .done
		test al,04h
		jz .notvesa
		mov ax,4F02h		; VESA return to normal video mode
		mov bx,0003h
		int 10h
.notvesa:
		mov ax,0003h		; Return to normal video mode
		int 10h
;		mov dx,TextColorReg	; Restore color registers
;		mov ax,1002h
;		int 10h
		mov [UsingVGA], byte 0

		mov byte [ScrollAttribute], 07h
		call use_font		; Restore text font/data
.done:
		popad
		pop es
		pop ds
		ret

;
; vgashowcursor/vgahidecursor:
;	If VGA graphics is enabled, draw a cursor/clear a cursor
;
vgashowcursor:
		pushad
		mov al,'_'
		jmp short vgacursorcommon
vgahidecursor:
		pushad
		mov al,' '
vgacursorcommon:
		cmp [UsingVGA], byte 1
		jne .done
		mov ah,09h
		mov bx,0007h
		mov cx,1
		int 10h
.done:
		popad
		ret


		section .data
		; Map colors to consecutive DAC registers
linear_color	db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0

		; See comboot.doc, INT 22h AX=0017h for the semantics
		; of this byte.
UsingVGA	db 0

		section .bss1
		alignb 4
LSSHeader	equ $
LSSMagic	resd 1			; Magic number
GraphXSize	resw 1			; Width of splash screen file
GraphYSize	resw 1			; Height of splash screen file
GraphColorMap	resb 3*16
VGAPos		resw 1			; Pointer into VGA memory
VGAFilePtr	resw 1			; Pointer into VGAFileBuf
; TextColorReg	resb 17			; VGA color registers for text mode
%if IS_SYSLINUX
VGAFileBuf	resb FILENAME_MAX+2	; Unmangled VGA image name
%else
VGAFileBuf	resb FILENAME_MAX	; Unmangled VGA image name
%endif
VGAFileBufEnd	equ $
VGAFileMBuf	resb FILENAME_MAX	; Mangled VGA image name

; We need a buffer of 640+80 bytes.  At this point, command_line should
; not be in use, so use that buffer.
VGARowBuffer	equ command_line