⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sgdi.asm

📁 汇编编程艺术
💻 ASM
📖 第 1 页 / 共 2 页
字号:
		.286
		page	58, 132
		name	SGDI
		title	SGDI Driver for Standard Game Adapter Card
		subttl	This Program is Public Domain Material.

; SGDI.EXE
;
;	Usage:
;		SDGI
;
; This program loads a TSR which patches INT 15 so arbitrary game programs
; can read the joystick in a portable fashion.
;
;
; We need to load cseg in memory before any other segments!

cseg		segment	para public 'code'
cseg		ends


; Initialization code, which we do not need except upon initial load,
; goes in the following segment:

Initialize	segment	para public 'INIT'
Initialize	ends

; UCR Standard Library routines which get dumped later on.

		.xlist
		include		stdlib.a
		includelib	stdlib.lib
		.list

sseg		segment	para stack 'stack'
sseg		ends

zzzzzzseg	segment	para public 'zzzzzzseg'
zzzzzzseg	ends



CSEG		segment	para public 'CODE'
		assume	cs:cseg, ds:nothing

wp		equ	<word ptr>
byp		equ	<byte ptr>

Int15Vect	dd	0

PSP		dw	?

; Port addresses for a typical joystick card:

JoyPort		equ	201h
JoyTrigger	equ	201h

; Data structure to hold information about each pot.
; (mainly for calibration and normalization purposes).

Pot		struc
PotMask		db	0			;Pot mask for hardware.
DidCal		db	0			;Is this pot calibrated?
min		dw	5000			;Minimum pot value
max		dw	0			;Max pot value
center		dw	0			;Pot value in the middle
Pot		ends

; Variables for each of the pots.  Must initialize the masks so they
; mask out all the bits except the incomming bit for each pot.

Pot0		Pot	<1>
Pot1		Pot	<2>
Pot2		Pot	<4>
Pot3		Pot	<8>



; The IDstring address gets passed back to the caller on a testpresence
; call.  The four bytes before the IDstring must contain the serial number
; and current driver number.

SerialNumber	db	0,0,0
IDNumber	db	0
IDString	db	"Standard SGDI Driver",0
		db	"Public Domain Driver Written by Randall L. Hyde",0


;============================================================================
;
; ReadPots- AH contains a bit mask to determine which pots we should read.
;	    Bit 0 is one if we should read pot 0, bit 1 is one if we should
;	    read pot 1, bit 2 is one if we should read pot 2, bit 3 is one
;	    if we should read pot 3.  All other bits will be zero.
;
;	This code returns the pot values in SI, BX, BP, and DI for Pot 0, 1,
;	2, & 3.
;

ReadPots	proc	near
		sub	bp, bp
		mov	si, bp
		mov	di, bp
		mov	bx, bp

; Wait for any previous signals to finish up before trying to read this
; guy.  It is possible that the last pot we read was very short.  However,
; the trigger signal starts timers running for all four pots.  This code
; terminates as soon as the current pot times out.  If the user immediately
; reads another pot, it is quite possible that the new pot's timer has
; not yet expired from the previous read.  The following loop makes sure we
; aren't measuring the time from the previous read.

		mov	dx, JoyPort
		mov	cx, 400h
Wait4Clean:	in	al, dx
		and	al, 0Fh
		loopnz	Wait4Clean

; Okay, read the pots.  The following code triggers the 558 timer chip
; and then sits in a loop until all four pot bits (masked with the pot mask
; in AL) become zero.  Each time through this loop that one or more of these
; bits contain zero, this loop increments the corresponding register(s).

		mov	dx, JoyTrigger
		out	dx, al		;Trigger pots
		mov	dx, JoyPort
		mov	cx, 1000h	;Don't let this go on forever.
PotReadLoop:	in	al, dx
		and	al, ah
		jz	PotReadDone
		shr	al, 1
		adc	si, 0		;Increment SI if pot 0 still active.
		shr	al, 1
		adc	bx, 0		;Increment BX if pot 1 still active.
		shr	al, 1
		adc	bp, 0		;Increment BP if pot 2 still active.
		shr	al, 1
		adc	di, 0		;Increment DI if pot 3 still active.
		loop	PotReadLoop	;Stop, eventually, if funny hardware.

		and	si, 0FFFh	;If we drop through to this point,
		and	bx, 0FFFh	; one or more pots timed out (usually
		and	bp, 0FFFh	; because they are not connected).
		and	di, 0FFFh	; The reg contains 4000h, set it to 0.
PotReadDone:
		ret
ReadPots	endp



;----------------------------------------------------------------------------
;
; Normalize- 	BX contains a pointer to a pot structure, AX contains
;		a pot value.  Normalize that value according to the
;		calibrated pot.
;
; Note: DS must point at cseg before calling this routine.


		assume	ds:cseg
Normalize	proc	near
		push	cx

; Sanity check to make sure the calibration process went okay.

		cmp	[bx].Pot.DidCal, 0	;Is this pot calibrated?
		je	BadNorm			;If not, quit.

		mov	dx, [bx].Pot.Center	;Do a sanity check on the
		cmp	dx, [bx].Pot.Min	; min, center, and max
		jbe	BadNorm			; values to make sure
		cmp	dx, [bx].Pot.Max	; min < center < max.
		jae	BadNorm

; Clip the value if it is out of range.

		cmp	ax, [bx].Pot.Min	;If the value is less than
		ja	MinOkay			; the minimum value, set it
		mov	ax, [bx].Pot.Min	; to the minimum value.
MinOkay:

		cmp	ax, [bx].Pot.Max	;If the value is greater than
		jb	MaxOkay			; the maximum value, set it
		mov	ax, [bx].Pot.Max	; to the maximum value.
MaxOkay:

; Scale this guy around the center:

		cmp	ax, [bx].Pot.Center	;See if less than or greater
		jb	Lower128		; than centered value.

; Okay, current reading is greater than the centered value, scale the reading
; into the range 128..255 here:

		sub	ax, [bx].Pot.Center
		mov	dl, ah			;Multiply by 128
		mov	ah, al
		mov	dh, 0
		mov	al, dh
		shr	dl, 1
		rcr	ax, 1
		mov	cx, [bx].Pot.Max
		sub	cx, [bx].Pot.Center
		jz	BadNorm			;Prevent division by zero.
		div	cx			;Compute normalized value.
		add	ax, 128			;Scale to range 128..255.
		cmp	ah, 0
		je	NormDone
		mov	ax, 0ffh	;Result must fit in 8 bits!
		jmp	NormDone

; If the reading is below the centered value, scale it into the range
; 0..127 here:

Lower128:	sub	ax, [bx].Pot.Min
		mov	dl, ah
		mov	ah, al
		mov	dh, 0
		mov	al, dh
		shr	dl, 1
		rcr	ax, 1
		mov	cx, [bx].Pot.Center
		sub	cx, [bx].Pot.Min
		jz	BadNorm
		div	cx
		cmp	ah, 0
		je	NormDone
		mov	ax, 0ffh
		jmp	NormDone

; If something went wrong, return zero as the normalized value.

BadNorm:	sub	ax, ax

NormDone:	pop	cx
		ret
Normalize	endp
		assume	ds:nothing

;============================================================================
; INT 15h handler functions.
;============================================================================
;
; Although these are defined as near procs, they are not really procedures.
; The MyInt15 code jumps to each of these with BX, a far return address, and
; the flags sitting on the stack.  Each of these routines must handle the
; stack appropriately.
;
;----------------------------------------------------------------------------
; BIOS- Handles the two BIOS calls, DL=0 to read the switches, DL=1 to
;	read the pots.  For the BIOS routines, we'll ignore the cooley
;	switch (the hat) and simply read the other four switches.

BIOS		proc	near
		cmp	dl, 1		;See if switch or pot routine.
		jb	Read4Sw
		je	ReadBIOSPots

; If not a valid BIOS call, jump to the original INT 15 handler and
; let it take care of this call.

		pop	bx
		jmp	cs:Int15Vect	;Let someone else handle it!

; BIOS read switches function.

Read4Sw:	push	dx
		mov	dx, JoyPort
		in	al, dx
		and	al, 0F0h	;Return only switch values.
		pop	dx
		pop	bx
		iret

; BIOS read pots function.

ReadBIOSPots:	pop	bx		;Return a value in BX!
		push	si
		push	di
		push	bp
		mov	ah, 0Fh		;Read all four pots.
		call	ReadPots
		mov	ax, si
		mov	cx, bp		;BX already contains pot 1 reading.
		mov	dx, di
		pop	bp
		pop	di
		pop	si
		iret
BIOS		endp

;----------------------------------------------------------------------------
;
; ReadPot-	On entry, DL contains a pot number to read.
;		Read and normalize that pot and return the result in AL.

		assume	ds:cseg
ReadPot		proc	near
;;;;;;;;;;	push	bx		;Already on stack.
		push	ds
		push	cx
		push	dx
		push	si
		push	di
		push	bp

		mov	bx, cseg
		mov	ds, bx

; If dl = 0, read and normalize the value for pot 0, if not, try some
; other pot.

		cmp	dl, 0
		jne	Try1
		mov	ah, Pot0.PotMask	;Get bit for this pot.
		call	ReadPots		;Read pot 0.
		lea	bx, Pot0		;Pointer to pot data.
		mov	ax, si			;Get pot 0 reading.
		call	Normalize		;Normalize to 0..FFh.
		jmp	GotPot			;Return to caller.

; Test for DL=1 here (read and normalize pot 1).

Try1:		cmp	dl, 1
		jne	Try2
		mov	ah, Pot1.PotMask
		call	ReadPots
		mov	ax, bx
		lea	bx, Pot1
		call	Normalize
		jmp	GotPot

; Test for DL=2 here (read and normalize pot 2).

Try2:		cmp	dl, 2
		jne	Try3
		mov	ah, Pot2.PotMask
		call	ReadPots
		lea	bx, Pot2
		mov	ax, bp
		call	Normalize
		jmp	GotPot

; Test for DL=3 here (read and normalize pot 3).

Try3:		cmp	dl, 3
		jne	BadPot
		mov	ah, Pot3.PotMask
		call	ReadPots
		lea	bx, Pot3
		mov	ax, di
		call	Normalize
		jmp	GotPot

; Bad value in DL if we drop to this point.  The standard game card
; only supports four pots.

BadPot:		sub	ax, ax		;Pot not available, return zero.
GotPot:		pop	bp
		pop	di
		pop	si

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -