From f950c9758ede9c9a2cb2889e4863cee546565a7b Mon Sep 17 00:00:00 2001 From: Eleni Maria Stea Date: Tue, 5 Jan 2021 20:51:22 +0200 Subject: [PATCH 1/1] double buffering with vsync --- bb.asm | 194 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 182 insertions(+), 12 deletions(-) diff --git a/bb.asm b/bb.asm index a3f6011..4eb536e 100644 --- a/bb.asm +++ b/bb.asm @@ -8,6 +8,20 @@ ; 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 + start: mov sp, 7c00h @@ -41,11 +55,11 @@ start: ; 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 @@ -132,21 +146,25 @@ 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, 0a000h + mov ax, backbuffer + shr ax, 4 ; to use it as segment! (shift right) mov es, ax main_loop: -; wait for vblank - mov dx, 3dah - in al, dx - and al, 8 ; the 4th bit is 1 when we are in the vertical blanking period - jz main_loop - +; draw to back buffer xor bx, bx ; mov bx, 0 to clear the register .static_loop: call rand @@ -156,6 +174,34 @@ main_loop: cmp bx, 64000 ; num pixels jnz .static_loop + ; draw lovebug + mov di, 32000 + mov si, lovebug + call blit32 + +; wait for vblank +.vsync: + mov dx, 3dah + in al, dx + and al, 8 ; the 4th bit is 1 when we are in the vertical blanking period + jnz .vsync + +; 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] + 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 @@ -164,9 +210,85 @@ main_loop: ; 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 .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: @@ -180,3 +302,51 @@ rand: 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: -- 1.7.10.4