14. フレームバッファでグラフィックス

Linux カーネルの2.2以降フレームバッファが使えるようになっています. アセンブラでもコンソール上でグラフィックを表示するプログラムが比較的 容易に作成できます.フレームバッファを使うためにはカーネルを再構築する 必要がありますが,こちらのページ を参考にしてカーネルを再構築して下さい.

準備

例によって,カーネルのヘッダファイルをアセンブラで使えるように変換します. まずフレームバッファ用の定数や構造体の定義に関する部分を用意します.

;=========================================================================
; file : fb.inc
; 2001/01/24
; derived from  : linux-2.4.0/include/linux/fb.h
;=========================================================================
%ifndef _FB_INC
%define _FB_INC

; Definitions of frame buffers

%assign  FB_MAJOR                29
%assign  FB_MAX                  32      ; sufficient for now

; ioctls
;   0x46 is 'F'
%assign  FBIOGET_VSCREENINFO     0x4600
%assign  FBIOPUT_VSCREENINFO     0x4601
%assign  FBIOGET_FSCREENINFO     0x4602
%assign  FBIOGETCMAP             0x4604
%assign  FBIOPUTCMAP             0x4605
%assign  FBIOPAN_DISPLAY         0x4606
; 0x4607-0x460B are defined below
; %assign   FBIOGET_MONITORSPEC  0x460C
; %assign   FBIOPUT_MONITORSPEC  0x460D
; %assign   FBIOSWITCH_MONIBIT   0x460E
%assign  FBIOGET_CON2FBMAP       0x460F
%assign  FBIOPUT_CON2FBMAP       0x4610
%assign  FBIOBLANK               0x4611          ; arg: 0 or vesa level + 1
;%assign  FBIOGET_VBLANK          _IOR('F', 0x12, struct fb_vblank)
%assign  FBIO_ALLOC              0x4613
%assign  FBIO_FREE               0x4614
%assign  FBIOGET_GLYPH           0x4615
%assign  FBIOGET_HWCINFO         0x4616
%assign  FBIOPUT_MODEINFO        0x4617
%assign  FBIOGET_DISPINFO        0x4618

%assign  FB_TYPE_PACKED_PIXELS          0   ; Packed Pixels
%assign  FB_TYPE_PLANES                 1   ; Non interleaved planes
%assign  FB_TYPE_INTERLEAVED_PLANES     2   ; Interleaved planes
%assign  FB_TYPE_TEXT                   3   ; Text/attributes
%assign  FB_TYPE_VGA_PLANES             4   ; EGA/VGA planes

%assign  FB_AUX_TEXT_MDA                0   ; Monochrome text
%assign  FB_AUX_TEXT_CGA                1   ; CGA/EGA/VGA Color text
%assign  FB_AUX_TEXT_S3_MMIO            2   ; S3 MMIO fasttext
%assign  FB_AUX_TEXT_MGA_STEP16         3   ; MGA Millenium I: text,attr,14 rsrvd bytes
%assign  FB_AUX_TEXT_MGA_STEP8          4   ; other MGAs:      text,attr, 6 rsved bytes

%assign  FB_AUX_VGA_PLANES_VGA4         0   ; 16 color planes (EGA/VGA)
%assign  FB_AUX_VGA_PLANES_CFB4         1   ; CFB4 in planes (VGA)
%assign  FB_AUX_VGA_PLANES_CFB8         2   ; CFB8 in planes (VGA)

%assign  FB_VISUAL_MONO01               0   ; Monochr. 1=Black 0=White
%assign  FB_VISUAL_MONO10               1   ; Monochr. 1=White 0=Black
%assign  FB_VISUAL_TRUECOLOR            2   ; True color
%assign  FB_VISUAL_PSEUDOCOLOR          3   ; Pseudo color (like atari)
%assign  FB_VISUAL_DIRECTCOLOR          4   ; Direct color
%assign  FB_VISUAL_STATIC_PSEUDOCOLOR   5   ; Pseudo color readonly

