![]() |
#1 |
Secret Agent beta image
Peder Jungck is the creator of Secret Agent. He also wrote two articles for a magazine called Programmer's Journal: Pixel Panning in May 1991 and Icon Power in September 1991.
Pixel Panning is about smooth scrolling graphics like those graphics in Commander Keen and Secret Agent. That article features two listings: Code:
; PIXELPAN.ASM -- EGA/VGA Pixel Panning routines ; BY PEDER JUNGCK ( Copyright 1991 ) ; Assembly language routines designed for C-style calling conventions ; All example routines use a near call model - assemble with /MX switch ; NOTE: the SetLineLength function is error trapped for Mode 0Dh (320x200) SLOW_EGA equ 0 .model small .code Public _Video_Mode ; (int Mode) Public _SetLineLength ; (int Length) Public _SetViewPosition ; (HPixel,LineNum) Public _Set_Pixel ; (x,y,Color) BytesPerLine dw 40 ; screen width in bytes (320x200 Mode) VOffset equ 0a000h ; video RAM offset Video_ModeParms struc dw ? ; pushed BP dw ? ; return address pushed by call vm_mode dw ? ; pass new video mode parameter Video_ModeParms ends _Video_Mode proc near ; void Video_Mode(int Mode); push bp mov bp,sp ; put sp in bp, to get parameters on stack mov ax,word ptr [bp+vm_mode] xor ah,ah ; set video mode ( ah=0 ) int 10h ; call video BIOS pop bp ret _Video_Mode endp SetLineLengthParms struc dw ? ; pushed BP dw ? ; return address pushed by call LineLen dw ? ; pass new scan line length SetLineLengthParms ends _SetLineLength proc near ; int SetLineLength(int Length) push bp mov bp,sp ; put sp in bp, to find parameters on stack mov ax,word ptr [bp+LineLen] cmp ax,40 ; Minimum Line Length (320x200) 40 bytes jae Low_OK ; 1 page wide x 8 high (mode 0Dh default) mov ax,40 ; Must be at least the minimum length jmp Hi_OK Low_OK: cmp ax,320 ; 320 bytes wide leaves only 200 high jbe Hi_OK ; 8 pages wide and one high (mode 0Dh) mov ax,320 ; Must be less or equal to maximum Hi_OK: mov BytesPerLine,ax xchg bx,ax ; save parameter to BX mov dx,3d4h mov ax,13h out dx,ax ; BytesPerVideoRamRow Func inc dx ; 3d5h data port mov ax,bx ; number of lines to output shr ax,1 ; need words for port out dx,ax mov ax,bx ; return # of lines we set pop bp ret _SetLineLength endp SetViewPositionParms struc dw ? ; pushed BP dw ? ; return address pushed by call HPixel dw ? ; pass in horizontal pixel offset LineNum dw ? ; pass in line number SetViewPositionParms ends _SetViewPosition proc near ;void SetViewPosition(int HPixel,int Linenum) push bp mov bp,sp ; put sp in bp, to find parameters on stack mov ax,[bp+HPixel] ; get horizontal pixel address mov cx,ax ; and save in cx and cx,07 ; get pixel offset of position shr ax,1 shr ax,1 shr ax,1 xchg bx,ax ; and save in bx mov ax,[bp+LineNum] ; get number of lines mul BytesPerLine ; multiply times bytes per line add bx,ax ; new upper left corner offset mov dx,3dah wait: in al,dx ; make sure not already doing a retrace test al,08h jz wait Retrace: in al,dx ; wait until the start of retrace test al,08 ; to perform clear of 3c0 port jnz Retrace cli ; disable interrupts in al,dx mov ax,bx ; upper corner in AH, BH holds high value mov al,0ch ; hi byte offset mov dx,3d4h out dx,ax mov al,0dh ; low byte offset mov ah,bl ; bl holds low byte value out dx,ax if SLOW_EGA sti mov dx,3dah wait2: in al,dx ; wait til we start vertical retrace test al,08h jz wait2 cli endif mov dx,3c0h ; ATC index register mov al,33h ; palette address source 1, reg address 13 out dx,al xchg cl,al ; get pixel offset out dx,al sti ; enable interrupts pop bp ret _SetViewPosition endp Set_PixelParms struc dw ? ; pushed BP dw ? ; return address pushed by call ps_xpos dw ? ps_ypos dw ? Color dw ? Set_PixelParms ends _Set_Pixel proc near ; void Set_Pixel(int x, int y, int Color) push bp mov bp,sp push ds ; save the data segment mov ax,VOffset ; get the video RAM address mov ds,ax ; set data segment to EGA/VGA mov ax,[bp+ps_ypos] ; get the y coordinate mul BytesPerLine ; get the offset to line y mov bx,[bp+ps_xpos] ; get the x coordinate mov cx,bx ; and save in CX too shr bx,1 ; and divide by 8 shr bx,1 shr bx,1 add bx,ax ; bx := BytesPerLine*y+(x/8) ; we now have x,y memory offset and cl,7 ; generate mask for one pixel in byte xor cl,7 mov ch,1 shl ch,cl ; ch := 1 >> (7-(x mod 8)) mov dx,3ceh ; now select write mode 2 mov al,5 out dx,al ; select mode (register 5) mov dx,3cfh mov al,2 out dx,al ; and set to write mode 2 mov dx,3ceh ; set up mask mov al,8 out dx,al ; select mask (register 8) mov dx,3cfh mov al,ch out dx,al ; set mask mov al,[bx] ; read from card and color dot mov ax,[bp+Color] mov [bx],al ; write color to dot mov dx,3ceh ; restore default mode mov al,5 out dx,al ; select mode (register 5) mov dx,3cfh mov al,0 out dx,al ; set write mode back to 0 mov dx,3ceh mov al,8 out dx,al ; select mask (register 8) mov dx,3cfh mov al,0ffh out dx,al ; and set default mask pop ds ; restore data segment pop bp ret _Set_Pixel endp end Code:
/* PAN-TEST.c --- Display Color Blocks and then pans the display */ extern void Video_Mode (int Mode); /* Use BIOS to set mode */ extern int SetLineLength (int Length); /* Sets bytes/scan line */ extern void SetViewPosition(int HPixel, int LineNum); /* Upper left pixel to display on screen */ extern void Set_Pixel(int x, int y, int Color); /* Set pixel to color */ int main () { int i,j,k,l; /* some loop variables */ Video_Mode ( 0x0d ); /* Step 1: Set video mode to 320x200x16 */ SetLineLength( 80 ); /* Step 2: 80 Bytes wide virtual screen */ /* Sets up 2 wide by 4 high memory */ SetViewPosition( 0,0 ); /* Step 3: Display upper left page */ /* Step 4: Place graphics in video memory -- Make sure whatever * routines you use properly adjust for the new memory layout. */ for (l=0; l<20; l++) /* Draw a color checkerboard */ for (k=0; k<20; k++) /* Not all is initially visible */ for (j=0; j<18; j++) /* but will be revealed by panning */ for (i=0; i<32; i++) Set_Pixel( i+j*32, k + l*20, j + l); /* Step 5: now we pan a little */ for (i=0; i<320; i++) /* 320 is first position page 2 */ SetViewPosition( i,0 ); /* Do a Horizontal Pan first */ for (i=320; i>0; i--) /* Diagonal Pan down and to left */ SetViewPosition( i,320-i ); /* to page 3/5 (120 lines down) */ for (i=0; i<320; i++) /* Vertical Pan up to origin */ SetViewPosition( 0,320-i ); /* to page 1 (120 lines down) */ Video_Mode ( 3 ); /* Restore to text mode and exit */ }; |
|
![]() |
![]() |
#2 |
Re: Secret Agent beta image
Icon Power is about drawing sprites a.k.a. icons on screen. That article also features two listings:
Code:
/* ICONDEMO.c --- a sample program for drawing and moving icons */ #include <stdio.h> #include <stdlib.h> typedef char Icon[160]; /* array of 160 bytes forms an icon. */ /* display icon at x,y from system RAM into video RAM with write mode 0 */ extern void near Display_Icon(int x, int y, void far *Data); /* copy icon from one spot in VRAM to another spotwith write mode 1. */ extern void near Copy_Icon(int OrigX, int OrigY, int X, int Y); extern void near Video_Mode(int Mode) ; extern void near Set_Pixel(int x, int y, int Color); Icon Icon1 = { 0x03,0x00,0x00,0x00,0x00, 0xF8,0x00,0x00,0x00,0x00, 0x07,0x00,0x03,0x03,0x03, 0xFC,0x00,0xF8,0xF8,0xF8, 0x0F,0x00,0x07,0x07,0x07, 0xF8,0x70,0x70,0x70,0x80, 0x0F,0x00,0x06,0x06,0x07, 0xF8,0xF0,0xD0,0xD0,0x40, 0x0F,0x00,0x06,0x06,0x07, 0xFC,0xF8,0xF8,0xF8,0x00, 0x0F,0x01,0x05,0x05,0x06, 0xF8,0xE0,0xE0,0xE0,0x10, 0x0F,0x01,0x05,0x05,0x06, 0xF8,0x70,0x70,0x50,0xB0, 0x0F,0x01,0x01,0x01,0x00, 0xFC,0xB8,0xB8,0xB8,0x40, 0x3F,0x00,0x00,0x0F,0x02, 0xFE,0x00,0x00,0xCC,0x0C, 0x7F,0x00,0x00,0x3F,0x21, 0xFE,0x00,0x00,0xFC,0x0C, 0x7F,0x00,0x00,0x33,0x30, 0xFC,0x00,0x00,0xF0,0xC0, 0x3F,0x00,0x00,0x03,0x00, 0xFC,0x00,0x00,0xC0,0x00, 0x3F,0x18,0x18,0x1B,0x1B, 0xFE,0x04,0x04,0xF4,0x04, 0x7F,0x30,0x30,0x3F,0x30, 0xFE,0x0C,0x0C,0xFC,0xCC, 0x7F,0x20,0x20,0x27,0x20, 0xFC,0x18,0x18,0x18,0x18, 0x27,0x00,0x00,0x00,0x00, 0x18,0x00,0x00,0x00,0x00 }; void delay(int count); void main() { int i,j; /* loop variables */ Video_Mode ( 0x0d ); /* Step 1-set video mode to 320x200x16 */ /* Sets up 2 wide by 4 high memory */ for (j=0; j<=15; j++) /* Step 2-manually draw the background */ for (i=0; i<=15; i++) /* icon using the Set_Pixel function */ if ((i+j & 1)==1) /* Alternate pixels lt. and dk. blue */ Set_Pixel(i,j,1); /* This generates the background */ else Set_Pixel(i,j,9); /* pattern, which you can change. */ for (j=0; j<13; j++) /* Step 3-copy the icon to fill screen */ for (i=0; i<=19; i++) /* 12.5 vertical is actual needed, */ Copy_Icon(0,0,i*2,j*16); /* the extra byte is offscreen */ Display_Icon(2, 90,&Icon1[0]); /* Step 4-draw icon bitmap to start */ Display_Icon(0,184,&Icon1[0]); /* position, draw copy for Copy_Icon */ getch(); /* wait for user input */ #define DELAY 100 /* set to your liking to slow things down */ for (j=0; j<20*DELAY; j += DELAY) { /* add our little delay loop */ Copy_Icon(2,90,37,90); /* redraw the background area we use */ for (i=2; i<38; i++) { /* Step 5-do some animation with icon */ Copy_Icon(0,184,i,90); /* copy icon to the new position */ Copy_Icon(0, 0,i-2,90); /* overwrite trailing w/bkg */ delay(j); /* and gradually slow it down */ } Display_Icon(0,184,&Icon1[0]); /* draw a new copy for Copy_Icon */ } getch(); /* wait for user prompt */ Video_Mode ( 3 ); /* restore to text mode before exiting */ }; void delay(int count) { /* our delay function to slow things down */ while (count--) srand(0); /* use any function for delay */ } |
|
![]() |
![]() |
#3 |
Re: Secret Agent beta image
Code:
; ICONTOOL.ASM -- EGA/VGA Icon Drawing ; set up for C style calling method for routines ; these routines are currently set up to use a near call model ; by Peder Jungck, Copyright 1991 ; DATA segment byte public 'DATA' DATA ends _TEXT segment byte public 'CODE' assume cs:_TEXT, ds:DATA, es:nothing; Public _Copy_Icon ;(int OrigX, int OrigY, int X, int Y); Public _Display_Icon ;(int x,int y,void far *Data); Public _Video_Mode ;(int Mode); Public _Set_Pixel ;(int x,int y, int Color); BytesPerLine dw 40 ; screen width in bytes (320x200 Mode) VOffset equ 0a000h ; video RAM offset Display_IconParms struc dw 2 dup(?) ; pushed BP and return address pp_xpos dw ? pp_ypos dw ? pp_pointer dw ? Display_IconParms ends _Display_Icon proc near ; _Display_Icon(int x, int y, void far *Data); push bp mov bp,sp push ds push di push si mov ax,VOffset ; EGA address mov es,ax ; segment ega mov ax,BytesPerLine ; RAM line length currently set xchg di,ax ; BytesPerLine to DI ;lds si,[bp+pp_pointer] ; ds:[si]=start of icon mov si, [bp+pp_pointer] mov ds, [bp+pp_pointer+2] mov ax,word ptr [bp+pp_ypos] ; get vertical line mul di mov bx,word ptr [bp+pp_xpos] ; horizontal byte add bx,ax ; (y*40) + bx <- horiz byte ; normally in wm0 dec di ; next line offset variable ; adding at position 2 in icon ; to end up at position 1 in ; next line of icon in video RAM mov dx,03c4h ; select the map register mov al,2 out dx,al mov cx,16 ; number of lines per icon DIStrt: mov dx,3ceh lodsb ; get the mask mov ah,8 xchg ah,al out dx,ax mov dx,03c5h ; load map register data addr mov al,1 ; plane 1 out dx,al lodsb xchg es:[bx],al mov al,2 ; plane 2 out dx,al lodsb xchg es:[bx],al mov al,4 ; plane 4 out dx,al lodsb xchg es:[bx],al mov al,8 ; plane 8 out dx,al lodsb xchg es:[bx],al inc bx ; column 2 mov dx,3ceh lodsb ; get the mask mov ah,8 xchg ah,al out dx,ax mov dx,03c5h ; load map register data addr mov al,1 ; plane 1 out dx,al lodsb xchg es:[bx],al mov al,2 ; plane 2 out dx,al lodsb xchg es:[bx],al mov al,4 ; plane 4 out dx,al lodsb xchg es:[bx],al mov al,8 ; plane 8 out dx,al lodsb xchg es:[bx],al add bx,di ; start of next line of icon ; in video RAM loop DIStrt ; do next row mov al,0fh ; reset the map mask out dx,al mov dx,3ceh mov ax,0ff08h ; reset bit mask to all ones out dx,ax pop si pop di pop ds pop bp ret _Display_Icon endp Copy_IconParms struc dw 2 dup(?) ; pushed BP and return address CIOx dw ? CIOy dw ? CIx dw ? CIy dw ? Copy_IconParms ends _Copy_Icon proc near ; Copy_Icon(int OrigX, int OrigY, int X, int Y); push bp mov bp,sp push si push di push ds mov ax,VOffset ; EGA address mov es,ax ; segment ega mov ds,ax ; segment for ega mov ax,word ptr [bp+CIOy] ; get origination icon addr mul BytesPerLine ; get vertical line mov si,word ptr [bp+CIOx] ; horizontal byte add si,ax ; (y*40) + bx <- horiz byte mov ax,word ptr [bp+CIy] ; get vertical line mul BytesPerLine mov di,word ptr [bp+CIx] ; horizontal byte add di,ax ; (y*40) + bx <- horiz byte ; normally in wm0 mov dx,03c4h mov al,02 out dx,al mov dx,03c5h ; load map register data addr mov al,0fh ; enable all planes out dx,al mov dx,3ceh mov al,5 out dx,al inc dx mov al,1 out dx,al ; select write mode 1 mov ax,BytesPerLine ; offset to next line dec ax ; subtract icon width dec ax mov cx,16 CIStrt: movsb ; reads ds:[si] then writes es:[di] movsb ; reads icon place in memory then writes to dest add si,ax ; get to start of next line of add di,ax ; the orig and dest addresses loop CIStrt mov dx,3cfh ; write mode register already mov al,0 ; selected, just output value out dx,al ; restore write mode 0 pop ds pop di pop si pop bp ret _Copy_Icon endp Video_ModeParms struc dw ? ; pushed BP dw ? ; return address pushed by call vm_mode dw ? ; pass new video mode parameter Video_ModeParms ends _Video_Mode proc near ; void Video_Mode(int Mode); push bp mov bp,sp ; put sp in bp, to get parameters on stack mov ax,word ptr [bp+vm_mode] xor ah,ah ; set video mode ( ah = 0 ) int 10h ; call video BIOS pop bp ret _Video_Mode endp Set_PixelParms struc dw ? ; pushed BP dw ? ; return address pushed by call ps_xpos dw ? ps_ypos dw ? Color dw ? Set_PixelParms ends _Set_Pixel proc near ; void Set_Pixel(int x, int y, int Color) push bp mov bp,sp push ds ; save the data segment mov ax,VOffset ; get the video RAM address mov ds,ax ; set data segment to EGA/VGA mov ax,[bp+ps_ypos] ; get the y coordinate mul BytesPerLine ; get the offset of line y mov bx,[bp+ps_xpos] ; get the x coordinate mov cx,bx ; and save in CX too shr bx,1 ; and divide by 8 shr bx,1 shr bx,1 add bx,ax ; bx := BytesPerLine*y+(x/8) ; we now have x,y memory offset and cl,7 ; generate mask for one pixel in byte xor cl,7 mov ch,1 shl ch,cl ; ch := 1 >> (7-(x mod 8)) mov dx,3ceh ; now select write mode 2 mov al,5 out dx,al ; select mode (register 5) mov dx,3cfh mov al,2 out dx,al ; and set to write mode 2 mov dx,3ceh ; set up mask mov al,8 out dx,al ; select mask (register 8) mov dx,3cfh mov al,ch out dx,al ; set mask mov al,[bx] ; read from card and color dot mov ax,[bp+Color] mov [bx], al ; write color to dot mov dx,3ceh ; restore default mode mov al,5 out dx,al ; select mode (register 5) mov dx,3cfh mov al,0 out dx,al ; set write mode back to 0 mov dx,3ceh mov al,8 out dx,al ; select mask (register 8) mov dx,3cfh mov al,0ffh out dx,al ; and set default mask pop ds ; restore data segment pop bp ret _Set_Pixel endp _TEXT ends end ![]() Is this image of agent 006 with red hands from a beta version of Secret Agent? Or did I just made a typo? |
|
![]() |
Bookmarks |
|
|