X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=bootsplash;a=blobdiff_plain;f=bootsplash.asm;h=b7f53c76958b130d493d04c6ee9ea17bd8b10bb0;hp=26f557acb8f2c36ee4ece51967e7053e59e60f02;hb=HEAD;hpb=8a2e90cd377e7177f32ffc3ffc30a508e3f5f474 diff --git a/bootsplash.asm b/bootsplash.asm index 26f557a..b7f53c7 100644 --- a/bootsplash.asm +++ b/bootsplash.asm @@ -1,10 +1,26 @@ org 7c00h bits 16 +BOOT_DEV equ 80h + stacktop equ 7b00h boot_driveno equ 7b00h ; 1 byte stage2_size equ stage2_end - stage2_start +spawn_rate equ 512 +framebuf equ 40000h + +%macro floppy_motor_off 0 + pushf + and dl, 80h + jnz %%end ; skip if high bit is set (i.e. it's not a floppy) + mov dx, 3f2h + in al, dx + and al, 0fh + out dx, al +%%end: popf +%endmacro + start: xor ax, ax mov ds, ax @@ -20,12 +36,13 @@ start: xor ax, ax mov es, ax mov bx, stage2_start - mov ah, 2 ; read sectors LBA call + mov ah, 2 ; read sectors call mov al, (stage2_size + 511) / 512 ; num sectors mov cx, 2 ; ch: cylinder, cl: sector xor dx, dx ; dh: head mov dl, [boot_driveno] int 13h + floppy_motor_off ; turn off floppy motor (if dl is < 80h) jnc stage2_start ; loaded successfully, jump to it ; failed to load second sector @@ -37,9 +54,9 @@ start: ; expects string ptr in ax printstr: - mov bx, ax -.loop: mov al, [bx] - inc bx + mov si, ax +.loop: mov al, [si] + inc si test al, al jz .done mov ah, 0eh @@ -49,38 +66,226 @@ printstr: .done: ret str_load_fail db "Failed to load second stage!",0 -str_foo db "Loaded 2nd stage boot loader",0 +str_booting db "Booting system... ",0 +str_bootfail db "failed!",0 times 510-($-$$) db 0 - dw 0xaa55 +bootsig dw 0xaa55 ; start of the second stage stage2_start: + pushf + cli + call splash + popf + + xor ax, ax + mov es, ax + mov ds, ax + + mov ax, str_booting + call printstr + + ; blank out the existing boot signature to really see if a boot sector + ; gets loaded correctly + xor ax, ax + mov [bootsig], ax + + ; load from BOOT_DEV into 7c00h and jump + mov bx, 7c00h + mov ax, 0201h ; ah: call 2 (read sectors), al: count = 1 + mov cx, 1 ; ch: cylinder 0, cl: sector 1 + mov dx, BOOT_DEV ; dh: head 0, dl: boot device number + int 13h + floppy_motor_off ; turn floppy motor off (if dl < 80h) + + jc .fail ; BIOS will set the carry flag on failure + mov ax, [bootsig] + cmp ax, 0aa55h + jnz .fail ; fail if what we loaded is not a valid boot sect + + mov ax, 0e0dh + mov bx, 7 + int 10h + mov ax, 0e0ah + int 10h + + jmp 7c00h ; all checks passed, jump there + +.fail: mov ax, str_bootfail + call printstr +.hang: cli + hlt + jmp .hang + + + ; splash screen effect +splash: mov ax, 13h int 10h - mov ax, 0a000h + ; setup ramdac colormap + mov ax, pal + shr ax, 4 + mov ds, ax + xor ax, ax + mov dx, 3c8h + out dx, al + inc dx + xor bx, bx +.cmap_loop: + mov al, [bx] + shr al, 2 + out dx, al + inc bx + cmp bx, 768 ; 256 * 3 + jnz .cmap_loop + + ; decompress image + mov ax, img + shr ax, 4 mov es, ax xor di, di - mov cx, 32000 - mov ax, 0505h - rep stosw + mov ax, imgrle + shr ax, 4 + mov ds, ax + xor si, si + mov cx, 64000 + call decode_rle - call waitkey + ; precalculate spawn points + mov ax, es + mov ds, ax ; decompressed image -> ds:bx + xor bx, bx + mov ax, spawn_pos + shr ax, 4 + mov es, ax ; spawn_pos table segment -> es:dx + xor edx, edx - mov ax, 3 - int 10h + mov cx, 64000 +.calcspawn_loop: + mov al, [bx] + test al, 0x80 + jz .notspawn + mov [es:edx * 2], bx + inc edx +.notspawn: + inc bx + dec cx + jnz .calcspawn_loop + ; update num_spawn_pos + xor ax, ax + mov ds, ax + mov [num_spawn_pos], edx + + mov ax, framebuf >> 4 + mov fs, ax ; fs will point to the off-screen framebuffer + + ; effect main loop +.mainloop: + mov cx, spawn_rate +.spawn: call rand + xor edx, edx + div dword [num_spawn_pos] ; edx <- rand % num_spawn_pos + mov bx, [es:edx * 2] ; grab one of the spawn positions + ; animate the spawn position xor ax, ax + mov al, [frameno] + mov bp, ax + movsx ax, byte [bp + sintab] + sar ax, 3 + add bx, ax + + mov byte [fs:bx], 0xff ; plot a pixel there + dec cx + jnz .spawn + + ; blur the screen upwards + mov ax, fs + mov ds, ax ; let's use ds for this to avoid long instructions + xor bx, bx ; use: pointer + xor ax, ax ; use: pixel accum + xor dx, dx ; use: second pixel +.blurloop: + xor ax, ax + mov al, [bx] + mov dl, [bx + 320] + add ax, dx + mov dl, [bx + 319] + add ax, dx + mov dl, [bx + 321] + add ax, dx + mov dl, [bx + 640] + add ax, dx + xor dx, dx + mov cx, 5 + div cx + mov [bx], al + + inc bx + cmp bx, 64000 - 640 + jnz .blurloop + + + ; wait until the start of vblank +.waitvblank: + mov dx, 3dah + in al, dx + and al, 8 + jz .waitvblank + + ; copy to screen + push es + mov ax, 0a000h mov es, ax + xor di, di + mov ax, fs + mov ds, ax + xor si, si + mov ecx, 16000 + rep movsd + pop es + xor ax, ax + mov ds, ax - mov ax, str_foo - call printstr + inc word [frameno] -.hang: cli - hlt - jmp .hang + ; check for keypress + in al, 64h + and al, 1 + jz .mainloop + in al, 60h + +.end: mov ax, 3 + int 10h + ret + + ; decode RLE from ds:si to es:di, cx: number of decoded bytes (0 means 65536) + ; - high bit set for the repetition count, followed by a value byte to + ; be repeated N times + ; - high bit not set for raw data that should be copied directly +decode_rle: + mov al, [si] + inc si + mov bl, 1 ; default to "copy once" for raw values + test al, 0x80 ; test the high bit to see if it's a count or a raw value + jz .copy + ; it's a count, clear the high bit, and read the next byte for the value + and al, 0x7f + mov bl, al + mov al, [si] + inc si +.copy: mov [es:di], al + inc di + dec cx ; decrement decoded bytes counter + jz .end ; as soon as it reaches 0, bail + dec bl + jnz .copy + jmp decode_rle +.end: ret + waitkey: in al, 64h @@ -89,6 +294,31 @@ waitkey: in al, 60h ret +rand: + mov eax, [randval] + mul dword [randmul] + add eax, 12345 + and eax, 0x7fffffff + mov [randval], eax + shr eax, 16 + ret + +randmul dd 1103515245 +randval dd 0ace1h + + + ; data +%include "lut.inc" + +num_spawn_pos dd 0 +frameno dw 0 + align 16 +spawn_pos: +imgrle: incbin "nuclear.rle" + align 16 +img: +pal: incbin "fire.pal" + stage2_end: ; vi:set ft=nasm: