Index: /tags/Configurator_v1.1.0/Inc/BiosData.inc
===================================================================
--- /tags/Configurator_v1.1.0/Inc/BiosData.inc	(revision 6)
+++ /tags/Configurator_v1.1.0/Inc/BiosData.inc	(revision 6)
@@ -0,0 +1,150 @@
+; File name		:	BiosData.inc
+; Project name	:	IDE BIOS
+; Created date	:	28.7.2007
+; Last update	:	23.3.2010
+; Author		:	Tomi Tilli
+; Description	:	Equates for BIOS Data Area.
+%ifndef BIOSDATA_INC
+%define BIOSDATA_INC
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; BIOS DATA AREA VARIABLES ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; BIOS Data Area (related to floppy drives and hard disks)
+struc BDA
+					resb	400h	; 40:0h, Start of BDA
+	.wCOM1			resb	2		; 0:400h, Serial I/O Address, Port 1
+	.wCOM2			resb	2		; 0:402h, Serial I/O Address, Port 2
+	.wCOM3			resb	2		; 0:404h, Serial I/O Address, Port 3
+	.wCOM4			resb	2		; 0:406h, Serial I/O Address, Port 4
+	.wLPT1			resb	2		; 0:408h, Parallel I/O Address, Port 1
+	.wLPT2			resb	2		; 0:40Ah, Parallel I/O Address, Port 2
+	.wLPT3			resb	2		; 0:40Ch, Parallel I/O Address, Port 3					
+	.wLPT4:							; 0:40Eh, Parallel I/O Address, Port 4 (PC/XT)
+	.wSegEBDA		resb	2		; 0:40Eh, Extended BIOS Data Area segment (AT+)
+	
+	.wEquipment		resb	2		; 0:410h, Equipment Word
+	.bTest			resb	1		; 0:412h, Manufacturing test
+	.wBaseMem		resb	2		; 0:413h, Base Memory Size in kB
+	.wAdptrMem:						; 0:415h, Adapter Memory Size (PC/XT)
+	.wError			resb	2		; 0:415h, Error Codes (AT+)
+	.bKBFlgs1		resb	1		; 0:417h, Keyboard, Shift Flags, Set 1
+	.bKBFlgs2		resb	1		; 0:418h, Keyboard, Shift Flags, Set 2
+	.bKBNumpad		resb	1		; 0:419h, Keyboard, ALT+Numpad work area
+	.wKBHead		resb	2		; 0:41Ah, Keyboard, Head of buffer pointer
+	.wKBTail		resb	2		; 0:41Ch, Keyboard, Tail of buffer pointer
+	.rgwKBBuff		resb	32		; 0:41Eh, Keyboard, 16-word buffer
+	
+	.bFDRecal		resb	1		; 0:43Eh, Diskette, Recalibrate status
+	.bFDMotor		resb	1		; 0:43Fh, Diskette, Motor status
+	
+	.bFDMotTime		resb	1		; 0:440h, Diskette, Motor timeout counter
+	.bFDRetST		resb	1		; 0:441h, Diskette, Controller status return code
+	.rgbFDStatus	resb	7		; 0:442h, Diskette, Diskette and Disk Controller status bytes
+	.bVidMode		resb	1		; 0:449h, Video, Mode
+	.wVidColumns	resb	2		; 0:44Ah, Video, Number of columns
+	.wVidBpP		resb	2		; 0:44Ch, Video, Total number of bytes per page
+	.wVidPageOff	resb	2		; 0:44Eh, Video, Current page offset
+	
+	.rgwVidCurPos	resb	16		; 0:450h, Video, Cursor position, pages 0...7
+	
+	.wVidCurShape	resb	2		; 0:460h, Video, Cursor shape
+	.bVidPageIdx	resb	1		; 0:462h, Video, Active display page
+	.wVidPort		resb	2		; 0:463h, Video, I/O Port number base
+	.bVidModeReg	resb	1		; 0:465h, Video, Internal mode register
+	.bVidPalette	resb	1		; 0:466h, Video, Color palette
+	.wCasTimeCnt:					; 0:467h, Cassette, Time count at data edge (PC)
+	.wGenOff		resb	2		; 0:467h, General use offset (XT+)
+	.wCasCRC:						; 0:469h, Cassette, CRC register (PC)
+	.wGenSeg		resb	2		; 0:469h, General use segment (XT+)
+	.bCasLast:						; 0:46Bh, Cassette, Last value read
+	.bLastIRQ		resb	1		; 0:46Bh, Last interrupt that occurred (XT+)
+	.dwTimerTicks	resb	4		; 0:46Ch, Timer ticks count
+	
+	.bTimer24h		resb	1		; 0:470h, Timer ticks rollover flag
+	.bKBCtrlBrk		resb	1		; 0:471h, Keyboard, Ctrl+Break flag
+	.wBoot			resb	2		; 0:472h, Warm boot flag
+	.bHDLastSt		resb	1		; 0:474h, Hard Disk, Status of Last Operation (XT+)
+	.bHDCount		resb	1		; 0:475h, Hard Disk, Number of HDs Attached (XT+)
+	.bHDCtrl		resb	1		; 0:476h, Hard Disk, Control Byte (temp, XT+) 
+	.bHDPortOff		resb	1		; 0:477h, Hard Disk, Port Offset (XT)
+	.bLPT1Timeout	resb	1		; 0:478h, Parallel Printer 1, Timeout (XT+)
+	.bLPT2Timeout	resb	1		; 0:479h, Parallel Printer 2, Timeout (XT+)
+	.bLPT3Timeout	resb	1		; 0:47Ah, Parallel Printer 3, Timeout (XT+)
+	.bLPT4Timeout	resb	1		; 0:47Bh, Parallel Printer 4, Timeout (XT+)
+	.bCOM1Timeout	resb	1		; 0:47Ch, Serial 1, Timeout (XT+)
+	.bCOM2Timeout	resb	1		; 0:47Dh, Serial 2, Timeout (XT+)
+	.bCOM3Timeout	resb	1		; 0:47Eh, Serial 3, Timeout (XT+)
+	.bCOM4Timeout	resb	1		; 0:47Fh, Serial 4, Timeout (XT+)
+	
+	.wKBPtrStart	resb	2		; 0:480h, Keyboard, Pointer to start of buffer (XT+)
+	.wKBPtrEnd		resb	2		; 0:482h, Keyboard, Pointer to end of buffer (XT+)
+	.bVidRows		resb	1		; 0:484h, Video, Number of rows (EGA+)
+	.wVidPpC		resb	2		; 0:485h, Video, Pixels per character (EGA+)
+	.bVidOptns		resb	1		; 0:487h, Video, Options (EGA+)
+	.bVidSwitches	resb	1		; 0:488h, Video, Switches (EGA+)
+	.bVidSave1		resb	1		; 0:489h, Video, Save area 1 (VGA+)
+	.bVidSave2		resb	1		; 0:48Ah, Video, Save area 2 (VGA+)
+	.bFDCfgData		resb	1		; 0:48Bh, Diskette, Configuration data (AT+)
+	.bHDStatus		resb	1		; 0:48Ch, Hard Disk, Status Register (AT+)
+	.bHDError		resb	1		; 0:48Dh, Hard Disk, Error Register (AT+)
+	.bHDTaskFlg		resb	1		; 0:48Eh, Hard Disk, Task Complete Flag (AT+)
+	.bFDCtrlInfo	resb	1		; 0:48Fh, Diskette, Controller information (AT+)
+	
+	.bFDMedia0		resb	1		; 0:490h, Diskette 0, Media state (AT+)
+	.bFDMedia1		resb	1		; 0:491h, Diskette 1, Media state (AT+)
+	.bFDOpStart0	resb	1		; 0:492h, Diskette 0, Operational starting state (AT+)
+	.bFDOpStart1	resb	1		; 0:493h, Diskette 1, Operational starting state (AT+)
+	.bFDCurCyl0		resb	1		; 0:494h, Diskette 0, Current cylinder (AT+)
+	.bFDCurCyl1		resb	1		; 0:495h, Diskette 1, Current cylinder (AT+)
+	.bKBFlgs3		resb	1		; 0:496h, Keyboard, Status flags 3 (AT+)
+	.bKBFlgs4		resb	1		; 0:497h, Keyboard, Status flags 4 (AT+)
+	.dwWaitPtr		resb	4		; 0:498h, User's wait flag pointer (AT+)
+	.dwWaitCnt		resb	4		; 0:49Ch, User's wait count (AT+)
+	
+	.bWaitFlg		resb	1		; 0:4A0h, Wait flag (AT+)
+	.rgbLAN			resb	7		; 0:4A1h, Local Area Network (AT+)
+	.dwVidPtr		resb	4		; 0:4A8h, Video, Parameter Control Block Pointer (EGA+)
+					resb	22h		; Reserved from 0:4ACh...0:4CDh
+
+	.dwDays			resb	4		; 0:4CEh, Clock, Days since 1980 (some BIOSes, AT+)
+					resb	2Eh		; Reserved from 0:4D2h...0:4FFh
+
+	.bPrntScrn		resb	1		; 0:500, Print screen status
+endstruc
+
+; BDA struct with only Hard Disk related locations
+struc HDBDA
+					resb	474h
+	.bHDLastSt		resb	1		; 0:474h, Status of Last Operation (XT+)
+	.bHDCount		resb	1		; 0:475h, Number of HDs Attached (XT+)
+	.bHDCtrl		resb	1		; 0:476h, Control Byte (temp, XT+)
+	.bHDPortOff		resb	1		; 0:477h, Port Offset (XT)
+					resb	15h
+	.bHDStatus:						; 0:48Ch, Status Register (AT+)
+	.bHDError:						; 0:48Dh, Error Register (AT+)
+	.wHDStAndErr	resb	2
+	.bHDTaskFlg		resb	1		; 0:48Eh, Task Complete Flag (AT+)
+endstruc
+
+
+;--------------------------------------------------------------------
+; Load BDA (Bios Data Area) segment to wanted segment register.
+;
+; LOAD_BDA_SEGMENT_TO
+;	Parameters:
+;		%1:		Destination Segment Register
+;		%2:		Temporary WORD Register
+;	Returns:
+;		%1:		BDA segment (zero)
+;	Corrupts registers:
+;		%2
+;--------------------------------------------------------------------
+%macro LOAD_BDA_SEGMENT_TO 2
+	xor		%2, %2
+	mov		%1, %2
+%endmacro
+
+
+%endif ; BIOSDATA_INC
Index: /tags/Configurator_v1.1.0/Inc/MenuPage.inc
===================================================================
--- /tags/Configurator_v1.1.0/Inc/MenuPage.inc	(revision 6)
+++ /tags/Configurator_v1.1.0/Inc/MenuPage.inc	(revision 6)
@@ -0,0 +1,54 @@
+; File name		:	MenuPage.inc
+; Project name	:	XTIDE Univeral BIOS Configurator
+; Created date	:	16.4.2010
+; Last update	:	25.4.2010
+; Author		:	Tomi Tilli
+; Description	:	Structs for menu pages and items.
+%ifndef MENUPAGE_INC
+%define MENUPAGE_INC
+
+; Variables for menu page (main menu and submenus)
+struc MENUPAGE
+	.bItemCnt			resb	1	; Number of MENUPAGEITEM structs
+						resb	1
+	.prgbItemToVal		resb	2	; Ptr to menuitem index to value lookup table
+	.rgMenuPageItem:				; MENUPAGEITEM structs (variable number)
+endstruc
+
+
+; Variables for single menuitem
+struc MENUPAGEITEM
+	.fnActivate			resb	2	; Offset to Menuitem activation function
+	.fnNameFormat		resb	2	; Offset to Menuitem name formatting function
+	.pValue				resb	2	; Offset to Menuitem value
+
+	.pSubMenuPage:					; Ptr to MENUPAGE for new submenu
+	.wValueMin			resb	2	; Minimum integer value
+
+	.rgszLookup:					; Ptr to lookup table for string values
+	.wValueMax:						; Maximum integer value
+	.wValueMask			resb	2	; Bitmask for Menuitem value flag
+
+	.szName				resb	2	; Offset to Menuitem name string
+	.szInfo				resb	2	; Offset to Menuitem information string
+	.szHelp				resb	2	; Offset to Menuitem help string
+	.szDialog			resb	2	; Offset to new value or other dialog string
+	.bFlags				resb	1	; Menuitem flags
+	.bType				resb	1	; Menuitem type
+endstruc
+
+; Bit defines for MENUPAGEITEM.bFlags
+FLG_MENUPAGEITEM_VISIBLE		EQU	(1<<0)	; Item is visible
+
+; Values for MENUPAGEITEM.bType
+TYPE_MENUPAGEITEM_BACK			EQU	(0<<1)	; Back to previous submenu
+TYPE_MENUPAGEITEM_NEXT			EQU	(1<<1)	; Open next submenu
+TYPE_MENUPAGEITEM_SPECIAL		EQU	(2<<1)	; Special menuitem without value
+TYPE_MENUPAGEITEM_UNSIGNED_BYTE	EQU	(3<<1)	; Menuitem with unsigned byte value
+TYPE_MENUPAGEITEM_UNSIGNED_WORD	EQU	(4<<1)	; Menuitem with unsigned word value
+TYPE_MENUPAGEITEM_HEX_BYTE		EQU	(5<<1)	; Menuitem with hexadecimal byte value
+TYPE_MENUPAGEITEM_HEX_WORD		EQU	(6<<1)	; Menuitem with hexadecimal word value
+TYPE_MENUPAGEITEM_FLAG			EQU	(7<<1)	; Menuitem with boolean flag value
+
+
+%endif ; MENUPAGE_INC
Index: /tags/Configurator_v1.1.0/Inc/RomVars.inc
===================================================================
--- /tags/Configurator_v1.1.0/Inc/RomVars.inc	(revision 6)
+++ /tags/Configurator_v1.1.0/Inc/RomVars.inc	(revision 6)
@@ -0,0 +1,88 @@
+; File name		:	RomVars.inc
+; Project name	:	IDE BIOS
+; Created date	:	23.3.2010
+; Last update	:	1.5.2010
+; Author		:	Tomi Tilli
+; Description	:	Defines for ROMVARS struct containing variables stored
+;					in BIOS ROM.
+%ifndef ROMVARS_INC
+%define ROMVARS_INC
+
+; ROM Variables. There are written to ROM image before flashing.
+struc ROMVARS
+	.wRomSign		resb	2	; ROM Signature (AA55h)
+	.bRomSize		resb	1	; ROM size in 512 byte blocks
+	.rgbJump		resb	5	; First instruction to ROM init (jmp)
+	; Offset 8 (8h) starts here
+	.rgbDate		resb	8	; BIOS build date string (mm/dd/yy)
+	; Offset 16 (10h) starts here
+	.rgbSign		resb	8	; Signature for XTIDE Configurator Program
+	.szTitle		resb	31	; BIOS title string
+	.szVersion		resb	25	; BIOS version string
+	; Offset 80 (50h) starts here
+	.wFlags			resb	2	; Word for ROM flags
+	.bIdeCnt		resb	1	; Number of supported IDE controllers
+	.bBootDrv		resb	1	; Boot Menu default drive
+	.bBootMnuH		resb	1	; Boot Menu maximum height
+	.bBootDelay		resb	1	; Boot Menu selection delay in seconds
+	.bBootLdrType	resb	1	; Boot Loader type
+	.bMinFddCnt		resb	1	; Minimum number of Floppy Drives
+	.bStealSize		resb	1	; Number of 1kB blocks stolen from 640kB base RAM
+					resb	7
+	; Offset 96 (60h) starts here
+	; Last IDEVARS must not start after offset FFh.
+	.ideVars0		resb	IDEVARS_size
+	.ideVars1		resb	IDEVARS_size
+	.ideVars2		resb	IDEVARS_size
+	.ideVars3		resb	IDEVARS_size
+	.ideVars4		resb	IDEVARS_size
+endstruc
+
+; Bit defines for ROMVARS.wFlags
+FLG_ROMVARS_FULLMODE	EQU	(1<<0)	; Full operating mode (steals base RAM, supports EBIOS etc.)
+FLG_ROMVARS_LATE		EQU	(1<<1)	; Late initialization
+FLG_ROMVARS_DRVXLAT		EQU	(1<<2)	; Enable drive number translation
+FLG_ROMVARS_ROMBOOT		EQU	(1<<3)	; Include ROMBOOT to boot menu
+FLG_ROMVARS_DRVNFO		EQU	(1<<4)	; Display drive info on boot menu
+FLG_ROMVARS_MAXSIZE		EQU	(1<<5)	; Maximize size by sacrificing compatibility with some old BIOSes
+
+; Bootloader types for ROMVARS.bBootLdrType
+BOOTLOADER_TYPE_MENU	EQU	(0<<1)	; Display boot menu on boot loader
+BOOTLOADER_TYPE_SIMPLE	EQU	(1<<1)	; Simple bootloader without menu
+BOOTLOADER_TYPE_NONE	EQU	(3<<1)	; Do not install boot loader
+
+
+; Controller specific variables
+struc IDEVARS
+	.wPort				resb	2	; IDE Base Port for Command Block (usual) Registers
+	.wPortCtrl			resb	2	; IDE Base Port for Control Block Registers
+	.bBusType			resb	1	; Bus type
+	.bIRQ				resb	1	; Interrupt Request Number
+						resb	4	; Reserved
+	.drvParamsMaster	resb	DRVPARAMS_size
+	.drvParamsSlave		resb	DRVPARAMS_size
+endstruc
+
+; Bus types for IDEVARS.bBusType
+BUS_TYPE_8_DUAL			EQU	(0<<1)	; XTIDE transfers with two 8-bit data ports
+BUS_TYPE_16				EQU	(1<<1)	; Normal 16-bit AT-IDE transfers
+BUS_TYPE_32				EQU	(2<<1)	; 32-bit VLB and PCI transfers
+BUS_TYPE_8_SINGLE		EQU	(3<<1)	; 8-bit transfers with single 8-bit data port
+
+
+; Master/Slave drive specific parameters
+struc DRVPARAMS
+	.wFlags			resb	2	; Drive flags
+					resb	2	; Reserved
+	.wCylinders		resb	2	; User specified cylinders (1...16383)
+	.wSectAndHeads:
+	.bSect			resb	1	; User specified Sectors per track (1...63)
+	.bHeads			resb	1	; User specified Heads (1...16)
+endstruc
+
+; Bit defines for DRVPARAMS.wFlags
+FLG_DRVPARAMS_USERCHS	EQU	(1<<0)	; User specified P-CHS values
+FLG_DRVPARAMS_BLOCKMODE	EQU	(1<<1)	; Enable Block mode transfers
+
+
+%endif ; ROMVARS_INC
Index: /tags/Configurator_v1.1.0/Inc/Variables.inc
===================================================================
--- /tags/Configurator_v1.1.0/Inc/Variables.inc	(revision 6)
+++ /tags/Configurator_v1.1.0/Inc/Variables.inc	(revision 6)
@@ -0,0 +1,64 @@
+; File name		:	Variables.inc
+; Project name	:	XTIDE Univeral BIOS Configurator
+; Created date	:	16.4.2010
+; Last update	:	2.5.2010
+; Author		:	Tomi Tilli
+; Description	:	Global variables for configuration program.
+%ifndef VARIABLES_INC
+%define VARIABLES_INC
+
+; Equates and defines
+WIDTH_MENU				EQU		38		; Menu width in characters
+WIDTH_DLG				EQU		34		; Dialog width in characters
+CNT_TITLE_LINES			EQU		4		; Number of title lines at the top of menu
+CNT_INFO_LINES			EQU		6		; Number of information lines at the bottom of menu
+CNT_TMEOUT_POLL			EQU		3		; EEPROM polling timeout (3 = 110...165ms)
+CNT_MAX_CTRLS			EQU		5		; Maximum number of IDE controllers
+HEIGHT_MIN_BOOTMNU		EQU		8		; Boot menu minimum height
+HEIGHT_MAX_BOOTMNU		EQU		25		; Boot menu maximum height
+LEN_SIGNATURE			EQU		8		; XTIDE Universal BIOS signature string length
+MAX_EEPROM_SIZE			EQU		16384
+
+
+; Program global variables
+struc CFGVARS
+	.wFlags				resb	2			; Program flags
+	.wEepromSize		resb	2			; Size in bytes for EEPROM to be flashed
+	.wEepromSegment		resb	2			; Segment where EEPROM is located
+	.bPageSize			resb	1			; EEPROM page size in bytes
+	.bSdpCommand		resb	1			; Command for Software Data Protection
+	.bMenuCnt			resb	1			; Number of opened menus
+						resb	1
+	.flashVars			resb	FLASHVARS_size
+
+	; EEPROM buffers
+	.rgbEepromBuffers	resb	MAX_EEPROM_SIZE * 2
+endstruc
+
+; Bit defines for CFGVARS.wFlags
+FLG_CFGVARS_FILELOADED	EQU	(1<<0)	; BIOS is loaded from file
+FLG_CFGVARS_ROMLOADED	EQU	(1<<1)	; BIOS is loaded from EEPROM
+FLG_CFGVARS_HIDEINFO	EQU	(1<<2)	; Hide menu information (FLG_MNU_HIDENFO)
+FLG_CFGVARS_UNSAVED		EQU	(1<<3)	; BIOS has unsaved changes
+FLG_CFGVARS_CHECKSUM	EQU	(1<<4)	; Generate checksum byte
+
+; SDP command for CFGVARS.bSdpCommand
+CMD_SDP_NONE			EQU	(0<<1)	; Do not use any SDP command
+CMD_SDP_ENABLE			EQU	(1<<1)	; Flash with SDP enable command
+CMD_SDP_DISABLE			EQU	(2<<1)	; Flash with SDP disable command
+
+
+; Variables required for flashing
+struc FLASHVARS
+	.wTotalPages		resb	2		; Total number of pages to write
+	.wPagesLeft			resb	2		; Pages left to write
+	.wPagesBeforeDraw	resb	2		; Number of pages to write before updating progress bar
+	.wByteOffset		resb	2		; Offset to byte to write next
+endstruc
+
+
+; Shortcuts to structs
+%define G_ROMVARS	g_cfgVars+CFGVARS.rgbNewROM
+
+
+%endif ; VARIABLES_INC
Index: /tags/Configurator_v1.1.0/Inc/emulate.inc
===================================================================
--- /tags/Configurator_v1.1.0/Inc/emulate.inc	(revision 6)
+++ /tags/Configurator_v1.1.0/Inc/emulate.inc	(revision 6)
@@ -0,0 +1,477 @@
+; File name		:	emulate.inc
+; Project name	:	Emulation library
+; Created date	:	21.10.2009
+; Last update	:	4.4.2010
+; Author		:	Tomi Tilli
+; Description	:	Macros for emulating later x86 instruction with older
+;					processors.
+;					Macros are used so optimized builds could be done
+;					easily for different processors.
+;
+;					This file must be first to be included to
+;					any source file.
+%ifndef EMULATE_INC
+%define EMULATE_INC
+
+; Defines for processor support. Unsupported instructions will be
+; emulated using macros.
+; If using 286, define USE_186 and USE_286
+; If using 386, define USE_186, USE_286 and USE_386
+; If AT class PC is used (instead of XT), define USE_AT
+;%define USE_186				; Define to use 18x/V20/V30 instructions
+;%define USE_286				; Define to use 286 instructions
+;%define USE_386				; Define to use 386 instructions
+;%define USE_AT					; Define for AT class machine
+; Above defines should be set on makefile!
+
+CPU 8086						; Allow 8088/8086 instructions only
+%ifdef USE_186
+CPU 186							; Allow instructions up to 188/186/V20/V30
+%elifdef USE_286
+CPU 286							; Allow instructions up to 286
+%elifdef USE_386
+CPU 386							; Allow instructions up to 386
+%endif
+BITS 16							; Set 16 bit code generation
+
+; Alignments for jump targets.
+; Following values are optimal for different processor types:
+; 286 and 386SX			WORD (16-bit, 2 bytes)
+; 386DX and 486			DWORD (32-bit, 4 bytes)
+; Pentium and later		QWORD (64-bit, 8 bytes)
+%ifdef USE_AT
+	%ifdef USE_386
+		JUMP_ALIGN		EQU		4
+		WORD_ALIGN		EQU		2
+	%else ; USE_286
+		JUMP_ALIGN		EQU		2
+		WORD_ALIGN		EQU		2
+	%endif
+%else ; XT
+	JUMP_ALIGN		EQU		1
+	WORD_ALIGN		EQU		1
+%endif
+
+;==========================================================================
+
+;--------------------------------------------------------------------
+; Emulates BSF (Bit Scan Forward) instruction when necessary.
+; BSF is used to find index of least significant bit.
+;
+; eBSF
+;	Parameters:
+;		%1:		Destination WORD Register for bit index (not CX or same as %2!)
+;		%2:		Source WORD operand where to search bit (not CX or same as %1!)
+;	Returns:
+;		%1:		Index of highest order bit from %2
+;		ZF:		Set if %2 is zero
+;				Cleared if %2 is non-zero
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro eBSF 2
+%ifndef USE_386
+	push	cx
+	cmp		WORD %2, BYTE 0		; Source operand is zero?
+	je		SHORT %%Return		;  If so, return with ZF set
+
+	; Set destination to zero and load mask for bit 0
+	xor		%1, %1
+	mov		cx, 1
+
+ALIGN JUMP_ALIGN
+%%BitLoop:
+	test	%2, cx				; Bit set?
+	jnz		SHORT %%Return		;  If so, return with ZF cleared
+	shl		cx, 1				; Prepare to test next bit
+	inc		%1					; Increment bit index
+	jmp		SHORT %%BitLoop		; Loop until bit found
+%%Return:
+	pop		cx
+;-----------------------------------
+%else
+	bsf		%1, %2
+%endif
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Emulates BSR (Bit Scan Reverse) instruction when necessary.
+; BSR is used to find index of most significant bit.
+;
+; eBSR
+;	Parameters:
+;		%1:		Destination WORD Register for bit index (not CX or same as %2!)
+;		%2:		Source WORD operand where to search bit (not CX or same as %1!)
+;	Returns:
+;		%1:		Index of highest order bit from %2
+;		ZF:		Set if %2 is zero
+;				Cleared if %2 is non-zero
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro eBSR 2
+%ifndef USE_386
+	push	cx
+	cmp		WORD %2, BYTE 0		; Source operand is zero?
+	je		SHORT %%Return		;  If so, return with ZF set
+
+	; Load mask for highest order bit
+	mov		cx, 1<<15
+	mov		%1, 15
+
+ALIGN JUMP_ALIGN
+%%BitLoop:
+	test	%2, cx				; Bit set?
+	jnz		SHORT %%Return		;  If so, return with ZF cleared
+	shr		cx, 1				; Prepare to test next bit
+	dec		%1					; Decrement bit index
+	jmp		SHORT %%BitLoop		; Loop until bit found
+%%Return:
+	pop		cx
+;-----------------------------------
+%else
+	bsr		%1, %2
+%endif
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Moves byte with zero-extending to any Register.
+;
+; eMOVZX
+;	Parameters:
+;		%1:		Destination Register (SP not supported)
+;		%2:		Byte register or byte address
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		FLAGS
+;--------------------------------------------------------------------
+%macro eMOVZX 2
+%ifndef USE_386
+	%ifidni %1, ax
+		xor		ax, ax
+		mov		al, %2
+	%elifidni %1, bx
+		mov		bl, %2
+		xor		bh, bh		; %2 may use BX in effective address
+	%elifidni %1, cx
+		xor		cx, cx
+		mov		cl, %2
+	%elifidni %1, dx
+		xor		dx, dx
+		mov		dl, %2
+	%else	; SI, DI, BP (all may be used in effective address)
+		push	ax
+		xor		ax, ax
+		mov		al, %2
+		xchg	ax, %1
+		pop		ax
+	%endif
+;-----------------------------------
+%else
+	movzx	%1, %2
+%endif
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Emulates PUSHA instruction when necessary.
+;
+; ePUSHA
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro ePUSHA 0
+%ifndef USE_186
+	push	ax
+	push	cx
+	push	dx
+	push	bx
+	; SP before first push should be pushed here
+	push	bp
+	push	si
+	push	di
+;-----------------------------------
+%else
+	pusha
+%endif
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Emulates POPA instruction when necessary.
+;
+; ePOPA
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro ePOPA 0
+%ifndef USE_186
+	pop		di
+	pop		si
+	pop		bp
+	; Old SP should be skipped here
+	pop		bx
+	pop		dx
+	pop		cx
+	pop		ax
+;-----------------------------------
+%else
+	popa
+%endif
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Emulates ENTER instruction when necessary.
+;
+; eENTER
+;	Parameters:
+;		%1:		Number of bytes to reserve from stack
+;		%2:		The lexical nesting level (not emulated)
+;	Returns:
+;		SS:BP:	Ptr to old BP
+;				([bp-2] points to highest local stack frame word)
+;	Corrupts registers:
+;		FLAGS
+;--------------------------------------------------------------------
+%macro eENTER 2
+%ifndef USE_186
+	push	bp
+	mov		bp, sp
+	sub		sp, %1
+;-----------------------------------
+%else
+	enter	%1, %2
+%endif
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Emulates LEAVE instruction when necessary.
+;
+; eLEAVE
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro eLEAVE 0
+%ifndef USE_186
+	mov		sp, bp
+	pop		bp
+;-----------------------------------
+%else
+	leave
+%endif
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Emulates LSS instruction when necessary.
+;
+; eLSS
+;	Parameters:
+;		%1:		Destination register
+;		%2:		Source memory address without brackets
+;	Returns:
+;		IF:		0 (interrupts disabled)
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro eLSS 2
+%ifndef USE_386
+	cli							; Disable interrupts
+	mov		%1, [%2]			; Load offset
+	mov		ss, [%2+2]			; Load segment
+;-----------------------------------
+%else
+	lss		%1, [%2]
+%endif
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Segment override prefix instruction.
+;
+; eSEG
+;	Parameters:
+;		%1:		Name of the segment (ES, CS, SS, DS, FS or GS)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro eSEG 1
+	%ifidni %1, es
+		db	00100110b
+	%elifidni %1, cs
+		db	00101110b
+	%elifidni %1, ss
+		db	00110110b
+	%elifidni %1, ds
+		db	00111110b
+	%elifidni %1, fs
+		db	01100100b
+	%elifidni %1, gs
+		db	01100101b
+	%else
+		%error "Invalid segment overried passed to eSEG!"
+	%endif
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Repeats string instruction with segment override.
+; This macro prevents 8088/8086 restart bug.
+;
+; eSEG_STR
+;	Parameters:
+;		%1:		REP/REPNE or REPE prefix
+;		%2:		Source segment override (destination is always ES)
+;		%3:		String instruction
+;		CX:		Repeat count
+;	Returns:
+;		FLAGS for cmps and scas only
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro eSEG_STR 3
+%ifndef USE_186	; 8088/8086 has string instruction restart bug when more than one prefix
+	 %%Loop:
+	 	%1						; REP is the prefix that can be lost
+	 	eSEG	%2				; SEG is the prefix that won't be lost
+	 	%3						; String instruction
+	 	jcxz	%%End			; Jump to end if no repeats left (preserves FLAGS)
+	 	jmp		SHORT %%Loop	; Loop while repeats left
+	 %%End:
+%else	; No bug on V20/V30 and later, don't know about 188/186
+	eSEG	%2
+	%1		%3
+%endif
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Bit shifts and rotates with immediate.
+;
+; eSHIFT_IM
+;	Parameters:
+;		%1:		Shift target
+;		%2:		Number of bits to shift
+;		%3:		Instruction (SHL, SHR, ROL, ROR, RCL, RCR)
+;	Returns:
+;		FLAGS
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro eSHIFT_IM 3
+%ifndef USE_186
+	%ifidni %1, cl
+		times %2	%3		%1, 1
+	%elifidni %1, ch
+		times %2	%3		%1, 1
+	%elifidni %1, cx
+		times %2	%3		%1, 1
+	%else
+		%if %2 > 7
+			push	cx
+			mov		cl, %2
+			%3		%1, cl
+			pop		cx
+		%else
+			times %2	%3		%1, 1
+		%endif
+	%endif
+;-----------------------------------
+%else
+	%3		%1, %2
+%endif
+%endmacro
+%macro eSHR_IM 2
+	eSHIFT_IM	%1, %2, shr
+%endmacro
+%macro eSHL_IM 2
+	eSHIFT_IM	%1, %2, shl
+%endmacro
+%macro eROR_IM 2
+	eSHIFT_IM	%1, %2, ror
+%endmacro
+%macro eROL_IM 2
+	eSHIFT_IM	%1, %2, rol
+%endmacro
+%macro eRCR_IM 2
+	eSHIFT_IM	%1, %2, rcr
+%endmacro
+%macro eRCL_IM 2
+	eSHIFT_IM	%1, %2, rcl
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Emulates PUSH imm instruction when necessary.
+;
+; ePUSH_I
+;	Parameters:
+;		%1:		Immediate to push
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro ePUSH_I 1
+%ifndef USE_186
+	push	bp					; Immediate goes here
+	push	bp
+	mov		bp, sp
+	mov		WORD [bp+2], %1
+	pop		bp
+;-----------------------------------
+%else
+	push	%1
+%endif
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Emulates PUSH imm instruction when necessary.
+; ePUSH_T uses temporary register for faster performance
+; and smaller code size than ePUSH_I.
+;
+; ePUSH_T
+;	Parameters:
+;		%1:		Temporary Register
+;		%2:		Immediate to push
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		%1
+;--------------------------------------------------------------------
+%macro ePUSH_T 2
+%ifndef USE_186
+	%ifidni %2, 0
+		xor		%1, %1
+	%else
+		mov		%1, %2
+	%endif
+	push	%1
+;-----------------------------------
+%else
+	push	%2
+%endif
+%endmacro
+
+
+%endif ; EMULATE_INC
Index: /tags/Configurator_v1.1.0/Src/BiosFile.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/BiosFile.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/BiosFile.asm	(revision 6)
@@ -0,0 +1,225 @@
+; File name		:	EEPROM.asm
+; Project name	:	XTIDE Univeral BIOS Configurator
+; Created date	:	20.4.2010
+; Last update	:	21.4.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for loading and saving BIOS image file.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Saves changes to loaded BIOS image file if user wants to do so.
+;
+; BiosFile_SaveUnsavedChanges
+;	Parameters:
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+BiosFile_SaveUnsavedChanges:
+	push	ds
+	push	di
+	push	si
+
+	; Check if saving is needed
+	test	WORD [cs:g_cfgVars+CFGVARS.wFlags], FLG_CFGVARS_UNSAVED
+	jz		SHORT .Return
+	test	WORD [cs:g_cfgVars+CFGVARS.wFlags], FLG_CFGVARS_FILELOADED
+	jz		SHORT .Return
+
+	; Ask if user wants to save
+	mov		ax, cs
+	mov		ds, ax
+	mov		es, ax
+	call	BiosFile_DoesUserWantToSaveChanges
+	jnc		SHORT .Return
+
+	; Write file
+	mov		si, 80h									; DS:SI points to default DTA (DOS PSP:80h)
+	mov		di, g_cfgVars+CFGVARS.rgbEepromBuffers	; ES:DI points to data to save
+	call	EEPROM_GenerateChecksum
+	call	BiosFile_SaveFile
+	jc		SHORT .Return							; Return if error
+
+	; Update unsaved status
+	and		WORD [cs:g_cfgVars+CFGVARS.wFlags], ~FLG_CFGVARS_UNSAVED
+ALIGN JUMP_ALIGN
+.Return:
+	pop		si
+	pop		di
+	pop		ds
+	ret
+
+;--------------------------------------------------------------------
+; Asks does user want to save changes to BIOS image file.
+;
+; BiosFile_DoesUserWantToSaveChanges
+;	Parameters:
+;		ES:		String segment
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Set if user wants to save changes
+;				Cleared if used does not want to save changes
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+BiosFile_DoesUserWantToSaveChanges:
+	mov		bl, WIDTH_DLG			; Dialog width
+	mov		di, g_szDlgSaveChanges	; ES:DI points to string to display
+	jmp		Menu_ShowYNDlg
+
+
+;--------------------------------------------------------------------
+; Saves loaded BIOS image to a file.
+;
+; BiosFile_SaveFile
+;	Parameters:
+;		DS:SI:	Ptr to DTA for selected file
+;		ES:DI:	Ptr to data to save
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Cleared if file saved successfully
+;				Set if any error
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+BiosFile_SaveFile:
+	; Open file
+	mov		al, VAL_FACCS_WRITE	; Open for writing
+	lea		dx, [si+DTA.szFile]	; DS:DX points to ASCIZ file name
+	call	File_Open
+	jc		SHORT BiosFile_DisplayFileErrorMessage
+
+	; Save file
+	mov		cx, [cs:g_cfgVars+CFGVARS.wEepromSize]
+	call	File_Write
+	jc		SHORT BiosFile_DisplayFileErrorMessage
+
+	; Close file
+	jmp		SHORT BiosFile_Close
+
+
+;--------------------------------------------------------------------
+; Loads file selected with BiosFile_SelectFile.
+;
+; BiosFile_LoadFile
+;	Parameters:
+;		DS:SI:	Ptr to DTA for selected file
+;		ES:DI:	Ptr to buffer where to load file
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CX:		EEPROM size in bytes
+;		CF:		Cleared if file loaded successfully
+;				Set if any error
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+BiosFile_LoadFile:
+	; Open file
+	mov		al, VAL_FACCS_READ	; Open for reading
+	lea		dx, [si+DTA.szFile]	; DS:DX points to ASCIZ file name
+	call	File_Open
+	jc		SHORT BiosFile_DisplayFileErrorMessage
+
+	; Load file to buffer
+	call	BiosFile_GetFileSizeToCX
+	jc		SHORT BiosFile_DisplayFileSizeErrorMessage
+	call	File_Read
+	jc		SHORT BiosFile_DisplayFileErrorMessage
+
+	; Close file
+BiosFile_Close:
+	call	File_Close
+	jc		SHORT BiosFile_DisplayFileErrorMessage
+	ret
+
+
+;--------------------------------------------------------------------
+; Returns size for selected file and makes sure it is not too large.
+;
+; BiosFile_GetFileSizeToCX
+;	Parameters:
+;		DS:SI:	Ptr to DTA for selected file
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CX:		File size in bytes
+;		CF:		Set if file was too large
+;				Cleared if supported size
+;	Corrupts registers:
+;		DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+BiosFile_GetFileSizeToCX:
+	mov		cx, [si+DTA.dwFileSize]
+	mov		dx, [si+DTA.dwFileSize+2]
+	test	dx, dx						; More than 65535 bytes?
+	jnz		SHORT .TooLargeFile
+	cmp		cx, MAX_EEPROM_SIZE			; Too large?
+	ja		SHORT .TooLargeFile
+	clc
+	ret
+.TooLargeFile:
+	stc
+	ret
+
+
+;--------------------------------------------------------------------
+; Displays error messages related to loading files.
+;
+; BiosFile_DisplayFileErrorMessage
+; BiosFile_DisplayFileSizeErrorMessage
+;	Parameters:
+;		AX:		DOS File I/O error code (BiosFile_DisplayFileErrorMessage only)
+;		DS:SI:	Ptr to DTA for selected file
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Set since error
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+BiosFile_DisplayFileErrorMessage:
+	call	File_GetErrStr		; Error string to ES:DI
+	jmp		SHORT BiosFile_DisplayErrorMessage
+BiosFile_DisplayFileSizeErrorMessage:
+	push	cs
+	pop		es
+	mov		di, g_szErrFileSize
+BiosFile_DisplayErrorMessage:
+	mov		bl, WIDTH_DLG		; Dialog width
+	call	Menu_ShowMsgDlg
+	stc
+	ret
+
+
+;--------------------------------------------------------------------
+; Selects BIOS file to be loaded.
+;
+; BiosFile_SelectFile
+;	Parameters:
+;		DS:DI	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		DS:SI:	Ptr to DTA for selected file
+;		CF:		Set if file selected successfully
+;				Cleared if user cancellation
+;	Corrupts registers:
+;		AX, BX, CX, DX, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+BiosFile_SelectFile:
+	push	di
+	push	cs								; Copy string segment...
+	pop		es								; ...to ES
+	mov		di, [di+MENUPAGEITEM.szDialog]	; ES:DI points to info string
+	mov		si, g_szFileSearch				; DS:SI points to file search string
+	mov		bl, WIDTH_DLG					; Dialog width
+	call	Menu_ShowFileDlg				; Get DTA to DS:SI
+	pop		di
+	ret
Index: /tags/Configurator_v1.1.0/Src/EEPROM.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/EEPROM.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/EEPROM.asm	(revision 6)
@@ -0,0 +1,282 @@
+; File name		:	EEPROM.asm
+; Project name	:	XTIDE Univeral BIOS Configurator
+; Created date	:	19.4.2010
+; Last update	:	2.5.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for managing EEPROM contents.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Loads XTIDE Universal BIOS from ROM to RAM to be configured.
+;
+; EEPROM_LoadBiosFromROM
+;	Parameters:
+;		Nothing
+;	Returns:
+;		CX:		BIOS size in bytes
+;	Corrupts registers:
+;		AX, BX, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+EEPROM_LoadBiosFromROM:
+	push	si
+	call	EEPROM_FindXtideUniversalBiosROM
+	xor		si, si									; Load from beginning of ROM
+	eMOVZX	cx, BYTE [es:ROMVARS.bRomSize]
+	eSHL_IM	cx, 9									; *= 512 for byte count
+	call	EEPROM_LoadBytesFromROM
+	pop		si
+	ret
+
+
+;--------------------------------------------------------------------
+; Loads old XTIDE Universal BIOS settings from ROM to RAM.
+;
+; EEPROM_LoadSettingsFromRomToRam
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, SI, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+EEPROM_LoadSettingsFromRomToRam:
+	mov		cx, ROMVARS_size - ROMVARS.wFlags	; Number of bytes to load
+	mov		si, ROMVARS.wFlags					; Offset where to start loading
+	; Fall to EEPROM_LoadBytesFromROM
+
+;--------------------------------------------------------------------
+; Loads wanted number of bytes from XTIDE Universal BIOS ROM.
+;
+; EEPROM_LoadBytesFromROM
+;	Parameters:
+;		CX:		Number of bytes to load from beginning of ROM
+;		SI:		Offset to first byte
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, SI, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+EEPROM_LoadBytesFromROM:
+	push	ds
+	push	di
+	push	cx
+
+	call	EEPROM_FindXtideUniversalBiosROM
+	push	es
+	pop		ds											; DS:SI points to ROM
+	push	cs
+	pop		es
+	lea		di, [si+g_cfgVars+CFGVARS.rgbEepromBuffers]	; ES:DI points to RAM buffer
+	shr		cx, 1										; Byte count to word count
+	cld													; MOVSW to increment SI and DI
+	rep movsw											; Read from ROM to RAM
+
+	pop		cx
+	pop		di
+	pop		ds
+	ret
+
+
+;--------------------------------------------------------------------
+; Finds EEPROM using known signature.
+;
+; EEPROM_FindXtideUniversalBiosROM
+;	Parameters:
+;		Nothing
+;	Returns:
+;		ES:		EEPROM segment
+;		CF:		Set if EEPROM was found
+;				Cleared if EEPROM not found
+;	Corrupts registers:
+;		AX, BX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+EEPROM_FindXtideUniversalBiosROM:
+	push	di
+	xor		di, di					; Zero DI
+	mov		bx, 0C000h				; First possible ROM segment
+ALIGN JUMP_ALIGN
+.SegmentLoop:
+	mov		es, bx					; Possible ROM segment to ES
+	call	EEPROM_IsXtideUniversalBiosSignaturePresent
+	je		SHORT .RomFound
+	add		bx, 200h				; Increment by 8kB
+	jnc		SHORT .SegmentLoop		; Loop until segment overflows
+	pop		di
+	clc
+	ret
+ALIGN JUMP_ALIGN
+.RomFound:
+	pop		di
+	stc
+	ret
+
+
+;--------------------------------------------------------------------
+; Checks if XTIDE Universal BIOS is loaded to be configured.
+;
+; EEPROM_IsXtideUniversalBiosLoaded
+;	Parameters:
+;		Nothing
+;	Returns:
+;		ZF:		Set if signature found
+;				Cleared if signature not present
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+EEPROM_IsXtideUniversalBiosLoaded:
+	push	es
+	push	di
+
+	push	cs
+	pop		es
+	mov		di, g_cfgVars+CFGVARS.rgbEepromBuffers
+	call	EEPROM_IsXtideUniversalBiosSignaturePresent
+
+	pop		di
+	pop		es
+	ret
+
+
+;--------------------------------------------------------------------
+; Checks if ROM contains Xtide Universal BIOS signature.
+;
+; EEPROM_IsXtideUniversalBiosSignaturePresent
+;	Parameters:
+;		ES:DI:	Ptr to ROM contents
+;	Returns:
+;		ZF:		Set if signature found
+;				Cleared if signature not present
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+EEPROM_IsXtideUniversalBiosSignaturePresent:
+	push	ds
+	push	di
+	push	si
+	push	cx
+
+	push	cs
+	pop		ds
+	mov		si, g_szSignature			; DS:SI points to known signature string
+	add		di, BYTE ROMVARS.rgbSign	; ES:DI points to possible ROM signature
+	mov		cx, LEN_SIGNATURE/2			; Signature string length in words
+	cld									; CMPSW to increment DI and SI
+	repe cmpsw
+
+	pop		cx
+	pop		si
+	pop		di
+	pop		ds
+	ret
+
+
+;--------------------------------------------------------------------
+; Called when new BIOS has been loaded to be flashed.
+;
+; EEPROM_NewBiosLoadedFromFileOrROM
+;	Parameters:
+;		AX:		EEPROM source (FLG_CFGVARS_FILELOADED or FLG_CFGVARS_ROMLOADED)
+;		CX:		EEPROM size in bytes
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+EEPROM_NewBiosLoadedFromFileOrROM:
+	and		WORD [cs:g_cfgVars+CFGVARS.wFlags], ~(FLG_CFGVARS_FILELOADED | FLG_CFGVARS_ROMLOADED | FLG_CFGVARS_UNSAVED)
+	or		WORD [cs:g_cfgVars+CFGVARS.wFlags], ax
+	mov		WORD [cs:g_cfgVars+CFGVARS.wEepromSize], cx
+	ret
+
+
+;--------------------------------------------------------------------
+; Generated checksum byte to the end of BIOS image buffer.
+;
+; EEPROM_GenerateChecksum
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+EEPROM_GenerateChecksum:
+	xor		ax, ax
+	mov		bx, g_cfgVars+CFGVARS.rgbEepromBuffers
+	mov		cx, [cs:g_cfgVars+CFGVARS.wEepromSize]
+	dec		cx
+ALIGN JUMP_ALIGN
+.ByteLoop:
+	add		al, [cs:bx]
+	inc		bx
+	loop	.ByteLoop
+	neg		al
+	mov		[cs:bx], al
+	ret
+
+
+;--------------------------------------------------------------------
+; Returns pointer source data to be flashed to EEPROM.
+;
+; EEPROM_GetSourceBufferPointerToDSSI
+;	Parameters:
+;		Nothing
+;	Returns:
+;		DS:SI:		Ptr to source buffer
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+EEPROM_GetSourceBufferPointerToDSSI:
+	push	cs
+	pop		ds
+	mov		si, g_cfgVars+CFGVARS.rgbEepromBuffers
+	ret
+
+
+;--------------------------------------------------------------------
+; Returns pointer to comparison buffer for old EEPROM data.
+;
+; EEPROM_GetComparisonBufferPointerToDSBX
+;	Parameters:
+;		Nothing
+;	Returns:
+;		DS:BX:		Ptr to verify buffer
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+EEPROM_GetComparisonBufferPointerToDSBX:
+	push	cs
+	pop		ds
+	mov		bx, [cs:g_cfgVars+CFGVARS.wEepromSize]
+	add		bx, g_cfgVars+CFGVARS.rgbEepromBuffers
+	ret
+
+
+;--------------------------------------------------------------------
+; Returns pointer to EEPROM where to flash.
+;
+; EEPROM_GetEepromPointerToESDI
+;	Parameters:
+;		Nothing
+;	Returns:
+;		ES:DI:		Ptr to EEPROM
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+EEPROM_GetEepromPointerToESDI:
+	mov		es, [cs:g_cfgVars+CFGVARS.wEepromSegment]
+	xor		di, di
+	ret
Index: /tags/Configurator_v1.1.0/Src/Flash.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Flash.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Flash.asm	(revision 6)
@@ -0,0 +1,290 @@
+; File name		:	Flash.asm
+; Project name	:	XTIDE Univeral BIOS Configurator
+; Created date	:	30.4.2010
+; Last update	:	2.5.2010
+; Author		:	Tomi Tilli
+; Description	:	Function for flashing the EEPROM.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Loads old XTIDE Universal BIOS settings from ROM to RAM.
+;
+; EEPROM_LoadSettingsFromRomToRam
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		BX, CX, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Flash_CopyCurrentContentsForComparison:
+	push	ds
+	push	di
+	push	si
+
+	call	EEPROM_GetComparisonBufferPointerToDSBX
+	push	ds
+	pop		es
+	mov		di, bx										; Comparison buffer now in ES:DI
+	xor		si, si
+	mov		ds, [cs:g_cfgVars+CFGVARS.wEepromSegment]	; EEPROM now in DS:SI
+	mov		cx, [cs:g_cfgVars+CFGVARS.wEepromSize]
+	shr		cx, 1			; Byte count to word count
+	cld													; MOVSW to increment DI and SI
+	rep movsw
+
+	pop		si
+	pop		di
+	pop		ds
+	ret
+
+
+;--------------------------------------------------------------------
+; Verifies that all data has been written successfully.
+;
+; Flash_WasDataWriteSuccessfull
+;	Parameters:
+;		Nothing
+;	Returns:
+;		ZF:		Set if data was written successfully
+;				Cleared if write failed
+;	Corrupts registers:
+;		CX, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Flash_WasDataWriteSuccessfull:
+	push	ds
+	push	di
+	push	si
+
+	call	EEPROM_GetSourceBufferPointerToDSSI
+	call	EEPROM_GetEepromPointerToESDI
+	mov		cx, [cs:g_cfgVars+CFGVARS.wEepromSize]
+	shr		cx, 1			; Byte count to word count
+	cld						; CMPSW to increment SI and DI
+	repe cmpsw
+
+	pop		si
+	pop		di
+	pop		ds
+	ret
+
+
+;--------------------------------------------------------------------
+; Writes page of data to EEPROM.
+;
+; Flash_WritePage
+;	Parameters:
+;		AX:		SDP command
+;		CX:		Page size (1, 2, 4, 8, 16, 32 or 64 bytes)
+;		DS:BX:	Ptr to comparison buffer with old EEPROM data
+;		DS:SI:	Ptr to source data to write
+;		ES:DI:	Ptr to destination EEPROM
+;	Returns:
+;		BX, SI, DI:	Updated to next page
+;		CF:		Cleared if page written successfully
+;				Set if polling timeout
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Flash_WritePage:
+	call	Flash_DoesPageNeedToBeWritten
+	jz		SHORT .ReturnWithoutWriting
+	push	bp
+	push	cx
+	push	ax
+
+	mov		bp, .LoopWritePageBytes	; Return address from SDP command
+	cli								; Disable interrupts
+	jmp		SHORT Flash_WriteSdpCommand
+
+ALIGN JUMP_ALIGN
+.LoopWritePageBytes:
+	lodsb							; Load source byte to AL, increment SI
+	cmp		al, [bx]				; Trying to write existing data?
+	je		SHORT .SkipByte
+	inc		bx						; Increment comparison buffer pointer
+	mov		ah, al					; Last byte written to AH
+	mov		bp, di					; ES:BP points to last byte written
+	stosb							; Write source byte to EEPROM, increment DI
+	loop	.LoopWritePageBytes
+	jmp		SHORT .PageCompleted
+ALIGN JUMP_ALIGN
+.SkipByte:
+	inc		bx
+	inc		di
+	loop	.LoopWritePageBytes
+
+ALIGN JUMP_ALIGN
+.PageCompleted:
+	sti								; Enable interrupts
+	call	Flash_PollEepromUntilWriteCycleHasCompleted
+	pop		ax
+	pop		cx
+	pop		bp
+	ret
+
+ALIGN JUMP_ALIGN
+.ReturnWithoutWriting:
+	add		bx, cx
+	add		si, cx
+	add		di, cx
+	clc
+	ret
+
+;--------------------------------------------------------------------
+; Compares source data and comparison buffer.
+;
+; Flash_DoesPageNeedToBeWritten
+;	Parameters:
+;		CX:		Page size (1, 2, 4, 8, 16, 32 or 64 bytes)
+;		DS:BX:	Ptr to comparison buffer with old EEPROM data
+;		DS:SI:	Ptr to source data to write
+;	Returns:
+;		ZF:		Set if no need to write page
+;				Cleared if writing is needed
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Flash_DoesPageNeedToBeWritten:
+	push	es
+	push	di
+	push	si
+	push	cx
+
+	push	ds
+	pop		es
+	mov		di, bx				; ES:DI now points to comparison buffer
+	cld							; CMPSB to increment SI and DI
+	repe cmpsb
+
+	pop		cx
+	pop		si
+	pop		di
+	pop		es
+	ret
+
+
+;--------------------------------------------------------------------
+; Writes Software Data Protection command to EEPROM.
+;
+; Flash_WriteSdpCommand
+;	Parameters:
+;		AX:		SDP command
+;		BP:		Return address
+;		ES:		Segment to EEPROM
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Flash_WriteSdpCommand:
+	cmp		ax, CMD_SDP_ENABLE
+	je		SHORT Flash_WriteSdpEnableCommand
+	cmp		ax, CMD_SDP_DISABLE
+	je		SHORT Flash_WriteSdpDisableCommand
+	jmp		bp
+
+ALIGN JUMP_ALIGN
+Flash_WriteSdpEnableCommand:
+	mov		BYTE [es:1555h], 0AAh	; Write AAh to address 1555h
+	mov		BYTE [es:0AAAh], 55h	; Write 55h to address 0AAAh
+	mov		BYTE [es:1555h], 0A0h	; Write A0h to address 1555h
+	jmp		bp
+
+ALIGN JUMP_ALIGN
+Flash_WriteSdpDisableCommand:
+	mov		BYTE [es:1555h], 0AAh	; Write AAh to address 1555h
+	mov		BYTE [es:0AAAh], 55h	; Write 55h to address 0AAAh
+	mov		BYTE [es:1555h], 80h	; Write 80h to address 1555h
+	mov		BYTE [es:1555h], 0AAh	; Write AAh to address 1555h
+	mov		BYTE [es:0AAAh], 55h	; Write 55h to address 0AAAh
+	mov		BYTE [es:1555h], 20h	; Write 20h to address 1555h
+	jmp		bp
+
+
+;--------------------------------------------------------------------
+; Polls EEPROM until write cycle ends.
+;
+; Flash_PollEepromUntilWriteCycleHasCompleted
+;	Parameters:
+;		AH:		Last byte written
+;		ES:BP:	Ptr to EEPROM last write location
+;	Returns:
+;		CF:		Cleared if polling successfull
+;				Set if polling timeout
+;	Corrupts registers:
+;		AX, CX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Flash_PollEepromUntilWriteCycleHasCompleted:
+	call	Flash_InitializePollingTimeout
+ALIGN JUMP_ALIGN
+.PollLoop:
+	mov		al, [es:bp]				; Load byte from EEPROM
+	and		ax, 8080h				; Clear all but bit 7 from both bytes
+	cmp		al, ah					; Same bytes?
+	je		SHORT .Return
+	call	Flash_UpdatePollingTimeout
+	jnc		SHORT .PollLoop			; Not timeout
+ALIGN JUMP_ALIGN
+.Return:
+	ret
+
+;--------------------------------------------------------------------
+; Initializes timeout counter. Timeouts are implemented using system
+; timer ticks. First tick might take 0...54.9ms and remaining ticks
+; will occur at 54.9ms intervals. Use delay of two (or more) ticks to
+; ensure at least 54.9ms wait.
+;
+; Flash_InitializePollingTimeout
+;	Parameters:
+;		Nothing
+;	Returns:
+;		CX:		Timeout end time for Flash_UpdatePollingTimeout
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Flash_InitializePollingTimeout:
+	push	ds
+	LOAD_BDA_SEGMENT_TO	ds, cx
+	mov		cx, CNT_TMEOUT_POLL
+	add		cx, [BDA.dwTimerTicks]		; CX = End time
+	pop		ds
+	sti									; Enable interrupts
+	ret
+
+;--------------------------------------------------------------------
+; Updates timeout counter. Timeout counter can be
+; initialized with Flash_InitializePollingTimeout.
+;
+; Flash_UpdatePollingTimeout
+;	Parameters:
+;		CX:		Timeout end time
+;	Returns:
+;		CF:		Set if timeout
+;				Cleared if time left
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Flash_UpdatePollingTimeout:
+	push	ds
+	push	ax
+	LOAD_BDA_SEGMENT_TO	ds, ax
+	cmp		cx, [BDA.dwTimerTicks]		; Timeout?
+	pop		ax
+	pop		ds
+	je		SHORT .ReturnTimeout
+	clc
+	ret
+.ReturnTimeout:
+	stc
+	ret
Index: /tags/Configurator_v1.1.0/Src/FormatTitle.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/FormatTitle.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/FormatTitle.asm	(revision 6)
@@ -0,0 +1,143 @@
+; File name		:	FormatTitle.asm
+; Project name	:	XTIDE Univeral BIOS Configurator
+; Created date	:	19.4.2010
+; Last update	:	20.4.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for printing menu title strings.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Redraws menu title strings.
+;
+; FormatTitle_RedrawMenuTitle
+;	Parameters:
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+FormatTitle_RedrawMenuTitle:
+	mov		dl, MFL_UPD_TITLE						; Invalidate Title strings
+	jmp		Menu_Invalidate
+
+
+;--------------------------------------------------------------------
+; Prints title strings for menu system.
+;
+; FormatTitle_String
+;	Parameters:
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+FormatTitle_String:
+	mov		ax, cs
+	mov		ds, ax
+	mov		es, ax
+	call	FormatTitle_PrintProgramName
+	call	FormatTitle_PrintImageSource
+	jmp		SHORT FormatTitle_PrintUnsavedChanges
+
+
+;--------------------------------------------------------------------
+; Prints program name.
+;
+; FormatTitle_PrintProgramName
+;	Parameters:
+;		SS:BP:	Ptr to MENUVARS
+;		DS=ES:	String segment
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+FormatTitle_PrintProgramName:
+	mov		di, g_szTitleProgramName
+	mov		cx, CNT_TITLE_LINES
+	call	MenuDraw_MultilineStr
+	call	MenuDraw_NewlineStr
+	jmp		MenuDraw_NewlineStr
+
+
+;--------------------------------------------------------------------
+; Prints where BIOS image is loaded from.
+;
+; FormatTitle_PrintImageSource
+;	Parameters:
+;		SS:BP:	Ptr to MENUVARS
+;		DS=ES:	String segment
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+FormatTitle_PrintImageSource:
+	test	WORD [g_cfgVars+CFGVARS.wFlags], FLG_CFGVARS_FILELOADED | FLG_CFGVARS_ROMLOADED
+	jz		SHORT FormatTitle_NothingLoaded
+	mov		dx, g_szImageSource
+	PRINT_STR
+	test	WORD [g_cfgVars+CFGVARS.wFlags], FLG_CFGVARS_FILELOADED
+	jnz		SHORT FormatTitle_FileLoaded
+	; Fall to FormatTitle_RomLoaded
+
+;--------------------------------------------------------------------
+; FormatTitle_RomLoaded
+; FormatTitle_FileLoaded
+; FormatTitle_NothingLoaded
+;	Parameters:
+;		SS:BP:	Ptr to MENUVARS
+;		DS=ES:	String segment
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+;ALIGN JUMP_ALIGN
+FormatTitle_RomLoaded:
+	mov		dx, g_szRomLoaded
+	PRINT_STR
+	ret
+
+ALIGN JUMP_ALIGN
+FormatTitle_FileLoaded:
+	mov		dx, 80h + DTA.szFile	; DTA starts at DOS PSP:80h
+	PRINT_STR
+	ret
+
+ALIGN JUMP_ALIGN
+FormatTitle_NothingLoaded:
+	mov		dx, g_szNoBiosLoaded
+	PRINT_STR
+	ret
+
+
+;--------------------------------------------------------------------
+; Prints unsaved changes.
+;
+; FormatTitle_PrintUnsavedChanges
+;	Parameters:
+;		SS:BP:	Ptr to MENUVARS
+;		DS=ES:	String segment
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+FormatTitle_PrintUnsavedChanges:
+	test	WORD [g_cfgVars+CFGVARS.wFlags], FLG_CFGVARS_UNSAVED
+	jz		SHORT .Return
+	mov		dl, '*'
+	PRINT_CHAR
+ALIGN JUMP_ALIGN
+.Return:
+	ret
Index: /tags/Configurator_v1.1.0/Src/Libraries/file.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Libraries/file.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Libraries/file.asm	(revision 6)
@@ -0,0 +1,499 @@
+; File name		:	file.asm
+; Project name	:	File library
+; Created date	:	19.11.2009
+; Last update	:	24.11.2009
+; Author		:	Tomi Tilli
+; Description	:	ASM library for DOS file handling.	
+
+;--------------- Equates -----------------------------
+
+; DOS DTA (Disk Transfer Area)
+struc DTA
+	; Undocumented fields
+	.reserved	resb	21
+	; Documented fields
+	.bFileAttr	resb	1	; 15h, Attribute of matching file
+	.wFileTime	resb	2	; 16h, File time
+	.wFileDate	resb	2	; 18h, File date
+	.dwFileSize	resb	4	; 1Ah, File size in bytes
+	.szFile		resb	13	; 1Eh, ASCIZ filename + extension
+endstruc
+
+; Bits for file attribute byte
+FLG_FATTR_RDONLY	EQU		(1<<0)	; Read only
+FLG_FATTR_HIDDEN	EQU		(1<<1)	; Hidden
+FLG_FATTR_SYS		EQU		(1<<2)	; System
+FLG_FATTR_LABEL		EQU		(1<<3)	; Volume Label
+FLG_FATTR_DIR		EQU		(1<<4)	; Directory
+FLG_FATTR_ARCH		EQU		(1<<5)	; Archive
+
+; File access and sharing modes
+VAL_FACCS_READ		EQU		0		; Read only
+VAL_FACCS_WRITE		EQU		1		; Write only
+VAL_FACCS_RW		EQU		2		; Read and Write
+
+; DOS File I/O error codes
+ERR_DOS_SUCCESS		EQU		0		; No error
+ERR_DOS_FUNC		EQU		1		; Function number invalid
+ERR_DOS_NOFILE		EQU		2		; File not found
+ERR_DOS_NOPATH		EQU		3		; Path not found
+ERR_DOS_TOOMANY		EQU		4		; Too many open files
+ERR_DOS_DENIED		EQU		5		; Access denied
+ERR_DOS_HANDLE		EQU		6		; Invalid handle
+ERR_DOS_CODE		EQU		12		; Access code invalid
+ERR_DOS_NOMORE		EQU		18		; No more files
+
+
+;-------------- Private global variables -------------
+; Section containing initialized data
+;SECTION .data
+
+; DOS file I/O related error strings
+g_szNoErr:		db	"No error",STOP
+g_szFunc:		db	"Function number invalid",STOP
+g_szNoFile:		db	"File not found",STOP
+g_szNoPath:		db	"Path not found",STOP
+g_szTooMany:	db	"Too many open files",STOP
+g_szDenied:		db	"Access denied",STOP
+g_szHandle:		db	"Invalid handle",STOP
+g_szCode:		db	"Access code invalid",STOP
+g_szNoMore:		db	"No more files",STOP
+g_szUnknown:	db	"Unknown file I/O error",STOP
+
+
+;-------------- Public functions ---------------------
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Returns pointer to error string.
+; Pointer is always valid, even if error code is not.
+; 
+; File_GetErrStr
+;	Parameters:
+;		AX:		DOS File I/O error code
+;	Returns:
+;		ES:DI:	Ptr to error string
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+File_GetErrStr:
+	mov		di, g_szNoMore		; Assume ERR_DOS_NOMORE
+	cmp		ax, ERR_DOS_NOMORE
+	je		.Return
+	mov		di, g_szCode		; Assume ERR_DOS_CODE
+	cmp		ax, ERR_DOS_CODE
+	je		.Return
+	mov		di, g_szUnknown		; Assume unknown error
+	cmp		ax, ERR_DOS_HANDLE	; Can use lookup?
+	ja		.Return				;  If not, return
+	mov		di, ax				; Copy error code to DI
+	shl		di, 1				; Shift for word lookup
+	mov		di, [cs:di+.rgwErrLookup]
+ALIGN JUMP_ALIGN
+.Return:
+	push	cs					; Copy CS...
+	pop		es					; ...to ES
+	ret
+ALIGN WORD_ALIGN
+.rgwErrLookup:
+	dw	g_szNoErr	; 0
+	dw	g_szFunc	; 1
+	dw	g_szNoFile	; 2
+	dw	g_szNoPath	; 3
+	dw	g_szTooMany	; 4
+	dw	g_szDenied	; 5
+	dw	g_szHandle	; 6
+
+
+;--------------------------------------------------------------------
+; Opens file for reading and writing.
+; File must be closed with File_Close when no longer needed.
+; 
+; File_Open
+;	Parameters:
+;		AL:		File access and sharing mode:
+;					VAL_FACCS_READ	Open file for reading
+;					VAL_FACCS_WRITE	Open file for writing
+;					VAL_FACCS_RW	Open file for read and write
+;		DS:DX:	Ptr to destination ASCIZ file name
+;	Returns:
+;		AX:		DOS error code if CF set
+;		BX:		File handle if CF cleared
+;		CF:		Clear if file opened successfully
+;				Set if error
+;	Corrupts registers:
+;		AX, BX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+File_Open:
+	mov		ah, 3Dh				; Open Existing File
+	int		21h
+	mov		bx, ax				; Copy handle to BX
+	ret
+
+
+;--------------------------------------------------------------------
+; Closes file.
+; 
+; File_Close
+;	Parameters:
+;		BX:		File handle
+;	Returns:
+;		AX:		DOS error code if CF set
+;		CF:		Clear if file closed successfully
+;				Set if error
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+File_Close:
+	mov		ah, 3Eh				; Open Existing File
+	int		21h
+	ret
+
+
+;--------------------------------------------------------------------
+; Reads binary data from file.
+; File position is updated so next read will start where
+; previous read stopped.
+; 
+; File_Read
+;	Parameters:
+;		BX:		File handle
+;		CX:		Number of bytes to read
+;		ES:DI:	Ptr to destination buffer
+;	Returns:
+;		AX:		Number of bytes actually read if successfull (EOF check)
+;				DOS error code if CF set
+;		CF:		Clear if successfull
+;				Set if error
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+File_Read:
+	push	ds
+	push	dx
+	push	es					; Copy ES...
+	pop		ds					; ...to DS
+	mov		dx, di				; DS:DX now points to destination buffer
+	mov		ah, 3Fh				; Read from File or Device
+	int		21h
+	pop		dx
+	pop		ds
+	ret
+
+
+;--------------------------------------------------------------------
+; Writes binary data to file.
+; File position is updated so next write will start where
+; previous write stopped.
+; 
+; File_Write
+;	Parameters:
+;		BX:		File handle
+;		CX:		Number of bytes to write
+;		ES:DI:	Ptr to source buffer
+;	Returns:
+;		AX:		Number of bytes actually written if successfull (EOF check)
+;				DOS error code if CF set
+;		CF:		Clear if successfull
+;				Set if error
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+File_Write:
+	push	ds
+	push	dx
+	push	es					; Copy ES...
+	pop		ds					; ...to DS
+	mov		dx, di				; DS:DX now points to source buffer
+	mov		ah, 40h				; Write to File or Device
+	int		21h
+	pop		dx
+	pop		ds
+	ret
+
+
+;--------------------------------------------------------------------
+; Sets current file position to wanted offset.
+; 
+; File_SetFilePos
+;	Parameters:
+;		BX:		File handle
+;		CX:DX:	New offset (signed)
+;	Returns:
+;		AX:		DOS error code if CF set
+;		CF:		Clear if successfull
+;				Set if error
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+File_SetFilePos:
+	push	dx
+	mov		ax, 42h<<8			; Set Current File Position (from file start)
+	int		21h
+	pop		dx
+	ret
+
+
+;--------------------------------------------------------------------
+; Changes current default drive.
+; 
+; File_SetDrive
+;	Parameters:
+;		DL:		New default drive (00h=A:, 01h=B: ...)
+;	Returns:
+;		AL:		Number of potentially valid drive letters available
+;	Corrupts registers:
+;		AH
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+File_SetDrive:
+	mov		ah, 0Eh				; Select Default Drive
+	int		21h
+	ret
+
+
+;--------------------------------------------------------------------
+; Returns current default drive and number of
+; potentially drive letters available.
+; 
+; File_GetDrive
+;	Parameters:
+;		Nothing
+;	Returns:
+;		AL:		Number of potentially valid drive letters available
+;		AH:		Current default drive (00h=A:, 01h=B: ...)
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+File_GetDrive:
+	push	dx
+	mov		ah, 19h				; Get Current Default Drive
+	int		21h					; Get drive to AL
+	mov		dl, al				; Copy drive number to DL
+	call	File_SetDrive		; Set to current and get drive letter count
+	mov		ah, dl				; Copy current drive to AH
+	pop		dx
+	ret
+
+
+;--------------------------------------------------------------------
+; Checks are the potentially valid drive letters returned by 
+; File_SetDrive and File_GetDrive actually valid or not.
+; 
+; File_IsDrive
+;	Parameters:
+;		DL:		Drive number (00h=A:, 01h=B: ...)
+;	Returns:
+;		AL:		00h if valid drive number, FFh if invalid drive number
+;		ZF:		Set if drive number is valid
+;				Cleared if drive number is invalid
+;	Corrupts registers:
+;		AH
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+File_IsDrive:
+	push	ds
+	push	bx
+	inc		dx					; 00h=default drive, 01h=A:, 02h=B: ...
+	mov		ah, 32h				; Get DOS Drive Parameter Block for Specific Drive
+	int		21h
+	dec		dx					; Restore DX
+	test	al, al				; Set ZF according to result
+	pop		bx
+	pop		ds
+	ret
+
+
+;--------------------------------------------------------------------
+; Returns number of valid drive letters.
+; 
+; File_GetValidDrvCnt
+;	Parameters:
+;		Nothing
+;	Returns:
+;		CX:		Number of valid drives
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+File_GetValidDrvCnt:
+	call	File_GetDrive		; Get potential drive letters to AL
+	eMOVZX	cx, al				; Letter count to CX
+	xor		dx, dx				; Zero DX (DH=valid count, DL=drv num)
+ALIGN JUMP_ALIGN
+.LetterLoop:
+	call	File_IsDrive
+	not		al					; Invert return bits
+	and		al, 1				; Clear all but bit 1
+	add		dh, al				; Increment valid count
+	inc		dx					; Increment drive number
+	loop	.LetterLoop			; Loop while drive letters left
+	eMOVZX	cx, dh				; Valid drv count to CX
+	ret
+
+
+;--------------------------------------------------------------------
+; Return device number for Nth valid drive.
+; This function does not check if index in CX is valid.
+; 
+; File_GetNthValidDrv
+;	Parameters:
+;		CX:		Index of valid drive to look for
+;	Returns:
+;		AX:		Drive letter (A, B...)
+;		DX:		Drive device number (00h=A:, 01h=B: ...)
+;	Corrupts registers:
+;		CX
+;--------------------------------------------------------------------	
+ALIGN JUMP_ALIGN
+File_GetNthValidDrv:
+	inc		cx					; Index to count
+	mov		dx, -1				; Dev num, increments to zero
+ALIGN JUMP_ALIGN
+.DrvLoop:
+	inc		dx					; Increment device number
+	call	File_IsDrive		; Is drive valid?
+	jnz		.DrvLoop			;  Loop if not
+	loop	.DrvLoop			; Loop until wanted drive found
+	mov		ax, dx				; Drive device number to AX
+	add		ax, 'A'				; Dev number to drive letter
+	ret
+
+
+;--------------------------------------------------------------------
+; Changes current directory.
+; 
+; File_ChangeDir
+;	Parameters:
+;		DS:DX	Ptr to destination ASCIZ path name
+;	Returns:
+;		AX:		DOS Error code
+;		CF:		Clear if successfull
+;				Set if error
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+File_ChangeDir:
+	mov		ah, 3Bh				; Set Current Directory
+	int		21h
+	ret
+
+
+;--------------------------------------------------------------------
+; Finds files from wanted path using search wildcard characters.
+; 
+; File_FindAndCount
+;	Parameters:
+;		DS:DX	Ptr to ASCIZ path or file name (* and ? wildcards allowed)
+;	Returns:
+;		CX:		Number of files found
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+File_IsFile:
+File_FindAndCount:
+	xor		cx, cx				; Zero file count
+	call	File_FindFirst		; Find first file
+	jc		.Return				; Return if no files found
+ALIGN JUMP_ALIGN
+.IsNextLoop:
+	inc		cx					; Increment file count
+	call	File_FindNext		; Find next file
+	jnc		.IsNextLoop			; Loop while files left
+ALIGN JUMP_ALIGN
+.Return:
+	ret
+
+
+;--------------------------------------------------------------------
+; Finds files from wanted path using search wildcard characters.
+; Ptr to DTA is returned for wanted file.
+; 
+; File_GetDTA
+;	Parameters:
+;		CX:		Index for file whose DTA is to be returned
+;		DS:DX	Ptr to ASCIZ path or file name (* and ? wildcards allowed)
+;	Returns:
+;		DS:BX:	Ptr to file DTA
+;		CF:		Set if file was not found
+;				Cleared if file found and DTA is returned
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+File_GetDTA:
+	call	File_FindFirst		; Find first file
+	jc		.RetErr				; Return if no files found
+	xor		dx, dx				; Zero file index
+ALIGN JUMP_ALIGN
+.IsNextLoop:
+	cmp		cx, dx				; Wanted file found?
+	je		.RetDTA				;  If so, jump to return DTA
+	inc		dx					; Increment index for next file
+	call	File_FindNext		; Find next file
+	jnc		.IsNextLoop			; Loop while files left
+.RetErr:
+	ret
+ALIGN JUMP_ALIGN
+.RetDTA:
+	push	cs					; Push code segment
+	pop		ds					; CS to DS
+	mov		bx, 80h				; DTA starts at DOS PSP:80h
+	ret
+
+
+;-------------- Private functions ---------------------
+
+;--------------------------------------------------------------------
+; Find first file or directory.
+; 
+; File_FindFirst
+;	Parameters:
+;		DS:DX	Ptr to ASCIZ path or file name (* and ? wildcards allowed)
+;	Returns:
+;		AX:		DOS Error code
+;		CF:		Set if file was not found
+;				Cleared if file was found
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+File_FindFirst:
+	push	cx
+	;mov		cx, FLG_FATTR_DIR	; Directories and files
+	xor		cx, cx
+	mov		ax, 4Eh<<8			; Find First Matching File
+	int		21h
+	pop		cx
+	ret
+
+
+;--------------------------------------------------------------------
+; Find next file or directory. File_FindFirst must always be called
+; before calling File_FindNext.
+; 
+; File_FindNext
+;	Parameters:
+;		Nothing
+;	Returns:
+;		AX:		DOS Error code
+;		CF:		Set if file was not found
+;				Cleared if file was found
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+File_FindNext:
+	mov		ah, 4Fh				; Find Next Matching File
+	int		21h
+	ret
Index: /tags/Configurator_v1.1.0/Src/Libraries/keys.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Libraries/keys.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Libraries/keys.asm	(revision 6)
@@ -0,0 +1,328 @@
+; File name		:	keys.asm
+; Project name	:	Keyboard library
+; Created date	:	17.11.2009
+; Last update	:	31.12.2009
+; Author		:	Tomi Tilli
+; Description	:	ASM library to for keyboard related functions.		
+
+;--------------- Equates -----------------------------
+
+; String library function to include
+%define USE_KEYS_STROKE			; Keys_GetStroke, Keys_IsStroke and Keys_WaitStroke
+%define USE_KEYS_PRNTGETUINT	; Keys_PrintGetUint
+%define USE_KEYS_PRNTGETYN		; Keys_PrintGetYN
+%define USE_KEYS_CLRBUFFER		; Keys_ClrBuffer
+
+; Some BIOS Scan Codes
+KEY_BSC_F1		EQU		3Bh
+KEY_BSC_F2		EQU		3Ch
+KEY_BSC_F3		EQU		3Dh
+KEY_BSC_F4		EQU		3Eh
+KEY_BSC_F5		EQU		3Fh
+KEY_BSC_F6		EQU		40h
+KEY_BSC_F7		EQU		41h
+KEY_BSC_F8		EQU		42h
+KEY_BSC_F9		EQU		43h
+KEY_BSC_F10		EQU		44h
+KEY_BSC_F11		EQU		57h
+KEY_BSC_F12		EQU		58h
+
+
+;-------------- Private global variables -------------
+; Section containing initialized data
+;SECTION .data
+
+
+;-------------- Public functions ---------------------
+; Section containing code
+SECTION .text
+
+
+;--------------------------------------------------------------------
+; Checks is keystroke available in keyboard buffer.
+; 
+; Keys_GetStroke	Removes key from buffer if keystroke available
+; Keys_IsStroke		Does not remove key from buffer
+; Keys_WaitStroke	Waits until keystroke is available and removes it from buffer
+;	Parameters:
+;		Nothing
+;	Returns:
+;		AL:		ASCII character (if keystroke available)
+;		AH:		BIOS scan code (if keystroke available)
+;		ZF:		Set if no keystroke available
+;				Cleared if keystroke available
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%ifdef USE_KEYS_STROKE
+ALIGN JUMP_ALIGN
+Keys_GetStroke:
+	call	Keys_IsStroke
+	jnz		Keys_WaitStroke
+	ret
+ALIGN JUMP_ALIGN
+Keys_IsStroke:
+	mov		ah, 01h				; Check for Keystroke
+	int		16h
+	ret
+ALIGN JUMP_ALIGN
+Keys_WaitStroke:
+	xor		ah, ah				; Get Keystroke
+	int		16h
+	test	ax, ax				; Clear ZF
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Reads keystokes, prints them and converts them to unsigned WORD
+; after user has pressed ENTER. Returned value is always valid unless
+; user has cancelled by pressing ESC.
+; 
+; Keys_PrintGetUint
+;	Parameters:
+;		CX:		Base (10=dec, 16=hex etc.)
+;		DX:		Max number of characters wanted
+;	Returns:
+;		DX:AX:	Unsigned DWORD that the user has entered
+;		CF:		Set if unsigned DWORD read successfully
+;				Cleared is user has cancelled
+;	Corrupts registers:
+;		BX
+;--------------------------------------------------------------------
+%ifdef USE_KEYS_PRNTGETUINT
+ALIGN JUMP_ALIGN
+Keys_PrintGetUint:
+	push	es
+	push	di
+	push	si
+
+	; Reserve stack for buffer
+	inc		dx					; Increment for STOP char
+	push	ss					; Copy SS...
+	pop		es					; ...to ES
+	mov		si, sp				; Backup SP
+	sub		sp, dx				; Reserve buffer from stack
+	mov		di, sp				; ES:DI now points to buffer
+
+	; Get user inputted string
+	mov		bx, String_IsBaseChar
+	call	Keys_GetStrToBuffer
+	jnc		.Return				; Return if user cancellation
+
+	; Convert string to DWORD
+	call	String_StrToUInt	; Get DWORD to DX:AX
+	
+	; Return
+ALIGN JUMP_ALIGN
+.Return:
+	mov		sp, si				; Destroy stack buffer
+	pop		si
+	pop		di
+	pop		es
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Reads keystokes until Y or N is pressed.
+; CF will be set to match selection.
+; 
+; Keys_PrintGetYN
+;	Parameters:
+;		Nothing
+;	Returns:
+;		AX:		'Y' if Y pressed
+;				'N' if N pressed
+;				Zero if ESC pressed
+;		CF:		Set if Y pressed
+;				Cleared if N or ESC pressed
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%ifdef USE_KEYS_PRNTGETYN
+ALIGN JUMP_ALIGN
+Keys_PrintGetYN:
+	call	Keys_WaitStroke		; Wait until keystroke
+	call	String_ToLower		; Char in AL to lower case
+	cmp		al, 'y'				; Y pressed?
+	je		.RetY				;  If so, return
+	cmp		al, 'n'				; N pressed?
+	je		.RetN				;  If so, return
+	cmp		al, ESC				; ESC pressed?
+	je		.RetEsc				;  If so, return N
+	call	Keys_Bell			; Play error sound
+	jmp		Keys_PrintGetYN		; Loop until right key pressed
+ALIGN JUMP_ALIGN
+.RetY:
+	mov		ax, 'Y'
+	stc
+	ret
+ALIGN JUMP_ALIGN
+.RetN:
+	mov		ax, 'N'
+	ret
+ALIGN JUMP_ALIGN
+.RetEsc:
+	xor		ax, ax
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Clears BIOS keystroke buffer.
+; 
+; Keys_ClrBuffer
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+%ifdef USE_KEYS_CLRBUFFER
+ALIGN JUMP_ALIGN
+Keys_ClrBuffer:
+	call	Keys_GetStroke		; Get keystroke
+	jnz		Keys_ClrBuffer		; Loop if keystroke found in buffer
+	ret
+%endif
+
+
+;-------------- Private functions ---------------------
+
+;--------------------------------------------------------------------
+; Reads user inputted string to buffer. Character verification is
+; supported to ignore unwanted characters.
+; Function returns when ENTER or ESC will be pressed.
+; 
+; Keys_GetStrToBuffer
+;	Parameters:
+;		DX:		Buffer length in characters with STOP included
+;		ES:DI:	Ptr to buffer
+;		CS:BX:	Ptr to char verification function:
+;					Parameters:
+;						AL:		Character to verify
+;						CX:		Anything passed to Keys_GetStrToBuffer
+;					Returns:
+;						CF:		Set if character is wanted type
+;								Cleared if character is not wanted
+;					Corrupts registers:
+;						Nothing
+;	Returns:
+;		AX:		String length in characters without STOP
+;		CF:		Set if string has been read successfully
+;				Cleared if user cancellation
+;	Corrupts registers:
+;		DX
+;--------------------------------------------------------------------
+%ifdef USE_KEYS_PRNTGETUINT
+ALIGN JUMP_ALIGN
+Keys_GetStrToBuffer:
+	push	di
+	push	si
+	dec		dx					; Decrement for STOP char
+	xor		si, si				; Zero char counter
+	cld							; STOSB to increment DI
+ALIGN JUMP_ALIGN
+.CharLoop:
+	call	Keys_WaitStroke		; Wait for keystroke
+	cmp		al, CR				; Enter pressed?
+	je		.End				;  If so, return (CF cleared)
+	cmp		al, ESC				; Esc pressed?
+	je		.Cancel				;  If so, jump to cancel
+	cmp		al, BS				; Backspace pressed?
+	je		.Backspace			;  If so, jump to process it
+	call	bx					; Is wanted character?
+	jnc		.Bell				;  If not, play error sound and wait next key
+
+	; Limit char count
+	cmp		si, dx				; Max number of chars entered?
+	jae		.CharLoop			;  If so, wait for ENTER or BACKSPACE
+
+	; Write base character in AL
+	stosb						; Store char from AL to [ES:DI]
+	inc		si					; Increment char count
+	push	dx
+	mov		dl, al				; Copy char to DL
+	PRINT_CHAR					; Print character
+	pop		dx
+	jmp		.CharLoop			; Jump to wait next char
+ALIGN JUMP_ALIGN
+.Bell:
+	call	Keys_Bell
+	jmp		.CharLoop			; Jump to wait next char
+ALIGN JUMP_ALIGN
+.Backspace:
+	call	Keys_Backspace
+	jmp		.CharLoop			; Jump to wait next char
+ALIGN JUMP_ALIGN
+.Cancel:
+	xor		si, si				; Zero string length (clear CF)
+	jmp		.Return
+ALIGN JUMP_ALIGN
+.End:
+	stc							; Set CF since success
+.Return:
+	mov		al, STOP			; End string
+	stosb
+	mov		ax, si				; String length
+	pop		si
+	pop		di
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Plays bell sound for invalid key presses.
+; 
+; Keys_Bell
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+%ifdef USE_KEYS_PRNTGETUINT or USE_KEYS_PRNTGETYN
+ALIGN JUMP_ALIGN
+Keys_Bell:
+	push	dx
+	mov		dl, BELL
+	PRINT_CHAR
+	pop		dx
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Handles backspace key by removing last written character.
+; 
+; Keys_Backspace
+;	Parameters:
+;		SI:		Character counter
+;		ES:DI:	Ptr to buffer
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+%ifdef USE_KEYS_PRNTGETUINT
+ALIGN JUMP_ALIGN
+Keys_Backspace:
+	push	dx
+	test	si, si				; At the beginning?
+	jz		.Return				;  If so, return
+	dec		si					; Decrement char counter
+	dec		di					; Decrement offset to buffer
+	mov		dl, BS				; Write backspace
+	PRINT_CHAR
+	mov		dl, ' '				; Write space
+	PRINT_CHAR
+	mov		dl, BS				; Back again
+	PRINT_CHAR
+ALIGN JUMP_ALIGN
+.Return:
+	pop		dx
+	ret
+%endif
Index: /tags/Configurator_v1.1.0/Src/Libraries/math.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Libraries/math.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Libraries/math.asm	(revision 6)
@@ -0,0 +1,184 @@
+; File name		:	math.asm
+; Project name	:	Math library
+; Created date	:	7.10.2009
+; Last update	:	1.1.2010
+; Author		:	Tomi Tilli
+; Description	:	ASM library to for math related functions.		
+
+;--------------- Equates -----------------------------
+
+; String library function to include
+%define USE_MATH_MULDWBYW		; Math_MulDWbyW
+%define USE_MATH_DIVDWBYW		; Math_DivDWbyW
+%define USE_MATH_REMTOTENTHS	; Math_RemToTenths
+
+
+;-------------- Private global variables -------------
+; Section containing initialized data
+;SECTION .data
+
+
+;-------------- Public functions ---------------------
+; Section containing code
+SECTION .text
+
+
+;--------------------------------------------------------------------
+; Macro to select lesser of two unsigned operands.
+; 
+; MIN_U
+;	Parameters:
+;		%1:		Operand 1
+;		%2:		Operand 2
+;	Returns:
+;		%1:		Lesser unsigned operand
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro MIN_U 2
+	cmp		%1, %2				; Is %1 smaller?
+	jb		%%Return			;  If so, return
+	mov		%1, %2				; Copy %2 to %1
+ALIGN JUMP_ALIGN
+%%Return:
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Macro to select greater of two unsigned operands.
+; 
+; MAX_U
+;	Parameters:
+;		%1:		Operand 1
+;		%2:		Operand 2
+;	Returns:
+;		%1:		Greater unsigned operand
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro MAX_U 2
+	cmp		%1, %2				; Is %1 greater?
+	ja		%%Return			;  If so, return
+	mov		%1, %2				; Copy %2 to %1
+ALIGN JUMP_ALIGN
+%%Return:
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Macro to select lesser and greater of two unsigned operands.
+; 
+; MINMAX_U
+;	Parameters:
+;		%1:		Operand 1
+;		%2:		Operand 2
+;	Returns:
+;		%1:		Lesser unsigned operand
+;		%2:		Greater unsigned operand
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro MINMAX_U 2
+	cmp		%1, %2				; Is %1 smaller?
+	jbe		%%Return			;  If so, return
+	xchg	%1, %2				; Exchange operands
+ALIGN JUMP_ALIGN
+%%Return:
+%endmacro
+
+
+;--------------------------------------------------------------------
+; DWORD * WORD multiplication.
+; Multiplies unsigned 32-bit integer by unsigned 16-bit integer.
+; Result is unsigned 32-bit integer, so overflow is possible.
+; 
+; Math_MulDWbyW
+;	Parameters:
+;		DX:AX:	32-bit unsigned integer to multiply
+;		CX:		16-bit unsigned multiplier
+;	Returns:
+;		DX:AX:	32-bit unsigned integer
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%ifdef USE_MATH_MULDWBYW
+ALIGN JUMP_ALIGN
+Math_MulDWbyW:
+	jcxz	.RetZero			; If CX=0, return 0
+	push	bx
+	mov		bx, dx				; Copy hiword to BX
+	xor		dx, dx				; Zero DX for multiplication
+	mul		cx					; DX:AX = AX (loword) * CX (multiplier)
+	push	dx					; Push possible overflow
+	xchg	ax, bx				; => AX=old hiword, BX=new loword
+	xor		dx, dx				; Zero DX for division
+	mul		cx					; DX:AX = AX (hiword) * CX (multiplier)
+	pop		dx					; Pop possible overflow from first mul
+	add		dx, ax				; Add new hiword to overflow from first mul
+	mov		ax, bx				; Copy new loword to AX
+	pop		bx
+	ret
+ALIGN JUMP_ALIGN
+.RetZero:						; Return 0 in DX:AX
+	xor		ax, ax
+	xor		dx, dx
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Divide a 32-bit unsigned integer so that quotient can be 32-bit.
+; 
+; Math_DivDWbyW
+;	Parameters:
+;		DX:AX:	32-bit unsigned divident
+;		CX:		16-bit unsigned divisor
+;	Returns:
+;		DX:AX:	32-bit unsigned quotient
+;		BX:		16-bit unsigned remainder
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%ifdef USE_MATH_DIVDWBYW
+ALIGN JUMP_ALIGN
+Math_DivDWbyW:
+	mov		bx, ax
+	mov		ax, dx
+	xor		dx, dx
+	div		cx
+	xchg	ax, bx
+	div		cx
+	xchg	dx, bx
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Converts remainder to tenths.
+; 
+; Math_RemToTenths
+;	Parameters:
+;		BX:		16-bit unsigned remainder
+;		CX:		16-bit unsigned divisor used when calculated the remainder (max 2559)
+;	Returns:
+;		BX:		Remainder converted to tenths
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%ifdef USE_MATH_REMTOTENTHS
+ALIGN JUMP_ALIGN
+Math_RemToTenths:
+	push	cx
+	push	ax
+	mov		ax, cx				; Copy divisor to AX
+	mov		cl, 10				; Load 10 to CL
+	div		cl					; AL = Divisor divided by 10
+	inc		ax					; Increment to compensate new remainder
+	xchg	ax, bx				; AX = 16-bit remainder to convert
+								; BL = Original divisor divided by 10
+	div		bl					; AX = Original remainder converted to tenths
+	eMOVZX	bx, al				; Copy return value to BX
+	pop		ax
+	pop		cx
+	ret
+%endif
Index: /tags/Configurator_v1.1.0/Src/Libraries/menu/menu.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Libraries/menu/menu.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Libraries/menu/menu.asm	(revision 6)
@@ -0,0 +1,720 @@
+; File name		:	menu.asm
+; Project name	:	Menu library
+; Created date	:	9.11.2009
+; Last update	:	20.4.2010
+; Author		:	Tomi Tilli
+; Description	:	ASM library to menu system.
+;
+;					Menu.asm contains function to be called from
+;					user code. Functions in other menu source files
+;					are only to be called by menu library itself!
+
+; Optional features.
+%define USE_MENU_DIALOGS		; All dialogs
+;%define USE_MENU_SETSEL		; Menu_SetSel
+%define USE_MENU_TOGGLEINFO		; Menu_ToggleInfo
+%define USE_MENU_INVITEMCNT		; Menu_InvItemCnt
+
+; Include other menu source files.
+%include "menudraw.asm"
+%include "menucrsr.asm"
+%include "menuloop.asm"
+%ifdef USE_MENU_DIALOGS
+	%include "menumsg.asm"
+	%include "menudlg.asm"
+	%include "menuprog.asm"
+	%include "menufile.asm"
+%endif
+
+;--------------- Equates -----------------------------
+
+; Menu Initialization Variables.
+; Menu must always be initialized to stack.
+struc MENUVARS
+	; Menu size set by user
+	.wSize:
+	.bWidth		resb	1	; Menu full width in chars (borders included)
+	.bHeight	resb	1	; Menu full height in chars (borders included)
+	.wTopDwnH:
+	.bTitleH	resb	1	; Title height in chars (borders not included, 0=disabled)
+	.bInfoH		resb	1	; Info height in chars (borders not included, 0=disabled)
+	
+	; Menu callback system set by user
+	.fnEvent	resb	2	; Offset to event callback function
+	
+	; Menu library internal variables.
+	; Do not modify from outside menu library!
+	.wTimeInit	resb	2	; System time ticks for autoselect (0=disabled)
+	.wTimeout	resb	2	; System time ticks left for autoselect
+	.wTimeLast	resb	2	; System time ticks when last read
+	.wInitCrsr:				; Initial cursor coordinates
+	.bInitX		resb	1
+	.bInitY		resb	1
+
+	; Item related variables
+	.wItemCnt	resb	2	; Total number of items in menu
+	.wItemSel	resb	2	; Index of currently selected (pointed) menuitem
+	.wItemTop	resb	2	; Index of first visible menuitem
+	.bVisCnt	resb	1	; Maximum number of visible menuitems
+	.bFlags		resb	1	; Menu flags
+
+	; User specific variables start here.
+	; 4-byte user pointer is stored here if menu created with Menu_Enter.
+	; Data is user specific if menu was created directly with Menu_Init.
+	.user		resb	0
+endstruc
+
+; Screen row count (can be used to limit max menu height)
+CNT_SCRN_ROW	EQU		25	; Number of rows on screen
+
+; Menu flags
+FLG_MNU_EXIT	EQU	(1<<0)	; Set when menu operation is to be stopped
+FLG_MNU_NOARRW	EQU	(1<<1)	; Do not draw item selection arrow
+FLG_MNU_HIDENFO	EQU	(1<<2)	; Hide menu information
+
+; Menu update and invalidate flags
+MFL_UPD_TITLE	EQU	(1<<0)	; Update title string(s)
+MFL_UPD_NFO		EQU	(1<<1)	; Update info string(s)
+MFL_UPD_ITEM	EQU	(1<<2)	; Update item string(s)
+MFL_UPD_NOCLEAR	EQU	(1<<4)	; Do not clear old chars (prevents flickering)
+
+
+;--------------------------------------------------------------------
+; Event callback function prototype.
+;
+; MENUVARS.fnEvent
+;	Parameters:
+;		BX:			Callback event
+;		CX:			Menuitem index (usually index of selected Menuitem)
+;		DX:			Event parameter (event specific)
+;		SS:BP:		Ptr to MENUVARS
+;		Other regs:	Undefined
+;	Returns:
+;		AH:			Event specific or unused. Set to 0 if unused.
+;		AL:			1=Event processed
+;					0=Event not processed (default action if any)
+;		Other regs:	Event specific or unused.
+;	Corrupts registers:
+;		BX, CX, DX
+;--------------------------------------------------------------------
+EVNT_MNU_EXIT		EQU	0		; Menu will quit
+								;	Ret AH:	1 to cancel exit
+								;			0 to allow menu exit
+EVNT_MMU_SELCHG		EQU	1		; Menuitem selection changed (with arrows)
+EVNT_MNU_SELSET		EQU	2		; Menuitem selected (with Enter)
+EVNT_MNU_KEY		EQU	3		; Keyboard key pressed
+								;	DH: BIOS Scan Code
+								;	DL: ASCII Char (if any)
+EVNT_MNU_UPD		EQU	4		; Menu needs to be updated (use currect cursor position)
+								;	DL:	MFL_UPD_TITLE set to update title string
+								;		MFL_UPD_NFO set to update info string
+								;		MFL_UPD_ITEM Set to update menuitem string
+								;			CX: Index of Menuitem to update
+EVNT_MNU_GETDEF		EQU	5		; Request menuitem to be selected by default
+								;	Ret CX:	Index of menuitem to select
+EVNT_MNU_INITDONE	EQU	6		; Menu has been initialized (created) but not yet drawn
+
+
+
+;-------------- Private global variables -------------
+; Section containing initialized data
+;SECTION .data
+
+
+;-------------- Public functions ---------------------
+; Section containing code
+SECTION .text
+
+
+;--------------------------------------------------------------------
+; Enters menu or submenu. Menu_Init does not have to be called
+; if this function is used to enter menu or submenu.
+; Menu_Init need to be called only when creating stack frame manually.
+; Manual creation allows custom menu position and user defined variables.
+;
+; Menu_Enter
+;	Parameters:
+;		AL:		Menu width with borders included
+;		AH:		Menu height with borders included
+;		BL:		Title line count (0=disable title)
+;		BH:		Info line count (0=disable info)
+;		CL:		Number of menuitems in top menu
+;		CH:		Menu flags
+;		DX:		Selection timeout in milliseconds (0=timeout disabled)
+;		DS:SI:	User specific far pointer (will be stored to MENUVARS.user)
+;		CS:DI:	Pointer to menu event handler function
+;	Returns:
+;		CX:		Index of last pointed Menuitem (not necessary selected with ENTER)
+;				FFFFh if cancelled with ESC
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Menu_Enter:
+	; Create stack frame
+	eENTER	MENUVARS_size+4, 0
+	sub		bp, MENUVARS_size+4	; Point to MENUVARS
+
+	; Initialize menu variables
+	mov		[bp+MENUVARS.wSize], ax
+	mov		[bp+MENUVARS.wTopDwnH], bx
+	mov		[bp+MENUVARS.fnEvent], di
+	mov		[bp+MENUVARS.user], si
+	mov		[bp+MENUVARS.user+2], ds
+
+	; Prepare to call Menu_Init
+	push	dx					; Store timeout
+	call	MenuCrsr_GetCenter	; Get centered coordinates to DX
+	pop		ax					; Restore timeout to AX
+	xor		bx, bx				; Zero BX
+	xchg	bl, ch				; Menu flags to BL, Item count to CX
+	call	Menu_Init
+
+	; Destroy stack frame
+	add		bp, MENUVARS_size+4	; Point to old BP
+	eLEAVE						; Destroy stack frame
+	ret
+
+
+;--------------------------------------------------------------------
+; Initialize Menu.
+; This function returns only after Menu_Exit has been called from
+; event callback function (MENUVARS.fnEvent).
+; Caller must clean MENUVARS from stack once this function returns!
+;
+; Multiple menus can be created to implement submenus.
+;
+; Menu_Init
+;	Parameters:
+;		AX:		Selection timeout (ms, 0=timeout disabled)
+;		BL:		Menu flags
+;		CX:		Number of menuitems in top menu
+;		DX:		Top left coordinate for menu
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CX:		Index of last pointed Menuitem (not necessary selected with ENTER)
+;				FFFFh if cancelled with ESC
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Menu_Init:
+	; Initialize internal variables
+	call	Menu_StartTimeout
+	xor		ax, ax						; Zero AX
+	mov		[bp+MENUVARS.wInitCrsr], dx
+	mov		[bp+MENUVARS.wItemCnt], cx
+	mov		[bp+MENUVARS.wItemSel], ax
+	mov		[bp+MENUVARS.wItemTop], ax
+	mov		[bp+MENUVARS.bFlags], bl
+
+	; Calculate number of visible menuitems
+	eMOVZX	ax, [bp+MENUVARS.bHeight]	; Load menu total height
+	times 2 dec	ax						; Decrement top and borders
+	or		ah, [bp+MENUVARS.bTitleH]	; Load title height
+	jz		.CheckInfo					;  If no title, check if info
+	sub		al, ah						; Subtract title lines
+	dec		ax							; Decrement item border
+ALIGN JUMP_ALIGN
+.CheckInfo:
+	xor		ah, ah						; Zero AH
+	or		ah, [bp+MENUVARS.bInfoH]	; Load info height
+	jz		.StoreVisible				;  If no info, jump to store
+	sub		al, ah						; Subtract info lines
+	dec		ax							; Decrement item border
+ALIGN JUMP_ALIGN
+.StoreVisible:
+	mov		[bp+MENUVARS.bVisCnt], al	; Store max visible menuitems
+
+	; Get default menuitem
+	mov		bx, EVNT_MNU_GETDEF
+	call	MenuLoop_SendEvent
+	test	al, al						; Default menuitem returned?
+	jz		.InitDone					;  If not, continue
+	mov		[bp+MENUVARS.wItemSel], cx	; Store default
+	eMOVZX	ax, [bp+MENUVARS.bVisCnt]	; Load one past last to be displayed
+	cmp		cx, ax						; Visible selection?
+	jb		.InitDone					;  If so, continue
+	mov		[bp+MENUVARS.wItemTop], cx	; Set selected to topmost
+
+	; Send EVNT_MNU_INITDONE event
+ALIGN JUMP_ALIGN
+.InitDone:
+	mov		bx, EVNT_MNU_INITDONE
+	call	MenuLoop_SendEvent
+
+	; Draw menu
+	call	MenuCrsr_Hide				; Hide cursor
+	mov		cx, -1						; Invalidate all menuitems
+	mov		dl, MFL_UPD_TITLE | MFL_UPD_ITEM | MFL_UPD_NFO
+	call	Menu_Invalidate
+
+	; Enter menu loop until Menu_Exit is called
+	call	MenuLoop_Enter
+	call	MenuCrsr_Show				; Show cursor again
+	mov		cx, [bp+MENUVARS.wItemSel]	; Load return value
+	ret
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Below functions are called only from event callback function ;
+; (MENUVARS.fnEvent)                                           ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;--------------------------------------------------------------------
+; Sets wanted menuitem selected and draws changes.
+;
+; Menu_SetSel
+;	Parameters:
+;		CX:		Index of menuitem to set selected
+;		SS:BP:	Ptr to MENUVARS for menu to refresh
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+%ifdef USE_MENU_SETSEL
+ALIGN JUMP_ALIGN
+Menu_SetSel:
+	cmp		cx, [bp+MENUVARS.wItemCnt]	; Valid menuitem index?
+	jae		.Return						;  If not, return
+	mov		[bp+MENUVARS.wItemSel], cx	; Store new selected index
+
+	; Scroll if necessary
+	mov		ax, [bp+MENUVARS.wItemTop]	; Load index of topmost visible
+	MIN_U	ax, cx						; AX = new topmost visible
+	mov		[bp+MENUVARS.wItemTop], ax	; Store new topmost
+	add		al, [bp+MENUVARS.bVisCnt]	; AX to one past...
+	adc		ah, 0						; ...last visible
+	cmp		cx, ax						; After last visible?
+	jb		.SendSelChg					;  If not, continue
+	mov		[bp+MENUVARS.wItemTop], cx	; New selection to topmost
+
+	; Send EVNT_MMU_SELCHG message
+ALIGN JUMP_ALIGN
+.SendSelChg:
+	mov		bx, EVNT_MMU_SELCHG
+	call	MenuLoop_SendEvent
+
+	; Redraw changes
+	mov		cx, -1						; Invalidate all menuitems
+	mov		dl, MFL_UPD_ITEM
+	call	Menu_Invalidate
+.Return:
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Shows or hides menu information at the bottom of menu.
+;
+; Menu_ShowInfo		Enables menu information
+; Menu_HideInfo		Disables menu information
+; Menu_ToggleInfo	Enables or disables menu information
+;	Parameters:
+;		SS:BP:	Ptr to MENUVARS for menu
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+%ifdef USE_MENU_TOGGLEINFO
+ALIGN JUMP_ALIGN
+Menu_ShowInfo:
+	test	BYTE [bp+MENUVARS.bFlags], FLG_MNU_HIDENFO
+	jnz		Menu_ToggleInfo
+	ret
+ALIGN JUMP_ALIGN
+Menu_HideInfo:
+	test	BYTE [bp+MENUVARS.bFlags], FLG_MNU_HIDENFO
+	jz		Menu_ToggleInfo
+	ret
+ALIGN JUMP_ALIGN
+Menu_ToggleInfo:
+	xor		BYTE [bp+MENUVARS.bFlags], FLG_MNU_HIDENFO
+	; Fall to Menu_RefreshMenu
+%endif
+
+
+;--------------------------------------------------------------------
+; Refreshes menu. This function must be called when
+; call to submenu Menu_Enter (or Menu_Init) returns.
+;
+; Menu_RefreshMenu
+;	Parameters:
+;		SS:BP:	Ptr to MENUVARS for menu to refresh
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Menu_RefreshMenu:
+	push	cx
+	call	MenuCrsr_Hide				; Hide cursor
+	call	Menu_RestartTimeout			; Restart selection timeout
+	call	Menu_GetTime				; Get system time ticks to CX:DX
+	mov		[bp+MENUVARS.wTimeLast], dx	; Store last time updated
+	call	Keys_ClrBuffer				; Clear keyboard buffer
+	call	MenuDraw_ClrScr				; Clear screen
+	mov		cx, -1						; Invalidate all menuitems
+	mov		dl, MFL_UPD_TITLE | MFL_UPD_NFO | MFL_UPD_ITEM
+	call	Menu_Invalidate				; Redraw everything
+	pop		cx
+	ret
+
+
+;--------------------------------------------------------------------
+; Destroy menu by causing Menu_Init to return.
+;
+; Menu_Exit
+;	Parameters:
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Set if user cancelled exit
+;				Cleared if user allowed exit
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Menu_Exit:
+	mov		bx, EVNT_MNU_EXIT
+	call	MenuLoop_SendEvent
+	rcr		ah, 1					; AH bit 0 to CF
+	jc		.Return					; Do not exit if AH non-zero
+	or		BYTE [bp+MENUVARS.bFlags], FLG_MNU_EXIT	; (Clear CF)
+ALIGN JUMP_ALIGN
+.Return:
+	ret
+
+
+;--------------------------------------------------------------------
+; Invalidate any menu string.
+; Menu then sends EVNT_MNU_UPD events when necessary.
+;
+; Menu_InvItemCnt	Changes total item count and invalidates
+;	Parameters: (in addition to Menu_Invalidate)
+;		CX:		New Total item count
+; Menu_Invalidate
+;	Parameters:
+;		DL:		Invalidate flags (any combination is valid):
+;					MFL_UPD_NOCLEAR	Set to prevent clearing old chars
+;					MFL_UPD_TITLE	Invalidate menu title string
+;					MFL_UPD_NFO		Invalidate menu info string
+;					MFL_UPD_ITEM	Invalidate menuitem strings
+;						CX: Index of Menuitem to update
+;							-1 to update all menuitems
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+%ifdef USE_MENU_INVITEMCNT
+ALIGN JUMP_ALIGN
+Menu_InvItemCnt:
+	xor		ax, ax
+	mov		[bp+MENUVARS.wItemCnt], cx
+	mov		[bp+MENUVARS.wItemSel], ax
+	mov		[bp+MENUVARS.wItemTop], ax
+	mov		cx, -1					; Invalidate all items
+	or		dl, MFL_UPD_ITEM | MFL_UPD_NFO
+%endif
+ALIGN JUMP_ALIGN
+Menu_Invalidate:
+	push	di
+	mov		di, dx
+	test	di, MFL_UPD_ITEM		; Invalidate Menuitems?
+	jz		.InvTitle				;  If not, jump to invalidate Title
+	cmp		cx, -1					; Redraw all menuitems?
+	je		.InvAllItems			;  If so, jump to draw
+	call	MenuCrsr_PointNthItem	; Set cursor position
+	call	MenuDraw_Item			; Draw single menuitem
+	jmp		.InvTitle				; Jump to invalidate Title
+ALIGN JUMP_ALIGN
+.InvAllItems:
+	test	di, MFL_UPD_NOCLEAR		; Keep background?
+	jnz		.DrawAllItems			;  If not, jump to draw
+	call	MenuDraw_ItemBorders	; Draw item borders
+ALIGN JUMP_ALIGN
+.DrawAllItems:
+	call	MenuDraw_AllItemsNoBord	; Draw items without borders
+
+ALIGN JUMP_ALIGN
+.InvTitle:
+	test	di, MFL_UPD_TITLE		; Invalidate Title?
+	jz		.InvInfo				;  If not, jump to invalidate Info
+	test	di, MFL_UPD_NOCLEAR		; Keep background?
+	jnz		.DrawTitle				;  If not, jump to draw
+	call	MenuDraw_TitleBorders	; Draw borders
+ALIGN JUMP_ALIGN
+.DrawTitle:
+	call	MenuDraw_TitleNoBord	; Draw title without borders
+
+ALIGN JUMP_ALIGN
+.InvInfo:
+	test	di, MFL_UPD_NFO			; Invalidate Info?
+	jz		.Return					;  If not, return
+	test	di, MFL_UPD_NOCLEAR		; Keep background?
+	jnz		.DrawInfo				;  If not, jump to draw
+	call	MenuDraw_InfoBorders	; Draw borders
+ALIGN JUMP_ALIGN
+.DrawInfo:
+	call	MenuDraw_InfoNoBord		; Draw info without borders
+ALIGN JUMP_ALIGN
+.Return:
+	pop		di
+	ret
+
+
+;--------------------------------------------------------------------
+; Starts or stops menu selection timeout.
+;
+; Menu_StopTimeout		; Stops timeout
+; Menu_StartTimeout		; Starts timeout with new value
+; Menu_RestartTimeout	; Restarts timeout with previous value
+;	Parameters:
+;		AX:		New timeout value in ms (for Menu_StartTimeout only)
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Menu_StopTimeout:
+	xor		ax, ax
+ALIGN JUMP_ALIGN
+Menu_StartTimeout:
+	push	dx
+	push	bx
+	xor		dx, dx
+	mov		bx, 55						; 1 timer tick = 54.945ms
+	div		bx							; DX:AX / 55
+	mov		[bp+MENUVARS.wTimeInit], ax	; Store timer tick count
+	mov		[bp+MENUVARS.wTimeout], ax
+	pop		bx
+	pop		dx
+	ret
+ALIGN JUMP_ALIGN
+Menu_RestartTimeout:
+	mov		ax, [bp+MENUVARS.wTimeInit]
+	mov		[bp+MENUVARS.wTimeout], ax
+	ret
+
+
+;--------------------------------------------------------------------
+; Returns system time in clock ticks. One tick is 54.95ms.
+;
+; Menu_GetTime
+;	Parameters:
+;		Nothing
+;	Returns:
+;		AL:		Midnight flag, set if midnight passed since last read
+;		CX:DX:	Number of clock ticks since midnight
+;	Corrupts registers:
+;		AH
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Menu_GetTime:
+	xor		ah, ah				; Get System Time
+	int		1Ah
+	ret
+
+
+;--------------------------------------------------------------------
+; Checks if Menuitem is currently visible.
+;
+; Menu_IsItemVisible
+;	Parameters:
+;		AX:		Menuitem index
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Set if Menuitem is visible
+;				Cleared if Menuitem is not visible
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Menu_IsItemVisible:
+	push	dx
+	mov		dx, [bp+MENUVARS.wItemTop]		; Load index of first visible
+	cmp		ax, dx							; First visible menuitem?
+	jb		.RetFalse						;  If below, return false
+	add		dl, [bp+MENUVARS.bVisCnt]		; Inc to one past...
+	adc		dh, 0							; ...last visible menuitem
+	cmp		ax, dx							; Over last visible?
+	jae		.RetFalse						;  If so, return false
+	pop		dx
+	ret										; Return with CF set
+ALIGN JUMP_ALIGN
+.RetFalse:
+	pop		dx
+	clc
+	ret
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Optional Dialog functions start here ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%ifdef USE_MENU_DIALOGS
+
+;--------------------------------------------------------------------
+; Shows message dialog to display string.
+; String can be multiple lines but line feeds will be determined
+; by menu system.
+;
+; Menu_ShowMsgDlg
+;	Parameters:
+;		BL:		Dialog width with borders included
+;		SS:BP:	Ptr to MENUVARS
+;		ES:DI:	Ptr to STOP terminated string to display
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Menu_ShowMsgDlg:
+	call	MenuMsg_ShowMessage
+	jmp		Menu_RefreshMenu
+
+
+;--------------------------------------------------------------------
+; Shows dialog that asks unsigned DWORD from user.
+;
+; Menu_ShowDWDlg
+;	Parameters:
+;		BL:		Dialog width with borders included
+;		CX:		Numeric base (10=dec, 16=hex...)
+;		SS:BP:	Ptr to MENUVARS
+;		ES:DI:	Ptr to STOP terminated string to display
+;	Returns:
+;		DX:AX:	User inputted data
+;		CF:		Set if user data inputted successfully
+;				Cleared is input cancelled
+;	Corrupts registers:
+;		BX, CX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Menu_ShowDWDlg:
+	mov		dx, MenuDlg_DWEvent	; Offset to event handler
+	call	MenuDlg_Show
+	push	ax
+	push	dx
+	pushf
+	call	Menu_RefreshMenu
+	popf
+	pop		dx
+	pop		ax
+	ret
+
+
+;--------------------------------------------------------------------
+; Shows dialog that asks Y/N input from user.
+;
+; Menu_ShowYNDlg
+;	Parameters:
+;		BL:		Dialog width with borders included
+;		SS:BP:	Ptr to MENUVARS
+;		ES:DI:	Ptr to STOP terminated string to display
+;	Returns:
+;		AX:		'Y' if Y pressed
+;				'N' if N pressed
+;				Zero if ESC pressed
+;		CF:		Set if Y pressed
+;				Cleared if N or ESC pressed
+;	Corrupts registers:
+;		BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Menu_ShowYNDlg:
+	mov		dx, MenuDlg_YNEvent	; Offset to event handler
+	call	MenuDlg_Show
+	push	ax
+	pushf
+	call	Menu_RefreshMenu
+	popf
+	pop		ax
+	ret
+
+
+;--------------------------------------------------------------------
+; Shows dialog that asks any string from user.
+;
+; Menu_ShowStrDlg
+;	Parameters:
+;		BL:		Dialog width with borders included
+;		CX:		Buffer length with STOP included
+;		SS:BP:	Ptr to MENUVARS
+;		ES:DI:	Ptr to STOP terminated string to display
+;		DS:SI:	Prt to buffer to receive string
+;	Returns:
+;		AX:		String length in characters without STOP
+;		CF:		Set if string inputted successfully
+;				Cleared if user cancellation
+;	Corrupts registers:
+;		BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Menu_ShowStrDlg:
+	mov		dx, MenuDlg_StrEvent	; Offset to event handler
+	call	MenuDlg_Show
+	push	ax
+	pushf
+	call	Menu_RefreshMenu
+	popf
+	pop		ax
+	ret
+
+
+;--------------------------------------------------------------------
+; Shows progress bar dialog.
+;
+; Menu_ShowProgDlg
+;	Parameters:
+;		BL:		Dialog width with borders included
+;		BH:		Dialog height with borders included
+;		SS:BP:	Ptr to MENUVARS
+;		ES:DI:	Far ptr to user specified task function
+;		DS:SI:	User specified far pointer
+;	Returns:
+;		AX:		User specified return code
+;	Corrupts registers:
+;		BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Menu_ShowProgDlg:
+	call	MenuProg_Show
+	push	ax
+	call	Menu_RefreshMenu
+	pop		ax
+	ret
+
+
+;--------------------------------------------------------------------
+; Shows dialog that user can use to select file.
+;
+; Menu_ShowFileDlg
+;	Parameters:
+;		BL:		Dialog width with borders included
+;		SS:BP:	Ptr to MENUVARS
+;		ES:DI:	Ptr to STOP terminated info string
+;		DS:SI:	Ptr to file search string (* and ? wildcards supported)
+;	Returns:
+;		DS:SI:	Ptr to DTA for selected file
+;		CF:		Set if file selected successfully
+;				Cleared if user cancellation
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Menu_ShowFileDlg:
+	call	MenuFile_ShowDlg
+	pushf
+	call	Menu_RefreshMenu
+	popf
+	ret
+
+
+%endif ; USE_MENU_DIALOGS
Index: /tags/Configurator_v1.1.0/Src/Libraries/menu/menucrsr.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Libraries/menu/menucrsr.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Libraries/menu/menucrsr.asm	(revision 6)
@@ -0,0 +1,252 @@
+; File name		:	menucrsr.asm
+; Project name	:	Menu library
+; Created date	:	10.11.2009
+; Last update	:	17.1.2010
+; Author		:	Tomi Tilli
+; Description	:	ASM library to menu system.
+;					Contains menu cursor functions.
+
+;--------------- Equates -----------------------------
+
+W_OFF_CRSR_STR	EQU		0102h	; User string cursor offset
+
+
+;-------------- Private global variables -------------
+; Section containing initialized data
+;SECTION .data
+
+
+;-------------- Public functions ---------------------
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Returns X and Y coordinates for menu top left corner.
+; This function is used for calculating initial coordinates when
+; initializing menu for first time.
+;	Parameters:
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		DL:		X coordinate for centered menu
+;		DH:		Y coordinate for centered menu
+;	Corrupts registers:
+;		AX, BX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuCrsr_GetCenter:
+	mov		ah, 0Fh						; Get Current Video Mode
+	int		10h
+	mov		dl, ah						; Copy column count to DL
+	sub		dl, [bp+MENUVARS.bWidth]	; Subtract menu width from columns
+	shr		dl, 1						; Divide by 2 for start X
+	mov		dh, CNT_SCRN_ROW			; Load row count
+	sub		dh, [bp+MENUVARS.bHeight]	; Subtract menu height from rows
+	shr		dh, 1						; Divide by 2 for start y
+	ret
+
+
+;--------------------------------------------------------------------
+; Sets cursor to start of menu string.
+; MenuCrsr_Point1stItem		Sets cursor to first menuitem string
+; MenuCrsr_PointInfo		Sets cursor to info string
+; MenuCrsr_PointTitle		Sets cursor to title string
+;	Parameters:
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuCrsr_Point1stItem:
+	xor		dx, dx						; Zero DX
+	call	MenuCrsr_PointItemBrdr		; Point to item border (left)
+	mov		cx, W_OFF_CRSR_STR & 0FFh	; Offset to user string (move X only)
+	jmp		MenuCrsr_Move				; Move cursor
+ALIGN JUMP_ALIGN
+MenuCrsr_PointInfo:
+	xor		dx, dx						; Zero DX
+	call	MenuCrsr_PointNfoBrdr		; Point to Info border (top left)
+	mov		cx, W_OFF_CRSR_STR			; Movement from border to user str
+	jmp		MenuCrsr_Move				; Move cursor
+ALIGN JUMP_ALIGN
+MenuCrsr_PointTitle:
+	xor		dx, dx						; Zero DX
+	call	MenuCrsr_PointTitleBrdr		; Point to Title border (top left)
+	mov		cx, W_OFF_CRSR_STR			; Movement from border to user str
+	jmp		MenuCrsr_Move				; Move cursor
+
+
+;--------------------------------------------------------------------
+; Sets cursor to start of wanted menuitem string.
+;
+; MenuCrsr_PointNthItem
+;	Parameters:
+;		CX:		Menuitem index where to set cursor
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuCrsr_PointNthItem:
+	push	cx
+	push	cx
+	call	MenuCrsr_Point1stItem		; Point to topmost menuitem
+	pop		cx
+	sub		cx, [bp+MENUVARS.wItemTop]	; Number of newlines needed
+	jcxz	.Return
+ALIGN JUMP_ALIGN
+.NewLineLoop:
+	call	MenuDraw_NewlineStr
+	loop	.NewLineLoop
+ALIGN JUMP_ALIGN
+.Return:
+	pop		cx
+	ret
+
+
+;--------------------------------------------------------------------
+; Sets cursor to start of menu border.
+; MenuCrsr_PointBelowBrdr	Sets cursor to below menu bottom border
+; MenuCrsr_PointNfoBrdr		Sets cursor to top left corner of info borders
+; MenuCrsr_PointItemBrdr	Sets cursor to first menuitem left border
+; MenuCrsr_PointTitleBrdr	Sets cursor to top left corner of title borders
+;	Parameters:
+;		DX:		0
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuCrsr_PointBelowBrdr:
+	mov		dh, [bp+MENUVARS.bInfoH]	; Load info height without borders
+	test	dh, dh						; Info displayed?
+	jz		.BottomOnly					; If not, continue
+	inc		dh							; Increment Y for top border
+ALIGN JUMP_ALIGN
+.BottomOnly:
+	inc		dh							; Increment Y for bottom border
+ALIGN JUMP_ALIGN
+MenuCrsr_PointNfoBrdr:
+	add		dh, [bp+MENUVARS.bVisCnt]	; Load max number of visible menuitems
+ALIGN JUMP_ALIGN
+MenuCrsr_PointItemBrdr:
+	inc		dh							; Add title top border
+	mov		al, [bp+MENUVARS.bTitleH]	; Load title height
+	add		dh, al						; Add title height to DH
+	test	al, al						; Title visible?
+	jz		MenuCrsr_PointTitleBrdr		;  If not, jump to set cursor
+	inc		dh							; Title bottom border
+ALIGN JUMP_ALIGN
+MenuCrsr_PointTitleBrdr:
+	add		dx, [bp+MENUVARS.wInitCrsr]	; Add initial cursor position
+	; Fall to MenuCrsr_SetCursor
+
+
+;--------------------------------------------------------------------
+; Sets cursor position in DX.
+;	Parameters:
+;		DL:		Cursor X coordinate
+;		DH:		Cursor Y coordinate
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuCrsr_SetCursor:
+	xor		bx, bx						; Zero page
+	mov		ah, 02h						; Set Cursor Position and Size
+	int		10h
+	ret
+
+
+;--------------------------------------------------------------------
+; Return cursor position in DX.
+;	Parameters:
+;		Nothing
+;	Returns:
+;		CL:		Cursor start scan line
+;		CH:		Cursor end scan line
+;		DL:		Cursor X coordinate
+;		DH:		Cursor Y coordinate
+;	Corrupts registers:
+;		AX, BX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuCrsr_GetCursor:
+	xor		bx, bx						; Zero page
+	mov		ah, 03h						; Get Cursor Position and Size
+	int		10h
+	ret
+
+
+;--------------------------------------------------------------------
+; Moves cursor from current location.
+;	Parameters:
+;		CL:		Cursor X coordinate movement (can be negative)
+;		CH:		Cursor Y coordinate movement (can be negative)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuCrsr_Move:
+	push	cx
+	call	MenuCrsr_GetCursor			; Get cursor position to DX
+	pop		cx
+	add		dl, cl						; Move X
+	add		dh, ch						; Move Y
+	jmp		MenuCrsr_SetCursor
+
+
+;--------------------------------------------------------------------
+; Shows cursor that has been hidden.
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuCrsr_Show:
+	mov		cx, 0607h		; Two line cursor near or at the bottom of cell
+	jmp		MenuCrsr_SetShape
+
+
+;--------------------------------------------------------------------
+; Hides cursor.
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuCrsr_Hide:
+	mov		cx, 2000h
+	; Fall to MenuCrsr_SetShape
+
+;--------------------------------------------------------------------
+; Sets cursor shape.
+;	Parameters:
+;		CL:		Cursor start scan line
+;		CH:		Cursor end scan line
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuCrsr_SetShape:
+	mov		ax, 0103h		; Set Text-Mode Cursor Shape
+							; AL=assumed video mode to prevent lock ups on some BIOSes
+	int		10h
+	ret
Index: /tags/Configurator_v1.1.0/Src/Libraries/menu/menudlg.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Libraries/menu/menudlg.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Libraries/menu/menudlg.asm	(revision 6)
@@ -0,0 +1,224 @@
+; File name		:	menudlg.asm
+; Project name	:	Menu library
+; Created date	:	17.11.2009
+; Last update	:	4.12.2009
+; Author		:	Tomi Tilli
+; Description	:	ASM library to menu system.
+;					Contains functions for displaying input dialogs.
+
+;--------------- Equates -----------------------------
+
+; Dialog init and return variables.
+; This is an expanded MSGVARS struct.
+struc DLGVARS
+	.msgVars	resb	MSGVARS_size
+
+	; Dialog parameters for different dialogs
+	.wCXPrm:	
+	.wPrmBase:				; Numeric base for DWORD dialog (10=dec, 16=hex...)
+	.wBuffLen	resb	2	; Buffer length for string dialog (with STOP included)
+	.dwBuffPtr	resb	4	; Far pointer to buffer to receive string
+
+	; Return variables for different dialogs
+	.dwReturn:
+	.dwRetDW:				; DWORD inputted by user
+	.wRetLen	resb	4	; Length of string inputted by user (chars without STOP)
+	.fSuccess	resb	1	; Was data inputted successfully by user
+				resb	1	; Alignment
+endstruc
+
+
+;-------------- Private global variables -------------
+; Section containing initialized data
+;SECTION .data
+
+g_strYN:	db	"Y/N: ",STOP	; For asking Y/N input
+
+
+;-------------- Public functions ---------------------
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Displays dialog.
+;
+; MenuDlg_Show
+;	Parameters:
+;		BL:		Dialog width with borders included
+;		CX:		Word parameter for dialog event handler
+;		DX:		Offset to dialog event handler
+;		SS:BP:	Ptr to MENUVARS
+;		DS:SI	Pointer parameter for dialog event handler
+;		ES:DI:	Ptr to STOP terminated string to display
+;	Returns:
+;		DX:AX:	User inputted data
+;		CF:		Set if user data inputted successfully
+;				Cleared is input cancelled
+;	Corrupts registers:
+;		BX, CX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuDlg_Show:
+	; Create stack frame
+	eENTER	DLGVARS_size, 0
+	sub		bp, DLGVARS_size				; Point to DLGVARS
+
+	; Initialize menu variables
+	mov		[bp+MENUVARS.bWidth], bl		; Menu width
+	mov		WORD [bp+MENUVARS.wTopDwnH], 0100h	; Title and Info size
+	mov		[bp+MENUVARS.fnEvent], dx		; Store handler offset
+	mov		[bp+MSGVARS.wStrOff], di		; Store far ptr...
+	mov		[bp+MSGVARS.wStrSeg], es		; ...to string to display
+	mov		[bp+DLGVARS.wCXPrm], cx			; Store word parameter
+	mov		[bp+DLGVARS.dwBuffPtr], si		; Store far pointer...
+	mov		[bp+DLGVARS.dwBuffPtr+2], ds	; ...parameter
+
+	; Enter menu
+	call	MenuMsg_GetLineCnt				; Get message line count to CX
+	mov		ax, CNT_SCRN_ROW-4				; Load max line count without borders and info
+	MIN_U	ax, cx							; String lines to display to AX
+	add		al, 4							; Add borders for dlg height
+	mov		[bp+MENUVARS.bHeight], al		; Store dialog height
+	call	MenuCrsr_GetCenter				; Get X and Y coordinates to DX
+	xor		ax, ax							; Selection timeout (disable)
+	mov		bl, FLG_MNU_NOARRW				; Menu flags
+	call	Menu_Init						; Returns only after dlg closed
+	call	MenuCrsr_Hide					; Hide cursor again
+
+	; Return
+	mov		ax, [bp+DLGVARS.dwReturn]		; Load return loword
+	mov		dx, [bp+DLGVARS.dwReturn+2]		; Load return hiword
+	mov		bl, [bp+DLGVARS.fSuccess]		; Load success flag
+	add		bp, DLGVARS_size				; Point to old BP
+	eLEAVE									; Destroy stack frame
+	rcr		bl, 1							; Move success flag to CF
+	ret
+
+
+;-------------- Private functions ---------------------
+
+;--------------------------------------------------------------------
+; DWORD input dialog event handler.
+;
+; MenuDlg_DWEvent
+;	Parameters:
+;		BX:		Callback event
+;		CX:		Selected menuitem index
+;		DX:		Event parameter (event specific)
+;		SS:BP:	Ptr to DLGVARS
+;	Returns:
+;		AH:		Event specific or unused
+;		AL:		1=Event processed
+;				0=Event not processed (default action if any)
+;	Corrupts registers:
+;		BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuDlg_DWEvent:
+	cmp		bx, EVNT_MNU_UPD			; Update strings?
+	jne		MenuDlg_JmpToMsgEvnt		;  If not, use message handler
+	test	dl, MFL_UPD_NFO				; Update info strings?
+	jz		MenuDlg_JmpToMsgEvnt		;  If not, use message handler
+
+	; Get user input instead of drawing info strings
+	call	MenuCrsr_Show				; Show cursor during input
+	mov		cx, [bp+DLGVARS.wPrmBase]	; Load numeric base to CX
+	eMOVZX	dx, [bp+MENUVARS.bWidth]	; Load dialog width
+	sub		dx, 4						; Subtract borders for max char count
+	call	Keys_PrintGetUint			; Get DWORD
+	mov		[bp+DLGVARS.dwRetDW], ax	; Store return loword
+	mov		[bp+DLGVARS.dwRetDW+2], dx	; Store return hiword
+	rcl		BYTE [bp+DLGVARS.fSuccess], 1	; Set or clear success flag
+
+	; Exit menu
+ALIGN JUMP_ALIGN
+MenuDlg_ExitHandler:
+	or		BYTE [bp+MENUVARS.bFlags], FLG_MNU_EXIT
+	mov		ax, 1
+	ret
+
+ALIGN JUMP_ALIGN
+MenuDlg_JmpToMsgEvnt:
+	jmp		MenuMsg_MsgEvent
+
+
+;--------------------------------------------------------------------
+; Y/N dialog event handler.
+;
+; MenuDlg_YNEvent
+;	Parameters:
+;		BX:		Callback event
+;		CX:		Selected menuitem index
+;		DX:		Event parameter (event specific)
+;		SS:BP:	Ptr to DLGVARS
+;	Returns:
+;		AH:		Event specific or unused
+;		AL:		1=Event processed
+;				0=Event not processed (default action if any)
+;	Corrupts registers:
+;		BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuDlg_YNEvent:
+	cmp		bx, EVNT_MNU_UPD			; Update strings?
+	jne		MenuDlg_JmpToMsgEvnt		;  If not, use message handler
+	test	dl, MFL_UPD_NFO				; Update info strings?
+	jz		MenuDlg_JmpToMsgEvnt		;  If not, use message handler
+
+	; Draw info string
+	push	ds
+	push	cs
+	pop		ds
+	mov		dx, g_strYN					; Y/N string in DS:DX
+	PRINT_STR
+	pop		ds
+
+	; Wait for user input
+	call	MenuCrsr_Show				; Show cursor during input
+	call	Keys_PrintGetYN
+	mov		[bp+DLGVARS.dwReturn], ax		; Store return char
+	rcl		BYTE [bp+DLGVARS.fSuccess], 1	; Set or clear Y/N flag
+	jmp		MenuDlg_ExitHandler
+
+
+;--------------------------------------------------------------------
+; String dialog event handler.
+;
+; MenuDlg_StrEvent
+;	Parameters:
+;		BX:		Callback event
+;		CX:		Selected menuitem index
+;		DX:		Event parameter (event specific)
+;		SS:BP:	Ptr to DLGVARS
+;	Returns:
+;		AH:		Event specific or unused
+;		AL:		1=Event processed
+;				0=Event not processed (default action if any)
+;	Corrupts registers:
+;		BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuDlg_StrEvent:
+	cmp		bx, EVNT_MNU_UPD			; Update strings?
+	jne		MenuDlg_JmpToMsgEvnt		;  If not, use message handler
+	test	dl, MFL_UPD_NFO				; Update info strings?
+	jz		MenuDlg_JmpToMsgEvnt		;  If not, use message handler
+
+	; Get string from user
+	push	es
+	push	di
+	call	MenuCrsr_Show				; Show cursor during input
+	mov		bx, .VerifyChar				; Load offset to char verify function
+	mov		dx, [bp+DLGVARS.wBuffLen]	; Load buffer length
+	mov		di, [bp+DLGVARS.dwBuffPtr]	; Load buffer offset
+	mov		es, [bp+DLGVARS.dwBuffPtr+2]; Load buffer segment
+	call	Keys_GetStrToBuffer			; Get string from user
+	mov		[bp+DLGVARS.wRetLen], ax	; Store string length
+	rcl		BYTE [bp+DLGVARS.fSuccess], 1	; Set or clear success flag
+	pop		di
+	pop		es
+	jmp		MenuDlg_ExitHandler
+ALIGN JUMP_ALIGN
+.VerifyChar:
+	stc									; Set CF to allow all chars
+	ret
Index: /tags/Configurator_v1.1.0/Src/Libraries/menu/menudraw.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Libraries/menu/menudraw.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Libraries/menu/menudraw.asm	(revision 6)
@@ -0,0 +1,467 @@
+; File name		:	menudraw.asm
+; Project name	:	Menu library
+; Created date	:	9.11.2009
+; Last update	:	21.1.2010
+; Author		:	Tomi Tilli
+; Description	:	ASM library to menu system.
+;					Contains menu drawing functions.
+
+;--------------- Equates -----------------------------
+
+
+
+;-------------- Private global variables -------------
+; Section containing initialized data
+;SECTION .data
+
+g_strTimeout:	db	B_LL,BHL_TVR,"Selection Timeout %us",TVL_BHR,STOP
+
+
+;-------------- Public functions ---------------------
+; Section containing code
+SECTION .text
+
+
+;--------------------------------------------------------------------
+; Clears screen.
+;
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuDraw_ClrScr:
+	xor		dx, dx						; Cursor to (0,0)
+	call	MenuCrsr_SetCursor
+	mov		ah, 0Fh						; Get Current Video Mode
+	int		10h
+	mov		al, CNT_SCRN_ROW			; Load row count
+	mul		ah							; AX=Column count * row count
+	mov		cx, ax						; Copy char count to CX
+	mov		bx, ATTR_MDA_NORMAL			; Page zero, normal attribute
+	mov		ax, 0920h					; Write Char and attr, space char
+	int		10h
+	ret
+
+
+;--------------------------------------------------------------------
+; Changes line. When printing menu strings, this function must be
+; called instead of normal Print_Newline.
+;
+; MenuDraw_NewlineStrClrLn	Clear current line from cursor pos before newline
+; MenuDraw_NewlineStr
+;	Parameters:
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuDraw_NewlineStrClrLn:
+	push	cx
+	call	MenuCrsr_GetCursor				; Get current cursor to DX
+	eMOVZX	cx, BYTE [bp+MENUVARS.bWidth]	; Load menu width
+	add		cl, [bp+MENUVARS.bInitX]		; Add menu start X coord
+	sub		cl, W_OFF_CRSR_STR & 0FFh		; Subtract right borders
+	sub		cl, dl							; Subtract current X coord
+	mov		dl, ' '							; Clear with space
+	call	Print_Repeat					; Clear line to the end
+	pop		cx
+ALIGN JUMP_ALIGN
+MenuDraw_NewlineStr:
+	push	cx
+	call	MenuCrsr_GetCursor				; Get current cursor to DX
+	mov		dl, [bp+MENUVARS.bInitX]		; Load X offset to border
+	add		dx, W_OFF_CRSR_STR				; Inc X and Y
+	call	MenuCrsr_SetCursor				; Set new cursor
+	pop		cx
+	ret
+
+
+;--------------------------------------------------------------------
+; Draws multiline Title or Info string.
+;
+; MenuDraw_MultilineStr
+;	Parameters:
+;		CX:		Max Title or Info line count (menu initialization params)
+;		ES:DI:	Ptr to STOP terminated string to display
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+%ifdef USE_MENU_DIALOGS
+ALIGN JUMP_ALIGN
+MenuDraw_MultilineStr:
+	push	si
+	xor		si, si
+ALIGN JUMP_ALIGN
+.LineLoop:
+	xchg	cx, si							; Idx to CX, count to SI
+	push	cx
+	call	MenuMsg_WriteLine				; Write line
+	pop		cx
+	jc		.Return							;  Return if last token written
+	call	MenuDraw_NewlineStr				; Cursor to next line
+	inc		cx								; Increment line index
+	xchg	cx, si							; Count to CX, idx to SI
+	loop	.LineLoop						; Loop while lines left
+ALIGN JUMP_ALIGN
+.Return:
+	pop		si
+	ret
+%endif ; USE_MENU_DIALOGS
+
+
+;--------------------------------------------------------------------
+; Draws menu component.
+;
+; MenuDraw_Title			Draws Title borders and user string
+; MenuDraw_Info				Draws Info borders and user string
+; MenuDraw_AllItems			Draws Item borders and all user menuitems
+; MenuDraw_TitleNoBord		MenuDraw_Title without clearing old chars
+; MenuDraw_InfoNoBord		MenuDraw_Info without clearing old chars
+; MenuDraw_AllItemsNoBord	MenuDraw_AllItems without clearing old chars
+;	Parameters:
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+;ALIGN JUMP_ALIGN
+;MenuDraw_Title:
+;	call	MenuDraw_TitleBorders			; Draw borders to clear old strings
+ALIGN JUMP_ALIGN
+MenuDraw_TitleNoBord:
+	cmp		BYTE [bp+MENUVARS.bTitleH], 0	; Any title strings?
+	jz		MenuDraw_NothingToDraw			;  If not, return
+	call	MenuCrsr_PointTitle				; Set cursor position
+	mov		dl, MFL_UPD_TITLE				; Update title string
+	jmp		MenuDraw_SendEvent
+
+;ALIGN JUMP_ALIGN
+;MenuDraw_Info:
+;	call	MenuDraw_InfoBorders			; Draw borders to clear old strings
+ALIGN JUMP_ALIGN
+MenuDraw_InfoNoBord:
+	cmp		BYTE [bp+MENUVARS.bInfoH], 0	; Any info strings?
+	jz		MenuDraw_NothingToDraw			;  If not, return
+	test	BYTE [bp+MENUVARS.bFlags], FLG_MNU_HIDENFO
+	jnz		MenuDraw_NothingToDraw			; Return if info is hidden
+	call	MenuCrsr_PointInfo				; Set cursor position
+	mov		dl, MFL_UPD_NFO					; Update title string
+	jmp		MenuDraw_SendEvent
+
+;ALIGN JUMP_ALIGN
+;MenuDraw_AllItems:
+;	call	MenuDraw_ItemBorders			; Draw borders to clear old strings
+ALIGN JUMP_ALIGN
+MenuDraw_AllItemsNoBord:	
+	cmp		WORD [bp+MENUVARS.wItemCnt], 0	; Any items to draw?
+	jz		MenuDraw_NothingToDraw			;  If not, return
+	call	MenuCrsr_Point1stItem			; Set cursor position
+	mov		cx, [bp+MENUVARS.wItemTop]		; Load idx of first menuitem to draw
+	eMOVZX	dx, BYTE [bp+MENUVARS.bVisCnt]	; Load number of visible menuitems
+	MIN_U	dx, [bp+MENUVARS.wItemCnt]		; Limit to item count
+	add		dx, cx							; One past last menuitem to draw
+ALIGN JUMP_ALIGN
+.DrawLoop:
+	push	dx
+	call	MenuDraw_Item					; Draw menuitem
+	pop		dx
+	inc		cx								; Increment menuitem index
+	cmp		cx, dx							; More items left?
+	jb		.DrawLoop						;  If so, loop
+	jmp		MenuDraw_NothingToDraw
+
+ALIGN JUMP_ALIGN
+MenuDraw_SendEvent:
+	mov		bx, EVNT_MNU_UPD				; Update string
+	call	MenuLoop_SendEvent
+ALIGN JUMP_ALIGN
+MenuDraw_NothingToDraw:
+	call	MenuCrsr_PointBelowBrdr			; Cursor to safe location
+	ret
+
+
+;--------------------------------------------------------------------
+; Draws Menuitem without borders.
+; This function does not set initial cursor position but does
+; change line for next menuitem!
+;
+; MenuDraw_Item
+;	Parameters:
+;		CX:		Index of menuitem to draw
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		AL:		1=Menuitem drawed by user event handler
+;				0=Menuitem not drawed by user event handler
+;	Corrupts registers:
+;		AH, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuDraw_Item:
+	push	cx
+	test	BYTE [bp+MENUVARS.bFlags], FLG_MNU_NOARRW
+	jnz		.DrawString					; Don't draw arrow unless wanted
+	mov		dl, RARROW					; Prepare to draw selection arrow
+	cmp		cx, [bp+MENUVARS.wItemSel]	; Drawing selected item?
+	je		.DrawArrow					;  If so, jump to draw arrow
+	mov		dl, ' '						; Load space instead of arrow
+ALIGN JUMP_ALIGN
+.DrawArrow:
+	PRINT_CHAR
+	mov		dl, ' '						; Draw space before user str
+	PRINT_CHAR
+ALIGN JUMP_ALIGN
+.DrawString:
+	mov		dl, MFL_UPD_ITEM			; Draw item string
+	mov		bx, EVNT_MNU_UPD			; Update string
+	call	[bp+MENUVARS.fnEvent]		; Send event
+	call	MenuDraw_NewlineStr			; Move cursor to next menuitem
+	pop		cx
+	ret
+
+
+;-------------- Private functions --------------------
+
+;--------------------------------------------------------------------
+; Changes line. When printing menu borders, this function must be
+; called instead of normal Print_Newline.
+;	Parameters:
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuDraw_NewlineBrdr:
+	call	MenuCrsr_GetCursor			; Get current cursor to DX
+	mov		dl, [bp+MENUVARS.bInitX]	; Load X offset to border
+	inc		dh							; Increment Y coordinate
+	jmp		MenuCrsr_SetCursor			; Set new cursor
+
+
+;--------------------------------------------------------------------
+; Draws menu borders. User strings will be cleared.
+;
+; MenuDraw_TitleBorders		Draws Title borders
+; MenuDraw_InfoBorders		Draws Info borders
+; MenuDraw_ItemBorders		Draws Item borders
+; MenuDraw_Timeout			Draw timeout border (not whole InfoBorders)
+;	Parameters:
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuDraw_TitleBorders:
+	xor		dx, dx							; Zero DX
+	call	MenuCrsr_PointTitleBrdr			; Set cursor
+	call	MenuDraw_TopBorder				; Draw top border
+	call	MenuDraw_NewlineBrdr			; Change line
+	eMOVZX	cx, BYTE [bp+MENUVARS.bTitleH]	; Load number of title strings
+	jcxz	.Return							; Return if no title strings
+ALIGN JUMP_ALIGN
+.LineLoop:
+	push	cx
+	call	MenuDraw_StringBorder
+	call	MenuDraw_NewlineBrdr
+	pop		cx
+	loop	.LineLoop
+	jmp		MenuDraw_MiddleBorder			; Thin border before menuitems
+ALIGN JUMP_ALIGN
+.Return:
+	ret
+
+ALIGN JUMP_ALIGN
+MenuDraw_InfoBorders:
+	xor		dx, dx							; Zero DX
+	call	MenuCrsr_PointNfoBrdr			; Set cursor
+	cmp		BYTE [bp+MENUVARS.bInfoH], 0	; Any info strings?
+	jz		MenuDraw_BottomBorder			;  If not, draw bottom border
+	test	BYTE [bp+MENUVARS.bFlags], FLG_MNU_HIDENFO
+	jnz		MenuDraw_BottomBorder			; Draw bottom border if info is hidden
+	call	MenuDraw_MiddleBorder			; Draw middle border
+	call	MenuDraw_NewlineBrdr			; Change line
+	eMOVZX	cx, BYTE [bp+MENUVARS.bInfoH]	; Load number of info strings
+ALIGN JUMP_ALIGN
+.LineLoop:
+	push	cx
+	call	MenuDraw_StringBorder
+	call	MenuDraw_NewlineBrdr
+	pop		cx
+	loop	.LineLoop
+	jmp		MenuDraw_BottomBorder
+	
+ALIGN JUMP_ALIGN
+MenuDraw_Timeout:
+	xor		dx, dx							; Zero DX
+	call	MenuCrsr_PointNfoBrdr			; Set cursor
+	mov		ch, [bp+MENUVARS.bInfoH]		; Load info str count to CH
+	test	ch, ch							; Any info strings?
+	jz		MenuDraw_BottomBorder			;  If not, draw bottom border
+	inc		ch								; Increment for info top border
+	xor		cl, cl							; Zero X coordinate
+	call	MenuCrsr_Move					; Move cursor
+	jmp		MenuDraw_BottomBorder
+
+ALIGN JUMP_ALIGN
+MenuDraw_ItemBorders:
+	cmp		WORD [bp+MENUVARS.wItemCnt], 0	; Any items?
+	jz		.Return							;  If not, return
+	xor		dx, dx							; Zero DX
+	call	MenuCrsr_PointItemBrdr			; Set cursor
+	eMOVZX	cx, BYTE [bp+MENUVARS.bVisCnt]	; Load max number of item strings
+ALIGN JUMP_ALIGN
+.LineLoop:
+	push	cx
+	call	MenuDraw_ScrollBorder
+	call	MenuDraw_NewlineBrdr
+	pop		cx
+	loop	.LineLoop
+.Return:
+	ret
+
+
+;--------------------------------------------------------------------
+; Draw horizontal border line to current cursor location.
+; MenuDraw_TopBorder	Draw thick top menu border
+; MenuDraw_StringBorder	Draw thick user string border
+; MenuDraw_ScrollBorder	Draw scrolling border for menuitems
+; MenuDraw_MiddleBorder	Draw thin middle menu border
+; MenuDraw_BottomBorder	Draw thick bottom menu border with timeout if set
+;	Parameters:
+;		CX:		Loop counter (Items left, MenuDraw_ScrollBorder only)
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuDraw_TopBorder:
+	mov		bh, B_TL
+	mov		bl, B_H
+	mov		dh, B_TR
+	jmp		MenuDraw_BorderChars
+	
+ALIGN JUMP_ALIGN
+MenuDraw_StringBorder:
+	mov		bh, B_V
+	mov		bl, ' '
+	mov		dh, B_V
+	jmp		MenuDraw_BorderChars
+
+ALIGN JUMP_ALIGN
+MenuDraw_ScrollBorder:
+	call	MenuDraw_GetScrollChar			; Load scroll char to DH
+	mov		bh, B_V
+	mov		bl, ' '
+	jmp		MenuDraw_BorderChars
+
+ALIGN JUMP_ALIGN
+MenuDraw_MiddleBorder:
+	mov		bh, BVL_THR
+	mov		bl, T_H
+	mov		dh, THL_BVR
+
+ALIGN JUMP_ALIGN
+MenuDraw_BorderChars:
+	mov		dl, bh							; Leftmost
+	PRINT_CHAR
+	eMOVZX	cx, BYTE [bp+MENUVARS.bWidth]
+	times 2 dec cx							; Subtract borders
+	mov		dl, bl							; Middle
+	call	Print_Repeat
+	mov		dl, dh							; Rightmost
+	PRINT_CHAR
+	ret
+
+ALIGN JUMP_ALIGN
+MenuDraw_BottomBorder:
+	mov		bh, B_LL
+	mov		bl, B_H
+	mov		dh, B_LR
+	cmp		WORD [bp+MENUVARS.wTimeInit], 0	; Timeout enabled?
+	jz		MenuDraw_BorderChars			;  If not, draw normal
+
+	; Print timeout value
+	push	ds
+	push	si
+	push	cs
+	pop		ds								; Copy CS to DS
+	mov		si, g_strTimeout				; Load ptr to timeout str (DS:SI)
+	mov		ax, 55							; 1 timer tick = 54.945ms
+	mul		WORD [bp+MENUVARS.wTimeout]		; DX:AX = millisecs
+	eSHR_IM	ax, 10							; ms to s (close enough to 1000)
+	push	ax								; Push seconds
+	call	Print_Format					; Print timeout
+	add		sp, 2							; Clean stack
+	pop		si
+	pop		ds
+
+	; Print remaining border chars
+	call	MenuCrsr_GetCursor				; Get cursor location to DX
+	sub		dl, [bp+MENUVARS.bInitX]		; Compensate for start X...
+	inc		dx								; ...and lower right corner
+	mov		dh, [bp+MENUVARS.bWidth]		; Load menu width to DH
+	sub		dh, dl							; Subtract current X coordinate
+	eMOVZX	cx, dh							; Number of border chars needed
+	mov		dl, B_H
+	call	Print_Repeat
+	mov		dl, B_LR
+	PRINT_CHAR
+	ret
+
+
+;--------------------------------------------------------------------
+; Returns character for scroll bars if needed.
+; If scroll bars are not needed, normal border character will be returned.
+;
+; Note! Current implementation doesn't always return thumb character
+;		if there are a lot of pages. Checking last char only is not enough.
+;
+; MenuDraw_GetScrollChar
+;	Parameters:
+;		CX:		Loop counter (Items left, MenuDraw_ScrollBorder only)
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		DH:		Scroll bar character
+;	Corrupts registers:
+;		AX, BX, CX, DL
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuDraw_GetScrollChar:
+	mov		dh, B_V						; Assume no scroll bars needed
+	mov		ax, [bp+MENUVARS.wItemCnt]	; Load menuitem count to AX
+	eMOVZX	bx, BYTE [bp+MENUVARS.bVisCnt]	; Load visible menuitems to BX
+	cmp		ax, bx						; Need scroll bars?
+	jbe		.Return						;  If not, return
+	
+	; Calculate last menuitem index for thumb char on this line
+	push	bx							; Store number of visible menuitems
+	sub		bx, cx						; Calculate Line index
+	inc		bx							; Increment for next line index
+	mul		bx							; DX:AX=Total item count * Next line idx
+	pop		bx							; Pop number of visible menuitems
+	div		bx							; AX=First Menuitem for next string line
+	dec		ax							; AX=Last Menuitem for this string line
+
+	; Draw thumb or track
+	mov		dh, FULL_BLCK				; Assume thumb line
+	call	Menu_IsItemVisible			; Is thumb menuitem visible?
+	jc		.Return						;  If so, draw thumb
+	mov		dh, T_V						; Load track character
+ALIGN JUMP_ALIGN
+.Return:
+	ret
Index: /tags/Configurator_v1.1.0/Src/Libraries/menu/menufile.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Libraries/menu/menufile.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Libraries/menu/menufile.asm	(revision 6)
@@ -0,0 +1,319 @@
+; File name		:	menufile.asm
+; Project name	:	Menu library
+; Created date	:	20.11.2009
+; Last update	:	8.1.2010
+; Author		:	Tomi Tilli
+; Description	:	ASM library to menu system.
+;					Contains functions for displaying file dialog.
+
+;--------------- Equates -----------------------------
+
+; Dialog init and return variables.
+; This is an expanded MSGVARS struct.
+struc FDLGVARS
+	.msgVars	resb	MSGVARS_size
+
+	; Dialog parameters
+	.fpFileSrch	resb	4	; Far pointer to file search string
+	.wFileCnt	resb	2	; Number of directories and files to display
+	.wDrvCnt	resb	2	; Valid drive letter count
+
+	; Return variables for different dialogs
+	.fpDTA		resb	4	; Ptr to DTA for selected file
+	.fSuccess	resb	1	; Was data inputted successfully by user
+				resb	1	; Alignment
+endstruc
+
+
+;-------------- Private global variables -------------
+; Section containing initialized data
+;SECTION .data
+
+g_szDir:	db	"[%S]",STOP
+g_szDrv:	db	"[%c:]",STOP
+
+
+;-------------- Public functions ---------------------
+; Section containing code
+SECTION .text
+
+
+;--------------------------------------------------------------------
+; Displays file dialog.
+;
+; MenuFile_ShowDlg
+;	Parameters:
+;		BL:		Dialog width with borders included
+;		SS:BP:	Ptr to MENUVARS
+;		ES:DI:	Ptr to STOP terminated string to display
+;		DS:SI:	Ptr to file search string (* and ? wildcards supported)
+;	Returns:
+;		DS:SI:	Ptr to selected file name string
+;		CF:		Set if user data inputted successfully
+;				Cleared is input cancelled
+;	Corrupts registers:
+;		BX, CX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuFile_ShowDlg:
+	; Create stack frame
+	eENTER	FDLGVARS_size, 0
+	sub		bp, FDLGVARS_size				; Point to FDLGVARS
+
+	; Initialize menu variables
+	mov		bh, CNT_SCRN_ROW				; Menu height
+	mov		[bp+MENUVARS.wSize], bx			; Menu size
+	mov		[bp+MSGVARS.wStrOff], di		; Store far ptr...
+	mov		[bp+MSGVARS.wStrSeg], es		; ...to info string to display
+	mov		[bp+FDLGVARS.fpFileSrch], si	; Store far pointer...
+	mov		[bp+FDLGVARS.fpFileSrch+2], ds	; ...to file search string
+	;call	File_GetValidDrvCnt				; Get drive letter count to CX (drive support broken! Works on DOSBox, not on DOS 6.22)
+	xor		cx, cx
+	mov		[bp+FDLGVARS.wDrvCnt], cx
+	mov		WORD [bp+MENUVARS.fnEvent], MenuFile_Event
+	mov		BYTE [bp+FDLGVARS.fSuccess], 0	; For user cancel
+	call	MenuMsg_GetLineCnt				; Get Info line count to CX
+	xchg	cl, ch							; CH=Info lines, CL=Title lines
+	mov		[bp+MENUVARS.wTopDwnH], cx
+
+	; Enter menu
+	mov		dx, si							; File search str ptr to DS:DX
+	call	MenuFile_GetItemCnt				; Get menuitem count to CX
+	call	MenuCrsr_GetCenter				; Get X and Y coordinates to DX
+	xor		ax, ax							; Selection timeout (disable)
+	xor		bx, bx							; Menu flags
+	call	Menu_Init						; Returns only after dlg closed
+
+	; Return
+	mov		si, [bp+FDLGVARS.fpDTA]			; Load offset to return DTA
+	mov		ds, [bp+FDLGVARS.fpDTA+2]		; Load segment to return DTA
+	mov		bl, [bp+FDLGVARS.fSuccess]		; Load success flag
+	add		bp, FDLGVARS_size				; Point to old BP
+	eLEAVE									; Destroy stack frame
+	rcr		bl, 1							; Move success flag to CF
+	ret
+
+
+;-------------- Private functions ---------------------
+
+;--------------------------------------------------------------------
+; File dialog event handler.
+;
+; MenuFile_Event
+;	Parameters:
+;		DS:DX:	Ptr to file search string (for example *.* or C:\temp\*.txt)
+;		SS:BP:	Ptr to FDLGVARS
+;	Returns:
+;		CX:		Number of menuitems to display files and drives
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuFile_GetItemCnt:
+	call	File_FindAndCount				; Get message line count to CX
+	mov		[bp+FDLGVARS.wFileCnt], cx		; Store file and dir count
+	add		cx, [bp+FDLGVARS.wDrvCnt]		; Add drive letter count to CX
+	ret
+
+
+;--------------------------------------------------------------------
+; Directory, File and Drive rendering functions for menuitems.
+; Cursor is assumed to be on correct position when this function is called.
+;
+; MenuFile_DrawItem
+;	Parameters:
+;		CX:		Index of menuitem to draw
+;		SS:BP:	Ptr to FDLGVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuFile_DrawItem:
+	push	ds
+	mov		dx, [bp+FDLGVARS.fpFileSrch]	; Load ptr to file search str
+	mov		ds, [bp+FDLGVARS.fpFileSrch+2]
+	call	File_GetDTA						; Get DTA ptr to DS:BX
+	jc		.DrawDrv						; No dir or file, draw drive
+	test	BYTE [bx+DTA.bFileAttr], FLG_FATTR_DIR
+	jnz		.DrawDir
+
+;--------------------------------------------------------------------
+; Directory, File and Drive rendering for menuitems.
+; Cursor is assumed to be on correct position.
+;
+; .DrawFile		Draws file menuitem
+; .DrawDir		Draws directory menuitem
+; .DrawDrv		Draws drive menuitem
+;	Parameters:
+;		CX:		Index of menuitem to draw
+;		DS:BX:	Ptr to DTA for menuitem (not for .DrawDrv)
+;		SS:BP:	Ptr to FDLGVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+.DrawFile:
+	lea		dx, [bx+DTA.szFile]	; DS:DX now points to filename string
+	PRINT_STR
+	pop		ds
+	ret
+ALIGN JUMP_ALIGN
+.DrawDir:
+	push	si
+	lea		ax, [bx+DTA.szFile]	; Dir string offset to AX
+	push	ds					; Push dir string segment
+	push	ax					; Push dir string offset
+	push	cs					; Copy CS...
+	pop		ds					; ...to DS for format string
+	mov		si, g_szDir			; Format string now in DS:SI
+	call	Print_Format
+	add		sp, 4				; Clean stack variables
+	pop		si
+	pop		ds
+	ret
+ALIGN JUMP_ALIGN
+.DrawDrv:
+	push	si
+	sub		cx, [bp+FDLGVARS.wFileCnt]	; Menuitem to valid drive index
+	call	File_GetNthValidDrv			; Get letter to AX
+	push	ax							; Push drive letter
+	push	cs							; Copy CS...
+	pop		ds							; ...to DS for format string
+	mov		si, g_szDrv					; Format string now in DS:SI
+	call	Print_Format
+	add		sp, 2						; Clean stack variables
+	pop		si
+	pop		ds
+	ret
+
+
+;--------------------------------------------------------------------
+; File dialog event handler.
+;
+; MenuFile_Event
+;	Parameters:
+;		BX:		Callback event
+;		CX:		Selected menuitem index
+;		DX:		Event parameter (event specific)
+;		SS:BP:	Ptr to FDLGVARS
+;	Returns:
+;		AH:		Event specific or unused
+;		AL:		1=Event processed
+;				0=Event not processed (default action if any)
+;	Corrupts registers:
+;		BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuFile_Event:
+	cmp		bx, EVNT_MNU_UPD		; Above last supported?
+	ja		.EventNotHandled		;  If so, return
+	shl		bx, 1					; Shift for word lookup
+	jmp		[cs:bx+.rgwEventJump]	; Jumpt to handle event
+ALIGN WORD_ALIGN
+.rgwEventJump:
+	dw		.EventExit				; 0, EVNT_MNU_EXIT
+	dw		.EventSelChg			; 1, EVNT_MMU_SELCHG
+	dw		.EventSelSet			; 2, EVNT_MNU_SELSET
+	dw		.EventKey				; 3, EVNT_MNU_KEY
+	dw		.EventUpd				; 4, EVNT_MNU_UPD
+
+; Events that do not require any handling
+ALIGN JUMP_ALIGN
+.EventSelChg:
+.EventKey:
+.EventNotHandled:
+	xor		ax, ax					; Event not processed
+	ret
+ALIGN JUMP_ALIGN
+.EventExit:
+.EventHandled:	; Return point from all handled events
+	mov		ax, 1
+	ret
+
+
+;--------------------------------------------------------------------
+; EVNT_MNU_SELSET event handler.
+;
+; .EventSelSet
+;	Parameters:
+;		CX:		Index of menuitem that user selected
+;		SS:BP:	Ptr to FDLGVARS
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.EventSelSet:
+	push	ds
+	cmp		cx, [bp+FDLGVARS.wFileCnt]		; Selecting file or dir?
+	jae		.ChgDrv							;  If not, must be drive
+	mov		dx, [bp+FDLGVARS.fpFileSrch]	; Load ptr to file search str
+	mov		ds, [bp+FDLGVARS.fpFileSrch+2]
+	call	File_GetDTA						; Get DTA ptr to DS:BX
+	rcl		al, 1							; CF to AL
+	test	BYTE [bx+DTA.bFileAttr], FLG_FATTR_DIR
+	jnz		.ChgDir							; If directory, go change
+
+	; File selected, close dialog
+	not		al								; Invert CF
+	mov		[bp+FDLGVARS.fSuccess], al		; Store success flag
+	mov		[bp+FDLGVARS.fpDTA], bx			; Store offset to DTA
+	mov		[bp+FDLGVARS.fpDTA+2], ds		; Store segment to DTA
+	pop		ds
+	jmp		MenuDlg_ExitHandler				; Close dialog
+
+ALIGN JUMP_ALIGN
+.ChgDrv:
+	sub		cx, [bp+FDLGVARS.wFileCnt]		; Menuitem to drive index
+	call	File_GetNthValidDrv				; Drv device num to DX
+	call	File_SetDrive					; Change drive
+	jmp		.ChangeDone						; Update menu
+ALIGN JUMP_ALIGN
+.ChgDir:
+	lea		dx, [bx+DTA.szFile]				; Offset to new path
+	call	File_ChangeDir					; Change directory
+ALIGN JUMP_ALIGN
+.ChangeDone:
+	mov		dx, [bp+FDLGVARS.fpFileSrch]	; Load ptr to file search str
+	mov		ds, [bp+FDLGVARS.fpFileSrch+2]
+	call	MenuFile_GetItemCnt				; Get file count from new dir
+	pop		ds
+	xor		dx, dx							; Redraw only necessary
+	call	Menu_InvItemCnt					; Redraw with new items
+	jmp		.EventHandled
+
+;--------------------------------------------------------------------
+; EVNT_MNU_UPD event handler.
+;
+; .EventUpd
+;	Parameters:
+;		CX:		Index of menuitem to update (MFL_UPD_ITEM only)
+;		DL:		Update flag:
+;					MFL_UPD_TITLE	Set to update title string
+;					MFL_UPD_NFO		Set to update info string
+;					MFL_UPD_ITEM	Set to update menuitem string
+;		SS:BP:	Ptr to FDLGVARS
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.EventUpd:
+	test	dl, MFL_UPD_TITLE	; Update title?
+	jnz		.EventNotHandled	;  If so, return without handling event
+	test	dl, MFL_UPD_NFO		; Update info?
+	jnz		.DrawInfo			;  If so, jump to update
+
+	; Update Menuitem
+	call	MenuFile_DrawItem	; Draw menuitem
+	jmp		.EventHandled
+
+	; Update Info string
+ALIGN JUMP_ALIGN
+.DrawInfo:
+	push	es
+	push	di
+	mov		di, [bp+MSGVARS.wStrOff]		; Load string offset
+	mov		es, [bp+MSGVARS.wStrSeg]		; Load string segment
+	eMOVZX	cx, BYTE [bp+MENUVARS.bInfoH]	; Load info line count to CX
+	call	MenuDraw_MultilineStr			; Draw multiline str
+	pop		di
+	pop		es
+	jmp		.EventHandled
Index: /tags/Configurator_v1.1.0/Src/Libraries/menu/menuloop.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Libraries/menu/menuloop.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Libraries/menu/menuloop.asm	(revision 6)
@@ -0,0 +1,329 @@
+; File name		:	menuloop.asm
+; Project name	:	Menu library
+; Created date	:	11.11.2009
+; Last update	:	10.12.2009
+; Author		:	Tomi Tilli
+; Description	:	ASM library to menu system.
+;					Contains event dispatching loop.
+
+;--------------- Equates -----------------------------
+
+; BIOS scan codes
+KEY_ENTER		EQU		1Ch
+KEY_ESC			EQU		01h
+KEY_UP			EQU		48h
+KEY_DOWN		EQU		50h
+KEY_PGUP		EQU		49h
+KEY_PGDN		EQU		51h
+KEY_HOME		EQU		47h
+KEY_END			EQU		4Fh
+CNT_MENU_KEYS	EQU		8		; Number of menukeys
+
+
+;-------------- Private global variables -------------
+; Section containing initialized data
+;SECTION .data
+
+
+;-------------- Public functions ---------------------
+; Section containing code
+SECTION .text
+
+
+;--------------------------------------------------------------------
+; Waits keyboard input, updates timeout and dispatch event for
+; user handler.
+;	Parameters:
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuLoop_Enter:
+	; Get current time for timeout
+	call	Menu_GetTime					; Get system time ticks to CX:DX
+	mov		[bp+MENUVARS.wTimeLast], dx		; Store last read time
+
+	; Check if menu operation should be continued
+ALIGN JUMP_ALIGN
+.CheckExit:
+	test	BYTE [bp+MENUVARS.bFlags], FLG_MNU_EXIT
+	jnz		.Return							; Return if exit flag set
+
+	; Check if keystroke available
+	call	Keys_GetStroke					; Get keystroke to AX
+	jz		.CheckTimeout					; If no keystroke, jump to check timeout
+	call	MenuLoop_ProcessKey				; Convert keystroke to events
+
+	; Check if timeout needs updating
+ALIGN JUMP_ALIGN
+.CheckTimeout:
+	cmp		WORD [bp+MENUVARS.wTimeInit], 0	; Timeout enabled?
+	jz		.CheckExit						;  If not, loop
+	call	Menu_GetTime					; Get system time ticks to CX:DX
+	mov		cx, dx							; Copy time loword to CX
+	sub		dx, [bp+MENUVARS.wTimeLast]		; Has time changed?
+	je		.CheckExit						;  If not, loop
+
+	; Update timeout
+	mov		[bp+MENUVARS.wTimeLast], cx		; Store last update time
+	sub		[bp+MENUVARS.wTimeout], dx		; Update timeout
+	ja		.PrintTimeout					;  If time left, just print new value
+	call	MenuLoop_SendSelEvent			; Send selection event
+
+	; Print timeout value
+ALIGN JUMP_ALIGN
+.PrintTimeout:
+	call	MenuDraw_Timeout
+	xor		dx, dx
+	call	MenuCrsr_PointBelowBrdr
+	jmp		.CheckExit
+
+ALIGN JUMP_ALIGN
+.Return:
+	ret
+
+
+;--------------------------------------------------------------------
+; Sends Menu event to user handler (MENUVARS.fnEvent).
+; MenuLoop_SendSelEvent		Sends Menuitem Selected event to user event handler
+; MenuLoop_SendEvent		Sends any event to user event handler
+;	Parameters:
+;		BX:		Event code
+;		DX:		Event parameter (event specific)
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		AH:		Event specific or unused
+;		AL:		1=Event processed
+;				0=Event not processed (default action if any)
+;	Corrupts registers:
+;		BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuLoop_SendSelEvent:
+	mov		bx, EVNT_MNU_SELSET
+ALIGN JUMP_ALIGN
+MenuLoop_SendEvent:
+	mov		cx, [bp+MENUVARS.wItemSel]
+	call	[bp+MENUVARS.fnEvent]
+	ret
+
+
+;-------------- Private functions ---------------------
+
+
+;--------------------------------------------------------------------
+; Processed menu key input.
+; Menu keys will be handled and other keys dispatched as key events.
+;	Parameters:
+;		AH:		BIOS Scan Code for key
+;		AL:		ASCII character
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuLoop_ProcessKey:
+	push	es
+	push	di
+
+	; Check if wanted key
+	push	cs
+	pop		es					; Copy CS to ES
+	mov		cx, CNT_MENU_KEYS	; Load number of menu keys
+	mov		di, .rgbKeyToIdx	; Load offset to translation table
+	xchg	al, ah				; Scan code to AL
+	cld							; SCASB to increment DI
+	repne scasb					; Compare [ES:DI] to AL until match
+	jne		.Dispatch			; If not menukey, jump to dispatch
+
+	; Jump to process menu key
+	mov		di, CNT_MENU_KEYS-1	; Convert CX...	
+	sub		di, cx				; ...to lookup index
+	shl		di, 1				; Prepare for word lookup
+	jmp		[cs:di+.rgwMenuKeyJmp]
+
+	; Dispatch key event
+ALIGN JUMP_ALIGN
+.Dispatch:
+	xchg	al, ah				; Restore AX
+	mov		bx, EVNT_MNU_KEY
+	mov		dx, ax				; Copy keys to DX
+	call	MenuLoop_SendEvent
+ALIGN JUMP_ALIGN
+.Return:
+	pop		di
+	pop		es
+	ret
+
+	;;;;;;;;;;;;;;;;;;;;;
+	; Menu key handlers ;
+	;;;;;;;;;;;;;;;;;;;;;
+
+	; ENTER pressed
+ALIGN JUMP_ALIGN
+.KeyEnter:
+	call	MenuLoop_SendSelEvent			; Send selection event
+	jmp		.Return
+
+	; ESC pressed
+ALIGN JUMP_ALIGN
+.KeyEsc:
+	call	Menu_Exit
+	jc		.Return							; User cancelled exit
+	mov		WORD [bp+MENUVARS.wItemSel], -1
+	jmp		.Return
+
+	; UP pressed
+ALIGN JUMP_ALIGN
+.KeyUp:
+%ifdef USE_MENU_DIALOGS
+	test	BYTE [bp+MENUVARS.bFlags], FLG_MNU_NOARRW	; Message dialog mode?
+	jnz		.TextScrollUp					;  If so, go to text scrolling
+%endif
+	mov		ax, [bp+MENUVARS.wItemSel]		; Load selected index 
+	test	ax, ax							; Already at top?
+	jz		.KeyEnd							;  If so, go to end
+	mov		dx, ax							; Copy selected index to DX
+	dec		ax								; Decrement menuitem index
+	mov		[bp+MENUVARS.wItemSel], ax		; Store new index
+	cmp		ax, [bp+MENUVARS.wItemTop]		; Need to scroll?
+	jae		.DrawSelection					;  If not, go to draw selection
+	dec		WORD [bp+MENUVARS.wItemTop]		; Scroll
+	jmp		.ScrollMenu
+
+%ifdef USE_MENU_DIALOGS
+ALIGN JUMP_ALIGN
+.TextScrollUp:
+	cmp		WORD [bp+MENUVARS.wItemTop], 0	; Already at the top?
+	jz		.Return							;  If so, return
+	dec		WORD [bp+MENUVARS.wItemTop]
+	jmp		.ScrollMenu
+%endif
+
+	; DOWN pressed
+ALIGN JUMP_ALIGN
+.KeyDown:
+%ifdef USE_MENU_DIALOGS
+	test	BYTE [bp+MENUVARS.bFlags], FLG_MNU_NOARRW	; Message dialog mode?
+	jnz		.TextScrollDown					;  If so, go to text scrolling
+%endif
+	mov		ax, [bp+MENUVARS.wItemSel]		; Load selected index
+	mov		dx, ax							; Copy selected index to DX
+	inc		ax								; Increment menuitem index
+	cmp		ax, [bp+MENUVARS.wItemCnt]		; Already at bottom?
+	je		.KeyHome						;  If so, go to beginning
+	mov		[bp+MENUVARS.wItemSel], ax		; Store new menuitem index
+	eMOVZX	bx, BYTE [bp+MENUVARS.bVisCnt]	; Load number of visible items
+	add		bx, [bp+MENUVARS.wItemTop]		; BX to one past last visible index
+	cmp		ax, bx							; Need to scroll?
+	jb		.DrawSelection					;  If not, go to draw selection
+	inc		WORD [bp+MENUVARS.wItemTop]		; Scroll
+	jmp		.ScrollMenu
+
+%ifdef USE_MENU_DIALOGS
+ALIGN JUMP_ALIGN
+.TextScrollDown:
+	eMOVZX	ax, BYTE [bp+MENUVARS.bVisCnt]	; Load visible items
+	add		ax, [bp+MENUVARS.wItemTop]		; Add topmost menuitem index
+	cmp		ax, [bp+MENUVARS.wItemCnt]		; Already at the bottom?
+	jae		.Return							;  If so, return
+	inc		WORD [bp+MENUVARS.wItemTop]
+	jmp		.ScrollMenu
+%endif
+
+	; PGUP pressed
+ALIGN JUMP_ALIGN
+.KeyPgUp:
+	mov		ax, [bp+MENUVARS.wItemSel]		; Load selected index
+	div		BYTE [bp+MENUVARS.bVisCnt]		; AL=Current page index
+	sub		al, 1							; Decrement page
+	jc		.KeyHome						; Select first item if overflow
+	mul		BYTE [bp+MENUVARS.bVisCnt]		; AX=Fist menuitem on page
+	mov		[bp+MENUVARS.wItemSel], ax
+	mov		[bp+MENUVARS.wItemTop], ax
+	jmp		.ScrollMenu
+
+	; PGDN pressed
+ALIGN JUMP_ALIGN
+.KeyPgDn:
+	mov		ax, [bp+MENUVARS.wItemSel]		; Load selected index
+	div		BYTE [bp+MENUVARS.bVisCnt]		; AL=Current page index
+	inc		ax								; Increment page
+	mul		BYTE [bp+MENUVARS.bVisCnt]		; AX=First menuitem on page
+	eMOVZX	bx, BYTE [bp+MENUVARS.bVisCnt]	; Load number of visible items
+	add		bx, ax							; BX now one past last visible
+	cmp		bx, [bp+MENUVARS.wItemCnt]		; Went over last?
+	jae		.KeyEnd							;  If so, select last menuitem
+	mov		[bp+MENUVARS.wItemSel], ax
+	mov		[bp+MENUVARS.wItemTop], ax
+	jmp		.ScrollMenu
+
+	; HOME pressed
+ALIGN JUMP_ALIGN
+.KeyHome:
+	xor		ax, ax
+	mov		[bp+MENUVARS.wItemSel], ax
+	mov		[bp+MENUVARS.wItemTop], ax
+	jmp		.ScrollMenu
+
+	; END pressed
+ALIGN JUMP_ALIGN
+.KeyEnd:
+	mov		ax, [bp+MENUVARS.wItemCnt]		; Load number if menuitems
+	mov		bx, ax							; Copy menuitem count to BX
+	dec		ax								; Decrement for last index
+	mov		[bp+MENUVARS.wItemSel], ax		; Store new selection
+	sub		bl, [bp+MENUVARS.bVisCnt]		; BX to first menuitem to draw
+	sbb		bh, 0
+	mov		[bp+MENUVARS.wItemTop], bx		; Store first menuitem to draw
+	jnc		.ScrollMenu	
+	mov		WORD [bp+MENUVARS.wItemTop], 0	; Overflow, start with 0
+	; Fall to .ScrollMenu
+
+	; Menuitem selection changed, redraw all items
+ALIGN JUMP_ALIGN
+.ScrollMenu:
+	mov		bx, EVNT_MMU_SELCHG
+	call	MenuLoop_SendEvent
+	call	Menu_RestartTimeout
+	xor		cx, cx							; Invalidate...
+	dec		cx								; ...all menuitems
+	mov		dl, MFL_UPD_ITEM
+	call	Menu_Invalidate
+	jmp		.Return
+
+; Menuitem selection changed, only two items needs to be redrawn
+ALIGN JUMP_ALIGN
+.DrawSelection:
+	MINMAX_U ax, dx							; First menuitem to AX, next to DX
+	push	dx								; Store second to draw
+	push	ax								; Store first to draw
+	mov		bx, EVNT_MMU_SELCHG
+	call	MenuLoop_SendEvent
+	call	Menu_RestartTimeout
+	pop		cx								; First to draw to CX
+	call	MenuCrsr_PointNthItem			; Set cursor position
+	call	MenuDraw_Item					; Draw first menuitem
+	pop		cx								; Second to draw to CX
+	call	MenuDraw_Item					; Draw second menuitem
+	jmp		.Return
+
+ALIGN WORD_ALIGN
+.rgwMenuKeyJmp:
+	dw		.KeyEnter	; KEY_ENTER
+	dw		.KeyEsc		; KEY_ESC
+	dw		.KeyUp		; KEY_UP
+	dw		.KeyDown	; KEY_DOWN
+	dw		.KeyPgUp	; KEY_PGUP
+	dw		.KeyPgDn	; KEY_PGDN
+	dw		.KeyHome	; KEY_HOME
+	dw		.KeyEnd		; KEY_END
+; Scan code to jump index translation table
+.rgbKeyToIdx:	
+	db	KEY_ENTER,	KEY_ESC,	KEY_UP,		KEY_DOWN,
+	db	KEY_PGUP,	KEY_PGDN,	KEY_HOME,	KEY_END
Index: /tags/Configurator_v1.1.0/Src/Libraries/menu/menumsg.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Libraries/menu/menumsg.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Libraries/menu/menumsg.asm	(revision 6)
@@ -0,0 +1,299 @@
+; File name		:	menumsg.asm
+; Project name	:	Menu library
+; Created date	:	13.11.2009
+; Last update	:	10.1.2010
+; Author		:	Tomi Tilli
+; Description	:	ASM library to menu system.
+;					Contains functions for displaying messages.
+
+;--------------- Equates -----------------------------
+
+; Control characters for Menu Message string.
+; Normal control characters cannot be used since message string
+; will be tokenized and converted to menuitems.
+%define MNU_NL			" |n "	; Menu newline defined as token string
+W_MNU_NL			EQU	"|n"	; Menu newline defined as WORD
+
+; Total border chars on left and right side of string menuitem
+SIZE_MSG_HBRDR		EQU		4	; Horizontal border size
+
+; Message variables. This is an expanded MENUVARS struct.
+struc MSGVARS
+	.menuVars	resb	MENUVARS_size
+	.dwStrPtr:					; Far pointer to string to display
+	.wStrOff:	resb	2		; Offset to string to display
+	.wStrSeg:	resb	2		; Segment to string to display
+endstruc
+
+
+;-------------- Private global variables -------------
+; Section containing initialized data
+;SECTION .data
+
+
+;-------------- Public functions ---------------------
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Displays message string.
+;
+; MenuMsg_ShowMessage
+;	Parameters:
+;		BL:		Dialog width with borders included
+;		SS:BP:	Ptr to MENUVARS
+;		ES:DI:	Ptr to STOP terminated string to display
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuMsg_ShowMessage:
+	; Create stack frame
+	eENTER	MSGVARS_size, 0
+	sub		bp, MSGVARS_size				; Point to MSGVARS
+
+	; Initialize menu variables
+	mov		[bp+MENUVARS.bWidth], bl		; Menu size
+	mov		WORD [bp+MENUVARS.wTopDwnH], 0	; Title and Info size
+	mov		WORD [bp+MENUVARS.fnEvent], MenuMsg_MsgEvent
+	mov		[bp+MSGVARS.wStrOff], di		; Store far ptr...
+	mov		[bp+MSGVARS.wStrSeg], es		; ...to string to display
+
+	; Enter menu
+	call	MenuMsg_GetLineCnt				; Get message line count to CX
+	mov		ax, CNT_SCRN_ROW-2				; Load max line rows to AX
+	MIN_U	ax, cx							; String lines to display to AX
+	times 2	inc ax							; Include borders for dlg height
+	mov		[bp+MENUVARS.bHeight], al		; Store dialog height
+	call	MenuCrsr_GetCenter				; Get X and Y coordinates to DX
+	xor		ax, ax							; Selection timeout (disable)
+	mov		bl, FLG_MNU_NOARRW				; Menu flags
+	call	Menu_Init						; Returns only after dlg closed
+
+	; Return
+	add		bp, MSGVARS_size				; Point to old BP
+	eLEAVE									; Destroy stack frame
+	ret
+
+
+;-------------- Private functions ---------------------
+
+;--------------------------------------------------------------------
+; Calculates number of string lines needed by string to display.
+;
+; MenuMsg_GetLineCnt
+;	Parameters:
+;		SS:BP:	Ptr to MSGVARS
+;		ES:DI:	Ptr to STOP terminated string to display
+;	Returns:
+;		CX:		Number of lines needed
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuMsg_GetLineCnt:
+	push	di
+
+	; Get index for last line
+	mov		cx, -1					; Get last possible line
+	call	MenuMsg_GetTokenForLine
+	inc		cx						; Last index to line count
+
+	; Return
+	pop		di
+	ret
+
+
+;--------------------------------------------------------------------
+; Check if line has space for token.
+;
+; MenuMsg_HasLineSpace
+;	Parameters:
+;		AX:		Token length in characters
+;		DX:		Characters left on line
+;		ES:DI:	Ptr to token string (not terminated!)
+;	Returns:
+;		DX:		Chars left after token + space at the end
+;		CF:		Set if space left for token
+;				Cleared if not enough space
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuMsg_HasLineSpace:
+	sub		dx, ax
+	jl		.NoSpace
+	cmp		WORD [es:di], W_MNU_NL	; Newline token?
+	je		.NoSpace				;  If so, end line
+	dec		dx						; Decrement for space after token
+	stc								; Set CF since space left
+	ret
+ALIGN JUMP_ALIGN
+.NoSpace:
+	xor		dx, dx					; Clear space left and CF
+	ret
+
+
+;--------------------------------------------------------------------
+; Return pointer to first token for wanted message line.
+;
+; MenuMsg_GetTokenForLine
+;	Parameters:
+;		CX:		Line index
+;		ES:DI:	Ptr to STOP terminated string to display
+;		SS:BP:	Ptr to MSGVARS
+;	Returns:
+;		AX:		Length of first token in characters
+;		CX:		Index of last line found (if wanted line not found)
+;		ES:DI:	Ptr to token
+;		CF:		Set if message line found
+;				Cleared if message line not found
+;	Corrupts registers:
+;		BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuMsg_GetTokenForLine:
+	test	cx, cx				; Line 0 wanted?
+	jz		.GetFirst			;  If so, just get token length
+	push	bp
+	push	si
+
+	; Prepare to scan tokens
+	eMOVZX	si, [bp+MENUVARS.bWidth]
+	sub		si, SIZE_MSG_HBRDR	; Max number of chars per line
+	mov		dx, si				; Initialize chars left on line
+	mov		bp, cx				; Copy line index to BP
+	xor		bx, bx				; Zero line index counter
+	xor		ax, ax				; Zero token length
+
+	; Scan all tokens to calculate lines needed
+ALIGN JUMP_ALIGN
+.TokenLoop:
+	; Get token and length
+	xor		cx, cx				; Always read token at index 0
+	add		di, ax				; Increment offset for next token
+	call	String_StrToken		; Get token length to AX, ptr to ES:DI
+	jnc		.Return				; Return if no more tokens (CF cleared)
+	; Check does line have space left for token
+	call	MenuMsg_HasLineSpace
+	jc		.TokenLoop			; Space left, check next token
+	; Change to next line
+	mov		dx, si				; Copy max chars on line
+	call	MenuMsg_HasLineSpace; Update chars left
+	inc		bx					; Increment line index
+	cmp		bx, bp				; Correct line found?
+	jne		.TokenLoop			;  If not, check more tokens
+	stc							; Set CF since line found
+ALIGN JUMP_ALIGN
+.Return:
+	mov		cx, bx				; Copy idx of last line found to CX
+	pop		si
+	pop		bp
+	ret
+ALIGN JUMP_ALIGN
+.GetFirst:
+	jmp		String_StrToken		; Get token length to AX, ptr to ES:DI
+
+
+;--------------------------------------------------------------------
+; Message dialog menu event handler.
+;
+; MenuMsg_WriteLine
+;	Parameters:
+;		CX:		Index of line to display
+;		ES:DI:	Ptr to STOP terminated string to display
+;		SS:BP:	Ptr to MSGVARS
+;	Returns:
+;		CF:		Set if end of string
+;				Cleared if string has unwritten tokens
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuMsg_WriteLine:
+	push	di
+	call	MenuMsg_GetTokenForLine			; Get ptr to first token, length to AX
+	jnc		.EndOfString					; Return if no tokens
+	eMOVZX	dx, BYTE [bp+MENUVARS.bWidth]	; Menu width
+	sub		dl, SIZE_MSG_HBRDR				; To line length 
+	mov		bl, ' '							; Space character
+ALIGN JUMP_ALIGN
+.PrintToken:
+	; Check if space for token
+	call	MenuMsg_HasLineSpace	; Space left on line?
+	jnc		.PrintDone				;  If not, all done
+	; Print token
+	push	ax						; Store token length
+	mov		cx, ax					; Copy token length to CX
+	call	Print_CharBuffer		; Print token
+	xchg	dx, bx					; Space char to DL
+	PRINT_CHAR
+	xchg	dx, bx					; Restore DX
+	pop		ax						; Pop token length
+	; Get next token
+	add		di, ax					; Point to next token
+	xor		cx, cx					; Get token at index 0
+	call	String_StrToken			; Get next token to ES:DI, len to AX
+	jc		.PrintToken				; Print while tokens left
+ALIGN JUMP_ALIGN
+.EndOfString:	; Last token written
+	stc
+ALIGN JUMP_ALIGN
+.PrintDone:		; End of line but tokens left
+	pop		di
+	ret
+
+
+;--------------------------------------------------------------------
+; Message dialog menu event handler.
+;
+; MenuMsg_MsgEvent
+;	Parameters:
+;		BX:		Callback event
+;		CX:		Selected menuitem index
+;		DX:		Event parameter (event specific)
+;		SS:BP:	Ptr to MSGVARS
+;	Returns:
+;		AH:		Event specific or unused
+;		AL:		1=Event processed
+;				0=Event not processed (default action if any)
+;	Corrupts registers:
+;		BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuMsg_MsgEvent:
+	cmp		bx, EVNT_MMU_SELCHG		; Selection changed?
+	je		.RetProcessed			;  If so, return
+	cmp		bx, EVNT_MNU_SELSET		; Enter to close dialog?
+	je		.CloseDialog			;  If so, jump to close dialog
+	cmp		bx, EVNT_MNU_UPD		; Draw menuitem string?
+	je		.DrawLine				;  If so, jump to draw
+	cmp		bx, EVNT_MNU_KEY		; Any key pressed to close dialog?
+	jne		.RetUnhandled			;  If not, ignore message
+
+	; Close dialog since key pressed
+ALIGN JUMP_ALIGN
+.CloseDialog:
+	or		BYTE [bp+MENUVARS.bFlags], FLG_MNU_EXIT	; Any key, exit
+ALIGN JUMP_ALIGN
+.RetUnhandled:
+	xor		ax, ax
+	ret
+
+ALIGN JUMP_ALIGN
+.DrawLine:
+	push	es
+	push	di
+
+	; Print string line
+	mov		di, [bp+MSGVARS.wStrOff]; Load string offset
+	mov		es, [bp+MSGVARS.wStrSeg]; Load string segment
+	call	MenuMsg_WriteLine
+	pop		di
+	pop		es
+ALIGN JUMP_ALIGN
+.RetProcessed:
+	mov		ax, 1					; Event processed
+	ret
Index: /tags/Configurator_v1.1.0/Src/Libraries/menu/menuprog.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Libraries/menu/menuprog.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Libraries/menu/menuprog.asm	(revision 6)
@@ -0,0 +1,199 @@
+; File name		:	menuprog.asm
+; Project name	:	Menu library
+; Created date	:	23.11.2009
+; Last update	:	23.11.2009
+; Author		:	Tomi Tilli
+; Description	:	ASM library to menu system.
+;					Contains functions for displaying progress bar dialog.
+
+;--------------- Equates -----------------------------
+
+; Dialog init and return variables.
+; This is an expanded MSGVARS struct.
+struc PDLGVARS
+	.msgVars	resb	MSGVARS_size
+
+	; Dialog parameters
+	.fpUser		resb	4	; Far pointer to user specific data
+	.ffnTask	resb	4	; Far pointer to task function
+
+	; Return variables for different dialogs
+	.wRetUser	resb	2	; User specific return variable
+endstruc
+
+;--------------------------------------------------------------------
+; Function prototype for Progress Task function (PDLGVARS.fnTask).
+; Cursor will be set to Title string location so user may modify the
+; title string if needed.
+; Remember to return with RETF instead of RET!
+;	Parameters:
+;		DS:SI:	User specified far pointer
+;	Returns:
+;		AX:		User specified return code if CF set
+;				Task completion percentage (0...100) if CF cleared
+;		CF:		Set if task was completed or cancelled
+;				Cleared if task must be continued
+;	Corrupts registers:
+;		BX, CX, DX
+;--------------------------------------------------------------------
+
+
+;-------------- Private global variables -------------
+; Section containing initialized data
+;SECTION .data
+
+
+;-------------- Public functions ---------------------
+; Section containing code
+SECTION .text
+
+
+;--------------------------------------------------------------------
+; Displays progress bar dialog.
+;
+; MenuProg_Show
+;	Parameters:
+;		BL:		Dialog width with borders included
+;		BH:		Dialog height with borders included
+;		SS:BP:	Ptr to MENUVARS
+;		ES:DI:	Far ptr to user specified task function
+;		DS:SI:	User specified far pointer
+;	Returns:
+;		AX:		User specified return code
+;	Corrupts registers:
+;		BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuProg_Show:
+	; Create stack frame
+	eENTER	PDLGVARS_size, 0
+	sub		bp, PDLGVARS_size				; Point to PDLGVARS
+
+	; Initialize menu variables
+	mov		[bp+MENUVARS.wSize], bx			; Menu size
+	mov		[bp+PDLGVARS.fpUser], si		; Store user defined...
+	mov		[bp+PDLGVARS.fpUser+2], ds		; ...far pointer
+	mov		[bp+PDLGVARS.ffnTask], di		; Store far ptr to...
+	mov		[bp+PDLGVARS.ffnTask+2], es		; ...task function
+	mov		WORD [bp+MENUVARS.wTopDwnH], 0101h	; 1 title line, 1 info line
+	mov		WORD [bp+MENUVARS.fnEvent], MenuProg_Event
+
+	; Enter menu
+	call	MenuCrsr_GetCenter				; Get X and Y coordinates to DX
+	xor		cx, cx							; No menuitems
+	xor		bx, bx							; Menu flags
+	xor		ax, ax							; Selection timeout (disable)
+	call	Menu_Init						; Returns only after dlg closed
+
+	; Return
+	mov		ax, [bp+PDLGVARS.wRetUser]		; Load user return variable
+	add		bp, PDLGVARS_size				; Point to old BP
+	eLEAVE									; Destroy stack frame
+	ret
+
+
+;-------------- Private functions ---------------------
+
+;--------------------------------------------------------------------
+; Draws progress bar.
+;
+; MenuProg_DrawBar
+;	Parameters:
+;		AX:		Completion percentage (0...100)
+;		SS:BP:	Ptr to PDLGVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuProg_DrawBar:
+	; Calculate number of chars to draw
+	eMOVZX	cx, BYTE [bp+MENUVARS.bWidth]	; Dialog width to CX
+	sub		cl, 4							; Sub borders, CX=bar width
+	mul		cl								; AX=bar with * percentage
+	mov		bx, 100							; Prepare to div by 100
+	div		bl								; AL=Full char cnt
+	sub		cl, al							; CX=Empty char cnt
+	mov		bl, al							; BX=full char cnt
+	
+	; Draw full chars
+	mov		dl, FULL_BLCK					; Load full block char
+	xchg	bx, cx							; CX=full chars, BX=empty chars
+	call	Print_Repeat					; Repeat chars
+	mov		dl, MIN_BLCK					; Load min block char
+	mov		cx, bx							; CX=empty chars
+	call	Print_Repeat					; Repeat chars
+	ret
+
+
+;--------------------------------------------------------------------
+; File dialog event handler.
+;
+; MenuProg_Event
+;	Parameters:
+;		BX:		Callback event
+;		CX:		Selected menuitem index
+;		DX:		Event parameter (event specific)
+;		SS:BP:	Ptr to PDLGVARS
+;	Returns:
+;		AH:		Event specific or unused
+;		AL:		1=Event processed
+;				0=Event not processed (default action if any)
+;	Corrupts registers:
+;		BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuProg_Event:
+	cmp		bx, EVNT_MNU_UPD		; Update menu string?
+	je		.EventUpd				;  If so, jump to update
+	xor		ax, ax					; Event not processed
+	ret
+
+ALIGN JUMP_ALIGN
+.EventHandled:	; Return point from all handled events
+	mov		ax, 1
+	ret
+
+;--------------------------------------------------------------------
+; EVNT_MNU_UPD event handler.
+;
+; .EventUpd
+;	Parameters:
+;		CX:		Index of menuitem to update (MFL_UPD_ITEM only)
+;		DL:		Update flag:
+;					MFL_UPD_TITLE	Set to update title string
+;					MFL_UPD_NFO		Set to update info string
+;					MFL_UPD_ITEM	Set to update menuitem string
+;		SS:BP:	Ptr to PDLGVARS
+;	Returns:
+;		AX:		1 (Event processed)
+;	Corrupts registers:
+;		BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.EventUpd:
+	test	dl, MFL_UPD_NFO		; Update info?
+	jz		.EventHandled		;  If not, do nothing and return
+
+	; Start task
+	push	ds
+	push	si
+	mov		si, [bp+PDLGVARS.fpUser]	; Load offset to user ptr
+	mov		ds, [bp+PDLGVARS.fpUser+2]	; Load segment to user ptr
+	xor		ax, ax						; Zero percent
+ALIGN JUMP_ALIGN
+.TaskLoop:
+	push	ax
+	call	MenuCrsr_PointInfo			; Point cursor to info string
+	pop		ax
+	call	MenuProg_DrawBar			; Draw progress bar
+	call	MenuCrsr_PointTitle			; Point cursor to title string
+	call	far [bp+PDLGVARS.ffnTask]	; Call task function
+	jnc		.TaskLoop					; Loop until task complete
+
+	; Task complete
+	mov		[bp+PDLGVARS.wRetUser], ax	; Store user return value
+	pop		si
+	pop		ds
+	jmp		MenuDlg_ExitHandler			; Close progress bar
Index: /tags/Configurator_v1.1.0/Src/Libraries/menu/prntvram.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Libraries/menu/prntvram.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Libraries/menu/prntvram.asm	(revision 6)
@@ -0,0 +1,222 @@
+; File name		:	prntvram.asm
+; Project name	:	Print library
+; Created date	:	7.12.2009
+; Last update	:	7.12.2009
+; Author		:	Tomi Tilli
+; Description	:	ASM library to for character and string
+;					printing using direct access to VRAM.
+;
+;					NOT WORKING!!!
+
+;--------------- Equates -----------------------------
+
+%include "BDA.inc"						; For BDA variables
+
+; Int 10h (BIOS) functions
+FN_BIOS_WR_CHAR_TEL	EQU		0Eh			; Teletype Output
+
+; Color adapter or Mono adapter segments
+SEG_COLOR			EQU		0B800h		; CGA+
+SEG_MONO			EQU		0B000h		; MDA, Hercules
+
+
+;-------------- Public functions ---------------------
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Return pointer to VRAM for current cursor position.
+; 
+; PrntVram_GetPtr
+;	Parameters:
+;		Nothing
+;	Returns:
+;		ES:DI:	Pointer to cursor location
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+PrntVram_GetPtr:
+	push	dx
+	xor		ax, ax							; Zero AX
+	mov		es, ax							; Copy zero to ES (BDA segment)
+
+	; Calculate offset to VRAM
+	eMOVZX	di, BYTE [es:BDA.bVidPageIdx]	; Load page index
+	shl		di, 1							; Shift for word lookup
+	mov		ax, [es:di+BDA.rgwVidCurPos]	; Load cursor position
+	shl		ax, 1							; Cursor offsets to WORD offsets
+	eMOVZX	di, al							; Copy X offset to DI
+	mov		al, ah							; Y offset to AL
+	xor		ah, ah							; Y offset to AX
+	mul		WORD [es:BDA.wVidColumns]		; DX:AX = Y offset * Column cnt
+	add		di, [es:BDA.wVidPageOff]		; Add page offset to DI
+	add		di, ax							; Add row offset to DI
+
+	; Get segment to VRAM
+	mov		ax, SEG_COLOR					; Assume CGA+
+	cmp		BYTE [es:BDA.bVidMode], 7		; MDA or Hercules?
+	jne		.Return							;  If not, return
+	mov		ax, SEG_MONO
+ALIGN JUMP_ALIGN
+.Return:
+	mov		es, ax
+	pop		dx
+	ret
+
+
+;--------------------------------------------------------------------
+; Prints character. All character printing functions must
+; use this macro to print characters (so printing implementation
+; can be easily modified when needed).
+; 
+; PRINT_CHAR
+;	Parameters:
+;		DL:		Character to print
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+%macro PRINT_CHAR 0
+	call	PrntVram_TeleChar
+%endmacro
+
+ALIGN JUMP_ALIGN
+PrntVram_TeleChar:
+	cmp		dl, 20h					; Printable char?
+	jb		.Bios					;  If not, use BIOS functions
+	push	es
+	push	di
+	call	PrntVram_GetPtr			; VRAM pointer to ES:DI
+	mov		[es:di], dl				; Store character
+	call	PtnrVram_IncCursor		; Increment cursor position
+	pop		di
+	pop		es
+	ret
+ALIGN JUMP_ALIGN
+.Bios:
+	push	bp						; Save because of buggy BIOSes
+	push	bx
+	mov		ah, FN_BIOS_WR_CHAR_TEL
+	mov		al, dl					; Copy char to write
+	xor		bx, bx					; Page 0
+	int		10h
+	pop		bx
+	pop		bp
+	ret
+
+ALIGN JUMP_ALIGN
+PtnrVram_IncCursor:
+	push	es
+	xor		ax, ax					; Zero AX
+	mov		es, ax					; Copy zero to ES (BDA segment)
+	mov		al, [es:BDA.rgwVidCurPos]
+	inc		ax
+	cmp		al, [es:BDA.wVidColumns]
+	pop		es
+	je		.IncRow
+	
+	; Inc column only
+	push	dx
+	push	cx
+	push	bx
+	mov		cx, 1
+	call	MenuCrsr_Move
+	pop		bx
+	pop		cx
+	pop		dx
+	ret
+ALIGN JUMP_ALIGN
+.IncRow:
+	push	dx
+	push	cx
+	push	bx
+	call	MenuCrsr_GetCursor
+	xor		dl, dl
+	inc		dh
+	call	MenuCrsr_SetCursor
+	pop		bx
+	pop		cx
+	pop		dx
+	ret
+
+
+;--------------------------------------------------------------------
+; Prints string. All string printing functions must
+; use this macro to print strings (so printing implementation
+; can be easily modified when needed).
+; 
+; PRINT_STR
+;	Parameters:
+;		DS:DX:		Ptr to STOP terminated string
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+%macro PRINT_STR 0
+	push	dx
+	call	Print_VramTeleStr
+	pop		dx
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Prints string and returns number of characters printed.
+; All string printing functions must use this macro to print strings
+; (so printing implementation can be easily modified when needed).
+; 
+; PRINT_STR_LEN
+;	Parameters:
+;		DS:DX:		Ptr to STOP terminated string
+;	Returns:
+;		DX:			Number of characters printed
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+%macro PRINT_STR_LEN 0
+	call	Print_VramTeleStr
+%endmacro
+
+ALIGN JUMP_ALIGN
+Print_VramTeleStr:
+	push	es
+	push	di
+	push	si
+	call	PrntVram_GetPtr			; VRAM pointer to ES:DI
+	mov		si, dx					; Copy offset to string
+	xor		dx, dx					; Zero char counter
+	cld								; STOSB to increment SI and DI
+ALIGN JUMP_ALIGN
+.CharLoop:
+	lodsb							; Load char from [DS:SI] to AL
+	cmp		al, 20h					; Printable character?
+	jb		.Bios					;  If not, use BIOS functions
+	
+	push	dx
+	mov		al, dl
+	PRINT_CHAR
+	pop		dx
+	
+	;stosb							; Store char to [ES:DI]
+	inc		dx						; Increment chars printed
+	;inc		di						; Skip attribute
+	jmp		.CharLoop				; Loop while chars left
+ALIGN JUMP_ALIGN
+.Return:
+	pop		si
+	pop		di
+	pop		es
+	ret
+ALIGN JUMP_ALIGN
+.Bios:
+	cmp		al, STOP				; End of string?
+	je		.Return					;  If so, return
+	push	dx
+	mov		dl, al
+	PRINT_CHAR
+	pop		dx
+	times 2 inc di
+	inc		dx						; Increment chars printed
+	jmp		.CharLoop				; Loop while chars left
Index: /tags/Configurator_v1.1.0/Src/Libraries/print.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Libraries/print.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Libraries/print.asm	(revision 6)
@@ -0,0 +1,709 @@
+; File name		:	print.asm
+; Project name	:	Print library
+; Created date	:	6.10.2009
+; Last update	:	31.12.2009
+; Author		:	Tomi Tilli
+; Description	:	ASM library to for character and string
+;					printing related functions.
+
+;--------------- Equates -----------------------------
+
+; String library function to include
+%define USE_PRINT_FORMAT			; Print_Format
+%define USE_PRINT_NEWLINE			; Print_Newline
+%define USE_PRINT_CHARBUFFER		; Print_CharBuffer
+%define USE_PRINT_REPEAT			; Print_Repeat
+;%define USE_PRINT_BOOL				; Print_Bool
+;%define USE_PRINT_INTSW			; Print_IntSW
+%define USE_PRINT_INTUW				; Print_IntUW
+;%define USE_PRINT_INTUDW			; Print_IntUDW
+%define USE_PRINT_INTHEXB			; Print_IntHexB
+%define USE_PRINT_INTHEXW			; Print_IntHexW
+;%define USE_PRINT_INTHEXDW			; Print_IntHexDW
+
+
+; Text mode character attribute byte bits for CGA+
+FLG_CGA_FG_B		EQU		(1<<0)
+FLG_CGA_FG_G		EQU		(1<<1)
+FLG_CGA_FG_R		EQU		(1<<2)
+FLG_CGA_FG_I		EQU		(1<<3)
+FLG_CGA_BG_B		EQU		(1<<4)
+FLG_CGA_BG_G		EQU		(1<<5)
+FLG_CGA_BG_R		EQU		(1<<6)
+FLG_CGA_BG_I		EQU		(1<<7)
+FLG_CGA_BG_BLNK		EQU		(1<<7)	; Blinking is default
+
+; Text mode character attribute bytes for MDA/Hercules (mono)
+; *Not displayed on some monitors
+ATTR_MDA_HIDDEN		EQU		00h	; Not displayed
+ATTR_MDA_ULINE		EQU		01h	; Underlined
+ATTR_MDA_NORMAL		EQU		07h	; Normal (white on black)
+ATTR_MDA_INT_U		EQU		09h	; High intensity, underlined
+ATTR_MDA_INT		EQU		0Fh	; High intensity
+ATTR_MDA_REVERSE	EQU		70h	; Reverse video (black on white)
+ATTR_MDA_BLNK		EQU		87h	; Blinking white on black*
+ATTR_MDA_BLNK_INT	EQU		8Fh	; Blinking high intensity*
+ATTR_MDA_BLNK_REV	EQU		0F0h; Blinking reverse video
+
+
+;-------------- Private global variables -------------
+; Section containing initialized data
+;SECTION .data
+
+g_rgbHex:		db	"0123456789ABCDEF"	; Hexadecimal printing
+g_rgbFormat:	; Placeholders for Print_Format
+%ifdef USE_PRINT_INTSW
+				db	'd'	; Prints signed 16-bit integer (WORD)
+%endif
+%ifdef USE_PRINT_INTUW
+				db	'u'	; Prints unsigned 16-bit integer (WORD)
+%endif
+%ifdef USE_PRINT_INTUDW
+				db	'U'	; Prints unsigned 32-bit integer (DWORD)
+%endif
+%ifdef USE_PRINT_INTHEXW
+				db	'x'	; Prints 8- or 16-bit hexadecimal (BYTE, WORD)
+%endif
+%ifdef USE_PRINT_INTHEXDW
+				db	'X'	; Prints 32-bit hexadecimal (DWORD)
+%endif
+				db	's'	; Prints string (DS segment)
+				db	'S'	; Prints string (far pointer)
+%ifdef USE_PRINT_BOOL
+				db	'b'	; Prints boolean value 0 or 1
+%endif
+				db	'c'	; Prints character
+				db	'C'	; Prints character number of times
+_g_rgbFormatEnd:
+
+; Number of different placeholders for Print_Format
+CNT_PLCEHLDRS		EQU		(_g_rgbFormatEnd-g_rgbFormat)
+
+
+
+;-------------- Public functions ---------------------
+; Section containing code
+SECTION .text
+
+; Include one file to use DOS, BIOS or VRAM macros and functions
+;%include "prntdos.asm"			; Include to use DOS printing functions
+%include "prntbios.asm"			; Include to use BIOS printing functions
+;%include "prntvram.asm"			; Include to access VRAM directly
+
+
+;--------------------------------------------------------------------
+; Debugging macro that prints wanted character and newline.
+; 
+; PRINT_DBG_CH
+;	Parameters:
+;		%1:		Character to print
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro PRINT_DBG_CH 1
+	pushf
+	push	dx
+	push	ax
+	mov		dl, %1
+	PRINT_CHAR
+	mov		dl, CR
+	PRINT_CHAR
+	mov		dl, LF
+	PRINT_CHAR
+	pop		ax
+	pop		dx
+	popf
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Simplified printf-style string formatting function.
+; Strings must end to STOP character.
+; Supports following formatting types:
+;	%d		Prints signed 16-bit integer (WORD)
+;	%u		Prints unsigned 16-bit integer (WORD)
+;	%U		Prints unsigned 32-bit integer (DWORD)
+;	%x		Prints 8- or 16-bit hexadecimal (BYTE, WORD)
+;	%X		Prints 32-bit hexadecimal (DWORD)
+;	%s		Prints string (DS segment)
+;	%S		Prints string (far pointer)
+;	%b		Prints boolean value 0 or 1
+;	%c		Prints character
+;	%[num]C	Prints character number of times (up to 256, 0=256)
+;	%%		Prints '%' character (no parameter pushed)
+;
+;	Any placeholder can be set to minimum length by specifying
+;	minimum number of characters. For example %8d would append spaces
+;	after integer so that at least 8 characters would be printed.
+;
+;	NOTE! Caller must clean the stack variables!
+; 
+; Print_Format
+;	Parameters:
+;		DL:			Min length character (usually space)
+;		DS:SI:		Pointer to string to format
+;		Stack:		Parameters for formatting placeholders.
+;					Parameter for first placeholder must be pushed last
+;					(to top of stack).
+;					High word must be pushed first for 32-bit parameters.
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, SI
+;--------------------------------------------------------------------
+%ifdef USE_PRINT_FORMAT
+ALIGN JUMP_ALIGN
+Print_Format:
+	push	es
+	push	bp
+	push	di
+	push	cx
+	push	dx					; Push min length character
+	push	cs					; Copy CS...
+	pop		es					; ...to ES
+	mov		bp, sp				; Copy SP to BP
+	add		bp, 2*6				; Set BP to point first stack parameter
+	cld							; Set LODSB to increment SI
+ALIGN JUMP_ALIGN
+.PrintLoop:			; Load characters from string
+	lodsb						; Load char from DS:SI to AL, increment SI
+	xor		cx, cx				; Zero minimum length
+	cmp		al, STOP			; End of string?
+	je		.Return				;  If so, return
+	cmp		al, '%'				; Format placeholder?
+	je		.Format				;  If so, jump to format
+ALIGN JUMP_ALIGN
+.PrintChar:			; Prints single character from AL
+	mov		dl, al				; Copy character to DL
+	PRINT_CHAR					; Print character
+	mov		dx, 1				; One char printed
+ALIGN JUMP_ALIGN
+.PrintXtraSoMin:	; Checks how many spaces to append
+	sub		cx, dx				; Number of spaces needed
+	jle		.PrintLoop			; Read next character if no spaces needed
+	pop		dx					; Pop min length character to DL
+ALIGN JUMP_ALIGN
+.PrintSpaceLoop:	; Loop to print the required spaces
+	PRINT_CHAR
+	loop	.PrintSpaceLoop
+	push	dx					; Store min length character
+	jmp		.PrintLoop			; Jump to read next character
+ALIGN JUMP_ALIGN
+.Return:			; The only return point for this function
+	pop		dx
+	pop		cx
+	pop		di
+	pop		bp
+	pop		es
+	ret
+ALIGN JUMP_ALIGN
+.UpdateMinLen:		; Updates placeholder minimum length
+	mov		al, ah				; Copy digit to AL
+	mov		ah, cl				; Copy previous length to AH
+	aad							; AL=10*AH+AL, AH=0
+	mov		cx, ax				; Copy new length to CX
+ALIGN JUMP_ALIGN
+.Format:
+	lodsb						; Load char from DS:SI to AL, increment SI
+	cmp		al, STOP
+	je		.Return				; Invalid string
+	mov		ah, al				; Copy char to AH
+	sub		ah, '0'				; Possible digit char to digit
+	cmp		ah, 9				; Was valid digit?
+	jbe		.UpdateMinLen		;  If so, jump to update minimum length
+	push	cx					; Store number of spaces needed
+	mov		cx, CNT_PLCEHLDRS	; Load number of placeholders to CX
+	mov		di, g_rgbFormat		; Load offset to format placeholder table
+	repne scasb					; Compare AL to [ES:DI] until match
+	pop		cx					; Restore spaces needed
+	jne		.PrintChar			; If no match, jump to print character
+	sub		di, g_rgbFormat+1	; To placeholder index
+	shl		di, 1				; Shift for word lookup
+	jmp		[cs:di+.g_rgwFormJump]	; Jump to format
+
+%ifdef USE_PRINT_INTSW
+ALIGN JUMP_ALIGN
+.Print_d:	; Print signed 16-bit integer
+	mov		ax, [bp]			; Load word to print
+	times 2 inc	bp
+	call	Print_IntSW
+	jmp		.PrintXtraSoMin
+%endif
+%ifdef USE_PRINT_INTUW
+ALIGN JUMP_ALIGN
+.Print_u:	; Print unsigned 16-bit integer
+	mov		ax, [bp]			; Load word to print
+	times 2 inc	bp
+	call	Print_IntUW
+	jmp		.PrintXtraSoMin
+%endif
+%ifdef USE_PRINT_INTUDW
+ALIGN JUMP_ALIGN
+.Print_U:	; Print unsigned 32-bit integer
+	mov		ax, [bp]			; Load loword
+	mov		dx, [bp+2]			; Load hiword
+	add		bp, 4
+	call	Print_IntUDW
+	jmp		.PrintXtraSoMin
+%endif
+%ifdef USE_PRINT_INTHEXW
+ALIGN JUMP_ALIGN
+.Print_x:	; Prints 8- or 16-bit hexadecimal
+	mov		ax, [bp]			; Load word to print
+	times 2 inc	bp
+%ifdef USE_PRINT_INTHEXB
+	test	ah, ah				; 16-bit hexadecimal?
+	jnz		.Print_x16			;  If so, jump to print it
+	call	Print_IntHexB
+	jmp		.PrintXtraSoMin
+.Print_x16:
+%endif
+	call	Print_IntHexW
+	jmp		.PrintXtraSoMin
+%endif
+%ifdef USE_PRINT_INTHEXDW
+ALIGN JUMP_ALIGN
+.Print_X:	; Prints 32-bit hexadecimal
+	mov		ax, [bp]			; Load loword
+	mov		dx, [bp+2]			; Load hiword
+	add		bp, 4
+	call	Print_IntHexDW
+	jmp		.PrintXtraSoMin
+%endif
+ALIGN JUMP_ALIGN
+.Print_s:	; Prints string from DS segment
+	mov		dx, [bp]			; Load offset to string
+	times 2 inc	bp
+	PRINT_STR_LEN				; Print string
+	jmp		.PrintXtraSoMin
+ALIGN JUMP_ALIGN
+.Print_S:	; Prints string using far pointer
+	push	ds					; Store DS
+	mov		dx, [bp]			; Load offset to string
+	mov		ds, [bp+2]			; Load segment to string
+	add		bp, 4
+	PRINT_STR_LEN				; Print string
+	pop		ds					; Restore DS
+	jmp		.PrintXtraSoMin
+%ifdef USE_PRINT_BOOL
+ALIGN JUMP_ALIGN
+.Print_b:	; Prints boolean value
+	mov		ax, [bp]			; Load boolean value to print
+	times 2 inc	bp
+	call	Print_Bool
+	jmp		.PrintXtraSoMin
+%endif
+ALIGN JUMP_ALIGN
+.Print_c:	; Prints character
+	mov		ax, [bp]			; Load character to print
+	times 2 inc	bp
+	jmp		.PrintChar			; Jump to print character
+ALIGN JUMP_ALIGN
+.Print_C:
+	mov		dx, [bp]			; Load character to print
+	times 2 inc	bp
+ALIGN JUMP_ALIGN
+.CharLoop:
+	PRINT_CHAR
+	loop	.CharLoop
+	jmp		.PrintLoop
+
+ALIGN JUMP_ALIGN
+.g_rgwFormJump:					; Jump table for Print_Format
+%ifdef USE_PRINT_INTSW
+	dw		.Print_d
+%endif
+%ifdef USE_PRINT_INTUW
+	dw		.Print_u
+%endif
+%ifdef USE_PRINT_INTUDW
+	dw		.Print_U
+%endif
+%ifdef USE_PRINT_INTHEXW
+	dw		.Print_x
+%endif
+%ifdef USE_PRINT_INTHEXDW
+	dw		.Print_X
+%endif
+	dw		.Print_s
+	dw		.Print_S
+%ifdef USE_PRINT_BOOL
+	dw		.Print_b
+%endif
+	dw		.Print_c
+	dw		.Print_C
+%endif
+
+
+;--------------------------------------------------------------------
+; Prints newline character to change line.
+; 
+; Print_Newline
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%ifdef USE_PRINT_NEWLINE
+ALIGN JUMP_ALIGN
+Print_Newline:
+	push	ax
+	push	dx
+	mov		dl, LF
+	PRINT_CHAR
+	mov		dl, CR
+	PRINT_CHAR
+	pop		dx
+	pop		ax
+	ret
+%endif
+	
+
+;--------------------------------------------------------------------
+; Prints wanted number of characters.
+; 
+; Print_CharBuffer
+;	Parameters:
+;		CX:		Number of characters to print
+;		ES:DI:	Ptr to character buffer
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX
+;--------------------------------------------------------------------
+%ifdef USE_PRINT_CHARBUFFER
+ALIGN JUMP_ALIGN
+Print_CharBuffer:
+	jcxz	.Return
+	push	ds
+	push	si
+	push	dx
+	push	es
+	pop		ds
+	mov		si, di
+	cld							; LODSB to increment SI
+ALIGN JUMP_ALIGN
+.Rep:
+	lodsb						; Load from [DS:SI] to AL
+	mov		dl, al				; Copy to DL for printing
+	PRINT_CHAR
+	loop	.Rep
+	pop		dx
+	pop		si
+	pop		ds
+.Return:
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Repeats wanted character.
+; 
+; Print_Repeat
+;	Parameters:
+;		CX:		Number of times to repeat character
+;		DL:		Character to repeat
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX
+;--------------------------------------------------------------------
+%ifdef USE_PRINT_REPEAT
+ALIGN JUMP_ALIGN
+Print_Repeat:
+	jcxz	.Return
+ALIGN JUMP_ALIGN
+.Rep:
+	PRINT_CHAR
+	loop	.Rep
+.Return:
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Prints boolean value.
+; 
+; Print_Bool
+;	Parameters:
+;		AX:		Boolean value (0=FALSE, non-zero=TRUE)
+;	Returns:
+;		DX:		Number of characters printed
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+%ifdef USE_PRINT_BOOL
+ALIGN JUMP_ALIGN
+Print_Bool:
+	mov		dl, '0'				; Assume FALSE
+	test	ax, ax				; Is FALSE?
+	jz		.Print				;  If so, jump to print
+	inc		dx					; Increment to '1'
+ALIGN JUMP_ALIGN
+.Print:
+	PRINT_CHAR
+	mov		dx, 1				; One character printed
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Prints signed or unsigned 16-bit integer.
+; 
+; Print_IntSW	Prints signed 16-bit word
+; Print_IntUW	Prints unsigned 16-bit word
+;	Parameters:
+;		AX:		Word to print
+;	Returns:
+;		DX:		Number of characters printed
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+%ifdef USE_PRINT_INTSW
+ALIGN JUMP_ALIGN
+Print_IntSW:
+	push	di					; Store DI
+	cmp		ax, 0				; Positive integer?
+	jge		Print_IntUW			;  If so, jump to print it
+	push	ax					; Store word
+	mov		dl, '-'				; Print '-'
+	PRINT_CHAR
+	mov		di, 1				; One character printed
+	pop		ax					; Restore word
+	neg		ax					; Negative to positive
+	jmp		Print_ContinueFromIntSW
+%endif
+
+%ifdef USE_PRINT_INTUW or USE_PRINT_INTSW
+ALIGN JUMP_ALIGN
+Print_IntUW:
+	push	di					; Store DI
+	xor		di, di				; Zero character counter
+Print_ContinueFromIntSW:
+	push	bx					; Store BX
+	push	cx					; Store CX
+	mov		bx, 10				; Load divisor to BX
+	mov		cx, 5				; Load number of divisions to CX
+ALIGN JUMP_ALIGN
+.DivLoop:
+	xor		dx, dx				; Zero DX for division
+	div		bx					; DX:AX / 10 => AX=quot, DX=rem
+	push	dx					; Push digit
+	loop	.DivLoop			; Loop to separate all characters
+	xor		bx, bx				; First char printed flag
+	mov		cl, 5				; Load number of characters to CL
+ALIGN JUMP_ALIGN
+.PrintLoop:
+	pop		dx					; Pop character to DX
+	or		bx, dx				; Still skipping zeroes?
+	loopz	.PrintLoop			;  If so, loop
+	add		dx, '0'				; Digit to character
+	PRINT_CHAR					; Print character
+	inc		di					; Increment chars printed
+	test	cx, cx				; Characters left
+	jnz		.PrintLoop			;  If so, loop
+	mov		dx, di				; Copy chars printed to DX
+	pop		cx
+	pop		bx
+	pop		di
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Prints unsigned 32-bit integer.
+; 
+; Print_IntUDW
+;	Parameters:
+;		DX:AX:	32-bit unsigned integer to print
+;	Returns:
+;		DX:		Number of characters printed
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+%ifdef USE_PRINT_INTUDW
+ALIGN JUMP_ALIGN
+Print_IntUDW:
+	push	di					; Store DI
+	push	si					; Store SI
+	push	bx					; Store BX
+	push	cx					; Store CX
+	mov		cx, 10				; Load divider to CX
+	mov		si, cx				; Load number of divisions (10) to SI
+	xor		di, di				; Zero DI (char counter)
+ALIGN JUMP_ALIGN
+.DivLoop:
+	call	Math_DivDWbyW		; DX:AX / 10 => DX:AX=quot, BX=rem
+	push	bx					; Push digit
+	dec		si					; Decrement number of divisions
+	jnz		.DivLoop			;  Loop while divisions left
+	xor		bx, bx				; First char printed flag
+ALIGN JUMP_ALIGN
+.PrintLoop:
+	pop		dx					; Pop character to DX
+	or		bx, dx				; Still skipping zeroes?
+	loopz	.PrintLoop			;  If so, loop
+	add		dx, '0'				; Digit to character
+	PRINT_CHAR					; Print character
+	inc		di					; Increment chars printed
+	test	cx, cx				; Characters left
+	jnz		.PrintLoop			;  If so, loop
+	mov		dx, di				; Copy characters printed to DX
+	pop		cx
+	pop		bx
+	pop		si
+	pop		di
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Prints 8-bit byte as hexadecimal string.
+; 
+; Print_IntHexB
+;	Parameters:
+;		AL:		8-bit BYTE to print
+;	Returns:
+;		DX:		Number of characters printed
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+%ifdef USE_PRINT_INTHEXB
+ALIGN JUMP_ALIGN
+Print_IntHexB:
+	push	bx
+	xor		ah, ah				; Zero AH, AX=word to print
+	mov		bx, 0FFh			; Set to print two digits
+	call	Print_HexString		; Print hex string
+	push	dx					; Store number of chars printed
+	mov		dl, 'h'				; Print 'h' at the end
+	PRINT_CHAR
+	pop		dx					; Restore number of chars printed
+	inc		dx					; Increment for 'h'
+	pop		bx
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Prints 16-bit word as hexadecimal string.
+; 
+; Print_IntHexW
+;	Parameters:
+;		AX:		16-bit WORD to print
+;	Returns:
+;		DX:		Number of characters printed
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+%ifdef USE_PRINT_INTHEXW
+ALIGN JUMP_ALIGN
+Print_IntHexW:
+	push	bx
+	xor		bx, bx				; Set to print all zeroes...
+	dec		bx					; ...BX = FFFFh
+	call	Print_HexString		; Print hex string
+	push	dx					; Store number of chars printed
+	mov		dl, 'h'				; Print 'h' at the end
+	PRINT_CHAR
+	pop		dx					; Restore number of chars printed
+	inc		dx					; Increment for 'h'
+	pop		bx
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Prints 32-bit dword as hexadecimal string.
+; 
+; Print_IntHexDW
+;	Parameters:
+;		DX:AX:	32-bit DWORD to print
+;	Returns:
+;		DX:		Number of characters printed
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+%ifdef USE_PRINT_INTHEXDW
+ALIGN JUMP_ALIGN
+Print_IntHexDW:
+	push	cx
+	push	bx
+	push	ax					; Store loword
+	mov		ax, dx				; Copy hiword to AX
+	xor		bx, bx				; Set to print all zeroes...
+	dec		bx					; ...BX = FFFFh
+	call	Print_HexString		; Print hex string
+	mov		cx, dx				; Copy number of chars printed
+	pop		ax					; Pop loword
+	call	Print_HexString		; Print hex string
+	add		cx, dx				; Add number of chars printed
+	mov		dl, 'h'				; Print 'h' at the end
+	PRINT_CHAR
+	inc		cx					; Increment number of chars printed
+	mov		dx, cx				; Copy number of chars printed to DX
+	pop		bx
+	pop		cx
+	ret
+%endif
+
+
+;-------------- Private functions --------------------
+
+;--------------------------------------------------------------------
+; Prints hexadecimal character for every nybble for WORD.
+; 
+; Print_HexString
+;	Parameters:
+;		AX:		16-bit WORD to print
+;		BX:		Mask for zero nybbles to print:
+;				FFFFh	= prints all digits
+;				0FFFh	= does not print digit 3 if it is zero
+;				00FFh	= does not print digits 3 and 2 if both are zeroes
+;				000Fh	= prints only digit 0 if other are zeroes
+;				0000h	= prints nothing if value is zero
+;	Returns:
+;		DX:		Number of characters printed
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+%ifdef USE_PRINT_INTHEXB or USE_PRINT_INTHEXW or USE_PRINT_INTHEXDW
+ALIGN JUMP_ALIGN
+Print_HexString:
+	push	bp
+	push	di
+	push	si
+	push	cx
+
+	mov		di, ax				; Backup WORD to DI
+	mov		cl, 12				; Prepare to shift nybbles
+	xor		dx, dx				; Zero DX
+ALIGN JUMP_ALIGN
+.NybbleLoop:
+	mov		bp, bx				; Copy mask to BP
+	mov		si, di				; Copy WORD to SI
+	shr		bp, cl				; Shift wanted mask nybble to BP
+	shr		si, cl				; Shift wanted nybble to SI
+	and		bp, 0Fh				; Clear unwanted mask bits
+	and		si, 0Fh				; Clear unwanted bits
+	or		bp, si				; Skip zeroes in front?
+	jz		.SkipPrint			;  If so, skip printing
+	mov		dl, [cs:si+g_rgbHex]; Load char to DL
+	PRINT_CHAR					; Print character
+	inc		dh					; Increment characters printed
+.SkipPrint:
+	sub		cl, 4				; Prepare to shift next nybble
+	jnc		.NybbleLoop			; Loop while nybbles left
+	mov		dl, dh				; Copy chars printed to DL
+	xor		dh, dh				; Zero DH
+
+	pop		cx
+	pop		si
+	pop		di
+	pop		bp
+	ret
+%endif
Index: /tags/Configurator_v1.1.0/Src/Libraries/prntbios.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Libraries/prntbios.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Libraries/prntbios.asm	(revision 6)
@@ -0,0 +1,109 @@
+; File name		:	prntbios.asm
+; Project name	:	Print library
+; Created date	:	7.12.2009
+; Last update	:	17.1.2010
+; Author		:	Tomi Tilli
+; Description	:	ASM library to for character and string
+;					printing using BIOS.
+
+;--------------- Equates -----------------------------
+
+; Int 10h (BIOS) functions
+FN_BIOS_WR_CHAR_TEL		EQU	0Eh	; Teletype Output
+
+
+;-------------- Public functions ---------------------
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Prints character. All character printing functions must
+; use this macro to print characters (so printing implementation
+; can be easily modified when needed).
+; 
+; PRINT_CHAR
+;	Parameters:
+;		DL:		Character to print
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+%macro PRINT_CHAR 0
+	call	Print_BiosTeleChar
+%endmacro
+
+ALIGN JUMP_ALIGN
+Print_BiosTeleChar:
+	push	bp					; Save because of buggy BIOSes
+	push	bx
+	mov		ah, FN_BIOS_WR_CHAR_TEL
+	mov		al, dl				; Copy char to write
+	xor		bx, bx				; Page 0
+	int		10h
+	pop		bx
+	pop		bp
+	ret
+
+
+;--------------------------------------------------------------------
+; Prints string. All string printing functions must
+; use this macro to print strings (so printing implementation
+; can be easily modified when needed).
+; 
+; PRINT_STR
+;	Parameters:
+;		DS:DX:		Ptr to STOP terminated string
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+%macro PRINT_STR 0
+	push	dx
+	call	Print_BiosTeleStr
+	pop		dx
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Prints string and returns number of characters printed.
+; All string printing functions must use this macro to print strings
+; (so printing implementation can be easily modified when needed).
+; 
+; PRINT_STR_LEN
+;	Parameters:
+;		DS:DX:		Ptr to STOP terminated string
+;	Returns:
+;		DX:			Number of characters printed
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+%macro PRINT_STR_LEN 0
+	call	Print_BiosTeleStr
+%endmacro
+
+ALIGN JUMP_ALIGN
+Print_BiosTeleStr:
+	push	bp						; Save because of buggy BIOSes
+	push	si
+	push	bx
+	mov		si, dx					; Copy offset to string
+	xor		dx, dx					; Zero char counter
+	xor		bx, bx					; Page 0
+	cld								; LODSB to increment SI
+ALIGN JUMP_ALIGN
+.CharLoop:
+	lodsb							; Load char from [DS:SI] to AL
+	cmp		al, STOP				; End of string?
+	je		.Return					;  If so, return
+	mov		ah, FN_BIOS_WR_CHAR_TEL	; Some BIOSes corrupt AH when returning
+	int		10h
+	inc		dx						; Increment chars printed
+	jmp		.CharLoop				; Loop while chars left
+ALIGN JUMP_ALIGN
+.Return:
+	pop		bx
+	pop		si
+	pop		bp
+	ret
Index: /tags/Configurator_v1.1.0/Src/Libraries/prntdos.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Libraries/prntdos.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Libraries/prntdos.asm	(revision 6)
@@ -0,0 +1,96 @@
+; File name		:	prntdos.asm
+; Project name	:	Print library
+; Created date	:	7.12.2009
+; Last update	:	7.12.2009
+; Author		:	Tomi Tilli
+; Description	:	ASM library to for character and string
+;					printing using DOS.
+
+;--------------- Equates -----------------------------
+
+; Int 21h (DOS) functions
+FN_DOS_WR_CHAR_STDOUT	EQU	02h	; Write Character to Standard Output
+FN_DOS_WR_STR_STDOUT	EQU	09h	; Write String to Standard Output
+
+
+;-------------- Public functions ---------------------
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Prints character. All character printing functions must
+; use this macro to print characters (so printing implementation
+; can be easily modified when needed).
+; 
+; PRINT_CHAR
+;	Parameters:
+;		DL:		Character to print
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+%macro PRINT_CHAR 0
+	mov		ah, FN_DOS_WR_CHAR_STDOUT
+	int		21h
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Prints string. All string printing functions must
+; use this macro to print strings (so printing implementation
+; can be easily modified when needed).
+; 
+; PRINT_STR
+;	Parameters:
+;		DS:DX:		Ptr to '$' terminated string
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+%macro PRINT_STR 0
+	mov		ah, FN_DOS_WR_STR_STDOUT
+	int		21h
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Prints string and returns number of characters printed.
+; All string printing functions must use this macro to print strings
+; (so printing implementation can be easily modified when needed).
+; 
+; PRINT_STR_LEN
+;	Parameters:
+;		DS:DX:		Ptr to STOP terminated string
+;	Returns:
+;		DX:			Number of characters printed
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+%macro PRINT_STR_LEN 0
+	call	Print_DosCharStr
+%endmacro
+
+ALIGN JUMP_ALIGN
+Print_DosCharStr:
+	push	si
+	push	cx
+	mov		si, dx				; Load offset to string
+	xor		cx, cx				; Zero character counter
+	cld							; LODSB to increment SI
+ALIGN JUMP_ALIGN
+.CharLoop:
+	lodsb						; Load from [DS:SI] to AL
+	cmp		al, STOP			; End of string?
+	je		.Return				;  If so, return
+	mov		dl, al				; Copy char to DL
+	PRINT_CHAR
+	inc		cx					; Increment characters printed
+	jmp		.CharLoop			; Loop while characters left
+ALIGN JUMP_ALIGN
+.Return:
+	mov		dx, cx				; Copy chars printed to DX
+	pop		cx
+	pop		si
+	ret
Index: /tags/Configurator_v1.1.0/Src/Libraries/string.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Libraries/string.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Libraries/string.asm	(revision 6)
@@ -0,0 +1,643 @@
+; File name		:	string.asm
+; Project name	:	String library
+; Created date	:	7.10.2009
+; Last update	:	26.11.2009
+; Author		:	Tomi Tilli
+; Description	:	ASM library to work as Standard C String and Character.
+
+;--------------- Equates -----------------------------
+
+; String library function to include
+%define USE_STR_ISCHAR
+%define USE_STR_ISBASECHAR
+%define USE_STR_BUFFHASCHAR
+;%define USE_STR_BUFFCMP
+%define USE_STR_TOUINT
+%define USE_STR_LEN
+%define USE_STR_TOKEN
+;%define USE_STR_WITHIN
+%define USE_STR_TOLOWER
+;%define USE_STR_TOUPPER
+
+; Special characters for strings
+STOP				EQU		0	; String ending character
+BELL				EQU		7	; Bell
+BS					EQU		8	; Backspace
+TAB					EQU		9	; Horizontal tab
+LF					EQU		10	; Line feed       \ Combine to...
+CR					EQU		13	; Carriage return / ...get a newline
+ESC					EQU		27	; ESC
+
+; Misc characters
+UARROW				EQU		24	; Up arrow
+DARROW				EQU		25	; Down arrow
+RARROW				EQU		26	; Right arrow
+LARROW				EQU		27	; Left arrow
+
+; Characters for printing boxes
+B_V					EQU		186	; Bold vertical border (Y-axis)
+B_H					EQU		205	; Bold horizontal border (X-axis)
+B_TL				EQU		201	; Bold top left border
+B_TR				EQU		187	; Bold top right border
+B_LR				EQU		188	; Bold lower right border
+B_LL				EQU		200	; Bold lower left border
+
+T_V					EQU		179	; Thin vertical border (Y-axis)
+T_H					EQU		196	; Thin horizontal border (X-axis)
+T_TL				EQU		218	; Thin top left border
+T_TR				EQU		191	; Thin top right border
+T_LR				EQU		217	; Thin lower right border
+T_LL				EQU		192	; Thin lower left border
+
+BVL_THR				EQU		199	; Bold vert on left, Thin horiz on right (||-)
+THL_BVR				EQU		182	; Thin horiz on left, Bold vert on right (-||)
+TVL_BHR				EQU		198	; Thin vert on left, Bold horiz on right (|=)
+BHL_TVR				EQU		181	; Bold horiz on left, Thin vert on right (=|)
+
+; Blocks
+MIN_BLCK			EQU		176	; Few character pixels set
+FULL_BLCK			EQU		219	; All character pixels set
+
+
+;-------------- Private global variables -------------
+; Section containing initialized data
+;SECTION .data
+
+
+;-------------- Public functions ---------------------
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Checks if character is some type of character.
+; 
+; String_IsAlphaNum (checks if alphanumeric letter, isalnum on C)
+; String_IsAlpha (checks if alphabetic letter, isalpha on C)
+; String_IsDigit (checks if decimal digit, isdigit on C)
+; String_IsLower (checks if lowercase letter, islower on C)
+; String_IsSpace (checks if any space character, isspace on C)
+; String_IsUpper (checks if uppercase letter, isupper on C)
+; String_IsHexDigit (checks if hexadecimal digit, isxdigit on C)
+;	Parameters:
+;		AL:		Character to check
+;	Returns:
+;		CF:		Set if character is the type to check
+;				Cleared if character is not the type to check
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%ifdef USE_STR_ISCHAR
+ALIGN JUMP_ALIGN
+String_IsAlphaNum:
+	call	String_IsAlpha		; Is alphabetic letter?
+	jnc		.CheckDigit			;  If not, jump to check if digit
+	ret
+.CheckDigit:
+	call	String_IsDigit		; Is dec digit?
+	ret
+
+ALIGN JUMP_ALIGN
+String_IsAlpha:
+	call	String_IsLower		; Is lower case letter?
+	jnc		.CheckUpper			;  If not, jump to check if upper
+	ret
+.CheckUpper:
+	call	String_IsUpper		; Is upper case letter?
+	ret
+
+ALIGN JUMP_ALIGN
+String_IsDigit:
+	cmp		al, '0'				; At least first dec digit?
+	jb		_String_IsRetFalse	;  If not, return FALSE
+	cmp		al, '9'+1			; At most last dec digit?
+	ret
+
+ALIGN JUMP_ALIGN
+String_IsLower:
+	cmp		al, 'a'				; At least first lower case letter?
+	jb		_String_IsRetFalse	;  If not, return FALSE
+	cmp		al, 'z'+1			; At most last lower case letter?
+	ret
+
+ALIGN JUMP_ALIGN
+String_IsSpace:
+	cmp		al, ' '+1			; Space or non-visible character?
+	ret
+
+ALIGN JUMP_ALIGN
+String_IsUpper:
+	cmp		al, 'A'				; At least first upper case letter?
+	jb		_String_IsRetFalse	;  If not, return FALSE
+	cmp		al, 'Z'+1			; At most last upper case letter?
+	ret
+
+ALIGN JUMP_ALIGN
+String_IsHexDigit:
+	call	String_IsAlphaNum	; Is alphabetic letter or digit?
+	jc		.CheckHex			;  If so, jump to check A...F
+	ret
+.CheckHex:
+	push	ax					; Store character
+	call	String_ToLower		; Convert to lower case letter
+	cmp		al, 'f'+1			; Last valid hex alphanumeric?
+	pop		ax					; Restore character
+	ret
+
+ALIGN JUMP_ALIGN
+_String_IsRetFalse:
+	clc							; Clear CF since false
+	ret
+%endif ; USE_STR_ISCHAR
+
+
+;--------------------------------------------------------------------
+; Checks if character belongs to specified numeric base.
+; 
+; String_IsBaseChar
+;	Parameters:
+;		AL:		Character to check
+;		CL:		Numeric base (10=dec, 16=hex etc.)
+;	Returns:
+;		AH:		Integer value for character
+;		CF:		Set if character belongs to base
+;				Set if character does not belong to base
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%ifdef USE_STR_ISBASECHAR
+ALIGN JUMP_ALIGN
+String_IsBaseChar:
+	mov		ah, al				; Copy char to AH
+	call	String_IsDigit		; Is '0'...'9'?
+	jc		.ConvertDigit		;  If so, jump to convert
+	call	String_IsAlpha		; Is alphabetic letter?
+	jnc		.RetFalse			;  If not, return FALSE
+	call	String_ToLower		; Convert to lower case
+	xchg	al, ah				; Converted char to AH
+	sub		ah, 'a'-10			; From char to integer: a=10, b=11...
+	cmp		ah, cl				; Belongs to base?
+	jae		.RetFalse			; If not, return FALSE
+	stc							; Set CF since belongs to base
+	ret
+ALIGN JUMP_ALIGN
+.ConvertDigit:
+	sub		ah, '0'				; Convert char to integer
+	cmp		ah, cl				; Belongs to base?
+	jae		.RetFalse			; If not, return FALSE
+	stc							; Set CF since belongs to base
+	ret
+ALIGN JUMP_ALIGN
+.RetFalse:
+	clc							; Clear CF since char doesn't belong to b
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Finds first occurrence of character from buffer (memchr on C).
+; 
+; String_BuffHasChar
+;	Parameters:
+;		AL:		Character to check
+;		CX:		Buffer length in bytes (1...65535, 0 clears CF)
+;		ES:DI:	Pointer to buffer
+;	Returns:
+;		AX:		Index of character in buffer (if char found)
+;		ES:BX:	Pointer to character location (if char found)
+;		CF:		Set if character found
+;				Cleared if character not found
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%ifdef USE_STR_BUFFHASCHAR
+ALIGN JUMP_ALIGN
+String_BuffHasChar:
+	jcxz	.Return				; Check length so no need to initialise ZF
+	push	di					; Store offset to buffer
+times 2 push	cx				; Store CX			
+	cld							; Set SCASB to increment DI
+	repne scasb					; Compare bytes to AL until found or CX=0
+	jne		.CharNotFound		; Character not found, return FALSE
+
+	; Character found
+	pop		ax					; Pop buffer length
+	sub		ax, cx				; Subtract number of chars left
+	dec		ax					; Number of chars scanned to found index
+	lea		bx, [di-1]			; Load character offset to BX
+	pop		cx					; Restore CX
+	pop		di					; Restore DI
+	stc							; Set CF since char found
+	ret
+.CharNotFound:
+times 2 pop	cx					; Restore CX
+	pop		di					; Restore DI
+.Return:
+	clc							; Clear CF since char not found
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Compares two buffers (memcmp on C).
+; 
+; String_BuffCmp
+;	Parameters:
+;		CX:		Buffer length in bytes (1...65535, 0 clears ZF)
+;		DS:SI:	Pointer to buffer 1
+;		ES:DI:	Pointer to buffer 2
+;	Returns:
+;		AX:		Index of unequal character (if buffers are not equal)
+;		ZF:		Set if buffers are equal
+;				Cleared if buffers are not equal
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%ifdef USE_STR_BUFFCMP
+ALIGN JUMP_ALIGN
+String_BuffCmp:
+	jcxz	.ReturnUnequal		; Check length so no need to initialise ZF
+	push	di					; Store offset to buffer 2
+	push	si					; Store offset to buffer 1
+times 2 push	cx				; Store CX			
+	cld							; Set CMPSB to increment SI and DI
+	repe cmpsb					; Compare bytes until not equal or CX=0
+	jne		.BuffersUnequal		; Unequal byte found, return FALSE
+	times 2 pop	cx				; Restore CX
+	pop		si					; Restore SI
+	pop		di					; Restore DI
+	ret
+.BuffersUnequal:
+	pop		ax					; Pop buffer length
+	sub		ax, cx				; Subtrack number of chars left
+	dec		ax					; Number of chars compared to unequal idx
+	xor		cx, cx				; Zero CX
+	dec		cx					; ZF=0
+	pop		cx					; Restore CX
+	pop		si					; Restore SI
+	pop		di					; Restore DI
+	ret
+.ReturnUnequal:
+	xor		ax, ax				; Zero AX
+	dec		ax					; AX = FFFFh, ZF=0
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Converts a string buffer to unsigned 32-bit integer.
+; 
+; String_BuffToUInt
+;	Parameters:
+;		ES:DI:	Pointer to string buffer to convert
+;		CX:		Base (10=dec, 16=hex etc.)
+;		SI:		Buffer length in characters
+;	Returns:
+;		DX:AX:	32-bit unsigned integer
+;		CF:		Set if converted successfully
+;				Cleared if error
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%ifdef USE_STR_TOUINT
+ALIGN JUMP_ALIGN
+String_BuffToUInt:
+	; Copy ES:DI to DS:SI
+	push	ds					; Store DS
+	push	si					; Store SI
+	push	di					; Store DI
+	push	bx					; Store BX
+	xchg	si, di				; Offset to SI, lenght to DI
+	push	es
+	pop		ds
+
+	; Prepare to read chars
+	xor		dx, dx				; Zero DX (HIWORD)
+	xor		bx, bx				; Zero BX (LOWORD)
+ALIGN JUMP_ALIGN
+.CharLoop:
+	lodsb						; Load char to AL
+	call	String_IsBaseChar	; Is valid character? (AH=digit)
+	jnc		.RetFalse			;  If not, return FALSE
+	xchg	ax, bx				; AX=LOWORD, BX=digit and char
+	call	Math_MulDWbyW		; DX:AX *= CX
+	xchg	ax, bx				; AX=digit and char, BX=LOWORD
+	mov		al, ah				; Copy digit to AL
+	xor		ah, ah				; Zero AH, AX=digit
+	add		bx, ax				; Add digit to LOWORD
+	adc		dx, 0				; Add carry to HIWORD
+	dec		di					; Decrement characters left
+	jnz		.CharLoop			; Loop while characters left
+
+	mov		ax, bx				; Copy loword to AX
+	pop		bx					; Restore BX
+	pop		di					; Restore DI
+	pop		si					; Restore SI
+	pop		ds					; Restore DS
+	stc							; Set CF since success
+	ret
+ALIGN JUMP_ALIGN
+.RetFalse:
+	mov		ax, bx				; Copy (likely incomplete) loword to AX
+	pop		bx					; Restore BX
+	pop		di					; Restore DI
+	pop		si					; Restore SI
+	pop		ds					; Restore DS
+	clc							; Clear CF since error
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Returns string lenght. Strings must end to STOP character (strlen on C).
+; 
+; String_StrLen
+;	Parameters:
+;		ES:DI:	Pointer to string
+;	Returns:
+;		AX:		String length in characters excluding STOP char
+;		CF:		Set if STOP character was found
+;				Cleared if STOP character was not found
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%ifdef USE_STR_LEN
+ALIGN JUMP_ALIGN
+String_StrLen:
+	push	cx					; Store CX
+	mov		al, STOP			; Load string end char to AL
+	mov		cx, -1				; Scan for maximum string length
+	call	String_BuffHasChar	; Find offset for string ending char
+	pop		cx					; Restore CX
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Returns length for token string. Token strings ends to any whitespace
+; character or to STOP.
+; 
+; String_TokenLen
+;	Parameters:
+;		ES:DI:	Pointer to token string
+;	Returns:
+;		AX:		Token length in characters
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%ifdef USE_STR_TOKEN
+ALIGN JUMP_ALIGN
+String_TokenLen:
+	push	bx					; Store BX
+	xor		bx, bx				; Zero BX for token length
+ALIGN JUMP_ALIGN
+.CharLoop:
+	mov		al, [es:di+bx]		; Load character to AL
+	cmp		al, STOP			; End of token?
+	je		.Return				;  If so, return
+	call	String_IsSpace		; End of token?
+	jc		.Return				;  If so, return
+	inc		bx					; Increment token length
+	jmp		.CharLoop			; Loop while characters left
+ALIGN JUMP_ALIGN
+.Return:
+	mov		ax, bx				; Copy string length to AX
+	pop		bx					; Restore BX
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Returns index and ptr to first occurrence of
+; string 2 in string 1 (strstr on C).
+; Strings must be STOP terminated strings.
+; 
+; String_StrWithin
+;	Parameters:
+;		DS:SI:	Pointer to string 1
+;		ES:DI:	Pointer to string 2
+;	Returns:
+;		AX:		Index to first occurrence of string 2 in string 1
+;		DS:BX:	Pointer to first occurrence of string 2 in string 1
+;		CF:		Set if string 2 was found in string 1
+;				Cleared if string 2 was not found
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%ifdef USE_STR_WITHIN
+ALIGN JUMP_ALIGN
+String_StrWithin:
+	push	cx					; Store CX
+	push	si					; Store SI
+	call	String_StrLen		; Load str2 length to AX
+	mov		cx, ax				; Copy str2 length to CX
+
+ALIGN JUMP_ALIGN
+.Str1CharLoop:
+	cmp		BYTE [si], STOP		; End of string?
+	je		.Str2NotFound		;  If so, return FALSE
+	call	String_BuffCmp		; str2 found in str1?
+	je		.Str2Found			;  If so, break loop
+	add		si, ax				; Add index to first unmatching char
+	inc		si					; Increment str1 ptr
+	jmp		.Str1CharLoop		; Loop while characters left
+
+ALIGN JUMP_ALIGN
+.Str2Found:
+	mov		bx, si				; Copy ptr to BX
+	mov		ax, si				; Copy ptr to AX
+	pop		si					; Restore SI
+	pop		cx					; Restore CX
+	sub		ax, si				; Calculate index to str2 in str1
+	stc							; Set CF since str2 found
+	ret
+ALIGN JUMP_ALIGN
+.Str2NotFound:
+	xor		bx, bx				; Zero BX
+	pop		si					; Restore SI
+	pop		cx					; Restore CX
+	clc							; Clear CF since str2 was not found
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Returns pointer to wanted token inside STOP terminated string.
+; Tokens are separated by any white space characters.
+; 
+; String_StrToken
+;	Parameters:
+;		CX:		Index of token to return
+;		ES:DI:	Pointer to string
+;	Returns:
+;		AX:		Token string length (if token found)
+;		ES:DI:	Pointer to token (if token found)
+;		CF:		Set if token found
+;				Cleared if token not found
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%ifdef USE_STR_TOKEN
+ALIGN JUMP_ALIGN
+String_StrToken:
+	push	cx					; Store CX
+	push	si					; Store SI
+	push	ds					; Store DS
+	push	es					; Copy ES:DI to DS:SI
+	pop		ds
+	mov		si, di
+	inc		cx					; Increment to number of tokens to search
+	cld							; LODSB to increment SI
+ALIGN JUMP_ALIGN
+.ConsumeWhite:
+	lodsb						; Load char to AL from [DS:SI]
+	cmp		al, STOP			; End of string?
+	je		.NotFound			;  If so, token was not found
+	call	String_IsSpace		; Any whitespace character?
+	jc		.ConsumeWhite		;  If so, skip it
+	dec		si					; Decrement SI to point first non-space
+	mov		di, si				; Copy offset to token to DI
+ALIGN JUMP_ALIGN
+.TokenLoop:
+	lodsb						; Load char to AL
+	cmp		al, STOP			; End of string?
+	je		.EndOfString		;  If so, end token
+	call	String_IsSpace		; Any whitespace character?
+	jnc		.TokenLoop			;  If not, loop
+	loop	.ConsumeWhite		; Loop until wanted token found
+.RetToken:
+	pop		ds					; Restore DS
+	pop		si					; Restore SI
+	pop		cx					; Restore CX
+	call	String_TokenLen		; Get token length to AX
+	stc							; Set CF since token found
+	ret
+ALIGN JUMP_ALIGN
+.EndOfString:
+	dec		si					; Offset to STOP
+	cmp		di, si				; STOP only char in token?
+	je		.NotFound			;  If so, then it is not valid token
+	loop	.NotFound			; If last token was not wanted
+	jmp		.RetToken
+ALIGN JUMP_ALIGN
+.NotFound:
+	pop		ds					; Restore DS
+	pop		si					; Restore SI
+	pop		cx					; Restore CX
+	clc							; Clear CF since token not found
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Converts a STOP terminated string to unsigned 32-bit integer.
+; 
+; String_StrToUInt
+;	Parameters:
+;		ES:DI:	Pointer to string to convert
+;		CX:		Base (10=dec, 16=hex etc.)
+;	Returns:
+;		DX:AX:	32-bit unsigned integer
+;		CF:		Set if converted successfully
+;				Cleared if error
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%ifdef USE_STR_TOUINT
+ALIGN JUMP_ALIGN
+String_StrToUInt:
+	push	si
+	call	String_StrLen		; Get string length to AX
+	mov		si, ax				; Copy length to SI
+	call	String_BuffToUInt	; Convert to integer in DX:AX
+	pop		si
+	ret
+%endif
+%if 0
+String_StrToUInt:		; Faster but we want to minimize size
+	; Copy ES:DI to DS:SI
+	push	ds					; Store DS
+	push	si					; Store SI
+	push	bx					; Store BX
+	mov		si, di				; Copy ES:DI to DS:SI
+	push	es
+	pop		ds
+
+	; Prepare to read chars
+	xor		dx, dx				; Zero DX (HIWORD)
+	xor		bx, bx				; Zero BX (LOWORD)
+ALIGN JUMP_ALIGN
+.CharLoop:
+	lodsb						; Load char to AL
+	cmp		al, STOP			; End of string?
+	je		.ConvComplete		;  If so, break loop
+	call	String_IsBaseChar	; Is valid character? (AH=digit)
+	jnc		.RetFalse			;  If not, return FALSE
+	xchg	ax, bx				; AX=LOWORD, BX=digit and char
+	call	Math_MulDWbyW		; DX:AX *= CX
+	xchg	ax, bx				; AX=digit and char, BX=LOWORD
+	mov		al, ah				; Copy digit to AL
+	xor		ah, ah				; Zero AH, AX=digit
+	add		bx, ax				; Add digit to LOWORD
+	adc		dx, 0				; Add carry to HIWORD
+	jmp		.CharLoop			; Loop while valid characters
+ALIGN JUMP_ALIGN
+.ConvComplete:
+	mov		ax, bx				; Copy loword to AX
+	pop		bx					; Restore BX
+	pop		si					; Restore SI
+	pop		ds					; Restore DS
+	stc							; Set CF since success
+	ret
+ALIGN JUMP_ALIGN
+.RetFalse:
+	mov		ax, bx				; Copy (likely incomplete) loword to AX
+	pop		bx					; Restore BX
+	pop		si					; Restore SI
+	pop		ds					; Restore DS
+	clc							; Clear CF since error
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Converts upper case character to lower case character.
+; 
+; String_ToLower
+;	Parameters:
+;		AL:		Character to convert
+;	Returns:
+;		AL:		Character with possible conversion
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%ifdef USE_STR_TOLOWER
+ALIGN JUMP_ALIGN
+String_ToLower:
+	call	String_IsUpper		; Is upper case character?
+	jnc		.Return				;  If not, return
+	add		al, 'a'-'A'			; Convert to lower case
+.Return:
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; Converts lower case character to upper case character.
+; 
+; String_ToUpper
+;	Parameters:
+;		AL:		Character to convert
+;	Returns:
+;		AL:		Character with possible conversion
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%ifdef USE_STR_TOUPPER
+ALIGN JUMP_ALIGN
+String_ToUpper:
+	call	String_IsLower		; Is lower case character?
+	jnc		.Return				;  If not, return
+	sub		al, 'a'-'A'			; Convert to upper case
+.Return:
+	ret
+%endif
Index: /tags/Configurator_v1.1.0/Src/Main.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Main.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Main.asm	(revision 6)
@@ -0,0 +1,152 @@
+; File name		:	main.asm
+; Project name	:	XTIDE Univeral BIOS Configurator
+; Created date	:	16.4.2010
+; Last update	:	30.4.2010
+; Author		:	Tomi Tilli
+; Description	:	Program start and exit.			
+
+; Include .inc files
+%include "emulate.inc"			; Emulation library. Must be first!
+%include "BiosData.inc"			; For BIOS Data Area variables
+%include "Variables.inc"		; Global variables for this program
+%include "MenuPage.inc"			; Menu page and item structs
+%include "RomVars.inc"			; XTIDE Universal BIOS ROMVARS
+
+
+; Section containing code
+SECTION .text
+
+; Program first instruction.
+ORG	100h						; Code starts at offset 100h (DOS .COM)
+Start:
+	jmp		Main_Start
+
+; Include library sources
+%include "math.asm"
+%include "print.asm"
+%include "string.asm"
+%include "keys.asm"
+%include "file.asm"
+%include "menu.asm"
+
+; Include sources for this program
+%include "Strings.asm"				; For program strings
+%include "MenuEvent.asm"			; For handling menu library events
+%include "MenuEventHotkey.asm"		; For handling menu hotkeys
+%include "MenuPage.asm"				; For accessing MENUPAGE structs
+%include "MenuPageItem.asm"			; For accessing MENUPAGEITEM structs
+%include "MenuPageItemFormat.asm"	; For printing menuitem names
+%include "FormatTitle.asm"			; For printing menu title
+%include "BiosFile.asm"				; For loading and saving BIOS file
+%include "EEPROM.asm"				; For handling EEPROM contents
+%include "Flash.asm"				; For flashing EEPROM
+
+%include "MainMenu.asm"				; For main menu
+%include "ConfigurationMenu.asm"	; For XTIDE Universal BIOS configuration menu
+%include "BootLoaderValueMenu.asm"	; For selecting boot loader type
+%include "IdeControllerMenu.asm"	; For configuring IDEVARS
+%include "BusTypeValueMenu.asm"		; For selecting bus type
+%include "DrvParamsMenu.asm"		; For configuring DRVPARAMS
+%include "BootMenuSettingsMenu.asm"	; For configuring boot menu
+%include "FlashMenu.asm"			; For flash settings
+%include "SdpCommandValueMenu.asm"	; For selecting SDP command
+
+
+;--------------------------------------------------------------------
+; Program start
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Main_Start:
+	call	MenuDraw_ClrScr		; Clear screen
+	call	Main_InitializeVariables
+
+	; Create main menu
+	mov		si, g_MenuPageMain	; DS:SI points to MENUPAGE for main menu
+	call	MainMenu_SetMenuitemVisibility
+	call	Main_EnterMenu		; Enter menu
+	call	MenuDraw_ClrScr		; Clear screen
+
+	; Exit to DOS
+	mov 	ax, 4C00h			; Exit to DOS
+	int 	21h
+
+
+;--------------------------------------------------------------------
+; Initializes global variables used in this program.
+;
+; Main_InitializeVariables
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Main_InitializeVariables:
+	; Zero all global variables
+	mov		di, g_cfgVars		; ES:DI points to global variables
+	mov		cx, (CFGVARS_size+ROMVARS_size)/2	; Size in words
+	xor		ax, ax				; To store zero
+	cld							; STOSW to increment DI
+	rep stosw					; Zero all variables
+
+	; Find Xtide Universal BIOS segment
+	mov		dx, 0D000h			; XTIDE default segment
+	call	EEPROM_FindXtideUniversalBiosROM
+	jnc		SHORT .InitializeVariables
+	mov		dx, es				; XTIDE segment to DX
+
+ALIGN JUMP_ALIGN
+.InitializeVariables:
+	mov		WORD [g_cfgVars+CFGVARS.wFlags], FLG_CFGVARS_CHECKSUM
+	mov		WORD [g_cfgVars+CFGVARS.wEepromSegment], dx
+	mov		BYTE [g_cfgVars+CFGVARS.bPageSize], 1
+	mov		BYTE [g_cfgVars+CFGVARS.bSdpCommand], CMD_SDP_ENABLE
+	ret
+
+
+;--------------------------------------------------------------------
+; Enters main or submenu.
+;
+; Main_EnterMenu
+;	Parameters:
+;		DS:SI:	Ptr to MENUPAGE (also menu user far pointer for MENUVARS.user)
+;	Returns:
+;		CX:		Index of last pointed Menuitem (not necessary selected with ENTER)
+;				FFFFh if cancelled with ESC
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Main_EnterMenu:
+	call	MenuPage_GetNumberOfVisibleItems
+	mov		cl, al								; Number of visible menuitems to CL
+	mov		ax, (CNT_SCRN_ROW<<8) | WIDTH_MENU
+	mov		bx, (CNT_INFO_LINES<<8) | CNT_TITLE_LINES
+	mov		ch, [cs:g_cfgVars+CFGVARS.wFlags]	; Load program flags to CH
+	and		ch, FLG_MNU_HIDENFO					; Clear all but info flag
+	xor		dx, dx								; No selection timeout
+	mov		di, MenuEvent_Handler				; CS:DI points to menu event handler
+	inc		BYTE [cs:g_cfgVars+CFGVARS.bMenuCnt]
+	call	Menu_Enter
+	dec		BYTE [cs:g_cfgVars+CFGVARS.bMenuCnt]
+	jz		SHORT .Return
+
+	; Update info visibility for previous menu where to resume
+	test	BYTE [cs:g_cfgVars+CFGVARS.wFlags], FLG_CFGVARS_HIDEINFO
+	jnz		SHORT .HideInfo
+	call	Menu_ShowInfo
+	ret
+ALIGN JUMP_ALIGN
+.HideInfo:
+	call	Menu_HideInfo
+.Return:
+	ret
+
+
+; Section containing uninitialized data
+SECTION .bss
+
+ALIGN WORD_ALIGN	; All global variables
+g_cfgVars:		resb	CFGVARS_size
Index: /tags/Configurator_v1.1.0/Src/MenuEvent.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/MenuEvent.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/MenuEvent.asm	(revision 6)
@@ -0,0 +1,276 @@
+; File name		:	MenuEvent.asm
+; Project name	:	XTIDE Univeral BIOS Configurator
+; Created date	:	16.4.2010
+; Last update	:	29.4.2010
+; Author		:	Tomi Tilli
+; Description	:	Handlers for menu library events.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Main event handler for all incoming events.
+;
+; MenuEvent_Handler
+;	Parameters:
+;		BX:		Callback event
+;		CX:		Menuitem index (usually index of selected Menuitem)
+;		DX:		Event parameter (event specific)
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		AH:		Event specific or unused. Set to 0 if unused.
+;		AL:		1=Event processed
+;				0=Event not processed (default action if any)
+;	Corrupts registers:
+;		BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuEvent_Handler:
+	push	es
+	push	ds
+	push	di
+	push	si
+
+	xor		ax, ax									; Event not processed
+	cmp		bx, BYTE EVNT_MNU_INITDONE				; Event in jump table?
+	ja		SHORT .Return
+	shl		bx, 1
+	call	[cs:bx+.rgwEventJmp]
+.Return:
+	pop		si
+	pop		di
+	pop		ds
+	pop		es
+	ret
+ALIGN WORD_ALIGN
+.rgwEventJmp:
+	dw		MenuEvent_Exit						; 0, EVNT_MNU_EXIT (Menu will quit)
+	dw		MenuEvent_EventItemSelectionChanged	; 1, EVNT_MMU_SELCHG (Menuitem selection changed (with arrows))
+	dw		MenuEvent_EventItemSelected			; 2, EVNT_MNU_SELSET (Menuitem selected (with Enter))
+	dw		MenuEvent_EventKeyPressed			; 3, EVNT_MNU_KEY (Keyboard key pressed)
+	dw		MenuEvent_EventMenuDraw				; 4, EVNT_MNU_UPD (Menu needs to be updated)
+	dw		MenuEvent_EventGetDefaultMenuitem	; 5, EVNT_MNU_GETDEF (Request menuitem to be selected by default)
+	dw		MenuEvent_EventMenuInitDone			; 6, EVNT_MNU_INITDONE (Menu has been initialized but not yet drawn)
+
+
+;--------------------------------------------------------------------
+; Handles Menu Exit notification (EVNT_MNU_EXIT).
+;
+; MenuEvent_Exit
+;	Parameters:
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		AH:		1 to cancel exit
+;				0 to allow menu exit
+;		AL:		1 = Event processed
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuEvent_Exit:
+	cmp		WORD [bp+MENUVARS.user], g_MenuPageMain	; Exiting main menu?
+	je		SHORT .AskUserAboutQuitting
+	mov		ax, 1					; Event handled
+	ret
+ALIGN JUMP_ALIGN
+.AskUserAboutQuitting:
+	call	BiosFile_SaveUnsavedChanges
+	mov		ax, 1					; Event handled
+	ret
+
+
+;--------------------------------------------------------------------
+; Handles Menuitem Selection Changed notification (EVNT_MMU_SELCHG).
+;
+; MenuEvent_EventItemSelectionChanged
+;	Parameters:
+;		CX:		Index of selected Menuitem
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		AX:		1 = Event processed
+;	Corrupts registers:
+;		BX, CX, DX, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuEvent_EventItemSelectionChanged:
+	mov		dl, MFL_UPD_NFO
+	call	Menu_Invalidate			; Invalidate info message
+	mov		ax, 1					; Event handled
+	ret
+
+
+;--------------------------------------------------------------------
+; Handles Menuitem Selected notification (EVNT_MNU_SELSET).
+;
+; MenuEvent_EventItemSelected
+;	Parameters:
+;		CX:		Index of selected Menuitem
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		AX:		1 = Event processed
+;	Corrupts registers:
+;		BX, CX, DX, SI, DI, DS, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuEvent_EventItemSelected:
+	lds		si, [bp+MENUVARS.user]					; DS:SI now points to MENUPAGE
+	call	MenuPage_GetMenuPageItemForVisibleIndex	; DS:DI now points to MENUPAGEITEM
+	jnc		SHORT .Return
+	push	cx
+	call	[di+MENUPAGEITEM.fnActivate]
+	pop		cx
+	jnc		SHORT .Return							; No changes
+	mov		dl, MFL_UPD_ITEM | MFL_UPD_NOCLEAR
+	call	Menu_Invalidate							; Invalidate menuitem
+.Return:
+	mov		ax, 1									; Event handled
+	ret
+
+
+;--------------------------------------------------------------------
+; Handles Key pressed notification (EVNT_MNU_KEY).
+;
+; MenuEvent_EventKeyPressed
+;	Parameters:
+;		CX:		Index of currently selected Menuitem
+;		DL:		ASCII character
+;		DH:		BIOS Scan Code
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		AX:		1 = Event processed
+;	Corrupts registers:
+;		BX, CX, DX, SI, DI, DS, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuEvent_EventKeyPressed:
+	lds		si, [bp+MENUVARS.user]					; DS:SI now points to MENUPAGE
+	call	MenuPage_GetMenuPageItemForVisibleIndex	; DS:DI now points to MENUPAGEITEM
+	jnc		SHORT .Return
+	call	MenuEventHotkey_Pressed
+.Return:
+	mov		ax, 1
+	ret
+
+
+;--------------------------------------------------------------------
+; Handles Menu Update notification (EVNT_MNU_UPD).
+;
+; MenuEvent_EventMenuDraw
+;	Parameters:
+;		CX: 	Index of Menuitem to update (if MFL_UPD_ITEM or MFL_UPD_NFO set)
+;		DL:		Update flag (only one):
+;					MFL_UPD_TITLE	Update Menu Title string(s)
+;					MFL_UPD_NFO		Update Menu Info string(s)
+;					MFL_UPD_ITEM	Update Menuitem string
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		AX:		Was event processed
+;	Corrupts registers:
+;		BX, CX, DX, SI, DI, DS, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuEvent_EventMenuDraw:
+	test	dl, MFL_UPD_ITEM		; Need to update Menuitem?
+	jnz		SHORT MenuEvent_DrawMenuitem
+	test	dl, MFL_UPD_NFO			; Need to update Info String(s)?
+	jnz		SHORT MenuEvent_DrawInfo
+	test	dl, MFL_UPD_TITLE		; Need to update Title String(s)?
+	jnz		SHORT MenuEvent_DrawTitle
+	xor		ax, ax
+	ret
+
+;--------------------------------------------------------------------
+; Draws Menuitem string. Cursor is set to a menuitem location.
+;
+; MenuEvent_DrawMenuitem
+;	Parameters:
+;		CX: 	Index of Menuitem to draw
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		AX:		Was event processed
+;	Corrupts registers:
+;		BX, CX, DX, SI, DI, DS, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuEvent_DrawMenuitem:
+	lds		si, [bp+MENUVARS.user]					; DS:SI now points to MENUPAGE
+	call	MenuPage_GetMenuPageItemForVisibleIndex	; DS:DI now points to MENUPAGEITEM
+	jnc		SHORT .Return
+	call	[di+MENUPAGEITEM.fnNameFormat]
+.Return:
+	mov		ax, 1
+	ret
+
+;--------------------------------------------------------------------
+; Draws information strings. Cursor is set to a first information line.
+;
+; MenuEvent_DrawInfo
+;	Parameters:
+;		CX: 	Index of selected menuitem
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		AX:		Was event processed
+;	Corrupts registers:
+;		BX, CX, DX, SI, DI, DS, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuEvent_DrawInfo:
+	lds		si, [bp+MENUVARS.user]					; DS:SI now points to MENUPAGE
+	call	MenuPage_GetMenuPageItemForVisibleIndex	; DS:DI now points to MENUPAGEITEM
+	jnc		SHORT .Return
+	call	MenuPageItem_PrintInfo
+.Return:
+	mov		ax, 1
+	ret
+
+;--------------------------------------------------------------------
+; Draws title strings. Cursor is set to a first title line.
+;
+; MenuEvent_DrawTitle
+;	Parameters:
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		AX:		Was event processed
+;	Corrupts registers:
+;		BX, CX, DX, SI, DI, DS, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuEvent_DrawTitle:
+	call	FormatTitle_String
+	mov		ax, 1
+	ret
+
+
+;--------------------------------------------------------------------
+; Handles Get Default Menuitem notification (EVNT_MNU_GETDEF).
+;
+; MenuEvent_EventGetDefaultMenuitem
+;	Parameters:
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		AX:		Was event processed
+;		CX:		Index of menuitem to set selected
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuEvent_EventGetDefaultMenuitem:
+	xor		ax, ax		; Not processed, default to menuitem 0
+	ret
+
+
+;--------------------------------------------------------------------
+; Handles Menu Initialized notification (EVNT_MNU_INITDONE).
+;
+; MenuEvent_EventMenuInitDone
+;	Parameters:
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		AX:		Was event processed
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuEvent_EventMenuInitDone:
+	mov		ax, 1
+	ret
Index: /tags/Configurator_v1.1.0/Src/MenuEventHotkey.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/MenuEventHotkey.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/MenuEventHotkey.asm	(revision 6)
@@ -0,0 +1,68 @@
+; File name		:	MenuEventHotkey.asm
+; Project name	:	XTIDE Univeral BIOS Configurator
+; Created date	:	16.4.2010
+; Last update	:	16.4.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions to handle menu hotkeys.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Handles all menu hotkeys.
+;
+; MenuEventHotkey_Pressed
+;	Parameters:
+;		CX:		Index (menu library) of currently selected Menuitem
+;		DL:		ASCII character for pressed key
+;		DH:		BIOS Scan Code for pressed key
+;		DS:SI:	Ptr to MENUPAGE
+;		DS:DI:	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, DI, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuEventHotkey_Pressed:
+	cmp		dh, KEY_BSC_F1		; Display help?
+	je		SHORT MenuEventHotkey_Help
+	cmp		dh, KEY_BSC_F2		; Toggle menu information?
+	je		SHORT MenuEventHotkey_ToggleInfo
+	ret
+
+
+;--------------------------------------------------------------------
+; Displays help dialog for menuitem.
+;
+; MenuEventHotkey_Help
+;	Parameters:
+;		DS:SI:	Ptr to MENUPAGE
+;		DS:DI:	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, DI, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuEventHotkey_Help:
+	jmp		MenuPageItem_DisplayHelpDialog
+
+
+;--------------------------------------------------------------------
+; Hides or sets menu information visible.
+;
+; MenuEventHotkey_ToggleInfo
+;	Parameters:
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuEventHotkey_ToggleInfo:
+	xor		WORD [g_cfgVars+CFGVARS.wFlags], BYTE FLG_CFGVARS_HIDEINFO
+	jmp		Menu_ToggleInfo
Index: /tags/Configurator_v1.1.0/Src/MenuPage.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/MenuPage.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/MenuPage.asm	(revision 6)
@@ -0,0 +1,151 @@
+; File name		:	MenuPage.asm
+; Project name	:	XTIDE Univeral BIOS Configurator
+; Created date	:	15.4.2010
+; Last update	:	27.4.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions to access MENUPAGE structs.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Returns number of visible menuitems in MENUPAGE.
+;
+; MenuPage_GetNumberOfVisibleItems
+;	Parameters:
+;		DS:SI:	Ptr to MENUPAGE
+;	Returns:
+;		AX:		Number of visible menuitems
+;	Corrupts registers:
+;		DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPage_GetNumberOfVisibleItems:
+	xor		ax, ax					; Zero visible menuitems
+	mov		di, MenuPage_IterateForNumberOfVisibleItems
+	jmp		SHORT MenuPage_IterateMenuPageItems
+
+;--------------------------------------------------------------------
+; Iteration callback function for MenuPage_GetNumberOfVisibleItems.
+;
+; MenuPage_IterateForNumberOfVisibleItems
+;	Parameters:
+;		AX:		Number of visible menuitems found so far
+;		DS:BX:	Ptr to MENUPAGEITEM to examine
+;	Returns:
+;		AX:		Number of visible menuitems found so far
+;		CF:		Cleared to continue iteration
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPage_IterateForNumberOfVisibleItems:
+	test	BYTE [bx+MENUPAGEITEM.bFlags], FLG_MENUPAGEITEM_VISIBLE	; Clears CF
+	jz		SHORT .NextItem
+	inc		ax						; Increment visible menuitems
+ALIGN JUMP_ALIGN
+.NextItem:
+	ret
+
+
+;--------------------------------------------------------------------
+; Returns pointer to MENUPAGEITEM for visible index (menu library index).
+;
+; MenuPage_GetMenuPageItemForVisibleIndex
+;	Parameters:
+;		CX:		Index of visible menuitem
+;		DS:SI:	Ptr to MENUPAGE
+;	Returns:
+;		DS:DI:	Ptr to MENUPAGEITEM
+;		CF:		Set if MENUPAGEITEM was found
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPage_GetMenuPageItemForVisibleIndex:
+	mov		ax, cx					; Menuitem index to menuitems to skip
+	mov		di, MenuPage_IterateForVisibleIndex
+	jmp		SHORT MenuPage_IterateMenuPageItems
+
+;--------------------------------------------------------------------
+; Iteration callback function for MenuPage_GetMenuPageItemForVisibleIndex.
+;
+; MenuPage_IterateForVisibleIndex
+;	Parameters:
+;		AX:		Number of visible menuitems left to skip
+;		DS:BX:	Ptr to MENUPAGEITEM to examine
+;	Returns:
+;		AX:		Number of visible menuitems left to skip
+;		CF:		Cleared to continue iteration
+;				Set if correct MENUPAGEITEM was found
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPage_IterateForVisibleIndex:
+	test	BYTE [bx+MENUPAGEITEM.bFlags], FLG_MENUPAGEITEM_VISIBLE	; Clears CF
+	jz		SHORT .NextItem
+	sub		ax, BYTE 1				; Set CF if correct MENUITEM found
+ALIGN JUMP_ALIGN
+.NextItem:
+	ret
+
+
+;--------------------------------------------------------------------
+; Iterates MENUPAGEITEMs until terminated by callback function or
+; all MENUPAGEITEMs have been iterated.
+;
+; MenuPage_IterateMenuPageItems
+;	Parameters:
+;		AX,DX:	Parameters to callback function
+;		DI:		Offset to iteration callback function
+;		DS:SI:	Ptr to MENUPAGE
+;	Returns:
+;		AX,DX:	Return values from callback function
+;		DS:DI:	Ptr to MENUPAGEITEM (only if CF set)
+;		CF:		Cleared if terminated by end of menuitems
+;				Set if terminated by callback function
+;	Corrupts registers:
+;		Nothing, unless corrupted by callback function
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPage_IterateMenuPageItems:
+	push	cx
+	push	bx
+	eMOVZX	cx, BYTE [si+MENUPAGE.bItemCnt]
+	lea		bx, [si+MENUPAGE.rgMenuPageItem]
+ALIGN JUMP_ALIGN
+.IterationLoop:
+	call	di							; Callback function
+	jc		SHORT .IterationComplete	; CF set, end iteration
+	add		bx, BYTE MENUPAGEITEM_size
+	loop	.IterationLoop
+	clc									; Clear CF since end of MENUITEMs
+ALIGN JUMP_ALIGN
+.IterationComplete:
+	mov		di, bx						; DS:DI points to MENUPAGEITEM
+	pop		bx
+	pop		cx
+	ret
+
+
+;--------------------------------------------------------------------
+; Updates number of menuitems and redraws them.
+;
+; MenuPage_InvalidateItemCount
+;	Parameters:
+;		DS:SI:	Ptr to MENUPAGE
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPage_InvalidateItemCount:
+	push	di
+	call	MenuPage_GetNumberOfVisibleItems
+	mov		cx, ax
+	mov		dl, MFL_UPD_ITEM | MFL_UPD_NFO
+	call	Menu_InvItemCnt
+	pop		di
+	ret
Index: /tags/Configurator_v1.1.0/Src/MenuPageItem.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/MenuPageItem.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/MenuPageItem.asm	(revision 6)
@@ -0,0 +1,428 @@
+; File name		:	MenuPageItem.asm
+; Project name	:	XTIDE Univeral BIOS Configurator
+; Created date	:	15.4.2010
+; Last update	:	1.5.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions to access MENUPAGEITEM structs.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Prints MenuPageItem information string to bottom of menu window.
+;
+; MenuPageItem_PrintInfo
+;	Parameters:
+;		DS:DI:	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, DI, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPageItem_PrintInfo:
+	push	cs
+	pop		es
+	eMOVZX	cx, BYTE [bp+MENUVARS.bInfoH]	; Info line count to CX
+	call	MenuPageItem_PrintCommonInfoLines
+	mov		di, [di+MENUPAGEITEM.szInfo]	; ES:DI now points to info string
+	jmp		MenuDraw_MultilineStr
+
+;--------------------------------------------------------------------
+; Prints information lines that are common for all menuitems.
+;
+; MenuPageItem_PrintCommonInfoLines
+;	Parameters:
+;		ES:		String segment
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPageItem_PrintCommonInfoLines:
+	push	di
+	push	cx
+	mov		di, g_szCommonInfo		; ES:DI now points common info string
+	call	MenuDraw_MultilineStr	; Draw title string
+	call	MenuDraw_NewlineStr		; Next line
+	call	MenuDraw_NewlineStr		; Next line
+	pop		cx
+	pop		di
+	ret
+
+
+;--------------------------------------------------------------------
+; Displays MenuPageItem help dialog.
+;
+; MenuPageItem_DisplayHelpDialog
+;	Parameters:
+;		DS:DI:	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, DI, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPageItem_DisplayHelpDialog:
+	mov		di, [di+MENUPAGEITEM.szHelp]	; ES:DI now points to help string
+	push	cs
+	pop		es
+	mov		bl, WIDTH_DLG					; Dialog width
+	jmp		Menu_ShowMsgDlg
+
+
+;--------------------------------------------------------------------
+; Displays message for special function menupageitem.
+;
+; MenuPageItem_DisplaySpecialFunctionDialog
+;	Parameters:
+;		DS:DI:	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPageItem_DisplaySpecialFunctionDialog:
+	push	es
+	push	di
+	push	cx
+
+	mov		di, [di+MENUPAGEITEM.szDialog]
+	push	cs
+	pop		es
+	mov		bl, WIDTH_DLG					; Dialog width
+	call	Menu_ShowMsgDlg
+
+	pop		cx
+	pop		di
+	pop		es
+	ret
+
+
+;--------------------------------------------------------------------
+; Asks unsigned byte from user.
+;
+; MenuPageItem_GetByteFromUser
+; MenuPageItem_GetByteFromUserWithoutMarkingUnsaved
+;	Parameters:
+;		DS:DI:	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Set if user data inputted succesfully
+;				Cleared if cancel
+;	Corrupts registers:
+;		AX, BX, CX, DX, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPageItem_GetByteFromUser:
+	call	MenuPageItem_GetByteFromUserWithoutMarkingUnsaved
+	jc		SHORT MenuPageItem_MarkSettingsAsUnsaved
+	ret
+ALIGN JUMP_ALIGN
+MenuPageItem_GetByteFromUserWithoutMarkingUnsaved:
+	mov		cx, 10								; Numeric base
+	mov		bx, [di+MENUPAGEITEM.szDialog]		; Dialog string
+	call	MenuPageItem_ShowWordDialog
+	jnc		SHORT .Return						; Return if cancel
+
+	; Limit to min or max and store value
+	MAX_U	ax, [di+MENUPAGEITEM.wValueMin]
+	MIN_U	ax, [di+MENUPAGEITEM.wValueMax]
+	mov		bx, [di+MENUPAGEITEM.pValue]
+	mov		[bx], al
+	stc
+.Return:
+	ret
+
+
+;--------------------------------------------------------------------
+; Asks unsigned word from user.
+;
+; MenuPageItem_GetWordFromUser
+; MenuPageItem_GetWordFromUserWithoutMarkingUnsaved
+;	Parameters:
+;		DS:DI:	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Set if user data inputted succesfully
+;				Cleared if cancel
+;	Corrupts registers:
+;		AX, BX, CX, DX, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPageItem_GetWordFromUser:
+	call	MenuPageItem_GetWordFromUserWithoutMarkingUnsaved
+	jc		SHORT MenuPageItem_MarkSettingsAsUnsaved
+	ret
+ALIGN JUMP_ALIGN
+MenuPageItem_GetWordFromUserWithoutMarkingUnsaved:
+	mov		cx, 10								; Numeric base
+	mov		bx, [di+MENUPAGEITEM.szDialog]		; Dialog string
+	call	MenuPageItem_ShowWordDialog
+	jnc		SHORT .Return						; Return if cancel
+
+	; Limit to min or max and store value
+	MAX_U	ax, [di+MENUPAGEITEM.wValueMin]
+	MIN_U	ax, [di+MENUPAGEITEM.wValueMax]
+	mov		bx, [di+MENUPAGEITEM.pValue]
+	mov		[bx], ax
+	stc
+.Return:
+	ret
+
+
+;--------------------------------------------------------------------
+; Asks hexadecimal byte from user.
+;
+; MenuPageItem_GetHexByteFromUser
+; MenuPageItem_GetHexByteFromUserWithoutMarkingUnsaved
+;	Parameters:
+;		DS:DI:	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Set if user data inputted succesfully
+;				Cleared if cancel
+;	Corrupts registers:
+;		AX, BX, CX, DX, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPageItem_GetHexByteFromUser:
+	call	MenuPageItem_GetHexByteFromUserWithoutMarkingUnsaved
+	jc		SHORT MenuPageItem_MarkSettingsAsUnsaved
+	ret
+ALIGN JUMP_ALIGN
+MenuPageItem_GetHexByteFromUserWithoutMarkingUnsaved:
+	mov		cx, 16								; Numeric base
+	mov		bx, [di+MENUPAGEITEM.szDialog]		; Dialog string
+	call	MenuPageItem_ShowWordDialog
+	jnc		SHORT .Return						; Return if cancel
+
+	; Store value
+	mov		bx, [di+MENUPAGEITEM.pValue]
+	mov		[bx], al
+.Return:
+	ret
+
+
+;--------------------------------------------------------------------
+; Asks hexadecimal word from user.
+;
+; MenuPageItem_GetHexWordFromUser
+; MenuPageItem_GetHexWordFromUserWithoutMarkingUnsaved
+;	Parameters:
+;		DS:DI:	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Set if user data inputted succesfully
+;				Cleared if cancel
+;	Corrupts registers:
+;		AX, BX, CX, DX, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPageItem_GetHexWordFromUser:
+	call	MenuPageItem_GetHexWordFromUserWithoutMarkingUnsaved
+	jc		SHORT MenuPageItem_MarkSettingsAsUnsaved
+	ret
+ALIGN JUMP_ALIGN
+MenuPageItem_GetHexWordFromUserWithoutMarkingUnsaved:
+	mov		cx, 16								; Numeric base
+	mov		bx, [di+MENUPAGEITEM.szDialog]		; Dialog string
+	call	MenuPageItem_ShowWordDialog
+	jnc		SHORT .Return						; Return if cancel
+
+	; Store value
+	mov		bx, [di+MENUPAGEITEM.pValue]
+	mov		[bx], ax
+.Return:
+	ret
+
+
+;--------------------------------------------------------------------
+; Called when any BIOS setting is modified.
+;
+; MenuPageItem_MarkSettingsAsUnsaved
+;	Parameters:
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Set since user data inputted succesfully
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPageItem_MarkSettingsAsUnsaved:
+	or		WORD [cs:g_cfgVars+CFGVARS.wFlags], FLG_CFGVARS_UNSAVED
+	call	FormatTitle_RedrawMenuTitle
+	stc
+	ret
+
+
+;--------------------------------------------------------------------
+; Shows dialog that asks WORD from user.
+;
+; MenuPageItem_ShowWordDialog
+;	Parameters:
+;		CX:		Numberic base (10=dec, 16=hex)
+;		DS:BX:	Ptr to dialog string
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		AX:		16-bit unsigned word inputted by user
+;		CF:		Set if user data inputted succesfully
+;				Cleared if cancel
+;	Corrupts registers:
+;		BX, CX, DX, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPageItem_ShowWordDialog:
+	push	di
+
+	push	cs
+	pop		es
+	mov		di, bx				; Dialog string now in ES:DI
+	mov		bl, WIDTH_DLG		; Dialog width
+	call	Menu_ShowDWDlg
+
+	pop		di
+	ret
+
+
+;--------------------------------------------------------------------
+; Asks boolean value (Y/N) from user.
+;
+; MenuPageItem_GetBoolFromUser
+; MenuPageItem_GetBoolFromUserWithoutMarkingUnsaved
+;	Parameters:
+;		DS:DI:	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Set if user data inputted succesfully
+;				Cleared if cancel
+;	Corrupts registers:
+;		AX, BX, CX, DX, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPageItem_GetBoolFromUser:
+	call	MenuPageItem_GetBoolFromUserWithoutMarkingUnsaved
+	jc		SHORT MenuPageItem_MarkSettingsAsUnsaved
+	ret
+ALIGN JUMP_ALIGN
+MenuPageItem_GetBoolFromUserWithoutMarkingUnsaved:
+	push	di
+	push	cs
+	pop		es
+	mov		di, [di+MENUPAGEITEM.szDialog]		; Dialog string
+	mov		bl, WIDTH_DLG						; Dialog width
+	call	Menu_ShowYNDlg
+	pop		di
+	jz		SHORT .Cancelled					; Return if cancelled
+	mov		bx, [di+MENUPAGEITEM.pValue]
+	mov		ax, [di+MENUPAGEITEM.wValueMask]
+	jc		SHORT .UserSelectedY
+
+	; User selected 'N'
+	not		ax
+	and		[bx], ax
+	stc
+	ret
+ALIGN JUMP_ALIGN
+.UserSelectedY:
+	or		[bx], ax
+	stc
+	ret
+.Cancelled:
+	clc
+	ret
+
+
+;--------------------------------------------------------------------
+; Activates new submenu for getting lookup value selected by user.
+;
+; MainPageItem_ActivateSubmenuForGettingLookupValue
+; MainPageItem_ActivateSubmenuForGettingLookupValueWithoutMarkingUnsaved
+;	Parameters:
+; 		DS:SI 	Ptr to MENUPAGE
+;		DS:DI	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Set if menuitem changed
+;				Cleared if no changes
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MainPageItem_ActivateSubmenuForGettingLookupValue:
+	call	MainPageItem_ActivateSubmenuForGettingLookupValueWithoutMarkingUnsaved
+	jc		SHORT MenuPageItem_MarkSettingsAsUnsaved
+	ret
+ALIGN JUMP_ALIGN
+MainPageItem_ActivateSubmenuForGettingLookupValueWithoutMarkingUnsaved:
+	call	MainPageItem_ActivateSubmenu
+	cmp		cx, BYTE 0
+	jl		SHORT .Return						; User cancellation
+	push	si
+	mov		si, [di+MENUPAGEITEM.pSubMenuPage]	; DS:SI points to value MENUPAGE
+	mov		bx, [si+MENUPAGE.prgbItemToVal]		; Load offset to lookup table
+	add		bx, cx								; Add menuitem index
+	mov		al, [bx]							; Load value
+	mov		bx, [di+MENUPAGEITEM.pValue]		; Load pointer to value
+	mov		[bx], al							; Store value
+	pop		si
+	stc											; Changes so redraw
+	ret
+.Return:
+	clc
+	ret
+
+
+;--------------------------------------------------------------------
+; Activates new submenu.
+;
+; MainPageItem_ActivateSubmenu
+;	Parameters:
+; 		DS:SI 	Ptr to MENUPAGE
+;		DS:DI	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CX:		Index of last pointed Menuitem (not necessary selected with ENTER)
+;				FFFFh if cancelled with ESC
+;		CF:		Set if menuitem changed
+;				Cleared if no changes
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MainPageItem_ActivateSubmenu:
+	push	di
+	push	si
+	mov		si, [di+MENUPAGEITEM.pSubMenuPage]	; DS:SI points to new MENUPAGE
+	call	Main_EnterMenu
+	call	Menu_RefreshMenu
+	pop		si
+	pop		di
+	clc
+	ret
+
+
+;--------------------------------------------------------------------
+; Leaves submenu.
+;
+; MainPageItem_ActivateLeaveSubmenu
+;	Parameters:
+; 		DS:SI 	Ptr to MENUPAGE
+;		DS:DI	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Cleared since no need to redraw
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MainPageItem_ActivateLeaveSubmenu:
+	call	Menu_Exit
+	clc
+	ret
Index: /tags/Configurator_v1.1.0/Src/MenuPageItemFormat.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/MenuPageItemFormat.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/MenuPageItemFormat.asm	(revision 6)
@@ -0,0 +1,225 @@
+; File name		:	MenuPageItemFormat.asm
+; Project name	:	XTIDE Univeral BIOS Configurator
+; Created date	:	15.4.2010
+; Last update	:	30.4.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for formatting 
+;					menuitem names from MENUPAGEITEM.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Prints lookup string for index values.
+;
+; MenuPageItemFormat_LookupString
+;	Parameters:
+;		DS:DI:	Ptr to MENUPAGEITEM
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, DX, SI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPageItemFormat_LookupString:
+	mov		si, [di+MENUPAGEITEM.rgszLookup]	; Load offset to string lookup table
+	mov		bx, [di+MENUPAGEITEM.pValue]		; Ptr to value containing lookup index
+	eMOVZX	bx, BYTE [bx]						; BX=lookup index (values are already shifted for WORD lookup)
+	push	WORD [bx+si]						; Push offset to string to print
+	mov		dh, 4								; Total of 4 bytes for formatting params
+	mov		si, .szStringName					; Offset to format string
+	jmp		MenuPageItemFormat_NameWithParamsPushed
+.szStringName:	db	"+%22s[%7s]",STOP
+
+
+;--------------------------------------------------------------------
+; Prints menuitem name for any MENUPAGEITEM.
+;
+; MenuPageItemFormat_NameForAnyType
+;	Parameters:
+;		DS:DI:	Ptr to MENUPAGEITEM
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, DX, SI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPageItemFormat_NameForAnyType:
+	eMOVZX	bx, BYTE [di+MENUPAGEITEM.bType]	; Load menuitem type
+	jmp		[cs:bx+.rgfnPrintBasedOnType]
+ALIGN WORD_ALIGN
+.rgfnPrintBasedOnType:
+	dw		MenuPageItemFormat_NameForBackToPreviousSubmenu		; TYPE_MENUPAGEITEM_BACK
+	dw		MenuPageItemFormat_NameForNextSubmenu				; TYPE_MENUPAGEITEM_NEXT
+	dw		MenuPageItemFormat_NameForSpecialFunction			; TYPE_MENUPAGEITEM_SPECIAL
+	dw		MenuPageItemFormat_NameWithUnsignedByteValue		; TYPE_MENUPAGEITEM_UNSIGNED_BYTE
+	dw		MenuPageItemFormat_NameWithUnsignedWordValue		; TYPE_MENUPAGEITEM_UNSIGNED_WORD
+	dw		MenuPageItemFormat_NameWithByteHexadecimalValue		; TYPE_MENUPAGEITEM_HEX_BYTE
+	dw		MenuPageItemFormat_NameWithWordHexadecimalValue		; TYPE_MENUPAGEITEM_HEX_WORD
+	dw		MenuPageItemFormat_NameWithFlagValue				; TYPE_MENUPAGEITEM_FLAG
+
+
+;--------------------------------------------------------------------
+; Prints "Back to previous menu" menuitem.
+;
+; MenuPageItemFormat_NameForBackToPreviousSubmenu
+;	Parameters:
+;		DS:DI:	Ptr to MENUPAGEITEM
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPageItemFormat_NameForBackToPreviousSubmenu:
+	mov		dh, 2								; Total of 2 bytes for formatting params
+	mov		si, .szPrevMenu						; Offset to format string
+	jmp		MenuPageItemFormat_NameWithParamsPushed
+.szPrevMenu:		db	"-%32s",STOP
+
+
+;--------------------------------------------------------------------
+; Prints menuitem name for menuitem that opens new submenu.
+;
+; MenuPageItemFormat_NameForNextSubmenu
+;	Parameters:
+;		DS:DI:	Ptr to MENUPAGEITEM
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DX, SI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPageItemFormat_NameForNextSubmenu:
+	mov		dh, 2								; Total of 2 bytes for formatting params
+	mov		si, .szNextMenu						; Offset to format string
+	jmp		MenuPageItemFormat_NameWithParamsPushed
+.szNextMenu:		db	"+%32s",STOP
+
+
+;--------------------------------------------------------------------
+; Prints menuitem name for menuitem with special function.
+;
+; MenuPageItemFormat_NameForSpecialFunction
+;	Parameters:
+;		DS:DI:	Ptr to MENUPAGEITEM
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DX, SI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPageItemFormat_NameForSpecialFunction:
+	mov		dh, 2								; Total of 2 bytes for formatting params
+	mov		si, .szSpecial						; Offset to format string
+	jmp		MenuPageItemFormat_NameWithParamsPushed
+.szSpecial:			db	"*%32s",STOP
+
+
+;--------------------------------------------------------------------
+; Prints menuitem name with unsigned integer value.
+;
+; MenuPageItemFormat_NameWithUnsignedByteValue
+; MenuPageItemFormat_NameWithUnsignedWordValue
+;	Parameters:
+;		DS:DI:	Ptr to MENUPAGEITEM
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DX, SI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPageItemFormat_NameWithUnsignedByteValue:
+	mov		si, [di+MENUPAGEITEM.pValue]		; DS:SI points to value
+	eMOVZX	ax, BYTE [si]						; Load byte to AX
+	push	ax									; Push byte
+	jmp		SHORT MenuPageItemFormat_NameWithUnsignedValuePushed
+ALIGN JUMP_ALIGN
+MenuPageItemFormat_NameWithUnsignedWordValue:
+	mov		si, [di+MENUPAGEITEM.pValue]		; DS:SI points to value
+	push	WORD [si]							; Push integer value
+MenuPageItemFormat_NameWithUnsignedValuePushed:
+	mov		dh, 4								; Total of 4 bytes for formatting params
+	mov		si, .szIntegerName					; Offset to format string
+	jmp		SHORT MenuPageItemFormat_NameWithParamsPushed
+.szIntegerName:	db	"%25s[%5u]",STOP
+
+
+;--------------------------------------------------------------------
+; Prints menuitem name with hexadecimal value.
+;
+; MenuPageItemFormat_NameWithByteHexadecimalValue
+; MenuPageItemFormat_NameWithWordHexadecimalValue
+;	Parameters:
+;		DS:DI:	Ptr to MENUPAGEITEM
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DX, SI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPageItemFormat_NameWithByteHexadecimalValue:
+	mov		si, [di+MENUPAGEITEM.pValue]		; DS:SI points to value
+	eMOVZX	ax, BYTE [si]						; Load byte to AX
+	push	ax									; Push byte
+	jmp		SHORT MenuPageItemFormat_NameWithHexadecimalValuePushed
+ALIGN JUMP_ALIGN
+MenuPageItemFormat_NameWithWordHexadecimalValue:
+	mov		si, [di+MENUPAGEITEM.pValue]		; DS:SI points to value
+	push	WORD [si]							; Push hexadecimal value
+MenuPageItemFormat_NameWithHexadecimalValuePushed:
+	mov		dh, 4								; Total of 4 bytes for formatting params
+	mov		si, .szHexName						; Offset to format string
+	jmp		SHORT MenuPageItemFormat_NameWithParamsPushed
+.szHexName:		db	"%25s[%5x]",STOP
+
+
+;--------------------------------------------------------------------
+; Prints menuitem name with Y/N flag value.
+;
+; MenuPageItemFormat_NameWithFlagValue
+;	Parameters:
+;		DS:DI:	Ptr to MENUPAGEITEM
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DX, SI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPageItemFormat_NameWithFlagValue:
+	mov		dx, 044Eh							; DH=4 bytes in stack, DL='N'
+	mov		si, [di+MENUPAGEITEM.pValue]		; DS:SI points to value
+	mov		ax, [si]							; Load value
+	test	ax, [di+MENUPAGEITEM.wValueMask]	; Flag set?
+	jz		SHORT .PushFlagValueChar
+	mov		dl, 'Y'
+.PushFlagValueChar:
+	push	dx
+	mov		si, .szFlagName						; Offset to format string
+	jmp		SHORT MenuPageItemFormat_NameWithParamsPushed
+.szFlagName:	db	"%25s[%5c]",STOP
+
+
+;--------------------------------------------------------------------
+; Prints formatted menuitem name.
+;
+; MenuPageItemFormat_NameWithParamsPushed
+;	Parameters:
+;		DH:		Number of bytes pushed to stack + 2 for name string
+;		SI:		Offset to formatting string
+;		DS:DI:	Ptr to MENUPAGEITEM
+;		DS:		String segment
+;		Stack:	Formatting parameters except menuitem name
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, SI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuPageItemFormat_NameWithParamsPushed:
+	push	WORD [di+MENUPAGEITEM.szName]
+	mov		dl, ' '				; Min length character
+	call	Print_Format
+	eMOVZX	ax, dh
+	add		sp, ax				; Clear format parameters from stack
+	ret
Index: /tags/Configurator_v1.1.0/Src/Menupages/BootMenuSettingsMenu.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Menupages/BootMenuSettingsMenu.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Menupages/BootMenuSettingsMenu.asm	(revision 6)
@@ -0,0 +1,122 @@
+; File name		:	BootMenuSettingsMenu.asm
+; Project name	:	XTIDE Univeral BIOS Configurator
+; Created date	:	27.4.2010
+; Last update	:	27.4.2010
+; Author		:	Tomi Tilli
+; Description	:	Menu for configuring boot menu settings.
+
+; Section containing initialized data
+SECTION .data
+
+; -Back to previous menu
+; Default boot drive (80h)
+; Display drive information (Y)
+; Display ROM boot selection (N)
+; Maximum height (20)
+; Minimum number of floppy drives (0)
+; Seconds for selection timeout (20)
+; Swap boot drive numbers (Y)
+
+
+ALIGN WORD_ALIGN
+g_MenuPageBootMenu:
+istruc MENUPAGE
+	at	MENUPAGE.bItemCnt,			db	8
+iend
+istruc MENUPAGEITEM	; Back to previous menu
+	at	MENUPAGEITEM.fnActivate,	dw	MainPageItem_ActivateLeaveSubmenu
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.szName,		dw	g_szPreviousMenu
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoIdeBack
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoIdeBack
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_BACK
+iend
+istruc MENUPAGEITEM	; Default boot drive
+	at	MENUPAGEITEM.fnActivate,	dw	MenuPageItem_GetHexByteFromUser
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.pValue,		dw	g_cfgVars+CFGVARS.rgbEepromBuffers+ROMVARS.bBootDrv
+	at	MENUPAGEITEM.wValueMin,		dw	0
+	at	MENUPAGEITEM.wValueMax,		dw	60
+	at	MENUPAGEITEM.szName,		dw	g_szItemBootDrive
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoBootDrive
+	at	MENUPAGEITEM.szHelp,		dw	g_szHelpBootDrive
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgBootDrive
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_HEX_BYTE
+iend
+istruc MENUPAGEITEM	; Display drive information
+	at	MENUPAGEITEM.fnActivate,	dw	MenuPageItem_GetBoolFromUser
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.pValue,		dw	g_cfgVars+CFGVARS.rgbEepromBuffers+ROMVARS.wFlags
+	at	MENUPAGEITEM.wValueMask,	dw	FLG_ROMVARS_DRVNFO
+	at	MENUPAGEITEM.szName,		dw	g_szItemBootInfo
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoBootInfo
+	at	MENUPAGEITEM.szHelp,		dw	g_szHelpBootInfo
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgBootInfo
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_FLAG
+iend
+istruc MENUPAGEITEM	; Display ROM boot selection
+	at	MENUPAGEITEM.fnActivate,	dw	MenuPageItem_GetBoolFromUser
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.pValue,		dw	g_cfgVars+CFGVARS.rgbEepromBuffers+ROMVARS.wFlags
+	at	MENUPAGEITEM.wValueMask,	dw	FLG_ROMVARS_ROMBOOT
+	at	MENUPAGEITEM.szName,		dw	g_szItemBootRomBoot
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoBootRomBoot
+	at	MENUPAGEITEM.szHelp,		dw	g_szHelpBootRomBoot
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgBootRomBoot
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_FLAG
+iend
+istruc MENUPAGEITEM	; Maximum height
+	at	MENUPAGEITEM.fnActivate,	dw	MenuPageItem_GetByteFromUser
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.pValue,		dw	g_cfgVars+CFGVARS.rgbEepromBuffers+ROMVARS.bBootMnuH
+	at	MENUPAGEITEM.wValueMin,		dw	8
+	at	MENUPAGEITEM.wValueMax,		dw	25
+	at	MENUPAGEITEM.szName,		dw	g_szItemBootHeight
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoBootHeight
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoBootHeight
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgBootHeight
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_UNSIGNED_BYTE
+iend
+istruc MENUPAGEITEM	; Minimum number of floppy drives
+	at	MENUPAGEITEM.fnActivate,	dw	MenuPageItem_GetByteFromUser
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.pValue,		dw	g_cfgVars+CFGVARS.rgbEepromBuffers+ROMVARS.bMinFddCnt
+	at	MENUPAGEITEM.wValueMin,		dw	0
+	at	MENUPAGEITEM.wValueMax,		dw	127
+	at	MENUPAGEITEM.szName,		dw	g_szItemBootMinFDD
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoBootMinFDD
+	at	MENUPAGEITEM.szHelp,		dw	g_szHelpBootMinFDD
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgBootMinFDD
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_UNSIGNED_BYTE
+iend
+istruc MENUPAGEITEM	; Seconds for selection timeout
+	at	MENUPAGEITEM.fnActivate,	dw	MenuPageItem_GetByteFromUser
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.pValue,		dw	g_cfgVars+CFGVARS.rgbEepromBuffers+ROMVARS.bBootDelay
+	at	MENUPAGEITEM.wValueMin,		dw	0
+	at	MENUPAGEITEM.wValueMax,		dw	60
+	at	MENUPAGEITEM.szName,		dw	g_szItemBootTimeout
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoBootTimeout
+	at	MENUPAGEITEM.szHelp,		dw	g_szHelpBootTimeout
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgBootTimeout
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_UNSIGNED_BYTE
+iend
+istruc MENUPAGEITEM	; Swap boot drive numbers
+	at	MENUPAGEITEM.fnActivate,	dw	MenuPageItem_GetBoolFromUser
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.pValue,		dw	g_cfgVars+CFGVARS.rgbEepromBuffers+ROMVARS.wFlags
+	at	MENUPAGEITEM.wValueMask,	dw	FLG_ROMVARS_DRVXLAT
+	at	MENUPAGEITEM.szName,		dw	g_szItemBootSwap
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoBootSwap
+	at	MENUPAGEITEM.szHelp,		dw	g_szHelpBootSwap
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgBootSwap
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_FLAG
+iend
Index: /tags/Configurator_v1.1.0/Src/Menupages/ConfigurationMenu.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Menupages/ConfigurationMenu.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Menupages/ConfigurationMenu.asm	(revision 6)
@@ -0,0 +1,390 @@
+; File name		:	ConfigurationMenu.asm
+; Project name	:	XTIDE Univeral BIOS Configurator
+; Created date	:	21.4.2010
+; Last update	:	2.5.2010
+; Author		:	Tomi Tilli
+; Description	:	XTIDE Universal BIOS configuration menu.
+
+; Section containing initialized data
+SECTION .data
+
+; -Back to previous menu
+; +Primary IDE
+; ...
+; +Last IDE
+; +Boot Menu settings
+; Boot loader type (None, Simple, Menu)
+; Late Initialization (N)
+; Maximize Disk Size (Y)
+; Full Operating Mode  (Y)
+; KiB to steal from base RAM (1)
+; Number of IDE controllers (5)
+
+ALIGN WORD_ALIGN
+g_MenuPageCfg:
+istruc MENUPAGE
+	at	MENUPAGE.bItemCnt,	db	13
+iend
+istruc MENUPAGEITEM	; Back to previous menu
+	at	MENUPAGEITEM.fnActivate,	dw	MainPageItem_ActivateLeaveSubmenu
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.szName,		dw	g_szPreviousMenu
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoCfgBack
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoCfgBack
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_BACK
+iend
+g_MenuPageItemCfgIde1:
+istruc MENUPAGEITEM	; Primary IDE
+	at	MENUPAGEITEM.fnActivate,	dw	ConfigurationMenu_ActivateIdeController
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.pValue,		dw	g_cfgVars+CFGVARS.rgbEepromBuffers+ROMVARS.ideVars0
+	at	MENUPAGEITEM.pSubMenuPage,	dw	g_MenuPageIdeVars
+	at	MENUPAGEITEM.szName,		dw	g_szItemCfgIde1
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoCfgIde
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoCfgIde
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_NEXT
+iend
+g_MenuPageItemCfgIde2:
+istruc MENUPAGEITEM
+	at	MENUPAGEITEM.fnActivate,	dw	ConfigurationMenu_ActivateIdeController
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.pValue,		dw	g_cfgVars+CFGVARS.rgbEepromBuffers+ROMVARS.ideVars1
+	at	MENUPAGEITEM.pSubMenuPage,	dw	g_MenuPageIdeVars
+	at	MENUPAGEITEM.szName,		dw	g_szItemCfgIde2
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoCfgIde
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoCfgIde
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_NEXT
+iend
+g_MenuPageItemCfgIde3:
+istruc MENUPAGEITEM
+	at	MENUPAGEITEM.fnActivate,	dw	ConfigurationMenu_ActivateIdeController
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.pValue,		dw	g_cfgVars+CFGVARS.rgbEepromBuffers+ROMVARS.ideVars2
+	at	MENUPAGEITEM.pSubMenuPage,	dw	g_MenuPageIdeVars
+	at	MENUPAGEITEM.szName,		dw	g_szItemCfgIde3
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoCfgIde
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoCfgIde
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_NEXT
+iend
+g_MenuPageItemCfgIde4:
+istruc MENUPAGEITEM
+	at	MENUPAGEITEM.fnActivate,	dw	ConfigurationMenu_ActivateIdeController
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.pValue,		dw	g_cfgVars+CFGVARS.rgbEepromBuffers+ROMVARS.ideVars3
+	at	MENUPAGEITEM.pSubMenuPage,	dw	g_MenuPageIdeVars
+	at	MENUPAGEITEM.szName,		dw	g_szItemCfgIde4
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoCfgIde
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoCfgIde
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_NEXT
+iend
+g_MenuPageItemCfgIde5:
+istruc MENUPAGEITEM
+	at	MENUPAGEITEM.fnActivate,	dw	ConfigurationMenu_ActivateIdeController
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.pValue,		dw	g_cfgVars+CFGVARS.rgbEepromBuffers+ROMVARS.ideVars4
+	at	MENUPAGEITEM.pSubMenuPage,	dw	g_MenuPageIdeVars
+	at	MENUPAGEITEM.szName,		dw	g_szItemCfgIde5
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoCfgIde
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoCfgIde
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_NEXT
+iend
+g_MenuPageItemCfgBootMenu:
+istruc MENUPAGEITEM	; Boot menu settings
+	at	MENUPAGEITEM.fnActivate,	dw	MainPageItem_ActivateSubmenu
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.pSubMenuPage,	dw	g_MenuPageBootMenu
+	at	MENUPAGEITEM.szName,		dw	g_szItemCfgBootMenu
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoCfgBootMenu
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoCfgBootMenu
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_NEXT
+iend
+istruc MENUPAGEITEM	; Boot Loader type
+	at	MENUPAGEITEM.fnActivate,	dw	ConfigurationMenu_ActivateBootLoaderType
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_LookupString
+	at	MENUPAGEITEM.pValue,		dw	g_cfgVars+CFGVARS.rgbEepromBuffers+ROMVARS.bBootLdrType
+	at	MENUPAGEITEM.pSubMenuPage,	dw	g_MenuPageBootLoaderType
+	at	MENUPAGEITEM.rgszLookup,	dw	g_rgszBootLoaderValueToString
+	at	MENUPAGEITEM.szName,		dw	g_szItemCfgBootLoader
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoCfgBootLoader
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoCfgBootLoader
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_NEXT
+iend
+istruc MENUPAGEITEM	; Late initialization
+	at	MENUPAGEITEM.fnActivate,	dw	MenuPageItem_GetBoolFromUser
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.pValue,		dw	g_cfgVars+CFGVARS.rgbEepromBuffers+ROMVARS.wFlags
+	at	MENUPAGEITEM.wValueMask,	dw	FLG_ROMVARS_LATE
+	at	MENUPAGEITEM.szName,		dw	g_szItemCfgLateInit
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoCfgLateInit
+	at	MENUPAGEITEM.szHelp,		dw	g_szHelpCfgLateInit
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgCfgLateInit
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_FLAG
+iend
+istruc MENUPAGEITEM	; Maximize disk size
+	at	MENUPAGEITEM.fnActivate,	dw	MenuPageItem_GetBoolFromUser
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.pValue,		dw	g_cfgVars+CFGVARS.rgbEepromBuffers+ROMVARS.wFlags
+	at	MENUPAGEITEM.wValueMask,	dw	FLG_ROMVARS_MAXSIZE
+	at	MENUPAGEITEM.szName,		dw	g_szItemCfgMaxSize
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoCfgMaxSize
+	at	MENUPAGEITEM.szHelp,		dw	g_szHelpCfgMaxSize
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgCfgMaxSize
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_FLAG
+iend
+istruc MENUPAGEITEM	; Full operating mode
+	at	MENUPAGEITEM.fnActivate,	dw	ConfigurationMenu_ActivateFullMode
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.pValue,		dw	g_cfgVars+CFGVARS.rgbEepromBuffers+ROMVARS.wFlags
+	at	MENUPAGEITEM.wValueMask,	dw	FLG_ROMVARS_FULLMODE
+	at	MENUPAGEITEM.szName,		dw	g_szItemCfgFullMode
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoCfgFullMode
+	at	MENUPAGEITEM.szHelp,		dw	g_szHelpCfgFullMode
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgCfgFullMode
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_FLAG
+iend
+g_MenuPageItemCfgStealRam:
+istruc MENUPAGEITEM	; kiB to steal from base RAM
+	at	MENUPAGEITEM.fnActivate,	dw	MenuPageItem_GetByteFromUser
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.pValue,		dw	g_cfgVars+CFGVARS.rgbEepromBuffers+ROMVARS.bStealSize
+	at	MENUPAGEITEM.wValueMin,		dw	1
+	at	MENUPAGEITEM.wValueMax,		dw	255
+	at	MENUPAGEITEM.szName,		dw	g_szItemCfgStealSize
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoCfgStealSize
+	at	MENUPAGEITEM.szHelp,		dw	g_szHelpCfgStealSize
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgCfgStealSize
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_UNSIGNED_BYTE
+iend
+g_MenuPageItemCfgIdeCnt:
+istruc MENUPAGEITEM	; Number of IDE controllers
+	at	MENUPAGEITEM.fnActivate,	dw	ConfigurationMenu_ActivateControllerCount
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.pValue,		dw	g_cfgVars+CFGVARS.rgbEepromBuffers+ROMVARS.bIdeCnt
+	at	MENUPAGEITEM.wValueMin,		dw	1
+	at	MENUPAGEITEM.wValueMax,		dw	5
+	at	MENUPAGEITEM.szName,		dw	g_szItemCfgIdeCnt
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoCfgIdeCnt
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoCfgIdeCnt
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgCfgIdeCnt
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_UNSIGNED_BYTE
+iend
+
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; ConfigurationMenu_ActivateIdeController
+;	Parameters:
+; 		DS:SI 	Ptr to MENUPAGE
+;		DS:DI	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Set if menuitem changed
+;				Cleared if no changes
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+ConfigurationMenu_ActivateIdeController:
+	mov		ax, [di+MENUPAGEITEM.pValue]	; AX=Offset to IDEVARS
+	call	IdeControllerMenu_SetIdevarsOffset
+	call	IdeControllerMenu_SetMenuitemVisibility
+	jmp		MainPageItem_ActivateSubmenu
+
+
+;--------------------------------------------------------------------
+; ConfigurationMenu_ActivateFullMode
+;	Parameters:
+; 		DS:SI 	Ptr to MENUPAGE
+;		DS:DI	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Set if menuitem changed
+;				Cleared if no changes
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+ConfigurationMenu_ActivateFullMode:
+	call	MenuPageItem_GetBoolFromUser
+	jc		SHORT ConfigurationMenu_SetMenuitemVisibilityAndDrawChanges
+	ret
+
+
+;--------------------------------------------------------------------
+; ConfigurationMenu_ActivateControllerCount
+;	Parameters:
+; 		DS:SI 	Ptr to MENUPAGE
+;		DS:DI	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Set if user data inputted succesfully
+;				Cleared if cancel
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+ConfigurationMenu_ActivateControllerCount:
+	call	MenuPageItem_GetByteFromUser
+	jc		SHORT ConfigurationMenu_SetMenuitemVisibilityAndDrawChanges
+	ret
+
+
+;--------------------------------------------------------------------
+; ConfigurationMenu_ActivateBootLoaderType
+;	Parameters:
+; 		DS:SI 	Ptr to MENUPAGE
+;		DS:DI	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Set if user data inputted succesfully
+;				Cleared if cancel
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+ConfigurationMenu_ActivateBootLoaderType:
+	call	MainPageItem_ActivateSubmenuForGettingLookupValue
+	jc		SHORT ConfigurationMenu_SetMenuitemVisibilityAndDrawChanges
+	ret
+
+
+;--------------------------------------------------------------------
+; ConfigurationMenu_SetMenuitemVisibilityAndDrawChanges
+;	Parameters:
+;		DS:SI:	Ptr to MENUPAGE
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Cleared since no need to draw changes
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+ConfigurationMenu_SetMenuitemVisibilityAndDrawChanges:
+	call	ConfigurationMenu_SetMenuitemVisibility
+	call	MenuPage_InvalidateItemCount
+	clc		; No need to redraw Full Mode menuitem
+	ret
+
+
+;--------------------------------------------------------------------
+; Enables or disables menuitems based on current configuration.
+;
+; ConfigurationMenu_SetMenuitemVisibility
+;	Parameters:
+;		DS:		CS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		BX, CX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+ConfigurationMenu_SetMenuitemVisibility:
+	call	ConfigurationMenu_SetBootMenuVisibility
+	call	ConfigurationMenu_SetFullModeVisibility
+	jmp		SHORT ConfigurationMenu_SetControllerCountVisibility
+
+ALIGN JUMP_ALIGN
+ConfigurationMenu_SetBootMenuVisibility:
+	cmp		BYTE [g_cfgVars+CFGVARS.rgbEepromBuffers+ROMVARS.bBootLdrType], BOOTLOADER_TYPE_MENU
+	jne		SHORT .DisableBootMenuSettings
+	or		BYTE [g_MenuPageItemCfgBootMenu+MENUPAGEITEM.bFlags], FLG_MENUPAGEITEM_VISIBLE
+	ret
+ALIGN JUMP_ALIGN
+.DisableBootMenuSettings:
+	and		BYTE [g_MenuPageItemCfgBootMenu+MENUPAGEITEM.bFlags], ~FLG_MENUPAGEITEM_VISIBLE
+	ret
+
+ALIGN JUMP_ALIGN
+ConfigurationMenu_SetFullModeVisibility:
+	test	WORD [g_cfgVars+CFGVARS.rgbEepromBuffers+ROMVARS.wFlags], FLG_ROMVARS_FULLMODE
+	jz		SHORT .DisableFullModeMenuitems
+	or		BYTE [g_MenuPageItemCfgStealRam+MENUPAGEITEM.bFlags], FLG_MENUPAGEITEM_VISIBLE
+	or		BYTE [g_MenuPageItemCfgIdeCnt+MENUPAGEITEM.bFlags], FLG_MENUPAGEITEM_VISIBLE
+	ret
+ALIGN JUMP_ALIGN
+.DisableFullModeMenuitems:
+	and		BYTE [g_MenuPageItemCfgStealRam+MENUPAGEITEM.bFlags], ~FLG_MENUPAGEITEM_VISIBLE
+	and		BYTE [g_MenuPageItemCfgIdeCnt+MENUPAGEITEM.bFlags], ~FLG_MENUPAGEITEM_VISIBLE
+	ret
+
+ALIGN JUMP_ALIGN
+ConfigurationMenu_SetControllerCountVisibility:
+	call	ConfigurationMenu_HideAdditionalIdeControllers
+	jmp		SHORT ConfigurationMenu_ShowAdditionalIdeControllers
+
+;--------------------------------------------------------------------
+; Hides all additional (not primary) IDE controller menuitems.
+;
+; ConfigurationMenu_HideAdditionalIdeControllers
+;	Parameters:
+;		DS:		CS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		BX, CX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+ConfigurationMenu_HideAdditionalIdeControllers:
+	mov		bx, g_MenuPageItemCfgIde2+MENUPAGEITEM.bFlags
+	mov		cx, CNT_MAX_CTRLS-1
+ALIGN JUMP_ALIGN
+.FlagLoop:
+	and		BYTE [bx], ~FLG_MENUPAGEITEM_VISIBLE
+	add		bx, MENUPAGEITEM_size
+	loop	.FlagLoop
+	ret
+
+;--------------------------------------------------------------------
+; Sets all additional (after primary) IDE controller menuitems visible.
+;
+; ConfigurationMenu_ShowAdditionalIdeControllers
+;	Parameters:
+;		DS:		CS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		BX, CX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+ConfigurationMenu_ShowAdditionalIdeControllers:
+	call	ConfigurationMenu_GetNumberOfIdeControllers
+	dec		cx					; First always visible
+	jcxz	.Return
+	mov		bx, g_MenuPageItemCfgIde2+MENUPAGEITEM.bFlags
+ALIGN JUMP_ALIGN
+.FlagLoop:
+	or		BYTE [bx], FLG_MENUPAGEITEM_VISIBLE
+	add		bx, MENUPAGEITEM_size
+	loop	.FlagLoop
+.Return:
+	ret
+
+;--------------------------------------------------------------------
+; Returns number of IDE controllers to set visible.
+;
+; ConfigurationMenu_GetNumberOfIdeControllers
+;	Parameters:
+;		DS:		CS
+;	Returns:
+;		CX:		Number of selected IDE controllers
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+ConfigurationMenu_GetNumberOfIdeControllers:
+	test	WORD [g_cfgVars+CFGVARS.rgbEepromBuffers+ROMVARS.wFlags], FLG_ROMVARS_FULLMODE
+	jz		SHORT .ReturnOneControllerForLiteMode
+	eMOVZX	cx, BYTE [g_cfgVars+CFGVARS.rgbEepromBuffers+ROMVARS.bIdeCnt]
+	ret
+ALIGN JUMP_ALIGN
+.ReturnOneControllerForLiteMode:
+	mov		cx, 1
+	ret
Index: /tags/Configurator_v1.1.0/Src/Menupages/DrvParamsMenu.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Menupages/DrvParamsMenu.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Menupages/DrvParamsMenu.asm	(revision 6)
@@ -0,0 +1,194 @@
+; File name		:	DrvParamsMenu.asm
+; Project name	:	XTIDE Univeral BIOS Configurator
+; Created date	:	26.4.2010
+; Last update	:	27.4.2010
+; Author		:	Tomi Tilli
+; Description	:	Menu for configuring DRVPARAMS.
+
+; Section containing initialized data
+SECTION .data
+
+; -Back to previous menu
+; Block Mode Transfers (Y)
+; User Specified CHS (Y)
+; Cylinders (16383)
+; Heads (16)
+; Sectors per track (63)
+
+ALIGN WORD_ALIGN
+g_MenuPageDrvParams:
+istruc MENUPAGE
+	at	MENUPAGE.bItemCnt,			db	6
+iend
+istruc MENUPAGEITEM	; Back to previous menu
+	at	MENUPAGEITEM.fnActivate,	dw	MainPageItem_ActivateLeaveSubmenu
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.szName,		dw	g_szPreviousMenu
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoDrvBack
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoDrvBack
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_BACK
+iend
+g_MenuPageItemDrvBlockMode:
+istruc MENUPAGEITEM	; Block Mode Transfers
+	at	MENUPAGEITEM.fnActivate,	dw	MenuPageItem_GetBoolFromUser
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.wValueMask,	dw	FLG_DRVPARAMS_BLOCKMODE
+	at	MENUPAGEITEM.szName,		dw	g_szItemDrvBlockMode
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoDrvBlockMode
+	at	MENUPAGEITEM.szHelp,		dw	g_szHelpDrvBlockMode
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgDrvBlockMode
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_FLAG
+iend
+g_MenuPageItemDrvUserCHS:
+istruc MENUPAGEITEM	; User Specified CHS
+	at	MENUPAGEITEM.fnActivate,	dw	DrvParamsMenu_ActivateUserCHS
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.wValueMask,	dw	FLG_DRVPARAMS_USERCHS
+	at	MENUPAGEITEM.szName,		dw	g_szItemDrvUserCHS
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoDrvUserCHS
+	at	MENUPAGEITEM.szHelp,		dw	g_szHelpDrvUserCHS
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgDrvUserCHS
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_FLAG
+iend
+g_MenuPageItemDrvCyls:
+istruc MENUPAGEITEM	; Cylinders
+	at	MENUPAGEITEM.fnActivate,	dw	MenuPageItem_GetWordFromUser
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.wValueMin,		dw	1
+	at	MENUPAGEITEM.wValueMax,		dw	16383
+	at	MENUPAGEITEM.szName,		dw	g_szItemDrvCyls
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoDrvCyls
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoDrvCyls
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgDrvCyls
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_UNSIGNED_WORD
+iend
+g_MenuPageItemDrvHeads:
+istruc MENUPAGEITEM	; Heads
+	at	MENUPAGEITEM.fnActivate,	dw	MenuPageItem_GetByteFromUser
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.wValueMin,		dw	1
+	at	MENUPAGEITEM.wValueMax,		dw	16
+	at	MENUPAGEITEM.szName,		dw	g_szItemDrvHeads
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoDrvHeads
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoDrvHeads
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgDrvHeads
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_UNSIGNED_BYTE
+iend
+g_MenuPageItemDrvSect:
+istruc MENUPAGEITEM	; Sectors per track
+	at	MENUPAGEITEM.fnActivate,	dw	MenuPageItem_GetByteFromUser
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.wValueMin,		dw	1
+	at	MENUPAGEITEM.wValueMax,		dw	63
+	at	MENUPAGEITEM.szName,		dw	g_szItemDrvSect
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoDrvSect
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoDrvSect
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgDrvSect
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_UNSIGNED_BYTE
+iend
+
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Stores DRVPARAMS specific pointers to MENUPAGEITEM structs.
+;
+; DrvParamsMenu_SetDrvParamsOffset
+;	Parameters:
+;		AX:		Offset to DRVPARAMS
+;		DS:		CS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		BX, CX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DrvParamsMenu_SetDrvParamsOffset:
+	eMOVZX	cx, BYTE [g_MenuPageDrvParams+MENUPAGE.bItemCnt]
+	dec		cx
+	mov		bx, g_MenuPageItemDrvBlockMode+MENUPAGEITEM.pValue
+ALIGN JUMP_ALIGN
+.StoreIdevarsLoop:
+	mov		[bx], ax
+	add		bx, MENUPAGEITEM_size
+	loop	.StoreIdevarsLoop
+
+	; Add offsets to values
+	add		WORD [g_MenuPageItemDrvBlockMode+MENUPAGEITEM.pValue], BYTE DRVPARAMS.wFlags
+	add		WORD [g_MenuPageItemDrvUserCHS+MENUPAGEITEM.pValue], BYTE DRVPARAMS.wFlags
+	add		WORD [g_MenuPageItemDrvCyls+MENUPAGEITEM.pValue], BYTE DRVPARAMS.wCylinders
+	add		WORD [g_MenuPageItemDrvHeads+MENUPAGEITEM.pValue], BYTE DRVPARAMS.bHeads
+	add		WORD [g_MenuPageItemDrvSect+MENUPAGEITEM.pValue], BYTE DRVPARAMS.bSect
+	ret
+
+
+;--------------------------------------------------------------------
+; DrvParamsMenu_ActivateUserCHS
+;	Parameters:
+; 		DS:SI 	Ptr to MENUPAGE
+;		DS:DI	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Set if menuitem changed
+;				Cleared if no changes
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DrvParamsMenu_ActivateUserCHS:
+	call	MenuPageItem_GetBoolFromUser
+	jc		SHORT DrvParamsMenu_SetMenuitemVisibilityAndDrawChanges
+	ret
+
+
+;--------------------------------------------------------------------
+; DrvParamsMenu_SetMenuitemVisibilityAndDrawChanges
+;	Parameters:
+;		DS:SI:	Ptr to MENUPAGE
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Cleared since no need to draw changes
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DrvParamsMenu_SetMenuitemVisibilityAndDrawChanges:
+	call	DrvParamsMenu_SetMenuitemVisibility
+	call	MenuPage_InvalidateItemCount
+	clc		; No need to redraw Full Mode menuitem
+	ret
+
+;--------------------------------------------------------------------
+; Enables or disables menuitems based on current configuration.
+;
+; DrvParamsMenu_SetMenuitemVisibility
+;	Parameters:
+;		DS:		CS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		BX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DrvParamsMenu_SetMenuitemVisibility:
+	jmp		SHORT DrvParamsMenu_SetChsVisibility
+
+ALIGN JUMP_ALIGN
+DrvParamsMenu_SetChsVisibility:
+	mov		bx, [g_MenuPageItemDrvUserCHS+MENUPAGEITEM.pValue]
+	test	WORD [bx], FLG_DRVPARAMS_USERCHS
+	jz		SHORT .DisableUserCHS
+	or		BYTE [g_MenuPageItemDrvCyls+MENUPAGEITEM.bFlags], FLG_MENUPAGEITEM_VISIBLE
+	or		BYTE [g_MenuPageItemDrvHeads+MENUPAGEITEM.bFlags], FLG_MENUPAGEITEM_VISIBLE
+	or		BYTE [g_MenuPageItemDrvSect+MENUPAGEITEM.bFlags], FLG_MENUPAGEITEM_VISIBLE
+	ret
+ALIGN JUMP_ALIGN
+.DisableUserCHS:
+	and		BYTE [g_MenuPageItemDrvCyls+MENUPAGEITEM.bFlags], ~FLG_MENUPAGEITEM_VISIBLE
+	and		BYTE [g_MenuPageItemDrvHeads+MENUPAGEITEM.bFlags], ~FLG_MENUPAGEITEM_VISIBLE
+	and		BYTE [g_MenuPageItemDrvSect+MENUPAGEITEM.bFlags], ~FLG_MENUPAGEITEM_VISIBLE
+	ret
Index: /tags/Configurator_v1.1.0/Src/Menupages/FlashMenu.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Menupages/FlashMenu.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Menupages/FlashMenu.asm	(revision 6)
@@ -0,0 +1,466 @@
+; File name		:	FlashMenu.asm
+; Project name	:	XTIDE Univeral BIOS Configurator
+; Created date	:	29.4.2010
+; Last update	:	2.5.2010
+; Author		:	Tomi Tilli
+; Description	:	Flash menu.
+
+
+; Flash error codes returned from progress bar task function
+ERR_FLASH_SUCCESSFULL	EQU		0
+ERR_FLASH_POLL_TIMEOUT	EQU		1
+
+
+; Section containing initialized data
+SECTION .data
+
+; -Back to previous menu
+; *Start flashing
+; +SDP command (Enable)
+; EEPROM address (D000h)
+; Page size (1)
+; Generate checksum byte (Y)
+
+ALIGN WORD_ALIGN
+g_MenuPageFlash:
+istruc MENUPAGE
+	at	MENUPAGE.bItemCnt,	db	6
+iend
+istruc MENUPAGEITEM	; Back to previous menu
+	at	MENUPAGEITEM.fnActivate,	dw	MainPageItem_ActivateLeaveSubmenu
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.szName,		dw	g_szPreviousMenu
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoCfgBack
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoCfgBack
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_BACK
+iend
+istruc MENUPAGEITEM	; Start flashing
+	at	MENUPAGEITEM.fnActivate,	dw	FlashMenu_ActivateStartFlashing
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.szName,		dw	g_szItemFlashStart
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoFlashStart
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoFlashStart
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_SPECIAL
+iend
+istruc MENUPAGEITEM	; SDP command
+	at	MENUPAGEITEM.fnActivate,	dw	FlashMenu_ActivateSdpCommand
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_LookupString
+	at	MENUPAGEITEM.pValue,		dw	g_cfgVars+CFGVARS.bSdpCommand
+	at	MENUPAGEITEM.pSubMenuPage,	dw	g_MenuPageSdpCommand
+	at	MENUPAGEITEM.rgszLookup,	dw	g_rgszSdpValueToString
+	at	MENUPAGEITEM.szName,		dw	g_szItemFlashSDP
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoFlashSDP
+	at	MENUPAGEITEM.szHelp,		dw	g_szHelpFlashSDP
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_NEXT
+iend
+istruc MENUPAGEITEM	; EEPROM address
+	at	MENUPAGEITEM.fnActivate,	dw	MenuPageItem_GetHexWordFromUserWithoutMarkingUnsaved
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.pValue,		dw	g_cfgVars+CFGVARS.wEepromSegment
+	at	MENUPAGEITEM.szName,		dw	g_szItemFlashAddr
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoFlashAddr
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoFlashAddr
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgFlashAddr
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_HEX_WORD
+iend
+istruc MENUPAGEITEM	; Page size
+	at	MENUPAGEITEM.fnActivate,	dw	FlashMenu_ActivatePageSize
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.pValue,		dw	g_cfgVars+CFGVARS.bPageSize
+	at	MENUPAGEITEM.wValueMin,		dw	1
+	at	MENUPAGEITEM.wValueMax,		dw	64
+	at	MENUPAGEITEM.szName,		dw	g_szItemFlashPageSize
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoFlashPageSize
+	at	MENUPAGEITEM.szHelp,		dw	g_szHelpFlashPageSize
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgFlashPageSize
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_UNSIGNED_BYTE
+iend
+istruc MENUPAGEITEM	; Generate checksum byte
+	at	MENUPAGEITEM.fnActivate,	dw	MenuPageItem_GetBoolFromUserWithoutMarkingUnsaved
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.pValue,		dw	g_cfgVars+CFGVARS.wFlags
+	at	MENUPAGEITEM.wValueMask,	dw	FLG_CFGVARS_CHECKSUM
+	at	MENUPAGEITEM.szName,		dw	g_szItemFlashChecksum
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoFlashChecksum
+	at	MENUPAGEITEM.szHelp,		dw	g_szHelpFlashChecksum
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgFlashChecksum
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_FLAG
+iend
+
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; FlashMenu_ActivateSdpCommand
+;	Parameters:
+; 		DS:SI 	Ptr to MENUPAGE
+;		DS:DI	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Set if menuitem changed
+;				Cleared if no changes
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+FlashMenu_ActivateSdpCommand:
+	call	MainPageItem_ActivateSubmenuForGettingLookupValueWithoutMarkingUnsaved
+	jnc		SHORT .Return
+	call	FormatTitle_RedrawMenuTitle
+	stc
+.Return:
+	ret
+
+
+;--------------------------------------------------------------------
+; FlashMenu_ActivatePageSize
+;	Parameters:
+; 		DS:SI 	Ptr to MENUPAGE
+;		DS:DI	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Set if menuitem changed
+;				Cleared if no changes
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+FlashMenu_ActivatePageSize:
+	call	MenuPageItem_GetByteFromUserWithoutMarkingUnsaved
+	jnc		SHORT .Cancel
+	eMOVZX	bx, BYTE [g_cfgVars+CFGVARS.bPageSize]
+	eBSR	ax, bx					; AX = Index of highest order bit
+	mov		cx, 1
+	xchg	ax, cx
+	shl		ax, cl					; AX = 1, 2, 4, 8, 16, 32 or 64
+	mov		[g_cfgVars+CFGVARS.bPageSize], al
+	stc
+	ret
+.Cancel:
+	clc
+	ret
+
+
+;--------------------------------------------------------------------
+; FlashMenu_ActivateStartFlashing
+;	Parameters:
+; 		DS:SI 	Ptr to MENUPAGE
+;		DS:DI	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Set if menuitem changed
+;				Cleared if no changes
+;	Corrupts registers:
+;		AX, BX, CX, DX, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+FlashMenu_ActivateStartFlashing:
+	test	WORD [g_cfgVars+CFGVARS.wFlags], FLG_CFGVARS_CHECKSUM
+	jz		SHORT .CopyContentsForComparison
+	call	EEPROM_GenerateChecksum
+ALIGN JUMP_ALIGN
+.CopyContentsForComparison:
+	call	Flash_CopyCurrentContentsForComparison
+	call	FlashMenu_InitializeFlashVars
+	call	FlashMenu_CreateProgressDialogAndStartFlashing
+	call	FlashMenu_ProcessFlashResults
+	clc
+	ret
+
+;--------------------------------------------------------------------
+; Initializes FLASHVARS.
+;
+; FlashMenu_InitializeFlashVars
+;	Parameters:
+;		DS:		CS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+FlashMenu_InitializeFlashVars:
+	; Total number of pages to write
+	xor		dx, dx
+	mov		ax, [g_cfgVars+CFGVARS.wEepromSize]		; DX:AX = Bytes to write
+	eMOVZX	cx, BYTE [g_cfgVars+CFGVARS.bPageSize]
+	div		cx										; AX = Total number of pages
+	mov		[g_cfgVars+CFGVARS.flashVars+FLASHVARS.wTotalPages], ax
+	mov		[g_cfgVars+CFGVARS.flashVars+FLASHVARS.wPagesLeft], ax
+
+	; Number of pages to write before updating progress bar
+	mov		cx, WIDTH_DLG-4
+	div		cx										; AX = Number of pages before update
+	mov		[g_cfgVars+CFGVARS.flashVars+FLASHVARS.wPagesBeforeDraw], ax
+
+	; Zero offset since nothing written yet
+	mov		WORD [g_cfgVars+CFGVARS.flashVars+FLASHVARS.wByteOffset], 0
+	ret
+
+;--------------------------------------------------------------------
+; Shows progress bar dialog.
+;
+; FlashMenu_CreateProgressDialogAndStartFlashing
+;	Parameters:
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		AX:		Return code from progress bar task function
+;	Corrupts registers:
+;		BX, CX, DX, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+FlashMenu_CreateProgressDialogAndStartFlashing:
+	push	ds
+	push	di
+	push	si
+
+	mov		bx, WIDTH_DLG | (5<<8)					; Height = 5 rows
+	mov		si, g_cfgVars+CFGVARS.flashVars			; DS:SI points to FLASHVARS
+	push	cs
+	pop		es
+	mov		di, FlashMenu_FlashProgressBarTask		; ES:DI points to progress bar task function
+	call	Menu_ShowProgDlg
+
+	pop		si
+	pop		di
+	pop		ds
+	ret
+
+;--------------------------------------------------------------------
+; Progress bar task function for flashing.
+; Cursor will be set to Title string location so progress dialog
+; title string can be modified if so wanted.
+; Remember to return with RETF instead of RET!
+;
+; FlashMenu_FlashProgressBarTask
+;	Parameters:
+;		DS:SI:	Pointer to FLASHVARS
+;	Returns:
+;		AX:		Error code if task completed (CF set)
+;				Task completion percentage (0...100) if CF cleared
+;		CF:		Set if task was completed or cancelled
+;				Cleared if task must be continued
+;	Corrupts registers:
+;		BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+FlashMenu_FlashProgressBarTask:
+	call	FlashMenu_UpdateProgressBarTitle
+	call	FlashMenu_FlashAllPagesBeforeUpdate
+	jc		SHORT .Timeout
+	call	FlashMenu_CalculateCompletionPercentage
+	jc		SHORT .FlashComplete
+	retf
+ALIGN JUMP_ALIGN
+.FlashComplete:
+	mov		ax, ERR_FLASH_SUCCESSFULL
+	retf
+.Timeout:
+	mov		ax, ERR_FLASH_POLL_TIMEOUT
+	retf
+
+
+;--------------------------------------------------------------------
+; Updates progress bar dialog title string.
+;
+; FlashMenu_UpdateProgressBarTitle
+;	Parameters:
+;		DS:SI:	Pointer to FLASHVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+FlashMenu_UpdateProgressBarTitle:
+	push	si
+	mov		ax, [si+FLASHVARS.wTotalPages]
+	sub		ax, [si+FLASHVARS.wPagesLeft]			; AX=Pages written
+	eMOVZX	dx, BYTE [g_cfgVars+CFGVARS.bPageSize]
+	mul		dx										; AX=Bytes written
+
+	push	WORD [g_cfgVars+CFGVARS.wEepromSize]	; EEPROM size
+	push	ax										; Bytes written
+	mov		si, g_szFlashProgress
+	call	Print_Format
+	add		sp, BYTE 4								; Clean stack
+	pop		si
+	ret
+
+;--------------------------------------------------------------------
+; Flashes pages until it is time to update progress bar.
+;
+; FlashMenu_FlashAllPagesBeforeUpdate
+;	Parameters:
+;		DS:SI:	Pointer to FLASHVARS
+;	Returns:
+;		CF:		Cleared if pages written successfully
+;				Set if polling timeout
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------	
+ALIGN JUMP_ALIGN
+FlashMenu_FlashAllPagesBeforeUpdate:
+	push	es
+	push	bp
+	push	di
+	push	si
+
+	mov		bp, si
+	mov		dx, [si+FLASHVARS.wPagesBeforeDraw]
+	call	FlashMenu_GetPointersToPageToFlash
+	eMOVZX	ax, BYTE [g_cfgVars+CFGVARS.bSdpCommand]
+	eMOVZX	cx, BYTE [g_cfgVars+CFGVARS.bPageSize]
+ALIGN JUMP_ALIGN
+.PageLoop:
+	call	Flash_WritePage
+	jc		SHORT .Return
+	add		[ds:bp+FLASHVARS.wByteOffset], cx
+	clc
+	dec		WORD [ds:bp+FLASHVARS.wPagesLeft]
+	jz		SHORT .Return		; Test since .wPagesBeforeDraw might write too much
+	dec		dx
+	jnz		SHORT .PageLoop
+.Return:
+	pop		si
+	pop		di
+	pop		bp
+	pop		es
+	ret
+
+;--------------------------------------------------------------------
+; Returns all pointers required for flashing.
+;
+; FlashMenu_GetPointersToPageToFlash
+;	Parameters:
+;		DS:SI:	Pointer to FLASHVARS
+;	Returns:
+;		DS:BX:	Pointer to comparison buffer
+;		DS:SI:	Pointer to source data buffer
+;		ES:DI:	Pointer to EEPROM
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+FlashMenu_GetPointersToPageToFlash:
+	mov		ax, [si+FLASHVARS.wByteOffset]
+	call	EEPROM_GetComparisonBufferPointerToDSBX
+	call	EEPROM_GetSourceBufferPointerToDSSI
+	call	EEPROM_GetEepromPointerToESDI
+	add		bx, ax
+	add		si, ax
+	add		di, ax
+	ret
+
+
+;--------------------------------------------------------------------
+; Returns all pointers required for flashing.
+;
+; FlashMenu_GetFlashPointersToNextPage
+;	Parameters:
+;		DS:SI:	Pointer to FLASHVARS
+;	Returns:
+;		AX:		Completion percentage (0...100)
+;		CF:		Set if all done
+;				Cleared if not yet complete
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+FlashMenu_CalculateCompletionPercentage:
+	cmp		WORD [si+FLASHVARS.wPagesLeft], 0
+	je		SHORT .FlashComplete
+	mov		ax, 100
+	mul		WORD [si+FLASHVARS.wPagesLeft]
+	div		WORD [si+FLASHVARS.wTotalPages]		; AX = Percentage left to write
+	mov		ah, 100
+	sub		ah, al
+	mov		al, ah
+	xor		ah, ah								; AX = Percentage written (clears CF)
+	ret
+ALIGN JUMP_ALIGN
+.FlashComplete:
+	mov		ax, 100
+	stc
+	ret
+
+
+;--------------------------------------------------------------------
+; Processes results from flashing.
+; Computer will be rebooted if PC expansion card BIOS was flashed.
+;
+; FlashMenu_ProcessFlashResults
+;	Parameters:
+;		AX:		Return code from progress bar task function
+; 		DS:SI 	Ptr to MENUPAGE
+;		DS:DI	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+FlashMenu_ProcessFlashResults:
+	cmp		ax, ERR_FLASH_POLL_TIMEOUT
+	je		SHORT FlashMenu_PollingTimeoutErrorDuringFlashing
+	call	Flash_WasDataWriteSuccessfull
+	jne		SHORT FlashMenu_DataVerifyErrorAfterFlashing
+	; Fall to FlashMenu_EepromFlashedSuccessfully
+
+;--------------------------------------------------------------------
+; Computer will be rebooted if PC expansion card BIOS was flashed.
+;
+; FlashMenu_EepromFlashedSuccessfully
+;	Parameters:
+; 		DS:SI 	Ptr to MENUPAGE
+;		DS:DI	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+FlashMenu_EepromFlashedSuccessfully:
+	cmp		WORD [g_cfgVars+CFGVARS.rgbEepromBuffers+ROMVARS.wRomSign], 0AA55h
+	je		SHORT .RebootSinceAllDone
+	mov		WORD [di+MENUPAGEITEM.szDialog], g_szFlashDoneContinue
+	jmp		MenuPageItem_DisplaySpecialFunctionDialog
+ALIGN JUMP_ALIGN
+.RebootSinceAllDone:
+	mov		WORD [di+MENUPAGEITEM.szDialog], g_szFlashDoneReboot
+	call	MenuPageItem_DisplaySpecialFunctionDialog
+	mov		al, 0FEh				; System reset (AT+ keyboard controller)
+	out		64h, al					; Reset computer (AT+)
+	jmp		WORD 0F000h:0FFF0h		; Safe reset on XTs only
+
+;--------------------------------------------------------------------
+; Displays flash error messages.
+;
+; FlashMenu_PollingTimeoutErrorDuringFlashing
+; FlashMenu_DataVerifyErrorAfterFlashing
+;	Parameters:
+; 		DS:SI 	Ptr to MENUPAGE
+;		DS:DI	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+FlashMenu_PollingTimeoutErrorDuringFlashing:
+	mov		WORD [di+MENUPAGEITEM.szDialog], g_szFlashTimeout
+	jmp		MenuPageItem_DisplaySpecialFunctionDialog
+
+ALIGN JUMP_ALIGN
+FlashMenu_DataVerifyErrorAfterFlashing:
+	mov		WORD [di+MENUPAGEITEM.szDialog], g_szFlashVerifyErr
+	jmp		MenuPageItem_DisplaySpecialFunctionDialog
Index: /tags/Configurator_v1.1.0/Src/Menupages/IdeControllerMenu.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Menupages/IdeControllerMenu.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Menupages/IdeControllerMenu.asm	(revision 6)
@@ -0,0 +1,236 @@
+; File name		:	IdeControllerMenu.asm
+; Project name	:	XTIDE Univeral BIOS Configurator
+; Created date	:	23.4.2010
+; Last update	:	27.4.2010
+; Author		:	Tomi Tilli
+; Description	:	Menu for configuring IDEVARS.
+
+; Section containing initialized data
+SECTION .data
+
+; -Back to previous menu
+; +Master Drive
+; +Slave Drive
+; Command Block (base port) address (01F0h)
+; Control Block address (03F0h)
+; Bus type (16-bit)
+; Enable Interrupt (Y)
+; IRQ (14)
+
+ALIGN WORD_ALIGN
+g_MenuPageIdeVars:
+istruc MENUPAGE
+	at	MENUPAGE.bItemCnt,			db	8
+iend
+istruc MENUPAGEITEM	; Back to previous menu
+	at	MENUPAGEITEM.fnActivate,	dw	MainPageItem_ActivateLeaveSubmenu
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.szName,		dw	g_szPreviousMenu
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoIdeBack
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoIdeBack
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_BACK
+iend
+g_MenuPageItemIdeMaster:
+istruc MENUPAGEITEM	; Master Drive
+	at	MENUPAGEITEM.fnActivate,	dw	IdeControllerMenu_ActivateMasterOrSlaveMenu
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.pSubMenuPage,	dw	g_MenuPageDrvParams
+	at	MENUPAGEITEM.szName,		dw	g_szItemIdeMaster
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoIdeMaster
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoIdeMaster
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_NEXT
+iend
+g_MenuPageItemIdeSlave:
+istruc MENUPAGEITEM	; Slave Drive
+	at	MENUPAGEITEM.fnActivate,	dw	IdeControllerMenu_ActivateMasterOrSlaveMenu
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.pSubMenuPage,	dw	g_MenuPageDrvParams
+	at	MENUPAGEITEM.szName,		dw	g_szItemIdeSlave
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoIdeSlave
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoIdeSlave
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_NEXT
+iend
+g_MenuPageItemIdeBusType:
+istruc MENUPAGEITEM	; Bus type
+	at	MENUPAGEITEM.fnActivate,	dw	MainPageItem_ActivateSubmenuForGettingLookupValue
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_LookupString
+	at	MENUPAGEITEM.pSubMenuPage,	dw	g_MenuPageBusType
+	at	MENUPAGEITEM.rgszLookup,	dw	g_rgszBusTypeValueToString
+	at	MENUPAGEITEM.szName,		dw	g_szItemIdeBusType
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoIdeBusType
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoIdeBusType
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_NEXT
+iend
+g_MenuPageItemIdeCmdPort:
+istruc MENUPAGEITEM	; Command Block (base port) address
+	at	MENUPAGEITEM.fnActivate,	dw	MenuPageItem_GetHexWordFromUser
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.szName,		dw	g_szItemIdeCmdPort
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoIdeCmdPort
+	at	MENUPAGEITEM.szHelp,		dw	g_szHelpIdeCmdPort
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgIdeCmdPort
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_HEX_WORD
+iend
+g_MenuPageItemIdeCtrlPort:
+istruc MENUPAGEITEM	; Control Block address (03F0h)
+	at	MENUPAGEITEM.fnActivate,	dw	MenuPageItem_GetHexWordFromUser
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.szName,		dw	g_szItemIdeCtrlPort
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoIdeCtrlPort
+	at	MENUPAGEITEM.szHelp,		dw	g_szHelpIdeCtrlPort
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgIdeCtrlPort
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_HEX_WORD
+iend
+g_MenuPageItemIdeEnIRQ:
+istruc MENUPAGEITEM	; Enable interrupt
+	at	MENUPAGEITEM.fnActivate,	dw	IdeControllerMenu_ActivateEnableInterrupt
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.wValueMask,	dw	000Fh
+	at	MENUPAGEITEM.szName,		dw	g_szItemIdeEnIRQ
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoIdeEnIRQ
+	at	MENUPAGEITEM.szHelp,		dw	g_szHelpIdeEnIRQ
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgIdeEnIRQ
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_FLAG
+iend
+g_MenuPageItemIdeIRQ:
+istruc MENUPAGEITEM	; IRQ
+	at	MENUPAGEITEM.fnActivate,	dw	MenuPageItem_GetByteFromUser
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.wValueMin,		dw	2
+	at	MENUPAGEITEM.wValueMax,		dw	15
+	at	MENUPAGEITEM.szName,		dw	g_szItemIdeIRQ
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoIdeIRQ
+	at	MENUPAGEITEM.szHelp,		dw	g_szHelpIdeIRQ
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgIdeIRQ
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_UNSIGNED_BYTE
+iend
+
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Stores IDEVARS specific pointers to IDE Controller Menu 
+; MENUPAGEITEM structs.
+;
+; IdeControllerMenu_SetIdevarsOffset
+;	Parameters:
+;		AX:		Offset to IDEVARS
+;		DS:		CS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		BX, CX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdeControllerMenu_SetIdevarsOffset:
+	eMOVZX	cx, BYTE [g_MenuPageIdeVars+MENUPAGE.bItemCnt]
+	dec		cx
+	mov		bx, g_MenuPageItemIdeMaster+MENUPAGEITEM.pValue
+ALIGN JUMP_ALIGN
+.StoreIdevarsLoop:
+	mov		[bx], ax
+	add		bx, MENUPAGEITEM_size
+	loop	.StoreIdevarsLoop
+
+	; Add offsets to values
+	add		WORD [g_MenuPageItemIdeMaster+MENUPAGEITEM.pValue], BYTE IDEVARS.drvParamsMaster
+	add		WORD [g_MenuPageItemIdeSlave+MENUPAGEITEM.pValue], BYTE IDEVARS.drvParamsSlave
+	add		WORD [g_MenuPageItemIdeBusType+MENUPAGEITEM.pValue], BYTE IDEVARS.bBusType
+	add		WORD [g_MenuPageItemIdeCmdPort+MENUPAGEITEM.pValue], BYTE IDEVARS.wPort
+	add		WORD [g_MenuPageItemIdeCtrlPort+MENUPAGEITEM.pValue], BYTE IDEVARS.wPortCtrl
+	add		WORD [g_MenuPageItemIdeEnIRQ+MENUPAGEITEM.pValue], BYTE IDEVARS.bIRQ
+	add		WORD [g_MenuPageItemIdeIRQ+MENUPAGEITEM.pValue], BYTE IDEVARS.bIRQ
+	ret
+
+
+;--------------------------------------------------------------------
+; IdeControllerMenu_ActivateMasterOrSlaveMenu
+;	Parameters:
+; 		DS:SI 	Ptr to MENUPAGE
+;		DS:DI	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Set if menuitem changed
+;				Cleared if no changes
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdeControllerMenu_ActivateMasterOrSlaveMenu:
+	mov		ax, [di+MENUPAGEITEM.pValue]	; AX=Offset to DRVPARAMS
+	call	DrvParamsMenu_SetDrvParamsOffset
+	call	DrvParamsMenu_SetMenuitemVisibility
+	jmp		MainPageItem_ActivateSubmenu
+
+
+;--------------------------------------------------------------------
+; IdeControllerMenu_ActivateEnableInterrupt
+;	Parameters:
+; 		DS:SI 	Ptr to MENUPAGE
+;		DS:DI	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Set if menuitem changed
+;				Cleared if no changes
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdeControllerMenu_ActivateEnableInterrupt:
+	call	MenuPageItem_GetBoolFromUser
+	jc		SHORT IdeControllerMenu_SetMenuitemVisibilityAndDrawChanges
+	ret
+
+
+;--------------------------------------------------------------------
+; IdeControllerMenu_SetMenuitemVisibilityAndDrawChanges
+;	Parameters:
+;		DS:SI:	Ptr to MENUPAGE
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Cleared since no need to draw changes
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdeControllerMenu_SetMenuitemVisibilityAndDrawChanges:
+	call	IdeControllerMenu_SetMenuitemVisibility
+	call	MenuPage_InvalidateItemCount
+	clc		; No need to redraw Full Mode menuitem
+	ret
+
+;--------------------------------------------------------------------
+; Enables or disables menuitems based on current configuration.
+;
+; IdeControllerMenu_SetMenuitemVisibility
+;	Parameters:
+;		DS:		CS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		BX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdeControllerMenu_SetMenuitemVisibility:
+	jmp		SHORT IdeControllerMenu_EnableOrDisableIrqSelect
+
+ALIGN JUMP_ALIGN
+IdeControllerMenu_EnableOrDisableIrqSelect:
+	mov		bx, [g_MenuPageItemIdeIRQ+MENUPAGEITEM.pValue]
+	cmp		BYTE [bx], 0				; Interrupts disabled?
+	je		SHORT .DisableIrqMenuitem
+	or		BYTE [g_MenuPageItemIdeIRQ+MENUPAGEITEM.bFlags], FLG_MENUPAGEITEM_VISIBLE
+	ret
+ALIGN JUMP_ALIGN
+.DisableIrqMenuitem:
+	and		BYTE [g_MenuPageItemIdeIRQ+MENUPAGEITEM.bFlags], ~FLG_MENUPAGEITEM_VISIBLE
+	ret
Index: /tags/Configurator_v1.1.0/Src/Menupages/MainMenu.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Menupages/MainMenu.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Menupages/MainMenu.asm	(revision 6)
@@ -0,0 +1,263 @@
+; File name		:	MainMenu.asm
+; Project name	:	XTIDE Univeral BIOS Configurator
+; Created date	:	19.4.2010
+; Last update	:	2.5.2010
+; Author		:	Tomi Tilli
+; Description	:	Main menu.
+
+; Section containing initialized data
+SECTION .data
+
+ALIGN WORD_ALIGN
+g_MenuPageMain:
+istruc MENUPAGE
+	at	MENUPAGE.bItemCnt,	db	6
+iend
+istruc MENUPAGEITEM	; Exit to DOS
+	at	MENUPAGEITEM.fnActivate,	dw	MainPageItem_ActivateLeaveSubmenu
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.szName,		dw	g_szItemMainExitToDOS
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoMainExitToDOS
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoMainExitToDOS
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_BACK
+iend
+istruc MENUPAGEITEM	; Load BIOS from file
+	at	MENUPAGEITEM.fnActivate,	dw	MainMenu_ActivateLoadBiosFromFile
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.szName,		dw	g_szItemMainLoadFile
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoMainLoadFile
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoMainLoadFile
+	at	MENUPAGEITEM.szDialog,		dw	g_szNfoMainLoadFile
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_NEXT
+iend
+g_MenuPageInfoMainLoadFromROM:
+istruc MENUPAGEITEM	; Load XTIDE Universal BIOS from ROM
+	at	MENUPAGEITEM.fnActivate,	dw	MainMenu_ActivateLoadBiosFromRom
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.szName,		dw	g_szItemMainLoadROM
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoMainLoadROM
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoMainLoadROM
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgMainLoadROM
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_SPECIAL
+iend
+g_MenuPageInfoMainLoadSettingsFromROM:
+istruc MENUPAGEITEM	; Load old settings from ROM
+	at	MENUPAGEITEM.fnActivate,	dw	MainMenu_ActivateLoadSettingsFromRom
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.szName,		dw	g_szItemMainLoadStngs
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoMainLoadStngs
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoMainLoadStngs
+	at	MENUPAGEITEM.szDialog,		dw	g_szDlgMainLoadStngs
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_SPECIAL
+iend
+g_MenuPageInfoMainConfigureBios:
+istruc MENUPAGEITEM	; Configure XTIDE Universal BIOS
+	at	MENUPAGEITEM.fnActivate,	dw	MainMenu_ActivateConfigureBios
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.pSubMenuPage,	dw	g_MenuPageCfg
+	at	MENUPAGEITEM.szName,		dw	g_szItemMainConfigure
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoMainConfigure
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoMainConfigure
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_NEXT
+iend
+g_MenuPageInfoMainFlash:
+istruc MENUPAGEITEM	; Flash EEPROM
+	at	MENUPAGEITEM.fnActivate,	dw	MainPageItem_ActivateSubmenu
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.pSubMenuPage,	dw	g_MenuPageFlash
+	at	MENUPAGEITEM.szName,		dw	g_szItemMainFlash
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoMainFlash
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoMainFlash
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_NEXT
+iend
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; MainMenu_ActivateLoadBiosFromFile
+;	Parameters:
+; 		DS:SI 	Ptr to MENUPAGE
+;		DS:DI	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Set if menuitem changed
+;				Cleared if no changes
+;	Corrupts registers:
+;		All
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MainMenu_ActivateLoadBiosFromFile:
+	push	si
+	call	BiosFile_SaveUnsavedChanges
+	call	BiosFile_SelectFile						; Let user select file
+	jc		SHORT .LoadUserSelectedFile
+	pop		si
+	ret												; User cancellation
+ALIGN JUMP_ALIGN
+.LoadUserSelectedFile:
+	push	cs
+	pop		es
+	mov		di, g_cfgVars+CFGVARS.rgbEepromBuffers	; ES:DI points to destination buffer
+	call	BiosFile_LoadFile						; Get file size to CX
+	pop		si
+	mov		ax, FLG_CFGVARS_FILELOADED				; Loaded file instead of ROM
+	jmp		SHORT MainMenu_NewBiosLoaded
+
+
+;--------------------------------------------------------------------
+; MainMenu_ActivateLoadBiosFromRom
+;	Parameters:
+; 		DS:SI 	Ptr to MENUPAGE
+;		DS:DI	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Set if menuitem changed
+;				Cleared if no changes
+;	Corrupts registers:
+;		All
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MainMenu_ActivateLoadBiosFromRom:
+	call	BiosFile_SaveUnsavedChanges
+	call	EEPROM_LoadBiosFromROM
+	call	MenuPageItem_DisplaySpecialFunctionDialog
+	mov		ax, FLG_CFGVARS_ROMLOADED	; Loaded ROM instead of file
+	jmp		SHORT MainMenu_NewBiosLoaded
+
+
+;--------------------------------------------------------------------
+; MainMenu_ActivateLoadSettingsFromRom
+;	Parameters:
+; 		DS:SI 	Ptr to MENUPAGE
+;		DS:DI	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Set if menuitem changed
+;				Cleared if no changes
+;	Corrupts registers:
+;		All
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MainMenu_ActivateLoadSettingsFromRom:
+	or		WORD [cs:g_cfgVars+CFGVARS.wFlags], FLG_CFGVARS_UNSAVED
+	call	EEPROM_LoadSettingsFromRomToRam
+	call	FormatTitle_RedrawMenuTitle
+	call	MenuPageItem_DisplaySpecialFunctionDialog
+	clc
+	ret
+
+
+;--------------------------------------------------------------------
+; MainMenu_ActivateConfigureBios
+;	Parameters:
+; 		DS:SI 	Ptr to MENUPAGE
+;		DS:DI	Ptr to MENUPAGEITEM
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Set if menuitem changed
+;				Cleared if no changes
+;	Corrupts registers:
+;		All
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MainMenu_ActivateConfigureBios:
+	call	ConfigurationMenu_SetMenuitemVisibility
+	jmp		MainPageItem_ActivateSubmenu
+
+
+;--------------------------------------------------------------------
+; MainMenu_NewBiosLoaded
+;	Parameters:
+;		AX:		EEPROM source (FLG_CFGVARS_FILELOADED or FLG_CFGVARS_ROMLOADED)
+;		CX:		EEPROM size in bytes
+;		DS:SI:	Ptr to MENUPAGE
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Cleared since no need to draw changes
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MainMenu_NewBiosLoaded:
+	call	EEPROM_NewBiosLoadedFromFileOrROM
+	call	FormatTitle_RedrawMenuTitle
+	; Fall to Main_SetMenuitemVisibilityAndDrawChanges
+
+;--------------------------------------------------------------------
+; Main_SetMenuitemVisibilityAndDrawChanges
+;	Parameters:
+;		DS:SI:	Ptr to MENUPAGE
+;		SS:BP:	Ptr to MENUVARS
+;	Returns:
+;		CF:		Cleared since no need to draw changes
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Main_SetMenuitemVisibilityAndDrawChanges:
+	call	MainMenu_SetMenuitemVisibility
+	call	MenuPage_InvalidateItemCount
+	clc		; No need to redraw Full Mode menuitem
+	ret
+
+
+;--------------------------------------------------------------------
+; Enables or disables menuitems based on current configuration.
+;
+; MainMenu_SetMenuitemVisibility
+;	Parameters:
+;		DS:		CS
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		BX, CX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MainMenu_SetMenuitemVisibility:
+	call	MainMenu_SetLoadBiosFromRomVisibility
+	call	MainMenu_SetConfigureXtideUniversalBiosVisibility
+	jmp		SHORT MainMenu_SetFlashVisibility
+
+ALIGN JUMP_ALIGN
+MainMenu_SetLoadBiosFromRomVisibility:
+	push	es
+	call	EEPROM_FindXtideUniversalBiosROM
+	pop		es
+	jnc		SHORT .XtideUniversalBiosNotFound
+	or		BYTE [g_MenuPageInfoMainLoadFromROM+MENUPAGEITEM.bFlags], FLG_MENUPAGEITEM_VISIBLE
+	call	EEPROM_IsXtideUniversalBiosLoaded
+	jne		SHORT .Return
+	or		BYTE [g_MenuPageInfoMainLoadSettingsFromROM+MENUPAGEITEM.bFlags], FLG_MENUPAGEITEM_VISIBLE
+ALIGN JUMP_ALIGN
+.Return:
+	ret
+ALIGN JUMP_ALIGN
+.XtideUniversalBiosNotFound:
+	and		BYTE [g_MenuPageInfoMainLoadFromROM+MENUPAGEITEM.bFlags], ~FLG_MENUPAGEITEM_VISIBLE
+	and		BYTE [g_MenuPageInfoMainLoadSettingsFromROM+MENUPAGEITEM.bFlags], ~FLG_MENUPAGEITEM_VISIBLE
+	ret
+
+ALIGN JUMP_ALIGN
+MainMenu_SetConfigureXtideUniversalBiosVisibility:
+	call	EEPROM_IsXtideUniversalBiosLoaded
+	jne		SHORT .XtideUniversalBiosNotLoaded
+	or		BYTE [g_MenuPageInfoMainConfigureBios+MENUPAGEITEM.bFlags], FLG_MENUPAGEITEM_VISIBLE
+	ret
+ALIGN JUMP_ALIGN
+.XtideUniversalBiosNotLoaded:
+	and		BYTE [g_MenuPageInfoMainConfigureBios+MENUPAGEITEM.bFlags], ~FLG_MENUPAGEITEM_VISIBLE
+	ret
+
+ALIGN JUMP_ALIGN
+MainMenu_SetFlashVisibility:
+	test	WORD [cs:g_cfgVars+CFGVARS.wFlags], FLG_CFGVARS_FILELOADED | FLG_CFGVARS_ROMLOADED
+	jz		SHORT .BiosNotLoaded
+	or		BYTE [g_MenuPageInfoMainFlash+MENUPAGEITEM.bFlags], FLG_MENUPAGEITEM_VISIBLE
+	ret
+ALIGN JUMP_ALIGN
+.BiosNotLoaded:
+	and		BYTE [g_MenuPageInfoMainFlash+MENUPAGEITEM.bFlags], ~FLG_MENUPAGEITEM_VISIBLE
+	ret
Index: /tags/Configurator_v1.1.0/Src/Menupages/Values/BootLoaderValueMenu.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Menupages/Values/BootLoaderValueMenu.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Menupages/Values/BootLoaderValueMenu.asm	(revision 6)
@@ -0,0 +1,56 @@
+; File name		:	BootLoaderValueMenu.asm
+; Project name	:	XTIDE Univeral BIOS Configurator
+; Created date	:	22.4.2010
+; Last update	:	25.4.2010
+; Author		:	Tomi Tilli
+; Description	:	Menu for selecting Boot Loader type.
+
+; Section containing initialized data
+SECTION .data
+
+ALIGN WORD_ALIGN
+g_MenuPageBootLoaderType:
+istruc MENUPAGE
+	at	MENUPAGE.bItemCnt,			db	3
+	at	MENUPAGE.prgbItemToVal,		dw	g_rgbBootLoaderMenuitemToValue
+iend
+istruc MENUPAGEITEM	; Boot menu
+	at	MENUPAGEITEM.fnActivate,	dw	MainPageItem_ActivateLeaveSubmenu
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.szName,		dw	g_szItemBootMenu
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoBootMenu
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoBootMenu
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_BACK
+iend
+istruc MENUPAGEITEM	; Simple
+	at	MENUPAGEITEM.fnActivate,	dw	MainPageItem_ActivateLeaveSubmenu
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.szName,		dw	g_szItemBootSimple
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoBootSimple
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoBootSimple
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_BACK
+iend
+istruc MENUPAGEITEM	; None
+	at	MENUPAGEITEM.fnActivate,	dw	MainPageItem_ActivateLeaveSubmenu
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.szName,		dw	g_szItemBootNone
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoBootNone
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoBootNone
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_BACK
+iend
+
+; Boot loader type value strings
+g_rgszBootLoaderValueToString:
+	dw		g_szValueBootLdrMenu		; BOOTLOADER_TYPE_MENU
+	dw		g_szValueBootLdrSimple		; BOOTLOADER_TYPE_SIMPLE
+	dw		g_szValueBootLdrSimple		; Undefined
+	dw		g_szValueBootLdrNone		; BOOTLOADER_TYPE_NONE
+
+; Lookup table for translating menuitem index to value
+g_rgbBootLoaderMenuitemToValue:
+	db		BOOTLOADER_TYPE_MENU
+	db		BOOTLOADER_TYPE_SIMPLE
+	db		BOOTLOADER_TYPE_NONE
Index: /tags/Configurator_v1.1.0/Src/Menupages/Values/BusTypeValueMenu.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Menupages/Values/BusTypeValueMenu.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Menupages/Values/BusTypeValueMenu.asm	(revision 6)
@@ -0,0 +1,66 @@
+; File name		:	BusTypeValueMenu.asm
+; Project name	:	XTIDE Univeral BIOS Configurator
+; Created date	:	25.4.2010
+; Last update	:	25.4.2010
+; Author		:	Tomi Tilli
+; Description	:	Menu for selecting bus type.
+
+; Section containing initialized data
+SECTION .data
+
+ALIGN WORD_ALIGN
+g_MenuPageBusType:
+istruc MENUPAGE
+	at	MENUPAGE.bItemCnt,			db	4
+	at	MENUPAGE.prgbItemToVal,		dw	g_rgbBusTypeMenuitemToValue
+iend
+istruc MENUPAGEITEM	; 8-bit dual port (XTIDE)
+	at	MENUPAGEITEM.fnActivate,	dw	MainPageItem_ActivateLeaveSubmenu
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.szName,		dw	g_szItemBus8Dual
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoBus8Dual
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoBus8Dual
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_BACK
+iend
+istruc MENUPAGEITEM	; 8-bit single port
+	at	MENUPAGEITEM.fnActivate,	dw	MainPageItem_ActivateLeaveSubmenu
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.szName,		dw	g_szItemBus8Single
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoBus8Single
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoBus8Single
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_BACK
+iend
+istruc MENUPAGEITEM	; 16-bit
+	at	MENUPAGEITEM.fnActivate,	dw	MainPageItem_ActivateLeaveSubmenu
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.szName,		dw	g_szItemBus16
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoBus16
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoBus16
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_BACK
+iend
+istruc MENUPAGEITEM	; 32-bit generic
+	at	MENUPAGEITEM.fnActivate,	dw	MainPageItem_ActivateLeaveSubmenu
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.szName,		dw	g_szItemBus32Generic
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoBus32Generic
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoBus32Generic
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_BACK
+iend
+
+; Lookup table for Bus type value strings
+g_rgszBusTypeValueToString:
+	dw	g_szValueDual8b
+	dw	g_szValue16b
+	dw	g_szValue32b
+	dw	g_szValueSingle8b
+
+; Lookup table for translating menuitem index to value
+g_rgbBusTypeMenuitemToValue:
+	db	BUS_TYPE_8_DUAL
+	db	BUS_TYPE_8_SINGLE
+	db	BUS_TYPE_16
+	db	BUS_TYPE_32
Index: /tags/Configurator_v1.1.0/Src/Menupages/Values/SdpCommandValueMenu.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Menupages/Values/SdpCommandValueMenu.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Menupages/Values/SdpCommandValueMenu.asm	(revision 6)
@@ -0,0 +1,55 @@
+; File name		:	SdpCommandValueMenu.asm
+; Project name	:	XTIDE Univeral BIOS Configurator
+; Created date	:	30.4.2010
+; Last update	:	30.4.2010
+; Author		:	Tomi Tilli
+; Description	:	Menu for selecting SDP command for flashing.
+
+; Section containing initialized data
+SECTION .data
+
+ALIGN WORD_ALIGN
+g_MenuPageSdpCommand:
+istruc MENUPAGE
+	at	MENUPAGE.bItemCnt,			db	3
+	at	MENUPAGE.prgbItemToVal,		dw	g_rgbSDPMenuitemToValue
+iend
+istruc MENUPAGEITEM	; None
+	at	MENUPAGEITEM.fnActivate,	dw	MainPageItem_ActivateLeaveSubmenu
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.szName,		dw	g_szItemSdpNone
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoSdpNone
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoSdpNone
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_BACK
+iend
+istruc MENUPAGEITEM	; Enable
+	at	MENUPAGEITEM.fnActivate,	dw	MainPageItem_ActivateLeaveSubmenu
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.szName,		dw	g_szItemSdpEnable
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoSdpEnable
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoSdpEnable
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_BACK
+iend
+istruc MENUPAGEITEM	; Disable
+	at	MENUPAGEITEM.fnActivate,	dw	MainPageItem_ActivateLeaveSubmenu
+	at	MENUPAGEITEM.fnNameFormat,	dw	MenuPageItemFormat_NameForAnyType
+	at	MENUPAGEITEM.szName,		dw	g_szItemSdpDisable
+	at	MENUPAGEITEM.szInfo,		dw	g_szNfoSdpDisable
+	at	MENUPAGEITEM.szHelp,		dw	g_szNfoSdpDisable
+	at	MENUPAGEITEM.bFlags,		db	FLG_MENUPAGEITEM_VISIBLE
+	at	MENUPAGEITEM.bType,			db	TYPE_MENUPAGEITEM_BACK
+iend
+
+; Lookup table for SDP command value strings
+g_rgszSdpValueToString:
+	dw	g_szValueSdpNone
+	dw	g_szValueSdpEnable
+	dw	g_szValueSdpDisable
+
+; Lookup table for translating menuitem index to value
+g_rgbSDPMenuitemToValue:
+	db	CMD_SDP_NONE
+	db	CMD_SDP_ENABLE
+	db	CMD_SDP_DISABLE
Index: /tags/Configurator_v1.1.0/Src/Strings.asm
===================================================================
--- /tags/Configurator_v1.1.0/Src/Strings.asm	(revision 6)
+++ /tags/Configurator_v1.1.0/Src/Strings.asm	(revision 6)
@@ -0,0 +1,297 @@
+; File name		:	Strings.asm
+; Project name	:	XTIDE Univeral BIOS Configurator
+; Created date	:	16.4.2010
+; Last update	:	2.5.2010
+; Author		:	Tomi Tilli
+; Description	:	Strings used in this program.
+
+; Section containing initialized data
+SECTION .data
+
+; General strings
+g_szSignature:		db	"XTIDE110",STOP		; XTIDE Universal BIOS signature string
+g_szCommonInfo:		db	"F1 displays item help. F2 toggles info. UP, DOWN, ENTER and ESC navigates. ENTER changes settings.",STOP
+g_szPreviousMenu:	db	"Back to previous menu",STOP
+g_szFileSearch:		db	"*.bin",STOP
+g_szErrFileSize:	db	"File size is too large! Maximum supported size is 16384 bytes.",STOP
+g_szDlgSaveChanges:	db	"Do you want to save changes to BIOS image file?",STOP
+
+
+; Flashing strings
+g_szFlashProgress:		db	"Writing EEPROM: %u / %u B.",STOP
+g_szFlashTimeout:		db	"Timeout error when polling EEPROM!",STOP
+g_szFlashVerifyErr:		db	"Data verification failed!",STOP
+g_szFlashDoneReboot:	db	"EEPROM written succesfully. Press any key to reboot.",STOP
+g_szFlashDoneContinue:	db	"EEPROM written succesfully.",STOP
+
+
+; Strings for menu title
+g_szTitleProgramName:	db	"Configuration and flashing program for XTIDE Universal BIOS v1.1.0",STOP
+g_szNoBiosLoaded:		db	"No BIOS loaded.",STOP
+g_szImageSource:		db	"Source image: ",STOP
+g_szRomLoaded:			db	"ROM",STOP
+
+
+; Strings for main menu
+g_szItemMainExitToDOS:	db	"Exit to DOS",STOP
+g_szItemMainLoadFile:	db	"Load BIOS from file",STOP
+g_szItemMainLoadROM:	db	"Load BIOS from EEPROM",STOP
+g_szItemMainLoadStngs:	db	"Load old settings from EEPROM",STOP
+g_szItemMainFlash:		db	"Flash EEPROM",STOP
+g_szItemMainConfigure:	db	"Configure XTIDE Universal BIOS",STOP
+
+g_szDlgMainLoadROM:		db	"Successfully loaded XTIDE Universal BIOS from EEPROM.",STOP
+g_szDlgMainLoadStngs:	db	"Successfully loaded settings from EEPROM.",STOP
+
+g_szNfoMainExitToDOS:	db	"Quits XTIDE Univeral BIOS Configurator.",STOP
+g_szNfoMainLoadFile:	db	"Load BIOS file to be configured or flashed.",STOP
+g_szNfoMainLoadROM:		db	"Load BIOS from EEPROM to be reconfigured.",STOP
+g_szNfoMainLoadStngs:	db	"Load old XTIDE Universal BIOS settings from EEPROM.",STOP
+g_szNfoMainFlash:		db	"Flash loaded BIOS image to EEPROM.",STOP
+g_szNfoMainConfigure:	db	"Configure XTIDE Universal BIOS settings.",STOP
+
+
+; Strings for XTIDE Universal BIOS configuration menu
+g_szItemCfgIde1:		db	"Primary IDE Controller",STOP
+g_szItemCfgIde2:		db	"Secondary IDE Controller",STOP
+g_szItemCfgIde3:		db	"Tertiary IDE Controller",STOP
+g_szItemCfgIde4:		db	"Quaternary IDE Controller",STOP
+g_szItemCfgIde5:		db	"Quinary IDE Controller",STOP
+g_szItemCfgBootMenu:	db	"Boot menu settings",STOP
+g_szItemCfgBootLoader:	db	"Boot loader type",STOP
+g_szItemCfgLateInit:	db	"Late initialization",STOP
+g_szItemCfgMaxSize:		db	"Maximize disk size",STOP
+g_szItemCfgFullMode:	db	"Full operating mode",STOP
+g_szItemCfgStealSize:	db	"kiB to steal from RAM",STOP
+g_szItemCfgIdeCnt:		db	"Number of IDE controllers",STOP
+
+g_szDlgCfgLateInit:		db	"Use late BIOS initialization?",STOP
+g_szDlgCfgMaxSize:		db	"Maximize hard disk size by sacrificing compatibility with old BIOSes?",STOP
+g_szDlgCfgFullMode:		db	"Enable full operating mode?",STOP
+g_szDlgCfgStealSize:	db	"How many kiB of base memory to steal for XTIDE Universal BIOS variables (1...255)?",STOP
+g_szDlgCfgIdeCnt:		db	"How many IDE controllers to manage (1...5)?",STOP
+
+g_szNfoCfgBack:			db	"Back to main menu.",STOP
+g_szNfoCfgIde:			db	"IDE controller and drive configuration.",STOP
+g_szNfoCfgBootMenu:		db	"Boot menu configuration.",STOP
+g_szNfoCfgBootLoader:	db	"Boot loader selection for INT 19h.",STOP
+g_szNfoCfgLateInit:		db	"Detect hard disks on boot loader.",STOP
+g_szNfoCfgMaxSize:		db	"Maximize hard disk size by not reserving diagnostic cylinder.",STOP
+g_szNfoCfgFullMode:		db	"Full mode supports multiple controllers and has more features.",STOP
+g_szNfoCfgStealSize:	db	"Number of kiB of base memory to steal for BIOS variables.",STOP
+g_szNfoCfgIdeCnt:		db	"Number of IDE controllers to manage.",STOP
+
+g_szHelpCfgLateInit:	db	"Normally expansion card BIOSes are initialized before POST completes. "
+						db	"Some (older) systems initialize expansion card BIOSes before they have "
+						db	"initialized themselves. This might cause problems since XTIDE Universal "
+						db	"BIOS requires some main BIOS functions for drive detection.",MNU_NL
+						db	"This problem can be fixed by using late initialization to "
+						db	"detect drives on boot loader. "
+						db	"Late initialization requires that XTIDE Universal BIOS is the last "
+						db	"BIOS that installs INT 19h handler. Make sure that XTIDE ROM is "
+						db	"configured to highest address if you have other storage device "
+						db	"controllers present.",STOP
+g_szHelpCfgMaxSize:		db	"Old BIOSes reserve diagnostic cylinder (landing zone cylinder for MFM drives) that "
+						db	"is not used. Later BIOSes do not reserve it to allow more data to be stored.",MNU_NL
+						db	"Do not maximize disk size if you need to move the drive between XTIDE Universal BIOS "
+						db	"controlled systems and systems with cylinder reserving BIOSes.",STOP
+g_szHelpCfgFullMode:	db	"Full mode supports up to 5 IDE controllers (10 drives). Full mode reserves a bit "
+						db	"of RAM from top of base memory. This makes possible to use ROM Basic and software that "
+						db	"requires top of interrupt vectors where XTIDE Universal BIOS parameters would be stored "
+						db	"in lite mode.",MNU_NL
+						db	"Lite mode supports only one IDE controller (2 drives) and stores parameters to top of "
+						db	"interrupt vectors (30:0h) so no base RAM needs to be reserved. Lite mode cannot be used "
+						db	"if some software requires top of interrupt vectors. Usually this is not a problem since "
+						db	"only IBM ROM Basic uses them.",MNU_NL
+						db	"Tandy 1000 models with 640 kiB or less memory need to use lite mode since top of base RAM "
+						db	"gets dynamically reserved by video hardware. This happens only with Tandy integrated "
+						db	"video controller, not with expansion graphics cards. It is possible to use full mode if "
+						db	"reserving RAM for video memory + what is required for XTIDE Universal BIOS. This would mean "
+						db	"129 kiB but most software should work with 65 kiB reserved.",STOP
+g_szHelpCfgStealSize:	db	"Parameters for detected hard disks must be stored somewhere. In full mode they are stored "
+						db	"to top of base RAM. At the moment 1 kiB is always enough but you might want to steal more if "
+						db	"you want to use full mode with Tandy 1000 (see help for Full Mode).",STOP
+
+g_szValueBootLdrMenu:	db	"Menu",STOP
+g_szValueBootLdrSimple:	db	"Simple",STOP
+g_szValueBootLdrNone:	db	"System",STOP
+
+; Strings for Boot Loader type menu
+g_szItemBootMenu:		db	"Boot menu",STOP
+g_szItemBootSimple:		db	"Simple boot loader",STOP
+g_szItemBootNone:		db	"System boot loader",STOP
+
+g_szNfoBootMenu:		db	"Boot menu for selecting drive to boot from.",STOP
+g_szNfoBootSimple:		db	"Typical A, C, INT 18h boot order.",STOP
+g_szNfoBootNone:		db	"Use boot loader provided by some other BIOS.",STOP
+
+
+; Strings for IDE Controller menu
+g_szItemIdeMaster:		db	"Master drive",STOP
+g_szItemIdeSlave:		db	"Slave drive",STOP
+g_szItemIdeCmdPort:		db	"Base (cmd block) address",STOP
+g_szItemIdeCtrlPort:	db	"Control block address",STOP
+g_szItemIdeBusType:		db	"Bus type",STOP
+g_szItemIdeEnIRQ:		db	"Enable interrupt",STOP
+g_szItemIdeIRQ:			db	"IRQ",STOP
+
+g_szDlgIdeCmdPort:		db	"Enter IDE command block (base port) address.",STOP
+g_szDlgIdeCtrlPort:		db	"Enter IDE control block address (usually command block + 200h).",STOP
+g_szDlgIdeEnIRQ:		db	"Enable interrupt?",STOP
+g_szDlgIdeIRQ:			db	"Enter IRQ channel (2...7 for 8-bit controllers, 2...15 for any other controller).",STOP
+
+g_szNfoIdeBack:			db	"Back to XTIDE Universal BIOS configuration menu.",STOP
+g_szNfoIdeMaster:		db	"Settings for master drive.",STOP
+g_szNfoIdeSlave:		db	"Settings for slave drive.",STOP
+g_szNfoIdeCmdPort:		db	"IDE Controller Command Block (base port) address.",STOP
+g_szNfoIdeCtrlPort:		db	"IDE Controller Control Block address. Usually Cmd Block + 200h.",STOP
+g_szNfoIdeBusType:		db	"Select controller bus type.",STOP
+g_szNfoIdeEnIRQ:		db	"Interrupt or polling mode.",STOP
+g_szNfoIdeIRQ:			db	"IRQ channel to use.",STOP
+
+g_szHelpIdeCmdPort:		db	"IDE controller command block address is the usual address mentioned for IDE controllers.",MNU_NL
+						db	"By default the primary IDE controller uses port 1F0h and secondary controller uses port 170h. "
+						db	"XTIDE uses port 300h by default.",STOP
+g_szHelpIdeCtrlPort:	db	"IDE controller control block address is normally command block address + 200h.",MNU_NL
+						db	"For XTIDE the control block registers are mapped right "
+						db	"after command block registers so use command block address + 8h for XTIDE.",STOP
+g_szHelpIdeEnIRQ:		db	"IDE controller can use interrupts to signal when it is ready to transfer data. This makes possible "
+						db	"to do other tasks while waiting drive to be ready. That is not useful in MS-DOS but using "
+						db	"interrupts frees the bus for any DMA transfers.",MNU_NL
+						db	"Polling mode is used when interrupts are disabled. Polling usually gives a little better access times "
+						db	"since interrupt handling requires extra processing. There can be some compatibility issues with some old drives "
+						db	"when polling is used with block mode transfers.",STOP
+g_szHelpIdeIRQ:			db	"IRQ channel to use. All controllers managed by XTIDE Universal BIOS can use the same IRQ when MS-DOS is used. "
+						db	"Other operating systems are likely to require different interrupts for each controller.",STOP
+
+g_szValueDual8b:		db	"2x8-bit",STOP
+g_szValue16b:			db	"16-bit",STOP
+g_szValue32b:			db	"32-bit",STOP
+g_szValueSingle8b:		db	"1x8-bit",STOP
+
+
+; Strings for Bus Type menu
+g_szItemBus8Dual:		db	"8-bit dual port (XTIDE)",STOP
+g_szItemBus8Single:		db	"8-bit single port",STOP
+g_szItemBus16:			db	"16-bit",STOP
+g_szItemBus32Generic:	db	"32-bit generic",STOP
+
+g_szNfoBus8Dual:		db	"8-bit ISA controllers with two data ports.",STOP
+g_szNfoBus8Single:		db	"8-bit ISA controllers with one data port.",STOP
+g_szNfoBus16:			db	"16-bit I/O for ISA (16-bit), VLB and PCI controllers.",STOP
+g_szNfoBus32Generic:	db	"Generic 32-bit I/O for VLB and PCI controllers.",STOP
+
+
+; Strings for DRVPARAMS menu
+g_szItemDrvBlockMode:	db	"Block mode transfers",STOP
+g_szItemDrvUserCHS:		db	"User specified CHS",STOP
+g_szItemDrvCyls:		db	"Cylinders",STOP
+g_szItemDrvHeads:		db	"Heads",STOP
+g_szItemDrvSect:		db	"Sectors per track",STOP
+
+g_szDlgDrvBlockMode:	db	"Enable block mode transfers?",STOP
+g_szDlgDrvUserCHS:		db	"Specify (P-)CHS parameters manually?",STOP
+g_szDlgDrvCyls:			db	"Enter number of P-CHS cylinders (1...16383).",STOP
+g_szDlgDrvHeads:		db	"Enter number of P-CHS heads (1...16).",STOP
+g_szDlgDrvSect:			db	"Enter number of sectors per track (1...63).",STOP
+
+g_szNfoDrvBack:			db	"Back to IDE controller menu.",STOP
+g_szNfoDrvBlockMode:	db	"Transfer multiple sectors per data request.",STOP
+g_szNfoDrvUserCHS:		db	"Specify (P-)CHS manually instead of autodetect.",STOP
+g_szNfoDrvCyls:			db	"Number of user specified P-CHS cylinders.",STOP
+g_szNfoDrvHeads:		db	"Number of user specified P-CHS heads.",STOP
+g_szNfoDrvSect:			db	"Number of user specified P-CHS sectors per track.",STOP
+
+g_szHelpDrvBlockMode:	db	"Block mode will speed up transfers since multiple sectors can be transferred "
+						db	"before waiting next data request. Normally block mode should always be kept enabled "
+						db	"but there is at least one drive with buggy block mode implementation. See readme for "
+						db	"more information.",STOP
+g_szHelpDrvUserCHS:		db	"Specify (P-)CHS parameters manually instead of autodetect.",MNU_NL
+						db	"This can be used to limit drive size for old operating systems "
+						db	"that do not support large hard disks.",MNU_NL
+						db	"Limiting cylinders will work for all drives but drives may not accept all "
+						db	"values for heads and sectors per track.",STOP
+
+
+; Strings for boot menu settings menu
+g_szItemBootHeight:		db	"Maximum height",STOP
+g_szItemBootTimeout:	db	"Selection timeout",STOP
+g_szItemBootDrive:		db	"Default boot drive",STOP
+g_szItemBootMinFDD:		db	"Min floppy drive count",STOP
+g_szItemBootSwap:		db	"Swap boot drive numbers",STOP
+g_szItemBootRomBoot:	db	"Display ROM boot",STOP
+g_szItemBootInfo:		db	"Display drive info",STOP
+
+g_szDlgBootHeight:		db	"Enter boot menu maximum height in characters (8...25).",STOP
+g_szDlgBootTimeout:		db	"Enter Boot Menu selection timeout in seconds (1...60, 0 disables timeout).",STOP
+g_szDlgBootDrive:		db	"Enter default drive number (0xh for Floppy Drives, 8xh for Hard Disks, FFh for ROM boot).",STOP
+g_szDlgBootMinFDD:		db	"Enter minimum number of floppy drives.",STOP
+g_szDlgBootSwap:		db	"Enable drive number translation?",STOP
+g_szDlgBootRomBoot:		db	"Show ROM Boot option on boot menu?",STOP
+g_szDlgBootInfo:		db	"Show drive information on boot menu?",STOP
+
+g_szNfoBootHeight:		db	"Boot Menu maximum height in characters.",STOP
+g_szNfoBootTimeout:		db	"Menu item selection timeout in seconds.",STOP
+g_szNfoBootDrive:		db	"Default drive on boot menu.",STOP
+g_szNfoBootMinFDD:		db	"Minimum number of floppy drives to display.",STOP
+g_szNfoBootSwap:		db	"Drive Number Translation (swap first drive with selected).",STOP
+g_szNfoBootRomBoot:		db	"Show ROM Basic or ROM DOS boot option.",STOP
+g_szNfoBootInfo:		db	"Show detailed drive information on boot menu.",STOP
+
+g_szHelpBootTimeout:	db	"Boot Menu selection timeout in seconds. When time goes to zero, "
+						db	"currently selected drive will be booted automatically.",MNU_NL
+						db	"Timeout can be disabled by setting this to 0.",STOP
+g_szHelpBootDrive:		db	"Default drive will be set selected by default when Boot Menu is displayed.",STOP
+g_szHelpBootMinFDD:		db	"Detecting correct number of floppy drives might fail when using floppy controller with it's own BIOS. "
+						db	"Minimum number of floppy drives can be specified to force non-detected drives to appear on boot menu.",STOP
+g_szHelpBootSwap:		db	"Some old operating systems (DOS) can only boot from "
+						db	"Floppy Drive A (00h) or first Hard Disk (80h, usually drive C). "
+						db	"Drive Translation can be used to modify drive numbers so that "
+						db	"selected drive will be mapped to 00h or 80h so that it can be booted.",STOP
+g_szHelpBootRomBoot:	db	"Some old systems have Basic or DOS in ROM. Since most systems don't have either, "
+						db	"ROM Boot setting is disabled by default. Enable it if you have use for it.",STOP
+g_szHelpBootInfo:		db	"Boot Menu can display some details about the drives in system. Reading this data "
+						db	"is slow on XTs so you might want to hide drive information.",STOP
+
+
+; Strings for Flash menu
+g_szItemFlashStart:		db	"Start flashing",STOP
+g_szItemFlashSDP:		db	"SDP command",STOP
+g_szItemFlashAddr:		db	"EEPROM address",STOP
+g_szItemFlashPageSize:	db	"Page size",STOP
+g_szItemFlashChecksum:	db	"Generate checksum byte",STOP
+
+g_szDlgFlashAddr:		db	"Enter segment address where EEPROM is located.",STOP
+g_szDlgFlashPageSize:	db	"Enter write page size (1, 2, 4, 8, 16, 32 or 64 bytes).",STOP
+g_szDlgFlashChecksum:	db	"Generate checksum byte to the end of BIOS image?",STOP
+
+g_szNfoFlashStart:		db	"Writes BIOS to EEPROM.",STOP
+g_szNfoFlashSDP:		db	"Software Data Protection command.",STOP
+g_szNfoFlashAddr:		db	"Address (segment) where EEPROM is located.",STOP
+g_szNfoFlashPageSize:	db	"Number of bytes to write before delay.",STOP
+g_szNfoFlashChecksum:	db	"Generate checksum byte to the end of BIOS image.",STOP
+
+g_szHelpFlashSDP:		db	"Software Data Protection protects the EEPROM from unwanted writes.",MNU_NL
+						db	"ENABLE command write protects the EEPROM after flashing. DISABLE command leaves the "
+						db	"EEPROM unprotected. NONE is meant for EEPROMs that do not support Software Data Protection.",MNU_NL
+						db	"Software Data Protection should always be left enabled if EEPROM supports it.",STOP
+g_szHelpFlashPageSize:	db	"Larger page size will improve write performance but not all "
+						db	"EEPROMs support large pages or page writing at all.",MNU_NL
+						db	"Byte writing mode will be used when page size is set "
+						db	"to 1. Byte writing mode is supported by every EEPROM. "
+						db	"Large pages cannot be used with slow CPUs.",STOP
+g_szHelpFlashChecksum:	db	"PC BIOSes require checksum byte to the end of expansion card BIOS ROMs. "
+						db	"Checksum generation can be disabled so any type of binaries can be flashed.",STOP
+
+
+; Strings for SDP command menu
+g_szValueSdpNone:
+g_szItemSdpNone:		db	"None",STOP
+g_szValueSdpEnable:
+g_szItemSdpEnable:		db	"Enable",STOP
+g_szValueSdpDisable:
+g_szItemSdpDisable:		db	"Disable",STOP
+
+g_szNfoSdpNone:			db	"Do not use Software Data Protection.",STOP
+g_szNfoSdpEnable:		db	"Enable Software Data Protection after flashing.",STOP
+g_szNfoSdpDisable:		db	"Disable Software Data Protection after flashing.",STOP
Index: /tags/Configurator_v1.1.0/gpl-2.0.txt
===================================================================
--- /tags/Configurator_v1.1.0/gpl-2.0.txt	(revision 6)
+++ /tags/Configurator_v1.1.0/gpl-2.0.txt	(revision 6)
@@ -0,0 +1,339 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
Index: /tags/Configurator_v1.1.0/makefile
===================================================================
--- /tags/Configurator_v1.1.0/makefile	(revision 6)
+++ /tags/Configurator_v1.1.0/makefile	(revision 6)
@@ -0,0 +1,111 @@
+###############################################################################
+# Generic makefile for building Assembly binary file.                         #
+# v. 1.0.0 (28.7.2007 ... 28.7.2007)                                          #
+# (C) Tomi Tilli                                                              #
+# aitotat@gmail.com                                                           #
+#                                                                             #
+# Valid makefile targets are:                                                 #
+# all		Removes existing files and builds binary file in \Build           #
+# build		Builds binary file in \Build                                      #
+# clean		Removes all files from \Build                                     #
+#                                                                             #
+# Build directory must be created manually if it does not exist.              #
+#                                                                             #
+###############################################################################
+
+###########################################
+# Source files and destination executable #
+###########################################
+
+# Assembly source code file (*.asm):
+SRC_ASM = Src\Main.asm
+
+# Program executable file name without extension:
+PROG = idecfg
+
+
+#######################################
+# Destination and include directories #
+#######################################
+
+# Directory where binary file will be compiled to
+BUILD_DIR = Build
+
+# Subdirectories where included files are:
+HEADERS = Inc/
+HEADERS += Src/
+HEADERS += Src/Libraries/
+HEADERS += Src/Libraries/menu/
+HEADERS += Src/Menupages/
+HEADERS += Src/Menupages/Values/
+
+
+#################################################################
+# Assembler preprocessor defines.                               #
+#################################################################
+DEFINES =
+
+
+###################
+# Other variables #
+###################
+
+# Add -D in front of every preprocessor define declaration
+DEFS = $(DEFINES:%=-D%)
+
+# Add -I in front of all header directories
+# and also set to search headers from current directory
+IHEADERS = $(HEADERS:%=-I%)
+IHEADERS += -I.
+
+# Path + target file to be build
+TARGET = $(BUILD_DIR)\$(PROG).com
+
+
+#########################
+# Compilers and linkers #
+#########################
+
+# Make
+MAKE = mingw32-make.exe
+
+# Assembler
+AS = nasm.exe
+
+# use this command to erase files.
+RM = -del /Q
+
+
+#############################
+# Compiler and linker flags #
+#############################
+
+# Assembly compiler flags
+ASFLAGS = -f bin				# Produce binary object files
+ASFLAGS += $(DEFS)				# Preprocessor defines
+ASFLAGS += $(IHEADERS)			# Set header file directory paths
+ASFLAGS += -Worphan-labels		# Warn about labels without colon
+ASFLAGS += -O9					# Optimize operands to their shortest forms
+
+
+############################################
+# Build process. Actual work is done here. #
+############################################
+
+.PHONY: all clean build
+
+# Make clean debug and release versions
+all:
+	@$(MAKE) clean
+	@$(MAKE) build
+	@echo All build!
+
+# Clean
+clean:
+	@$(RM) $(BUILD_DIR)\*.*
+	@echo Deleted "(*.*)" from "$(BUILD_DIR)\"
+
+# Build
+build:
+	@$(AS) "$(SRC_ASM)" $(ASFLAGS) -o"$(TARGET)"
+	@echo "$(TARGET)" build.
