16ビットアセンブリを使用してbmpを表示
(November 18 th,2013に書いてあります)
ゲームは16ビットを使って1つのゲームを書くことが要求されているので、画像を表示できればもっと良いと考え始めました.
256色のビットマップを表示する方法をいろいろ探したが,64 kを超えるデータセグメントの防止は結局使用されなかった.やはり記念に書いておきましょう.
まず、bmpファイルの構造を理解する必要があります.次に、bmp(ビットマップ)構造体について説明します.
1.BMPファイル構成
BMPファイルは、ファイルヘッダ、ビットマップ情報ヘッダ、色情報、グラフィックデータの4つの部分から構成される.
2.BMPファイルヘッダ(14バイト)
BMPヘッダデータ構造には、BMPファイルの種類、ファイルサイズ、ビットマップの開始位置などの情報が含まれている.
構造は次のように定義されます.
3.ビットマップ情報ヘッダ(40バイト)
BMPビットマップ情報ヘッダデータは、ビットマップのサイズ等を説明するための情報である.
4.カラーテーブル
カラーテーブルは、ビットマップのカラーを説明するために使用されます.いくつかのテーブルアイテムがあり、各テーブルアイテムはRGBQUADタイプの構造であり、カラーを定義します.RGBQUAD構造の定義は以下の通りである.
カラーテーブルのRGBQUAD構造データの個数はbiBitCountで決定する:
biBitCount=1,4,8の場合、それぞれ2,16256個のテーブル項目がある.
biBitCount=24の場合、カラーテーブル項目はありません.
ビットマップ情報ヘッダとカラーテーブルはビットマップ情報を構成し、BITMAPINFO構造は以下のように定義される.
5.ビットマップデータ
ビットマップデータは、ビットマップの各画素値を記録し、記録順序は、スキャンライン内で左から右、スキャンライン間で下から上である.ビットマップのピクセル値のバイト数:
biBitCount=1の場合、8画素が1バイトを占める.
biBitCount=4の場合、2画素が1バイトを占める.
biBitCount=8の場合、1画素が1バイトを占める.
biBitCount=24の場合、1画素が3バイトを占める.
Windowsでは、スキャン行のバイト数を指定します.
4の倍数(すなわちlong単位)で、不足しているものは0で充填し、
次のコードは、表示するためにアセンブリされます.
320*200
の
256
カラービットマップの例:
dosboxでの表示効果:
(画像を256色に処理するので、原図に対して少し歪んでいる可能性があります)
ゲームは16ビットを使って1つのゲームを書くことが要求されているので、画像を表示できればもっと良いと考え始めました.
256色のビットマップを表示する方法をいろいろ探したが,64 kを超えるデータセグメントの防止は結局使用されなかった.やはり記念に書いておきましょう.
まず、bmpファイルの構造を理解する必要があります.次に、bmp(ビットマップ)構造体について説明します.
1.BMPファイル構成
BMPファイルは、ファイルヘッダ、ビットマップ情報ヘッダ、色情報、グラフィックデータの4つの部分から構成される.
2.BMPファイルヘッダ(14バイト)
BMPヘッダデータ構造には、BMPファイルの種類、ファイルサイズ、ビットマップの開始位置などの情報が含まれている.
構造は次のように定義されます.
typedef struct tagBITMAPFILEHEADER
{
WORD bfType; // , BM(1-2 )
DWORD bfSize; // , (3-6 )
WORD bfReserved1; // , 0(7-8 )
WORD bfReserved2; // , 0(9-10 )
DWORD bfOffBits; // , (11-14 )
// ,
} BITMAPFILEHEADER;
3.ビットマップ情報ヘッダ(40バイト)
BMPビットマップ情報ヘッダデータは、ビットマップのサイズ等を説明するための情報である.
typedef struct tagBITMAPINFOHEADER{
DWORD biSize; // (15-18 )
LONG biWidth; // , (19-22 )
LONG biHeight; // , (23-26 )
WORD biPlanes; // , 1(27-28 )
WORD biBitCount;// , 1( ),(29-30 )
// 4(16 ),8(256 )16( ) 24( )
DWORD biCompression; // , 0( ),(31-34 )
// 1(BI_RLE8 ) 2(BI_RLE4 )
DWORD biSizeImage; // , (35-38 )
LONG biXPelsPerMeter; // , (39-42 )
LONG biYPelsPerMeter; // , (43-46 )
DWORD biClrUsed;// (47-50 )
DWORD biClrImportant;// (51-54 )
} BITMAPINFOHEADER;
4.カラーテーブル
カラーテーブルは、ビットマップのカラーを説明するために使用されます.いくつかのテーブルアイテムがあり、各テーブルアイテムはRGBQUADタイプの構造であり、カラーを定義します.RGBQUAD構造の定義は以下の通りである.
typedef struct tagRGBQUAD {
BYTE rgbBlue;// ( 0-255)
BYTE rgbGreen; // ( 0-255)
BYTE rgbRed; // ( 0-255)
BYTE rgbReserved;// , 0
} RGBQUAD;
カラーテーブルのRGBQUAD構造データの個数はbiBitCountで決定する:
biBitCount=1,4,8の場合、それぞれ2,16256個のテーブル項目がある.
biBitCount=24の場合、カラーテーブル項目はありません.
ビットマップ情報ヘッダとカラーテーブルはビットマップ情報を構成し、BITMAPINFO構造は以下のように定義される.
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader; //
RGBQUAD bmiColors[1]; //
} BITMAPINFO;
5.ビットマップデータ
ビットマップデータは、ビットマップの各画素値を記録し、記録順序は、スキャンライン内で左から右、スキャンライン間で下から上である.ビットマップのピクセル値のバイト数:
biBitCount=1の場合、8画素が1バイトを占める.
biBitCount=4の場合、2画素が1バイトを占める.
biBitCount=8の場合、1画素が1バイトを占める.
biBitCount=24の場合、1画素が3バイトを占める.
Windowsでは、スキャン行のバイト数を指定します.
4の倍数(すなわちlong単位)で、不足しているものは0で充填し、
biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8) * bi.biHeight;
次のコードは、表示するためにアセンブリされます.
320*200
の
256
カラービットマップの例:
;------------------------------------------------------------------------------------------
;
data segment
pathname db '1.bmp', 00 ;
x0 dw 0
y0 dw 0
handle dw ? ;
bmpdata1 db 256*4 dup(?) ;
bmpdata2 db 64000 dup(0) ;
bmpwidth dw ? ;
bmplength dw ? ;
pelsnum dw ? ; temp num
num dw ?
flag dw ? ; scren set
screnwidth dw 320
screnlength dw 200
data ends
;stack
stack1 segment stack
dw 100h dup(?)
stack1 ends
; code
prognam segment
assume cs:prognam, ds:data, ss:stack1
main proc far
; main part of the program
mov ax, data
mov ds, ax
call openf
call getinfo
call readf
call dispy1
call dispy2
main endp
;---------------------------------------------------
; handle
openf proc near
lea dx, pathname
; ah = 3dh,al = 0 , AX
mov ah, 3dh
mov al, 0
int 21h
mov handle, ax
ret
openf endp
;--------------------------------------------------
;
getinfo proc near
; ,bx = , cx:dx = , al = 0
mov ah, 42h
mov al, 0
mov bx, handle
mov cx, 0
mov dx, 12h ; 18
int 21h
; ,ds:dx = , bx = , cx = , ax = 0
mov ah, 3fh
lea dx, bmpwidth ;
mov cx, 2
int 21h
mov ah, 42h
mov al, 0
mov bx, handle
mov cx, 0
mov dx, 16h ; 22
int 21h
mov ah, 3fh
lea dx, bmplength ;
mov cx, 2
int 21h
mov ax, bmpwidth
mul bmplength
mov pelsnum, ax ; pelsnum
ret
getinfo endp
;---------------------------------------------------
;
readf proc near
; 54
mov ah, 42h
mov al, 0
mov bx, handle
mov cx, 0
mov dx, 36h
int 21h
mov ah, 3fh
lea dx, bmpdata1 ; bmpdata1
mov cx, 256*4 ; + + + (0) 256*4
int 21h
ret
readf endp
;-------------------------------------------------------
;display
dispy1 proc near
; 256 ,320*200
mov ax, 0013h
int 10h
; rgb 256
mov cx, 256
lea si, bmpdata1 ;
p:
mov dx, 3c8h ; i/o
mov ax, cx
dec ax
neg ax ;
add ax, 255 ; ax = ffffh(al = ffh, ah = ffh)
out dx, al ; al dx i/o
inc dx
; bmp :bgr~bgr~...(~ 00h)
; rgb/4 , ,rgb (0~63), (0~255)
mov al, [si+2]
shr al, 1
shr al, 1
out dx, al
mov al, [si+1]
shr al, 1
shr al, 1
out dx, al
mov al, [si]
shr al, 1
shr al, 1
out dx, al
add si, 4
loop p
ret
dispy1 endp
;--------------------------------------------------
dispy2 proc near
mov bx, 0a000h ; 40k
mov es, bx
dp30:
mov di, 0
cld ; df
mov cx, y0 ; cx = 0
dp00:
mov ax, bmpwidth ; ax =
mov dx, ax
and dx, 11b
jz dp000
mov ax, 4
sub ax, dx
add ax, bmpwidth
dp000:
inc cx
mul cx
dec cx
mov bx, 0
sub bx, ax
mov ax, bx
mov bx, 0
sbb bx, dx
mov dx, bx
push cx
mov cx, dx
mov dx, ax
mov bx, handle
mov ax, 4202h
int 21h
mov dx, offset bmpdata2
mov cx, bmpwidth
mov ah, 3fh
int 21h
pop cx
cmp ax, bmpwidth
jb dp3
mov si, offset bmpdata2
add si, x0
dp0:
push di
mov dx, 0
dp1:
lodsb
stosb
inc dx
cmp dx, 320
jae dp2
push dx
add dx, x0
cmp dx, bmpwidth
pop dx
jb dp1
dp2:
pop di
add di, 320
inc cx
push cx
sub cx, y0
cmp cx, 200
pop cx
jae dp3
push cx
cmp cx, bmplength
pop cx
jb dp00
dp3:
mov ah,0
int 16h
cmp ax, 4800h
je up
cmp ax, 4b00h
je left
cmp ax, 4d00h
je right
cmp ax, 5000h
je down
cmp ax, 011bh
je exit
jmp dp3
up:
mov ax, y0
sub ax, 1
jl dp3
mov y0, ax
jmp dp30
down:
mov ax, y0
add ax, 1
push ax
add ax, 200
cmp ax, bmplength
pop ax
jae dp3
mov y0,ax
jmp dp30
left:
mov ax, x0
sub ax, 1
jl dp3
mov x0, ax
jmp dp30
right:
mov ax, x0
add ax, 1
push ax
add ax, 320
cmp ax, bmpwidth
pop ax
jae dp3
mov x0, ax
jmp dp30
exit:
mov ax, 3
int 10h
mov ax, 4c00h
int 21h
xp1:
mov ax, bmplength
mul screnwidth
mov num, ax
lea si, bmpdata2
mov cx, bmpwidth
push cx
mov ax, bmplength
mov flag, ax
dec flag
sub num, 320
mov di, num
add di, 320
add di, bmpwidth
l2:
sub di, 320
sub di, bmpwidth
cmp flag, 0
jz l3
dec flag
pop cx
push cx
dis:
mov al, [si]
mov ah, 0
stosb
add si, 1
cmp cx, 1
jz l2
loop dis
l3:
mov ah, 0
int 16h
mov ax, 3
int 10h
mov ax, 4c00h
int 21h
dispy2 endp
prognam ends
end main
dosboxでの表示効果:
(画像を256色に処理するので、原図に対して少し歪んでいる可能性があります)