Search code examples
assemblykernelosdevfasmvideo-memory

How to load image from disk to vmem


I am writing an OS in fasm assembly and I faced with problem. I was trying to draw font pixel-by-pixel, but it is too hard and strange. I want to make bitmap pixel-by-pixel font and save it on hdd, and in kernel code make function, that can load it to video memory. I tried to google it, but without success. Help, please

Code of kernel:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  Macroses
macro rect c, x, y, w, h {
    pusha
    mov bx, c
    mov cx, x
    mov dx, y
    mov si, w
    mov di, h
    call __rect
    popa
}
macro pixel c, x, y {rect c, x, y, 1, 1}
macro __video__init {
    pusha
    ;mov ax, 0x4F02
    ;mov bx, 0x101
    ;int 0x10
    mov   ah,     0x00
    mov   al,     0x13
    int   0x10
    rect  0x00,   0,      0,     640*2,   480*2
    popa
}
macro sym c, x, y, s {
    pusha
    xor bx, bx
    mov bx, c
    mov cx, x
    mov dx, y
    mov al, s
    call __sym
    popa
}
macro image x, y, w, h, addr {
    pusha
    mov si, x
    mov di, y
    mov [reg0], w
    mov [reg8], h
    mov bp, addr
    popa
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  Cosmetics
macro return value {
    mov eax, value
ret
}
macro far a {
    mov ax, a/16
    mov ds, ax
    mov es, ax
    mul ax, 16
    mov sp, ax
    div ax, 16
    jmp ax:0x0000
}
macro rint trr {
    pusha
    mov bp, trr
    cmp bp, 0x10
    popa
    je __r10h
}
macro retn {ret}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  Tests
macro __video__test {
    sym 0x0F, 0x00, 0x00, '!'
    sym 0x0F, 0x0F, 0x00, '"'
    sym 0x0F, 0x20, 0x00, '#'
    sym 0x0F, 0x30, 0x00, '$'
    sym 0x0F, 0x40, 0x00, '%'
    sym 0x0F, 0x50, 0x00, '&'
    sym 0x0F, 0x60, 0x00, "'"
    sym 0x0F, 0x70, 0x00, '('
    sym 0x0F, 0x80, 0x00, ')'
    sym 0x0F, 0x90, 0x00, '*'
    sym 0x0F, 0xA0, 0x00, '+'
    sym 0x0F, 0xB0, 0x00, ','
    sym 0x0F, 0xC0, 0x00, '-'
    sym 0x0F, 0xD0, 0x00, '.'
    sym 0x0F, 0xE0, 0x00, '/'
    sym 0x0F, 0xF0, 0x00, '0'
    sym 0x0F, 0x100,0x00, '1'
    image 0, 0, 320, 200, 0
    call __frame
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  Kernel
__kernel:
    org 0x7E00
    mov [bootdev], dl
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  Grafic Core
    __video__init
    ;rect 0x01, 0x00, 0x00, 0x280, 0x190
    __video__test

    jmp $
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  Bss
    buffer     db 1024 dup (?)
    bootdev    db 0x00
    reg0       db 0x0000
    reg1       db 0x0000
    hexstr     db '0x0000', 0x00
    rstr       db "Talisman's R-OS 0.0.1a", 0x00
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  Funcs
;;;;;;;;;;;;;;;;;;;;;;  Bitmap font func
__sym:
    cmp al, '!'
    je .!
    cmp al, '"'
    je ."
    cmp al, '#'
    je .sharp
    cmp al, '$'
    je .dollar
    cmp al, '%'
    je .%
    cmp al, '&'
    je .et
    cmp al, "'"
    je .'
    cmp al, '('
    je .brt
    cmp al, ')'
    je .brt2
    cmp al, '*'
    je .star
    cmp al, '+'
    je .plus
    cmp al, ','
    je .comma
    cmp al, '-'
    je .menos
    cmp al, '.'
    je .point
    cmp al, '/'
    je .slash
    cmp al, '0'
    je .0
    cmp al, '1'
    je .1
    retn
.!:
    add cx, 3
    add dx, 4
    rect bx, cx, dx, 2, 5
    add dx, 7
    rect bx, cx, dx, 2, 2
    retn
.":
    add cx, 2
    add dx, 3
    rect bx, cx, dx, 2, 3
    add cx, 3
    rect bx, cx, dx, 2, 3
    retn
.sharp:
    add cx, 2
    add dx, 4
    rect bx, cx, dx, 2, 8
    add cx, 3
    rect bx, cx, dx, 2, 8
    sub cx, 4
    inc dx
    rect bx, cx, dx, 7, 1
    add dx, 4
    rect bx, cx, dx, 7, 1
    retn
.dollar:
    add cx, 3
    add dx, 2
    rect bx, cx, dx, 2, 2
    dec cx
    add dx, 2
    rect bx, cx, dx, 4, 1
    dec cx
    inc dx
    rect bx, cx, dx, 2, 2
    add cx, 4
    rect bx, cx, dx, 2, 2
    sub cx, 3
    add dx, 2
    rect bx, cx, dx, 2, 1
    add cx, 2
    add dx, 1
    rect bx, cx, dx, 2, 1
    inc cx
    inc dx
    rect bx, cx, dx, 2, 2
    sub cx, 4
    rect bx, cx, dx, 2, 2
    inc cx
    add dx, 2
    rect bx, cx, dx, 4, 1
    inc cx
    inc dx
    rect bx, cx, dx, 2, 2
    retn
.%:
    inc cx
    inc dx
    rect bx, cx, dx, 2, 1
    dec cx
    inc dx
    rect bx, cx, dx, 1, 2
    add cx, 3
    rect bx, cx, dx, 1, 2
    sub cx, 2
    add dx, 2
    rect bx, cx, dx, 2, 1
    dec cx
    add dx, 5
    rect bx, cx, dx, 1, 3
    inc cx
    dec dx
    rect bx, cx, dx, 1, 3
    inc cx
    dec dx
    rect bx, cx, dx, 1, 3
    inc cx
    dec dx
    rect bx, cx, dx, 1, 3
    inc cx
    dec dx
    rect bx, cx, dx, 1, 3
    inc cx
    dec dx
    rect bx, cx, dx, 1, 3
    inc cx
    dec dx
    rect bx, cx, dx, 1, 3
    inc cx
    dec dx
    rect bx, cx, dx, 1, 3
    sub cx, 2
    add dx, 7
    rect bx, cx, dx, 2, 1
    dec cx
    inc dx
    rect bx, cx, dx, 1, 2
    add cx, 3
    rect bx, cx, dx, 1, 2
    sub cx, 2
    add dx, 2
    rect bx, cx, dx, 2, 1
    retn
.et:
    add cx, 2
    add dx, 3
    rect bx, cx, dx, 3, 1
    dec cx
    inc dx
    rect bx, cx, dx, 2 ,2
    add cx, 3
    rect bx, cx, dx, 2, 2
    sub cx, 2
    add dx, 2
    rect bx, cx, dx, 3, 1
    dec cx
    inc dx
    rect bx, cx, dx, 2, 4
    add cx, 3
    inc dx
    rect bx, cx, dx, 4, 1
    inc cx
    inc dx
    rect bx, cx, dx, 2, 2
    sub cx, 3
    add dx, 2
    rect bx, cx, dx, 3, 1
    add cx, 4
    rect bx, cx, dx, 2, 1
    retn
.':
    add cx, 3
    add dx, 2
    rect bx, cx, dx, 2, 3
    retn
.brt:
    add cx, 5
    add dx, 2
    pixel bx, cx, dx
    dec cx
    inc dx
    rect bx, cx, dx, 2, 1
    dec cx
    inc dx
    rect bx, cx, dx, 2, 1
    inc dx
    rect bx, cx, dx, 2, 1
    dec cx
    inc dx
    rect bx, cx, dx, 2, 1
    inc dx
    rect bx, cx, dx, 2, 1
    inc cx
    inc dx
    rect bx, cx, dx, 2, 1
    inc dx
    rect bx, cx, dx, 2, 1
    inc cx
    inc dx
    rect bx, cx, dx, 2, 1
    inc cx
    inc dx
    pixel bx, cx, dx
    retn
.brt2:
    add cx, 3
    add dx, 2
    rect bx, cx, dx, 1, 2
    ;inc cx
    ;inc dx
    ;rect bx, cx, dx, 1, 2
    inc cx
    inc dx
    pixel bx, cx, dx
    inc dx
    rect bx, cx, dx, 2, 2
    inc cx
    add dx, 2
    rect bx, cx, dx, 2, 2
    dec cx
    add dx, 2
    rect bx, cx, dx, 2, 2
    ;dec cx
    inc dx
    ;rect bx, cx, dx, 2, 1
    dec cx
    inc dx
    rect bx, cx, dx, 2, 1
    inc dx
    pixel bx, cx, dx
    retn
.star:
    add cx, 3
    add dx, 3
    pixel bx, cx, dx
    sub cx, 2
    inc dx
    rect bx, cx, dx, 5, 1
    inc cx
    inc dx
    rect bx, cx, dx, 3, 1
    inc dx
    pixel bx, cx, dx
    add cx, 2
    pixel bx, cx, dx
    retn
.plus:
    add cx, 3
    add dx, 5
    rect bx, cx, dx, 2, 5
    sub cx, 2
    add dx, 2
    rect bx, cx, dx, 6, 1
    retn
.comma:
    add cx, 3
    add dx, 10
    rect bx, cx, dx, 2, 2
    inc cx
    add dx, 2
    pixel bx, cx, dx
    retn
.menos:
    inc cx
    add dx, 7
    rect bx, cx, dx, 6, 1
    retn
.point:
    add cx, 3
    add dx, 10
    rect bx, cx, dx, 2, 2
    retn
.slash:
    add dx, 9
    rect bx, cx, dx, 1, 3
    inc cx
    dec dx
    rect bx, cx, dx, 1, 3
    inc cx
    dec dx
    rect bx, cx, dx, 1, 3
    inc cx
    dec dx
    rect bx, cx, dx, 1, 3
    inc cx
    dec dx
    rect bx, cx, dx, 1, 3
    inc cx
    dec dx
    rect bx, cx, dx, 1, 3
    inc cx
    dec dx
    rect bx, cx, dx, 1, 3
    inc cx
    dec dx
    rect bx, cx, dx, 1, 3
    retn
.0:
    inc cx
    add dx, 3
    rect bx, cx, dx, 2, 10
    add cx, 4
    rect bx, cx, dx, 2, 10
    dec cx
    inc dx
    rect bx, cx, dx, 1, 3
    dec cx
    add dx, 5
    rect bx, cx, dx, 1, 3
    dec cx
    sub dx, 7
    rect bx, cx, dx, 4, 1
    add dx, 11
    rect bx, cx, dx, 4, 1
    retn
.1:
    add cx, 4
    add dx, 2
    rect bx, cx, dx, 2, 10
    sub cx, 2
    add dx, 2
    rect bx, cx, dx, 3, 2
    add dx, 6
    rect bx, cx, dx, 6, 2
    retn
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  fast putpix func
__rect:
    push    ds    dx       di
    imul    dx,   320
    add dx,   cx
    mov ax,   0xA000
    mov ds,   ax
    jmp ._o
._o:
    push    si
    jmp ._i
._i:
    dec si
    mov byte  [edx+esi],       bl;bx
    jnz ._i
    pop si
    add dx,   320
    dec di
    jnz ._o
    pop di    dx       ds
    ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  Image func
__image:
    mov ah, 0x00
    int 0x13
    mov ah, 0x02
    mov al, [reg8]
    imul al, 320
    add al, 0x8700
    add al, [reg0]
    idiv al, 512
    mov bx, 0x8700+si+320*di
    mov es, 0x00
    mov ch, 0x00
    mov cl, (bp+512+0x7FFF-64000)/512
    mov dh, 0x00
    mov dl, [bootdev]
    int 0x13
    ret
__frame:
    mov ebx, 0x00000000
._l:
    mov byte [ebx+0xA000], [ebx+0x8700]
    cmp ebx, 6400
    je ._r
    jmp ._l
._r:
    ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  R interrupts
__r10h:
    sym bx, cx, dx, al
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  Footer
__footer:
    cli
    hlt
    jmp $-2
    times 0x7FFF-64000-$+$$ db 0x00

I hope my code will be more optimized in the future.


Solution

  • I can't make head nor tails about your __image code! You have thrown together a bunch of instructions that FASM wouldn't even be able to assemble.

    And why would you load a font, or image, or any other file from disk when you don't have a file system that you can use? For now, all you can do is embed the character set in the kernel that your 1st stage bootloader has loaded into memory.

    This is wrong: In your __video__init macro, where you setup the 320x200 256-color video mode, the black filled rectangle (rect 0x00, 0, 0, 640*2, 480*2) that you draw is much too large, and frankly you don't need it since setting the video mode will already have blackend the screen.

    A bitmapped solution

    To start using a bitmapped font, you'll have to define a character set in your program. Below is a very incomplete example of a character set where each character is 8 pixels wide and 12 pixels height. I have included the bit patterns for the digit "0" and the capitals "A" and "B".

    CharSet12:
        times (48 * 12) db 0                                         ; 0 -> 47
        db 0, 124, 198, 198, 198, 214, 214, 198, 198, 198, 124, 0    ; 48 = Char "0"
        times (16 * 12) db 0                                         ; 49 -> 64
        db 0, 16, 56, 108, 198, 198, 254, 198, 198, 198, 198, 0      ; 65 = Char "A"
        db 0, 252, 102, 102, 102, 124, 102, 102, 102, 102, 252, 0    ; 66 = Char "B"
        times (189 * 12) db 0                                        ; 67 -> 255
    

    You can design your own fonts this way and select any width and height that you like.

    Drawing transparent text

    In transparent text, you only plot pixels that have the foreground color. The background shines through. Next code does that:

    ; IN (al,bl,cx,dx) OUT () MOD (ax)
    DrawTransparentCharacter:
        push    es cx si di
        mov     ah, 12          ; OffsetInCharacterSet = CharacterHeight * ASCII
        mul     al
        mov     si, ax
        imul    di, dx, 320     ; OffsetInVideoMemory = (Y * 320) + X
        add     di, cx
        mov     ax, 0xA000
        mov     es, ax
        mov     ch, 12          ; CharacterHeight
    .OuterLoop:
        mov     cl, 8           ; CharacterWidth
        mov     al, [CharSet12 + si]
    .InnerLoop:
        shl     al, 1
        jnc     .Skip
        mov     [es:di], bl     ; Plot pixel
    .Skip:
        inc     di
        dec     cl
        jnz     .InnerLoop
        inc     si              ; To next font byte
        add     di, 320 - 8     ; To next scanline
        dec     ch
        jnz     .OuterLoop
        pop     di si cx es
        ret
    

    Now you can output a character anywhere on the screen based on the pixel position of its upperleft corner.

    ; This draws a light green "A" in the middle of the screen
    mov     dx, 94      ; Y
    mov     cx, 156     ; X
    mov     bl, 10      ; Color LightGreen
    mov     al, 65      ; "A"
    call    DrawTransparentCharacter
    

    Drawing opaque text

    In opaque text, you not only plot pixels that have the foreground color, but also those that make up the background rectangle. Next code does that:

    ; IN (al,bx,cx,dx) OUT () MOD (ax)
    DrawOpaqueCharacter:
        push    es cx dx si di
        mov     ah, 12          ; OffsetInCharacterSet = CharacterHeight * ASCII
        mul     al
        mov     si, ax
        imul    di, dx, 320     ; OffsetInVideoMemory = (Y * 320) + X
        add     di, cx
        mov     ax, 0xA000
        mov     es, ax
        mov     ch, 12          ; CharacterHeight
    .OuterLoop:
        mov     cl, 8           ; CharacterWidth
        mov     al, [CharSet12 + si]
    .InnerLoop:
        mov     dl, bl          ; Foreground color
        shl     al, 1
        jc      .Plot
        mov     dl, bh          ; Background color
    .Plot:
        mov     [es:di], dl     ; Plot pixel
        inc     di
        dec     cl
        jnz     .InnerLoop
        inc     si              ; To next font byte
        add     di, 320 - 8     ; To next scanline
        dec     ch
        jnz     .OuterLoop
        pop     di si dx cx es
        ret
    

    Now you can output a character anywhere on the screen based on the pixel position of its upperleft corner.

    ; This draws a green on bright white "B" in the bottom right corner of the screen
    mov     dx, 188     ; Y
    mov     cx, 312     ; X
    mov     bx, 0x0F02  ; Colors GreenOnBrightWhite
    mov     al, 66      ; "B"
    call    DrawOpaqueCharacter