%assign  FB_ACCEL_NONE                  0   ; no hardware accelerator
%assign  FB_ACCEL_ATARIBLITT            1   ; Atari Blitter
%assign  FB_ACCEL_AMIGABLITT            2   ; Amiga Blitter
%assign  FB_ACCEL_S3_TRIO64             3   ; Cybervision64 (S3 Trio64)
%assign  FB_ACCEL_NCR_77C32BLT          4   ; RetinaZ3 (NCR 77C32BLT)
%assign  FB_ACCEL_S3_VIRGE              5   ; Cybervision64/3D (S3 ViRGE)
%assign  FB_ACCEL_ATI_MACH64GX          6   ; ATI Mach 64GX family
%assign  FB_ACCEL_DEC_TGA               7   ; DEC 21030 TGA
%assign  FB_ACCEL_ATI_MACH64CT          8   ; ATI Mach 64CT family
%assign  FB_ACCEL_ATI_MACH64VT          9   ; ATI Mach 64CT family VT class
%assign  FB_ACCEL_ATI_MACH64GT          10  ; ATI Mach 64CT family GT class
%assign  FB_ACCEL_SUN_CREATOR           11  ; Sun Creator/Creator3D
%assign  FB_ACCEL_SUN_CGSIX             12  ; Sun cg6
%assign  FB_ACCEL_SUN_LEO               13  ; Sun leo/zx
%assign  FB_ACCEL_IMS_TWINTURBO         14  ; IMS Twin Turbo
%assign  FB_ACCEL_3DLABS_PERMEDIA2      15  ; 3Dlabs Permedia 2
%assign  FB_ACCEL_MATROX_MGA2064W       16  ; Matrox MGA2064W (Millenium)
%assign  FB_ACCEL_MATROX_MGA1064SG      17  ; Matrox MGA1064SG (Mystique)
%assign  FB_ACCEL_MATROX_MGA2164W       18  ; Matrox MGA2164W (Millenium II)
%assign  FB_ACCEL_MATROX_MGA2164W_AGP   19  ; Matrox MGA2164W (Millenium II)
%assign  FB_ACCEL_MATROX_MGAG100        20  ; Matrox G100 (Productiva G100)
%assign  FB_ACCEL_MATROX_MGAG200        21  ; Matrox G200 (Myst, Mill, ...)
%assign  FB_ACCEL_SUN_CG14              22  ; Sun cgfourteen
%assign  FB_ACCEL_SUN_BWTWO             23  ; Sun bwtwo
%assign  FB_ACCEL_SUN_CGTHREE           24  ; Sun cgthree
%assign  FB_ACCEL_SUN_TCX               25  ; Sun tcx
%assign  FB_ACCEL_MATROX_MGAG400        26  ; Matrox G400
%assign  FB_ACCEL_NV3                   27  ; nVidia RIVA 128
%assign  FB_ACCEL_NV4                   28  ; nVidia RIVA TNT
%assign  FB_ACCEL_NV5                   29  ; nVidia RIVA TNT2
%assign  FB_ACCEL_CT_6555x              30  ; C&T 6555x
%assign  FB_ACCEL_3DFX_BANSHEE          31  ; 3Dfx Banshee
%assign  FB_ACCEL_ATI_RAGE128           32  ; ATI Rage128 family
%assign  FB_ACCEL_IGS_CYBER2000         33  ; CyberPro 2000
%assign  FB_ACCEL_IGS_CYBER2010         34  ; CyberPro 2010
%assign  FB_ACCEL_IGS_CYBER5000         35  ; CyberPro 5000
%assign  FB_ACCEL_SIS_GLAMOUR           36  ; SiS 300/630/540

struc fb_fix_screeninfo
    .id                 resb   16   ; identification string eg "TT Builtin"
    .smem_start         resd    1   ; Start of frame buffer mem
                                    ; (physical address)
    .smem_len           resd    1   ; Length of frame buffer mem
    .type               resd    1   ; see FB_TYPE_*
    .type_aux           resd    1   ; Interleave for interleaved Planes
    .visual             resd    1   ; see FB_VISUAL_*
    .xpanstep           resw    1   ; zero if no hardware panning
    .ypanstep           resw    1   ; zero if no hardware panning
    .ywrapstep          resw    1   ; zero if no hardware ywrap
    .padding            resw    1   ;  for alignment, jm 1/26/2001
    .line_length        resd    1   ; length of a line in bytes
    .mmio_start         resd    1   ; Start of Memory Mapped I/O
                                    ; (physical address)
    .mmio_len           resd    1   ; Length of Memory Mapped I/O
    .accel              resd    1   ; Type of acceleration available
    .reserved           resw    3   ; Reserved for future compatibility
endstruc

; Interpretation of offset for color fields: All offsets are from the right,
; inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you
; can use the offset as right argument to <<). A pixel afterwards is a bit
; stream and is written to video memory as that unmodified. This implies
; big-endian byte order if bits_per_pixel is greater than 8.

struc fb_bitfield
    .offset             resd    1       ; beginning of bitfield
    .length             resd    1       ; length of bitfield
    .msb_right          resd    1       ; != 0 : Most significant bit is
                                    ; right
endstruc

%assign  FB_NONSTD_HAM           1       ; Hold-And-Modify (HAM)

%assign  FB_ACTIVATE_NOW         0       ; set values immediately (or vbl)
%assign  FB_ACTIVATE_NXTOPEN     1       ; activate on next open
%assign  FB_ACTIVATE_TEST        2       ; don't set, round up impossible
%assign  FB_ACTIVATE_MASK       15
                                         ; values
%assign  FB_ACTIVATE_VBL        16       ; activate values on next vbl
%assign  FB_CHANGE_CMAP_VBL     32       ; change colormap on vbl
%assign  FB_ACTIVATE_ALL        64       ; change all VCs on this fb

