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

📄 fspxw.asm

📁 汇编编程艺术
💻 ASM
📖 第 1 页 / 共 2 页
字号:
		.286
		page	58, 132
		name	FSPXW
		title	FSPXW (Flightstick Pro driver for XWING).
		subttl	Copyright (C) 1994 Randall Hyde.


; FSPXW.EXE
;
;	Usage:
;		FSPXW
;
; This program executes the XWING.EXE program and patches it to use the
; Flightstick Pro.


byp		textequ	<byte ptr>
wp		textequ	<word ptr>


cseg		segment para public 'CODE'
cseg		ends

sseg		segment	para stack 'STACK'
sseg		ends

zzzzzzseg	segment	para public 'zzzzzzseg'
zzzzzzseg	ends

		include		stdlib.a
		includelib	stdlib.lib
		matchfuncs

		ifndef	debug
Installation	segment	para public 'Install'
Installation	ends
		endif

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

; Timer interrupt vector

Int1CVect	dd	?


; PSP-	Program Segment Prefix.  Needed to free up memory before running
;	the real application program.

PSP		dw	0



; Program Loading data structures (for DOS).

ExecStruct	dw	0			;Use parent's Environment blk.
		dd	CmdLine			;For the cmd ln parms.
		dd	DfltFCB
		dd	DfltFCB
LoadSSSP	dd	?
LoadCSIP	dd	?
PgmName		dd	Pgm


; Variables for the throttle pot.
; LastThrottle contains the character last sent (so we only send one copy).
; ThrtlCntDn counts the number of times the throttle routine gets called.

LastThrottle	db	0
ThrtlCntDn	db	10


; Button Mask- Used to mask out the programmed buttons when the game
; reads the real buttons.

ButtonMask	db	0f0h


; The following variables allow the user to reprogram the buttons.

KeyRdf		struct
Ptrs		dw	?
ptr2		dw	?
ptr3		dw	?
ptr4		dw	?
Index		dw	?
Cnt		dw	?
Pgmd		dw	?
KeyRdf		ends


; Left codes are output if the cooley switch is pressed to the left.

Left		KeyRdf	<Left1, Left2, Left3, Left4, 0, 6, 1>
Left1		dw	'7', 0,0,0,0,0,0,0,0
Left2		dw	'4', 0,0,0,0,0,0,0,0
Left3		dw	'1', 0,0,0,0,0,0,0,0
Left4		dw	0,   0,0,0,0,0,0,0,0

; Right codes are output if the cooley switch is pressed to the Right.

Right		KeyRdf	<Right1, Right2, Right3, Right4, 0, 6, 1>
Right1		dw	'9', 0,0,0,0,0,0,0,0
Right2		dw	'6', 0,0,0,0,0,0,0,0
Right3		dw	'3', 0,0,0,0,0,0,0,0
Right4		dw	0,   0,0,0,0,0,0,0,0

; Up codes are output if the cooley switch is pressed Up.

Up		KeyRdf	<Up1, Up2, Up3, Up4, 0, 2, 1>
Up1		dw	'8', 0,0,0,0,0,0,0,0
Up2		dw	0,  0,0,0,0,0,0,0,0
Up3		dw	0,  0,0,0,0,0,0,0,0
Up4		dw	0,  0,0,0,0,0,0,0,0

; DownKey codes are output if the cooley switch is pressed Down.

Down		KeyRdf	<Down1, Down2, Down3, Down4, 0, 2, 1>
Down1		dw	'2', 0,0,0,0,0,0,0,0
Down2		dw	0,   0,0,0,0,0,0,0,0
Down3		dw	0,   0,0,0,0,0,0,0,0
Down4		dw	0,   0,0,0,0,0,0,0,0

; Sw0 codes are output if the user pulls the trigger.

Sw0		KeyRdf	<Sw01, Sw02, Sw03, Sw04, 0, 0, 0>
Sw01		dw	0, 0,0,0,0,0,0,0,0
Sw02		dw	0, 0,0,0,0,0,0,0,0
Sw03		dw	0, 0,0,0,0,0,0,0,0
Sw04		dw	0, 0,0,0,0,0,0,0,0


; Sw1 codes are output if the user presses Sw1 (the left button
; if the user hasn't swapped the left and right buttons).

Sw1		KeyRdf	<Sw11, Sw12, Sw13, Sw14, 0, 0, 0>
Sw11		dw	0, 0,0,0,0,0,0,0,0
Sw12		dw	0, 0,0,0,0,0,0,0,0
Sw13		dw	0, 0,0,0,0,0,0,0,0
Sw14		dw	0, 0,0,0,0,0,0,0,0

; Sw2 codes are output if the user presses Sw2 (the middle button).

Sw2		KeyRdf	<Sw21, Sw22, Sw23, Sw24, 0, 2, 1>
Sw21		dw	'w', 0,0,0,0,0,0,0,0
Sw22		dw	0,   0,0,0,0,0,0,0,0
Sw23		dw	0,   0,0,0,0,0,0,0,0
Sw24		dw	0,   0,0,0,0,0,0,0,0

; Sw3 codes are output if the user presses Sw3 (the right button
; if the user hasn't swapped the left and right buttons).

Sw3		KeyRdf	<Sw31, Sw32, Sw33, Sw34, 0, 0, 0>
Sw31		dw	0, 0,0,0,0,0,0,0,0
Sw32		dw	0, 0,0,0,0,0,0,0,0
Sw33		dw	0, 0,0,0,0,0,0,0,0
Sw34		dw	0, 0,0,0,0,0,0,0,0

; Switch status buttons:

CurSw		db	0
LastSw		db	0


;****************************************************************************
; FSPXW patch begins here.  This is the memory resident part.  Only put code
; which which has to be present at run-time or needs to be resident after
; freeing up memory.
;****************************************************************************

Main		proc
		mov	cs:PSP, ds
		mov	ax, cseg		;Get ptr to vars segment
		mov	ds, ax


; Get the current INT 1Ch interrupt vector:

		mov	ax, 351ch
		int	21h
		mov	wp Int1CVect, bx
		mov	wp Int1CVect+2, es

; The following call to MEMINIT assumes no error occurs.  If it does,
; we're hosed anyway.

		mov	ax, zzzzzzseg
		mov	es, ax
		mov	cx, 1024/16
		meminit2


; Do some initialization before running the game.  These are calls to the
; initialization code which gets dumped before actually running XWING.

		call	far ptr ChkBIOS15
		call	far ptr Identify
;		call	far ptr Reprogram
		call	far ptr Calibrate

; If any switches were programmed, remove those switches from the
; ButtonMask:

		mov	al, 0f0h		;Assume all buttons are okay.
		cmp	sw0.pgmd, 0
		je	Sw0NotPgmd
		and	al, 0e0h		;Remove sw0 from contention.
Sw0NotPgmd:

		cmp	sw1.pgmd, 0
		je	Sw1NotPgmd
		and	al, 0d0h		;Remove Sw1 from contention.
Sw1NotPgmd:

		cmp	sw2.pgmd, 0
		je	Sw2NotPgmd
		and	al, 0b0h		;Remove Sw2 from contention.
Sw2NotPgmd:

		cmp	sw3.pgmd, 0
		je	Sw3NotPgmd
		and	al, 070h		;Remove Sw3 from contention.
Sw3NotPgmd:
		mov	ButtonMask, al		;Save result as button mask

; Now, free up memory from ZZZZZZSEG on to make room for XWING.
; Note: Absolutely no calls to UCR Standard Library routines from
; this point forward! (ExitPgm is okay, it's just a macro which calls DOS.)
; Note that after the execution of this code, none of the code & data
; from zzzzzzseg on is valid.

		mov	bx, zzzzzzseg
		sub	bx, PSP
		inc	bx
		mov	es, PSP
		mov	ah, 4ah
		int	21h
		jnc	GoodRealloc
		print
		byte	"Memory allocation error."
		byte	cr,lf,0
		jmp	Quit

GoodRealloc:

; Now load the XWING program into memory:

		mov	bx, seg ExecStruct
		mov	es, bx
		mov	bx, offset ExecStruct	;Ptr to program record.
		lds	dx, PgmName
		mov	ax, 4b01h		;Load, do not exec, pgm
		int	21h
		jc	Quit			;If error loading file.

; Search for the joystick code in memory:

		mov	si, zzzzzzseg
		mov	ds, si
		xor	si, si

		mov	di, cs
		mov	es, di
		mov	di, offset JoyStickCode
		mov	cx, JoyLength
		call	FindCode
		jc	Quit			;If didn't find joystick code.


; Patch the XWING joystick code here

		mov	byp ds:[si], 09ah	;Far call
		mov	wp ds:[si+1], offset ReadGame
		mov	wp ds:[si+3], cs

; Find the Button code here.

		mov	si, zzzzzzseg
		mov	ds, si
		xor	si, si

		mov	di, cs
		mov	es, di
		mov	di, offset ReadSwCode
		mov	cx, ButtonLength
		call	FindCode
		jc	Quit

; Patch the button code here.

		mov	byp ds:[si], 9ah
		mov	wp ds:[si+1], offset ReadButtons
		mov	wp ds:[si+3], cs
		mov	byp ds:[si+5], 90h	;NOP.


; Patch in our timer interrupt handler:

		mov	ax, 251ch
		mov	dx, seg MyInt1C
		mov	ds, dx
		mov	dx, offset MyInt1C
		int	21h


; Okay, start the XWING.EXE program running

		mov	ah, 62h			;Get PSP
		int	21h
		mov	ds, bx
		mov	es, bx
		mov	wp ds:[10], offset Quit
		mov	wp ds:[12], cs
		mov	ss, wp cseg:LoadSSSP+2
		mov	sp, wp cseg:LoadSSSP
		jmp	dword ptr cseg:LoadCSIP


Quit:		lds	dx, cs:Int1CVect		;Restore timer vector.
		mov	ax, 251ch
		int	21h
		ExitPgm

Main		endp

;****************************************************************************
;
; ReadGame-	This routine gets called whenever XWing reads the joystick.
;		On every 10th call it will read the throttle pot and send
;		appropriate characters to the type ahead buffer, if
;		necessary.

		assume	ds:nothing
ReadGame	proc	far
		dec	cs:ThrtlCntDn		;Only do this each 10th time
		jne	SkipThrottle		; XWING calls the joystick
		mov	cs:ThrtlCntDn, 10	; routine.

		push	ax
		push	bx		;No need to save bp, dx, or cx as
		push	di		; XWING preserves these.

		mov	ah, 84h
		mov	dx, 103h	;Read the throttle pot
		int	15h

; Convert the value returned by the pot routine into the four characters
; 0..63:"\", 64..127:"[", 128..191:"]", 192..255:<bs>, to denote zero, 1/3,
; 2/3, and full power, respectively.

		mov	dl, al
		mov	ax, "\"		;Zero power
		cmp	dl, 192
		jae	SetPower
		mov	ax, "["		;1/3 power.
		cmp	dl, 128
		jae	SetPower
		mov	ax, "]"		;2/3 power.
		cmp	dl, 64
		jae	SetPower
		mov	ax, 8		;BS, full power.
SetPower:	cmp	al, cs:LastThrottle
		je	SkipPIB
		mov	cs:LastThrottle, al
		call	PutInBuffer

SkipPIB:	pop	di
		pop	bx
		pop	ax
SkipThrottle:	neg	bx		;XWING returns data in these registers.
		neg	di		;We patched the NEG and STI instrs
		sti			; so do that here.
		ret
ReadGame	endp

		assume	ds:nothing
ReadButtons	proc	far
		mov	ah, 84h
		mov	dx, 0
		int	15h
		not	al
		and	al, ButtonMask		;Turn off pgmd buttons.
		ret
ReadButtons	endp



; MyInt1C- Called every 1/18th second.  Reads switches and decides if it
; should shove some characters into the type ahead buffer.

		assume	ds:cseg
MyInt1c		proc	far
		push	ds
		push	ax
		push	bx
		push	dx
		mov	ax, cseg
		mov	ds, ax

		mov    	al, CurSw
		mov	LastSw, al

⌨️ 快捷键说明

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