now it plays properly, will fix up some leftovers later
[bootcard] / bootcard.asm
1 ; ---- boot me! ----
2 ; nasm -f bin -o bootcard.img bootcard.asm
3 ; cat bootcard.img >/dev/<usbstick>
4
5 %define MIDI
6
7         bits 16
8 %ifdef DOS
9         org 100h
10         jmp start
11 %else
12         org 7c00h
13 %endif
14
15 barh    equ 4
16 nbars   equ 11
17 barstart equ 200 - (nbars+1) * barh
18
19 %ifdef DOS
20 nticks  dd 0
21 tmoffs  dd 0
22 musptr  dd 0
23 frame   dd 0
24 pnote   dd 0
25 fval    dd 0
26 cmap    dd 0
27
28 saved_tintr_offs dw 0
29 saved_tintr_seg dw 0
30 %else
31 nticks  equ 7e00h
32 tmoffs  equ 7e04h
33 musptr  equ 7e08h
34 frame   equ 7e0ch
35 pnote   equ 7e18h
36 fval    equ 7e10h
37 cmap    equ 7e14h
38 %endif
39
40 %macro setcur 2
41         mov dx, %1 | (%2 << 8)
42         xor bx, bx
43         mov ah, 2
44         int 10h
45 %endmacro
46 %macro spkon 0
47         in al, 61h
48         or al, 3
49         out 61h, al
50 %endmacro
51 %macro spkoff 0
52         in al, 61h
53         and al, 0fch
54         out 61h, al
55 %endmacro
56 %macro stimer 2
57         mov al, (%1 << 6) | 36h
58         out 43h, al
59         mov ax, %2
60         out 40h + %1, al
61         mov al, ah
62         out 40h + %1, al
63 %endmacro
64
65 start:
66 %ifndef DOS
67         xor ax, ax
68         mov ds, ax
69         mov es, ax
70         mov ss, ax
71         mov sp, 7c00h
72
73         mov di, nticks
74         mov cx, 16
75         rep stosw
76
77         cli
78         mov word [32], tintr
79         mov [34], ax
80 %else
81         ; for DOS save the previous interrupt handler to restore at the end
82         xor ax, ax
83         mov es, ax
84         mov ax, [es:32]
85         mov [saved_tintr_offs], ax
86         mov ax, [es:34]
87         mov [saved_tintr_seg], ax
88
89         cli
90         mov ax, ds
91         mov word [es:32], tintr
92         mov [es:34], ax
93 %endif
94
95         stimer 0, 5966
96 %ifdef MIDI
97         call resetmidi
98         mov ax, 0c0h    ; change program on chan 0
99         call sendmidi
100         mov ax, 19      ; church organ
101         call sendmidi
102 %endif
103         mov ax, 13h
104         int 10h
105         push 0a000h
106         pop es
107
108         
109         mov al, 16
110         mov di, barstart * 320
111         mov bx, nbars
112 .drawbars:
113         mov cx, barh * 320
114         rep stosb
115         inc al
116         dec bx
117         jnz .drawbars
118
119         setcur 12, 16
120         mov si, str1
121         call textout
122
123         sti
124
125 mainloop:
126         mov dx, 3dah
127 .invb:  in al, dx
128         and al, 8
129         jnz .invb
130 .novb:  in al, dx
131         and al, 8
132         jz .novb
133
134 drawbg:
135         mov bx, 200
136         xor di, di
137 .fillgrad:
138         mov ax, bx
139         mov ah, al
140         mov cx, 2400 ; 15 lines
141         rep stosw
142         inc bx
143         cmp bx, 208
144         jnz .fillgrad
145
146         ; mountains
147         mov cx, 320
148         mov bp, sp
149 .mnt:   mov [bp - 2], cx
150         fild word [bp - 2]
151         fidiv word [w30]
152         fsincos
153         fiadd word [w5]
154         fimul word [w5]
155         fistp word [bp - 2]
156         fstp st0
157         mov bx, [bp - 2]
158         add bx, 84
159         imul bx, bx, 320
160         add bx, cx
161 .mntcol:
162         mov byte [es:bx], 0
163         add bx, 320
164         cmp bx, 128 * 320
165         jb .mntcol
166
167         dec cx
168         jnz .mnt
169
170         ; upd colormap
171         mov dx, 3c8h
172         mov al, 16
173         out dx, al
174         inc dx
175         mov si, cmap
176         mov cx, 16 * 3
177         rep outsb
178
179 %ifdef DOS
180         in al, 60h
181         dec al
182         jnz mainloop
183
184         mov ax, 3
185         int 10h
186
187         cli
188         xor ax, ax
189         mov es, ax
190         mov ax, [saved_tintr_offs]
191         mov word [es:32], ax
192         mov ax, [saved_tintr_seg]
193         mov [es:34], ax
194         stimer 0, 0xffff
195         sti
196         ret
197 %else
198         jmp mainloop
199 %endif
200
201 textout:
202         mov al, [si]
203         and al, al
204         jz textout_done
205         mov ah, 0eh
206         mov bx, 82
207         int 10h
208         inc si
209         jmp textout
210 textout_done:
211         ret
212
213 %ifdef MIDI
214 note_on:
215         mov [pnote], ax
216         mov ax, 90h     ; note-on command for channel 0
217         call sendmidi
218         mov ax, [pnote]
219         call sendmidi
220         mov ax, 127
221         jmp sendmidi
222
223 note_off:
224         mov ax, [pnote]
225         test ax, ax
226         jz textout_done
227         mov ax, 80h     ; note-off command for channel 0
228         call sendmidi
229         mov ax, [pnote]
230         call sendmidi
231         mov ax, 64
232         jmp sendmidi
233
234 all_notes_off:
235         mov ax, 0b0h    ; channel mode message for channel 0...
236         call sendmidi
237         mov ax, 7bh     ; all notes off
238         call sendmidi
239         xor ax, ax
240         mov [pnote], ax
241         jmp sendmidi
242
243 waitmidi:
244         mov dx, 331h
245 .wait:  in al, dx       ; read status port
246         test al, 40h    ; test output-ready bit (0: ready)
247         jnz .wait
248         ret
249
250 sendmidi:
251         push dx
252         push ax
253         call waitmidi
254         pop ax
255         dec dx
256         out dx, al
257         pop dx
258         ret
259
260 resetmidi:
261         call waitmidi
262         mov ax, 0ffh    ; reset command
263         out dx, al
264         call waitmidi
265         mov ax, 3fh     ; enter UART mode
266         out dx, al
267         ret
268 %endif  ; MIDI
269
270 tintr:
271         pusha
272         mov ax, [nticks]
273         inc ax
274         mov [nticks], ax
275
276         mov bx, [musptr]
277 %ifdef MIDI
278         cmp bx, 22*2
279 %else
280         cmp bx, 22*3
281 %endif
282         jnz .skiploop
283         xor bx, bx
284         mov [tmoffs], ax
285 .skiploop:
286         xor cx, cx
287         mov cl, [music + bx]
288         shl cx, 4
289         sub ax, [tmoffs]
290         cmp ax, cx
291         jb .end
292
293 %ifdef MIDI
294         mov al, [music + 1 + bx]
295         xor ah, ah
296         add bx, 2
297 %else
298         mov ax, [music + 1 + bx]
299         add bx, 3
300 %endif
301         mov [musptr], bx
302         test ax, ax
303         jz .off
304
305         mov bx, ax
306 %ifdef MIDI
307         sub bx, 43
308 %else
309         shr bx, 9
310         sub bx, 13
311 %endif
312         imul bx, bx, 3
313         mov byte [cmap + bx], 3fh
314         mov word [cmap + bx + 1], 2f2fh
315
316 %ifdef MIDI
317         push ax
318         ;call note_off
319         call all_notes_off
320         pop ax
321         call note_on
322 %else
323         mov bx, ax
324         stimer 2, bx
325         spkon
326 %endif
327         jmp .end
328
329 .off:
330 %ifdef MIDI
331         call all_notes_off
332 %else
333         spkoff
334 %endif
335
336 .end:   test word [nticks], 1
337         jnz .eoi
338         mov cx, 16 * 3
339         mov si, cmap
340 .fadecol:
341         lodsb
342         test al, al
343         jz .skipdec
344         dec al
345         mov [si-1], al
346 .skipdec:
347         dec cx
348         jnz .fadecol
349         
350 .eoi:   mov al, 20h
351         out 20h, al
352         popa
353         iret
354
355 str1:   db 'Michael ',3,' Athena',0
356
357 %ifdef MIDI
358 G2      equ 43
359 C3      equ 48
360 D3      equ 50
361 B2      equ 47
362 F3      equ 53
363 E3      equ 52
364 %else
365 G2      equ 12175
366 C3      equ 9121
367 D3      equ 8126
368 B2      equ 9664
369 F3      equ 6833
370 E3      equ 7239
371 %endif
372
373
374 %ifdef MIDI
375 %macro EV 2
376         db %1 >> 4
377         db %2
378 %endmacro
379 %else
380 %macro EV 2
381         db %1 >> 4
382         dw %2
383 %endmacro
384 %endif
385
386 music:  EV     0,  G2
387         EV   160,  C3
388         EV   272,  C3
389         EV   320,  C3
390         EV   560,  0
391         EV   640,  G2
392         EV   800,  D3
393         EV   912,  B2
394         EV   960,  C3
395         EV  1200,  0
396         EV  1280,  G2
397         EV  1440,  C3
398         EV  1552,  F3
399         EV  1600,  F3
400         EV  1760,  E3
401         EV  1872,  D3
402         EV  1920,  C3
403         EV  2080,  B2
404         EV  2192,  C3
405         EV  2240,  D3
406         EV  2560,  0
407         EV  2720,  0
408
409 w5:     dw 5
410 w30:    dw 30
411
412 %ifndef DOS
413 %ifndef MIDI
414         times 446-($-$$) db 0
415         dd 00212080h
416         dd 0820280ch
417         dd 00000800h
418         dd 0001f800h
419 %endif
420
421         times 510-($-$$) db 0
422         dw 0aa55h
423 %endif
424 ; vi:ft=nasm ts=8 sts=8 sw=8: