;----------------------------------------------------------------------- ; MODULE XCBITMAP ; This module was written by Matthew MacKenzie ; matm@eng.umd.edu ; ; Compiled bitmap functions all MODE X 256 Color resolutions ; ; Compile with Tasm. ; C callable. ; ; ****** XLIB - Mode X graphics library **************** ; ****** **************** ; ****** Written By Themie Gouthas **************** ; ****** Aeronautical Research Laboratory **************** ; ****** Defence Science and Technology Organisation **************** ; ****** Australia **************** ; ; egg@dstos3.dsto.gov.au ; teg@bart.dsto.gov.au ;----------------------------------------------------------------------- include xlib.inc include xcbitmap.inc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; _x_compile_bitmap ; ; Compile a linear bitmap to generate machine code to plot it ; at any required screen coordinates FAST. Faster than blits ; using planar bitmaps as in module XPBIITMAP ; ; C near-callable as: ; int x_compile_bitmap (WORD logical_screen_width, ; char far * bitmap, char far * output); ; ; The logical width is in bytes rather than pixels. ; ; All four main registers are totaled. ; ; The source linear bitmaps have the following structure: ; ; BYTE 0 The bitmap width in pixels range 1..255 ; BYTE 1 The bitmap height in rows range 1..255 ; BYTE 2..n The width*height bytes of the bitmap in ; cloumn row order ; ; The returned value is the size of the compiled bitmap, in bytes. ; accessory macros to save typing (what else?) Emitb macro arg mov byte ptr es:[di],&arg& inc di endm Emitw macro arg mov word ptr es:[di],&arg& add di,2 endm ; opcodes emitted by _x_compile_sprite ROL_AL equ 0c0d0h ; rol al SHORT_STORE_8 equ 044c6h ; mov [si]+disp8, imm8 STORE_8 equ 084c6h ; mov [si]+disp16, imm8 SHORT_STORE_16 equ 044c7h ; mov [si]+disp8, imm16 STORE_16 equ 084c7h ; mov [si]+disp16, imm16 ADC_SI_IMMED equ 0d683h ; adc si,imm8 OUT_AL equ 0eeh ; out dx,al RETURN equ 0cbh ; ret .data align 2 ColumnMask db 011h,022h,044h,088h .code align 2 _x_compile_bitmap proc ARG logical_width:word,bitmap:dword,output:dword LOCAL bwidth,scanx,scany,outputx,outputy,column,set_column,input_size:word=LocalStk push bp mov bp, sp ; caller's stack frame sub sp,LocalStk ; local space push si push di push ds mov word ptr [scanx],0 mov word ptr [scany],0 mov word ptr [outputx],0 mov word ptr [outputy],0 mov word ptr [column],0 mov word ptr [set_column],0 lds si,[bitmap] ; 32-bit pointer to source bitmap les di,[output] ; 32-bit pointer to destination stream lodsb ; load width byte xor ah, ah ; convert to word mov [bwidth], ax ; save for future reference mov bl, al ; copy width byte to bl lodsb ; load height byte -- already a word since ah=0 mul bl ; mult height word by width byte mov [input_size], ax; to get pixel total @@MainLoop: mov bx, [scanx] ; position in original bitmap add bx, [scany] mov al, [si+bx] ; get pixel or al, al ; skip empty pixels jnz @@NoAdvance jmp @@Advance @@NoAdvance: mov dx, [set_column] cmp dx, [column] je @@SameColumn @@ColumnLoop: Emitw ROL_AL ; emit code to move to new column Emitw ADC_SI_IMMED Emitb 0 inc dx cmp dx, [column] jl @@ColumnLoop Emitb OUT_AL ; emit code to set VGA mask for new column mov [set_column], dx @@SameColumn: mov dx, [outputy] ; calculate output position add dx, [outputx] sub dx, 128 add word ptr [scanx], 4 mov cx, [scanx] ; within four pixels of right edge? cmp cx, [bwidth] jge @@OnePixel inc word ptr [outputx] mov ah, [si+bx+4] ; get second pixel or ah, ah jnz @@TwoPixels @@OnePixel: cmp dx, 127 ; can we use shorter form? jg @@OnePixLarge cmp dx, -128 jl @@OnePixLarge Emitw SHORT_STORE_8 Emitb dl ; 8-bit position in output jmp @@EmitOnePixel @@OnePixLarge: Emitw STORE_8 Emitw dx ; position in output @@EmitOnePixel: Emitb al jmp short @@Advance @@TwoPixels: cmp dx, 127 jg @@TwoPixLarge cmp dx, -128 jl @@TwoPixLarge Emitw SHORT_STORE_16 Emitb dl ; 8-bit position in output jmp @@EmitTwoPixels @@TwoPixLarge: Emitw STORE_16 Emitw dx ; position in output @@EmitTwoPixels: Emitw ax @@Advance: inc word ptr [outputx] mov ax, [scanx] add ax, 4 cmp ax, [bwidth] jl @@AdvanceDone mov dx, [outputy] add dx, [logical_width] mov cx, [scany] add cx, [bwidth] cmp cx, [input_size] jl @@NoNewColumn inc word ptr [column] mov cx, [column] cmp cx, 4 je @@Exit ; Column 4: there is no column 4. xor cx, cx ; scany and outputy are 0 again for mov dx, cx ; the new column @@NoNewColumn: mov [outputy], dx mov [scany], cx mov word ptr [outputx], 0 mov ax,[column] @@AdvanceDone: mov [scanx], ax jmp @@MainLoop @@Exit: Emitb RETURN mov ax,di sub ax,word ptr [output] ; size of generated code pop ds pop di pop si mov sp, bp pop bp ret _x_compile_bitmap endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; _x_sizeof_cbitmap ; ; This function follows the same algorithm as the one above, ; but does not generate a new object. Its sole purpose is to ; determine how much space the compiled bitmap will require. ; ; C near-callable as: ; int x_sizeof_cbitmap (WORD logical_screen_width, ; char far * bitmap); ; ; The logical width is in bytes rather than pixels. ; ; All four main registers are totaled. ; ; The source linear bitmaps have the following structure: ; ; BYTE 0 The bitmap width in pixels range 1..255 ; BYTE 1 The bitmap height in rows range 1..255 ; BYTE 2..n The width*height bytes of the bitmap in ; cloumn row order ; ; The returned value is the size of the compiled bitmap, in bytes. align 2 _x_sizeof_cbitmap proc ARG logical_width:word,bitmap:dword LOCAL bwidth,scanx,scany,outputx,outputy,column,set_column,input_size:word=LocalStk push bp mov bp, sp ; caller's stack frame sub sp,LocalStk ; local space push si push di push ds mov word ptr [scanx], 0 mov word ptr [scany], 0 mov word ptr [outputx], 0 mov word ptr [outputy], 0 mov word ptr [column], 0 mov word ptr [set_column], 0 lds si,[bitmap] ; 32-bit pointer to source bitmap mov di, 1 ; initial size is just the size of the far RET lodsb ; load width byte xor ah, ah ; convert to word mov [bwidth], ax ; save for future reference mov bl, al ; copy width byte to bl lodsb ; load height byte -- already a word since ah=0 mul bl ; mult height word by width byte mov [input_size], ax; to get pixel total @@MainLoop: mov bx, [scanx] ; position in original bitmap add bx, [scany] mov al, [si+bx] ; get pixel or al, al ; skip empty pixels jnz @@NoAdvance jmp @@Advance @@NoAdvance: mov dx, [set_column] cmp dx, [column] je @@SameColumn @@ColumnLoop: add di, 5 ; size of code to move to new column inc dx cmp dx,[column] jl @@ColumnLoop inc di ; size of code to set VGA mask mov [set_column], dx @@SameColumn: mov dx, [outputy] ; calculate output position add dx, [outputx] sub dx, 128 add word ptr [scanx], 4 mov cx, [scanx] ; within four pixels of right edge? cmp cx, [bwidth] jge @@OnePixel inc word ptr [outputx] mov ah,[si+bx+4] ; get second pixel or ah, ah jnz @@TwoPixels @@OnePixel: cmp dx, 127 ; can we use shorter form? jg @@OnePixLarge cmp dx, -128 jl @@OnePixLarge add di, 4 ; size of 8-bit position in output plus one pixel jmp @@EmitOnePixel @@OnePixLarge: add di, 5 ; size of position in output plus one pixels @@EmitOnePixel: jmp short @@Advance @@TwoPixels: cmp dx, 127 jg @@TwoPixLarge cmp dx, -128 jl @@TwoPixLarge add di, 5 ; size of 8-bit position in output plus two pixels jmp @@EmitTwoPixels @@TwoPixLarge: add di, 6 ; size of 16-bit position in output plus two pixels @@EmitTwoPixels: @@Advance: inc word ptr [outputx] mov ax, [scanx] add ax,4 cmp ax, [bwidth] jl @@AdvanceDone mov dx, [outputy] add dx, [logical_width] mov cx, [scany] add cx, [bwidth] cmp cx, [input_size] jl @@NoNewColumn inc word ptr [column] mov cx, [column] cmp cx, 4 je @@Exit ; Column 4: there is no column 4. xor cx,cx ; scany and outputy are 0 again for mov dx,cx ; the new column @@NoNewColumn: mov [outputy], dx mov [scany], cx mov word ptr [outputx], 0 mov ax,[column] @@AdvanceDone: mov [scanx], ax jmp @@MainLoop @@Exit: mov ax, di ; size of generated code pop ds pop di pop si mov sp,bp pop bp ret _x_sizeof_cbitmap endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; _x_put_cbitmap ; ; Displays a compiled bitmap generated by x_compile_bitmap at given ; coordinates, on a given screen page. ; ; C near-callable as: ; void x_put_cbitmap (int XPos, int YPos, ; unsigned int PageOffset, char far * Sprite); ; ax, bx, cx, and dx are squashed like insignificant insects. align 2 _x_put_cbitmap proc ARG XPos:word,YPos:word,PageOffset:word,Sprite:dword push bp mov bp, sp push si push ds mov ax, [_ScrnLogicalByteWidth] ; global Xlib variable mul word ptr [YPos] ; height in bytes mov si, [XPos] mov bx, si sar si, 2 ; width in bytes add si, ax add si, [PageOffset]; (YPos * screen width) + add si, 128 ; (Xpos / 4) + page base + 128 ==> starting pos and bx, 3 mov ah, ColumnMask[bx] mov dx, SC_INDEX mov al, MAP_MASK out dx, ax inc dx ; ready to send out other masks as bytes mov al, ah mov bx, SCREEN_SEG mov ds, bx ; We do this so the compiled shape won't need ; segment overrides. call dword ptr [Sprite] ; the business end of the routine pop ds pop si pop bp ret _x_put_cbitmap endp end