HINTS for GAME FINAL PROJECT
****************************
	NOTE: I WILL CONSTANTLY UPDATE THIS FILE WITH
	NEW INFORMATION AS THEY ARISE.  --Chee

1. It is useful to organize your programs into
	separate "assembly modules".  For instance,
	each member of a team should probably write one
	(or more) assembly module.  Besides our lecture notes,
	you should read up chapter 14 on memory
	management for more details.

	In the following example, we assume you use the
	small memory model for all your modules (including the
	main module).  Suppose that "module 1" contains
	the definitions of procedures Proc_1 and Proc_2
	and it uses some other procedures Proc_3 and Proc_4
	as well as an external byte variable Var_1.  Then
	this is how your file for module 1 looks:

		title MODULE 1
		extrn Proc_3:near, Proc_4:near, Var_1:byte
		public Proc_1, Proc_2
		.model small
		...
		... the usual stuff
		end

	To assemble them conveniently in one command,
	you can put the commands into one file with a ".bat"
	extension.  Use your favorite editor to enter the
	following into a file called asm.bat:

		@rem	This is a remark:
		@rem	This bat file assembles all my modules at once,
		@rem	  and then executes the main program.
		@rem	The main file is called mygame.asm
		@rem	  and the other files are module1.asm, module2.asm.

		echo	Begin assembly...

		tasm	mygame + module1 + module2 
		tlink	mygame + module1 + module2

		echo	End assembly and linking of mygame.

	Now you can just call "asm" to assemble and link.

2. Many games need a random number generator.  In the class
	homepage, we provided such a routine in the file
	random.asm.  There is also a test program (trand.asm)
	to exercise random.asm.  Random.asm is written as a
	TSR.  But you should be able to directly incorporate
	it into your game program if you wish.
	 
3. Mouse Routines: these are called via INT 33h.
	Here are the various functions (the function number
	is loaded into register ax before calling the interrupt).
   Function 0 -- reset
	Output:
		ax=mouse status (-1=installed, 0=not installed)
		bx=number of buttons
   Function 1 -- show Mouse Cursor
	Output: none
   Function 2 -- show Mouse Cursor
	Output: none
   Function 3 -- get mouse position and button status
	Output:
		bx=button status
			xxxx xxxx xxxx xMRL
			M=middle (if present)
			R=right
			L=left
			(0=not pressed, 1=pressed)
		cx=horizontal mouse cursor position
		dx=vertical mouse cursor position
			(divide positions by 2 for medium resolution
			graphics, divide by 8 for text mode)
   Function 4 -- set mouse cursor position
	Input:
		cx=new horizontal position
		dx=new vertical position
	Output: none
   Function 5 -- get button press information
	Input:
		bx=button of interest (0=L,1=R,2=M)
	Output:
		ax=button status (current status of ALL buttons)
		bx=number of button presses on specified button
		cx=horizontal position at last press
		dx=vertical position at last press
   Function 6 -- get button release information
	Input:
		bx=button of interest (0=L,1=R,2=M)
	Output:
		ax=button status (current status of ALL buttons)
		bx=number of button presses on specified button
		cx=horizontal position at last press
		dx=vertical position at last press
   Function 7 -- set minimum and maximum X position
	Input:
		cx=new minimum horizontal cursor position
		dx=new maximum horizontal cursor position
	Output: none
   Function 8 -- set minimum and maximum Y position
	Input:
		cx=new minimum vertical cursor position
		dx=new maximum vertical cursor position
	Output: none
   Function 9 -- define graphics cursor
	Input:
		bx=horizontal cursor hot spot
		cx=vertical cursor hot spot
		   NOTE: (bx,cx)=(0,0) is upper left.
			 See additional notes below.
		es:dx=address of screen and cursor mask
	Output: none

4. Mouse cursor (cf.function 9, INT 33h).
	My program mse2.asm illustrates the
	use of this function. 

	The graphics cursor is displayed as an array of pixels,
	either 16x16 or 8x8, depending on display mode.
	This cursor is defined by two 16x16 array of bits,
	called the SCREEN MASK and CURSOR MASK.  For medium
	resolution, 2 bits of the masks are taken at a time,
	corresponding to 4 possible colors.

	The SCREEN MASK is AND'ed with the display screen.
	The CURSOR MASK is XOR'ed (not OR'ed) with the result.  Thus we
	have the following behaviour:

	SCREEN MASK	CURSOR MASK	RESULTING SCREEN BIT
	    0		    0			0
	    0		    1			1
	    1		    0		    unchanged
	    1		    1		     inverted

	The definition of the DEFAULT graphics cursor is
	given as follows:

		mov ax, 9
		mov bx, -1	; default hot spot is past arrow tip
		mov cx, -1
		mov dx, offset default
				; we assume ES is properly set up already
		int 33h
		;
		default:
		; screen mask ---
		  db	0011111111111111b
		  db	0001111111111111b
		  db	0000111111111111b
		  db	0000011111111111b
		;
		  db	0000001111111111b
		  db	0000000111111111b
		  db	0000000011111111b
		  db	0000000001111111b
		;
		  db	0000000000111111b
		  db	0000000111111111b
		  db	0001000011111111b
		  db	0011000011111111b
		;
		  db	1111100001111111b
		  db	1111100001111111b
		  db	1111110000111111b
		  db	1111111111111111b
		;
		; cursor mask ---
		  db	0000000000000000b
		  db	0100000000000000b
		  db	0110000000000000b
		  db	0111000000000000b
		;
		  db	0111100000000000b
		  db	0111110000000000b
		  db	0111111000000000b
		  db	0111111100000000b
		;
		  db	0111111110000000b
		  db	0111111111000000b
		  db	0111110000000000b
		  db	0100011000000000b
		;
		  db	0000011000000000b
		  db	0000001100000000b
		  db	0000001100000000b
		  db	0000000000000000b
	