%assign  FB_ACCELF_TEXT          1       ; text mode acceleration

%assign  FB_SYNC_HOR_HIGH_ACT    1       ; horizontal sync high active
%assign  FB_SYNC_VERT_HIGH_ACT   2       ; vertical sync high active
%assign  FB_SYNC_EXT             4       ; external sync
%assign  FB_SYNC_COMP_HIGH_ACT   8       ; composite sync high active
%assign  FB_SYNC_BROADCAST       16      ; broadcast video timings
                                         ; vtotal = 144d/288n/576i => PAL
                                         ; vtotal = 121d/242n/484i => NTSC
%assign  FB_SYNC_ON_GREEN        32      ; sync on green

%assign  FB_VMODE_NONINTERLACED  0       ; non interlaced
%assign  FB_VMODE_INTERLACED     1       ; interlaced
%assign  FB_VMODE_DOUBLE         2       ; double scan
%assign  FB_VMODE_MASK           255

%assign  FB_VMODE_YWRAP          256     ; ywrap instead of panning
%assign  FB_VMODE_SMOOTH_XPAN    512     ; smooth xpan possible (internally used)
%assign  FB_VMODE_CONUPDATE      512     ; don't update x/yoffset

struc fb_var_screeninfo
    .xres               resd    1   ; visible resolution
    .yres               resd    1
    .xres_virtual       resd    1   ; virtual resolution
    .yres_virtual       resd    1
    .xoffset            resd    1   ; offset from virtual to visible
    .yoffset            resd    1   ; resolution
    .bits_per_pixel     resd    1   ; guess what
    .grayscale          resd    1   ; != 0 Graylevels instead of colors
    .red_offset         resd    1   ; beginning of bitfield
    .red_length         resd    1   ; length of bitfield
    .red_msb_right      resd    1   ; != 0 : Most significant bit is
    .green_offset       resd    1   ; beginning of bitfield
    .green_length       resd    1   ; length of bitfield
    .green_msb_right    resd    1   ; != 0 : Most significant bit is
    .blue_offset        resd    1   ; beginning of bitfield
    .blue_length        resd    1   ; length of bitfield
    .blue_msb_right     resd    1   ; != 0 : Most significant bit is
    .transp_offset      resd    1   ; beginning of bitfield
    .transp_length      resd    1   ; length of bitfield
    .transp_msb_right   resd    1   ; != 0 : Most significant bit is
    .nonstd             resd    1   ; != 0 Non standard pixel format
    .activate           resd    1   ; see FB_ACTIVATE_*
    .height             resd    1   ; height of picture in mm
    .width              resd    1   ; width of picture in mm
    .accel_flags        resd    1   ; acceleration flags (hints)
    ; Timing: All values in pixclocks, except pixclock (of course)
    .pixclock           resd    1   ; pixel clock in ps (pico seconds)
    .left_margin        resd    1   ; time from sync to picture
    .right_margin       resd    1   ; time from picture to sync
    .upper_margin       resd    1   ; time from sync to picture
    .lower_margin       resd    1
    .hsync_len          resd    1   ; length of horizontal sync
    .vsync_len          resd    1   ; length of vertical sync
    .sync               resd    1   ; see FB_SYNC_*
    .vmode              resd    1   ; see FB_VMODE_*
    .reserved           resd    6   ; Reserved for future compatibility
endstruc

struc fb_cmap
    .start              resd    1   ; First entry
    .len                resd    1   ; Number of entries
    .red                resd    1   ; Red values
    .green              resd    1
    .blue               resd    1
    .transp             resd    1   ; transparency, can be NULL
endstruc

struc fb_con2fbmap
    .console            resd    1;
    .framebuffer        resd    1;
endstruc

; VESA Blanking Levels
%assign  VESA_NO_BLANKING        0
%assign  VESA_VSYNC_SUSPEND      1
%assign  VESA_HSYNC_SUSPEND      2
%assign  VESA_POWERDOWN          3

struc fb_monspecs
    .hfmin              resd    1   ; hfreq lower limit (Hz)
    .hfmax              resd    1   ; hfreq upper limit (Hz)
    .vfmin              resw    1   ; vfreq lower limit (Hz)
    .vfmax              resw    1   ; vfreq upper limit (Hz)
    .dpms               resw    1   ; supports DPMS
endstruc

%assign  FB_VBLANK_VBLANKING     0x001   ; currently in a vertical blank
%assign  FB_VBLANK_HBLANKING     0x002   ; currently in a horizontal blank
%assign  FB_VBLANK_HAVE_VBLANK   0x004   ; vertical blanks can be detected
%assign  FB_VBLANK_HAVE_HBLANK   0x008   ; horizontal blanks can be detected
%assign  FB_VBLANK_HAVE_COUNT    0x010   ; global retrace counter is available
%assign  FB_VBLANK_HAVE_VCOUNT   0x020   ; the vcount field is valid
%assign  FB_VBLANK_HAVE_HCOUNT   0x040   ; the hcount field is valid
%assign  FB_VBLANK_VSYNCING      0x080   ; currently in a vsync
%assign  FB_VBLANK_HAVE_VSYNC    0x100   ; verical syncs can be detected

struc fb_vblank
    .flags              resd    1   ; FB_VBLANK flags
    .count              resd    1   ; counter of retraces since boot
    .vcount             resd    1   ; current scanline position
    .hcount             resd    1   ; current scandot position
    .reserved           resd    4   ; reserved for future compatibility
endstruc

%assign  FBCMD_GET_CURRENTPAR    0xDEAD0005
%assign  FBCMD_SET_CURRENTPAR    0xDEAD8005

; Hardware Cursor

%assign  FBIOGET_FCURSORINFO     0x4607
%assign  FBIOGET_VCURSORINFO     0x4608
%assign  FBIOPUT_VCURSORINFO     0x4609
%assign  FBIOGET_CURSORSTATE     0x460A
%assign  FBIOPUT_CURSORSTATE     0x460B

struc fb_fix_cursorinfo
    .crsr_width         resw    1   ; width and height of the cursor in
    .crsr_height        resw    1   ; pixels (zero if no cursor)
    .crsr_xsize         resw    1   ; cursor size in display pixels
    .crsr_ysize         resw    1
    .crsr_color1        resw    1   ; colormap entry for cursor color1
    .crsr_color2        resw    1   ; colormap entry for cursor color2
endstruc

struc fb_var_cursorinfo
    .width              resw    1
    .height             resw    1
    .xspot              resw    1
    .yspot              resw    1
    .data               resb    1   ; field with [height][width]
endstruc

struc fb_cursorstate
    .xoffset            resw    1
    .yoffset            resw    1
    .mode               resw    1
endstruc

%assign  FB_CURSOR_OFF           0
%assign  FB_CURSOR_ON            1
%assign  FB_CURSOR_FLASH         2

%endif


次にフレームバッファをメモリにマッピングする mmap システムコールを使用できるように 次のファイルを準備します

;=========================================================================
; file : mman.inc
; 2001/01/08
; derived from  : linux-2.4.0-test12/include/asm-i386/mman.h
;=========================================================================

%ifndef __MMAN_H__
%define __MMAN_H__

%assign     PROT_READ       0x1     ; page can be read
%assign     PROT_WRITE      0x2     ; page can be written
%assign     PROT_EXEC       0x4     ; page can be executed
%assign     PROT_NONE       0x0     ; page can not be accessed

%assign     MAP_SHARED      0x01    ; Share changes
%assign     MAP_PRIVATE     0x02    ; Changes are private
%assign     MAP_TYPE        0x0f    ; Mask for type of mapping
%assign     MAP_FIXED       0x10    ; Interpret addr exactly
%assign     MAP_ANONYMOUS   0x20    ; don't use a file

%assign     MAP_GROWSDOWN   0x0100  ; stack-like segment
%assign     MAP_DENYWRITE   0x0800  ; ETXTBSY
%assign     MAP_EXECUTABLE  0x1000  ; mark it as an executable
%assign     MAP_LOCKED      0x2000  ; pages are locked
%assign     MAP_NORESERVE   0x4000  ; don't check for reservations

%assign     MS_ASYNC        1       ; sync memory asynchronously
%assign     MS_INVALIDATE   2       ; invalidate the caches
%assign     MS_SYNC         4       ; synchronous memory sync

%assign     MCL_CURRENT     1       ; lock all current mappings
%assign     MCL_FUTURE      2       ; lock all future mappings

%assign     MADV_NORMAL     0x0     ; default page-in behavior
%assign     MADV_RANDOM     0x1     ; page-in minimum required
%assign     MADV_SEQUENTIAL 0x2     ; read-ahead aggressively
%assign     MADV_WILLNEED   0x3     ; pre-fault pages
%assign     MADV_DONTNEED   0x4     ; discard these pages

; compatibility flags
%assign     MAP_ANON    MAP_ANONYMOUS
%assign     MAP_FILE    0

; from linux/arch/i386/kernel/sys_i386.c

struc mmap_arg_struct
    .addr       resd    1;
    .len        resd    1;
    .prot       resd    1;
    .flags      resd    1;
    .fd         resd    1;
    .offset     resd    1;
endstruc

%endif


フレームバッファ用ライブラリ

フレームバッファを使う上で必要となる決まった操作をサブルーチンとして用意しておきます. フレームバッファのオープン, クローズ,設定の変更と復帰などです.

;-------------------------------------------------------------------------
;  file : fblib.inc
;  2001/02/22
;  Copyright (C) 2001  Jun Mizutani <mizutani.jun@nifty.ne.jp>
;-------------------------------------------------------------------------

%include    "fb.inc"
%include    "mman.inc"

%assign O_RDWR               02q

;==============================================================
section .text

;-------------------------------------------------------------------------
; フレームバッファのデバイスファイルをオープン
;-------------------------------------------------------------------------
fbdev_open:
                mov     eax, SYS_open       ; /dev/fb0 のオープン
                mov     ebx, fb_device
                mov     ecx, O_RDWR
                int     0x80
                mov     [fb_desc], eax      ; /dev/fb0 の fd を保存
                mov     [mmap_arg.fd], eax
                test    eax, eax
                ret
fb_device       db      "/dev/fb0", 0

;-------------------------------------------------------------------------
; フレームバッファのデバイスファイルをクローズ
;-------------------------------------------------------------------------
fbdev_close:
                mov     eax, SYS_close       ; /dev/fb0
                mov     ebx, [fb_desc]
                int     0x80
                ret

;-------------------------------------------------------------------------
; フレームバッファの物理状態を取得
;-------------------------------------------------------------------------
fb_get_fscreen:
                mov     eax, SYS_ioctl
                mov     ebx, [fb_desc]
                mov     ecx, FBIOGET_FSCREENINFO
                mov     edx, fscinfo        ; 保存先指定
                int     0x80
                test    eax, eax
                ret

;-------------------------------------------------------------------------
; 現在のフレームバッファの状態を保存
;-------------------------------------------------------------------------
fb_get_screen:
                mov     eax, SYS_ioctl
                mov     ebx, [fb_desc]
                mov     ecx, FBIOGET_VSCREENINFO
                mov     edx, scinfo_save    ; 保存先指定
                int     0x80
                test    eax, eax
                ret

;-------------------------------------------------------------------------
; フレームバッファ設定を書きこむ
;-------------------------------------------------------------------------
fb_set_screen:
                mov     eax, SYS_ioctl
                mov     ebx, [fb_desc]
                mov     ecx, FBIOPUT_VSCREENINFO
                mov     edx, scinfo_data    ; 設定済みデータ
                int     0x80
                test    eax, eax
                ret

;-------------------------------------------------------------------------
; 保存済みのフレームバッファ設定を新規設定用にコピー
;-------------------------------------------------------------------------
fb_copy_scinfo:
                push    esi
                push    edi
                mov     esi, scinfo_save    ; 保存済みデータ
                mov     edi, scinfo_data    ; 設定用データ
                mov     ecx, (fb_var_screeninfo_size / 4)
                cld
                rep movsd
                pop     edi
                pop     esi
                ret

;-------------------------------------------------------------------------
; フレームバッファメモリをマッピング
;-------------------------------------------------------------------------
fb_map_screen:
                mov     eax, [scinfo_data.yres_virtual]
                mul     dword [scinfo_data.xres_virtual]
                mov     ebx, [scinfo_data.bits_per_pixel]
                shr     ebx, 3
                mul     ebx
                mov     [mmap_arg.len], eax
                mov     dword[mmap_arg.prot], (PROT_READ | PROT_WRITE)
                mov     dword[mmap_arg.flags], MAP_SHARED
                xor     eax, eax
                mov     [mmap_arg.addr], eax
                mov     [mmap_arg.offset], eax
                mov     eax, SYS_mmap
                mov     ebx, mmap_arg
                int     0x80
                test    eax, eax
                ret

;-------------------------------------------------------------------------
; フレームバッファメモリをアンマップ
;-------------------------------------------------------------------------
fb_unmap_screen:
                mov     eax, SYS_munmap
                mov     ebx, [mmap_arg.addr]
                mov     ecx, [mmap_arg.len]
                int     0x80
                test    eax, eax
                ret

;-------------------------------------------------------------------------
; カラーマップ(パレット)を取得
;-------------------------------------------------------------------------
fb_get_colormap:
                mov     eax, SYS_ioctl
                mov     ebx, [fb_desc]
                mov     ecx, FBIOGETCMAP
                mov     edx, colormap_save
                int     0x80
                test    eax, eax
                ret

;-------------------------------------------------------------------------
; カラーマップ(パレット)を設定
;-------------------------------------------------------------------------
fb_set_colormap:
                mov     eax, SYS_ioctl
                mov     ebx, [fb_desc]
                mov     ecx, FBIOPUTCMAP
                mov     edx, colormap_data
                int     0x80
                ret

;-------------------------------------------------------------------------
; カラーマップ(パレット)を作成
;-------------------------------------------------------------------------
fb_test_colormap:
                push    edi
                xor     eax, eax
                mov     eax, 0xffff
                mov     edi, red_data
                mov     ecx, 0x100
    .loop:
                mov     [edi], ax
                mov     [edi+0x200], ax
                mov     [edi+0x400], ax
                sub     eax, 0x01
                inc     edi
                loop    .loop
                pop     edi
                ret

