-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathVIDEO.ASM
284 lines (237 loc) · 6.89 KB
/
VIDEO.ASM
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
; ==============================================================================
; Generic video functionality.
; ==============================================================================
.MODEL large ; multiple data segments and multiple code segments
.STACK 1024
; --- INCLUDES -----------------------------------------------------------------
INCLUDE video.inc
; --- MACROS AND CONSTANTS -----------------------------------------------------
; VGA DAC ports
PORT_VGA_DAC_READ equ 03c7h ; write
PORT_VGA_DAC_WRITE equ 03c8h ; write
PORT_VGA_DAC_DATA equ 03c9h ; read/write
FADESTEPS equ 32
FADESTEPSB equ 5 ; 5 bits
; --- DATA SEGMENT -------------------------------------------------------------
.FARDATA?
; The following buffer is used to keep 16-bit fixed point palette values during fading
paletteFader dw 2 * 768 dup(?)
paletteStepsC dw ?
; --- CODE SEGMENT -------------------------------------------------------------
.CODE
; Set the video mode and returns the previous mode in AL.
setVideoMode PROC FAR
push bp ; save dynamic link
mov bp, sp ; update bp
push bx
mov ah, 0fh ; get current video mode in al
int 10h
mov bx, ax
mov ax, [bp + 6][0] ; get requested mode
xor ah, ah ; function 0
int 10h
mov ax, bx
pop bx
pop bp
retf 2 ; return
setVideoMode ENDP
; Immediately set a new VGA palette
;
; Arguments are SEGMENT and OFFSET of destination palette (points to 768 bytes)
setPalette PROC FAR
push bp
mov bp, sp
push cx
push dx
push si
push ds
mov ax, [bp + 6][2] ; get data segment argument
mov ds, ax ; and set it as DS
mov ax, [bp + 6][0] ; get the offset argument
mov si, ax ; and set it as source index
cli ; disable interrupts
mov dx, PORT_VGA_DAC_WRITE
xor ax, ax
out dx, al ; start at color 0
mov dx, PORT_VGA_DAC_DATA
mov cx, 768 ; we need to write 768 channel color bytes
@@: ; local loop label
lodsb ; load next channel color byte into al
out dx, al ; write the byte in al to DAC DATA port
dec cx ; decrement loop counter
jnz @B ; loop if more todo (@B is the first @@ label before this point)
sti ; enable interrupts
pop ds
pop si
pop dx
pop cx
pop bp
retf 4
setPalette ENDP
; Call this function to start a palette fade,
; starting with the currently active palette
; (uses paletteFader and paletteSteps)
; (defaults to 32 steps)
; Arguments are SEGMENT and OFFSET of destination palette (points to 768 bytes)
paletteInitFade PROC FAR
ASSUME ds:@FARDATA?, es:@FARDATA?
push bp
mov bp, sp
push ax
push bx
push cx
push dx
push si
push di
push ds
push es
cld
; setup segment registers
mov ax, [bp + 6][2] ; get data segment
mov ds, ax
; one palette color uses 6 bits, these are shifted 9 left to get
; a 15 bit fixed point number with an extra sign bit (= 16 bits total)
; paletteFader contains 16 bit palette RGB values and steps used for
; fading (interleaved)
; get the active palette into paletteFader (shifted left 9 bits)
; and create the array of delta (step values) in 16-bit FP arithm.
mov ax, @FARDATA?
mov es, ax
mov ax, FADESTEPS ; initialize steps
mov es:[paletteStepsC], ax
mov si, [bp + 6][0] ; get the offset of target
mov di, offset paletteFader
xor ch, ch ; 256 RGB colors (uses wrapping)
cli ; disable interrupts
xor ax, ax
mov dx, PORT_VGA_DAC_READ
out dx, al ; set color index 0
mov dx, PORT_VGA_DAC_DATA
@@:
; RED
lodsb ; al := ds:[si] (load dest value in al)
mov bl, al ; put it in bl
in al, dx ; read active color in al
sub bl, al ; get difference (can be negative)
mov cl, 9 ; prepare for 9 bit shift left
sal bx, cl ; make 16 bit fixed point
shl ax, cl ; make 16 bit fixed point
mov cl, FADESTEPSB ; prepare for step division
sar bx, cl ; steps (div by number of steps)
stosw ; store active color (16 bit)
mov ax, bx
stosw ; store step value (16 bit)
; GREEN
lodsb ; al := ds:[si] (load dest value in al)
mov bl, al ; put it in bl
in al, dx ; read active color in al
sub bl, al ; get difference (can be negative)
mov cl, 9 ; prepare for 9 bit shift left
sal bx, cl ; make 16 bit fixed point
shl ax, cl ; make 16 bit fixed point
mov cl, FADESTEPSB ; prepare for step division
sar bx, cl ; steps (div by number of steps)
stosw ; store active color (16 bit)
mov ax, bx
stosw ; store step value (16 bit)
; BLUE
lodsb ; al := ds:[si] (load dest value in al)
mov bl, al ; put it in bl
in al, dx ; read active color in al
sub bl, al ; get difference (can be negative)
mov cl, 9 ; prepare for 9 bit shift left
sal bx, cl ; make 16 bit fixed point
shl ax, cl ; make 16 bit fixed point
mov cl, FADESTEPSB ; prepare for step division
sar bx, cl ; steps (div by number of steps)
stosw ; store active color (16 bit)
mov ax, bx
stosw ; store step value (16 bit)
inc ch
jnz @B
sti ; enable interrupts
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
pop bp ; restore original BP
retf 4 ; return and free 2 args
paletteInitFade ENDP
; Perform the next palette fading step
; More steps are needed when return value (AX) is non-zero
paletteNextFade PROC FAR
ASSUME ds:@FARDATA?, es:@FARDATA?
push bp
push bx
push cx
push dx
push di
push ds
push es
cld
mov ax, @FARDATA?
mov ds, ax
mov es, ax
cli ; disable interrupts
; add deltas and set new palette
xor ax, ax
mov dx, PORT_VGA_DAC_WRITE
out dx, al ; start at index 0
mov si, offset paletteFader
mov di, si
xor ch, ch ; 256 color indexes
mov dx, PORT_VGA_DAC_DATA
mov cl, 9
@@:
; RED
lodsw ; load active color in ax
mov bx, ax
lodsw ; load step in ax
add ax, bx ; add active color and step
stosw ; store new active color
add di, 2
add ax, 256 ; rounding (9 bits fraction, so add 0.5 in decimals = 2^8 = 256)
shr ax, cl ; convert 16 bit FP to 6 bit int
out dx, al ; write active color
; GREEN
lodsw ; load active color in ax
mov bx, ax
lodsw ; load step in ax
add ax, bx ; add active color and step
stosw ; store new active color
add di, 2
add ax, 256 ; rounding
shr ax, cl ; convert 16 bit FP to 6 bit int
out dx, al ; write active color
; BLUE
lodsw ; load active color in ax
mov bx, ax
lodsw ; load step in ax
add ax, bx ; add active color and step
stosw ; store new active color
add di, 2
add ax, 256 ; rounding
shr ax, cl ; convert 16 bit FP to 6 bit int
out dx, al ; write active color
inc ch
jnz @B
sti ; enable interrupts
; one step less todo
mov ax, [paletteStepsC]
dec ax
mov [paletteStepsC], ax
pop es
pop ds
pop di
pop dx
pop cx
pop bx
pop bp
retf 0
paletteNextFade ENDP
; _------------------------------- END OF CODE ---------------------------------
END