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