5. Keeping absolute time.
	In graphics animation, you often need to delay
	the display.  One way is to use a do-nothing loop.
	But this approach does not keep absolute time -- the
	time depends on the speed of your CPU.
	To avoid this problem, you need to make use
	of the timer chip in your PC.  Chapter 16 of your
	text book gives a simple solution.  Essentially, it
	writes a timer interrupt procedure called TIMER_TICK
	(page 344) to be called automatically 18.2 times per
	second (equivalently, every 55 ms).  This procedure
	simply sets a global variable TIMER_FLAG to 1.

	This TIMER_TICK program is used in pgm16_2 (page 346).
	It is used to for generating a fixed frequency
	tone for the sound card (page 347).

	I have written a sample program (found in the file
	timeout.asm) to illustrate how you can keep time using
	the timer_tick interrupt routine.

	NOTE: Another method to keep absolute time is to
	directly read the clock tick at address 0000:046C
	and 0000:046E (this is a 32 bit value that is updated
	by the clock every 55 ms).  See the file egalib.asm
	in the vga-asm directory.

6. It is often useful to know if the keyboard buffer is empty
	or not, without waiting for the user to type something.
	This requires INT 16h, function 1 (not found in text).
	Hear is how to use it:
		INPUT: ah=1
		OUTPUT: zero flag (ZF) is set if keyboard is empty.
	My program timeout.asm (mentioned in the previous item)
	uses this interrupt function.

	Actually, DOS also provides a similar interrupt function:
	INT 21h, function 11 is called the "input status interrupt".
		INPUT:  ah=11
		OUTPUT: al=0 if buffer is empty
			al=0FFh if buffer is not empty
	Related to this interrupt is the ability to flush the buffer,
	and execute an input command at the same time.
	INT 21h, function 0Ch:
		INPUT:  ah=0Ch
			al=1,6,7,8 or OAh
	The output depends on which of the subfunctions (1,6,7,8,0Ah)
	is used.  Other inputs are also necessary,
	depending on the subfunction.
	For instance, al=0Ah refers to reading a string.  In this
	case, ds:dx must be setup to contain the address of the
	memory buffer for storing the string input.

7. Using standard memory models.

	This is a recap of our lecture about standard
	memory models.  Usually, we use the "small" model
	and this should be sufficient for many of your
	projects as well.  But suppose you need other
	models.  First, let us note that the small model
	assumes that there are separate segments for
	each of the following:
		code, stack, data.

	Suppose your program does not fit the small model.
	You can of course, go to full blown definitions
	of your own segments (using the "SEGMENT" directive).
	But a more convenient way is to use other standard models.
	We now explained three of the most common ones.
	In other models, we allow code and data to be put into
	more than one segment.  Moreover, we distinguish several
	kinds of data segments.
		data:	has (possibly) initialized data
		data?:	has only un-initialized data
		const:	has constant data
		fardata: has (possibly) initialized data
		fardata?: has only un-initialized data
	
	MEDIUM MODEL: data here can be put in one segment but code
	needs to be put into several segments.  
	To use this model, you use the following directive:

		.MODEL MEDIUM <csn>

	where <csn> refers to "code segment name".  If you have
	several assembly modules, each with a different <csn>,
	you can generate several code segments this way.
	But, in fact, you can also generate more than one code
	segment within the same assembly module, by using the
	directive
		.CODE <csn>
	This directive begins a new code segment with name
	<csn>_text, or continues a previously started code
	segment with that name.

	COMPACT MODEL: code here can be put into one segment
	but data needs to be put into several segments.
	The usual .DATA directive generates one data segment which
	is the "near data segment".  You can generate other data 
	segments by using the directive

		.FARDATA <name>

	This begins or continues (possibly) initialized data
	segment with name <name>.  For instance, suppose if you have
	the statements

		.FARDATA data1
		Var1 db ?
		...

	To you can access Var1, you need to first get its
	segment number into ds.  For instance, to set Var1 to 
	the constant 1, you can do

		mov dx, SEG Var1	; alternatively, use
					; 	mov dx,data1
		mov ds, ax		; this sets up ds
		mov di, OFFSET Var1	; alternatively, use
					;	lea di,Var1
		mov [di], BYTE PTR 1
	
	LARGE MODEL: this is just the combination of the medium
	and the compact models.

	NOTE: the "assume" statement is useful in these models.

8. VGA graphics
	A collection of graphics routines in assembly
language and in C language is available in subdirectories "vga-asm" and
"vga-c" in the progs directory.  The file egalib.asm in vga-asm includes
all the other programs. So you could assemble it to test all the
routines.  However, you need to write your own main program!

	P.S. I found that using "CONST" as name of a segment
	is illegal in TASM, so you can replace it by "_CONST".
	There are 3 places where you need to do this.

Perhaps the most useful single program here is in prog087.asm
which copies one block of pixels from a source to a distination. 
There is also a line drawing program (prog086.asm).
	
9. Helppc
	This is an online system that allows you to
	get all kinds of technical information for pc programming.
	Please go to the link called "helppc" to get these files and
	installation information.
