1

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.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459

1 Answers1

1

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
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Sep Roland
  • 33,889
  • 7
  • 43
  • 76
  • I understood that I made a lot of helpless actions, but let's think that font placed in hdd without fs, without title. just tuple of bytes. and i wanna copy bytes from hdd to video buffer. it's all. thanks for advices – Våñø Čhêt Oct 25 '21 at 17:26