PUBLIC _enableUnchainedVGAMode PUBLIC _enableTextMode PUBLIC _fillScreen PUBLIC _latchCopyCube PUBLIC _drawColorCube PUBLIC _writeCube PUBLIC _keyboardPressed PUBLIC keyboardHandler_ DISPLAY_MODE_VGA equ 13h DISPLAY_MODE_TEXT equ 03h VGA_SEQUENCE_CONTROLLER_INDEX equ 0x3c4 VGA_SEQUENCE_CONTROLLER_DATA equ 0x3c5 VGA_SEQUENCE_CONTROLLER_MEMORY_MODE equ 0x04 VGA_SEQUENCE_CONTROLLER_MAP_MASK_MODE equ 0x02 VGA_GRAPHICS_MODE_INDEX equ 0x3CE VGA_GRAPHICS_MODE equ 0x05 VGA_CRT_CONTROLLER_INDEX equ 0x03d4 VGA_CRT_CONTROLLER_DATA equ 0x03d5 VGA_CRT_CONTROLLER_UNDERLINE_LOC equ 0x14 VGA_CRT_CONTROLLER_MODE_CONTROL equ 0x17 .386 .model flat,c .DATA _keyboardPressed db 0 .CODE keyboardHandler_: cli push eax push ebx ; put scancode into bl in al, 0x60 mov bl, al ; acknowledge keyboard in al, 0x61 mov ah, al or al, 0x80 out 0x61, al xchg ah, al out 0x61, al ; a key is pressed if the topmost bit of the scancode is 0 and bl,0x80 jne _keyboardHandler_notKeydown mov [_keyboardPressed], 1 _keyboardHandler_notKeydown: ; acknowledge interrupt mov al, 0x20 out 0x20, al pop ebx pop eax sti ; return from the interrupt in a way that preserves the calling stack iretd _enableUnchainedVGAMode: mov ax,0x0013; int 0x10 mov dx, VGA_SEQUENCE_CONTROLLER_INDEX mov al, VGA_SEQUENCE_CONTROLLER_MEMORY_MODE mov ah, 0x06 out dx, ax mov dx, VGA_CRT_CONTROLLER_INDEX mov al, VGA_CRT_CONTROLLER_MODE_CONTROL mov ah, 0xe3 out dx, ax mov dx, VGA_CRT_CONTROLLER_INDEX mov al, VGA_CRT_CONTROLLER_UNDERLINE_LOC mov ah, 0x00 out dx, ax ret _enableTextMode: mov ah,0h mov al,DISPLAY_MODE_TEXT int 10h ret _fillScreen: push ebp mov ebp, esp ; set all bitplanes mov dx, VGA_SEQUENCE_CONTROLLER_INDEX mov al, 0x02 mov ah, 0x0f out dx, ax push ebx push ecx push edx sub eax,eax mov al, [ebp+8] ; requested color ; we can write a long at a time and let the bus ; and BIU work out the details. on a 16-bit ISA ; bus with a 16-bit VGA card, this will be faster ; than byte writes sub edx,edx add dl,al shl edx,8 add dl,al shl edx,8 add dl,al shl edx,8 add dl,al ; with all planes selected we only need to fill 16000 bytes of data ; and we're filling them four bytes at a time mov cx, 4000 mov ebx, 0xA0000 ; VGA base address _fillScreen_loop: mov DWORD PTR [ebx], edx add ebx,4 loop _fillScreen_loop pop edx pop ecx pop ebx mov esp,ebp pop ebp ret _drawColorCube: push ebp mov ebp, esp sub esp, 4 ; y push ebx push ecx push edx ; write to all planes mov dx, VGA_SEQUENCE_CONTROLLER_INDEX mov al, VGA_SEQUENCE_CONTROLLER_MAP_MASK_MODE mov ah, 0xf out dx, ax ; write out host data only mov dx, VGA_GRAPHICS_MODE_INDEX mov al, 0x03 mov ah, 0x00 out dx, ax ; disable set/reset registers mov al, 0x00 mov ah, 0x00 out dx, ax mov al, 0x01 mov ah, 0x00 out dx, ax mov DWORD PTR [ebp-4], 16 ; y mov cx,[ebp-4] ; offset is [ebp+8] mov bh,[ebp+12]; color _drawColorCube_yLoop: mov [ebp-4],cx ; put the VGA write offset into eax mov eax,[ebp-4] dec eax mov bl,80 mul bl add eax,[ebp+8] add eax,0xa0000 mov cx, 4 _drawColorCube_xLoop: mov [eax],bh ; write color four bytes at a time inc eax loop _drawColorCube_xLoop mov cx, [ebp-4] loop _drawColorCube_yLoop pop edx pop ecx pop ebx mov esp, ebp pop ebp ret _writeCube: push ebp mov ebp,esp ; we need a y variable sub esp,4 push ebx push ecx push edx ; [ebp+8] is x offset ; [ebp+12] is data rotate ; [ebp+16] is set/reset ; [ebp+20] is enable set/reset ; enable Logical Operation and host data shifts mov dx, VGA_GRAPHICS_MODE_INDEX mov al, 0x03 mov ah, [ebp+12] out dx, ax ; enable set/reset registers mov dx, VGA_GRAPHICS_MODE_INDEX mov al, 0x00 mov ah, [ebp+16] out dx, ax mov dx, VGA_GRAPHICS_MODE_INDEX mov al, 0x01 mov ah, [ebp+20] out dx, ax mov DWORD PTR [ebp-4],16 mov cx,[ebp-4] _writeCube_yLoop: mov [ebp-4],cx ; determine the offset within VGA memory to write this line to ; and put it in eax mov eax,[ebp-4] dec eax mov bl,80 mul bl add eax,0xA0000 ; 16 pixels across mov cx,16 _writeCube_xLoop: push eax ; get the plane to write to in bl push ecx dec ecx and ecx,0x03 mov bl,1 shl bl,cl pop ecx ; write to one plane mov dx, VGA_SEQUENCE_CONTROLLER_INDEX mov al, VGA_SEQUENCE_CONTROLLER_MAP_MASK_MODE mov ah, bl out dx, ax ; select color to write into bl mov ax,[ebp-4] dec ax mov bl,16 mul bl add al,cl mov bl,al pop eax push edx push ecx ; select the correct pixel offset (x / 4) and write the color dec ecx shr ecx,2 add ecx,[ebp+8] mov BYTE PTR [eax+ecx],bl pop ecx pop edx loop _writeCube_xLoop mov cx,[ebp-4] loop _writeCube_yLoop pop edx pop ecx pop ebx mov esp,ebp pop ebp ret _latchCopyCube: push ebp mov ebp, esp ; we need a y variable sub esp,4 ; y push edx push ebx ; accept a mode ; accept a mix value ; accept an x offset ; [ebp+8] is x offset ; [ebp+12] is written value ; [ebp+16] is data rotate register ; [ebp+20] is set/reset register ; [ebp+24] is enable set/reset register ; write to all planes mov dx, VGA_SEQUENCE_CONTROLLER_INDEX mov al, VGA_SEQUENCE_CONTROLLER_MAP_MASK_MODE mov ah, 0xf out dx, ax ; enable Logical Operation and host data shifts mov dx, VGA_GRAPHICS_MODE_INDEX mov al, 0x03 mov ah, [ebp+16] out dx, ax ; enable set/reset registers mov dx, VGA_GRAPHICS_MODE_INDEX mov al, 0x00 mov ah, [ebp+20] out dx, ax mov dx, VGA_GRAPHICS_MODE_INDEX mov al, 0x01 mov ah, [ebp+24] out dx, ax mov dh, [ebp+12] mov DWORD PTR [ebp-4],16 ; y ; read across the cube, should take 4 * 16 reads mov cx,[ebp-4] _latchCopyCube_yLoop: mov [ebp-4],cx ; put y back in loop mov eax,[ebp-4] ; put y in eax dec eax ; offset by 1 for loop ; can only multiply in eax by register mov bl,80 mul bl ; number of lines add eax,0xa0000 ; vga base address ; keep our index handy mov ebx, [ebp+8] ; start x loop mov cx,4 _latchCopyCube_xLoop: ; fill latches via memory read mov dl, BYTE PTR [eax] ; write blank mov BYTE PTR [eax+ebx], dh ; increment vga pointer inc eax ; loop until x is 0 loop _latchCopyCube_xLoop ; restore y for looping mov cx,[ebp-4] ; loop until y is 0 loop _latchCopyCube_yLoop _done: ; put things back pop ebx pop edx mov esp,ebp pop ebp ret end