This repository has been archived by the owner on Dec 24, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 91
/
Copy pathL31-1.ASM
326 lines (326 loc) · 7.88 KB
/
L31-1.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
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
; Program to demonstrate pixel drawing in 320x400 256-color
; mode on the VGA. Draws 8 lines to form an octagon, a pixel
; at a time. Draws 8 octagons in all, one on top of the other,
; each in a different color set. Although it's not used, a
; pixel read function is also provided.
;
VGA_SEGMENT equ 0a000h
SC_INDEX equ 3c4h ;Sequence Controller Index register
GC_INDEX equ 3ceh ;Graphics Controller Index register
CRTC_INDEX equ 3d4h ;CRT Controller Index register
MAP_MASK equ 2 ;Map Mask register index in SC
MEMORY_MODE equ 4 ;Memory Mode register index in SC
MAX_SCAN_LINE equ 9 ;Maximum Scan Line reg index in CRTC
START_ADDRESS_HIGH equ 0ch ;Start Address High reg index in CRTC
UNDERLINE equ 14h ;Underline Location reg index in CRTC
MODE_CONTROL equ 17h ;Mode Control register index in CRTC
READ_MAP equ 4 ;Read Map register index in GC
GRAPHICS_MODE equ 5 ;Graphics Mode register index in GC
MISCELLANEOUS equ 6 ;Miscellaneous register index in GC
SCREEN_WIDTH equ 320 ;# of pixels across screen
SCREEN_HEIGHT equ 400 ;# of scan lines on screen
WORD_OUTS_OK equ 1 ;set to 0 to assemble for
; computers that can't handle
; word outs to indexed VGA registers
;
stack segment para stack 'STACK'
db 512 dup (?)
stack ends
;
Data segment word 'DATA'
;
BaseColor db 0
;
; Structure used to control drawing of a line.
;
LineControl struc
StartX dw ?
StartY dw ?
LineXInc dw ?
LineYInc dw ?
BaseLength dw ?
LineColor db ?
LineControl ends
;
; List of descriptors for lines to draw.
;
LineList label LineControl
LineControl <130,110,1,0,60,0>
LineControl <190,110,1,1,60,1>
LineControl <250,170,0,1,60,2>
LineControl <250,230,-1,1,60,3>
LineControl <190,290,-1,0,60,4>
LineControl <130,290,-1,-1,60,5>
LineControl <70,230,0,-1,60,6>
LineControl <70,170,1,-1,60,7>
LineControl <-1,0,0,0,0,0>
Data ends
;
; Macro to output a word value to a port.
;
OUT_WORD macro
if WORD_OUTS_OK
out dx,ax
else
out dx,al
inc dx
xchg ah,al
out dx,al
dec dx
xchg ah,al
endif
endm
;
; Macro to output a constant value to an indexed VGA register.
;
CONSTANT_TO_INDEXED_REGISTER macro ADDRESS, INDEX, VALUE
mov dx,ADDRESS
mov ax,(VALUE shl 8) + INDEX
OUT_WORD
endm
;
Code segment
assume cs:Code, ds:Data
Start proc near
mov ax,Data
mov ds,ax
;
; Set 320x400 256-color mode.
;
call Set320By400Mode
;
; We're in 320x400 256-color mode. Draw each line in turn.
;
ColorLoop:
mov si,offset LineList ;point to the start of the
; line descriptor list
LineLoop:
mov cx,[si+StartX] ;set the initial X coordinate
cmp cx,-1
jz LinesDone ;a descriptor with a -1 X
; coordinate marks the end
; of the list
mov dx,[si+StartY] ;set the initial Y coordinate,
mov bl,[si+LineColor] ; line color,
mov bp,[si+BaseLength] ; and pixel count
add bl,[BaseColor] ;adjust the line color according
; to BaseColor
PixelLoop:
push cx ;save the coordinates
push dx
call WritePixel ;draw this pixel
pop dx ;retrieve the coordinates
pop cx
add cx,[si+LineXInc];set the coordinates of the
add dx,[si+LineYInc]; next point of the line
dec bp ;any more points?
jnz PixelLoop ;yes, draw the next
add si,size LineControl ;point to the next line descriptor
jmp LineLoop ; and draw the next line
LinesDone:
call GetNextKey ;wait for a key, then
inc [BaseColor] ; bump the color selection and
cmp [BaseColor],8 ; see if we're done
jb ColorLoop ;not done yet
;
; Wait for a key and return to text mode and end when
; one is pressed.
;
call GetNextKey
mov ax,0003h
int 10h ;text mode
mov ah,4ch
int 21h ;done
;
Start endp
;
; Sets up 320x400 256-color modes.
;
; Input: none
;
; Output: none
;
Set320By400Mode proc near
;
; First, go to normal 320x200 256-color mode, which is really a
; 320x400 256-color mode with each line scanned twice.
;
mov ax,0013h ;AH = 0 means mode set, AL = 13h selects
; 256-color graphics mode
int 10h ;BIOS video interrupt
;
; Change CPU addressing of video memory to linear (not odd/even,
; chain, or chain 4), to allow us to access all 256K of display
; memory. When this is done, VGA memory will look just like memory
; in modes 10h and 12h, except that each byte of display memory will
; control one 256-color pixel, with 4 adjacent pixels at any given
; address, one pixel per plane.
;
mov dx,SC_INDEX
mov al,MEMORY_MODE
out dx,al
inc dx
in al,dx
and al,not 08h ;turn off chain 4
or al,04h ;turn off odd/even
out dx,al
mov dx,GC_INDEX
mov al,GRAPHICS_MODE
out dx,al
inc dx
in al,dx
and al,not 10h ;turn off odd/even
out dx,al
dec dx
mov al,MISCELLANEOUS
out dx,al
inc dx
in al,dx
and al,not 02h ;turn off chain
out dx,al
;
; Now clear the whole screen, since the mode 13h mode set only
; cleared 64K out of the 256K of display memory. Do this before
; we switch the CRTC out of mode 13h, so we don't see garbage
; on the screen when we make the switch.
;
CONSTANT_TO_INDEXED_REGISTER SC_INDEX,MAP_MASK,0fh
;enable writes to all planes, so
; we can clear 4 pixels at a time
mov ax,VGA_SEGMENT
mov es,ax
sub di,di
mov ax,di
mov cx,8000h ;# of words in 64K
cld
rep stosw ;clear all of display memory
;
; Tweak the mode to 320x400 256-color mode by not scanning each
; line twice.
;
mov dx,CRTC_INDEX
IF 1 ; the following code can be disabled to test memory access in 320x200 mode -JP
mov al,MAX_SCAN_LINE
out dx,al
inc dx
in al,dx
and al,not 1fh ;set maximum scan line = 0
out dx,al
dec dx
ENDIF
;
; Change CRTC scanning from doubleword mode to byte mode, allowing
; the CRTC to scan more than 64K of video data.
;
mov al,UNDERLINE
out dx,al
inc dx
in al,dx
and al,not 40h ;turn off doubleword
out dx,al
dec dx
mov al,MODE_CONTROL
out dx,al
inc dx
in al,dx
or al,40h ;turn on the byte mode bit, so memory is
; scanned for video data in a purely
; linear way, just as in modes 10h and 12h
out dx,al
ret
Set320By400Mode endp
;
; Draws a pixel in the specified color at the specified
; location in 320x400 256-color mode.
;
; Input:
; CX = X coordinate of pixel
; DX = Y coordinate of pixel
; BL = pixel color
;
; Output: none
;
; Registers altered: AX, CX, DX, DI, ES
;
WritePixel proc near
mov ax,VGA_SEGMENT
mov es,ax ;point to display memory
mov ax,SCREEN_WIDTH/4
;there are 4 pixels at each address, so
; each 320-pixel row is 80 bytes wide
; in each plane
mul dx ;point to start of desired row
push cx ;set aside the X coordinate
shr cx,1 ;there are 4 pixels at each address
shr cx,1 ; so divide the X coordinate by 4
add ax,cx ;point to the pixel's address
mov di,ax
pop cx ;get back the X coordinate
and cl,3 ;get the plane # of the pixel
mov ah,1
shl ah,cl ;set the bit corresponding to the plane
; the pixel is in
mov al,MAP_MASK
mov dx,SC_INDEX
OUT_WORD ;set to write to the proper plane for
; the pixel
mov es:[di],bl ;draw the pixel
ret
WritePixel endp
;
; Reads the color of the pixel at the specified location in 320x400
; 256-color mode.
;
; Input:
; CX = X coordinate of pixel to read
; DX = Y coordinate of pixel to read
;
; Output:
; AL = pixel color
;
; Registers altered: AX, CX, DX, SI, ES
;
ReadPixel proc near
mov ax,VGA_SEGMENT
mov es,ax ;point to display memory
mov ax,SCREEN_WIDTH/4
;there are 4 pixels at each address, so
; each 320-pixel row is 80 bytes wide
; in each plane
mul dx ;point to start of desired row
push cx ;set aside the X coordinate
shr cx,1 ;there are 4 pixels at each address
shr cx,1 ; so divide the X coordinate by 4
add ax,cx ;point to the pixel's address
mov si,ax
pop ax ;get back the X coordinate
and al,3 ;get the plane # of the pixel
mov ah,al
mov al,READ_MAP
mov dx,GC_INDEX
OUT_WORD ;set to read from the proper plane for
; the pixel
lods byte ptr es:[si];read the pixel
ret
ReadPixel endp
;
; Waits for the next key and returns it in AX.
;
; Input: none
;
; Output:
; AX = full 16-bit code for key pressed
;
GetNextKey proc near
WaitKey:
mov ah,1
int 16h
jz WaitKey ;wait for a key to become available
sub ah,ah
int 16h ;read the key
ret
GetNextKey endp
;
Code ends
;
end Start