fb0214fa457d9dfeaf4463a69f80c6488dd58bf4
[vtuts] / dos1 / c.asm
1 ; Lowest yet: 270
2
3         bits 16
4 %ifdef BOOTSECT
5         org 7c00h
6 %else
7         org 100h
8 %endif
9
10 NUM_POINTS equ 8192
11 SHADOW_OFFS equ 5
12
13 SIERP_PT equ code_end
14 RANDVAL equ code_end + 4
15
16
17 %macro WAIT_VBLANK 0
18         mov dx, 3dah
19 .notblank:
20         in al, dx
21         and al, 8
22         jz .notblank    ; loop while vblank bit is 0 (visible area)
23 %endmacro
24
25
26 start:
27 %ifdef BOOTSECT
28         xor ax, ax
29         mov ds, ax
30         mov es, ax
31         mov ss, ax
32         jmp 00:.setcs
33 .setcs:
34         mov sp, 0
35 %endif
36         mov al, 13h
37         int 10h
38
39         ; "allocate" the next segment for the framebuffer
40         mov ax, es
41         add ax, 1000h
42         mov es, ax
43
44 mainloop:
45         call animate
46
47         ; clear the framebuffer
48         mov al, 128
49         mov cx, 64000
50         xor di, di
51         rep stosb
52
53         ; draw shadow
54         mov si, 5
55         mov byte [setcol + 1], 199      ; shadow color
56         call drawsierp
57         ; draw fractal
58         xor si, si
59         mov byte [setcol + 1], 2        ; fractal color
60         call drawsierp
61
62         ; copy framebuffer to video ram
63         push ds
64         push es
65         ; point ds:si (source) to es:0
66         mov ax, es
67         mov ds, ax
68         xor si, si
69         ; point es:di (dest) to a000:0
70         mov ax, 0a000h
71         mov es, ax
72         xor di, di
73         mov cx, 32000
74         WAIT_VBLANK
75         rep movsw
76         pop es
77         pop ds
78
79 %ifdef BOOTSECT
80         jmp mainloop
81 %else
82         in al, 60h      ; read pending scancode from the keyboard port (if any)
83         dec al          ; ESC is 1, so decrement ...
84         jnz mainloop    ; ... and loop as long as the result was not 0
85
86         ; switch back to text mode (mode 3)
87         mov ax, 3
88         int 10h
89         ; return to dos
90         ret
91 %endif
92
93         ; draw sierpinski triangle
94 drawsierp:
95         ; start from one of the vertices
96         mov ax, [sierp_verts]
97         mov bx, [sierp_verts + 2]
98         mov [SIERP_PT], ax
99         mov [SIERP_PT + 2], bx
100         ; number of iterations in cx
101         mov cx, NUM_POINTS
102 dsloop: ; pick a vertex at random and move half-way there
103         call rand
104         mov bx, 3
105         xor dx, dx
106         div bx  ; dx is now rand % 3
107         ; put the vertex address in bx
108         mov bx, sierp_verts
109         shl dx, 2
110         add bx, dx
111         ; add to SIERP_PT and divide by 2 to move half-way there
112         mov ax, [bx]
113         add ax, [SIERP_PT]
114         shr ax, 1
115         mov [SIERP_PT], ax      ; store the resulting X back to [SIERP_PT]
116         mov di, ax              ; save X coordinate in di
117         mov ax, [bx + 2]
118         add ax, [SIERP_PT + 2]
119         shr ax, 1
120         mov [SIERP_PT + 2], ax  ; store the reuslting Y back to [SIERP_PT + 2]
121         add ax, si      ; add offset
122         mov bx, ax
123         shl ax, 8
124         shl bx, 6
125         add bx, ax              ; bx = Y * 320
126 setcol: mov al, 1
127         mov byte [es:bx + di], al
128
129         dec cx
130         jnz dsloop
131         ret
132
133 sierp_verts:
134         dw 160, 40
135         dw 240, 160
136         dw 80, 160
137 sierp_vel:
138         dw 1, 1
139         dw -1, 1
140         dw -1, -1
141 bounds  dw 200 - SHADOW_OFFS
142         dw 320 - SHADOW_OFFS
143
144
145 animate:
146         mov cx, 3
147         mov di, sierp_verts
148         mov si, sierp_vel
149 .loop:
150         mov ebx, 2
151 .xyloop:
152         mov ax, [di]            ; grab vertex X
153         add ax, [si]            ; add velocity X
154         jl .xout
155         cmp ax, [ebx * 2 + bounds - 2]
156         jge .xout
157         jmp .skip_xflip
158 .xout:
159         sub ax, [si]            ; revert to previous X
160         neg word [si]           ; negate velocity X
161 .skip_xflip:
162         mov [di], ax            ; update vertex X
163
164         ; to do the same for Y increment edi and esi by 2
165         add di, 2
166         add si, 2
167         dec bx
168         jnz .xyloop
169
170         dec cx
171         jnz .loop
172         ret
173
174         ; random number generator
175 rand:
176         mov ax, [randval]
177         mov bx, ax
178         shr bx, 7
179         xor ax, bx
180         mov bx, ax
181         shl bx, 9
182         xor ax, bx
183         mov [randval], ax
184         ret
185 ;       mov eax, [RANDVAL]
186 ;       mul dword [randmul]
187 ;       add eax, 12345
188 ;       and eax, 0x7fffffff
189 ;       mov [RANDVAL], eax
190 ;       shr eax, 16
191 ;       ret
192
193 ;randmul dd 1103515245
194 randval dw 0ace1h
195 code_end:
196
197 %ifdef BOOTSECT
198         times 510-($-$$) db 0
199         db 0x55,0xaa
200 %endif
201 ; vi:ft=nasm: