RLE blitter, plus RLE encoding and decoding tools
[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 start:
9         xor ax, ax
10         mov ds, ax
11         mov es, ax
12         mov ss, ax
13         mov gs, ax
14         mov fs, ax
15
16         mov sp, stacktop
17         mov [boot_driveno], dl
18
19         ; load the rest of the code at 7e00
20         xor ax, ax
21         mov es, ax
22         mov bx, stage2_start
23         mov ah, 2               ; read sectors LBA call
24         mov al, (stage2_size + 511) / 512  ; num sectors
25         mov cx, 2               ; ch: cylinder, cl: sector
26         xor dx, dx              ; dh: head
27         mov dl, [boot_driveno]
28         int 13h
29         jnc stage2_start        ; loaded successfully, jump to it
30
31         ; failed to load second sector
32         mov ax, str_load_fail
33         call printstr
34 .hang:  cli
35         hlt
36         jmp .hang
37
38         ; expects string ptr in ax
39 printstr:
40         mov si, ax
41 .loop:  mov al, [si]
42         inc si
43         test al, al
44         jz .done
45         mov ah, 0eh
46         mov bx, 7
47         int 10h
48         jmp .loop
49 .done:  ret
50
51 str_load_fail db "Failed to load second stage!",0
52 str_booting db "Booting ...",0
53
54
55         times 510-($-$$) db 0
56         dw 0xaa55
57
58         ; start of the second stage
59 stage2_start:
60         call splash
61
62         xor ax, ax
63         mov es, ax
64         mov ds, ax
65
66         mov ax, str_booting
67         call printstr
68
69         cli
70 .hang:  hlt
71         jmp .hang
72
73         ; splash screen effect
74 splash:
75         mov ax, 13h
76         int 10h
77
78         mov ax, 0a000h
79         mov es, ax
80         xor di, di
81
82         mov ax, pic
83         shr ax, 4
84         mov ds, ax
85         xor si, si
86
87         mov cx, 64000
88         call decode_rle
89
90         call waitkey
91
92         mov ax, 3
93         int 10h
94         ret
95
96         ; decode RLE from ds:si to es:di, cx: number of decoded bytes (0 means 65536)
97         ; - high bit set for the repetition count, followed by a value byte to
98         ;   be repeated N times
99         ; - high bit not set for raw data that should be copied directly
100 decode_rle:
101         mov al, [si]
102         inc si
103         mov bl, 1       ; default to "copy once" for raw values
104         test al, 0x80   ; test the high bit to see if it's a count or a raw value
105         jz .copy
106         ; it's a count, clear the high bit, and read the next byte for the value
107         and al, 0x7f
108         mov bl, al
109         mov al, [si]
110         inc si
111 .copy:  mov [es:di], al
112         inc di
113         dec cx          ; decrement decoded bytes counter
114         jz .end         ; as soon as it reaches 0, bail
115         dec bl
116         jnz .copy
117         jmp decode_rle
118 .end:   ret
119         
120
121 waitkey:
122         in al, 64h
123         test al, 1
124         jz waitkey
125         in al, 60h
126         ret
127
128         ; data
129         align 16
130 pic:    incbin "nuclear.rle"
131
132 stage2_end:
133
134 ; vi:set ft=nasm: