'
' NeoLib - Main Module
'
' Features:
'  3 subs
'  1 functions
' For a total of: 4 routines
'
' Specially designed and coded for AAP's QBCPC
' Official Library of the QuickBASIC Caliber Programming Compo (Summer & Autumn 2003)
'
'Credits go to: Plasma, Dav, v1ctor
'for the nice FFix Code

DECLARE FUNCTION neoInit% (Layers AS INTEGER)

DECLARE SUB neoClose ()
DECLARE SUB neoFFix ()
DECLARE SUB neoVsync (Times AS INTEGER)

'CONST FALSE = 0, TRUE = NOT FALSE

DEFINT A-Z
'$DYNAMIC
'$INCLUDE: 'NeoLib.bi'
'$LIB: 'QB.LIB'

TYPE MemAddress
	Segment AS INTEGER
	Offset	AS INTEGER
END TYPE

DIM SHARED FFixCode(0 TO 5) AS LONG
DIM SHARED IsInstalledFFix AS INTEGER, OldInt3DhVector AS MemAddress

'/////////////////////////////////////////////////////////////////////////
' FUNCTIONS
'/////////////////////////////////////////////////////////////////////////
FUNCTION neoInit (Layers AS INTEGER)
	'this function will initialize NeoLib v1.6
	'- Layers: amount of EMS layers to create
	'Returns: -1 initialization successful
	'	   0 initialization failed

	'## MACRO BEGIN NEOLAYER
	IF Layers > 0 THEN
		IF neoLayerCreate(Layers) = 0 THEN neoInit = 0: EXIT FUNCTION
	END IF
	'## MACRO END

	'## MACRO BEGIN NEODRAW
	neoDrawInitLayers
	'## MACRO END

	'## MACRO BEGIN NEOSPRT
	neoSpriteInitLayers
	'## MACRO END

	'## MACRO BEGIN NEOKEYB
	neoKeybOn
	OUT &H60, &HF3
	FOR I = 0 TO 249: NEXT I
	OUT &H60, 0
	'## MACRO END

	SCREEN 13
	'## MACRO BEGIN NEOFONT
	neoFontInitLayers
	'## MACRO END
	neoInit = -1
	IsInstalledFFix = 0
END FUNCTION

'/////////////////////////////////////////////////////////////////////////
' SUBS
'/////////////////////////////////////////////////////////////////////////
SUB neoVSync (Times AS INTEGER)
	FOR I = 1 TO Times
		WAIT &H3DA, 8
		WAIT &H3DA, 8, 8
	NEXT I
END SUB

SUB neoClose
	'this routine closes down NeoLib v1.6

        '## MACRO BEGIN NEOLAYER
        neoLayerRemove
        '## MACRO END

        '## MACRO BEGIN NEODRAW
        neoDrawInitLayers
        neoDrawSetClipBox 0, 0, 0, 0
        '## MACRO END

        '## MACRO BEGIN NEOFONT
        neoFontInitLayers
        neoFontSetClipBox 0, 0, 0, 0
        '## MACRO END

        '## MACRO BEGIN NEOSPRT
        neoSpriteInitLayers
        neoSpriteSetClipBox 0, 0, 0, 0
        '## MACRO END

        'close down FFix if detected
        IF IsInstalledFFix = -1 THEN neoFFix

        SCREEN 0
        WIDTH 80, 25
END SUB

SUB neoFFix
	'applies or removes the Floating Point fix for QB45
	'it may not be as fast as ASM ones, but still... ;)

	'After a long but interesting conversation with Plasma,
	'I sought for v1ctor's patch at Dav's QB Code Post, where
	'they had this nice little routine. It didn't differ much
        'from my own routine, but this is better.
        'So credits go to: Plasma, Dav, v1ctor

	IF IsInstalledFFix = 0 THEN
		'the required code for the interrupt 3Dh replenishment is:

		'0E70:0100 55 		PUSH BP
		'0E70:0101 8BEC 	MOV BP,SP
		'0E70:0103 53 		PUSH BX
		'0E70:0104 8B5E02 	MOV BX,[BP+02]
		'0E70:0107 83EB02 	SUB BX,+02
		'0E70:010A 06 		PUSH ES
		'0E70:010B 8E4604 	MOV ES,[BP+04]
		'0E70:010E 26 		ES:
		'0E70:010F C707909B 	MOV WORD PTR [BX],9B90
		'0E70:0113 07 		POP ES
		'0E70:0114 5B 		POP BX
		'0E70:0115 5D 		POP BP
		'0E70:0116 9B 		WAIT
		'0E70:0117 CF 		IRET

		FFixCode(0) = &H53EC8B55
		FFixCode(1) = &H83025E8B
		FFixCode(2) = &H8E0602EB
		FFixCode(3) = &HC7260446
		FFixCode(4) = &H079B9007
		FFixCode(5) = &HCF9B5D5B

        	'first get the old interrupt vector
        	RegsX.ax = &H353D	'get interrupt vector 3D
        	INTERRUPTX &H21, RegsX, RegsX
        	OldInt3DhVector.Segment = RegsX.es
        	OldInt3DhVector.Offset = RegsX.bx

        	'now set the new interrupt vector
        	RegsX.ax = &H253D	'set interrupt vector 3D
        	RegsX.ds = VARSEG(FFixCode(0))
        	RegsX.dx = VARPTR(FFixCode(0))
        	INTERRUPTX &H21, RegsX, RegsX

        	'initialize (by calling a floating point function)
        	P! = TIMER

        	'set flag
        	IsInstalledFFix = -1
        ELSE

        	'first get the old interrupt vector
        	RegsX.ax = &H353D	'get interrupt vector 3D
        	INTERRUPTX &H21, RegsX, RegsX

        	'remove the floating point fix
        	RegsX.ax = &H253D
        	RegsX.ds = OldInt3DhVector.Segment
        	RegsX.dx = OldInt3DhVector.Offset
        	INTERRUPTX &H21, RegsX, RegsX

        	'init
        	P! = TIMER

        	'update flag
        	IsInstalledFFix = 0
        END IF
END SUB
