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