Code: Select all
;**************************************************;
; DISPLAY 640x480 IMAGE DEMO. ;
; ;
; by Dex (of DexOS fame.) ;
; ;
; It can be assembled with fasm and maybe ;
; nasm ?.To assemble do this: ;
; (c:\fasm BmpView.asm kernel32.exe) ;
; just change "test.bmp" before assembling to ;
; change image,(NOTE: most be 640x480 256 colors) ;
; ;
; You can run it from pure dos or from bootprog ;
; by Alexei A. Frounze (http://alexfru.chat.ru) ;
; ;
; On running it, it sets up vesa mode 640x480 8bpp ;
; goes to pmode and diplays a 640x480 8bpp bmp ;
; image "test.bmp", it prints error if no vesa2 ;
; ;
; Thanks to Tomasz Grysztar (for fasm),Christopher ;
; Giese,and any one else who has helped me. ;
; ;
; More Demos, tut and DexOS, can be found at ;
; ;
; www.dex4u.com ;
; ;
;**************************************************;
format MZ
use16
jmp start
header equ [ModeInfo_PhysBasePtr]
linear_sel equ linear_sel_1-gdt
sys_code equ sys_code_1-gdt
sys_data equ sys_data_1-gdt
Real_code equ Real_code_1-gdt
Real_data equ Real_data_1-gdt
include 'vesainfo.inc' ; VESA information block,we need the for Vesa info
;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; This sets vesa info ;
;..............................................................................................;
start:
push cs
pop ds
mov ax,ds
mov es,ax
;------------------------------------------------------------
; Purpose: Checks to see if VESA is available and if the desired mode is
; available.
; Inputs: None
; Outputs: VESAInfo and VESA_Info structures filled (if successful)
;------------------------------------------------------------
mov dword [VESAInfo_Signature],'VBE2'
mov ax,4f00h ; Is Vesa installed ?
mov di,VESA_Info ; This is the address of how info block.
int 10h
cmp ax,004Fh ; Is vesa installed ?,
jne near NoVesa2 ; If not print a mesage & quit.
mov ax,4f01h ; Get Vesa Mode information.
mov di,Mode_Info ; This is the address of how info block.
mov cx,0x4101 ;0x4112 ; 4112h = 32/24bit ; 0x4101 = 256bit ;4111h = 65535bit (640*480)
and cx,0xfff
int 10h
cmp dword [VESAInfo_Signature], 'VESA'
jne near NoVesa2
cmp byte [VESAInfo_Version+1], 2
jb NoVesa2 ; VESA version below 2.0
mov ax,4f02h ; set vesa screen mode
mov bx,0x4101 ; 4101h = 640x480 256
int 10h
cmp ax,004Fh
jne NoVesa2 ; jump if no vesa 2
;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; This sets up going into pmode ;
;..............................................................................................;
call enable_A20
xor ebx,ebx
mov bx,ds ; BX=segment
shl ebx,4 ; BX="linear" address of segment base
mov eax,ebx
mov [sys_code_1 + 2],ax ; set base address of 32-bit segments
mov [sys_data_1 + 2],ax
mov [Real_code_1 + 2],ax ; set base address of 16-bit segments
mov [Real_data_1 + 2],ax
shr eax,16
mov [sys_code_1 + 4],al
mov [sys_data_1 + 4],al
mov [Real_code_1 + 4],al
mov [Real_data_1 + 4],al
mov [sys_code_1 + 7],ah
mov [sys_data_1 + 7],ah
mov [Real_code_1 + 7],ah
mov [Real_data_1 + 7],ah
add ebx,gdt ; EBX=linear address of gdt
mov [gdtr + 2],ebx
cli ; Disable interrupts,
mov ax,cs
mov [RealModeCS],ax
lgdt [gdtr] ; Load the GDT descriptor
mov eax, cr0 ; Copy the contents of CR0 into EAX
or eax, 1 ; Set bit 0
mov cr0, eax ; Copy the contents of EAX into CR0
jmp 10h:clear_pipe ; Jump to code segment, offset clear_pipe
NoVesa2:
mov ax,0xB800
mov es,ax
lea si,[NoVesa2Msg] ; Just print's a error mesage and end's.
mov di,(80 * 5 + 6) * 2
mov cx,58
cld
rep movsb
NoVesa2End:
jmp NoVesa2End
USE32 ; We now need 32-bit instructions
clear_pipe:
;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; We are in pmode ;
;..............................................................................................;
xor edi,edi
xor esi,esi
mov ax, 18h ; Save data segment identifyer
mov ds, ax ; Move a valid data segment into the data segment register
mov ss, ax ; Move a valid data segment into the stack segment register
mov es,ax
nop
mov es,ax
mov fs,ax
mov gs,ax
mainloop:
call Fdd_motor_off
call DisplayBMP
jmp $
;**********************************************************************************************;
; Procedure's ;
;**********************************************************************************************;
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::;
; load image to screen ;
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::;
;----------------------------------------------------;
; Check valid bmp. ;
;----------------------------------------------------;
DisplayBMP:
mov esi,LoadMeHere
cmp word [ds:esi],'BM'
jnz bmp_error
mov bx,[ds:esi + 18] ; picture width 12
mov ebp,[ds:esi + 22] ; picture depth 16
cmp bx,640 ; W
ja bmp_error
cmp ebp,480 ; H
ja bmp_error
cmp word [ds:esi + 28],8 ; bits per pixel
jnz bmp_error
;----------------------------------------------------;
; Set pal. ;
;----------------------------------------------------;
add esi,0x36 ; start of palette
xor ecx,ecx
mov cx,256 ; number of colors
mov dx,0x03c8
mov al,0
out dx,al
inc dx
set_pal: ; Convert 4 byte BGR -> 3 byte RGB
mov al,[esi+2] ; red
shr al,2
out dx,al
mov al,[esi+1] ; green
shr al,2
out dx,al
mov al,[esi] ; blue
shr al,2
out dx,al
add esi,4
loop set_pal
lea dx,[bx+3] ; round bmp width
and dx,-4
imul edi,ebp,640
add edi,[ModeInfo_PhysBasePtr]
mov ax,08h
mov es,ax
add edi,640
new_line:
sub edi,640
pushad
mov cx,bx ; columns
rep movsb
popad
add esi,edx ; start of next bmp line
dec ebp
jnz new_line
jmp @f
;----------------------------------------------------;
; Error message. ;
;----------------------------------------------------;
bmp_error:
;----------------------------------------------------;
; wait for key press ;
;----------------------------------------------------;
@@:
ret
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::;
; enable A20 line ;
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::;
enable_A20:
pusha
cli ; Disable all irqs
cld
mov al,255 ; Mask all irqs
out 0xa1,al
out 0x21,al
l.5: in al,0x64 ; Enable A20
test al,2 ; Test the buffer full flag
jnz l.5 ; Loop until buffer is empty
mov al,0xD1 ; Keyboard: write to output port
out 0x64,al ; Output command to keyboard
l.6: in al,0x64
test al,2
jnz l.6 ; Wait 'till buffer is empty again
mov al,0xDF ; keyboard: set A20
out 0x60,al ; Send it to the keyboard controller
mov cx,14h
l.7: ; this is approx. a 25uS delay to wait
out 0edh,ax ; for the kb controler to execute our
loop l.7 ; command.
sti
popa
ret
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::;
; Turn floppy motor off. ;
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::;
Fdd_motor_off:
mov dx,0x3f2
mov al,0
out dx,al
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Proc End ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
NoVesa2Msg: db "Y O U N E E D V E S A 2 F O R T H I S D E M O ! "
JustInCase:
dd 0
RealModeCS:
dw 0
ridtr: dw 0xFFFF ; limit=0xFFFF
dd 0 ; base=0
count1: dw 0
count: db 0
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::;
; GDT ;
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::;
gdtr: dw gdt_end - gdt - 1 ; GDT limit
dd gdt ; (GDT base gets set above)
gdt: ; Address for the gdt
dw 0 ; limit 15:0 (0h) Null Segment
dw 0 ; base 15:0
db 0 ; base 23:16
db 0 ; type
db 0 ; limit 19:16, flags
db 0 ; base 31:24
linear_sel_1:
dw 0xFFFF ; (8h) linear Data segment, read/write, expand down
dw 0
db 0
db 10010010b
db 11001111b
db 0
sys_code_1: ; (10h) Code segment, read/execute, nonconforming
dw 0FFFFh
dw 0
db 0
db 10011010b
db 11001111b
db 0
sys_data_1: ; (18h) Data segment, read/write, expand down
dw 0FFFFh
dw 0
db 0
db 10010010b
db 11001111b
db 0
Real_code_1: ; (20h) Real mode code segment
dw 0xFFFF
dw 0
db 0
db 10011010b
db 0
db 0
Real_data_1: ; (28h) Real mode data segment
dw 0xFFFF
dw 0
db 0
db 10010010b
db 0
db 0
gdt_end: ; Used to calculate the size of the GDT
LoadMeHere:
file 'test.bmp'
Note: you need to get bootprog to load the mz exe once assembled.