2000 ; MCGA grafikrutiner (320x200x256) PUBLIC mcgaInit PUBLIC mcgaExit mcgaPutPixel PROTO C, x:WORD, y:WORD, color:WORD mcgaGetPixel PROTO C, x:WORD, y:WORD mcgaDrawLine PROTO C, x1:WORD, y1:WORD, x2:WORD, y2:WORD, color:WORD mcgaDrawBox PROTO C, x1:WORD, y1:WORD, x2:WORD, y2:WORD, color:WORD mcgaDrawPoly PROTO C, numpoints:WORD, polypoints:DWORD, color:WORD mcgaPutSpriteInv PROTO C, x:WORD, y:WORD, wide:WORD, deep:WORD, sprtseg:WORD, sprtoffs:WORD, destseg:WORD mcgaPutSprite PROTO C, x:WORD, y:WORD, wide:WORD, deep:WORD, sprtseg:WORD, sprtoffs:WORD, destseg:WORD mcgaPutImgInv PROTO C, x:WORD, y:WORD, wide:WORD, deep:WORD, srcseg:WORD, destseg:WORD mcgaPutImg PROTO C,x:WORD, y:WORD, wide:WORD, deep:WORD, srcseg:WORD, destseg:WORD PUBLIC vsync PUBLIC dis_refresh PUBLIC ena_refresh init_mouse PROTO C, max_x:WORD, max_y:WORD, start_x:WORD,start_y:WORD PUBLIC exit_mouse PUBLIC get_mouse_event PUBLIC get_button_status load_iff PROTO C, mode:WORD, fname:PTR BYTE, picseg:VARARG load_pcx PROTO C, mode:WORD, fname:PTR BYTE, picseg:VARARG INCLUDE DOS.INC INCLUDE BIOS.INC .MODEL SMALL, C .386 .DOSSEG .DATA screen dd 0a0000000h .CODE mcgaInit PROC mov ax, 0013h int 10h ret mcgaInit ENDP mcgaExit PROC mov ax, 0003h int 10h ret mcgaExit ENDP ; int mcgaClrScr(int color); mcgaClrScr PROC USES ES DI, color:WORD les di, screen mov ax, color ; Fill EAX with color value mov ah, al ror eax, 16 mov ax, color mov ah, al mov cx, 64000/4 ; Number of dwords rep stosd ; Let's go! ret mcgaClrScr ENDP ; int mcgaClrArea(int x, int y, int w, int h, int color); mcgaClrArea PROC USES ES SI DI, x:WORD, y:WORD, w:WORD, h:WORD, color:WORD mov ax, 320 ; Calculate destination mov dx, w ; offset value to add sub ax, dx ; for each line mov bx, ax ; offset -> BX les di, screen ; Calculate offset mov di, x mov ax, y xchg ah, al ; ax = 256 * y add di, ax ; di = 256 * y + x shr ax, 2 add di, ax ; di = 320 *y + x (+ offset in buffer if needed.) mov ax, color ; Fill EAX with color value mov ah, al ror eax, 16 mov ax, color mov ah, al mov cx, h y_loop: push cx mov cx, w shr cx, 2 ; CX = line length in dwords rep stosd ; move the dwords mov cx, w ; restore CX and cx, 0000000000000011b ; CX = number of residual bytes rep stosb ; move the residual bytes, if any add di, bx ; Add line offset pop cx loop y_loop ret mcgaClrArea ENDP ; int mcgaPutPixel(int x, int y, int color); mcgaPutPixel PROC USES ES DI, x:WORD, y:WORD, color:WORD les di, screen mov di, x mov ax, y xchg ah, al ; ax = 256 * y add di, ax ; di = 256 * y + x shr ax, 2 add di, ax ; di = 320 *y + x (+ offset in buffer if needed.) mov ax, color mov es:[di], al ; Write pixel ret mcgaPutPixel ENDP ; int mcgaGetPixel(int x, int y); mcgaGetPixel PROC USES ES DI, x:WORD, y:WORD les di, screen mov di, x mov ax, y xchg ah, al ; ax = 256 * y add di, ax ; di = 256 * y + x shr ax, 2 add di, ax ; di = 320*y+x (+ offset in buffer if needed.) xor ah, ah mov al, es:[di] ; Return pixel color ret mcgaGetPixel ENDP ;***** ;***** line ;***** ; The following line routine is a modified version of code in Richard ; Wilton's book "Programmer's Guide to PC and PS/2 Video Systems". SCREENSEG EQU 0A000h PIXELADDR MACRO xchg ah,al ; ax=256*y add bx,ax ; bx=256*y+x shr ax,2 add bx,ax ; bx=320*y+x (+ offset in buffer if needed.) mov ax,SCREENSEG mov es,ax ; es:bx=address of pixel ENDM mcgaDrawLine PROC USES CX ES SI DI, x1:WORD, y1:WORD, x2:WORD, y2:WORD, colour:WORD LOCAL VARincr1:WORD, VARincr2:WORD, VARroutine:WORD ; check for vertical lines mov si,320 ; initial y-increment mov cx,x2 sub cx,x1 ; cx=x2-x1 jz vertLine ; force x1 < x2 jns L01 ; jump if x1=0 neg cx ; force dy>=0 mov ax,bx ; ax=y2 L31: inc cx ; cx=# of pixels to draw mov bx,x1 ; bx=x PIXELADDR ; es:bx mov di,bx ; es:di dec si ; si=bytes/line-1 mov ax,colour L32: stosb add di,si ; next line loop L32 jmp Lexit ; routine for horizontal lines (slope=0) horizLine: mov ax,y1 mov bx,x1 PIXELADDR ; es:bx mov di,bx ; es:di mov ax,colour mov ah,al mov bx,ax shl eax,16 mov ax,bx inc cx mov dx,cx shr cx,2 rep stosd mov cx,dx and cx,0000000000000011b rep stosb jmp Lexit ; routine for dy<=dx (slope<=1) ; es:di -> video buffer ; bx=y-increment ; cx =# of pixels to draw ; si=decision variable loSlopeLine: mov ax,colour L11: stosb ; put pixel, increment x or si,si ; test sign of d jns L12 ; jump id d>=0 add si,VARincr1 ; d=d+incr1 loop L11 jmp Lexit L12: add si,VARincr2 ; d=d+incr2 add di,bx ; increment y loop L11 jmp Lexit ; routine for dy>dx (slope >1) ; es:di -> video buffer ; bx=y-increment ; cx=# of pixels to draw ; si=decision variable hiSlopeLine: mov ax,colour L21: stosb ; put pixel, increment x add di,bx ; increment y L22: or si,si ; test sign of d jns L23 ; jump if d>=0 add si,VARincr1 ; d=d+incr1 dec di ; dec x (inc by stosb) loop L21 jmp Lexit L23: add si,VARincr2 ; d=d+incr2 loop L21 Lexit: ret mcgaDrawLine ENDP ; void mcgaDrawBox(int x1, int y1, int x2, int y2, int color); mcgaDrawBox PROC, x1:WORD, y1:WORD, x2:WORD, y2:WORD, color:WORD push color push y1 push x2 push y1 push x1 call mcgaDrawLine add sp, 10 push color push y2 push x2 push y1 push x2 call mcgaDrawLine add sp, 10 push color push y2 push x1 push y2 push x2 call mcgaDrawLine add sp, 10 push color push y1 push x1 push y2 push x1 call mcgaDrawLine add sp, 10 ret mcgaDrawBox ENDP ; void mcgaDrawPoly(int numpoints, int far *polypoints, int color); mcgaDrawPoly PROC USES CX ES DI, numpoints:WORD, polypoints:DWORD, color:WORD les di, polypoints mov cx, numpoints dec cx poly_lp: push color push word ptr es:[di + 6] push word ptr es:[di + 4] push word ptr es:[di + 2] push word ptr es:[di + 0] call mcgaDrawLine add sp, 10 add di, 4 ; x2 -> x1, y2 -> y1 loop poly_lp ret mcgaDrawPoly ENDP ULX = 0 ULY = 0 LRX = 319 LRY = 199 ;***** ;***** Draws a sprite with clipping in "Invisible" mode ;***** Any pixel with col 2000 or value 0 is not written out ;***** parts taken from The Graphics Engine mcgaPutSpriteInv PROC C USES ES SI DI, x:WORD,y:WORD,wide:WORD,deep:WORD,sprtseg:WORD,sprtoffs:WORD,destseg:WORD mov si,sprtoffs mov cx,wide ;xsize mov dx,deep ; ysize mov ax,x cmp ax,LRX ; check x <= VIEWPORTLRX jg quit cmp ax,ULX ; check x >= VIEWPORTULX jl xLessThanMin checkxMax: mov ax,x add ax,cx ; right edge of image cmp ax,LRX jg truncateRightImage ; truncate if necessary checkyMin: mov ax,y cmp ax,LRY ; check y <= OUTVIEWPORTLRY jg quit cmp ax,ULY ; check y >= OUTVIEWPORTULY jl yLessThanMin checkyMax: mov ax,y add ax,dx ; bottom of image cmp ax,LRY jg truncateBottomImage ; truncate if necessary jmp drawImage ; jump to draw logic xLessThanMin: ; clip x to 0 mov bx,ULX mov x,bx sub bx,ax add si,bx sub cx,bx cmp cx,0 jle quit ; quit if offscreen jmp checkxMax quit: ; exit routine ret truncateRightImage: ; truncate the excess of right edge sub ax,LRX ; ax=right edge from before dec ax sub cx,ax jmp checkyMin yLessThanMin: ; clip y to VIEWPORTULY mov bx,ULY mov y,bx sub bx,ax sub dx,bx cmp dx,0 jle quit ; quit if offscreen push dx push cx mov ax,bx mov cx,320 mul cx pop cx pop dx add si,ax jmp checkyMax truncateBottomImage: ; clip y to OUTVIEWPORTLRY sub ax,LRY dec ax sub dx,ax cmp dx,0 ; quit if no lines left jle quit ; fall through to drawImage drawImage: ; label for @@yGreaterThanMax jmp ; calculate the pixel address mov es,destseg mov di,x mov ax,y xchg ah,al ; ax=256*y add di,ax ; di=256*y+x shr ax,2 ; ax=64*y add di,ax ; di=320*y+x push ds mov ds,sprtseg mov ax,320 sub ax,cx ; update destAdd push bp mov bp,ax mov bx,cx xor ch,ch y_lp: mov ax,bx x_lp: mov cl,ds:[si] jcxz skip_palreg0 mov es:[di],cl skip_palreg0: inc si inc di dec ax jnz x_lp add si,bp ;next line add di,bp dec dx jnz y_lp pop bp pop ds ret mcgaPutSpriteInv ENDP ;***** Draws a sprite with clipping in "replace" mode ;***** parts taken from The Graphics Engine ;***** mcgaPutSprite PROC C USES ES SI DI, x:WORD,y:WORD,wide:WORD,deep:WORD,sprtseg:WORD,sprtoffs:WORD,destseg:WORD mov si,sprtoffs mov cx,wide ;xsize mov dx,deep ;ysize mov ax,x cmp ax,LRX ; check x <= VIEWPORTLRX jg quit cmp ax,ULX ; check x >= VIEWPORTULX jl xLessThanMin checkxMax: mov ax,x add ax,cx ; right edge of image cmp ax,LRX jg truncateRightImage ; truncate if necessary checkyMin: mov ax,y cmp ax,LRY ; check y <= OUTVIEWPORTLRY jg quit cmp ax,ULY ; check y >= OUTVIEWPORTULY jl yLessThanMin checkyMax: mov ax,y add ax,dx ; bottom of image cmp ax,LRY jg truncateBottomImage ; truncate if necessary jmp drawImage ; jump to draw logic xLessThanMin: ; clip x to 0 mov bx,ULX mov x,bx sub bx,ax add si,bx sub cx,bx cmp cx,0 jle quit ; quit if offscreen jmp checkxMax quit: ; exit routine ret truncateRightImage: ; truncate the excess of right edge sub ax,LRX ; ax=right edge from before dec ax sub cx,ax jmp checkyMin yLessThanMin: ; clip y to VIEWPORTULY mov bx,ULY mov y,bx sub bx,ax sub dx,bx cmp dx,0 jle quit ; quit if offscreen push dx push cx mov ax,bx mov cx,320 mul cx pop cx pop dx add si,ax jmp checkyMax truncateBottomImage: ; clip y to OUTVIEWPORTLRY sub ax,LRY dec ax sub dx,ax cmp dx,0 ; quit if no lines left jle quit ; fall through to drawImage drawImage: mov es,destseg ; CALCULATE PIXEL ADDRESS mov di,x mov ax,y xchg ah,al ; ax=256*y add di,ax ; di=256*y+x shr ax,2 ; ax=64*y add di,ax ; di=320*y+x push ds mov ds,sprtseg mov ax,320 sub ax,cx ; update destAdd mov bx,cx ; BX = CX jmp LoopA ; jump to loop entry point LoopB: mov cx,bx ; CX = line length in bytes add di,ax ; update DI add si,ax ; and SI LoopA: shr cx,2 ; CX = line length in dwords rep movsd ; move the dwords mov cx,bx ; restore CX and cx,0000000000000011b ; CX = number of residual bytes rep movsb ; move the residual bytes, if any dec dx ; decrement loop counter jnz LoopB ; restart loop if necesary pop ds jmp quit ; done loop, quit mcgaPutSprite ENDP ; mcgaPutImgInv copies an area from one segment to another with the same ; x and y coordinates for src and dest. Invisible mode. mcgaPutImgInv PROC C USES ES SI DI, x:WORD,y:WORD,wide:WORD,deep:WORD,srcseg:WORD,destseg:WORD LOCAL x2:WORD,y2:WORD,dest_x:WORD,dest_y:WORD mov dx,x mov dest_x,dx add dx,wide sub dx,1 mov x2,dx mov dx,y mov dest_y,dx add dx,deep sub dx,1 mov y2,dx ; mov bx,ViewportULX ; preload for speed ; mov cx,ViewportLRX mov ax,x ; clip x1 cmp ax,ULX jge L1b mov x,ULX jmp L2a L1b: cmp ax,LRX jle L2a ret L2a: mov ax,x2 ; clip x2 cmp ax,ULX jge L2b ret L2b: cmp ax,LRX jle L3a mov x2,LRX L3a: ; mov bx,ViewportULY ; preload for speed ; mov cx,ViewportLRY mov ax,y ; clip y1 cmp ax,ULY jge L3b mov y,ULY jmp L4a L3b: cmp ax,LRY jle L4a ret L4a: mov ax,y2 ; clip y2 cmp ax,ULY jge L4b ret L4b: cmp ax,LRY jle L5 mov y2,LRY L5: mov es,destseg mov di,dest_x mov ax,dest_y cmp di,ULX jge destx_ok mov di,ULX destx_ok: cmp ax,ULY jge desty_ok mov ax,ULY desty_ok: ; calculate dest offset xchg ah,al ; ax=256*y add di,ax ; di=256*y+x shr ax,2 ; ax=64*y add di,ax ; di=320*y+x push ds mov ds,srcseg mov ax,x2 ;calculate source width sub ax,x inc ax push ax ;save source width for later mov si,x ;Calculate source offset mov ax,y xchg ah,al ; ax=256*y add si,ax ; si=256*y+x shr ax,2 add si,ax ; si=320*y+x (+ offset in buffer if needed.) mov ax,x2 ; calculate srcAdd sub ax,x mov dx,319 sub dx,ax push dx ; save srcAdd for later mov ax,y2 ; y loop counter sub ax,y mov dx,ax inc dx pop ax ; pop srcAdd pop cx ; pop source width push bp mov bp,ax mov bx,cx xor ch,ch y_lp: mov ax,bx x_lp: mov cl,ds:[si] jcxz skip_palreg0 mov es:[di],cl skip_palreg0: inc si inc di dec ax jnz x_lp add si,bp ;next line add di,bp dec dx jnz y_lp pop bp pop ds ret mcgaPutImgInv ENDP ; mcgaPutImg copies an area from one segment to another with the same ; x and y coordinates for src and dest. Replace mode. mcgaPutImg PROC C USES ES SI DI, x:WORD,y:WORD,wide:WORD,deep:WORD,srcseg:WORD,destseg:WORD LOCAL x2:WORD,y2:WORD,dest_x:WORD,dest_y:WORD mov dx,x mov dest_x,dx add dx,wide sub dx,1 mov x2,dx mov dx,y mov dest_y,dx add dx,deep sub dx,1 mov y2,dx ; mov bx,ViewportULX ; preload for speed ; mov cx,ViewportLRX mov ax,x ; clip x1 cmp ax,ULX jge L1b mov x,ULX jmp L2a 2000 L1b: cmp ax,LRX jle L2a ret L2a: mov ax,x2 ; clip x2 cmp ax,ULX jge L2b ret L2b: cmp ax,LRX jle L3a mov x2,LRX L3a: ; mov bx,ViewportULY ; preload for speed ; mov cx,ViewportLRY mov ax,y ; clip y1 cmp ax,ULY jge L3b mov y,ULY jmp L4a L3b: cmp ax,LRY jle L4a ret L4a: mov ax,y2 ; clip y2 cmp ax,ULY jge L4b ret L4b: cmp ax,LRY jle L5 mov y2,LRY L5: mov es,destseg mov di,dest_x mov ax,dest_y cmp di,ULX jge no_x_adj mov di,ULX no_x_adj: cmp ax,ULY jge no_y_adj mov ax,ULY no_y_adj: ; calculate dest offset xchg ah,al ; ax=256*y add di,ax ; di=256*y+x shr ax,2 ; ax=64*y add di,ax ; di=320*y+x push ds mov ds,srcseg mov ax,x2 ;calculate source width sub ax,x inc ax push ax ;save source width for later mov si,x ;Calculate source offset mov ax,y xchg ah,al ; ax=256*y add si,ax ; si=256*y+x shr ax,2 add si,ax ; si=320*y+x (+ offset in buffer if needed.) mov ax,x2 ; calculate srcAdd sub ax,x mov dx,319 sub dx,ax push dx ; save srcAdd for later mov ax,y2 ; y loop counter sub ax,y mov dx,ax inc dx pop ax ; pop srcAdd pop cx ; pop source width mov bx,cx ; BX = CX jmp LoopB ; jump to loop entry point LoopA: mov cx,bx ; CX = line length in bytes add si,ax ; update SI add di,ax ; update DI LoopB: shr cx,2 ; CX = line length in dwords rep movsd ; move the dwords mov cx,bx ; restore CX and cx,0000000000000011b ; CX = number of residual bytes rep movsb ; move the residual bytes, if any dec dx ; decrement loop counter jnz LoopA ; restart loop if necesary pop ds ret mcgaPutImg ENDP ;============================================================================ ;============================================================================ vsync PROC mov dx,3dah wt1: in al,dx test al,00001000b jnz wt1 wt2: in al,dx test al,00001000b ;wait until bit 4 is 1 jz wt2 ;indicating vertical blank started ret vsync ENDP dis_refresh PROC mov ah,12h mov al,1 mov bl,36h int 10h ret dis_refresh ENDP ena_refresh PROC mov ah,12h mov al,0 mov bl,36h int 10h ret ena_refresh ENDP ;-------------------- musrutiner ------------------------ .DATA PUBLIC mousex PUBLIC mousey mousex dw 0 mousey dw 0 PUBLIC event_flags event_flags dw ? mousefreeze db ? .CODE mousehandler PROC FAR push ax push bx push dx push ds mov bx,@data mov ds,bx cmp byte ptr[mousefreeze],1 jz exit_handler mov mousex,cx ;update mouse coordinates mov mousey,dx mov cx,0 ;clear flags test ax,1 jz not_moved or cx,1 not_moved: test ax,2 ;Check Left button pressed jz not_leftbpress or cx,2 not_leftbpress: test ax,4 ;Check Left button released jz not_leftbrel or cx,4 not_leftbrel: test ax,8 ;Check right button pressed jz not_rightbpress or cx,8 not_rightbpress: test ax,16 ;Check right button released jz exit_handler or cx,16 exit_handler: mov event_flags,cx pop ds pop dx pop bx pop ax retf mousehandler ENDP init_mouse PROC C USES cx dx, max_x:WORD, max_y:WORD, start_x:WORD, start_y:WORD mov ax,0 ;Mouse driver function 0 -- reset and detect int 33h cmp ax,0 jz no_driver_installed mov mousefreeze,1 ;Freeze handler until installation completed mov dx,max_x ;Pixels horizontally mov ax,7 ;mouse driver function 7 -- set max x range mov cx,0 ;Minimum range int 33h mov dx,max_y ;Pixels vertically mov ax,8 ;mouse driver function 8 -- set max y range mov cx,0 ;Minimum range int 33h ; Now install user routine mov ax,cs mov es,ax mov dx, offset mousehandler mov cx,31 ;bits for calling routine mov ax,12 ;Function 12 -- set user routine int 33h mov cx,start_x ;xcoord mov dx,start_y ;ycoord mov ax,4 ;mouse driver function 4 -- set mouse position int 33h mov mousefreeze,0 ;Now the handler can start its work mov ax,1 no_driver_installed: ret init_mouse ENDP get_mouse_event PROC mov ax,event_flags mov event_flags,0 ret get_mouse_event ENDP get_button_status PROC mov ax,3 int 33h mov ax,bx ret get_button_status ENDP exit_mouse PROC mov ax,0 int 33h ret exit_mouse ENDP ;------------------------------------------------------------------------ ;Extern procedur f”r att ladda en komprimerad IFF/ILBM fil i 320x200x256 ;Laddar in hela den komprimerade delen i minnet innan ;dekomprimering. Kr„ver mer fritt minne, men g†r mycket ;snabbare. ; ; anropas med INVOKE load_iff,,,[] ; mode: 0 = ladda direkt till bildminne ; 1 = skapa bildbuffert och ladda in till denna ; 2 = ladda in i redan allokerad buffert (bufferns segment anges som ; sista parameter) ; ; returv„rden: AX = -1 om fel,annars inladdad bilds segment om mode=1 ; BX = bildens bredd ; CX = bildens h”jd ;----------------------------------------------------------------------- read32bit MACRO add di,3 @Read di,1,handle dec di @Read di,1,handle dec di @Read di,1,handle dec di @Read di,1,handle ENDM read16bit MACRO add di,1 @Read di,1,handle dec di @Read di,1,handle ENDM w EQU word ptr calc_offs MACRO xchg ah,al ; ax=256*y add bx,ax ; bx=256*y+x shr ax,2 add bx,ax ; bx=320*y+x (+ offset in buffer if needed.) ENDM .DATA FORM dd 4d524f46h ILBM dd 4d424c49h BMHD dd 44484d42h CMAP dd 50414d43h BODY dd 59444f42h no_iffstr db 'This is not an IFF/ILBM file!',13,10,'$' no_compstr db 'Not a compressed IFF/ILBM file!',13,10,'$' vidseg dw 0a000h .DATA? comp_seg dw ? uncomp_seg dw ? handle dw ? img_size dw ? block_id dd ? block_len dd ? wdth dw ? hght dw ? xwdth dw ? planes db ? compress db ? inbyte db ? inbyte2 db ? scan dw ? plane db ? adr dw ? nxtline dw ? palbuf db 768 dup (?) BMHDbuf db 20 dup (?) .CODE load_iff PROC C USES ES SI DI, mode:WORD, fname:PTR BYTE, picseg:VARARG mov dx,fname @OpenFile dx,0 jc error mov handle,ax call read_lbmhdr jc error mov dx,w[block_len] add dx,15 shr dx,4 @GetBlock dx jc error mov comp_seg,ax mov di,dx push ds @Read 0,w[block_len],handle,comp_seg ;H„r laddas hela den pop ds ;komprimerade delen in cmp mode,0 jz mode_0 cmp mode,1 jz mode_1 cmp mode,2 jz mode_2 mode_0: ;Ladda direkt till bildminne mov es,vidseg jmp over_modes mode_1: ;Mode 1 = ladda till buffert mov ax,64000/16 ;buffert skapas i denna procedur @GetBlock ax jc error mov uncomp_seg,ax mov es,uncomp_seg jmp over_mode2 mode_2: mov es,picseg[0] ;Ladda till redan allokerad buffert over_mode2: mov di,0 mov eax,0 mov cx,64000/4 cld rep stosd ;Clear buffer over_modes: mov xwdth,320 mov gs,comp_seg mov si,0 mov scan,0 nxt_scan: mov plane,0 nxt_plane: mov bx,0 mov ax,scan calc_offs mov di,bx add bx,wdth mov bp,bx ;Index to next line mov cl,plane do_line: mov dl,gs:[si] inc si mov inbyte,dl cmp inbyte,128 ja repeat_byte jz next ; 80h = Pad byte mov bx,0 mov bl,inbyte lp1: mov dh,gs:[si] inc si mov dl,dh shr dl,7 and dl,1 shl dl,cl or es:[di],dl inc di mov dl,dh shr dl,6 and dl,1 shl dl,cl or es:[di],dl inc di mov dl,dh shr dl,5 1b2b and dl,1 shl dl,cl or es:[di],dl inc di mov dl,dh shr dl,4 and dl,1 shl dl,cl or es:[di],dl inc di mov dl,dh shr dl,3 and dl,1 shl dl,cl or es:[di],dl inc di mov dl,dh shr dl,2 and dl,1 shl dl,cl or es:[di],dl inc di mov dl,dh shr dl,1 and dl,1 shl dl,cl or es:[di],dl inc di mov dl,dh and dl,1 shl dl,cl or es:[di],dl inc di dec bl jns lp1 jmp next repeat_byte: mov dh,gs:[si] inc si mov bx,0 mov bl,inbyte not bl add bl,1 lp2: mov dl,dh shr dl,7 and dl,1 shl dl,cl or es:[di],dl inc di mov dl,dh shr dl,6 and dl,1 shl dl,cl or es:[di],dl inc di mov dl,dh shr dl,5 and dl,1 shl dl,cl or es:[di],dl inc di mov dl,dh shr dl,4 and dl,1 shl dl,cl or es:[di],dl inc di mov dl,dh shr dl,3 and dl,1 shl dl,cl or es:[di],dl inc di mov dl,dh shr dl,2 and dl,1 shl dl,cl or es:[di],dl inc di mov dl,dh shr dl,1 and dl,1 shl dl,cl or es:[di],dl inc di mov dl,dh and dl,1 shl dl,cl or es:[di],dl inc di dec bl jns lp2 next: cmp di,bp jb do_line inc plane mov dl,planes cmp plane,dl jb nxt_plane inc scan mov dx,hght cmp scan,dx jb nxt_scan mov es,comp_seg @FreeBlock ;Frig”r den tempor„ra inladdningsbufferten @CloseFile handle mov ax,uncomp_seg mov bx,wdth mov cx,hght ret error: mov ax,-1 ret load_iff ENDP read_lbmhdr PROC mov ax,ds mov es,ax lea di,block_id[0] @Read di,4,handle lea si,FORM[0] cmpsd jnz no_iff mov di,offset block_len @Read di,4,handle lea di,block_id[0] @Read di,4,handle lea si,ILBM[0] cmpsd jnz no_iff get_bmhd: lea di,block_id[0] @Read di,4,handle lea di,block_len[0] read32bit lea si,block_id[0] lea di,BMHD[0] cmpsd jz go_on1 @MovePtrRel handle,block_len jmp get_bmhd go_on1: mov di,offset BMHDbuf @Read di,20,handle mov bx,di mov dx,[bx] ror dx,8 mov wdth,dx mov dx,[bx+2] ror dx,8 mov hght,dx mov dl,[bx+8] mov planes,dl mov dl,[bx+10] mov compress,dl cmp byte ptr[compress],0 jz no_compress get_cmap: lea di,block_id[0] @Read di,4,handle lea di,block_len[0] read32bit lea si,block_id[0] lea di,CMAP[0] cmpsd jz go_on2 @MovePtrRel handle,block_len jmp get_cmap go_on2: mov di,offset palbuf @Read di,w[block_len],handle lea di,palbuf[0] mov cx,w[block_len] shiftpal: shr byte ptr[di],2 inc di loop shiftpal mov ah,10h ;Set palette mov al,12h mov bx,0 mov cx,256 mov dx,offset palbuf int 10h get_body: lea di,block_id[0] @Read di,4,handle lea di,block_len[0] read32bit lea si,block_id[0] lea di,BODY[0] cmpsd jz go_on3 @MovePtrRel handle,block_len jmp get_body go_on3: clc ret no_iff: mov ah,9 mov dx,offset no_iffstr int 21h stc ret no_compress: mov ah,9 mov dx,offset no_compstr int 21h stc ret read_lbmhdr ENDP ;------ Rutin f”r att ladda in en fil i PCX-format i 320x200x256 ---------- ; ; anropas med INVOKE load_pcx,,,[] ; mode: 0 = ladda direkt till bildminne ; 1 = skapa bildbuffert och ladda in till denna ; 2 = ladda in i redan allokerad buffert (bufferns segment anges som ; sista parameter) ; ; returv„rden: AX = -1 om fel,annars inladdad bilds segment om mode=1 ; BX = bildens bredd ; CX = bildens h”jd ;-------------------------------------------------------------------------- .DATA pcxhdrstruct STRUCT manufacturer db ? version db ? encoding db ? bitsPerPixel db ? xmin dw ? ymin dw ? xmax dw ? ymax dw ? hres dw ? vres dw ? palette db 48 dup (?) reserved db ? colourPlanes db ? bytesPerLine dw ? paletteType dw ? filler db 58 dup (?) pcxhdrstruct ENDS pcxhdr pcxhdrstruct <> no_pcxstr db 'This is not a PCX file!',13,10,'$' malloc_errstr db 'Not enough memory!',13,10,'$' comp_len dd ? end_of_line dw ? pal_start dd ? .CODE load_pcx PROC C USES ES SI DI, mode:WORD, fname:PTR BYTE, picseg:VARARG mov dx,fname @OpenFile dx,0 mov handle,ax jc error call read_pcxhdr jc error mov edx,comp_len add edx,15 shr edx,4 @GetBlock dx jc error mov comp_seg,ax mov di,0 mov si,comp_seg nxtblk: push ds @Read di,8000h,handle,si ;H„r laddas hela den pop ds ;komprimerade delen in cmp ax,8000h jnz end_reached add di,8000h jnz no_segchg add si,1000h ;change segment if needed no_segchg: jmp nxtblk end_reached: cmp mode,0 jz mode_0 cmp mode,1 jz mode_1 cmp mode,2 jz mode_2 mode_0: ;Ladda direkt till bildminne mov es,vidseg jmp over_modes mode_1: ;Mode 1 = ladda till buffert mov ax,64000/16 ;buffert skapas i denna procedur @GetBlock ax mov uncomp_seg,ax mov es,ax jmp over_modes mode_2: mov es,picseg[0] ;Ladda till redan allokerad buffert over_modes: mov fs,comp_seg mov si,0 mov di,0 mov dx,hght mov scan,dx nxt_line: mov dx,di add dx,pcxhdr.bytesPerLine mov end_of_line,dx nxt_byte: mov dl,fs:[si] inc si jnz no_segchg1 mov ax,fs add ax,1000h mov fs,ax no_segchg1: mov al,dl and al,0c0h cmp al,0c0h jnz just_store and dl,3fh xor cx,cx mov cl,dl mov dl,fs:[si] inc si jnz no_segchg2 mov ax,fs add ax,1000h mov fs,ax no_segchg2: run_lp: mov es:[di],dl inc di loop run_lp jmp over_juststore just_store: mov es:[di],dl inc di over_juststore: cmp di,end_of_line jb nxt_byte dec scan jnz nxt_line mov es,comp_seg @FreeBlock ;Frig”r den tempor„ra inladdningsbufferten @CloseFile handle mov ax,uncomp_seg mov bx,wdth mov cx,hght ret error: mov ax,-1 ret load_pcx ENDP read_pcxhdr PROC mov di,offset pcxhdr @Read di,128,handle cmp pcxhdr.manufacturer,0ah jnz no_pcx cmp pcxhdr.version,5 jnz no_pcx @GetFileSize handle ror eax,16 mov ax,dx rol eax,16 mov comp_len,eax sub comp_len,128 sub eax,768 mov pal_start,eax @MovePtrAbs handle,pal_start mov di,offset palbuf @Read di,768,handle ;L„s in palett lea di,palbuf[0] mov cx,768 shiftpal: shr byte ptr[di],2 inc di loop shiftpal mov ax,ds mov es,ax mov ah,10h ;Set palette mov al,12h mov bx,0 mov cx,256 mov dx,offset palbuf int 10h ;seek to start of image data @MovePtrAbs handle,128 mov dx,pcxhdr.xmax sub dx,pcxhdr.xmin add dx,1 mov wdth,dx mov dx,pcxhdr.ymax sub dx,pcxhdr.ymin add dx,1 mov hght,dx clc ret no_pcx: mov ah,9 mov dx,offset no_pcxstr int 21h stc ret read_pcxhdr ENDP END . 0