;-------------------------------------------------------------------------
; 保存済みのフレームバッファ設定を復帰
;-------------------------------------------------------------------------
fb_restore_sc:
                mov     eax, SYS_ioctl
                mov     ebx, [fb_desc]
                mov     ecx, FBIOPUT_VSCREENINFO
                mov     edx, scinfo_save
                int     0x80
                ret

;-------------------------------------------------------------------------
; 保存済みのカラーマップ(パレット)を復帰
;-------------------------------------------------------------------------
fb_restore_cmap:
                mov     eax, SYS_ioctl
                mov     ebx, [fb_desc]
                mov     ecx, FBIOPUTCMAP
                mov     edx, colormap_save
                int     0x80
                ret

;==============================================================
section .data

                align   4
colormap_save istruc fb_cmap
    .start      dd    0           ; First entry
    .len        dd    0x100       ; Number of entries (256)
    .red        dd    red_save
    .green      dd    green_save
    .blue       dd    blue_save
    .transp     dd    0           ; transparency, can be NULL
iend

colormap_data istruc fb_cmap
    .start      dd    0           ; First entry
    .len        dd    0x100       ; Number of entries
    .red        dd    red_data
    .green      dd    green_data
    .blue       dd    blue_data
    .transp     dd    0           ; transparency, can be NULL
iend

;==============================================================
section .bss
                        alignb   4

fb_desc:                resd    1
fb_address:             resd    1

red_save:               resw    0x100
green_save:             resw    0x100
blue_save:              resw    0x100

red_data:               resw    0x100
green_data:             resw    0x100
blue_data:              resw    0x100

mmap_arg istruc mmap_arg_struct
    .addr       resd    1;
    .len        resd    1;
    .prot       resd    1;
    .flags      resd    1;
    .fd         resd    1;
    .offset     resd    1;
iend

                        alignb   4
scinfo_save:       istruc fb_var_screeninfo
    .xres               resd    1   ; visible resolution
    .yres               resd    1
    .xres_virtual       resd    1   ; virtual resolution
    .yres_virtual       resd    1
    .xoffset            resd    1   ; offset from virtual to visible
    .yoffset            resd    1   ; resolution
    .bits_per_pixel     resd    1   ; guess what
    .grayscale          resd    1   ; != 0 Graylevels instead of colors
    .red_offset         resd    1   ; beginning of bitfield
    .red_length         resd    1   ; length of bitfield
    .red_msb_right      resd    1   ; != 0 : Most significant bit is
    .green_offset       resd    1   ; beginning of bitfield
    .green_length       resd    1   ; length of bitfield
    .green_msb_right    resd    1   ; != 0 : Most significant bit is
    .blue_offset        resd    1   ; beginning of bitfield
    .blue_length        resd    1   ; length of bitfield
    .blue_msb_right     resd    1   ; != 0 : Most significant bit is
    .transp_offset      resd    1   ; beginning of bitfield
    .transp_length      resd    1   ; length of bitfield
    .transp_msb_right   resd    1   ; != 0 : Most significant bit is
    .nonstd             resd    1   ; != 0 Non standard pixel format
    .activate           resd    1   ; see FB_ACTIVATE_*
    .height             resd    1   ; height of picture in mm
    .width              resd    1   ; width of picture in mm
    .accel_flags        resd    1   ; acceleration flags (hints)
    .pixclock           resd    1   ; pixel clock in ps (pico seconds)
    .left_margin        resd    1   ; time from sync to picture
    .right_margin       resd    1   ; time from picture to sync
    .upper_margin       resd    1   ; time from sync to picture
    .lower_margin       resd    1
    .hsync_len          resd    1   ; length of horizontal sync
    .vsync_len          resd    1   ; length of vertical sync
    .sync               resd    1   ; see FB_SYNC_*
    .vmode              resd    1   ; see FB_VMODE_*
    .reserved           resd    6   ; Reserved for future compatibility
iend

                        alignb   4
