{$A+,B-,D-,E+,F+,G+,I-,L-,N+,P-,Q-,R-,S-,T-,V-,X+,Y-} {*-----------------------------------------------*} {| |} {| <<< VGA 13h-mode unit for fast graphics >>> |} {| Written on Borland Pascal 7.0 |} {| and supports real and protected modes. |} {| Version 1.11 p, last update : 20-Dec-97 |} {| Coded by HardBreaker [FleXoft Co.] |} {| alexic@ropnet.ru; 9135@multi-page.cea.ru |} {| Alexic@hotmail.com, #pascal-IRC-EFNet |} {| Special thanks to : Zyklon, [bios], my wife |} {| |} {*-----------------------------------------------*} Unit Graphics; Interface Type { VGA color record } TColor = record R, G, B : byte; end; { VGA palette structures } PVGAPalette = ^TVGAPalette; TVGAPalette = array[0..255] of TColor; { Sprite structures } PSprite = ^TSprite; TSprite = record a, b : word; data : pointer; end; Const { Unit version label } Version = '1.11 p'; { Error codes } VGA_Ok = 0; VGA_NoMemory = -1; VGA_IOError = -2; VGA_NoFile = -3; VGA_BadVersion = -4; VGA_BadFormat = -5; { Workplace area } MinX = 0; MaxX = 319; MinY = 0; MaxY = 199; Var { Pointer to double buffer } { aka virtual or shadow screen } DBuffer : pointer; { Pointer to VGA videobuffer } VBuffer : pointer; {$L vb30.obj} { include 32-bit grapics procedures } { see asm source at the end of file } { -------------------------------------------------------------------------- } Function GetVideoMode:byte; { get current video mode } Procedure SetVideoMode(n:byte); { set video mode } Procedure InitGraphMode; { init 13h graph mode } Procedure DoneGraphMode; { restore old mode } Function InitDoubleBuffer:integer; { allocate double buffer } Procedure DoneDoubleBuffer; { deallocate double buffer } Procedure ShowBuffer32; { copy d-buffer to screen } Procedure ClearDBuffer32; { clear d-buffer fast } Procedure ClearVBuffer32; { clear screen buffer fast } Procedure Retrace; { wait for back trace } { -------------------------------------------------------------------------- } Procedure SetPoint(x,y:integer;c:byte); { fast point to d-buffer } Function GetPoint(x,y:integer):byte; { get point from d-buffer } Procedure SetScreenPoint(x,y:integer;c:byte); { fast point direct to screen} Function GetScreenPoint(x,y:integer):byte; { get point from screen } Procedure SetVLine(x,y1,y2:integer;c:byte); { fast vertical line (db) } Procedure SetHLine(x1,x2,y:integer;c:byte); { fast horizontal line (db) } Procedure SetLine(x1,y1,x2,y2:integer;c:byte); { set line (not so fast) } Procedure SetBox(x1,y1,x2,y2:integer;c:byte); { draw box } Procedure SetRect(x1,y1,x2,y2:integer;c:byte); { draw rectangle } { -------------------------------------------------------------------------- } Procedure SetPaletteColor(c,r,g,b:byte); { set palette color } Procedure GetPaletteColor(c:byte;var r,g,b:byte); { get palette color } Function ColorInPal(var c:byte;r,g,b:byte;p:pointer):boolean; { check color } Function FindColor(var c:byte;r,g,b:byte;p:pointer):integer; { find color } Procedure SetAllPalette(p: pointer); { set all vga palette } Procedure GetAllPalette(p: pointer); { get all vga palette } Procedure FadeIn(n:word;p:pointer); { fading palette in } Procedure FadeOut(n:word); { fading palette out } { -------------------------------------------------------------------------- } Procedure BitBLT_Opaque(x,y:integer; sprite:TSprite); { bit blitting } Procedure BitBLT_Transparent(x,y:integer; sprite:TSprite); { bit blitting } Procedure BitBLT_OpaqueT(x,y:integer; sprite:TSprite); { bit blitting } Procedure BitBLT_TransparentT(x,y:integer; sprite:TSprite); { bit blitting } Procedure Zoom_OpaqueT(zx,zy,za,zb:integer; sprite:TSprite); { zoom opaque } Procedure Zoom_TransparentT(zx,zy,za,zb:integer; sprite:TSprite); { zoom tr. } Procedure GetImage(zx,zy:integer; sprite:TSprite); { } { -------------------------------------------------------------------------- } Function InitSysFont(cb,cf:byte):integer; { load BIOS 1st 128 chars } Procedure DoneSysFont; { unload system font } Procedure TextOut(x,y:integer; st:string); { write to screen/d-buffer } { -------------------------------------------------------------------------- } Function GetVGAErrorMsg(n:integer):string; { get error msg by errnum } { -------------------------------------------------------------------------- } Implementation Uses CRT; Type PFontBuffer = ^TFontBuffer; TFontBuffer = array[0..8191] of byte; Var sysfont : PFontBuffer; { --------------------------------------------------------------------- } Function GetVideoMode; { Job : return current videomode via bios call } { Input : none } { Output : videomode ( byte ) } begin; asm mov ah, $0F int $10 mov @result, al end; end; Procedure SetVideoMode; assembler; { Job : set video mode via bios call } { Input : videomode number ( byte ) } { Output : none } asm xor ah, ah mov al, n int $10 end; Procedure InitGraphMode; assembler; { Job : initiate 13h mode ( 320x200x256 ) } { Input : none } { Output : none } asm mov ax,$0013 int $10 end; Procedure DoneGraphMode; assembler; { Job : reset to 03h text mode ( 80x25 ) } { Input : none } { Output : none } asm mov ax, $0003 int $10 end; Function InitDoubleBuffer; { Job : allocate double buffer 64000 bytes in heap } { Input : none } { Output : operation error code (integer), 0 if no errors } begin if dbuffer = vbuffer then begin if MaxAvail < 64000 then begin InitDoubleBuffer:=VGA_NoMemory; exit; end; getmem(dbuffer,64000); end; InitDoubleBuffer:=VGA_Ok; end; Procedure DoneDoubleBuffer; { Job : deallocate double buffer } { Input : none } { Output : none } begin if dbuffer <> vbuffer then begin freemem(dbuffer,64000); dbuffer:=vbuffer; end; end; Procedure ShowBuffer32; external; { Job : fast copy double buffer to VGA screen memory } { Input : none } { Output : none } Procedure ClearDBuffer32; external; { Job : fast cleaning double buffer } { Input : none } { Output : none } Procedure ClearVBuffer32; external; { Job : fast cleaning VGA screen memory } { Input : none } { Output : none } Procedure Retrace; assembler; { Job : wait for begin retracing CRT } { Input : none } { Output : none } asm mov dx,$3da @wait1: in al,dx and al,8 jnz @wait1 @wait2: in al,dx and al,8 jz @wait2 end; { --------------------------------------------------------------------- } Procedure SetPoint; assembler; { Job : set fast point on screen/double buffer ( with clipping ) } { Input : x, y - coordinates; c - color index } { Output : none } asm mov ax, y { load y to ax } cmp ax, MinY jl @fin cmp ax, MaxY jg @fin mov cx, x { load x to cx } cmp cx, MinX jl @fin cmp cx, MaxX jg @fin les di, dbuffer { loading d-buffer starting address } mov bx, ax { copy y to bx } sal ax, 6 { shift equal mult on 32 } sal bx, 8 { shift equal mult on 256 } add ax, bx { equal mult on 320 (with shifts) } add ax, cx { starting point solved } add di, ax { starting point in es:di now } mov bh, c { load color into bh } mov es:[di], bh { moving color into d-buffer } @fin: end; Function GetPoint; { Job : get point from screen/double buffer ( with clipping ) } { Input : x, y - coordinates } { Output : color index } begin; asm mov ax, y { load y to ax } cmp ax, MinY jl @fin cmp ax, MaxY jg @fin mov cx, x { load x to cx } cmp cx, MinX jl @fin cmp cx, MaxX jg @fin les di, dbuffer { loading d-buffer starting address } mov bx, ax { copy y to bx } sal ax, 6 { shift equal mult on 32 } sal bx, 8 { shift equal mult on 256 } add ax, bx { equal mult on 320 (with shifts) } add ax, cx { starting point solved } add di, ax { starting point in es:di now } mov bh, es:[di] mov @result, bh jmp @ok @fin: mov @result, 0 @ok: end; end; Procedure SetScreenPoint; assembler; { Job : set point direct to screen ( with clipping ) } { Input : x, y - coordinates; c - color index } { Output : none } asm mov ax, y { load y to ax } cmp ax, MinY jl @fin cmp ax, MaxY jg @fin mov cx, x { load x to cx } cmp cx, MinX jl @fin cmp cx, MaxX jg @fin les di, vbuffer { loading screen buffer starting address } mov bx, ax { copy y to bx } sal ax, 6 { shift equal mult on 32 } sal bx, 8 { shift equal mult on 256 } add ax, bx { equal mult on 320 (with shifts) } add ax, cx { starting point solved } add di, ax { starting point in es:di now } mov bh, c { load color into bh } mov es:[di], bh { moving color into d-buffer } @fin: end; Function GetScreenPoint; { Job : get point from VGA screen memory } { Input : x, y - coordinates } { Output : color index } begin; asm mov ax, y { load y to ax } cmp ax, MinY jl @fin cmp ax, MaxX jg @fin mov cx, x { load x to cx } cmp cx, MinX jl @fin cmp cx, MaxX jg @fin les di, vbuffer { loading d-buffer starting address } mov bx, ax { copy y to bx } sal ax, 6 { shift equal mult on 32 } sal bx, 8 { shift equal mult on 256 } add ax, bx { equal mult on 320 (with shifts) } add ax, cx { starting point solved } add di, ax { starting point in es:di now } mov bh, es:[di] { load point from buffer to bh } mov @result, bh { return color into func. result } jmp @ok @fin: mov @result, 0 @ok: end; end; Procedure SetVLine; assembler; { Job : draw vertical line to screen/double buffer ( with clipping ) } { Input : x, y1, y2 - coordinates; c - color index } { Output : none } asm mov cx, x cmp cx, MinX jl @fin cmp cx, MaxX jg @fin mov ax, y1 cmp y2, ax jg @nochange xchg y2, ax mov y1, ax @nochange: mov ax, y1 cmp ax, MaxY jg @fin cmp ax, MinY jge @notopcut mov ax, MinY mov y1, ax @notopcut: mov ax, y2 cmp ax, MinY jl @fin cmp ax, MaxY jle @nobottomcut mov ax, MaxY mov y2, ax @nobottomcut: les di, dbuffer { loading d-buffer starting address } mov ax, y1 { solving starting point } mov bx, ax { copy y1 to bx } sal ax, 6 { shift equal mult on 32 } sal bx, 8 { shift equal mult on 256 } add ax, bx { equal mult on 320 (with shifts) } mov bx, x { load x to bx } add ax, bx { starting point solved } add di, ax { starting point in es:di now } mov cx, y2 { load y2 coordinate to ax } mov bx, y1 { load y1 coordinate to bx } inc cx { correct size of line } sub cx, bx { size of line -1 in ax } mov bh, c { load color into bh } mov ax, 320 { load size of line into cx } @cont: { label for repeat points } mov es:[di], bh { moving color into d-buffer } add di, ax { increment pointer } loop @cont { return if not ready } @fin: end; Procedure SetHLine; assembler; { Job : draw horizontal line to screen/dble buffer ( with clipping ) } { Input : x1, x2, y - coordinates, c - color index } { Output : none } asm mov ax, y cmp ax, MinY jl @fin cmp ax, MaxY jg @fin mov ax, x1 cmp x2, ax jg @nochange xchg x2, ax mov x1, ax @nochange: mov ax, x1 cmp ax, MaxX jg @fin cmp ax, MinX jge @noleftcut mov ax, MinX mov x1, ax @noleftcut: mov ax, x2 cmp ax, MinX jl @fin cmp ax, MaxX jle @norightcut mov ax, MaxX mov x2, ax @norightcut: les di, dbuffer { loading d-buffer starting address } mov ax, y { solving starting point } mov bx, ax { copy y to bx } sal ax, 6 { shift equal mult on 32 } sal bx, 8 { shift equal mult on 256 } add ax, bx { equal mult on 320 (with shifts) } mov bx, x1 { load first x to bx } add ax, bx { starting point solved } add di, ax { starting point in es:di now } mov cx, x2 { load y2 coordinate to ax } inc cx { correct size of line } mov bx, x1 { load y1 coordinate bx } sub cx, bx { size of line -1 in ax } mov bh, c { load color into bh } @cont: { label for repeat point } mov es:[di], bh { moving color into d-buffer } inc di { increment pointer } loop @cont { return if not ready } @fin: end; procedure SetLine; { * needs optimizing * } { Job : draw any line on screen/double buffer } { Input : x1, y1, x2, y2 - coordinates; c - color index } { Output : none } var dx, dy, s, e, i : integer; j, delta : single; begin dx:=x2 - x1; dy:=y2 - y1; if dx = 0 then begin if dy = 0 then begin SetPoint(x1,y1,c); exit; end; if dy > 0 then begin SetVLine(x1,y1,y2,c); exit; end; end; if dy = 0 then begin if dx = 0 then begin SetPoint(x1,y1,c); exit; end; if dx > 0 then begin SetHLine(x1,x2,y1,c); exit; end; end; if abs(dx) > abs(dy) then begin delta:=dy / dx; if dx > 0 then begin j:=y1; s:=x1; e:=x2; end else begin j:=y2; s:=x2; e:=x1; end; for i:=s to e do begin SetPoint(i,round(j),c); j:=j+delta; end; end else begin delta:=dx / dy; if dy > 0 then begin j:=x1; s:=y1; e:=y2; end else begin j:=x2; s:=y2; e:=y1; end; for i:=s to e do begin SetPoint(round(j),i,c); j:=j+delta; end; end; end; Procedure SetBox; { * needs optimizing a bit * } { Job : draw filled box on screen/double buffer } { Input : x1, y1, x2, y2 - coordinates; c - color index } { Output : none } var i, s, e : integer; begin if y1 < y2 then begin s:=y1; e:=y2 end else begin s:=y2; e:=y1; end; for i:=s to e do SetHLine(x1,x2,i,c); end; Procedure SetRect; { * needs optimizing a bit * } { Job : draw rectangle on screen/double buffer } { Input : x1, y1, x2, y2 - coordinates; c - color index } { Output : none } begin SetHLine(x1,x2,y1,c); SetHLine(x1,x2,y2,c); SetVLine(x1,y1,y2,c); SetVLine(x2,y1,y2,c); end; { --------------------------------------------------------------------- } Procedure SetPaletteColor; { Job : set selected color in VGA palette } { Input : c - color index; r, g, b - color components (0..63) } { Output : none } begin port[$3C6]:=$FF; port[$3C8]:=c; port[$3C9]:=r; port[$3C9]:=g; port[$3C9]:=b; end; Procedure GetPaletteColor; { Job : get selected color from VGA palette } { Input : c - color index } { Output : r, g, b - color components (0..63) } begin port[$3C6]:=$FF; port[$3C7]:=c; r:=port[$3C9]; g:=port[$3C9]; b:=port[$3C9]; end; Function ColorInPal; { Job : check color in palette } { Input : r,g,b - color components; p - palette, if NIL - VGA palette } { Output : true if color in palette, in that case c - index in palette } var pal : PVGAPalette; tr, tg, tb : byte; ok, en : boolean; begin c:=0; pal:=p; ok:=false; en:=false; repeat if pal = NIL then begin GetPaletteColor(c,tr,tg,tb); end else begin tr:=pal^[c].r; tg:=pal^[c].g; tb:=pal^[c].b; end; if (r = tr) and (g = tg) and (b = tb) then ok:=true; if (not ok) and (c < 255) then inc(c) else en:=true; until ok or en; ColorInPal:=ok; end; Function FindColor; { Job : find nearest color in palette } { Input : r, g, b - color components; p - palette,if NIL - VGA palette } { Output : deviation } var i, save, tr, tg, tb : byte; dist, d : integer; pal : PVGAPalette; begin dist:=1000; save:=0; pal:=p; for i:=0 to 255 do begin if pal = NIL then begin GetPaletteColor(i,tr,tg,tb); end else begin tr:=pal^[i].r; tg:=pal^[i].g; tb:=pal^[i].b; end; d:=round(sqrt(sqr(tr-r)+sqr(tg-g)+sqr(tb-b))); if d < dist then begin dist:=d; save:=i; end; end; c:=save; end; Procedure SetAllPalette; { Job : set all palette colors from memory buffer } { Input : p - pointer to mem buffer ( 768 bytes of color components ) } { Output : none } var i:byte; pp : PVGAPalette; begin pp:=p; for i:=0 to 255 do begin port[$3C6]:=$FF; port[$3C8]:=i; port[$3C9]:=pp^[i].r; port[$3C9]:=pp^[i].g; port[$3C9]:=pp^[i].b; end; end; Procedure GetAllPalette; { Job : read all VGA palette colors from DAC to memory buffer } { Input : p - pointer to mem buffer ( 768 bytes of color components ) } { Output : none } var i:byte; pp : PVGAPalette; begin pp:=p; for i:=0 to 255 do begin port[$3C6]:=$FF; port[$3C7]:=i; pp^[i].r:=port[$3C9]; pp^[i].g:=port[$3C9]; pp^[i].b:=port[$3C9]; end; end; Procedure FadeIn; { * needs optimizing * } { Job : fading screen palette into new palette } { Input : n - fading speed; p : new palette } { Output : none } var tmp : TVGAPalette; pp : PVGAPalette; i, j : byte; begin pp:=p; for j:=0 to 63 do begin Delay(n); for i:=0 to 255 do begin tmp[i].R:=round((pp^[i].r / 63) * j); tmp[i].G:=round((pp^[i].g / 63) * j); tmp[i].B:=round((pp^[i].b / 63) * j); end; Retrace; SetAllPalette(@tmp); end; end; Procedure FadeOut; { * needs optimizing * } { Job : fading screen out } { Input : n - fading speed } { Output : none } var tmp, base : TVGAPalette; i, j : byte; begin GetAllPalette(@base); for j:=63 downto 0 do begin Delay(n); for i:=0 to 255 do begin tmp[i].R:=round(j * (base[i].R / 63)); tmp[i].G:=round(j * (base[i].G / 63)); tmp[i].B:=round(j * (base[i].B / 63)); end; Retrace; SetAllPalette(@tmp); end; end; { --------------------------------------------------------------------- } Procedure BitBLT_Opaque; { Job : draw sprite to screen/double buffer ( with clipping ) } { Input : x, y - coordinates; sprite - sprite structure } { Output : none } var ra, rb, ox, oy, fx, fy, ch1, ch2 : integer; sz, rz : word; begin asm mov ax, x mov bx, MaxX cmp ax, bx jg @fin mov dx, MinX mov cx, sprite.a add ax, cx cmp ax, dx jle @fin mov ra, cx mov ax, x cmp ax, dx jge @m_zx mov ox, dx sub ox, ax mov fx, dx mov cx, ox sub ra, cx jmp @m_zxe @m_zx: mov ox, 0 mov fx, ax @m_zxe: mov ch1, ax mov bx, sprite.a dec bx add ch1, bx mov cx, MaxX cmp ch1, cx jle @noxdec mov ax, ch1 sub ax, cx sub ra, ax @noxdec: mov ax, y mov bx, MaxY cmp ax, bx jg @fin mov dx, MinY mov cx, sprite.b add ax, cx cmp ax, dx jle @fin mov rb, cx mov ax, y cmp ax, dx jge @m_zy mov oy, dx sub oy, ax mov fy, dx mov cx, oy sub rb, cx jmp @m_zye @m_zy: mov oy, 0 mov fy, ax @m_zye: mov ch2, ax mov bx, sprite.b dec bx add ch2, bx mov cx, MaxY cmp ch2, cx jle @noydec mov ax, ch2 sub ax, cx sub rb, ax @noydec: mov ax, oy mov bx, sprite.a imul bx mov sz, ax mov ax, ra mov bx, rb imul bx mov rz, ax { go draw } push ds les di, dbuffer add di, fx mov ax, fy mov bx, ax sal ax, 6 sal bx, 8 add di, bx add di, ax lds si, sprite.data add si, sz add si, ox mov dx, sprite.a mov bx, ra mov cx, rz @sprite_loop: mov al, ds:[si] mov es:[di], al inc di inc si dec bx cmp bx, 0 jne @nocorr mov bx, ra sub di, bx add di, 320 add si, dx sub si, bx @nocorr: loop @sprite_loop pop ds @fin: end; end; Procedure BitBLT_Transparent; { Job : draw sprite to screen/double buffer with transparency check } { trancparency color = 0 ( with clipping ) } { Input : x, y - coordinates; sprite - sprite structure } { Output : none } var ra, rb, ox, oy, fx, fy, ch1, ch2 : integer; sz, rz : word; begin asm mov ax, x mov bx, MaxX cmp ax, bx jg @fin mov dx, MinX mov cx, sprite.a add ax, cx cmp ax, dx jle @fin mov ra, cx mov ax, x cmp ax, dx jge @m_zx mov ox, dx sub ox, ax mov fx, dx mov cx, ox sub ra, cx jmp @m_zxe @m_zx: mov ox, 0 mov fx, ax @m_zxe: mov ch1, ax mov bx, sprite.a dec bx add ch1, bx mov cx, MaxX cmp ch1, cx jle @noxdec mov ax, ch1 sub ax, cx sub ra, ax @noxdec: mov ax, y mov bx, MaxY cmp ax, bx jg @fin mov dx, MinY mov cx, sprite.b add ax, cx cmp ax, dx jle @fin mov rb, cx mov ax, y cmp ax, dx jge @m_zy mov oy, dx sub oy, ax mov fy, dx mov cx, oy sub rb, cx jmp @m_zye @m_zy: mov oy, 0 mov fy, ax @m_zye: mov ch2, ax mov bx, sprite.b dec bx add ch2, bx mov cx, MaxY cmp ch2, cx jle @noydec mov ax, ch2 sub ax, cx sub rb, ax @noydec: mov ax, oy mov bx, sprite.a imul bx mov sz, ax mov ax, ra mov bx, rb imul bx mov rz, ax { go draw } push ds les di, dbuffer add di, fx mov ax, fy mov bx, ax sal ax, 6 sal bx, 8 add di, bx add di, ax lds si, sprite.data add si, sz add si, ox mov dx, sprite.a mov bx, ra mov cx, rz @sprite_loop: mov al, ds:[si] cmp al, 0 je @skip_transparent mov es:[di], al @skip_transparent: inc di inc si dec bx cmp bx, 0 jne @nocorr mov bx, ra sub di, bx add di, 320 add si, dx sub si, bx @nocorr: loop @sprite_loop pop ds @fin: end; end; Procedure BitBLT_OpaqueT; { Job : draw sprite to screen/double buffer ( w/o clipping ) } { Input : x, y - coordinates; sprite - sprite structure } { Output : none } begin asm push ds { save DS segment } les di, dbuffer { load d-buffer } mov ax, y { load starting y } mov bx, ax { copy starting y } sal ax, 6 { mul to 64 } sal bx, 8 { mul to 256 } add ax, bx { now mul to 320 } mov bx, x { load starting x } add ax, bx { solving starting dest point } add di, ax { dest first point in es:di } lds si, sprite.data { load source point to ds:si } mov bx, sprite.b { load height to bx } mov cx, sprite.a { load width to cx } @cont_next_line: { label for next line } mov cx, sprite.a { load width again } @cont_line: { label for next pixel } mov al, ds:[si] { load source to al } mov [es:di], al { load al to dest } inc si { increment source line } inc di { increment dest line } dec cx { decrement pixel counter } jnz @cont_line { return if line not ready } add di, 320 { add const to next line } sub di, sprite.a { correct to start line } dec bx { decrement lines counter } jnz @cont_next_line { continue if block not ready } pop ds { return ds segment } end; end; Procedure BitBLT_TransparentT; { Job : draw sprite to screen/double buffer with transparency check } { trancparency color = 0 ( w/o clipping ) } { Input : x, y - coordinates; sprite - sprite structure } { Output : none } begin asm push ds { save DS segment } les di, dbuffer { load d-buffer } mov ax, y { load starting y } mov bx, ax { copy starting y } sal ax, 6 { mul to 64 } sal bx, 8 { mul to 256 } add ax, bx { now mul to 320 } mov bx, x { load starting x } add ax, bx { solving starting dest point } add di, ax { dest first point in es:di } lds si, sprite.data { load source point to ds:si } mov bx, sprite.b { load height to bx } mov cx, sprite.a { load width to cx } @cont_next_line: { label for next line } mov cx, sprite.a { load width again } @cont_line: { label for next pixel } mov al, ds:[si] { load source to al } cmp al, 0 { compare with transparent } je @skip_transparent { skip if transparent } mov [es:di], al { load al to dest } @skip_transparent: { label for skipping } inc si { increment source line } inc di { increment dest line } dec cx { decrement pixel counter } jnz @cont_line { return if line not ready } add di, 320 { add const to next line } sub di, sprite.a { correct to start line } dec bx { decrement lines counter } jnz @cont_next_line { continue if block not ready } pop ds { return ds segment } end; end; procedure Zoom_OpaqueT; { * needs addon clipping * } { Job : moving sprite into screen with zooming ( w/o clipping ) } { max sprite size for correct zooming - 255x255 } { Input : zx, zy, za, zb - position and size of sprite on screen, } { sprite - sprite structure } { Output : none ( visual result :) } var vdx, vdy, soff : word; begin asm push ds { save ds register, will changed } mov ax, 320 { * } sub ax, word ptr za mov word ptr soff, ax { make screen offset } mov ax, word ptr sprite.a { * } mov bx, word ptr za sal ax, 8 xor dx, dx div bx mov word ptr vdx, ax { count increment x factor } mov ax, word ptr sprite.b { * } mov bx, word ptr zb sal ax, 8 xor dx, dx div bx mov word ptr vdy, ax { count increment y factor } les di, dbuffer { * } mov ax, zy mov bx, ax sal ax, 6 sal bx, 8 add ax, bx mov bx, zx add ax, bx add di, ax { es:di points to first screen pixel } lds si, sprite.data { ds:si points to first pixel of sprite } xor dx, dx { reset current row (fixed) counter } mov cx, zb { init counter by column size } @column: push cx { save cx for inner loop } push dx { save dx for inner loop } xor bx, bx { reset bx (row pixel offset) } xor dx, dx { reset row (fixed) counter } mov cx, za { init current pixel in row } @row: mov al, ds:[si][bx] { pick up pixel from sprite } mov es:[di], al { draw pixel into video (or double) buffer } add dx, word ptr vdx { increment pixel in row counter (fixed) } mov bl, dh { modify bx by integer part of current pixel } inc di { increment video (double) buffer offset } loop @row { loop of row drawing } add di, word ptr soff { increment screen (double) buffer offset } pop dx { restore dx for outer loop } pop cx { restore cx for outer loop } mov ah, dh { move dh to ah } add dx, word ptr vdy { increment column counter (fixed) } mov al, dh sub al, ah jz @nonextcol @incy: add si, word ptr sprite.a dec al cmp al, 0 jnz @incy @nonextcol: loop @column pop ds { restore ds register } end; end; procedure Zoom_TransparentT; { * needs addon clipping * } { Job : moving sprite into screen with zooming ( w/o clipping ) } { max sprite size for correct zooming - 255x255 } { Input : zx, zy, za, zb - position and size of sprite on screen, } { sprite - sprite structure } { Output : none ( visual result :) } var vdx, vdy, soff : word; begin asm push ds { save ds register, will changed } mov ax, 320 { * } sub ax, word ptr za mov word ptr soff, ax { make screen offset } mov ax, word ptr sprite.a { * } mov bx, word ptr za sal ax, 8 xor dx, dx div bx mov word ptr vdx, ax { count increment x factor } mov ax, word ptr sprite.b { * } mov bx, word ptr zb sal ax, 8 xor dx, dx div bx mov word ptr vdy, ax { count increment y factor } les di, dbuffer { * } mov ax, zy mov bx, ax sal ax, 6 sal bx, 8 add ax, bx mov bx, zx add ax, bx add di, ax { es:di points to first screen pixel } lds si, sprite.data { ds:si points to first pixel of sprite } xor dx, dx { reset current row (fixed) counter } mov cx, zb { init counter by column size } @column: push cx { save cx for inner loop } push dx { save dx for inner loop } xor bx, bx { reset bx (row pixel offset) } xor dx, dx { reset row (fixed) counter } mov cx, za { init current pixel in row } push bp { save bp (will changed) } mov bp, word ptr vdx { store horiz. increment into bp } @row: mov al, ds:[si][bx] { pick up pixel from sprite } cmp al, 0 { compare pixel with transparent color } je @skip { skip if transparent color } mov es:[di], al { draw pixel into video (or double) buffer } @skip: add dx, bp { increment pixel in row counter (fixed) } mov bl, dh { modify bx by int. part of current pixel } inc di { increment video (double) buffer offset } loop @row { loop of row drawing } pop bp { restore bp register } add di, word ptr soff { increment screen (double) buffer offset } pop dx { restore dx for outer loop } pop cx { restore cx for outer loop } mov ah, dh { move dh to ah } add dx, word ptr vdy { increment column counter (fixed) } mov al, dh sub al, ah jz @nonextcol mov bx, word ptr sprite.a @incy: add si, bx dec al cmp al, 0 jnz @incy @nonextcol: loop @column pop ds { restore ds register } end; end; procedure GetImage; { * needs optimizing * } { Job : moving screen/dbl buffer image to sprite structure } { Input : zx, zy - position image on screen } { sprite - sprite structure, filled with a, b sprite size } { and allocated memory for sprite ( getmem(data, a * b) ) } { Output : none } type tm = array[0..64000] of byte; var i, j : integer; m : ^tm; begin m:=sprite.data; for i:=zx to zx+sprite.a-1 do begin for j:=zy to zy+sprite.b-1 do begin m^[(i-zx)+(j-zy)*sprite.a]:=GetPoint(i,j); end; end; end; { ------------------------------------------------------------------------ } Function InitSysFont; { Job : allocate buffer and fill it with char bitmaps } { here using copy of BIOS standart first 128 ASCII chars } { Input : cb, cf - colors of background and foreground of chars } { Output : error code, 0 if Ok } const fs : array[0..1023] of byte = ( 0, 0, 0, 0, 0, 0, 0, 0,126,129,165,129,189,153,129,126, 126,255,219,255,195,231,255,126,108,254,254,254,124, 56, 16, 0, 16, 56,124,254,124, 56, 16, 0, 56,124, 56,254,254,124, 56,124, 16, 16, 56,124,254,124, 56,124, 0, 0, 24, 60, 60, 24, 0, 0, 255,255,231,195,195,231,255,255, 0, 60,102, 66, 66,102, 60, 0, 255,195,153,189,189,153,195,255, 15, 7, 15,125,204,204,204,120, 60,102,102,102, 60, 24,126, 24, 63, 51, 63, 48, 48,112,240,224, 127, 99,127, 99, 99,103,230,192,153, 90, 60,231,231, 60, 90,153, 128,224,248,254,248,224,128, 0, 2, 14, 62,254, 62, 14, 2, 0, 24, 60,126, 24, 24,126, 60, 24,102,102,102,102,102, 0,102, 0, 127,219,219,123, 27, 27, 27, 0, 62, 99, 56,108,108, 56,204,120, 0, 0, 0, 0,126,126,126, 0, 24, 60,126, 24,126, 60, 24,255, 24, 60,126, 24, 24, 24, 24, 0, 24, 24, 24, 24,126, 60, 24, 0, 0, 24, 12,254, 12, 24, 0, 0, 0, 48, 96,254, 96, 48, 0, 0, 0, 0,192,192,192,254, 0, 0, 0, 36,102,255,102, 36, 0, 0, 0, 24, 60,126,255,255, 0, 0, 0,255,255,126, 60, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48,120,120,120, 48, 0, 48, 0, 108,108,108, 0, 0, 0, 0, 0,108,108,254,108,254,108,108, 0, 48,124,192,120, 12,248, 48, 0, 0,198,204, 24, 48,102,198, 0, 56,108, 56,118,220,204,118, 0, 96, 96,192, 0, 0, 0, 0, 0, 24, 48, 96, 96, 96, 48, 24, 0, 96, 48, 24, 24, 24, 48, 96, 0, 0,102, 60,255, 60,102, 0, 0, 0, 48, 48,252, 48, 48, 0, 0, 0, 0, 0, 0, 0, 48, 48, 96, 0, 0, 0,252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 0, 6, 12, 24, 48, 96,192,128, 0, 124,198,206,222,246,230,124, 0, 48,112, 48, 48, 48, 48,252, 0, 120,204, 12, 56, 96,204,252, 0,120,204, 12, 56, 12,204,120, 0, 28, 60,108,204,254, 12, 30, 0,252,192,248, 12, 12,204,120, 0, 56, 96,192,248,204,204,120, 0,252,204, 12, 24, 48, 48, 48, 0, 120,204,204,120,204,204,120, 0,120,204,204,124, 12, 24,112, 0, 0, 48, 48, 0, 0, 48, 48, 0, 0, 48, 48, 0, 0, 48, 48, 96, 24, 48, 96,192, 96, 48, 24, 0, 0, 0,252, 0, 0,252, 0, 0, 96, 48, 24, 12, 24, 48, 96, 0,120,204, 12, 24, 48, 0, 48, 0, 124,198,222,222,222,192,120, 0, 48,120,204,204,252,204,204, 0, 252,102,102,124,102,102,252, 0, 60,102,192,192,192,102, 60, 0, 248,108,102,102,102,108,248, 0,126, 96, 96,120, 96, 96,126, 0, 126, 96, 96,120, 96, 96, 96, 0, 60,102,192,192,206,102, 62, 0, 204,204,204,252,204,204,204, 0,120, 48, 48, 48, 48, 48,120, 0, 30, 12, 12, 12,204,204,120, 0,230,102,108,120,108,102,230, 0, 96, 96, 96, 96, 96, 96,126, 0,198,238,254,254,214,198,198, 0, 198,230,246,222,206,198,198, 0, 56,108,198,198,198,108, 56, 0, 252,102,102,124, 96, 96,240, 0,120,204,204,204,220,120, 28, 0, 252,102,102,124,108,102,230, 0,120,204,224,112, 28,204,120, 0, 252, 48, 48, 48, 48, 48, 48, 0,204,204,204,204,204,204,252, 0, 204,204,204,204,204,120, 48, 0,198,198,198,214,254,238,198, 0, 198,198,108, 56, 56,108,198, 0,204,204,204,120, 48, 48,120, 0, 254, 6, 12, 24, 48, 96,254, 0,120, 96, 96, 96, 96, 96,120, 0, 192, 96, 48, 24, 12, 6, 2, 0,120, 24, 24, 24, 24, 24,120, 0, 16, 56,108,198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 48, 48, 24, 0, 0, 0, 0, 0, 0, 0,120, 12,124,204,118, 0, 224, 96, 96,124,102,102,220, 0, 0, 0,120,204,192,204,120, 0, 28, 12, 12,124,204,204,118, 0, 0, 0,120,204,252,192,120, 0, 56,108, 96,240, 96, 96,240, 0, 0, 0,118,204,204,124, 12,248, 224, 96,108,118,102,102,230, 0, 48, 0,112, 48, 48, 48,120, 0, 12, 0, 12, 12, 12,204,204,120,224, 96,102,108,120,108,230, 0, 112, 48, 48, 48, 48, 48,120, 0, 0, 0,204,254,254,214,198, 0, 0, 0,248,204,204,204,204, 0, 0, 0,120,204,204,204,120, 0, 0, 0,220,102,102,124, 96,240, 0, 0,118,204,204,124, 12, 30, 0, 0,220,118,102, 96,240, 0, 0, 0,124,192,120, 12,248, 0, 16, 48,124, 48, 48, 52, 24, 0, 0, 0,204,204,204,204,118, 0, 0, 0,204,204,204,120, 48, 0, 0, 0,198,214,254,254,108, 0, 0, 0,198,108, 56,108,198, 0, 0, 0,204,204,204,124, 12,248, 0, 0,252,152, 48,100,252, 0, 28, 48, 48,224, 48, 48, 28, 0, 24, 24, 24, 0, 24, 24, 24, 0,224, 48, 48, 28, 48, 48,224, 0, 118,220, 0, 0, 0, 0, 0, 0, 0, 16, 56,108,198,198,254, 0); var i,j,k,v : byte; begin if sysfont <> NIL then exit; if maxavail < sizeof(TFontBuffer) then begin InitSysFont:=VGA_NoMemory; exit; end; new(sysfont); for i:=0 to 127 do begin { symbol count } for j:=0 to 7 do begin { byte count(line) } for k:=0 to 7 do begin { bit count(column) } {v:=($80 shr k) and (mem[$F000:$FA6E+i*8+j]);} v:=($80 shr k) and fs[i*8+j]; if v > 0 then sysfont^[i*64+j*8+k]:=cf else sysfont^[i*64+j*8+k]:=cb; end; end; end; InitSysFont:=VGA_Ok; end; Procedure DoneSysFont; { Job : deallocate system bitmap font buffer } { Input : none } { Output : none } begin if sysfont = NIL then exit; dispose(sysfont); sysfont:=NIL; end; Procedure TextOut; { * needs addon clipping * } { Job : writing string out to screen/dble-buffer ( without cliping ) } { Input : x, y - position of left top corner of string; st - string } { Output : none } var size : word; lineptr : pointer; begin if sysfont = NIL then begin exit; end; size:=length(st); if size = 0 then exit; lineptr:=addr(st); asm push ds les di, dbuffer mov ax, y mov bx, ax { copy y to bx } sal ax, 6 { shift equal mult on 32 } sal bx, 8 { shift equal mult on 256 } add ax, bx { equal mult on 320 (with shifts) } mov bx, x add ax, bx add di, ax { es:di - screen position } lds si, sysfont mov dx, 1 { current char } mov cx, size @char: push es push di les di, lineptr add di, dx inc dx xor ax, ax mov al, es:[di] and al, $7F sal ax, 6 mov bx, ax pop di pop es push cx mov cx, 8 @col: push cx mov cx, 8 @row: mov al, ds:[si+bx] { ds:si points to 64 bytes of char in font } cmp al, 0 jz @skip_transparent mov es:[di], al @skip_transparent: inc si inc di loop @row pop cx add di, 312 loop @col sub di, 2552 sub si, 64 pop cx loop @char pop ds end; end; { --------------------------------------------------------------------- } Function GetVGAErrorMsg(n:integer):string; { Job : return text message of VGA error } { Input : n - error code } { Output : string with error message } var msg : string; begin case n of VGA_Ok : msg:='No errors'; VGA_NoMemory : msg:='Out of memory'; VGA_IOError : msg:='IO error'; VGA_NoFile : msg:='File not exists'; VGA_BadVersion : msg:='Version unsupported'; VGA_BadFormat : msg:='Incorrect file format'; else msg:='Undefined error'; end; GetVGAErrorMsg:=msg; end; Begin sysfont:=NIL; {$IFDEF DPMI} dbuffer:=ptr(SegA000,$0000); vbuffer:=ptr(SegA000,$0000); {$ELSE} dbuffer:=ptr($A000,$0000); vbuffer:=ptr($A000,$0000); {$ENDIF} End. { ---x---x---x---x---x---x---x--- Cut here ---x---x---x---x---x---x---x--- } { Move that part into VB30.ASM and assemble it with TASM } .MODEL MEDIUM EXTRN vbuffer:DWORD EXTRN dbuffer:DWORD PUBLIC ClearDBuffer32 PUBLIC ClearVBuffer32 PUBLIC ShowBuffer32 .CODE .386 ClearDBuffer32 PROC FAR cld les di, dbuffer mov cx, 16000 xor eax, eax rep stosd ret ClearDBuffer32 ENDP ClearVBuffer32 PROC FAR cld les di, vbuffer mov cx, 16000 xor eax, eax rep stosd ret ClearVBuffer32 ENDP ShowBuffer32 PROC FAR push ds cld les di, vbuffer lds si, dbuffer mov cx, 16000 rep movsd pop ds ret ShowBuffer32 ENDP END { End of VB30.ASM file } { ---x---x---x---x---x---x---x--- Cut here ---x---x---x---x---x---x---x--- } { there are 8x8 chars, image from BIOS first 128 chars } { every char coded by 8 bytes, every bit in byte is point in row } { bits : 7 6 5 4 3 2 1 0 } { byte 0 [#|#|#|#|#|#| | ] = 1111 1100 = $FC = 252 } { byte 1 [ |#|#| | |#|#| ] = 0110 0110 = $66 = 102 } { byte 2 [ |#|#| | |#|#| ] = 0110 0110 = $66 = 102 } { byte 3 [ |#|#|#|#|#| | ] = 0111 1100 = $7C = 124 } { byte 4 [ |#|#| | |#|#| ] = 0110 0110 = $66 = 102 } { byte 5 [ |#|#| | |#|#| ] = 0110 0110 = $66 = 102 } { byte 6 [#|#|#|#|#|#| | ] = 1111 1100 = $FC = 252 } { byte 7 [ | | | | | | | ] = 0000 0000 = $00 = 0 } const fs : array[0..1023] of byte = ( 0, 0, 0, 0, 0, 0, 0, 0,126,129,165,129,189,153,129,126, 126,255,219,255,195,231,255,126,108,254,254,254,124, 56, 16, 0, 16, 56,124,254,124, 56, 16, 0, 56,124, 56,254,254,124, 56,124, 16, 16, 56,124,254,124, 56,124, 0, 0, 24, 60, 60, 24, 0, 0, 255,255,231,195,195,231,255,255, 0, 60,102, 66, 66,102, 60, 0, 255,195,153,189,189,153,195,255, 15, 7, 15,125,204,204,204,120, 60,102,102,102, 60, 24,126, 24, 63, 51, 63, 48, 48,112,240,224, 127, 99,127, 99, 99,103,230,192,153, 90, 60,231,231, 60, 90,153, 128,224,248,254,248,224,128, 0, 2, 14, 62,254, 62, 14, 2, 0, 24, 60,126, 24, 24,126, 60, 24,102,102,102,102,102, 0,102, 0, 127,219,219,123, 27, 27, 27, 0, 62, 99, 56,108,108, 56,204,120, 0, 0, 0, 0,126,126,126, 0, 24, 60,126, 24,126, 60, 24,255, 24, 60,126, 24, 24, 24, 24, 0, 24, 24, 24, 24,126, 60, 24, 0, 0, 24, 12,254, 12, 24, 0, 0, 0, 48, 96,254, 96, 48, 0, 0, 0, 0,192,192,192,254, 0, 0, 0, 36,102,255,102, 36, 0, 0, 0, 24, 60,126,255,255, 0, 0, 0,255,255,126, 60, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48,120,120,120, 48, 0, 48, 0, 108,108,108, 0, 0, 0, 0, 0,108,108,254,108,254,108,108, 0, 48,124,192,120, 12,248, 48, 0, 0,198,204, 24, 48,102,198, 0, 56,108, 56,118,220,204,118, 0, 96, 96,192, 0, 0, 0, 0, 0, 24, 48, 96, 96, 96, 48, 24, 0, 96, 48, 24, 24, 24, 48, 96, 0, 0,102, 60,255, 60,102, 0, 0, 0, 48, 48,252, 48, 48, 0, 0, 0, 0, 0, 0, 0, 48, 48, 96, 0, 0, 0,252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 0, 6, 12, 24, 48, 96,192,128, 0, 124,198,206,222,246,230,124, 0, 48,112, 48, 48, 48, 48,252, 0, 120,204, 12, 56, 96,204,252, 0,120,204, 12, 56, 12,204,120, 0, 28, 60,108,204,254, 12, 30, 0,252,192,248, 12, 12,204,120, 0, 56, 96,192,248,204,204,120, 0,252,204, 12, 24, 48, 48, 48, 0, 120,204,204,120,204,204,120, 0,120,204,204,124, 12, 24,112, 0, 0, 48, 48, 0, 0, 48, 48, 0, 0, 48, 48, 0, 0, 48, 48, 96, 24, 48, 96,192, 96, 48, 24, 0, 0, 0,252, 0, 0,252, 0, 0, 96, 48, 24, 12, 24, 48, 96, 0,120,204, 12, 24, 48, 0, 48, 0, 124,198,222,222,222,192,120, 0, 48,120,204,204,252,204,204, 0, 252,102,102,124,102,102,252, 0, 60,102,192,192,192,102, 60, 0, 248,108,102,102,102,108,248, 0,126, 96, 96,120, 96, 96,126, 0, 126, 96, 96,120, 96, 96, 96, 0, 60,102,192,192,206,102, 62, 0, 204,204,204,252,204,204,204, 0,120, 48, 48, 48, 48, 48,120, 0, 30, 12, 12, 12,204,204,120, 0,230,102,108,120,108,102,230, 0, 96, 96, 96, 96, 96, 96,126, 0,198,238,254,254,214,198,198, 0, 198,230,246,222,206,198,198, 0, 56,108,198,198,198,108, 56, 0, 252,102,102,124, 96, 96,240, 0,120,204,204,204,220,120, 28, 0, 252,102,102,124,108,102,230, 0,120,204,224,112, 28,204,120, 0, 252, 48, 48, 48, 48, 48, 48, 0,204,204,204,204,204,204,252, 0, 204,204,204,204,204,120, 48, 0,198,198,198,214,254,238,198, 0, 198,198,108, 56, 56,108,198, 0,204,204,204,120, 48, 48,120, 0, 254, 6, 12, 24, 48, 96,254, 0,120, 96, 96, 96, 96, 96,120, 0, 192, 96, 48, 24, 12, 6, 2, 0,120, 24, 24, 24, 24, 24,120, 0, 16, 56,108,198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 48, 48, 24, 0, 0, 0, 0, 0, 0, 0,120, 12,124,204,118, 0, 224, 96, 96,124,102,102,220, 0, 0, 0,120,204,192,204,120, 0, 28, 12, 12,124,204,204,118, 0, 0, 0,120,204,252,192,120, 0, 56,108, 96,240, 96, 96,240, 0, 0, 0,118,204,204,124, 12,248, 224, 96,108,118,102,102,230, 0, 48, 0,112, 48, 48, 48,120, 0, 12, 0, 12, 12, 12,204,204,120,224, 96,102,108,120,108,230, 0, 112, 48, 48, 48, 48, 48,120, 0, 0, 0,204,254,254,214,198, 0, 0, 0,248,204,204,204,204, 0, 0, 0,120,204,204,204,120, 0, 0, 0,220,102,102,124, 96,240, 0, 0,118,204,204,124, 12, 30, 0, 0,220,118,102, 96,240, 0, 0, 0,124,192,120, 12,248, 0, 16, 48,124, 48, 48, 52, 24, 0, 0, 0,204,204,204,204,118, 0, 0, 0,204,204,204,120, 48, 0, 0, 0,198,214,254,254,108, 0, 0, 0,198,108, 56,108,198, 0, 0, 0,204,204,204,124, 12,248, 0, 0,252,152, 48,100,252, 0, 28, 48, 48,224, 48, 48, 28, 0, 24, 24, 24, 0, 24, 24, 24, 0,224, 48, 48, 28, 48, 48,224, 0, 118,220, 0, 0, 0, 0, 0, 0, 0, 16, 56,108,198,198,254, 0); { End of char fonts } { ---x---x---x---x---x---x---x--- Cut here ---x---x---x---x---x---x---x--- } { the following contains additional files that should be included with this file. To extract, you need XX3402 available with the SWAG distribution. 1. Cut the text below out, and save to a file .. filename.xx 2. Use XX3402 : xx3402 d filename.xx 3. The decoded file should be created in the same directory. 4. If the file is a archive file, use the proper archive program to extract the members. { ------------------ CUT ----------------------} { ---------------------------- OBJ NEEDED FOR THIS UNIT --------------------- } *XX3402-000335-170197--72--85-61511--------VB30.OBJ--1-OF--1 U+c+05NWAn+iMLBhl6UU++++53FpQa7j623nQqJhMalZQW+UJaJmQqZjPW+n9X8NW-++ECZ1 crcX05NWAn+iMLBh0cU1+21dH7M0++-cW+A+E84IZV++0JN0An-TJ2JMJ+F1HoF3YtU5+2Uk ++61+SCK1++3LoF-J222F23IEQ8M-k-6+++2-E2DZUU+-YF5IYxJI6iO-++4zk7PX-A+-pN0 JIN4FJ6+-oF0JIN4FJ6+FN+J+++-1YBAFI3GF27JFYN3IXAm++++Ud+J+++-1YBAFI3GJY7J FYN3IXAm1k++MN+H+++-13B6HpR0JIN4FJ6nAVs++B86-+-+cU4Fc1E++E++zAEy++0tU1ta Aw1nNej9zAEy++0tU1taAw1nNej95jn2DU++lHM++9a+DjBadFz9StkF+AE1JU922ZM-l07K +QEaJU86WU6++5E+ ***** END OF BLOCK 1 ***** { ---------------------------- ASM MODULE --------------------- } .MODEL MEDIUM EXTRN vbuffer:DWORD EXTRN dbuffer:DWORD PUBLIC ClearDBuffer32 PUBLIC ClearVBuffer32 PUBLIC ShowBuffer32 .CODE .386 ClearDBuffer32 PROC FAR cld les di, dbuffer mov cx, 16000 xor eax, eax rep stosd ret ClearDBuffer32 ENDP ClearVBuffer32 PROC FAR cld les di, vbuffer mov cx, 16000 xor eax, eax rep stosd ret ClearVBuffer32 ENDP ShowBuffer32 PROC FAR push ds cld les di, vbuffer lds si, dbuffer mov cx, 16000 rep movsd pop ds ret ShowBuffer32 ENDP END