aboutsummaryrefslogtreecommitdiffstats
path: root/core/graphics.inc
blob: 884776eac8887759a5ed698291fbeb2033227e12 (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
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
;; -----------------------------------------------------------------------
;;
;;   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
		push di
		mov cx,640/4
		xor eax,eax
		rep stosd
		pop di
		mov cx,[GraphXSize]
		call rledecode			; Decode one row
		pop si
		mov di,VGAPlaneBuffer
		push di
		mov bp,640
		call packedpixel2vga
		pop si
		push es
		mov di,0A000h			; VGA segment
		mov es,di
		mov di,[VGAPos]
		call outputvga
		pop es
		add word [VGAPos],640/8
		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)
; DS:DI -> output (four planes)
;
packedpixel2vga:
		xor cx,cx
.planeloop:
		inc cx
		push si
		push bp
.loop1:
		mov bx,8
.loop2:
		lodsb
		shr al,cl
		rcl dl,1		; VGA is bigendian.  Sigh.
		dec bx
		jnz .loop2
		mov [di],dl
		inc di
		sub bp,byte 8
		ja .loop1
		pop bp
		pop si
		cmp cl,3
		jbe .planeloop
		ret

;
; outputvga:
;	Output four subsequent lines of VGA data
;
; DS:SI	-> four planes @ 640/8=80 bytes
; ES:DI	-> pointer into VGA memory
;
outputvga:
		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
		dec ax		; AL <- 1
.loop1:
		out dx,al	; Select the bit plane to write
		push di
		mov cx,640/8
		rep movsb
		pop di
		add ax,ax
		cmp al,8
		jbe .loop1
		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 .bss2
		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

		alignb 4
VGARowBuffer	resb 640+80		; Decompression buffer
VGAPlaneBuffer	resb (640/8)*4		; Plane buffers