It's me again
I was a little afraid to write here
again but well, I try
I was trying to display something in bochs (with vgabios-lgpl, not cirrus), so I started looking
here.
It seems that, like with ROM, I can't write from A000:0000 to B000:FFFF (well, I can't write yet) + I can't use BIOS (obviously)
Then I read this:
Writing specific drivers
The alternative approach is to not use the BIOS at all. In this case, you must write your own drivers to interact with the hardware.
The simplest way to get graphics modes without using BIOS would be to develop or reuse an existing VGA driver. This gives you all low resolution modes on practically all hardware, and is easier to do than setting up a virtual machine of any sort.
However, if you want to support high resolutions, you must write a driver for each graphics card that you want your OS to support. Only recommended if you have more than one life to waste. Note that there is no official documentation available for a lot of video cards, and that you need to resort to second-hand information (which tends to be incomplete) and existing driver implementations. If you want hardware acceleration, this is the only way to go.
Seems familiar?
Following
IBM specs, VGA mode 0x13 should be perfect. Graphics mode (= you don't have to deal with fonts yet), decent resolution (320x200), small color range (byte sized)
Perfect, let's do it! I supposed I need to setup something. So I was quite happy when I found someone that
did that work for me. However, I miss some parts (font bitmap, I can find it on google, and a mysterious text.inc). Since that part aren't fundamental, I can delete that parts, call amazing function set_mode_0x13 and after only 20900 steps, it starts to loop without any sense.
This is a good sign: you need to do-it-yourself completely.
I tried to port modes.c from osdev files, only 13h mode. This is the code (it seems to assembly correctly)
vga.inc
Code: Select all
%define VGA_AC_INDEX 0x3C0
%define VGA_AC_WRITE 0x3C0
%define VGA_MISC_WRITE 0x3C2
%define VGA_SEQ_INDEX 0x3C4
%define VGA_SEQ_DATA 0x3C5
%define VGA_GC_INDEX 0x3CE
%define VGA_GC_DATA 0x3CF
; COLOR emulation MONO emulation
%define VGA_CRTC_INDEX 0x3D4 ; 0x3B4
%define VGA_CRTC_DATA 0x3D5 ; 0x3B5
%define VGA_INSTAT_READ 0x3DA
%define VGA_NUM_MISC_REG 1
%define VGA_NUM_SEQ_REGS 5
%define VGA_NUM_CRTC_REGS 25
%define VGA_NUM_GC_REGS 9
%define VGA_NUM_AC_REGS 21
%define VGA_NUM_REGS (VGA_NUM_MISC_REG+VGA_NUM_SEQ_REGS+VGA_NUM_CRTC_REGS+VGA_NUM_GC_REGS+VGA_NUM_AC_REGS)
%macro outb 2
mov dx, %1
mov al, %2
out dx, al
%endmacro
%macro outw 2
mov dx, %1
mov ax, %2
out dx, ax
%endmacro
%macro inb 1
mov dx, %1
in al, dx
%endmacro
%macro inw 1
mov dx, %1
in ax, dx
%endmacro
vgamode_13h_reg:
db 0x63 ; MISC
db 0x03, 0x01, 0x0F, 0x00, 0x0E ; SEQ
db 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, ; CRTS
db 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ; CRTS
db 0x9C, 0x0E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3, 0xFF ; CRTS
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF ; GC
db 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, ; AC
db 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, ; AC
db 0x41, 0x00, 0x0F, 0x00, 0x00 ; AC
set_mode_13h:
; set misc
outb VGA_MISC_WRITE, [vgamode_13h_reg]
;set sequencer
mov bx, 0 ; xor bl, 0
%define INDEX (VGA_NUM_MISC_REG)
.sequencerLoop:
outb VGA_SEQ_INDEX, bl
outb VGA_SEQ_DATA, [vgamode_13h_reg+INDEX+bx]
inc bl
cmp bl, VGA_NUM_SEQ_REGS
jl .sequencerLoop
; unlock CRTR
outb VGA_CRTC_INDEX, 0x03
inb VGA_CRTC_DATA
or al, 0x80
outb VGA_CRTC_DATA, al
outb VGA_CRTC_INDEX, 0x03
inb VGA_CRTC_DATA
and al, 0x7F; ~0x80
outb VGA_CRTC_DATA, al
; write CRTC reg
mov bx, 0
%define INDEX (VGA_NUM_MISC_REG+VGA_NUM_SEQ_REGS)
.crtrLoop:
outb VGA_CRTC_INDEX, bl
outb VGA_CRTC_DATA, [vgamode_13h_reg+INDEX+bx]
inc bl
cmp bl, VGA_NUM_CRTC_REGS
jl .crtrLoop
; write gc regs
mov bx, 0
%define INDEX (VGA_NUM_MISC_REG+VGA_NUM_SEQ_REGS+VGA_NUM_CRTC_REGS)
.GCLoop:
outb VGA_GC_INDEX, bl
outb VGA_GC_DATA, [vgamode_13h_reg+INDEX+bx]
inc bl
cmp bl, VGA_NUM_GC_REGS
jl .GCLoop
; write ATTRIBUTE CONTROLLER regs
mov bx, 0
%define INDEX (VGA_NUM_MISC_REG+VGA_NUM_SEQ_REGS+VGA_NUM_CRTC_REGS+VGA_NUM_GC_REGS)
.ACLoop:
inb VGA_INSTAT_READ
outb VGA_AC_INDEX, bl
outb VGA_AC_WRITE, [vgamode_13h_reg+INDEX+bx]
inc bl
cmp bl, VGA_NUM_AC_REGS
jl .ACLoop
; lock 16-color palette and unblank display (WHAT?)
inb VGA_INSTAT_READ
mov bl, 0x20
outb VGA_AC_INDEX, bl
;end
ret
fill_screen:
; sync
nop
nop
nop
; es = video segment 0xA000
; this time, I should load it
mov ax, 0xA000
mov es, ax
; random color, similar to red-pink in default IBM palette
mov al, 0x50
; fill everything
mov bx, 0
.drawLoop:
mov [es:bx], al
inc bx
cmp bx, 320*200-1
jmp .drawLoop
; done
ret
main.asm
Code: Select all
[ORG 0xF000]
[BITS 16]
times (4096-(END-START)) db 0 ; remember the org 0xf000
START:
; 0xF 0000 to FFFF ROM CODE
; 0x9 FFFE to 0000 STACK and VARIABLES
%include "vga.inc"
; ============= CODE =============
MAIN:
jmp 0xF000:SETUP ; change cs
nop ; add it to not execute LOCK command
SETUP:
; SETUP segments
mov ax, 0xF000
mov ds, ax
mov ax, 0xA000
mov es, ax ; vga segment
mov ax, 0x9000
mov ss, ax
mov sp, 0xFFFE ; sp = 0xE FFFF
mov bp, 0xFFFE
call set_mode_13h
call fill_screen
jmp $
DATA:
db "Ciao", 0
JUMP: ; FFFF FFF0
jmp MAIN
times (16-($-JUMP)) db 0
END:
It doesn't crash. After only 625 step in bochs dbg, it calls fill_screen, which should fill from es:0000 to es:ffff (es = A000).
Screen remains black.
So I asked myself: do I need to inizialize something before setting up VGA? I don't think so, because (
I'm about to say something silly) I read somewhere that VGA isn't related to PCI, so I don't need to init PCI before VGA. They lied?
Any ideas?