scinfo_data:       istruc fb_var_screeninfo
    .xres               resd    1   ; visible resolution
    .yres               resd    1
    .xres_virtual       resd    1   ; virtual resolution
    .yres_virtual       resd    1
    .xoffset            resd    1   ; offset from virtual to visible
    .yoffset            resd    1   ; resolution
    .bits_per_pixel     resd    1   ; guess what
    .grayscale          resd    1   ; != 0 Graylevels instead of colors
    .red_offset         resd    1   ; beginning of bitfield
    .red_length         resd    1   ; length of bitfield
    .red_msb_right      resd    1   ; != 0 : Most significant bit is
    .green_offset       resd    1   ; beginning of bitfield
    .green_length       resd    1   ; length of bitfield
    .green_msb_right    resd    1   ; != 0 : Most significant bit is
    .blue_offset        resd    1   ; beginning of bitfield
    .blue_length        resd    1   ; length of bitfield
    .blue_msb_right     resd    1   ; != 0 : Most significant bit is
    .transp_offset      resd    1   ; beginning of bitfield
    .transp_length      resd    1   ; length of bitfield
    .transp_msb_right   resd    1   ; != 0 : Most significant bit is
    .nonstd             resd    1   ; != 0 Non standard pixel format
    .activate           resd    1   ; see FB_ACTIVATE_*
    .height             resd    1   ; height of picture in mm
    .width              resd    1   ; width of picture in mm
    .accel_flags        resd    1   ; acceleration flags (hints)
    .pixclock           resd    1   ; pixel clock in ps (pico seconds)
    .left_margin        resd    1   ; time from sync to picture
    .right_margin       resd    1   ; time from picture to sync
    .upper_margin       resd    1   ; time from sync to picture
    .lower_margin       resd    1
    .hsync_len          resd    1   ; length of horizontal sync
    .vsync_len          resd    1   ; length of vertical sync
    .sync               resd    1   ; see FB_SYNC_*
    .vmode              resd    1   ; see FB_VMODE_*
    .reserved           resd    6   ; Reserved for future compatibility
iend

fscinfo             istruc  fb_fix_screeninfo
    .id                 resb   16   ; identification string eg "TT Builtin"
    .smem_start         resd    1   ; Start of frame buffer mem
                                    ; (physical address)
    .smem_len           resd    1   ; Length of frame buffer mem
    .type               resd    1   ; see FB_TYPE_*
    .type_aux           resd    1   ; Interleave for interleaved Planes
    .visual             resd    1   ; see FB_VISUAL_*
    .xpanstep           resw    1   ; zero if no hardware panning
    .ypanstep           resw    1   ; zero if no hardware panning
    .ywrapstep          resw    1   ; zero if no hardware ywrap
    .padding            resw    1   ;  for alignment, jm 1/26/2001
    .line_length        resd    1   ; length of a line in bytes
    .mmio_start         resd    1   ; Start of Memory Mapped I/O
                                    ; (physical address)
    .mmio_len           resd    1   ; Length of Memory Mapped I/O
    .accel              resd    1   ; Type of acceleration available
    .reserved           resw    3   ; Reserved for future compatibility
iend

各サブルーチンを簡単に解説します.eax, ebx, ecx, edx レジスタは保存されません. 必要ならば呼び出し前に保存してください.edi, esi レジスタは変化しません.

fbdev_open
フレームバッファのデバイスファイルをオープン.最初に呼びます.
fbdev_close
フレームバッファのデバイスファイルをクローズ.最後に呼びます.
fb_get_fscreen
フレームバッファの物理状態を fscinfo に取得します.fscinfo.visual の値で TrueColor(2),PseudoColor(3)を判断することができます.
mode:317の例
Frame Buffer Physical Screen Information
 ID string               : VESA VGA
 frame buffer mem start  : $D6000000
 frame buffer mem length : 4194304
 frame buffer type       : 0
 interleave              : 0
 frame buffer visual     : 2
 x pan step              : 0
 y pan step              : 0
 y wrap step             : 0
 line length (bytes)     : 2048
 Memory Mapped I/O start : 0
 Memory Mapped I/O length: 0
 acceleration type       : 0
fb_get_screen
現在のフレームバッファの状態を scinfo_save に取得します.たとえば  scinfo_save.xres でX方向の解像度を知ることができます.これで取得した値を 使うことで異なる画面モードに対応した描画が可能になります.
mode:317の例
Frame Buffer Virtual Screen Information
 x resolution    : 1024
 y resolution    : 768
 x res virtual   : 1024
 y res virtual   : 768
 x offset        : 0
 y offset        : 0
 bits/pixel      : 16
 grayscale       : 0
 RED    offset   : 11
        length   : 5
        msb_right: 0
 GREEN  offset   : 5
        length   : 6
        msb_right: 0
 BLUE   offset   : 0
        length   : 5
        msb_right: 0
 TRANSP offset   : 0
        length   : 0
        msb_right: 0
 nonstd          : 0
 activate        : 0
 height          : -1
 width           : -1
 accel_flags     : 0
 pixclock        : 12714
 left margin     : 128
 right margin    : 32
 upper margin    : 16
 lower margin    : 4
 hsync length    : 128
 vsync length    : 4
 sync            : 0
 vmode           : 0
fb_copy_scinfo
保存済みのフレームバッファ設定scinfo_save を新規設定用に scinfo_data にコピー. 設定を変更する場合にコピーに変更を加え,オリジナルは復帰用に残しておきます.
fb_set_screen
フレームバッファ設定 scinfo_data を書き込みます.VESA VGA では解像度などを変更 することはできません.RivaTNTなどのチップにネイティブに対応したフレームバッファの場合は 動的に変更することができます.
fb_map_screen
フレームバッファをメモリをマッピングします. マッピングされたメモリの先頭アドレスが eax に返ります.このアドレスから始まるメモリに値を書き込むと画面に表示されるようになります.
fb_unmap_screen
フレームバッファメモリをアンマップ.フレームバッファが不要になったら呼びます.
fb_get_colormap
カラーマップ(パレット)を取得.frame buffer visual が 3 (Pseudo color) の時に使用します.
fb_set_colormap
カラーマップ(パレット)を設定
Pseudo color (256色モード)の時のみ有効です.
fb_test_colormap
カラーマップ(パレット)を作成する場合のサンプル.作成したカラーマップはfb_set_colormapで設定します.
fb_restore_cmap
fb_get_colormap で保存済みのカラーマップ(パレット)を復帰.カラーマップを変更した 場合には終了時に呼び出して元に戻しておきます.

サンプル

fblib.inc を使って実際に画面に何かを表示してみましょう.画面モードは以下のモードの内で ビデオカードがサポートしているモード (317が無難) で起動して下さい.

Colours 640x480 800x600 1024x768 1280x1024 1600x1200
15 bits 310 313 316 319 31D
16 bits 311 314 317 31A 31E
;---------------------------------------------------------------------
;   Frame buffer
;   2001/02/22 Jun Mizutani
;   fbtest.asm
;---------------------------------------------------------------------
%include        "stdio.inc"
%include        "fblib.inc"

%assign O_RDONLY             00q

;==============================================================
section .text
global _start

_start:
        ;-------------------------------------------
        ; フレームバッファの準備
        ;-------------------------------------------
                call    fbdev_open          ; /dev/fb0 をオープン
                js      near .fb_Error
                call    fb_get_screen       ; スクリーン情報を取得
                js      .fb_Error
                call    fb_copy_scinfo      ; scinfo_data を設定
                call    fb_map_screen       ; メモリにマッピング
                js      .fb_Error
                mov     [fb_mem], eax       ; 先頭アドレス
                mov     edi, [fb_mem]
                mov     ebx, [mmap_arg.len] ; サイズ
        ;-------------------------------------------
        ; [edi] から [edi+ebx-1] の範囲に書き込み
        ;-------------------------------------------
                call    OpenRandom
                shr     ebx, 1
                mov     ecx, 10000
    .loop:      call    GetRandom
                xor     edx, edx
                div     ebx
                mov     [edi+edx*2], dx     ; ランダムに点を打つ
                loop    .loop
                call    CloseRandom
                xor     esi, esi
                mov     ecx, ebx
                shr     ecx, 1
    .loop2:     mov     eax, [edi+esi*4]    ; 画面読み出し
                xor     eax, 0x55555555
                mov     [edi+esi*4], eax    ; 画面書き込み
                inc     esi
                loop    .loop2
                xor     esi, esi
                mov     ecx, ebx
                shr     ecx, 1
    .loop3:     mov     eax, [edi+esi*4]    ; 画面読み出し
                xor     eax, 0x55555555
                mov     [edi+esi*4], eax    ; 画面書き込み
                inc     esi
                loop    .loop3
        ;-------------------------------------------
        ; フレームバッファの後始末
        ;-------------------------------------------
    .exit       call    fb_unmap_screen
                call    fbdev_close
                call    Exit
        ;-------------------------------------------

    .fb_Error:
                mov     eax, fberr_msg
                call    OutAsciiZ
                jmp     short .exit

fberr_msg       db 'frabe buffer error!', 10, 0

OpenRandom:     pusha
                mov     ebx, RandomDev
                mov     ecx, O_RDONLY           ; flag
                mov     eax, SYS_open           ; システムコール番号
                mov     edx, 0644q              ; mode
                int     0x80
                mov     [RandomFD], eax
                popa
                ret

GetRandom:      pusha
                push    eax                     ; バッファ確保
                mov     eax, SYS_read           ; システムコール番号
                mov     ebx, [RandomFD]
                mov     ecx, esp
                mov     edx, 3                  ; 読みこみバイト数
                int     0x80
                pop     eax                     ; 結果読み出し
                mov     [esp+28], eax
                popa
                ret

CloseRandom:    push    ebx
                mov     eax, SYS_close
                mov     ebx, [RandomFD]
                int     0x80
                pop     ebx
                ret

RandomDev       db   '/dev/urandom', 0

;==============================================================
section .bss

fb_mem          resd 1
RandomFD        resd 1

乱数を /dev/urandom から取得しているため長くなっていますが,フレームバッファ の初期化と終了処理は15行程度のコードです.乱数の読み出しに時間がかかっているため ランダムに点を打つ部分は速くありません.グラフィックスの描画は 先頭アドレス [fb_mem] から大きさ [mmap_arg.len] の範囲のメモリになんらかの値を 書き込みだけです.