Forum Archive

Go Back   3D Realms Forums > 3D Realms Topics > Other Apogee/3D Realms Games
Blogs FAQ Community Calendar

Notices

 
 
Thread Tools
Old 09-21-2014, 01:47 PM   #1
Frenkel

Frenkel's Avatar
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  */
};
When you compile that code and run the resulting executable you'll see some colored blocks move across the screen. I could post a video on YouTube if someone is interested.
__________________
Groeten van Frenkel
Visit us at the Official S&F Prod. Homepage
Frenkel is offline  
Old 09-21-2014, 01:53 PM   #2
Frenkel

Frenkel's Avatar
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             */
}
__________________
Groeten van Frenkel
Visit us at the Official S&F Prod. Homepage
Frenkel is offline  
Old 09-21-2014, 02:03 PM   #3
Frenkel

Frenkel's Avatar
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
When you compile that code and run the resulting executable you'll see a sprite move across the screen:


Is this image of agent 006 with red hands from a beta version of Secret Agent?
Or did I just made a typo?
__________________
Groeten van Frenkel
Visit us at the Official S&F Prod. Homepage
Frenkel is offline  
Old 10-06-2014, 03:37 PM   #4
Joe Siegler
3D Realms Staff

Joe Siegler's Avatar
Re: Secret Agent beta image
I don't think I've ever seen that shit before.
__________________
Apogee / 3D Realms Employee: Dec 14, 1992 - May 22, 2009, Oct 23, 2014 - current

"Lifting up the Cross to the waiting lost" - Petra | John 3:16
Joe Siegler is offline  
 

Bookmarks


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -6. The time now is 02:42 PM.

Page generated in 0.18168092 seconds (100.00% PHP - 0% MySQL) with 18 queries

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2024, vBulletin Solutions, Inc.

Website is ©1987-2014 Apogee Software, Ltd.
Ideas and messages posted here become property of Apogee Software Ltd.