X-Git-Url: http://git.mutantstargoat.com?p=bootboot;a=blobdiff_plain;f=bb.asm;h=5f901bf5066d333aa224c8cce126e11ab283ee7c;hp=3f4bcd1debf141a33485c37ef5e29a87cbe43f50;hb=HEAD;hpb=8f6f00a366b21dbbc84ca918bb9542f4221f8054 diff --git a/bb.asm b/bb.asm index 3f4bcd1..5f901bf 100644 --- a/bb.asm +++ b/bb.asm @@ -1,3 +1,6 @@ +; author Eleni Maria Stea +; my x86 assembly helloworld :) + ; org: all instructions from now on start in 7c00h ; 7c00h is where the bios loads the 1st sector ; assembler formatting: @@ -8,6 +11,44 @@ ; we have to tell assembler that code is 16bit mode bits 16 +; macros +%macro SETPAL 4 ; 4 = num arguments of macro (index rgb) + mov dx, 3c8h ; index register + mov al, %1 + out dx, al + inc dx + mov al, %2 >> 2 + out dx, al + mov al, %3 >> 2 + out dx, al + mov al, %4 >> 2 ; shift to give the value from 0 - 255 + out dx, al +%endmacro + +bios_param_block: + jmp start ; 2 bytes + nop ; 1 byte + ; start of BPB at offset 3 + db "BSPL 0.1" ; 03h: OEM ident, 8 bytes + dw 512 ; 0bh: bytes per sector + db 1 ; 0dh: sectors per cluster + dw 1 ; 0eh: reserved sectors (including boot record) + db 2 ; 10h: number of FATs + dw 224 ; 11h: number of dir entries + dw 2880 ; 13h: number of sectors in volume + db 0fh ; 15h: media descriptor type (f = 3.5" HD floppy) + dw 9 ; 16h: number of sectors per FAT + dw 18 ; 18h: number of sectors per track + dw 2 ; 1ah: number of heads + dd 0 ; 1ch: number of hidden sectors + dd 0 ; 20h: high bits of sector count + db 0 ; 24h: drive number + db 0 ; 25h: winnt flags + db 28h ; 26h: signature(?) + dd 0 ; 27h: volume serial number + db "BOOTBOOT "; 2bh: volume label, 11 bytes + db "FAT12 " ; 36h: filesystem id, 8 bytes + start: mov sp, 7c00h @@ -37,26 +78,15 @@ start: mov ax, 3 call clearscreen -; waiting for keypress -; x86 has 2 special instructions to read/write from I/O -; devices: in and out (because some processors have different -; address spaces for devices and for memory, arm not) -.key_wait: - in al, 64h ; 60h = keyb data port, 64h = keyb status port - and al, 1 ; 1 = OUTBUF_FULL = the keyb controller out buf is full - jz .key_wait - - in al, 60h ; reads the keyb that was pressed to reset the flag - ; load 2nd sector from boot device and jump to it ; bios helpers, 13h = disk io mov ax, 0 mov ds, ax - mov ah, 02h ; call 2: read sectors into memory - mov al, 1 ; number of sectors to read - mov ch, 0 ; low 8 bits of cylinder number - mov cl, 2 ; sector number that starts from 1 - mov dh, 0 ; head number + mov ah, 02h ; call 2: read sectors into memory + mov al, 3 ; number of sectors to read + mov ch, 0 ; low 8 bits of cylinder number + mov cl, 2 ; sector number that starts from 1 + mov dh, 0 ; head number mov dl, [saved_drive_num] ; 8bits mov bx, sector_2 int 13h @@ -143,5 +173,245 @@ sector_2: test al, 3fh ; test with 3fh to keep the lowest 6 bits of al jnz .pal_loop +; setup lovebug palette + SETPAL 64, 0, 255, 0 ; chr(64) = @ + SETPAL 65, 0, 0, 0 ; A + SETPAL 66, 50, 50, 50 ; B + SETPAL 67, 57, 4, 4 ; C + SETPAL 68, 108, 9, 9 ; D + SETPAL 69, 164, 4, 4 ; E + +; disable all interrupts (for bios to not read the keyboard) + cli + + ; ds on 0 because rand uses it for accesses to mem + xor ax, ax + mov ds, ax + mov ax, backbuffer + shr ax, 4 ; to use it as segment! (shift right) + mov es, ax +main_loop: +; draw to back buffer + xor bx, bx ; mov bx, 0 to clear the register +.static_loop: + call rand + and ax, 3fh ; last six bits of eax (see rand) + mov [es:bx], al ; [] -> bx offset and default segment ds we change it to es + inc bx + cmp bx, 64000 ; num pixels + jnz .static_loop + + ; draw lovebug + mov di, (200 - 32) * 320 + 160 - 16 + mov ax, [num_frames] + shr ax, 2 ; /4 + cmp ax, 200 - 32 + jz .end + mov bx, ax + shl ax, 8 + shl bx, 6 + add ax, bx + sub di, ax + call rand + and ax, 3 ; random value in 0, 2 + sub ax, 1 ; random value in -1, 1 + add di, ax + mov si, lovebug + call blit32 + +; wait for vblank +.vsync_blank: + mov dx, 3dah + in al, dx + and al, 8 + jnz .vsync_blank +.vsync_visible: + in al, dx + and al, 8 ; the 4th bit is 1 when we are in the vertical blanking period + jz .vsync_visible + +; copy backbuffer to video memory + push es + push ds + mov ax, es + mov ds, ax ; ds points to backbuffer now (was in es) + xor si, si + mov ax, 0a000h + mov es, ax + xor di, di ; write in es:di + mov ecx, 16000 ; 16000 double words (dwords) = 64000 bytes + rep movsd + pop ds + pop es + + inc word [num_frames] +; moved above: +; cmp word [num_frames], 200 - 32 +; jz .end + + in al, 64h ; 60h = keyb data port, 64h = keyb status port + and al, 1 ; 1 = OUTBUF_FULL = the keyb controller out buf is full + jz main_loop ; no key pressed, loop back + in al, 60h ; reads the keyb that was pressed to reset the flag + +.end: +; re-enable all interrupts + sti + +; text mode + mov ax, 3 ; text mode + int 10h +; use bios to print +; Int 10/AH=0Eh + mov si, str_frames + call print_str + mov ax, [num_frames] + call print_num + mov si, str_newline + call print_str + + mov dx, 80h ; default to load from drive 80h + cmp byte [saved_drive_num], 80h + jnz .not_hd + inc dl ; next hd +.not_hd: +; load hard disk boot sector + xor ax, ax + mov es, ax + mov bx, 7c00h + mov ah, 02h + mov al, 1 + mov ch, 0 + mov cl, 1 + mov dh, 0 + int 13h + jnc 7c00h .inf_loop: jmp .inf_loop + +; reads from ds:si writes to es:di (bug top left corner) +; knows how many pixels on screen and how many in the lovebug +blit32: + mov cx, 1024 ; 32 x 32 lovebug +.loop: + mov al, [ds:si] + cmp al, 64 + jz .skip_pixel + mov [es:di], al +.skip_pixel: + inc si + inc di + + dec cx ; dec the num_pixels we want to write + jz .end ; all pixels have been written + test cx, 1fh ; keep 5 least significant bits, 3 most significant bits 0 + jnz .loop ; when this is 0 we are in a multiple of 32 + add di, 320 - 32 ; screen width - bug width + jmp .loop +.end: + ret + +print_str: + ;Int 10/AH=0Eh + mov al, [si] + test al, al + jz .end + mov ah, 0eh + xor bx, bx + int 10h + inc si + jmp print_str +.end: + ret + +print_num: + ; converts digits to ascii - print + push word 0 + test ax, ax + jnz .conv_loop + push word '0' + jmp .conv_end +.conv_loop: + test ax, ax + jz .conv_end + xor dx, dx + mov cx, 10 + div cx ; ax contains cx / 10 + add dl, '0' + push dx + jmp .conv_loop +.conv_end: + mov bp, sp + mov ax, [ss:bp] + test ax, ax + jz .print_end + mov ah, 0eh + xor bx, bx + int 10h + add sp, 2 + jmp .conv_end +.print_end: + add sp, 2 + ret + +; random number generator +; by nuclear +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 + +num_frames dw 0 +str_frames db 'frames: ', 0 +str_newline db 13, 10, 0 ; crlf carriage return line feed newline + +; db to write pixels transparent 255 +; @: transparent +; A: black +; B: gray +; C: dark red +; D: medium red +; E: red +lovebug: + db '@@@@BAAAB@@@@@BAAB@@@@@BAAAB@@@@' + db '@@@@@@@@AAAB@BAAAAB@BAAA@@@@@@@@' + db '@@@@@@@@@@@AAAAAAAAAA@@@@@@@@@@@' + db '@@@@@@@@@@@@AAAAAAAA@@@@@@@@@@@@' + db '@@@@@@@@@@@@AAAAAAAA@@@@@@@@@@@@' + db '@@@@@@@@@@@@BAAAAAAB@@@@@@@@@@@@' + db '@@@@@@@@@@@@@AAACAA@@@@@@@@@@@@@' + db '@@@@@@@@@@CDDEECDEEDDC@@@@@@@@@@' + db '@@@@@@@CDDEEEEEDCEEEEEDDC@@@@@@@' + db '@@@@@CDEEEEDCDECDEDCDEEEEDC@@@@@' + db '@@@@CDDCDEECACEDCECACEEDCDDC@@@@' + db '@@@CDECACEEDCDECDEDCDEECACEDC@@@' + db '@@@DEEDCDEEEEEEDCEEEEEEDCDEED@@@' + db '@@CEEEEEEEEEEEDCDDEEEEEEEEEEEC@@' + db '@@DEDCDEEEDCDECACCEDCDEEEDCDED@@' + db '@@EECACEEECACEDCDDECACEEECACEE@@' + db '@CEEDCDEEEDCDEEDCEEDCDEEEDCDEEC@' + db '@DEEEEEEEEEEEEDCCDEEEEEEEEEEEED@' + db 'CEEEEEEDCDEEEDCBACDEEEDCDEEEEEEC' + db 'CEDCDEECACEEDCAABACDEECACEEDCDEC' + db 'DECACEEDCDEDCAABAAACDEDCDEECACED' + db 'DEDCDEEEEEDCAAAABAAACDEEEEEDCDED' + db 'CEEEEEEEEECAAAABAAAAACEEEEEEEEEC' + db 'CEEEEEEEEDAAAAAABAAAAADEEEEEEEEC' + db '@DEDCDEEDCAAAAABAAAAAACDEEDCDED@' + db '@DECACEDCAAAAAAABAAAAAACDECACED@' + db '@DEDCDDCAAAAAAABAAAAAAAACDDCDED@' + db '@CEEEECAAAAAAAAABAAAAAAAACEEEEC@' + db '@@EEED@AAAAAAAABAAAAAAAAA@DEEE@@' + db '@@EEDC@@AAAAAAAABAAAAAAA@@CDEE@@' + db '@@DEC@@@@@AAAAABAAAAAA@@@@@CED@@' + db '@@@C@@@@@@@@AAAABAAA@@@@@@@@C@@@' + + align 16 ; if the address is not a multiple of 16 add some 0 to become one (because we'll use backbuffer as a segment) +backbuffer: