attempt to blur up
[bootsplash] / bootsplash.asm
1         org 7c00h
2         bits 16
3
4 stacktop equ 7b00h
5 boot_driveno equ 7b00h  ; 1 byte
6 stage2_size equ stage2_end - stage2_start
7
8 spawn_rate equ 5
9 framebuf equ 40000h
10
11 start:
12         xor ax, ax
13         mov ds, ax
14         mov es, ax
15         mov ss, ax
16         mov gs, ax
17         mov fs, ax
18
19         mov sp, stacktop
20         mov [boot_driveno], dl
21
22         ; load the rest of the code at 7e00
23         xor ax, ax
24         mov es, ax
25         mov bx, stage2_start
26         mov ah, 2               ; read sectors LBA call
27         mov al, (stage2_size + 511) / 512  ; num sectors
28         mov cx, 2               ; ch: cylinder, cl: sector
29         xor dx, dx              ; dh: head
30         mov dl, [boot_driveno]
31         int 13h
32         jnc stage2_start        ; loaded successfully, jump to it
33
34         ; failed to load second sector
35         mov ax, str_load_fail
36         call printstr
37 .hang:  cli
38         hlt
39         jmp .hang
40
41         ; expects string ptr in ax
42 printstr:
43         mov si, ax
44 .loop:  mov al, [si]
45         inc si
46         test al, al
47         jz .done
48         mov ah, 0eh
49         mov bx, 7
50         int 10h
51         jmp .loop
52 .done:  ret
53
54 str_load_fail db "Failed to load second stage!",0
55 str_booting db "Booting ...",0
56
57
58         times 510-($-$$) db 0
59         dw 0xaa55
60
61         ; start of the second stage
62 stage2_start:
63         call splash
64
65         xor ax, ax
66         mov es, ax
67         mov ds, ax
68
69         mov ax, str_booting
70         call printstr
71
72         cli
73 .hang:  hlt
74         jmp .hang
75
76         ; splash screen effect
77 splash:
78         mov ax, 13h
79         int 10h
80
81         ; setup ramdac colormap
82         mov ax, pal
83         shr ax, 4
84         mov ds, ax
85         xor ax, ax
86         mov dx, 3c8h
87         out dx, al
88         inc dx
89         xor bx, bx
90 .cmap_loop:
91         mov al, [bx]
92         shr al, 2
93         out dx, al
94         inc bx
95         cmp bx, 768     ; 256 * 3
96         jnz .cmap_loop
97
98         ; decompress image
99         mov ax, img
100         shr ax, 4
101         mov es, ax
102         xor di, di
103         mov ax, imgrle
104         shr ax, 4
105         mov ds, ax
106         xor si, si
107         mov cx, 64000
108         call decode_rle
109
110         ; precalculate spawn points
111         mov ax, es
112         mov ds, ax      ; decompressed image -> ds:bx
113         xor bx, bx
114         mov ax, spawn_pos
115         shr ax, 4
116         mov es, ax      ; spawn_pos table segment -> es:dx
117         xor edx, edx
118
119         mov cx, 64000
120 .calcspawn_loop:
121         mov al, [bx]
122         test al, 0x80
123         jz .notspawn
124         mov [es:edx * 2], bx
125         inc edx
126 .notspawn:
127         inc bx
128         dec cx
129         jnz .calcspawn_loop
130         ; update num_spawn_pos
131         xor ax, ax
132         mov ds, ax
133         mov [num_spawn_pos], edx
134
135         mov ax, framebuf >> 4
136         mov fs, ax              ; fs will point to the off-screen framebuffer
137
138         ; effect main loop
139 .mainloop:
140         mov cx, spawn_rate
141 .spawn: call rand
142         xor edx, edx
143         div dword [num_spawn_pos]       ; edx <- rand % num_spawn_pos
144         mov bx, [es:edx * 2]            ; grab one of the spawn positions
145         mov byte [fs:bx], 0xff          ; plot a pixel there
146         dec cx
147         jnz .spawn
148
149         ; blur the screen upwards
150         mov ax, fs
151         mov ds, ax      ; let's use ds for this to avoid long instructions
152         xor bx, bx      ; use: pointer
153         xor ax, ax      ; use: pixel accum
154         xor dx, dx      ; use: second pixel
155 .blurloop:
156         mov al, [bx]
157         mov dl, [bx + 320]
158         add ax, dx
159         shr ax, 1
160         mov [bx], al
161         inc bx
162         cmp bx, 64000 - 320
163         jnz .blurloop
164
165
166         ; wait until the start of vblank
167 .waitvblank:
168         mov dx, 3dah
169         in al, dx
170         and al, 8
171         jz .waitvblank
172
173         ; copy to screen
174         push es
175         mov ax, 0a000h
176         mov es, ax
177         xor di, di
178         mov ax, fs
179         mov ds, ax
180         xor si, si
181         mov ecx, 16000
182         rep movsd
183         pop es
184         xor ax, ax
185         mov ds, ax
186
187         ; check for keypress
188         in al, 64h
189         and al, 1
190         jz .mainloop
191         in al, 60h
192
193 .end:   mov ax, 3
194         int 10h
195         ret
196
197         ; decode RLE from ds:si to es:di, cx: number of decoded bytes (0 means 65536)
198         ; - high bit set for the repetition count, followed by a value byte to
199         ;   be repeated N times
200         ; - high bit not set for raw data that should be copied directly
201 decode_rle:
202         mov al, [si]
203         inc si
204         mov bl, 1       ; default to "copy once" for raw values
205         test al, 0x80   ; test the high bit to see if it's a count or a raw value
206         jz .copy
207         ; it's a count, clear the high bit, and read the next byte for the value
208         and al, 0x7f
209         mov bl, al
210         mov al, [si]
211         inc si
212 .copy:  mov [es:di], al
213         inc di
214         dec cx          ; decrement decoded bytes counter
215         jz .end         ; as soon as it reaches 0, bail
216         dec bl
217         jnz .copy
218         jmp decode_rle
219 .end:   ret
220         
221
222 waitkey:
223         in al, 64h
224         test al, 1
225         jz waitkey
226         in al, 60h
227         ret
228
229 rand:
230         mov eax, [randval]
231         mul dword [randmul]
232         add eax, 12345
233         and eax, 0x7fffffff
234         mov [randval], eax
235         shr eax, 16
236         ret
237
238 randmul dd 1103515245
239 randval dd 0ace1h
240
241
242         ; data
243 num_spawn_pos dd 0
244         align 16
245 spawn_pos:
246 imgrle: incbin "nuclear.rle"
247         align 16
248 img:
249 pal:    incbin "fire.pal"
250
251 stage2_end:
252
253 ; vi:set ft=nasm: