Index: /trunk/Assembly_Library/Inc/AssemblyLibrary.inc
===================================================================
--- /trunk/Assembly_Library/Inc/AssemblyLibrary.inc	(revision 41)
+++ /trunk/Assembly_Library/Inc/AssemblyLibrary.inc	(revision 41)
@@ -0,0 +1,47 @@
+; File name		:	AssemblyLibrary.inc
+; Project name	:	Assembly Library
+; Created date	:	2.7.2010
+; Last update	:	16.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Common defines for all library functions.
+%ifndef ASSEMBLY_LIBRARY_INC
+%define ASSEMBLY_LIBRARY_INC
+
+; Include .inc files
+%include "Emulate.inc"			; Must be included first!
+%include "BiosData.inc"
+%include "BiosFunctions.inc"
+%include "Debug.inc"
+%include "DosFunctions.inc"
+%include "Math.inc"
+
+; Library dependencies
+%ifdef INCLUDE_MENU_DIALOGS
+	%include "Dialog.inc"
+	%define INCLUDE_MENU_LIBRARY
+	%define INCLUDE_FILE_LIBRARY
+%endif
+
+%ifdef INCLUDE_MENU_LIBRARY
+	%include "Menu.inc"
+	%include "MenuEvents.inc"
+	%define INCLUDE_KEYBOARD_LIBRARY
+	%define INCLUDE_TIME_LIBRARY
+%endif
+
+%ifdef INCLUDE_KEYBOARD_LIBRARY
+	%define INCLUDE_DISPLAY_LIBRARY
+	%define INCLUDE_UTIL_LIBRARY
+%endif
+
+%ifdef INCLUDE_DISPLAY_LIBRARY
+	%include "Display.inc"
+	%define INCLUDE_STRING_LIBRARY
+%endif
+
+%ifdef INCLUDE_FILE_LIBRARY
+	%define INCLUDE_UTIL_LIBRARY
+%endif
+
+
+%endif ; ASSEMBLY_LIBRARY_INC
Index: /trunk/Assembly_Library/Inc/BiosData.inc
===================================================================
--- /trunk/Assembly_Library/Inc/BiosData.inc	(revision 41)
+++ /trunk/Assembly_Library/Inc/BiosData.inc	(revision 41)
@@ -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: /trunk/Assembly_Library/Inc/BiosFunctions.inc
===================================================================
--- /trunk/Assembly_Library/Inc/BiosFunctions.inc	(revision 41)
+++ /trunk/Assembly_Library/Inc/BiosFunctions.inc	(revision 41)
@@ -0,0 +1,31 @@
+; File name		:	BiosFunctions.inc
+; Project name	:	AssemblyLibrary
+; Created date	:	25.6.2010
+; Last update	:	24.7.2010
+; Author		:	Tomi Tilli
+; Description	:	Defines for BIOS functions.
+%ifndef BIOS_FUNCTIONS_INC
+%define BIOS_FUNCTIONS_INC
+
+; BIOS interrupts
+BIOS_VIDEO_INTERRUPT_10h		EQU		10h
+BIOS_SYSTEM_INTERRUPT_15h		EQU		15h
+BIOS_KEYBOARD_INTERRUPT_16h		EQU		16h
+
+
+; BIOS video functions
+SET_TEXT_MODE_CURSOR_SHAPE		EQU		01h
+SET_CURSOR_POSITION				EQU		02h
+GET_CURSOR_POSITION_AND_SIZE	EQU		03h
+SELECT_ACTIVE_DISPLAY_PAGE		EQU		05h
+TELETYPE_OUTPUT					EQU		0Eh
+
+; BIOS keyboard functions
+GET_KEYSTROKE					EQU		00h
+CHECK_FOR_KEYSTROKE				EQU		01h
+
+; BIOS system functions
+EVENT_WAIT						EQU		86h
+
+
+%endif ; BIOS_FUNCTIONS_INC
Index: /trunk/Assembly_Library/Inc/Debug.inc
===================================================================
--- /trunk/Assembly_Library/Inc/Debug.inc	(revision 41)
+++ /trunk/Assembly_Library/Inc/Debug.inc	(revision 41)
@@ -0,0 +1,98 @@
+; File name		:	Debug.inc
+; Project name	:	Assembly Library
+; Created date	:	8.8.2010
+; Last update	:	8.8.2010
+; Author		:	Tomi Tilli
+; Description	:	Debugging macros.
+%ifndef DEBUG_INC
+%define DEBUG_INC
+
+
+;--------------------------------------------------------------------
+; DISPLAY_DEBUG_WORD_AND_WAIT_ANY_KEY
+;	Parameters:
+;		%1:		Debug word
+;		%2:		Numeric base (2, 10, 16)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro DISPLAY_DEBUG_WORD_AND_WAIT_ANY_KEY 2
+	push	di
+	push	bx
+	push	ax
+
+	mov		ax, %1
+	mov		bx, %2
+	CALL_DISPLAY_LIBRARY PrintWordFromAXwithBaseInBX
+	call	Keyboard_RemoveAllKeystrokesFromBuffer
+	call	Keyboard_GetKeystrokeToAXandWaitIfNecessary
+
+	pop		ax
+	pop		bx
+	pop		di
+%endmacro
+
+
+;--------------------------------------------------------------------
+; DISPLAY_DEBUG_CHARACTER_AND_WAIT_ANY_KEY
+;	Parameters:
+;		%1:		Character to print
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro DISPLAY_DEBUG_CHARACTER_AND_WAIT_ANY_KEY 1
+	push	di
+	push	ax
+
+	mov		al, %1
+	CALL_DISPLAY_LIBRARY PrintCharacterFromAL
+	call	Keyboard_RemoveAllKeystrokesFromBuffer
+	call	Keyboard_GetKeystrokeToAXandWaitIfNecessary
+
+	pop		ax
+	pop		di
+%endmacro
+
+
+;--------------------------------------------------------------------
+; DISPLAY_DEBUG_CHARACTER
+;	Parameters:
+;		%1:		Character to print
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro DISPLAY_DEBUG_CHARACTER 1
+	push	di
+	push	ax
+	mov		al, %1
+	CALL_DISPLAY_LIBRARY PrintCharacterFromAL
+	pop		ax
+	pop		di
+%endmacro
+
+
+;--------------------------------------------------------------------
+; WAIT_ANY_KEY_TO_CONTINUE
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro WAIT_ANY_KEY_TO_CONTINUE 0
+	push	ax
+	call	Keyboard_RemoveAllKeystrokesFromBuffer
+	call	Keyboard_GetKeystrokeToAXandWaitIfNecessary
+	pop		ax
+%endmacro
+
+
+
+%endif ; DEBUG_INC
Index: /trunk/Assembly_Library/Inc/Dialog.inc
===================================================================
--- /trunk/Assembly_Library/Inc/Dialog.inc	(revision 41)
+++ /trunk/Assembly_Library/Inc/Dialog.inc	(revision 41)
@@ -0,0 +1,89 @@
+; File name		:	Dialog.inc
+; Project name	:	Assembly Library
+; Created date	:	15.9.2010
+; Last update	:	15.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Defines for Menu library dialogs.
+%ifndef DIALOG_INC
+%define DIALOG_INC
+
+; Struct and defines for all dialogs
+struc DIALOG
+	.menu					resb	MENU_size
+	.fpDialogIO				resb	4	; Ptr to DIALOG_INPUT + dialog specific data
+	.pParentMenu			resb	2
+endstruc
+
+DIALOG_DELTA_WIDTH_FROM_PARENT		EQU		5
+DIALOG_MAX_WIDTH					EQU		60
+DIALOG_MAX_HEIGHT					EQU		25
+
+
+; Dialog parameter and return value structs
+struc DIALOG_INPUT
+	.fszTitle			resb	4
+	.fszItems			resb	4
+	.fszInfo			resb	4
+endstruc
+
+struc WORD_DIALOG_IO
+	.dialogInput		resb	DIALOG_INPUT_size
+	.bUserCancellation	resb	1
+	.bNumericBase		resb	1
+	.wMin				resb	2
+	.wMax				resb	2
+	.wReturnWord		resb	2
+endstruc
+
+struc STRING_DIALOG_IO
+	.dialogInput		resb	DIALOG_INPUT_size
+	.bUserCancellation	resb	1
+						resb	1
+	.fnCharFilter		resb	2	; Optional, can be NULL to accept all
+	.wBufferSize:
+	.wReturnLength		resb	2	; String length without NULL
+	.fpReturnBuffer		resb	4
+endstruc
+
+struc PROGRESS_DIALOG_IO
+	.dialogInput					resb	DIALOG_INPUT_size
+									resb	2
+	.wCurrentProgressValue			resb	2
+	.wMaxProgressValue				resb	2
+	.wMinProgressValue				resb	2
+	.fnTaskWithParamInDSSI			resb	2
+
+	; Progress Dialog internal values
+	.wProgressPerCharacter			resb	2
+	.wStartTimeTicks				resb	2
+endstruc
+
+struc FILE_DIALOG_IO
+	; DIALOG_INPUT adjusted for File Dialog
+	.fszTitle			resb	4
+	.fszItemBuffer		resb	4	; For generating file strings
+						resb	4
+
+	.bUserCancellation	resb	1
+						resb	1
+	.bDialogFlags		resb	1
+	.bFileAttributes	resb	1
+						resb	2
+	.fpFileFilterString:			; Ptr to NULL terminated search string (may include path and wildcards)
+	.szFile				resb	FILENAME_BUFFER_SIZE
+endstruc
+
+
+; File dialog
+FILENAME_BUFFER_SIZE				EQU		14	; 8+1+3+NULL+alignment
+MAX_FILE_DIALOG_INFO_LINES			EQU		3
+FLG_FILEDIALOG_DRIVES				EQU		(1<<0)	; Allow changing drive
+FLG_FILEDIALOG_DIRECTORY			EQU		(1<<1)	; Select directory instead of file
+FLG_FILEDIALOG_NEW					EQU		(1<<2)	; Allow creating new file or directory
+
+KEY_FILEDIALOG_CHANGE_DRIVE			EQU		3Ch		; F2
+KEY_FILEDIALOG_SELECT_DIRECTORY		EQU		3Dh		; F3
+KEY_FILEDIALOG_NEW_FILE_OR_DIR		EQU		3Eh		; F4
+
+
+%endif ; DIALOG_INC
Index: /trunk/Assembly_Library/Inc/Display.inc
===================================================================
--- /trunk/Assembly_Library/Inc/Display.inc	(revision 41)
+++ /trunk/Assembly_Library/Inc/Display.inc	(revision 41)
@@ -0,0 +1,207 @@
+; File name		:	Display.inc
+; Project name	:	AssemblyLibrary
+; Created date	:	25.6.2010
+; Last update	:	15.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Defines for display library.
+%ifndef DISPLAY_INC
+%define DISPLAY_INC
+
+;--------------------------------------------------------------------
+; Display Library users need to use this macro since it will provide
+; compatibility with future library versions.
+;
+; CALL_DISPLAY_LIBRARY
+;	Parameters:
+;		%1:			Function to call (functionName from DISPLAY_LIB)
+;		Registers:	Depends on function to call
+;	Returns:
+;		Depends on function to call
+;	Corrupts registers:
+;		AX (unless used as a return register), DI
+;--------------------------------------------------------------------
+%macro CALL_DISPLAY_LIBRARY 1
+	%ifidn %1, PushDisplayContext
+		call	DisplayContext_Push
+	%elifidn %1, PopDisplayContext
+		call	DisplayContext_Pop
+	%else
+		mov		di, DISPLAY_LIB.%1
+		call	Display_FunctionFromDI
+	%endif
+%endmacro
+
+
+; Display library functions
+struc DISPLAY_LIB
+	.PushDisplayContext:
+	.PopDisplayContext:
+	.InitializeDisplayContext					resb	2
+
+	.SetCharacterPointerFromBXAX				resb	2
+	.SetCharacterOutputFunctionFromAX			resb	2
+	.SetCharacterOutputParameterFromAX			resb	2
+	.SetCharacterAttributeFromAL				resb	2
+	.SetCursorShapeFromAX						resb	2
+	.SetCursorCoordinatesFromAX					resb	2
+	.SetNewPageFromAL							resb	2
+	.SynchronizeDisplayContextToHardware		resb	2
+
+	.GetCharacterPointerToBXAX					resb	2
+	.GetSoftwareCoordinatesToAX					resb	2
+	.GetColumnsToALandRowsToAH					resb	2
+
+	.FormatNullTerminatedStringFromCSSI			resb	2
+	.PrintSignedDecimalIntegerFromAX			resb	2
+	.PrintWordFromAXwithBaseInBX				resb	2
+	.PrintCharBufferFromBXSIwithLengthInCX		resb	2
+	.PrintNullTerminatedStringFromBXSI			resb	2
+	.PrintNullTerminatedStringFromCSSI			resb	2
+	.PrintRepeatedCharacterFromALwithCountInCX	resb	2
+	.PrintCharacterFromAL						resb	2
+	.PrintNewlineCharacters						resb	2
+	.ClearAreaWithHeightInAHandWidthInAL		resb	2
+	.ClearScreen								resb	2
+endstruc
+
+; Character output functions for DISPLAY_LIB.SetCharacterOutputFunctionFromAX
+TELETYPE_OUTPUT_WITH_ATTRIBUTE				EQU		DisplayCharOut_TeletypeOutputWithAttribute
+TELETYPE_OUTPUT_WITHOUT_ATTRIBUTE			EQU		DisplayCharOut_TeletypeOutput
+TELETYPE_OUTPUT_USING_BIOS					EQU		DisplayCharOut_BiosTeletypeOutput
+FAST_OUTPUT_WITH_ATTRIBUTE_ONLY				EQU		DisplayCharOut_Attribute
+FAST_OUTPUT_WITH_CHAR_ONLY					EQU		DisplayCharOut_Character
+FAST_OUTPUT_WITH_CHAR_AND_ATTRIBUTE			EQU		DisplayCharOut_CharacterWithAttribute
+BUFFER_OUTPUT_WITH_CHAR_ONLY				EQU		DisplayCharOut_WriteCharacterToBuffer
+
+DEFAULT_CHARACTER_OUTPUT					EQU		TELETYPE_OUTPUT_WITH_ATTRIBUTE
+
+
+struc VIDEO_BDA
+						resb	449h
+	.bMode				resb	1		; 0:449h, Video, Mode
+	.wColumns			resb	2		; 0:44Ah, Video, Number of columns
+	.wBytesPerPage		resb	2		; 0:44Ch, Video, Total number of bytes per page
+	.wPageOffset		resb	2		; 0:44Eh, Video, Current page offset
+	.rgwCursors			resb	4		; 0:450h, Video, Cursor position, pages 0...1
+	.displayContext		resb	12		; Our own display context (normally cursors for pages 2...7)
+	.wCursorShape		resb	2		; 0:460h, Video, Cursor shape
+	.bActivePage		resb	1		; 0:462h, Video, Active display page
+	.wVideoPort			resb	2		; 0:463h, Video, I/O Port number base
+	.bInternalModeReg	resb	1		; 0:465h, Video, Internal mode register
+	.bColorPalette		resb	1		; 0:466h, Video, Color palette
+endstruc
+
+struc DISPLAY_CONTEXT
+	.fpCursorPosition	resb	4	; Far pointer to cursor position in video memory
+	.fnCharOut			resb	2	; Function to draw character with
+	.wCharOutParam		resb	2	; User parameter for custom character output function
+	.wCursorShape		resb	2	; Current cursor shape
+	.bAttribute			resb	1	; Selected character attribute
+						resb	1
+endstruc
+
+
+; Text mode character attribute byte bits for CGA+ (color adapters)
+FLG_COLOR_FORE_BLUE			EQU		(1<<0)
+FLG_COLOR_FORE_GREEN		EQU		(1<<1)
+FLG_COLOR_FORE_RED			EQU		(1<<2)
+FLG_COLOR_FORE_INTENSITY	EQU		(1<<3)
+FLG_COLOR_FORE_FONT_B		EQU		(1<<3)	; Select font set B (if available, EGA+)
+FLG_COLOR_BACK_BLUE			EQU		(1<<4)
+FLG_COLOR_BACK_GREEN		EQU		(1<<5)
+FLG_COLOR_BACK_RED			EQU		(1<<6)
+FLG_COLOR_BACK_INTENSITY	EQU		(1<<7)	; Intensity when blinking is disabled
+FLG_COLOR_BLINK				EQU		(1<<7)	; Blinking color when enabled (enabled by default)
+
+; CGA colors
+%define COLOR_ATTRIBUTE(foreground, background)	( (foreground) | ((background)<<4) )
+COLOR_BLACK					EQU		0
+COLOR_BLUE					EQU		1
+COLOR_GREEN					EQU		2
+COLOR_CYAN					EQU		3
+COLOR_RED					EQU		4
+COLOR_MAGENTA				EQU		5
+COLOR_BROWN					EQU		6
+COLOR_WHITE					EQU		7		; Last background color if blinking enabled
+COLOR_GRAY					EQU		8
+COLOR_LIGHT_BLUE			EQU		9
+COLOR_LIGHT_GREEN			EQU		10
+COLOR_LIGHT_CYAN			EQU		11
+COLOR_LIGHT_RED				EQU		12
+COLOR_LIGHT_MAGENTA			EQU		13
+COLOR_YELLOW				EQU		14
+COLOR_BRIGHT_WHITE			EQU		15
+
+
+; Text mode character attribute byte bits for MDA (monochrome adapters)
+; (attributes 00h, 08h, 80h, 88h, 70h, 78h, F0h and F8h are exceptions)
+FLG_MONO_UNDERLINE			EQU		(1<<1)
+FLG_MONO_INTENSITY			EQU		(1<<3)
+FLG_MONO_BLINK				EQU		(1<<7)
+
+; Text mode character attribute bytes for MDA/Hercules (monochrome adapters)
+; *Not displayed on some monitors
+MONO_HIDDEN					EQU		00h		; Not displayed (same for 08h, 80h and 88h)
+MONO_UNDERLINE				EQU		01h		; Underlined
+MONO_NORMAL					EQU		07h		; Normal (white on black)
+MONO_BRIGHT_UNDERLINE		EQU		09h		; High intensity, underlined
+MONO_BRIGHT					EQU		0Fh		; High intensity
+MONO_REVERSE				EQU		70h		; Reverse video (black on white)
+MONO_REVERSE_DARK			EQU		78h		; (dark green on green)
+MONO_BLINK					EQU		87h		; Blinking white on black*
+MONO_BRIGHT_BLINK			EQU		8Fh		; Blinking high intensity*
+MONO_REVERSE_BLINK			EQU		0F0h	; Blinking reverse video
+MONO_REVERSE_DARK_BLINK		EQU		0F8h	; (blinking dark green on green)
+
+
+; Cursor position macro for DX register
+%define CURSOR_XY(x, y)	( (x) | ((y)<<8) )
+
+; Cursor shapes
+CURSOR_NORMAL				EQU		0607h		; Two line cursor near or at the bottom of cell
+CURSOR_HIDDEN				EQU		2000h
+
+
+; Display modes
+CGA_TEXT_MODE_BW40			EQU		0		; Applications should use...
+CGA_TEXT_MODE_CO40			EQU		1
+CGA_TEXT_MODE_BW80			EQU		2		; ..black, white and bright white attributes only
+CGA_TEXT_MODE_CO80			EQU		3
+MDA_TEXT_MODE				EQU		7		; Real monochrome attributes available
+
+
+; Display segments
+COLOR_TEXT_SEGMENT			EQU		0B800h	; Text modes 0...3 (CGA+)
+MONO_TEXT_SEGMENT			EQU		0B000h	; Text mode 7 (MDA, Hercules)
+
+
+; Control characters for teletype output
+NULL						EQU		00h
+SOH							EQU		01h		; Start of heading
+STX							EQU		02h		; Start of text
+BELL						EQU		07h		; Bell
+BS							EQU		08h		; Backspace
+TAB							EQU		09h		; Horizontal TAB
+LF							EQU		0Ah		; Line feed (newline)
+CR							EQU		0Dh		; Carriage return
+ESC							EQU		1Bh		; Escape
+
+; Non ASCII characters (code page 437)
+DOUBLE_TOP_RIGHT_CORNER						EQU		187
+DOUBLE_TOP_LEFT_CORNER						EQU		201
+DOUBLE_BOTTOM_RIGHT_CORNER					EQU		188
+DOUBLE_BOTTOM_LEFT_CORNER					EQU		200
+DOUBLE_VERTICAL								EQU		186
+DOUBLE_HORIZONTAL							EQU		205
+DOUBLE_VERTICAL_TO_RIGHT_SINGLE				EQU		199
+DOUBLE_VERTICAL_TO_LEFT_SINGLE				EQU		182
+DOUBLE_LEFT_HORIZONTAL_TO_SINGLE_VERTICAL	EQU		181
+DOUBLE_RIGHT_HORIZONTAL_TO_SINGLE_VERTICAL	EQU		198
+SINGLE_HORIZONTAL							EQU		196
+SINGLE_LEFT_HORIZONTAL_TO_VERTICAL			EQU		180
+SINGLE_RIGHT_HORIZONTAL_TO_VERTICAL			EQU		195
+ANGLE_QUOTE_LEFT							EQU		174
+ANGLE_QUOTE_RIGHT							EQU		175
+
+
+%endif ; DISPLAY_INC
Index: /trunk/Assembly_Library/Inc/DosFunctions.inc
===================================================================
--- /trunk/Assembly_Library/Inc/DosFunctions.inc	(revision 41)
+++ /trunk/Assembly_Library/Inc/DosFunctions.inc	(revision 41)
@@ -0,0 +1,79 @@
+; File name		:	DosFunctions.inc
+; Project name	:	AssemblyLibrary
+; Created date	:	1.9.2010
+; Last update	:	3.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Defines for MS-DOS functions.
+%ifndef DOS_FUNCTIONS_INC
+%define DOS_FUNCTIONS_INC
+
+; DOS interrupts
+DOS_INTERRUPT_21h									EQU		21h
+DOS_CRITICAL_ERROR_HANDLER_24h						EQU		24h
+
+; DOS file functions
+SELECT_DEFAULT_DRIVE								EQU		0Eh
+GET_CURRENT_DEFAULT_DRIVE							EQU		19h
+SET_INTERRUPT_VECTOR								EQU		25h
+GET_DISK_TRANSFER_AREA_ADDRESS						EQU		2Fh
+GET_DOS_DRIVE_PARAMETER_BLOCK_FOR_SPECIFIC_DRIVE	EQU		32h
+SET_CURRENT_DIRECTORY								EQU		3Bh
+OPEN_EXISTING_FILE									EQU		3Dh
+CLOSE_FILE											EQU		3Eh
+READ_FROM_FILE_OR_DEVICE							EQU		3Fh
+WRITE_TO_FILE_OR_DEVICE								EQU		40h
+SET_CURRENT_FILE_POSITION							EQU		42h
+GET_CURRENT_DIRECTORY								EQU		47h
+FIND_FIRST_MATCHING_FILE							EQU		4Eh
+FIND_NEXT_MATCHING_FILE								EQU		4Fh
+
+; DOS errors
+ERR_DOS_DRIVE_NOT_READY								EQU		15h
+
+
+; File attribute flags
+FLG_FILEATTR_READ_ONLY			EQU		(1<<0)
+FLG_FILEATTR_HIDDEN				EQU		(1<<1)
+FLG_FILEATTR_SYSTEM				EQU		(1<<2)
+FLG_FILEATTR_VOLUME_LABEL		EQU		(1<<3)
+FLG_FILEATTR_DIRECTORY			EQU		(1<<4)
+FLG_FILEATTR_ARCHIVE			EQU		(1<<5)
+
+
+
+; DOS Program Segment Prefix (PSP, first 256 (100h) bytes on top of program)
+struc PSP
+	.int20hInstruction				resb	2
+	.wSizeOfMemoryInParagraphs		resb	2
+	.reservedAt4h					resb	1
+	.callToDosFunctionDispatcher	resb	5
+	.fpInt22hTerminate				resb	4
+	.fpInt23hCtrlC					resb	4
+	.fpInt24hCriticalError			resb	4
+	.reservedAt16h					resb	22
+	.wEnvironmentSegment			resb	2
+	.reservedAt2Eh					resb	34
+	.int21hAndRetfInstructions		resb	3
+	.reservedAt53h					resb	9
+	.FCB1							resb	16
+	.FCB2							resb	20
+	.DiskTransferArea:
+	.bCommandLineLength				resb	1
+	.szCommandLine					resb	127
+endstruc
+
+
+; DOS DTA (Disk Transfer Area)
+struc DTA
+	; Undocumented fields
+	.reservedAt0h		resb	21
+	; Documented fields
+	.bFileAttributes	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
+
+
+%endif ; DOS_FUNCTIONS_INC
Index: /trunk/Assembly_Library/Inc/Emulate.inc
===================================================================
--- /trunk/Assembly_Library/Inc/Emulate.inc	(revision 41)
+++ /trunk/Assembly_Library/Inc/Emulate.inc	(revision 41)
@@ -0,0 +1,536 @@
+; File name		:	emulate.inc
+; Project name	:	Emulation library
+; Created date	:	21.10.2009
+; Last update	:	29.7.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
+
+
+;--------------------------------------------------------------------
+; Conditional Move.
+;
+; eCMOVcc
+;	Parameters:
+;		%1:		Destination data
+;		%2:		Source data
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro eCMOVC 2
+	jnc		SHORT %%Return
+	mov		%1, %2
+%%Return:
+%endmacro
+
+%macro eCMOVE 2
+	jne		SHORT %%Return
+	mov		%1, %2
+%%Return:
+%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
+		mov		al, %2
+		xor		ah, ah
+	%elifidni %1, bx
+		mov		bl, %2
+		xor		bh, bh		; %2 may use BX in effective address
+	%elifidni %1, cx
+		mov		cl, %2
+		xor		ch, ch
+	%elifidni %1, dx
+		mov		dl, %2
+		xor		dh, dh
+	%else	; SI, DI, BP (all may be used in effective address)
+		push	ax
+		mov		al, %2
+		xor		ah, ah
+		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, set to 0)
+;	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:
+;		BP:		What it was before eENTER
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro eLEAVE 0
+%ifndef USE_186
+	mov		sp, bp
+	pop		bp
+;-----------------------------------
+%else
+	leave
+%endif
+%endmacro
+
+
+;--------------------------------------------------------------------
+; eENTER_STRUCT
+;	Parameters:
+;		%1:		Number of bytes to reserve from stack
+;	Returns:
+;		SS:BP:	Ptr to beginning of struct reserved from stack
+;	Corrupts registers:
+;		FLAGS
+;--------------------------------------------------------------------
+%macro eENTER_STRUCT 1
+	push	bp
+	sub		sp, %1
+	mov		bp, sp
+	;eENTER	%1, 0
+	;sub		bp, %1			; SS:BP now points to struct
+%endmacro
+
+;--------------------------------------------------------------------
+; eLEAVE_STRUCT
+;	Parameters:
+;		%1:		Number of bytes reserved with eENTER_STRUCT
+;	Returns:
+;		BP:		What it was before eENTER_STRUCT
+;	Corrupts registers:
+;		FLAGS
+;--------------------------------------------------------------------
+%macro eLEAVE_STRUCT 1
+	add		sp, %1
+	pop		bp
+	;add		bp, %1			; Restore BP to what it was after eENTER
+	;eLEAVE
+%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: /trunk/Assembly_Library/Inc/Math.inc
===================================================================
--- /trunk/Assembly_Library/Inc/Math.inc	(revision 41)
+++ /trunk/Assembly_Library/Inc/Math.inc	(revision 41)
@@ -0,0 +1,70 @@
+; File name		:	Math.inc
+; Project name	:	Assembly Library
+; Created date	:	12.8.2010
+; Last update	:	12.8.2010
+; Author		:	Tomi Tilli
+; Description	:	Math related macros.
+%ifndef MATH_INC
+%define MATH_INC
+
+FALSE		EQU		0
+TRUE		EQU		1
+
+
+;--------------------------------------------------------------------
+; MIN_U		Unsigned comparison
+; MIN_S		Signed comparison
+;	Parameters:
+;		%1:		Operand 1
+;		%2:		Operand 2
+;	Returns:
+;		%1:		Lesser 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 MIN_S 2
+	cmp		%1, %2				; Is %1 smaller?
+	jl		%%Return			;  If so, return
+	mov		%1, %2				; Copy %2 to %1
+ALIGN JUMP_ALIGN
+%%Return:
+%endmacro
+
+
+;--------------------------------------------------------------------
+; MAX_U		Unsigned comparison
+; MAX_S		Signed comparison
+;	Parameters:
+;		%1:		Operand 1
+;		%2:		Operand 2
+;	Returns:
+;		%1:		Lesser 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 MAX_S 2
+	cmp		%1, %2				; Is %1 greater?
+	jg		%%Return			;  If so, return
+	mov		%1, %2				; Copy %2 to %1
+ALIGN JUMP_ALIGN
+%%Return:
+%endmacro
+
+
+%endif ; MATH_INC
Index: /trunk/Assembly_Library/Inc/Menu.inc
===================================================================
--- /trunk/Assembly_Library/Inc/Menu.inc	(revision 41)
+++ /trunk/Assembly_Library/Inc/Menu.inc	(revision 41)
@@ -0,0 +1,145 @@
+; File name		:	Menu.inc
+; Project name	:	Assembly Library
+; Created date	:	13.7.2010
+; Last update	:	15.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Defines for Menu library.
+%ifndef MENU_INC
+%define MENU_INC
+
+;--------------------------------------------------------------------
+; Menu Library users need to use this macro since it will provide
+; compatibility with future library versions.
+;
+; CALL_MENU_LIBRARY
+;	Parameters:
+;		%1:			Function to call (functionName from MENU_LIB)
+;		BP:			Menu handle
+;		Registers:	Depends on function to call
+;	Returns:
+;		Depends on function to call
+;	Corrupts registers:
+;		AX (unless used as a return register), DI
+;--------------------------------------------------------------------
+%macro CALL_MENU_LIBRARY 1
+	%ifidn %1, Close
+		call	MenuInit_CloseMenuWindow
+
+	%elifidn %1, SetUserDataFromDSSI
+		call	MenuInit_SetUserDataFromDSSI
+
+	%elifidn %1, GetUserDataToDSSI
+		call	MenuInit_GetUserDataToDSSI
+
+	%elifidn %1, SetTitleHeightFromAL
+		call	MenuInit_SetTitleHeightFromAL
+
+	%elifidn %1, SetTotalItemsFromAX
+		call	MenuInit_SetTotalItemsFromAX
+
+	%elifidn %1, SetInformationHeightFromAL
+		call	MenuInit_SetInformationHeightFromAL
+
+	%elifidn %1, SetTimeoutValueFromAX
+		call	MenuTime_SetSelectionTimeoutValueFromAX
+
+	%else
+		mov		di, MENU_LIB.%1
+		call	Menu_FunctionFromDI
+	%endif
+%endmacro
+
+; Menu library functions
+struc MENU_LIB
+	.DisplayWithHandlerInBXandUserDataInDXAX	resb	2
+	.Close:
+	.RefreshWindow								resb	2
+
+	.SetUserDataFromDSSI:
+	.GetUserDataToDSSI:
+
+	.SetTitleHeightFromAL:
+	.RefreshTitle								resb	2
+
+	.HighlightItemFromAX						resb	2
+	.SetTotalItemsFromAX:
+	.RefreshItemFromAX							resb	2
+
+	.SetInformationHeightFromAL:
+	.RefreshInformation							resb	2
+
+	.RestartTimeout								resb	2
+	.SetTimeoutValueFromAX:
+
+%ifdef INCLUDE_MENU_DIALOGS
+	.StartProgressTaskWithIoInDSSIandParamInDXAX	resb	2
+	.SetProgressValueFromAX							resb	2
+
+	.DisplayMessageWithInputInDSSI					resb	2
+	.GetSelectionToAXwithInputInDSSI				resb	2
+	.GetWordWithIoInDSSI							resb	2
+	.GetStringWithIoInDSSI							resb	2
+	.GetFileNameWithIoInDSSI						resb	2
+%endif
+endstruc
+
+
+; Menu initialization parameters
+struc MENUINIT
+	.wTimeoutTicks					resb	2	; Selection timeout in system timer ticks
+	.wItems							resb	2	; Number of items in menu
+
+	.wTitleAndInfoLines:
+	.bTitleLines					resb	1	; Number of title lines
+	.bInfoLines						resb	1	; Number of information lines
+
+	.wWidthAndHeight:
+	.bWidth							resb	1	; Menu width in characters
+	.bHeight						resb	1	; Menu height in characters
+endstruc
+
+
+; All menu parameters
+struc MENU
+	.menuInit						resb	MENUINIT_size	; Must be first
+	.fnEventHandler					resb	2	; Offset to Menu event handler
+	.dwUserData						resb	4	; User specified data
+
+	.bFlags							resb	1	; Menu flags
+	.bLastSecondPrinted				resb	1	; To minimize CGA snow when using timeouts
+	.wTimeoutCounter				resb	2
+
+	.wHighlightedItem				resb	2	; Index for highlighted item
+	.wFirstVisibleItem				resb	2	; Index for first visible item on the menu
+endstruc
+
+; Flags for MENU.wFlags
+FLG_MENU_EXIT						EQU		(1<<0)	; Close and exit menu
+FLG_MENU_NOHIGHLIGHT				EQU		(1<<1)	; Never highlight items
+FLG_MENU_USER_HANDLES_SCROLLING		EQU		(1<<2)
+
+
+MENU_VERTICAL_BORDER_LINES			EQU		5	; Title top and bottom + Info top and bottom + bottom shadow
+MENU_HORIZONTAL_BORDER_LINES		EQU		3	; Left + Right borders + Right shadow
+MENU_TEXT_ROW_OFFSET				EQU		1
+MENU_TEXT_COLUMN_OFFSET				EQU		2
+
+SCROLL_TRACK_CHARACTER				EQU		176
+SCROLL_THUMB_CHARACTER				EQU		219
+
+NO_ITEM_SELECTED					EQU		-1
+NO_ITEM_HIGHLIGHTED					EQU		-1
+
+
+; Keyboard keys (scan codes) used by menu library
+MENU_KEY_ENTER		EQU		1Ch
+MENU_KEY_ESC		EQU		01h
+MENU_KEY_UP			EQU		48h
+MENU_KEY_DOWN		EQU		50h
+MENU_KEY_PGUP		EQU		49h
+MENU_KEY_PGDN		EQU		51h
+MENU_KEY_HOME		EQU		47h
+MENU_KEY_END		EQU		4Fh
+
+
+%endif ; MENU_INC
Index: /trunk/Assembly_Library/Inc/MenuEvents.inc
===================================================================
--- /trunk/Assembly_Library/Inc/MenuEvents.inc	(revision 41)
+++ /trunk/Assembly_Library/Inc/MenuEvents.inc	(revision 41)
@@ -0,0 +1,62 @@
+; File name		:	MenuEvents.inc
+; Project name	:	Assembly Library
+; Created date	:	13.7.2010
+; Last update	:	11.8.2010
+; Author		:	Tomi Tilli
+; Description	:	Defines for Menu events send to the user.
+%ifndef MENUEVENTS_INC
+%define MENUEVENTS_INC
+
+;--------------------------------------------------------------------
+; Events to be processed in user implemented handler.
+;	Common parameters for all events:
+;		BX:			Menu event (anything from MENUEVENT struct)
+;		SS:BP:		Menu library handle
+;	Common return values for all events:
+;		CF:			Set if event processed
+;					Cleared if event not processed
+;	Corrupts registers:
+;		All
+;--------------------------------------------------------------------
+struc MENUEVENT
+	; Parameters:
+	;	DS:SI:		Ptr to MENUINIT struct to initialize
+	; Returns:
+	;	DS:SI:		Ptr to initialized MENUINIT struct
+	.InitializeMenuinitFromDSSI		resb	2
+
+	; Parameters:
+	;	None
+	.ExitMenu						resb	2
+
+	; Parameters:
+	;	None
+	.IdleProcessing					resb	2
+
+	; Parameters:
+	;	CX:			Index of new highlighted item
+	;	DX:			Index of previously highlighted item or NO_ITEM_HIGHLIGHTED
+	.ItemHighlightedFromCX			resb	2
+
+	; Parameters:
+	;	CX:			Index of selected item
+	.ItemSelectedFromCX				resb	2
+
+	; Parameters:
+	;	AL:			ASCII character for the key
+	;	AH:			Keyboard library scan code for the key
+	.KeyStrokeInAX					resb	2
+
+	; Parameters:
+	;	None but cursor has been positioned to the beginning of first line
+	.RefreshTitle					resb	2
+	.RefreshInformation				resb	2
+
+	; Parameters:
+	;	CX:			Index of item to refresh
+	;	Cursor has been positioned to the beginning of item line
+	.RefreshItemFromCX				resb	2
+endstruc
+
+
+%endif ; MENUEVENTS_INC
Index: /trunk/Assembly_Library/Src/AssemblyLibrary.asm
===================================================================
--- /trunk/Assembly_Library/Src/AssemblyLibrary.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/AssemblyLibrary.asm	(revision 41)
@@ -0,0 +1,73 @@
+; File name		:	AssemblyLibrary.asm
+; Project name	:	Assembly Library
+; Created date	:	15.9.2010
+; Last update	:	15.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Assembly Library main file. This is the only file that
+;					needs to be included.
+
+; Section containing code
+SECTION .text
+
+%ifdef INCLUDE_DISPLAY_LIBRARY
+	%include "Display.asm"
+	%include "DisplayCharOut.asm"
+	%include "DisplayContext.asm"
+	%include "DisplayCursor.asm"
+	%include "DisplayFormat.asm"
+	%include "DisplayPage.asm"
+	%include "DisplayPrint.asm"
+%endif
+
+%ifdef INCLUDE_FILE_LIBRARY
+	%include "Directory.asm"
+	%include "DosCritical.asm"
+	%include "Drive.asm"
+	%include "FileIO.asm"
+%endif
+
+%ifdef INCLUDE_KEYBOARD_LIBRARY
+	%include "Keyboard.asm"
+%endif
+
+%ifdef INCLUDE_MENU_LIBRARY
+	%include "Menu.asm"
+	%include "MenuAttributes.asm"
+	%include "MenuBorders.asm"
+	%include "MenuCharOut.asm"
+	%include "MenuEvent.asm"
+	%include "MenuInit.asm"
+	%include "MenuLocation.asm"
+	%include "MenuLoop.asm"
+	%include "MenuScrollbars.asm"
+	%include "MenuText.asm"
+	%include "MenuTime.asm"
+
+	%ifdef INCLUDE_MENU_DIALOGS
+		%include "Dialog.asm"
+		%include "DialogFile.asm"
+		%include "DialogMessage.asm"
+		%include "DialogProgress.asm"
+		%include "DialogSelection.asm"
+		%include "DialogString.asm"
+		%include "DialogWord.asm"
+		%include "LineSplitter.asm"
+		%include "StringsForDialogs.asm"
+	%endif
+%endif
+
+%ifdef INCLUDE_STRING_LIBRARY
+	%include "Char.asm"
+	%include "String.asm"
+%endif
+
+%ifdef INCLUDE_TIME_LIBRARY
+	%include "Delay.asm"
+	%include "TimerTicks.asm"
+%endif
+
+%ifdef INCLUDE_UTIL_LIBRARY
+	%include "Bit.asm"
+	%include "Memory.asm"
+	%include "Size.asm"
+%endif
Index: /trunk/Assembly_Library/Src/Display/Display.asm
===================================================================
--- /trunk/Assembly_Library/Src/Display/Display.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Display/Display.asm	(revision 41)
@@ -0,0 +1,93 @@
+; File name		:	Display.asm
+; Project name	:	Assembly Library
+; Created date	:	2.7.2010
+; Last update	:	13.8.2010
+; Author		:	Tomi Tilli
+; Description	:	Display Library functions for CALL_DISPLAY_LIBRARY macro
+;					that users should use to make library call.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; DisplayFunctionFromDI
+;	Parameters:
+;		DI:		Function to call (DISPLAY_LIB.functionName)
+;		Others:	Depends on function to call (DX cannot be parameter)
+;	Returns:
+;		Depends on function to call
+;	Corrupts registers:
+;		AX (unless used as a return register), DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Display_FunctionFromDI:
+	push	es
+	push	ds
+	push	dx
+
+	cld
+	LOAD_BDA_SEGMENT_TO	ds, dx
+	mov		dx, [cs:di+.rgfnDisplayLibraryFunctions]
+	les		di, [VIDEO_BDA.displayContext+DISPLAY_CONTEXT.fpCursorPosition]
+	call	dx
+	mov		[VIDEO_BDA.displayContext+DISPLAY_CONTEXT.fpCursorPosition], di
+
+	pop		dx
+	pop		ds
+	pop		es
+	ret
+
+;--------------------------------------------------------------------
+; .FormatNullTerminatedStringFromCSSI
+;	Parameters:
+;		Same as DisplayPrint_FormattedNullTerminatedStringFromCSSI
+;	Returns:
+;		Stack variables will be cleaned
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.FormatNullTerminatedStringFromCSSI:
+	pop		ax					; Discard return address to inside DisplayFunctionFromDI
+	call	DisplayPrint_FormattedNullTerminatedStringFromCSSI
+	mov		[VIDEO_BDA.displayContext+DISPLAY_CONTEXT.fpCursorPosition], di
+
+	pop		dx
+	pop		ds
+	pop		es
+
+	pop		ax					; Pop return address
+	mov		sp, bp				; Clean stack variables
+	jmp		ax
+
+
+ALIGN WORD_ALIGN
+.rgfnDisplayLibraryFunctions:
+istruc DISPLAY_LIB
+	at	DISPLAY_LIB.InitializeDisplayContext,					dw	DisplayContext_Initialize
+
+	at	DISPLAY_LIB.SetCharacterPointerFromBXAX,				dw	DisplayContext_SetCharacterPointerFromBXAX
+	at	DISPLAY_LIB.SetCharacterOutputFunctionFromAX,			dw	DisplayContext_SetCharacterOutputFunctionFromAX
+	at	DISPLAY_LIB.SetCharacterOutputParameterFromAX,			dw	DisplayContext_SetCharacterOutputParameterFromAX
+	at	DISPLAY_LIB.SetCharacterAttributeFromAL,				dw	DisplayContext_SetCharacterAttributeFromAL
+	at	DISPLAY_LIB.SetCursorShapeFromAX,						dw	DisplayCursor_SetShapeFromAX
+	at	DISPLAY_LIB.SetCursorCoordinatesFromAX,					dw	DisplayCursor_SetCoordinatesFromAX
+	at	DISPLAY_LIB.SetNewPageFromAL,							dw	DisplayPage_SetFromAL
+	at	DISPLAY_LIB.SynchronizeDisplayContextToHardware,		dw	DisplayContext_SynchronizeToHardware
+
+	at	DISPLAY_LIB.GetCharacterPointerToBXAX,					dw	DisplayContext_GetCharacterPointerToBXAX
+	at	DISPLAY_LIB.GetSoftwareCoordinatesToAX,					dw	DisplayCursor_GetSoftwareCoordinatesToAX
+	at	DISPLAY_LIB.GetColumnsToALandRowsToAH,					dw	DisplayPage_GetColumnsToALandRowsToAH
+
+	at	DISPLAY_LIB.FormatNullTerminatedStringFromCSSI,			dw	.FormatNullTerminatedStringFromCSSI
+	at	DISPLAY_LIB.PrintSignedDecimalIntegerFromAX,			dw	DisplayPrint_SignedDecimalIntegerFromAX
+	at	DISPLAY_LIB.PrintWordFromAXwithBaseInBX,				dw	DisplayPrint_WordFromAXWithBaseInBX
+	at	DISPLAY_LIB.PrintCharBufferFromBXSIwithLengthInCX,		dw	DisplayPrint_CharacterBufferFromBXSIwithLengthInCX
+	at	DISPLAY_LIB.PrintNullTerminatedStringFromBXSI,			dw	DisplayPrint_NullTerminatedStringFromBXSI
+	at	DISPLAY_LIB.PrintNullTerminatedStringFromCSSI,			dw	DisplayPrint_NullTerminatedStringFromCSSI
+	at	DISPLAY_LIB.PrintRepeatedCharacterFromALwithCountInCX,	dw	DisplayPrint_RepeatCharacterFromALwithCountInCX
+	at	DISPLAY_LIB.PrintCharacterFromAL,						dw	DisplayPrint_CharacterFromAL
+	at	DISPLAY_LIB.PrintNewlineCharacters,						dw	DisplayPrint_Newline
+	at	DISPLAY_LIB.ClearAreaWithHeightInAHandWidthInAL,		dw	DisplayPrint_ClearAreaWithHeightInAHandWidthInAL
+	at	DISPLAY_LIB.ClearScreen,								dw	DisplayPrint_ClearScreen
+iend
Index: /trunk/Assembly_Library/Src/Display/DisplayCharOut.asm
===================================================================
--- /trunk/Assembly_Library/Src/Display/DisplayCharOut.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Display/DisplayCharOut.asm	(revision 41)
@@ -0,0 +1,130 @@
+; File name		:	DisplayCharOut.asm
+; Project name	:	Assembly Library
+; Created date	:	26.6.2010
+; Last update	:	13.8.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for outputting characters to video memory.
+;					These functions are meant to be called by Display_CharacterFromAL
+;					and Display_RepeatCharacterFromAL using function pointer
+;					stored in DISPLAY_CONTEXT.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; DisplayCharOut_TeletypeOutputWithAttribute
+; DisplayCharOut_TeletypeOutput
+;	Parameters:
+;		AL:		Character to output
+;		AH:		Attribute to output
+;		DS:		BDA segment (zero)
+;		ES:DI:	Ptr to video memory where to output
+;	Returns:
+;		DI:		Incremented for next character
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayCharOut_TeletypeOutputWithAttribute:
+	cmp		al, ' '							; Printable character?
+	jb		SHORT DisplayCharOut_BiosTeletypeOutput
+	stosw
+	ret
+
+ALIGN JUMP_ALIGN
+DisplayCharOut_TeletypeOutput:
+	cmp		al, ' '							; Printable character?
+	jae		SHORT DisplayCharOut_Character
+	; Fall to DisplayCharOut_BiosTeletypeOutput
+
+;--------------------------------------------------------------------
+; DisplayCharOut_BiosTeletypeOutput
+;	Parameters:
+;		AL:		Control character
+;		DS:		BDA segment (zero)
+;		ES:DI:	Ptr to video memory where to output
+;	Returns:
+;		DI:		Incremented for next character
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayCharOut_BiosTeletypeOutput:
+	push	ax
+	call	DisplayCursor_SynchronizeCoordinatesToHardware
+	pop		ax
+	call	.OutputCharacterWithBIOS
+	call	DisplayCursor_GetHardwareCoordinatesToAX
+	jmp		DisplayCursor_SetCoordinatesFromAX
+
+;--------------------------------------------------------------------
+; .OutputCharacterWithBIOS
+;	Parameters:
+;		AL:		Character to output
+;		DS:		BDA segment
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.OutputCharacterWithBIOS:
+	push	bx
+	mov		ah, TELETYPE_OUTPUT
+	mov		bh, [VIDEO_BDA.bActivePage]
+	int		BIOS_VIDEO_INTERRUPT_10h
+	pop		bx
+	ret
+
+
+;--------------------------------------------------------------------
+; DisplayCharOut_Attribute
+; DisplayCharOut_Character
+; DisplayCharOut_CharacterWithAttribute
+;	Parameters:
+;		AL:		Character to output
+;		AH:		Attribute to output
+;		ES:DI:	Ptr to video memory where to output
+;	Returns:
+;		DI:		Incremented for next character
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayCharOut_Attribute:
+	xchg	al, ah				; Swap character and attribute
+	inc		di					; Skip character
+	stosb
+	ret
+
+ALIGN JUMP_ALIGN
+DisplayCharOut_Character:
+	stosb
+	inc		di					; Skip attribute
+	ret
+
+ALIGN JUMP_ALIGN
+DisplayCharOut_CharacterWithAttribute:
+	stosw
+	ret
+
+
+;--------------------------------------------------------------------
+; DisplayCharOut_WriteCharacterToBuffer
+;	Parameters:
+;		AL:		Character to output
+;		DS:		BDA segment (zero)
+;		ES:DI:	Ptr to destination string buffer
+;		DISPLAY_CONTEXT.wCharOutParam:	Offset to end of buffer (one past last)
+;	Returns:
+;		ES:DI:	Updated for next character
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayCharOut_WriteCharacterToBuffer:
+	cmp		di, [VIDEO_BDA.displayContext+DISPLAY_CONTEXT.wCharOutParam]
+	jae		SHORT .BufferFull
+	stosb
+.BufferFull:
+	ret
Index: /trunk/Assembly_Library/Src/Display/DisplayContext.asm
===================================================================
--- /trunk/Assembly_Library/Src/Display/DisplayContext.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Display/DisplayContext.asm	(revision 41)
@@ -0,0 +1,212 @@
+; File name		:	DisplayContext.asm
+; Project name	:	Assembly Library
+; Created date	:	25.6.2010
+; Last update	:	13.8.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for managing display context.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; DisplayContext_Initialize
+;	Parameters:
+;		DS:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DX, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayContext_Initialize:
+	call	.DetectAndSetDisplaySegment
+	mov		WORD [VIDEO_BDA.displayContext+DISPLAY_CONTEXT.fnCharOut], DEFAULT_CHARACTER_OUTPUT
+	mov		WORD [VIDEO_BDA.displayContext+DISPLAY_CONTEXT.wCursorShape], CURSOR_NORMAL
+	mov		BYTE [VIDEO_BDA.displayContext+DISPLAY_CONTEXT.bAttribute], MONO_NORMAL
+
+	xor		ax, ax
+	call	DisplayCursor_SetCoordinatesFromAX
+	jmp		SHORT DisplayContext_SynchronizeToHardware
+
+;--------------------------------------------------------------------
+; .DetectAndSetDisplaySegment
+;	Parameters:
+;		DS:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+.DetectAndSetDisplaySegment:
+	mov		WORD [VIDEO_BDA.displayContext+DISPLAY_CONTEXT.fpCursorPosition+2], COLOR_TEXT_SEGMENT
+	cmp		BYTE [VIDEO_BDA.bMode], MDA_TEXT_MODE
+	jne		SHORT .Return
+	sub		WORD [VIDEO_BDA.displayContext+DISPLAY_CONTEXT.fpCursorPosition+2], COLOR_TEXT_SEGMENT - MONO_TEXT_SEGMENT
+.Return:
+	ret
+
+
+;--------------------------------------------------------------------
+; DisplayContext_Push
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayContext_Push:
+	mov		di, ds					; Backup DS
+	LOAD_BDA_SEGMENT_TO	ds, ax
+	pop		ax						; Pop return address
+
+	%assign i 0
+	%rep DISPLAY_CONTEXT_size / 2
+		push	WORD [VIDEO_BDA.displayContext + i]
+	%assign i i+2
+	%endrep
+
+	mov		ds, di					; Restore DS
+	jmp		ax
+
+;--------------------------------------------------------------------
+; DisplayContext_Pop
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayContext_Pop:
+	mov		di, ds					; Backup DS
+	LOAD_BDA_SEGMENT_TO	ds, ax
+	pop		ax						; Pop return address
+
+	%assign i DISPLAY_CONTEXT_size-2
+	%rep DISPLAY_CONTEXT_size / 2
+		pop		WORD [VIDEO_BDA.displayContext + i]
+	%assign i i-2
+	%endrep
+
+	push	ax						; Push return address
+	push	dx
+	call	DisplayContext_SynchronizeToHardware
+	pop		dx
+	mov		ds, di					; Restore DS
+	ret
+
+
+;--------------------------------------------------------------------
+; DisplayContext_SynchronizeToHardware
+;	Parameters:
+;		DS:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayContext_SynchronizeToHardware:
+	call	DisplayPage_SynchronizeToHardware
+	call	DisplayCursor_SynchronizeShapeToHardware
+	jmp		DisplayCursor_SynchronizeCoordinatesToHardware
+
+
+;--------------------------------------------------------------------
+; DisplayContext_SetCharacterPointerFromBXAX
+;	Parameters:
+;		BX:AX:	Ptr to destination for next character to output
+;		DS:		BDA segment (zero)
+;	Returns:
+;		ES:DI:	Pointer that was in DX:AX
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayContext_SetCharacterPointerFromBXAX:
+	mov		[VIDEO_BDA.displayContext+DISPLAY_CONTEXT.fpCursorPosition], ax
+	mov		[VIDEO_BDA.displayContext+DISPLAY_CONTEXT.fpCursorPosition+2], bx
+	xchg	di, ax
+	mov		es, bx
+	ret
+
+
+;--------------------------------------------------------------------
+; DisplayContext_GetCharacterPointerToBXAX
+;	Parameters:
+;		DS:		BDA segment (zero)
+;	Returns:
+;		BX:AX:	Ptr to destination for next character to output
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayContext_GetCharacterPointerToBXAX:
+	mov		ax, [VIDEO_BDA.displayContext+DISPLAY_CONTEXT.fpCursorPosition]
+	mov		bx, [VIDEO_BDA.displayContext+DISPLAY_CONTEXT.fpCursorPosition+2]
+	ret
+
+
+;--------------------------------------------------------------------
+; DisplayContext_SetCharacterOutputFunctionFromAX
+;	Parameters:
+;		AX:		Offset to character output function
+;		DS:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayContext_SetCharacterOutputFunctionFromAX:
+	mov		[VIDEO_BDA.displayContext+DISPLAY_CONTEXT.fnCharOut], ax
+	ret
+
+
+;--------------------------------------------------------------------
+; DisplayContext_SetCharacterAttributeFromAL
+;	Parameters:
+;		AL:		Character attribute
+;		DS:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayContext_SetCharacterAttributeFromAL:
+	mov		[VIDEO_BDA.displayContext+DISPLAY_CONTEXT.bAttribute], al
+	ret
+
+
+;--------------------------------------------------------------------
+; DisplayContext_SetCharacterOutputParameterFromAX
+;	Parameters:
+;		AX:		Parameter for Character Output function
+;		DS:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayContext_SetCharacterOutputParameterFromAX:
+	mov		[VIDEO_BDA.displayContext+DISPLAY_CONTEXT.wCharOutParam], ax
+	ret
+
+;--------------------------------------------------------------------
+; DisplayContext_GetCharacterOutputParameterToDX
+;	Parameters:
+;		DS:		BDA segment (zero)
+;	Returns:
+;		DX:		User parameter for Character Output function
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------	
+ALIGN JUMP_ALIGN
+DisplayContext_GetCharacterOutputParameterToDX:
+	mov		dx, [VIDEO_BDA.displayContext+DISPLAY_CONTEXT.wCharOutParam]
+	ret
Index: /trunk/Assembly_Library/Src/Display/DisplayCursor.asm
===================================================================
--- /trunk/Assembly_Library/Src/Display/DisplayCursor.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Display/DisplayCursor.asm	(revision 41)
@@ -0,0 +1,185 @@
+; File name		:	DisplayCursor.asm
+; Project name	:	Assembly Library
+; Created date	:	26.6.2010
+; Last update	:	15.7.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for managing display cursor.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; DisplayCursor_SetShapeFromAX
+;	Parameters:
+;		AX:		Cursor shape (AH=Start scan line, AL=End scan line)
+;		DS:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayCursor_SetShapeFromAX:
+	mov		[VIDEO_BDA.displayContext+DISPLAY_CONTEXT.wCursorShape], ax
+	ret
+
+
+;--------------------------------------------------------------------
+; DisplayCursor_SetCoordinatesFromAX
+;	Parameters:
+;		AL:		Cursor column (X-coordinate)
+;		AH:		Cursor row (Y-coordinate)
+;		DS:		BDA segment (zero)
+;	Returns:
+;		DI:		Offset to cursor location in video RAM
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayCursor_SetCoordinatesFromAX:
+	xchg	dx, ax
+	call	.ConvertOffsetToAXfromCoordinatesInDX
+	add		ax, [VIDEO_BDA.wPageOffset]				; AX = Video RAM offset
+	mov		[VIDEO_BDA.displayContext+DISPLAY_CONTEXT.fpCursorPosition], ax
+	xchg	di, ax
+	ret
+
+;--------------------------------------------------------------------
+; .ConvertOffsetToAXfromCoordinatesInDX
+;	Parameters:
+;		DL:		Cursor column (X-coordinate)
+;		DH:		Cursor row (Y-coordinate)
+;		DS:		BDA segment (zero)
+;	Returns:
+;		AX:		Offset to cursor location in selected page
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.ConvertOffsetToAXfromCoordinatesInDX:
+	mov		ax, [VIDEO_BDA.wColumns]		; Column count, 40 or 80
+	mul		dh								; AX = Column count * row index
+	add		al, dl							; Add column offset
+	adc		ah, 0
+	shl		ax, 1							; Convert to WORD offset
+	ret
+
+
+;--------------------------------------------------------------------
+; DisplayCursor_GetSoftwareCoordinatesToAX
+;	Parameters:
+;		AX:		Offset to cursor location in selected page
+;		DS:		BDA segment (zero)
+;	Returns:
+;		AL:		Cursor column (X-coordinate)
+;		AH:		Cursor row (Y-coordinate)
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayCursor_GetSoftwareCoordinatesToAX:
+	mov		ax, [VIDEO_BDA.displayContext+DISPLAY_CONTEXT.fpCursorPosition]
+	sub		ax, [VIDEO_BDA.wPageOffset]
+	shr		ax, 1							; WORD offset to character offset
+	div		BYTE [VIDEO_BDA.wColumns]		; AL = full rows, AH = column index for last row
+	xchg	al, ah
+	ret
+
+
+;--------------------------------------------------------------------
+; DisplayCursor_GetHardwareCoordinatesToAX
+;	Parameters:
+;		DS:		BDA segment (zero)
+;	Returns:
+;		AL:		Hardware cursor column (X-coordinate)
+;		AH:		Hardware cursor row (Y-coordinate)
+;	Corrupts registers:
+;		DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayCursor_GetHardwareCoordinatesToAX:
+	push	cx
+	push	bx
+
+	mov		ah, GET_CURSOR_POSITION_AND_SIZE
+	mov		bh, [VIDEO_BDA.bActivePage]
+	int		BIOS_VIDEO_INTERRUPT_10h
+	xchg	ax, dx
+
+	pop		bx
+	pop		cx
+	ret
+
+
+;--------------------------------------------------------------------
+; DisplayCursor_SynchronizeShapeToHardware
+;	Parameters:
+;		DS:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayCursor_SynchronizeShapeToHardware:
+	mov		dx, [VIDEO_BDA.displayContext+DISPLAY_CONTEXT.wCursorShape]
+	; Fall to .SetHardwareCursorShapeFromDX
+
+;--------------------------------------------------------------------
+; .SetHardwareCursorShapeFromDX
+;	Parameters:
+;		DX:		Cursor shape
+;		DS:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+.SetHardwareCursorShapeFromDX:
+	cmp		dx, [VIDEO_BDA.wCursorShape]
+	je		SHORT .Return					; Return if no changes
+	push	cx
+	mov		cx, dx							; BIOS wants cursor shape in CX
+	mov		al, [VIDEO_BDA.bMode]			; Load video mode to prevent lock ups on some BIOSes
+	mov		ah, SET_TEXT_MODE_CURSOR_SHAPE
+	int		BIOS_VIDEO_INTERRUPT_10h
+	pop		cx
+ALIGN JUMP_ALIGN, ret
+.Return:
+	ret
+
+
+;--------------------------------------------------------------------
+; DisplayCursor_SynchronizeCoordinatesToHardware
+;	Parameters:
+;		DS:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayCursor_SynchronizeCoordinatesToHardware:
+	call	DisplayCursor_GetSoftwareCoordinatesToAX
+	; Fall to .SetHardwareCursorCoordinatesFromAX
+
+;--------------------------------------------------------------------
+; .SetHardwareCursorCoordinatesFromAX
+;	Parameters:
+;		AL:		Cursor column (X-coordinate)
+;		AH:		Cursor row (Y-coordinate)
+;		DS:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+;ALIGN JUMP_ALIGN
+.SetHardwareCursorCoordinatesFromAX:
+	push	bx
+	xchg	dx, ax							; BIOS wants coordinates in DX
+	mov		ah, SET_CURSOR_POSITION
+	mov		bh, [VIDEO_BDA.bActivePage]
+	int		BIOS_VIDEO_INTERRUPT_10h
+	pop		bx
+	ret
Index: /trunk/Assembly_Library/Src/Display/DisplayFormat.asm
===================================================================
--- /trunk/Assembly_Library/Src/Display/DisplayFormat.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Display/DisplayFormat.asm	(revision 41)
@@ -0,0 +1,293 @@
+; File name		:	DisplayFormat.asm
+; Project name	:	Assembly Library
+; Created date	:	29.6.2010
+; Last update	:	10.8.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for displaying formatted strings.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; DisplayFormat_ParseCharacters
+;	Parameters:
+;		DS:		BDA segment (zero)
+;		SS:BP:	Pointer to first format parameter (-=2 for next parameter)
+;		CS:SI:	Pointer to string to format
+;		ES:DI:	Ptr to cursor location in video RAM
+;	Returns:
+;		DI:		Updated offset to video RAM
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, BP
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayFormat_ParseCharacters:
+	call	.ReadCharacterAndTestForNull
+	jz		SHORT .Return
+	xor		cx, cx							; Zero CX for parsing number parameter
+	cmp		al, '%'
+	je		SHORT .FormatParameterEncountered
+	call	DisplayPrint_CharacterFromAL	; Control or printable character
+	jmp		SHORT DisplayFormat_ParseCharacters
+ALIGN JUMP_ALIGN
+.Return:
+	ret
+
+;--------------------------------------------------------------------
+; .ReadCharacterAndTestForNull
+;	Parameters:
+;		CS:SI:	Pointer next character from string
+;	Returns:
+;		AL:		Character from string
+;		SI:		Incremented to next character
+;		ZF:		Set if NULL, cleared if valid character
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.ReadCharacterAndTestForNull:
+	eSEG	cs
+	lodsb									; Load from CS:SI to AL
+	test	al, al							; NULL to end string?
+	ret
+
+
+;--------------------------------------------------------------------
+; .FormatParameterEncountered
+;	Parameters:
+;		CX:		Zero or previous number parameter
+;		DS:		BDA segment (zero)
+;		SS:BP:	Pointer to next format parameter
+;		CS:SI:	Pointer to next format string character
+;		ES:DI:	Ptr to cursor location in video RAM
+;	Returns:
+;		SI:		Incremented to next character
+;		BP:		Offset to next format parameter
+;		Eventually jumps to DisplayFormat_ParseCharacters
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.FormatParameterEncountered:
+	call	.ReadCharacterAndTestForNull
+	jz		SHORT .Return
+	call	Char_IsDecimalDigitInAL
+	jnc		SHORT .FormatWithCorrectFormatFunction
+	; Fall to .ParseNumberParameterToCX
+
+;--------------------------------------------------------------------
+; .ParseNumberParameterToCX
+;	Parameters:
+;		AL:		Number digit from format string
+;		CX:		Zero or previous number parameter
+;	Returns:
+;		CX:		Updated number parameter
+;		Jumps to .FormatParameterEncountered
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+.ParseNumberParameterToCX:
+	sub		al, '0'				; Digit '0'...'9' to integer 0...9
+	mov		ah, cl				; Previous number parameter to AH
+	aad							; AL += (AH * 10)
+	mov		cl, al				; Updated number parameter now in CX
+	jmp		SHORT .FormatParameterEncountered
+
+;--------------------------------------------------------------------
+; .FormatWithCorrectFormatFunction
+;	Parameters:
+;		AL:		Format placeholder character (non digit character after '%')
+;		CX:		Number parameter (zero if no number parameter present)
+;		DS:		BDA segment (zero)
+;		SS:BP:	Pointer to format parameter
+;		CS:SI:	Pointer to next format string character
+;		ES:DI:	Ptr to cursor location in video RAM
+;	Returns:
+;		Eventually jumps to DisplayFormat_ParseCharacters
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.FormatWithCorrectFormatFunction:
+	xor		bx, bx								; Zero lookup index
+ALIGN JUMP_ALIGN
+.PlaceholderComparisonLoop:
+	cmp		al, [cs:bx+.rgcFormatCharToLookupIndex]
+	je		SHORT .JumpToFormatPlaceholder
+	inc		bx
+	cmp		bl, .EndOFrgcFormatCharToLookupIndex - .rgcFormatCharToLookupIndex
+	jb		SHORT .PlaceholderComparisonLoop	; Loop
+	call	DisplayPrint_CharacterFromAL		; Display unsupported format character
+	; Fall to .UpdateSpacesToAppendAfterPrintingSingleCharacter
+
+;--------------------------------------------------------------------
+; .UpdateSpacesToAppendAfterPrintingSingleCharacter
+; .UpdateSpacesToAppend
+;	Parameters:
+;		BX:		Number of characters printed (.UpdateSpacesToAppend only)
+;		CX:		Number parameter (zero if no number parameter present)
+;		DS:		BDA segment (zero)
+;		SS:BP:	Pointer to format parameter
+;		CS:SI:	Pointer to next format string character
+;		ES:DI:	Ptr to cursor location in video RAM
+;	Returns:
+;		CX:		Number of spaces to append
+;		Jumps to .PrepareToFormatNextParameter
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.UpdateSpacesToAppendAfterPrintingSingleCharacter:
+	mov		bx, 1
+ALIGN JUMP_ALIGN
+.UpdateSpacesToAppend:
+	jcxz	.PrepareToFormatNextParameter
+	sub		cx, bx				; Number of spaces to append
+	jle		SHORT .PrepareToFormatNextParameter
+	mov		al, ' '
+	call	DisplayPrint_RepeatCharacterFromALwithCountInCX
+	; Fall to .PrepareToFormatNextParameter
+
+;--------------------------------------------------------------------
+; .PrepareToFormatNextParameter
+;	Parameters:
+;		DS:		BDA segment (zero)
+;		SS:BP:	Pointer to format parameter
+;		CS:SI:	Pointer to next format string character
+;		ES:DI:	Ptr to cursor location in video RAM
+;	Returns:
+;		BP:		Adjusted to point next stack parameter
+;		Jumps to DisplayFormat_ParseCharacters
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.PrepareToFormatNextParameter:
+	dec		bp
+	dec		bp
+	jmp		SHORT DisplayFormat_ParseCharacters
+
+
+;--------------------------------------------------------------------
+; .JumpToFormatPlaceholder
+;	Parameters:
+;		BX:		Lookup index for format function
+;		CX:		Number parameter (zero if no number parameter present)
+;		DS:		BDA segment (zero)
+;		SS:BP:	Pointer to next format parameter
+;		CS:SI:	Pointer to next format string character
+;		ES:DI:	Ptr to cursor location in video RAM
+;	Returns:
+;		Eventually jumps to DisplayFormat_ParseCharacters
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.JumpToFormatPlaceholder:
+	shl		bx, 1					; Shift for WORD lookup
+	jmp		[cs:bx+.rgfnFormatParameter]
+
+ALIGN JUMP_ALIGN
+.a_FormatAttributeForNextCharacter:
+	mov		bl, [bp]
+	xchg	bl, [VIDEO_BDA.displayContext+DISPLAY_CONTEXT.bAttribute]
+	call	.ReadCharacterAndTestForNull
+	jz		SHORT .Return
+	call	DisplayPrint_CharacterFromAL
+	mov		[VIDEO_BDA.displayContext+DISPLAY_CONTEXT.bAttribute], bl
+	jmp		SHORT .UpdateSpacesToAppendAfterPrintingSingleCharacter
+
+ALIGN JUMP_ALIGN
+.A_FormatAttributeForRemainingString:
+	mov		al, [bp]
+	mov		[VIDEO_BDA.displayContext+DISPLAY_CONTEXT.bAttribute], al
+	jmp		SHORT .PrepareToFormatNextParameter
+
+ALIGN JUMP_ALIGN
+.d_FormatSignedDecimalWord:
+	mov		ax, [bp]
+	call	DisplayPrint_SignedDecimalIntegerFromAX
+	jmp		SHORT .UpdateSpacesToAppend
+
+ALIGN JUMP_ALIGN
+.u_FormatUnsignedDecimalWord:
+	mov		ax, [bp]
+	mov		bx, 10
+	call	DisplayPrint_WordFromAXWithBaseInBX
+	jmp		SHORT .UpdateSpacesToAppend
+
+ALIGN JUMP_ALIGN
+.x_FormatHexadecimalWord:
+	mov		ax, [bp]
+	mov		bx, 16
+	call	DisplayPrint_WordFromAXWithBaseInBX
+	inc		bx					; Increment character count for 'h'
+	mov		al, 'h'
+	call	DisplayPrint_CharacterFromAL
+	jmp		SHORT .UpdateSpacesToAppend
+
+ALIGN JUMP_ALIGN
+.s_FormatStringFromSegmentCS:
+	xchg	si, [bp]
+	call	DisplayPrint_NullTerminatedStringFromCSSI
+	mov		si, [bp]			; Restore SI
+	jmp		SHORT .UpdateSpacesToAppend
+
+ALIGN JUMP_ALIGN
+.S_FormatStringFromFarPointer:
+	xchg	si, [bp]
+	mov		bx, [bp-2]
+	call	DisplayPrint_NullTerminatedStringFromBXSI
+	mov		si, [bp]			; Restore SI
+	jmp		SHORT .UpdateSpacesToAppendWithDWordParameter
+
+ALIGN JUMP_ALIGN
+.c_FormatCharacter:
+	mov		al, [bp]
+	jmp		SHORT .FormatSingleCharacterFromAL
+
+ALIGN JUMP_ALIGN
+.t_FormatRepeatCharacter:
+	mov		cx, [bp-2]
+	mov		bx, cx
+	mov		al, [bp]
+	call	DisplayPrint_RepeatCharacterFromALwithCountInCX
+	jmp		SHORT .UpdateSpacesToAppendWithDWordParameter
+
+ALIGN JUMP_ALIGN
+.percent_FormatPercent:
+	mov		al, '%'
+	inc		bp					; Adjust here since...
+	inc		bp					; ...no parameter on stack
+	; Fall to .FormatSingleCharacterFromAL
+
+ALIGN JUMP_ALIGN
+.FormatSingleCharacterFromAL:
+	call	DisplayPrint_CharacterFromAL
+	jmp		.UpdateSpacesToAppendAfterPrintingSingleCharacter
+
+ALIGN JUMP_ALIGN
+.UpdateSpacesToAppendWithDWordParameter:
+	dec		bp
+	dec		bp
+	jmp		.UpdateSpacesToAppend
+
+
+; Table for converting format character to jump table index
+.rgcFormatCharToLookupIndex:
+	db		"aAduxsSct%"
+.EndOFrgcFormatCharToLookupIndex:
+
+; Jump table
+ALIGN WORD_ALIGN
+.rgfnFormatParameter:
+	dw		.a_FormatAttributeForNextCharacter
+	dw		.A_FormatAttributeForRemainingString
+	dw		.d_FormatSignedDecimalWord
+	dw		.u_FormatUnsignedDecimalWord
+	dw		.x_FormatHexadecimalWord
+	dw		.s_FormatStringFromSegmentCS
+	dw		.S_FormatStringFromFarPointer
+	dw		.c_FormatCharacter
+	dw		.t_FormatRepeatCharacter
+	dw		.percent_FormatPercent
Index: /trunk/Assembly_Library/Src/Display/DisplayPage.asm
===================================================================
--- /trunk/Assembly_Library/Src/Display/DisplayPage.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Display/DisplayPage.asm	(revision 41)
@@ -0,0 +1,67 @@
+; File name		:	DisplayPage.asm
+; Project name	:	Assembly Library
+; Created date	:	26.6.2010
+; Last update	:	3.7.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for managing display page.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; DisplayPage_SetFromAL
+;	Parameters:
+;		AL:		New display page
+;		DS:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayPage_SetFromAL:
+	xor		ah, ah
+	mul		WORD [VIDEO_BDA.wBytesPerPage]		; AX = Offset to page
+	mov		[VIDEO_BDA.displayContext+DISPLAY_CONTEXT.fpCursorPosition], ax
+	ret
+
+
+;--------------------------------------------------------------------
+; DisplayPage_GetColumnsToALandRowsToAH
+;	Parameters:
+;		DS:		BDA segment (zero)
+;	Returns:
+;		AL:		Number of columns in selected text mode
+;		AH:		Number of rows in selected text mode
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayPage_GetColumnsToALandRowsToAH:
+	mov		al, [VIDEO_BDA.wColumns]		; 40 or 80
+	mov		ah, 25							; Always 25 rows on standard text modes
+	ret
+
+
+;--------------------------------------------------------------------
+; DisplayPage_SynchronizeToHardware
+;	Parameters:
+;		DS:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayPage_SynchronizeToHardware:
+	xor		dx, dx
+	mov		ax, [VIDEO_BDA.displayContext+DISPLAY_CONTEXT.fpCursorPosition]
+	div		WORD [VIDEO_BDA.wBytesPerPage]	; AX = Page
+
+	cmp		al, [VIDEO_BDA.bActivePage]
+	je		SHORT .Return					; Same page, no need to synchronize
+	mov		ah, SELECT_ACTIVE_DISPLAY_PAGE
+	int		BIOS_VIDEO_INTERRUPT_10h
+ALIGN JUMP_ALIGN, ret
+.Return:
+	ret
Index: /trunk/Assembly_Library/Src/Display/DisplayPrint.asm
===================================================================
--- /trunk/Assembly_Library/Src/Display/DisplayPrint.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Display/DisplayPrint.asm	(revision 41)
@@ -0,0 +1,356 @@
+; File name		:	Display.asm
+; Project name	:	Assembly Library
+; Created date	:	26.6.2010
+; Last update	:	10.8.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for display output.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Supports following formatting types:
+;	%a		Specifies attribute for next character
+;	%A		Specifies attribute for remaining string (or until next %A)
+;	%d		Prints signed 16-bit decimal integer
+;	%u		Prints unsigned 16-bit decimal integer
+;	%x		Prints 16-bit hexadecimal integer
+;	%s		Prints string (from CS segment)
+;	%S		Prints string (far pointer)
+;	%c		Prints character
+;	%t		Prints character number of times (character needs to be pushed first, then repeat times)
+;	%%		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.
+; 
+; DisplayPrint_FormattedNullTerminatedStringFromCSSI
+;	Parameters:
+;		BP:		SP before pushing parameters
+;		DS:		BDA segment (zero)
+;		CS:SI:	Pointer to string to format
+;		ES:DI:	Ptr to cursor location in video RAM
+;		Stack:	Parameters for formatting placeholders.
+;				Parameter for first placeholder must be pushed first.
+;				Low word must pushed first for placeholders requiring
+;				32-bit parameters (two words).
+;	Returns:
+;		DI:		Updated offset to video RAM
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayPrint_FormattedNullTerminatedStringFromCSSI:
+	push	bp
+	push	si
+	push	cx
+	push	bx
+	push	WORD [VIDEO_BDA.displayContext+DISPLAY_CONTEXT.bAttribute]
+
+	dec		bp					; Point BP to...
+	dec		bp					; ...first stack parameter
+	call	DisplayFormat_ParseCharacters
+
+	; Pop original character attribute
+	pop		ax
+	mov		[VIDEO_BDA.displayContext+DISPLAY_CONTEXT.bAttribute], al
+
+	pop		bx
+	pop		cx
+	pop		si
+	pop		bp
+	ret
+
+
+;--------------------------------------------------------------------
+; DisplayPrint_SignedDecimalIntegerFromAX
+;	Parameters:
+;		AX:		Word to display
+;		DS:		BDA segment (zero)
+;		ES:DI:	Ptr to cursor location in video RAM
+;	Returns:
+;		BX:		Number of characters printed
+;		DI:		Updated offset to video RAM
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayPrint_SignedDecimalIntegerFromAX:
+	mov		bx, 10
+	test	ah, 1<<7			; Sign bit set?
+	jz		SHORT DisplayPrint_WordFromAXWithBaseInBX
+
+	push	ax
+	mov		al, '-'
+	call	DisplayPrint_CharacterFromAL
+	pop		ax
+	neg		ax
+	call	DisplayPrint_WordFromAXWithBaseInBX
+	inc		bx					; Increment character count for '-'
+	ret
+
+
+;--------------------------------------------------------------------
+; DisplayPrint_WordFromAXWithBaseInBX
+;	Parameters:
+;		AX:		Word to display
+;		BX:		Integer base (binary=2, octal=8, decimal=10, hexadecimal=16)
+;		DS:		BDA segment (zero)
+;		ES:DI:	Ptr to cursor location in video RAM
+;	Returns:
+;		BX:		Number of characters printed
+;		DI:		Updated offset to video RAM
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayPrint_WordFromAXWithBaseInBX:
+	push	cx
+
+	xor		cx, cx
+ALIGN JUMP_ALIGN
+.DivideLoop:
+	xor		dx, dx				; DX:AX now holds the integer
+	div		bx					; Divide DX:AX by base
+	push	dx					; Push remainder
+	inc		cx					; Increment character count
+	test	ax, ax				; All divided?
+	jnz		SHORT .DivideLoop	;  If not, loop
+	mov		dx, cx				; Character count to DX
+ALIGN JUMP_ALIGN
+.PrintLoop:
+	pop		bx					; Pop digit
+	mov		al, [cs:bx+.rgcDigitToCharacter]
+	call	DisplayPrint_CharacterFromAL
+	loop	.PrintLoop
+	mov		bx, dx				; Return characters printed
+
+	pop		cx
+	ret
+.rgcDigitToCharacter:	db	"0123456789ABCDEF"
+
+
+;--------------------------------------------------------------------
+; DisplayPrint_CharacterBufferFromBXSIwithLengthInCX
+;	Parameters:
+;		CX:		Buffer length (characters)
+;		BX:SI:	Ptr to NULL terminated string
+;		DS:		BDA segment (zero)
+;		ES:DI:	Ptr to cursor location in video RAM
+;	Returns:
+;		BX:		Number of characters printed
+;		DI:		Updated offset to video RAM
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayPrint_CharacterBufferFromBXSIwithLengthInCX:
+	push	cx
+
+	mov		es, bx					; Buffer now in ES:SI
+	xor		bx, bx					; Zero character counter
+	jcxz	.BufferPrinted
+ALIGN JUMP_ALIGN
+.CharacterOutputLoop:
+	mov		al, [es:bx+si]
+	inc		bx
+	call	LoadDisplaySegmentAndPrintCharacterFromAL
+	loop	.CharacterOutputLoop
+.BufferPrinted:
+	mov		es, [VIDEO_BDA.displayContext+DISPLAY_CONTEXT.fpCursorPosition+2]
+	pop		cx
+	ret
+
+
+;--------------------------------------------------------------------
+; DisplayPrint_NullTerminatedStringFromCSSI
+;	Parameters:
+;		CS:SI:	Ptr to NULL terminated string
+;		DS:		BDA segment (zero)
+;		ES:DI:	Ptr to cursor location in video RAM
+;	Returns:
+;		BX:		Number of characters printed
+;		DI:		Updated offset to video RAM
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayPrint_NullTerminatedStringFromCSSI:
+	mov		bx, cs
+	; Fall to DisplayPrint_NullTerminatedStringFromBXSI
+
+;--------------------------------------------------------------------
+; DisplayPrint_NullTerminatedStringFromBXSI
+;	Parameters:
+;		DS:		BDA segment (zero)
+;		BX:SI:	Ptr to NULL terminated string
+;		ES:DI:	Ptr to cursor location in video RAM
+;	Returns:
+;		BX:		Number of characters printed
+;		DI:		Updated offset to video RAM
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayPrint_NullTerminatedStringFromBXSI:
+	mov		es, bx					; String now in ES:SI
+	xor		bx, bx					; Zero character counter
+ALIGN JUMP_ALIGN
+.CharacterOutputLoop:
+	mov		al, [es:bx+si]
+	test	al, al
+	jz		SHORT .AllCharacterPrinted
+	inc		bx
+
+	call	LoadDisplaySegmentAndPrintCharacterFromAL
+	jmp		SHORT .CharacterOutputLoop
+ALIGN JUMP_ALIGN
+.AllCharacterPrinted:
+	mov		es, [VIDEO_BDA.displayContext+DISPLAY_CONTEXT.fpCursorPosition+2]
+	ret
+
+;--------------------------------------------------------------------
+; LoadDisplaySegmentAndPrintCharacterFromAL
+;	Parameters:
+;		AL:		Character to print
+;		DI:		Offset to cursor location in video RAM
+;		DS:		BDA segment (zero)
+;	Returns:
+;		DI:		Updated offset to video RAM
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+LoadDisplaySegmentAndPrintCharacterFromAL:
+	push	es
+	mov		es, [VIDEO_BDA.displayContext+DISPLAY_CONTEXT.fpCursorPosition+2]
+	call	DisplayPrint_CharacterFromAL
+	pop		es
+	ret
+
+
+;--------------------------------------------------------------------
+; DisplayPrint_Newline
+;	Parameters:
+;		DS:		BDA segment (zero)
+;		ES:DI:	Ptr to cursor location in video RAM
+;	Returns:
+;		DI:		Updated offset to video RAM
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayPrint_Newline:
+	mov		al, CR
+	call	DisplayPrint_CharacterFromAL
+	mov		al, LF
+	jmp		SHORT DisplayPrint_CharacterFromAL
+
+
+;--------------------------------------------------------------------
+; DisplayPrint_RepeatCharacterFromALwithCountInCX
+;	Parameters:
+;		AL:		Character to display
+;		CX:		Repeat count
+;		DS:		BDA segment (zero)
+;		ES:DI:	Ptr to cursor location in video RAM
+;	Returns:
+;		DI:		Updated offset to video RAM
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayPrint_RepeatCharacterFromALwithCountInCX:
+	push	ax
+	call	DisplayPrint_CharacterFromAL
+	pop		ax
+	loop	DisplayPrint_RepeatCharacterFromALwithCountInCX
+	ret
+
+
+;--------------------------------------------------------------------
+; DisplayPrint_CharacterFromAL
+;	Parameters:
+;		AL:		Character to display
+;		DS:		BDA segment (zero)
+;		ES:DI:	Ptr to cursor location in video RAM
+;	Returns:
+;		DI:		Updated offset to video RAM
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayPrint_CharacterFromAL:
+	mov		ah, [VIDEO_BDA.displayContext+DISPLAY_CONTEXT.bAttribute]
+	jmp		[VIDEO_BDA.displayContext+DISPLAY_CONTEXT.fnCharOut]
+
+
+;--------------------------------------------------------------------
+; DisplayPrint_ClearScreen
+;	Parameters:
+;		DS:		BDA segment (zero)
+;		ES:DI:	Ptr to cursor location in video RAM
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayPrint_ClearScreen:
+	push	di
+	xor		ax, ax
+	call	DisplayCursor_SetCoordinatesFromAX
+	call	DisplayPage_GetColumnsToALandRowsToAH
+	call	DisplayPrint_ClearAreaWithHeightInAHandWidthInAL
+	pop		di
+	mov		[VIDEO_BDA.displayContext+DISPLAY_CONTEXT.fpCursorPosition], di
+	ret
+
+
+;--------------------------------------------------------------------
+; DisplayPrint_ClearAreaWithHeightInAHandWidthInAL
+;	Parameters:
+;		AH:		Area height
+;		AL:		Area width
+;		DS:		BDA segment (zero)
+;		ES:DI:	Ptr to cursor location in video RAM
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DisplayPrint_ClearAreaWithHeightInAHandWidthInAL:
+	push	cx
+	push	bx
+	push	di
+
+	xchg	bx, ax							; Move parameters to BX
+	call	DisplayCursor_GetSoftwareCoordinatesToAX
+	xchg	dx, ax							; Coordinates now in DX
+	xor		cx, cx							; Zero CX
+
+ALIGN JUMP_ALIGN
+.ClearRowFromArea:
+	mov		al, ' '							; Clear with space
+	mov		ah, [VIDEO_BDA.displayContext+DISPLAY_CONTEXT.bAttribute]
+	mov		cl, bl							; Area width = WORDs to clear
+	rep stosw
+	dec		bh
+	jz		SHORT .AreaCleared
+
+	inc		dh								; Increment row
+	push	dx
+	xchg	ax, dx
+	call	DisplayCursor_SetCoordinatesFromAX
+	pop		dx
+	jmp		SHORT .ClearRowFromArea
+
+ALIGN JUMP_ALIGN
+.AreaCleared:
+	pop		di
+	mov		[VIDEO_BDA.displayContext+DISPLAY_CONTEXT.fpCursorPosition], di
+	pop		bx
+	pop		cx
+	ret
Index: /trunk/Assembly_Library/Src/File/Directory.asm
===================================================================
--- /trunk/Assembly_Library/Src/File/Directory.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/File/Directory.asm	(revision 41)
@@ -0,0 +1,147 @@
+; File name		:	Directory.asm
+; Project name	:	Assembly Library
+; Created date	:	3.9.2010
+; Last update	:	6.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for accessing directories.
+
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Directory_GetDiskTransferAreaAddressToDSSI
+;	Parameters:
+;		Nothing
+;	Returns:
+;		DS:SI:	Ptr to DTA
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Directory_GetDiskTransferAreaAddressToDSSI:
+	push	es
+	push	bx
+
+	mov		ah, GET_DISK_TRANSFER_AREA_ADDRESS
+	int		DOS_INTERRUPT_21h
+	push	es
+	pop		ds
+	mov		si, bx
+
+	pop		bx
+	pop		es
+	ret
+
+
+;--------------------------------------------------------------------
+; Directory_ChangeToPathFromDSSI
+;	Parameters:
+;		DS:SI:	Ptr to NULL terminated path (max 64 bytes)
+;	Returns:
+;		AX:		Error code
+;		CF:		Cleared if success
+;				Set if error
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Directory_ChangeToPathFromDSSI:
+	xchg	dx, si		; Path now in DS:DX
+	mov		ah, SET_CURRENT_DIRECTORY
+	int		DOS_INTERRUPT_21h
+	xchg	si, dx
+	ret
+
+
+;--------------------------------------------------------------------
+; Directory_WriteCurrentPathToDSSI
+;	Parameters:
+;		DS:SI:	Ptr to destination buffer (64 bytes)
+;	Returns:
+;		AX:		Error code
+;		CF:		Cleared if success
+;				Set if error
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Directory_WriteCurrentPathToDSSI:
+	push	dx
+
+	xor		dx, dx				; Default drive (00h)
+	mov		ah, GET_CURRENT_DIRECTORY
+	int		DOS_INTERRUPT_21h
+
+	pop		dx
+	ret
+
+
+;--------------------------------------------------------------------
+; Directory_GetMatchCountToAXforSearchStringInDSSIwithAttributesInCX
+;	Parameters:
+;		CX:		File attributes
+;		DS:SI:	NULL terminated search string (may include path and wildcards)
+;	Returns:
+;		AX:		Number of matching files found
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Directory_GetMatchCountToAXforSearchStringInDSSIwithAttributesInCX:
+	push	dx
+	xor		dx, dx				; Zero counter
+	call	Directory_UpdateDTAForFirstMatchForDSSIwithAttributesInCX
+	jc		SHORT .NoMoreFilesFound
+ALIGN JUMP_ALIGN
+.FindNextFile:
+	inc		dx					; Increment match count
+	call	Directory_UpdateDTAForNextMatchUsingPreviousParameters
+	jnc		SHORT .FindNextFile
+ALIGN JUMP_ALIGN
+.NoMoreFilesFound:
+	xchg	ax, dx				; Match count to AX
+	pop		dx
+	ret
+
+
+;--------------------------------------------------------------------
+; Directory_UpdateDTAForFirstMatchForDSSIwithAttributesInCX
+;	Parameters:
+;		CX:		File attributes
+;		DS:SI:	NULL terminated search string (may include path and wildcards)
+;	Returns:
+;		AX:		Error code
+;		CF:		Cleared if success
+;				Set if error
+;		Disk Transfer Area (DTA) will be updated
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Directory_UpdateDTAForFirstMatchForDSSIwithAttributesInCX:
+	xchg	dx, si							; Search string now in DS:DX
+	mov		ax, FIND_FIRST_MATCHING_FILE<<8	; Zero AL (special flag for APPEND)
+	int		DOS_INTERRUPT_21h
+	xchg	si, dx
+	ret
+
+
+;--------------------------------------------------------------------
+; Directory_UpdateDTAForNextMatchUsingPreviousParameters
+;	Parameters:
+;		Nothing (Parameters from previous call to 
+;				Directory_UpdateDTAForFirstMatchForDSSIwithAttributesInCX are used)
+;	Returns:
+;		AX:		Error code
+;		CF:		Cleared if success
+;				Set if error
+;		Disk Transfer Area (DTA) will be updated
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Directory_UpdateDTAForNextMatchUsingPreviousParameters:
+	mov		ah, FIND_NEXT_MATCHING_FILE
+	int		DOS_INTERRUPT_21h
+	ret
Index: /trunk/Assembly_Library/Src/File/DosCritical.asm
===================================================================
--- /trunk/Assembly_Library/Src/File/DosCritical.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/File/DosCritical.asm	(revision 41)
@@ -0,0 +1,79 @@
+; File name		:	DosCritical.asm
+; Project name	:	Assembly Library
+; Created date	:	1.9.2010
+; Last update	:	2.9.2010
+; Author		:	Tomi Tilli
+; Description	:	DOS Critical Error Handler (24h) replacements.
+
+; DOS Critical Error Handler return values
+struc CRITICAL_ERROR_ACTION
+	.ignoreErrorAndContinueProcessingRequest	resb	1
+	.retryOperation								resb	1
+	.terminateProgramAsThoughInt21hAH4ChCalled	resb	1
+	.failSystemCallInProgress					resb	1
+endstruc
+
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; DosCritical_InstallNewHandlerFromCSDX
+;	Parameters:
+;		CS:DX:	New Critical Error Handler
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DosCritical_InstallNewHandlerFromCSDX:
+	push	ds
+
+	push	cs
+	pop		ds
+	mov		ax, (SET_INTERRUPT_VECTOR<<8) | DOS_CRITICAL_ERROR_HANDLER_24h
+	int		DOS_INTERRUPT_21h
+
+	pop		ds
+	ret
+
+
+;--------------------------------------------------------------------
+; DosCritical_RestoreDosHandler
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DosCritical_RestoreDosHandler:
+	push	ds
+	push	dx
+	push	ax
+
+	lds		dx, [cs:PSP.fpInt24hCriticalError]
+	mov		ax, (SET_INTERRUPT_VECTOR<<8) | DOS_CRITICAL_ERROR_HANDLER_24h
+	int		DOS_INTERRUPT_21h
+
+	pop		ax
+	pop		dx
+	pop		ds
+	ret
+
+
+;--------------------------------------------------------------------
+; DosCritical_HandlerToIgnoreAllErrors
+;	Parameters:
+;		Nothing
+;	Returns:
+;		AL:		CRITICAL_ERROR_ACTION
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------	
+ALIGN JUMP_ALIGN
+DosCritical_HandlerToIgnoreAllErrors:
+	mov		al, CRITICAL_ERROR_ACTION.ignoreErrorAndContinueProcessingRequest
+	iret
Index: /trunk/Assembly_Library/Src/File/Drive.asm
===================================================================
--- /trunk/Assembly_Library/Src/File/Drive.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/File/Drive.asm	(revision 41)
@@ -0,0 +1,183 @@
+; File name		:	Drive.asm
+; Project name	:	Assembly Library
+; Created date	:	1.9.2010
+; Last update	:	3.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for accessing drives.
+
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Drive_GetNumberOfAvailableDrivesToAX
+;	Parameters:
+;		Nothing
+;	Returns:
+;		AX:		Number of available drives
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Drive_GetNumberOfAvailableDrivesToAX:
+	push	dx
+	push	cx
+
+	call	Drive_GetFlagsForAvailableDrivesToDXAX
+	call	Bit_GetSetCountToCXfromDXAX
+	xchg	ax, cx
+
+	pop		cx
+	pop		dx
+	ret
+
+
+;--------------------------------------------------------------------
+; Drive_GetFlagsForAvailableDrivesToDXAX
+;	Parameters:
+;		Nothing
+;	Returns:
+;		DX:AX:	Flags containing valid drives (bit 0 = drive A, bit 1 = drive B ...)
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Drive_GetFlagsForAvailableDrivesToDXAX:
+	push	cx
+	push	bx
+	mov		dx, DosCritical_HandlerToIgnoreAllErrors
+	call	DosCritical_InstallNewHandlerFromCSDX
+
+	call	.GetNumberOfPotentiallyValidDriveLettersToCX
+	xor		bx, bx
+	xor		ax, ax				; Temporary use BX:AX for flags
+	xor		dx, dx				; Start from drive 0
+	call	.CheckDriveValidityUntilCXisZero
+	mov		dx, bx				; Flags now in DX:AX
+
+	call	DosCritical_RestoreDosHandler
+	pop		bx
+	pop		cx
+	ret
+
+;--------------------------------------------------------------------
+; .GetNumberOfPotentiallyValidDriveLettersToCX
+;	Parameters:
+;		Nothing
+;	Returns:
+;		CX:		Number of potentially valid drive letters available
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.GetNumberOfPotentiallyValidDriveLettersToCX:
+	call	Drive_GetDefaultToAL
+	xchg	dx, ax			; Default drive to DL
+	call	Drive_SetDefaultFromDL
+	eMOVZX	cx, al			; Number of potentially valid drive letters available
+	MIN_U	cx, 32
+	ret
+
+;--------------------------------------------------------------------
+; .CheckDriveValidityUntilCXisZero
+;	Parameters:
+;		CX:		Number of potentially valid drive letters left
+;		DL:		Drive number (00h=A:, 01h=B: ...)
+;		BX:AX:	Flags for drive numbers
+;	Returns:
+;		BX:AX:	Flags for valid drive numbers
+;	Corrupts registers:
+;		CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.CheckDriveValidityUntilCXisZero:
+	call	.IsValidDriveNumberInDL
+	jnz		SHORT .PrepareToCheckNextDrive
+	call	.SetFlagToBXAXfromDriveInDL
+ALIGN JUMP_ALIGN
+.PrepareToCheckNextDrive:
+	inc		dx
+	loop	.CheckDriveValidityUntilCXisZero
+	ret
+
+;--------------------------------------------------------------------
+; .IsValidDriveNumberInDL
+;	Parameters:
+;		DL:		Drive number (00h=A:, 01h=B: ...)
+;	Returns:
+;		ZF:		Set if drive number is valid
+;				Cleared if drive number is invalid
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.IsValidDriveNumberInDL:
+	push	ds
+	push	bx
+	push	ax
+
+	inc		dx			; Default drive is 00h and first drive is 01h
+	mov		ah, GET_DOS_DRIVE_PARAMETER_BLOCK_FOR_SPECIFIC_DRIVE
+	int		DOS_INTERRUPT_21h
+	dec		dx
+	test	al, al
+
+	pop		ax
+	pop		bx
+	pop		ds
+	ret
+
+;--------------------------------------------------------------------
+; .SetFlagToBXAXfromDriveInDL
+;	Parameters:
+;		DL:		Drive number (0...31)
+;		BX:AX:	Flags containing drive numbers
+;	Returns:
+;		BX:AX:	Flags with wanted drive bit set
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.SetFlagToBXAXfromDriveInDL:
+	push	cx
+
+	mov		cl, dl
+	xchg	dx, bx
+	call	Bit_SetToDXAXfromIndexInCL
+	xchg	bx, dx
+
+	pop		cx
+	ret
+
+
+;--------------------------------------------------------------------
+; Drive_GetDefaultToAL
+;	Parameters:
+;		Nothing
+;	Returns:
+;		AL:		Current default drive (00h=A:, 01h=B: ...)
+;	Corrupts registers:
+;		AH
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Drive_GetDefaultToAL:
+	mov		ah, GET_CURRENT_DEFAULT_DRIVE
+	int		DOS_INTERRUPT_21h
+	ret
+
+
+;--------------------------------------------------------------------
+; Drive_SetDefaultFromDL
+;	Parameters:
+;		DL:		New default drive (00h=A:, 01h=B: ...)
+;	Returns:
+;		AL:		Number of potentially valid drive letters available
+;	Corrupts registers:
+;		AH
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Drive_SetDefaultFromDL:
+	mov		ah, SELECT_DEFAULT_DRIVE
+	int		DOS_INTERRUPT_21h
+	ret
+	
Index: /trunk/Assembly_Library/Src/File/FileIO.asm
===================================================================
--- /trunk/Assembly_Library/Src/File/FileIO.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/File/FileIO.asm	(revision 41)
@@ -0,0 +1,144 @@
+; File name		:	FileIO.asm
+; Project name	:	Assembly Library
+; Created date	:	1.9.2010
+; Last update	:	3.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for file access.
+
+
+; File access and sharing modes
+struc FILE_ACCESS
+	.ReadOnly		resb	1
+	.WriteOnly		resb	1
+	.ReadAndWrite	resb	1
+endstruc
+
+; Origin of file seek
+struc SEEK_FROM
+	.startOfFile			resb	1
+	.currentFilePosition	resb	1
+	.endOfFile				resb	1
+endstruc
+
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; FileIO_OpenWithPathInDSSIandFileAccessInAL
+;	Parameters:
+;		AL:		FILE_ACCESS.(mode)
+;		DS:SI:	Ptr to NULL terminated path or 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
+FileIO_OpenWithPathInDSSIandFileAccessInAL:
+	xchg	dx, si		; Path now in DS:DX
+	mov		ah, OPEN_EXISTING_FILE
+	int		DOS_INTERRUPT_21h
+	xchg	si, dx
+	ret
+
+
+;--------------------------------------------------------------------
+; FileIO_CloseUsingHandleFromBX
+;	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
+FileIO_CloseUsingHandleFromBX:
+	mov		ah, CLOSE_FILE
+	int		DOS_INTERRUPT_21h
+	ret
+
+
+;--------------------------------------------------------------------
+; File position is updated so next read will start where
+; previous read stopped.
+; 
+; FileIO_ReadCXbytesToDSSIusingHandleFromBX
+;	Parameters:
+;		BX:		File handle
+;		CX:		Number of bytes to read
+;		DS:SI:	Ptr to destination buffer
+;	Returns:
+;		AX:		Number of bytes actually read if successfull (0 if at EOF before call)
+;				DOS error code if CF set
+;		CF:		Clear if successfull
+;				Set if error
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+FileIO_ReadCXbytesToDSSIusingHandleFromBX:
+	xchg	dx, si				; DS:DX now points to source buffer
+	mov		ah, READ_FROM_FILE_OR_DEVICE
+	int		DOS_INTERRUPT_21h
+	xchg	si, dx
+	ret
+
+
+;--------------------------------------------------------------------
+; File position is updated so next write will start where
+; previous write stopped.
+; 
+; FileIO_WriteCXbytesFromDSSIusingHandleFromBX:
+;	Parameters:
+;		BX:		File handle
+;		CX:		Number of bytes to write
+;		DS:SI:	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
+FileIO_WriteCXbytesFromDSSIusingHandleFromBX:
+	xchg	dx, si				; DS:DX now points to source buffer
+	mov		ah, WRITE_TO_FILE_OR_DEVICE
+	int		DOS_INTERRUPT_21h
+	xchg	si, dx
+	ret
+
+
+;--------------------------------------------------------------------
+; FileIO_SeekFromOriginInALtoOffsetInDXAXusingHandleFromBX:
+;	Parameters:
+;		AL:		SEEK_FROM.(origin)
+;		BX:		File handle
+;		DX:AX:	Seek offset (signed)
+;	Returns:
+;		AX:		DOS error code if CF set
+;		CF:		Clear if successfull
+;				Set if error
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+FileIO_SeekFromOriginInALtoOffsetInDXAXusingHandleFromBX:
+	push	dx
+	push	cx
+
+	mov		cx, dx				; DOS wants high word in CX
+	xchg	dx, ax				; DOS wants low word in DX
+	mov		ah, SET_CURRENT_FILE_POSITION
+	int		DOS_INTERRUPT_21h
+
+	pop		cx
+	pop		dx
+	ret
Index: /trunk/Assembly_Library/Src/Keyboard/Keyboard.asm
===================================================================
--- /trunk/Assembly_Library/Src/Keyboard/Keyboard.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Keyboard/Keyboard.asm	(revision 41)
@@ -0,0 +1,279 @@
+; File name		:	Keyboard.asm
+; Project name	:	Assembly Library
+; Created date	:	5.7.2010
+; Last update	:	12.8.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for managing keyboard.
+
+BUFFER_SIZE_FOR_WORD_INPUT		EQU		6	; 5 chars + NULL
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Reads user inputted word.
+; Function returns when ENTER or ESC will be pressed.
+; 
+; Keyboard_ReadUserInputtedWordWhilePrinting
+;	Parameters
+;		BX:		Numeric base (10 or 16)
+;	Returns:
+;		AX:		User inputted word
+;		ZF:		Set if user cancellation
+;	Corrupts registers:
+;		DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Keyboard_ReadUserInputtedWordWhilePrinting:
+	push	es
+	push	di
+	push	cx
+
+	eENTER_STRUCT BUFFER_SIZE_FOR_WORD_INPUT
+	call	Memory_CopySSBPtoESDI
+
+	mov		cx, BUFFER_SIZE_FOR_WORD_INPUT
+	call	Char_GetFilterFunctionToDXforNumericBaseInBX
+	call	Keyboard_ReadUserInputtedStringToESDIWhilePrinting
+	jz		SHORT .Return
+
+	call	Memory_ExchangeDSSIwithESDI
+	call	String_ConvertWordToAXfromStringInDSSIwithBaseInBX
+	call	Memory_ExchangeDSSIwithESDI
+.Return:
+	eLEAVE_STRUCT BUFFER_SIZE_FOR_WORD_INPUT
+	test	cx, cx					; Set ZF if string length is zero
+	pop		cx
+	pop		di
+	pop		es
+	ret
+
+
+;--------------------------------------------------------------------
+; Reads user inputted string to buffer. Character filter is
+; supported to ignore unwanted characters.
+; Function returns when ENTER or ESC will be pressed.
+; 
+; Keyboard_ReadUserInputtedStringToESDIWhilePrinting
+;	Parameters:
+;		CX:		Buffer size (with NULL)
+;		ES:DI:	Ptr to destination buffer
+;		CS:DX:	Ptr to character filter function:
+;					Parameters:
+;						AL:		Character inputted by user
+;					Returns:
+;						CF:		Set if character is accepted
+;								Cleared if character is rejected
+;					Corrupts registers:
+;						Nothing
+;	Returns:
+;		CX:		String length in characters (without NULL)
+;		ZF:		Set if user cancellation
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Keyboard_ReadUserInputtedStringToESDIWhilePrinting:
+	push	di
+	push	si
+	push	bx
+	call	.PrepareDisplayContextForKeyboardInput
+	jcxz	.ReturnAfterUpdatingZF
+
+	xor		bx, bx								; Zero character counter
+	dec		cx									; Decrement buffer size for NULL
+	cld
+ALIGN JUMP_ALIGN
+.GetCharacterFromUser:
+	call	Keyboard_GetKeystrokeToAXandWaitIfNecessary	; Get ASCII to AL
+	call	.ProcessControlCharacter
+	jz		SHORT .TerminateStringWithNULL
+	jc		SHORT .PlayBellForRejectedCharacter
+	call	dx									; Filter character
+	jnc		SHORT .PlayBellForRejectedCharacter
+	inc		bx									; Increment number of characters stored
+	stosb										; Store from AL to ES:DI
+	call	Keyboard_PrintInputtedCharacter
+	loop	.GetCharacterFromUser
+.PlayBellForRejectedCharacter:
+	call	Keyboard_PlayBellForUnwantedKeystroke
+	jmp		SHORT .GetCharacterFromUser
+
+.TerminateStringWithNULL:
+	stosb										; Terminate string with NULL
+	mov		cx, bx								; String length now in CX
+
+.ReturnAfterUpdatingZF:
+	CALL_DISPLAY_LIBRARY PopDisplayContext
+	test	cx, cx								; Clear or set ZF
+	pop		bx
+	pop		si
+	pop		di
+	ret
+
+;--------------------------------------------------------------------
+; .PrepareDisplayContextForKeyboardInput
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing (Display context pushed to stack)
+;	Corrupts registers:
+;		AX, BX, SI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.PrepareDisplayContextForKeyboardInput:
+	pop		bx					; Pop return address to BX
+	mov		si, di
+
+	CALL_DISPLAY_LIBRARY PushDisplayContext
+	mov		ax, CURSOR_NORMAL
+	CALL_DISPLAY_LIBRARY SetCursorShapeFromAX
+	CALL_DISPLAY_LIBRARY SynchronizeDisplayContextToHardware
+
+	mov		di, si
+	jmp		bx
+
+
+;--------------------------------------------------------------------
+; .ProcessControlCharacter
+;	Parameters:
+;		AL:		Character inputted by user
+;		CX:		Number of bytes left in buffer
+;		BX:		Total number of characters inputted
+;		ES:DI:	Ptr where to store next character
+;	Returns:
+;		AL:		Character inputted by user or NULL if end of input
+;		BX:		Cleared if user cancellation
+;		ZF:		Set if user has ended or cancelled key input
+;		CF:		Set if character is rejected
+;	Corrupts registers:
+;		AH
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.ProcessControlCharacter:
+	cmp		al, CR								; ENTER to terminate string?
+	je		SHORT .EndCharacterInput
+	cmp		al, ESC								; Cancel input?
+	je		SHORT .CancelCharacterInput
+	cmp		al, BS								; Backspace?
+	je		SHORT .Backspace
+	jcxz	.RejectCharacter
+	test	al, al								; Clear ZF and CF
+	ret
+
+.Backspace:
+	test	bx, bx								; At the beginning?
+	jz		SHORT .RejectCharacter
+	inc		cx									; Increment bytes left
+	dec		bx									; Decrement characters inputted
+	dec		di
+	call	Keyboard_PrintBackspace
+.RejectCharacter:
+	test	al, al								; Clear ZF...
+	stc											; ...and set CF
+	ret
+
+.CancelCharacterInput:
+	xor		bx, bx
+.EndCharacterInput:
+	xor		al, al								; Set ZF and clear CF
+	ret
+
+
+;--------------------------------------------------------------------
+; Keyboard_PrintBackspace
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Keyboard_PrintBackspace:
+	mov		al, BS
+	call	Keyboard_PrintInputtedCharacter
+	mov		al, ' '
+	call	Keyboard_PrintInputtedCharacter
+	mov		al, BS
+	jmp		SHORT Keyboard_PrintInputtedCharacter
+
+
+;--------------------------------------------------------------------
+; Keyboard_PlayBellForUnwantedKeystroke
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Keyboard_PlayBellForUnwantedKeystroke:
+	mov		al, BELL
+	; Fall to Keyboard_PrintInputtedCharacter
+
+;--------------------------------------------------------------------
+; Keyboard_PrintInputtedCharacter
+;	Parameters:
+;		AL:		Character inputted by user
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Keyboard_PrintInputtedCharacter:
+	push	di
+	CALL_DISPLAY_LIBRARY PrintCharacterFromAL
+	CALL_DISPLAY_LIBRARY SynchronizeDisplayContextToHardware
+	pop		di
+	ret
+
+
+;--------------------------------------------------------------------
+; Keyboard_RemoveAllKeystrokesFromBuffer
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Keyboard_RemoveAllKeystrokesFromBuffer:
+	call	Keyboard_GetKeystrokeToAX
+	jnz		SHORT Keyboard_RemoveAllKeystrokesFromBuffer
+	ret
+
+
+;--------------------------------------------------------------------
+; Keyboard_GetKeystrokeToAX
+; Keyboard_GetKeystrokeToAXandLeaveItToBuffer
+; Keyboard_GetKeystrokeToAXandWaitIfNecessary
+;	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
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Keyboard_GetKeystrokeToAX:
+	call	Keyboard_GetKeystrokeToAXandLeaveItToBuffer
+	jnz		SHORT Keyboard_GetKeystrokeToAXandWaitIfNecessary
+	ret	
+ALIGN JUMP_ALIGN
+Keyboard_GetKeystrokeToAXandLeaveItToBuffer:
+	mov		ah, CHECK_FOR_KEYSTROKE
+	int		BIOS_KEYBOARD_INTERRUPT_16h
+	ret
+ALIGN JUMP_ALIGN
+Keyboard_GetKeystrokeToAXandWaitIfNecessary:
+	xor		ah, ah						; GET_KEYSTROKE
+	int		BIOS_KEYBOARD_INTERRUPT_16h
+	test	ax, ax						; Clear ZF
+	ret
Index: /trunk/Assembly_Library/Src/LibSizeCheck.asm
===================================================================
--- /trunk/Assembly_Library/Src/LibSizeCheck.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/LibSizeCheck.asm	(revision 41)
@@ -0,0 +1,22 @@
+; File name		:	LibSizeCheck.asm
+; Project name	:	Assembly Library
+; Created date	:	15.9.2010
+; Last update	:	15.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Tests for Assembly Library.
+;					Builds wanted library functions to check their size.
+
+; Include .inc files
+%define INCLUDE_DISPLAY_LIBRARY
+%define INCLUDE_FILE_LIBRARY
+%define INCLUDE_KEYBOARD_LIBRARY
+%define INCLUDE_MENU_LIBRARY
+%define INCLUDE_MENU_DIALOGS
+%define INCLUDE_STRING_LIBRARY
+%define INCLUDE_TIME_LIBRARY
+%define INCLUDE_UTIL_LIBRARY
+%include "AssemblyLibrary.inc"	; Assembly Library. Must be included first!
+
+
+; Include library sources
+%include "AssemblyLibrary.asm"
Index: /trunk/Assembly_Library/Src/LibraryTests.asm
===================================================================
--- /trunk/Assembly_Library/Src/LibraryTests.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/LibraryTests.asm	(revision 41)
@@ -0,0 +1,586 @@
+; File name		:	LibraryTests.asm
+; Project name	:	Assembly Library
+; Created date	:	27.6.2010
+; Last update	:	15.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Tests for Assembly Library.
+;					This file should not be included when using the library on
+;					some other project.		
+
+; Include .inc files
+%define INCLUDE_MENU_DIALOGS
+%include "AssemblyLibrary.inc"	; Assembly Library. Must be included first!
+
+
+; Section containing code
+SECTION .text
+
+; Program first instruction.
+ORG	100h						; Code starts at offset 100h (DOS .COM)
+Start:
+	jmp		LibraryTests_Start
+
+; Include library sources
+%include "AssemblyLibrary.asm"
+
+
+;--------------------------------------------------------------------
+; Program start
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+LibraryTests_Start:	
+	CALL_DISPLAY_LIBRARY InitializeDisplayContext
+	CALL_DISPLAY_LIBRARY ClearScreen
+
+	call	LibraryTests_ForDisplayLibrary
+	;call	LibraryTests_ForKeyboardLibrary
+	call	LibraryTests_ForMenuLibrary
+
+	; Exit to DOS
+	;mov		ax, CURSOR_XY(1, 1)
+	;CALL_DISPLAY_LIBRARY SetCursorCoordinatesFromAX
+	CALL_DISPLAY_LIBRARY SynchronizeDisplayContextToHardware
+	mov 	ax, 4C00h			; Exit to DOS
+	int 	21h
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ALIGN JUMP_ALIGN
+LibraryTests_ForMenuLibrary:
+	mov		[cs:g_dialogInputOutput+DIALOG_INPUT.fszTitle+2], cs
+	mov		[cs:g_dialogInputOutput+DIALOG_INPUT.fszItems+2], cs
+	mov		[cs:g_dialogInputOutput+DIALOG_INPUT.fszInfo+2], cs
+
+	mov		bx, .MenuEventHandler
+	call	MenuInit_DisplayMenuWithHandlerInBXandUserDataInDXAX
+	ret
+
+ALIGN JUMP_ALIGN
+.MenuEventHandler:
+	jmp		[cs:bx+.rgfnMenuEvents]
+.NotHandled:
+	clc		; Not handled so clear
+	ret
+
+ALIGN JUMP_ALIGN
+.InitializeMenu:
+	mov		WORD [si+MENUINIT.wTimeoutTicks], 10000 / 55	; 10 seconds
+	mov		WORD [si+MENUINIT.wItems], 51
+	mov		BYTE [si+MENUINIT.bWidth], 40
+	mov		BYTE [si+MENUINIT.bHeight], 20
+	mov		BYTE [si+MENUINIT.bTitleLines], TEST_MENU_TITLE_LINES
+	mov		BYTE [si+MENUINIT.bInfoLines], TEST_MENU_INFO_LINES
+	mov		ax, 1
+	CALL_MENU_LIBRARY HighlightItemFromAX
+	stc
+	ret
+
+ALIGN JUMP_ALIGN
+.RefreshTitle:
+	mov		si, .szMenuTitle
+	CALL_DISPLAY_LIBRARY PrintNullTerminatedStringFromCSSI
+	stc
+	ret
+.szMenuTitle:
+	db		"First line for menu title.",CR,LF,
+	db		"This is the second line.",NULL
+
+ALIGN JUMP_ALIGN
+.RefreshInformation:
+	push	bp
+	mov		bp, sp
+	mov		si, .szInfoTitle
+	CALL_DISPLAY_LIBRARY FormatNullTerminatedStringFromCSSI
+	pop		bp
+	stc
+	ret
+.szInfoTitle:
+	db		"Information line 1,",CR,LF,
+	db		"Information line 2,",CR,LF,
+	db		"This is the last information line.",NULL
+
+ALIGN JUMP_ALIGN
+.RefreshItemFromCX:
+	cmp		cx, TEST_MENU_VALID_ITEMS
+	jb		SHORT .PrintKnownItem
+
+	push	bp
+	mov		si, .szItem
+	mov		bp, sp
+	push	cx				; Item index
+	CALL_DISPLAY_LIBRARY FormatNullTerminatedStringFromCSSI
+	pop		bp
+	stc
+	ret
+.szItem:
+	db	"This is item %d.",NULL
+.PrintKnownItem:
+	mov		si, cx
+	shl		si, 1
+	mov		si, [cs:si+.rgszItems]
+	CALL_DISPLAY_LIBRARY PrintNullTerminatedStringFromCSSI
+	stc
+	ret
+
+ALIGN JUMP_ALIGN
+.ItemSelectedFromCX:
+	push	cs
+	pop		ds
+	cmp		cx, TEST_MENU_VALID_ITEMS
+	jae		SHORT .ReturnWithoutHandling
+	mov		bx, cx
+	shl		bx, 1
+	jmp		[bx+.rgfnSelectionHandler]
+.ReturnWithoutHandling:
+	stc
+	ret
+
+ALIGN WORD_ALIGN
+.rgfnSelectionHandler:
+	dw		.ExitMenu
+	dw		.ToggleTitle
+	dw		.ToggleInfo
+	dw		.ShowMessageDialogWithUnformattedText
+	dw		.AskWordFromUser
+	dw		.AskStringFromUser
+	dw		.AskSelectionFromUser
+	dw		.AskFileFromUser
+	dw		.TestProgressBar
+
+
+ALIGN JUMP_ALIGN
+.ExitMenu:
+	CALL_MENU_LIBRARY Close
+	stc
+	ret
+
+ALIGN JUMP_ALIGN
+.ToggleTitle:
+	mov		al, [bp+MENUINIT.bTitleLines]
+	xor		al, TEST_MENU_TITLE_LINES
+	CALL_MENU_LIBRARY SetTitleHeightFromAL
+	jmp		SHORT .RefreshMenuWindow
+ALIGN JUMP_ALIGN
+.ToggleInfo:
+	mov		al, [bp+MENUINIT.bInfoLines]
+	xor		al, TEST_MENU_INFO_LINES
+	CALL_MENU_LIBRARY SetInformationHeightFromAL
+.RefreshMenuWindow:
+	CALL_MENU_LIBRARY RestartTimeout
+	CALL_MENU_LIBRARY RefreshWindow
+	stc
+	ret
+
+ALIGN JUMP_ALIGN
+.ShowMessageDialogWithUnformattedText:
+	mov		di, g_szVeryLongString
+	jmp		.ShowDialogWithStringInCSDI
+
+ALIGN JUMP_ALIGN
+.AskWordFromUser:
+	mov		si, g_dialogInputOutput
+	mov		BYTE [si+WORD_DIALOG_IO.bNumericBase], 10
+	mov		WORD [si+WORD_DIALOG_IO.wMin], 10
+	mov		WORD [si+WORD_DIALOG_IO.wMax], 20
+	CALL_MENU_LIBRARY GetWordWithIoInDSSI
+
+	mov		ax, [si+WORD_DIALOG_IO.wReturnWord]
+	mov		di, g_szBuffer
+	call	.FormatWordFromAXtoStringBufferInCSDI
+	call	.ShowDialogWithStringInCSDI
+	stc
+	ret
+
+ALIGN JUMP_ALIGN
+.AskStringFromUser:
+	mov		si, g_dialogInputOutput
+	mov		WORD [si+STRING_DIALOG_IO.fnCharFilter], NULL
+	mov		WORD [si+STRING_DIALOG_IO.wBufferSize], 17
+	mov		WORD [si+STRING_DIALOG_IO.fpReturnBuffer], g_szBuffer
+	mov		[si+STRING_DIALOG_IO.fpReturnBuffer+2], cs
+	CALL_MENU_LIBRARY GetStringWithIoInDSSI
+
+	mov		di, g_szBuffer
+	call	.ShowDialogWithStringInCSDI
+	stc
+	ret
+
+ALIGN JUMP_ALIGN
+.AskSelectionFromUser:
+	mov		si, g_dialogInputOutput
+	mov		WORD [si+DIALOG_INPUT.fszItems], .szSelections
+	CALL_MENU_LIBRARY GetSelectionToAXwithInputInDSSI
+
+	mov		di, g_szBuffer
+	call	.FormatWordFromAXtoStringBufferInCSDI
+	call	.ShowDialogWithStringInCSDI
+	stc
+	ret
+.szSelections:
+	db		"Cancel",LF
+	db		"Yes",LF
+	db		"No",NULL
+
+ALIGN JUMP_ALIGN
+.AskFileFromUser:
+	mov		si, g_dialogInputOutput
+	mov		WORD [si+DIALOG_INPUT.fszItems], g_szBuffer
+	mov		BYTE [si+FILE_DIALOG_IO.bDialogFlags], FLG_FILEDIALOG_DIRECTORY | FLG_FILEDIALOG_NEW | FLG_FILEDIALOG_DRIVES
+	mov		BYTE [si+FILE_DIALOG_IO.bFileAttributes], FLG_FILEATTR_DIRECTORY | FLG_FILEATTR_ARCHIVE
+	mov		WORD [si+FILE_DIALOG_IO.fpFileFilterString], .szAllFiles
+	mov		[si+FILE_DIALOG_IO.fpFileFilterString+2], cs
+	mov		[si+STRING_DIALOG_IO.fpReturnBuffer+2], cs
+	CALL_MENU_LIBRARY GetFileNameWithIoInDSSI
+	cmp		BYTE [g_dialogInputOutput+FILE_DIALOG_IO.bUserCancellation], TRUE
+	je		SHORT .FileSelectionCancelled
+
+	mov		di, g_dialogInputOutput + FILE_DIALOG_IO.szFile
+	call	.ShowDialogWithStringInCSDI
+.FileSelectionCancelled:
+	stc
+	ret
+.szAllFiles:
+	db		"*.*",NULL
+
+
+ALIGN JUMP_ALIGN
+.FormatWordFromAXtoStringBufferInCSDI:
+	push	bp
+	push	di
+	mov		si, di
+	xchg	cx, ax
+	CALL_DISPLAY_LIBRARY PushDisplayContext
+
+	mov		bx, cs
+	mov		ax, si
+	CALL_DISPLAY_LIBRARY SetCharacterPointerFromBXAX
+	mov		ax, BUFFER_OUTPUT_WITH_CHAR_ONLY
+	CALL_DISPLAY_LIBRARY SetCharacterOutputFunctionFromAX
+	lea		ax, [si+STRING_BUFFER_SIZE]
+	CALL_DISPLAY_LIBRARY SetCharacterOutputParameterFromAX
+
+	mov		si, .szFormatWord
+	mov		bp, sp
+	push	cx
+	CALL_DISPLAY_LIBRARY FormatNullTerminatedStringFromCSSI
+	mov		al, NULL
+	CALL_DISPLAY_LIBRARY PrintCharacterFromAL	; Terminate buffer with NULL
+
+	CALL_DISPLAY_LIBRARY PopDisplayContext
+	pop		di
+	pop		bp
+	ret
+.szFormatWord:
+	db		"Integer %d selected!",NULL
+
+
+ALIGN JUMP_ALIGN
+.ShowDialogWithStringInCSDI:
+	push	cs
+	pop		ds
+	mov		si, g_dialogInputOutput
+	mov		WORD [si+DIALOG_INPUT.fszItems], di
+	CALL_MENU_LIBRARY DisplayMessageWithInputInDSSI
+	stc
+	ret
+
+
+ALIGN JUMP_ALIGN
+.TestProgressBar:
+	push	cs
+	pop		ds
+	mov		si, g_dialogInputOutput
+	mov		WORD [si+PROGRESS_DIALOG_IO.wCurrentProgressValue], 0
+	mov		WORD [si+PROGRESS_DIALOG_IO.wMaxProgressValue], 500
+	mov		WORD [si+PROGRESS_DIALOG_IO.wMinProgressValue], 0
+	mov		WORD [si+PROGRESS_DIALOG_IO.fnTaskWithParamInDSSI], .ProgressTaskWithParamInDSSI
+	mov		ax, 500			; Counter for progress task
+	CALL_MENU_LIBRARY StartProgressTaskWithIoInDSSIandParamInDXAX
+	stc
+	ret
+
+ALIGN JUMP_ALIGN
+.ProgressTaskWithParamInDSSI:
+	mov		ax, 50000					; 50 millisec delay
+	call	Delay_MicrosecondsFromAX
+	dec		si
+	CALL_MENU_LIBRARY SetUserDataFromDSSI
+	mov		ax, 500
+	sub		ax, si
+	push	si
+	CALL_MENU_LIBRARY SetProgressValueFromAX
+	pop		si
+	test	si, si
+	jnz		.ProgressTaskWithParamInDSSI
+	ret
+	
+	
+
+ALIGN WORD_ALIGN
+.rgfnMenuEvents:
+	dw		.InitializeMenu		; .InitializeMenuinitToDSSI
+	dw		.NotHandled			; .ExitMenu
+	dw		.NotHandled			; .IdleProcessing
+	dw		.NotHandled			; .ItemHighlightedFromCX
+	dw		.ItemSelectedFromCX	; .ItemSelectedFromCX
+	dw		.NotHandled			; .KeyStrokeInDX
+	dw		.RefreshTitle		; .RefreshTitle
+	dw		.RefreshInformation	; .RefreshInformation
+	dw		.RefreshItemFromCX	; .RefreshItemFromCX
+
+.rgszItems:
+	dw		.szExitMenu
+	dw		.szToggleTitle
+	dw		.szToggleInfo
+	dw		.szShowMessage
+	dw		.szAskWord
+	dw		.szAskString
+	dw		.szAskSelection
+	dw		.szAskFile
+	dw		.szTestProgress
+.szExitMenu:	db	"Exit menu",NULL
+.szToggleTitle:	db	"Toggle title",NULL
+.szToggleInfo:	db	"Toggle information",NULL
+.szShowMessage:	db	"Display unformatted message",NULL
+.szAskWord:		db	"Input word",NULL
+.szAskString:	db	"Input string",NULL
+.szAskSelection:db	"Display selection dialog",NULL
+.szAskFile:		db	"Display file dialog",NULL
+.szTestProgress:db	"Display progress bar",NULL
+TEST_MENU_VALID_ITEMS			EQU		9
+TEST_MENU_TITLE_LINES			EQU		2
+TEST_MENU_INFO_LINES			EQU		3
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ALIGN JUMP_ALIGN
+LibraryTests_ForKeyboardLibrary:
+	mov		ax, CURSOR_XY(0, 6)
+	CALL_DISPLAY_LIBRARY SetCursorCoordinatesFromAX
+	call	ReadUnsignedDecimalInteger
+	call	ReadHexadecimalWord
+	ret
+
+
+ReadUnsignedDecimalInteger:
+	mov		si, .szEnterUnsignedWord
+	CALL_DISPLAY_LIBRARY PrintNullTerminatedStringFromCSSI
+	CALL_DISPLAY_LIBRARY SynchronizeDisplayContextToHardware	; Move hardware cursor
+
+	mov		bx, 10			; Numeric base
+	call	Keyboard_ReadUserInputtedWordWhilePrinting
+
+	mov		si, .szWordEntered
+	mov		bp, sp
+	push	ax
+	CALL_DISPLAY_LIBRARY FormatNullTerminatedStringFromCSSI
+	ret
+.szWordEntered:
+	db	". Word entered: %u",LF,CR,NULL
+.szEnterUnsignedWord:
+	db	"Enter unsigned word: ",NULL
+
+
+ReadHexadecimalWord:
+	mov		si, .szEnterHexadecimalWord
+	CALL_DISPLAY_LIBRARY PrintNullTerminatedStringFromCSSI
+	CALL_DISPLAY_LIBRARY SynchronizeDisplayContextToHardware	; Move hardware cursor
+
+	mov		bx, 16			; Numeric base
+	call	Keyboard_ReadUserInputtedWordWhilePrinting
+
+	mov		si, .szWordEntered
+	mov		bp, sp
+	push	ax
+	CALL_DISPLAY_LIBRARY FormatNullTerminatedStringFromCSSI
+	ret
+.szWordEntered:
+	db	". Word entered: %x",LF,CR,NULL
+.szEnterHexadecimalWord:
+	db	"Enter hexadecimal word: ",NULL
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ALIGN JUMP_ALIGN
+LibraryTests_ForDisplayLibrary:
+	CALL_DISPLAY_LIBRARY PushDisplayContext
+	call	PrintHorizontalRuler
+	call	PrintVerticalRuler
+
+	mov		ax, CURSOR_XY(0, 1)
+	CALL_DISPLAY_LIBRARY SetCursorCoordinatesFromAX
+	mov		al, COLOR_ATTRIBUTE(COLOR_BRIGHT_WHITE, COLOR_BLACK)
+	CALL_DISPLAY_LIBRARY SetCharacterAttributeFromAL
+	call	PrintFormattedStrings
+
+	CALL_DISPLAY_LIBRARY PopDisplayContext
+	ret
+
+
+PrintHorizontalRuler:
+	mov		ax, CURSOR_XY(0, 0)
+	CALL_DISPLAY_LIBRARY SetCursorCoordinatesFromAX
+	CALL_DISPLAY_LIBRARY GetColumnsToALandRowsToAH
+	eMOVZX	cx, al
+	mov		bx, 10<<8			; Divider 10 to BH
+.ColumnNumberLoop:
+	eMOVZX	ax, bl				; Column index to AX (0...79)
+	div		bh					; AH = 0...9, AL = attribute
+	mov		dx, ax
+	inc		ax					; Increment attribute for non-black foreground
+	CALL_DISPLAY_LIBRARY SetCharacterAttributeFromAL
+	xchg	ax, dx
+	mov		al, '0'
+	add		al, ah				; AL = '0'...'9'
+	CALL_DISPLAY_LIBRARY PrintCharacterFromAL
+	inc		bx					; Increment column index
+	loop	.ColumnNumberLoop
+	ret
+
+
+PrintVerticalRuler:
+	CALL_DISPLAY_LIBRARY GetColumnsToALandRowsToAH
+	eMOVZX	cx, ah				; Number of rows to CX
+	dec		ax					; Last column
+	xor		ah, ah
+	CALL_DISPLAY_LIBRARY SetCursorCoordinatesFromAX
+
+	dec		cx					; Decrement rows to print last row outside loop
+	mov		bx, 10<<8			; BH = 10 (divider), BL = 0 (row index)
+	mov		si, .szVerticalRulerCharacter
+.RowNumberLoop:
+	call	.PrintRowNumberFromBL
+	inc		bx					; Increment row index
+	loop	.RowNumberLoop
+
+	; Last row
+	mov		si, .szLastVerticalRulerCharacter
+.PrintRowNumberFromBL:
+	eMOVZX	ax, bl				; Row index to AX (0...24)
+	div		bh					; AH = 0...9, AL = attribute
+	add		al, COLOR_GRAY		; Start from color GRAY
+	mov		bp, sp				; Prepare BP for string formatting
+	push	ax					; Push attribute
+	eMOVZX	ax, ah
+	push	ax					; Push row index
+	CALL_DISPLAY_LIBRARY FormatNullTerminatedStringFromCSSI
+	ret
+
+.szVerticalRulerCharacter:
+	db	"%A%u",LF,NULL
+.szLastVerticalRulerCharacter:
+	db	"%A%u",NULL
+
+
+PrintFormattedStrings:
+	call	.PrintIntegers
+	call	.PrintHexadecimals
+	call	.PrintCharacters
+	call	.PrintStrings
+	call	.RepeatChar
+	ret
+
+.PrintIntegers:
+	mov		si, .szIntegers
+	mov		bp, sp
+	ePUSH_T	ax, COLOR_ATTRIBUTE(COLOR_RED, COLOR_BLACK)
+	ePUSH_T	ax, -32768
+	ePUSH_T	ax, -1
+	ePUSH_T	ax, 0
+	ePUSH_T	ax, 1
+	ePUSH_T	ax, 65535
+	CALL_DISPLAY_LIBRARY FormatNullTerminatedStringFromCSSI
+	ret
+.szIntegers:
+	db	"Integers -32768, -1, 0, 1, 65535:          %A|%6d|%6d|%6d|%6d|%6u|",LF,CR,NULL
+
+.PrintHexadecimals:
+	mov		si, .szHexadecimals
+	mov		bp, sp
+	ePUSH_T	ax, COLOR_ATTRIBUTE(COLOR_RED, COLOR_BLACK)
+	ePUSH_T	ax, 0CACAh
+	ePUSH_T	ax, 0FFFFh
+	ePUSH_T	ax, 0
+	ePUSH_T	ax, 5A5Ah
+	ePUSH_T	ax, 0A5A5h
+	CALL_DISPLAY_LIBRARY FormatNullTerminatedStringFromCSSI
+	ret
+.szHexadecimals:
+	db	"Hexadecimals CACAh, FFFFh, 0, 5A5Ah, A5A5h:%A|%6x|%6x|%6x|%6x|%6x|",LF,CR,NULL
+
+.PrintCharacters:
+	mov		si, .szCharacters
+	mov		bp, sp
+	ePUSH_T	ax, COLOR_ATTRIBUTE(COLOR_RED, COLOR_BLACK)
+	ePUSH_T	ax, 'a'
+	ePUSH_T	ax, 'B'
+	ePUSH_T	ax, 'c'
+	ePUSH_T	ax, 'D'
+	CALL_DISPLAY_LIBRARY FormatNullTerminatedStringFromCSSI
+	ret
+.szCharacters:
+	db	"Characters a, B, c, D, percent:            %A|%6c|%6c|%6c|%6c|%6%|",LF,CR,NULL
+
+.PrintStrings:
+	mov		si, .szStrings
+	mov		bp, sp
+	ePUSH_T	ax, COLOR_ATTRIBUTE(COLOR_RED, COLOR_BLACK)
+	ePUSH_T	ax, .szCSSI
+	ePUSH_T	ax, .szFar
+	push	cs
+	CALL_DISPLAY_LIBRARY FormatNullTerminatedStringFromCSSI
+	ret
+.szStrings:
+	db	"Strings ",'"',"Hello CSSI",'"'," and ",'"',"Far",'"',":            %A|%20s|%13S|",LF,CR,NULL
+.szCSSI:
+	db	"Hello CSSI",NULL
+.szFar:
+	db	"Far",NULL
+	
+.RepeatChar:
+	mov		si, .szRepeat
+	mov		bp, sp
+	ePUSH_T	ax, COLOR_ATTRIBUTE(COLOR_RED, COLOR_BLACK)
+	ePUSH_T	ax, '-'
+	ePUSH_T	ax, 36
+	CALL_DISPLAY_LIBRARY FormatNullTerminatedStringFromCSSI
+	ret
+.szRepeat:
+	db	"Repeating character '-':                   %A%t",LF,CR,NULL
+		
+
+
+; Section containing initialized data
+;SECTION .data
+
+g_szDialogTitle:
+	db		"This is a generic title for all dialogs.",NULL
+g_szDialogInfo:
+	db		"This is a generic information for all dialogs.",NULL
+g_szVeryLongString:
+	db		"This is a very long string containing multiple lines of text. This is needed "
+	db		"so scroll bars and message dialog can be tested. This string does not use "
+	db		"formatting so it should be simple to display this correctly. This string "
+	db		"does, however, use newline characters. Lets change line right now!",CR,LF,
+	db		"Well did it work? Let's try line feed alone",LF,"Well? "
+	db		"We could also see what two spaces does _  _. There was two spaces between "
+	db		"underscores. Lets try three this time _   _. Well, did they work correctly? "
+	db		"What next, I guess that was all, no wait. Let's see what TAB does! Here it "
+	db		"goes:",TAB,"Well did it work? Just one more time:",TAB,"Well are we good? "
+	db		"No since LF is the only supported control character, unfortunately. "
+	db		"This is the last sentence of this long string!",NULL
+
+g_dialogInputOutput:
+istruc DIALOG_INPUT
+	at	DIALOG_INPUT.fszTitle,	dw	g_szDialogTitle
+	at	DIALOG_INPUT.fszInfo,	dw	g_szDialogInfo
+iend
+	times	20	db	0
+
+
+; Section containing uninitialized data
+SECTION .bss
+
+STRING_BUFFER_SIZE			EQU		100
+g_szBuffer:
Index: /trunk/Assembly_Library/Src/Menu/Dialog/Dialog.asm
===================================================================
--- /trunk/Assembly_Library/Src/Menu/Dialog/Dialog.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Menu/Dialog/Dialog.asm	(revision 41)
@@ -0,0 +1,307 @@
+; File name		:	Dialog.asm
+; Project name	:	Assembly Library
+; Created date	:	6.8.2010
+; Last update	:	16.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Common functions for many dialogs.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Dialog_DisplayWithDialogInputInDSSIandHandlerInBX
+;	Parameters:
+;		BX:		Offset to menu event handler
+;		DX:AX:	Optional user data
+;		DS:SI:	Ptr to DIALOG_INPUT
+;		SS:BP:	Ptr to parent MENU
+;	Returns:
+;		AX:		Selected item
+;	Corrupts registers:
+;		BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Dialog_DisplayWithDialogInputInDSSIandHandlerInBX:
+	push	es
+	push	ds
+	mov		di, bp								; Backup parent MENU
+	eENTER_STRUCT DIALOG_size
+
+	mov		cx, DIALOG_size / 2
+	call	Memory_ZeroSSBPbyWordsInCX
+	mov		[bp+DIALOG.fpDialogIO], si
+	mov		[bp+DIALOG.fpDialogIO+2], ds
+	mov		[bp+DIALOG.pParentMenu], di
+
+	call	MenuInit_EnterMenuWithHandlerInBXandUserDataInDXAX
+	call	Dialog_RemoveFromScreenByRedrawingParentMenu
+	call	Keyboard_RemoveAllKeystrokesFromBuffer
+
+	mov		ax, [bp+MENU.wHighlightedItem]
+	eLEAVE_STRUCT DIALOG_size
+	pop		ds
+	pop		es
+	ret
+
+
+;--------------------------------------------------------------------
+; Dialog_EventNotHandled
+;	Parameters:
+;		BX:		Menu event (anything from MENUEVENT struct)
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		CF:		Cleared since event not processed
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Dialog_EventNotHandled:
+	clc
+	ret
+
+
+;--------------------------------------------------------------------
+; Dialog_EventAnyThatClosesDialog
+;	Parameters:
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		CF:		Set since event processed
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Dialog_EventAnyThatClosesDialog:
+	call	MenuInit_CloseMenuWindow
+	stc
+	ret
+
+
+;--------------------------------------------------------------------
+; Dialog_EventInitializeMenuinitFromDSSIforSingleItem
+;	Parameters:
+;		DS:SI:		Ptr to MENUINIT struct to initialize
+;		SS:BP:		Ptr to DIALOG
+;	Returns:
+;		DS:SI:		Ptr to initialized MENUINIT struct
+;		CF:			Set since event processed
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Dialog_EventInitializeMenuinitFromDSSIforSingleItem:
+	les		di, [bp+DIALOG.fpDialogIO]
+	mov		WORD [es:di+DIALOG_INPUT.fszItems], g_szSingleItem
+	mov		[es:di+DIALOG_INPUT.fszItems+2], cs
+	; Fall to Dialog_EventInitializeMenuinitFromDSSI
+
+;--------------------------------------------------------------------
+; Dialog_EventInitializeMenuinitFromDSSI
+;	Parameters:
+;		DS:SI:		Ptr to MENUINIT struct to initialize
+;		SS:BP:		Ptr to DIALOG
+;	Returns:
+;		DS:SI:		Ptr to initialized MENUINIT struct
+;		CF:			Set since event processed
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Dialog_EventInitializeMenuinitFromDSSI:
+	les		di, [bp+DIALOG.fpDialogIO]
+	call	.GetWidthBasedOnParentMenuToAL
+	mov		[bp+MENUINIT.bWidth], al
+
+	call	MenuLocation_GetMaxTextLineLengthToAX
+	mov		bx, ax
+	lds		si, [es:di+DIALOG_INPUT.fszTitle]
+	call	LineSplitter_SplitStringFromDSSIwithMaxLineLengthInAXandGetLineCountToAX
+	mov		[bp+MENUINIT.bTitleLines], al
+
+	mov		ax, bx
+	lds		si, [es:di+DIALOG_INPUT.fszItems]
+	call	LineSplitter_SplitStringFromDSSIwithMaxLineLengthInAXandGetLineCountToAX
+	mov		[bp+MENUINIT.wItems], ax
+
+	xchg	ax, bx
+	lds		si, [es:di+DIALOG_INPUT.fszInfo]
+	call	LineSplitter_SplitStringFromDSSIwithMaxLineLengthInAXandGetLineCountToAX
+	mov		[bp+MENUINIT.bInfoLines], al
+
+	call	.GetHeightToAH				; Line counts are required
+	mov		[bp+MENUINIT.bHeight], ah
+	stc
+	ret
+
+;--------------------------------------------------------------------
+; .GetWidthBasedOnParentMenuToAL
+;	Parameters:
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		AX:		Width for dialog
+;	Corrupts registers:
+;		BX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.GetWidthBasedOnParentMenuToAL:
+	mov		bx, [bp+DIALOG.pParentMenu]
+	mov		al, [ss:bx+MENUINIT.bWidth]
+	sub		al, DIALOG_DELTA_WIDTH_FROM_PARENT
+	MIN_U	al, DIALOG_MAX_WIDTH
+	ret
+
+;--------------------------------------------------------------------
+; .GetHeightToAH
+;	Parameters:
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		AH:		Height for dialog
+;	Corrupts registers:
+;		AL, BX, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.GetHeightToAH:
+	CALL_DISPLAY_LIBRARY GetColumnsToALandRowsToAH
+	xchg	bx, ax
+	mov		ah, [bp+MENUINIT.bTitleLines]
+	add		ah, [bp+MENUINIT.wItems]
+	add		ah, [bp+MENUINIT.bInfoLines]
+	add		ah, BYTE MENU_VERTICAL_BORDER_LINES
+	MIN_U	ah, bh
+	MIN_U	ah, DIALOG_MAX_HEIGHT
+	ret
+
+
+;--------------------------------------------------------------------
+; Dialog_EventRefreshTitle
+; Dialog_EventRefreshInformation
+;	Parameters:
+;		SS:BP:		Ptr to DIALOG
+;	Returns:
+;		CF:			Set since event processed
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Dialog_EventRefreshTitle:
+	mov		dl, [bp+MENUINIT.bTitleLines]
+	lds		si, [bp+DIALOG.fpDialogIO]
+	les		di, [si+DIALOG_INPUT.fszTitle]
+	jmp		SHORT PrintDLlinesFromESDI
+
+ALIGN JUMP_ALIGN
+Dialog_EventRefreshInformation:
+	mov		dl, [bp+MENUINIT.bInfoLines]
+	lds		si, [bp+DIALOG.fpDialogIO]
+	les		di, [si+DIALOG_INPUT.fszInfo]
+	; Fall to PrintDLlinesFromESDI
+
+ALIGN JUMP_ALIGN
+PrintDLlinesFromESDI:
+	xor		cx, cx				; Start from line zero
+	mov		dh, cl				; Line count now in DX
+ALIGN JUMP_ALIGN
+.PrintNextLine:
+	call	LineSplitter_PrintLineInCXfromStringInESDI
+	push	di
+	CALL_DISPLAY_LIBRARY PrintNewlineCharacters
+	pop		di
+	inc		cx
+	dec		dx
+	jnz		SHORT .PrintNextLine
+	stc
+	ret
+
+
+;--------------------------------------------------------------------
+; Dialog_EventRefreshItemFromCX
+;	Parameters:
+;		CX:			Item to refresh
+;		SS:BP:		Ptr to DIALOG
+;	Returns:
+;		CF:			Set since event processed
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Dialog_EventRefreshItemFromCX:
+	lds		si, [bp+DIALOG.fpDialogIO]
+	les		di, [si+DIALOG_INPUT.fszItems]
+	call	LineSplitter_PrintLineInCXfromStringInESDI
+	stc
+	ret
+
+
+;--------------------------------------------------------------------
+; Dialog_RemoveFromScreenByRedrawingParentMenu
+;	Parameters:
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		Nothing
+;	Corrupts:
+;		AX, BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Dialog_RemoveFromScreenByRedrawingParentMenu:
+	mov		si, [bp+DIALOG.pParentMenu]	; SS:SI points to parent MENU
+	call	.ResetSelectionTimeoutFromParentMenuInSSSI
+	call	.GetParentTitleBorderCoordinatesToDX
+	call	MenuLocation_GetTitleBordersTopLeftCoordinatesToAX
+	cmp		ah, dh		; Dialog taller than parent?
+	jb		SHORT .RedrawDialogAreaAndWholeParentWindow
+	jmp		SHORT .RedrawWholeParentWindow
+
+;--------------------------------------------------------------------
+; .ResetSelectionTimeoutFromParentMenuInSSSI
+;	Parameters:
+;		SS:SI:	Ptr to parent MENU
+;	Returns:
+;		Nothing
+;	Corrupts:
+;		AX, BX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.ResetSelectionTimeoutFromParentMenuInSSSI:
+	xchg	bp, si
+	call	MenuTime_RestartSelectionTimeout	; Restart timeout for parent MENU
+	xchg	si, bp
+	ret
+
+;--------------------------------------------------------------------
+; .GetParentTitleBorderCoordinatesToDX
+;	Parameters:
+;		SS:SI:	Ptr to parent MENU
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		DL:		Parent border column (X)
+;		DH:		Parent border row (Y)
+;	Corrupts:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.GetParentTitleBorderCoordinatesToDX:
+	xchg	si, bp
+	call	MenuLocation_GetTitleBordersTopLeftCoordinatesToAX
+	xchg	bp, si
+	xchg	dx, ax
+	ret
+
+;--------------------------------------------------------------------
+; .RedrawDialogAreaAndWholeParentWindow
+; .RedrawWholeParentWindow
+;	Parameters:
+;		SS:SI:	Ptr to parent MENU
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		Nothing
+;	Corrupts:
+;		AX, BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.RedrawDialogAreaAndWholeParentWindow:
+	mov		al, MONO_NORMAL
+	CALL_DISPLAY_LIBRARY SetCharacterAttributeFromAL
+	call	MenuLocation_GetTitleBordersTopLeftCoordinatesToAX
+	CALL_DISPLAY_LIBRARY SetCursorCoordinatesFromAX
+	mov		ax, [bp+MENUINIT.wWidthAndHeight]
+	CALL_DISPLAY_LIBRARY ClearAreaWithHeightInAHandWidthInAL
+	; Fall to .RedrawWholeParentWindow
+
+ALIGN JUMP_ALIGN
+.RedrawWholeParentWindow:
+	push	bp
+	mov		bp, si
+	call	MenuInit_RefreshMenuWindow
+	pop		bp
+	ret
Index: /trunk/Assembly_Library/Src/Menu/Dialog/DialogFile.asm
===================================================================
--- /trunk/Assembly_Library/Src/Menu/Dialog/DialogFile.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Menu/Dialog/DialogFile.asm	(revision 41)
@@ -0,0 +1,673 @@
+; File name		:	DialogFile.asm
+; Project name	:	Assembly Library
+; Created date	:	6.9.2010
+; Last update	:	16.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Displays file dialog.
+
+
+CURRENTDIR_CHARACTERS	EQU		002Eh
+UPDIR_CHARACTERS		EQU		2E2Eh
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; DialogFile_GetFileNameWithIoInDSSI
+;	Parameters:
+;		DS:SI:	Ptr to FILE_DIALOG_IO
+;		SS:BP:	Ptr to parent MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DialogFile_GetFileNameWithIoInDSSI:
+	mov		bx, FileEventHandler
+	mov		BYTE [si+FILE_DIALOG_IO.bUserCancellation], TRUE
+	jmp		Dialog_DisplayWithDialogInputInDSSIandHandlerInBX
+
+
+;--------------------------------------------------------------------
+; FileEventHandler
+;	Common parameters for all events:
+;		BX:			Menu event (anything from MENUEVENT struct)
+;		SS:BP:		Ptr to DIALOG
+;	Common return values for all events:
+;		CF:			Set if event processed
+;					Cleared if event not processed
+;	Corrupts registers:
+;		All
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+FileEventHandler:
+	jmp		[cs:bx+.rgfnEventHandlers]
+
+
+ALIGN JUMP_ALIGN
+.ItemSelectedFromCX:
+	call	LoadItemStringBufferToESDI
+	call	LineSplitter_GetOffsetToSIforLineCXfromStringInESDI
+	push	es
+	pop		ds
+	jmp		ParseSelectionFromItemLineInDSSI
+
+
+ALIGN JUMP_ALIGN
+.RefreshInformation:
+	call	GetInfoLinesToCXandDialogFlagsToAX
+	mov		si, [cs:.rgszInfoStringLookup]
+	xor		bx, bx
+	xchg	dx, ax
+ALIGN JUMP_ALIGN
+.InfoLineLoop:
+	shr		dl, 1
+	jnc		SHORT .CheckNextFlag
+	mov		si, [cs:bx+.rgszInfoStringLookup]
+	push	bx
+	CALL_DISPLAY_LIBRARY PrintNullTerminatedStringFromCSSI
+	pop		bx
+ALIGN JUMP_ALIGN
+.CheckNextFlag:
+	inc		bx
+	inc		bx
+	loop	.InfoLineLoop
+	stc						; Event processed
+	ret
+
+
+ALIGN WORD_ALIGN
+.rgszInfoStringLookup:
+	dw		g_szChangeDrive
+	dw		g_szSelectDirectory
+	dw		g_szCreateNew
+
+.rgfnEventHandlers:
+istruc MENUEVENT
+	at	MENUEVENT.InitializeMenuinitFromDSSI,	dw	InitializeMenuinitFromSSBP
+	at	MENUEVENT.ExitMenu,						dw	Dialog_EventNotHandled
+	at	MENUEVENT.IdleProcessing,				dw	Dialog_EventNotHandled
+	at	MENUEVENT.ItemHighlightedFromCX,		dw	Dialog_EventNotHandled
+	at	MENUEVENT.ItemSelectedFromCX,			dw	.ItemSelectedFromCX
+	at	MENUEVENT.KeyStrokeInAX,				dw	HandleFunctionKeyFromAH
+	at	MENUEVENT.RefreshTitle,					dw	Dialog_EventRefreshTitle
+	at	MENUEVENT.RefreshInformation,			dw	.RefreshInformation
+	at	MENUEVENT.RefreshItemFromCX,			dw	Dialog_EventRefreshItemFromCX
+iend
+
+
+;--------------------------------------------------------------------
+; InitializeMenuinitFromSSBP
+;	Parameters:
+;		DS:SI:		Ptr to MENUINIT to initialize (also points to DIALOG)
+;		SS:BP:		Ptr to DIALOG
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		All, except BP
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+InitializeMenuinitFromSSBP:
+	call	LoadItemStringBufferToESDI
+	call	CreateStringFromCurrentDirectoryContentsToESDI
+	push	ss
+	pop		ds
+	mov		si, bp
+	call	Dialog_EventInitializeMenuinitFromDSSI
+	call	GetInfoLinesToCXandDialogFlagsToAX
+	mov		[bp+MENUINIT.bInfoLines], cl
+	CALL_DISPLAY_LIBRARY GetColumnsToALandRowsToAH
+	mov		[bp+MENUINIT.bHeight], ah				; Always max height
+	mov		WORD [bp+MENU.wHighlightedItem], 0
+	ret
+
+
+;--------------------------------------------------------------------
+; LoadItemStringBufferToESDI
+;	Parameters:
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		ES:DI:	Ptr to item string buffer
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+LoadItemStringBufferToESDI:
+	les		di, [bp+DIALOG.fpDialogIO]
+	les		di, [es:di+FILE_DIALOG_IO.fszItemBuffer]
+	ret
+
+
+;--------------------------------------------------------------------
+; CreateStringFromCurrentDirectoryContentsToESDI
+;	Parameters:
+;		ES:DI:	Buffer where to create item string
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, SI, DI, DS, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+CreateStringFromCurrentDirectoryContentsToESDI:
+	lds		si, [bp+DIALOG.fpDialogIO]
+	eMOVZX	cx, BYTE [si+FILE_DIALOG_IO.bFileAttributes]
+	lds		si, [si+FILE_DIALOG_IO.fpFileFilterString]
+	call	Directory_UpdateDTAForFirstMatchForDSSIwithAttributesInCX
+	rcr		cx, 1			; Store CF
+	call	.ClearDLifInRootDirectory
+	call	Directory_GetDiskTransferAreaAddressToDSSI
+	rcl		cx, 1			; Restore CF
+	; Fall to .FindMatchingFilesAndWriteThemToESDI
+
+;--------------------------------------------------------------------
+; .FindMatchingFilesAndWriteThemToESDI
+;	Parameters:
+;		DL:		Zero if root directory selected
+;		DS:SI:	Ptr to DTA with first matching file
+;		ES:DI:	Ptr to destination string buffer
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DI
+;--------------------------------------------------------------------
+;ALIGN JUMP_ALIGN
+.FindMatchingFilesAndWriteThemToESDI:
+	jc		SHORT RemoveLastLFandTerminateESDIwithNull
+	call	AppendFileToBufferInESDIfromDtaInDSSI
+	call	Directory_UpdateDTAForNextMatchUsingPreviousParameters
+	jmp		SHORT .FindMatchingFilesAndWriteThemToESDI
+
+;--------------------------------------------------------------------
+; .ClearDLifInRootDirectory
+;	Parameters:
+;		SS:BP:	Ptr to DIALOG
+;		ES:DI:	Ptr to destination string buffer
+;	Returns:
+;		DL:		Cleared if in root directory
+;				Set if in any other directory
+;	Corrupts registers:
+;		AX, SI, DS
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.ClearDLifInRootDirectory:
+	push	es
+	pop		ds
+	mov		si, di
+	call	Directory_WriteCurrentPathToDSSI
+	mov		dl, [si]
+	ret
+
+;--------------------------------------------------------------------
+; RemoveLastLFandTerminateESDIwithNull
+;	Parameters:
+;		ES:DI:	Ptr to destination string buffer
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+RemoveLastLFandTerminateESDIwithNull:
+	xor		ax, ax
+	dec		di				; Remove last LF
+	stosb
+	ret
+
+;--------------------------------------------------------------------
+; AppendFileToBufferInESDIfromDtaInDSSI
+;	Parameters:
+;		DL:		Zero if root directory selected
+;		DS:SI:	Ptr to DTA containing file information
+;		ES:DI:	Ptr to destination string buffer
+;	Returns:
+;		DI:		Updated for next file
+;	Corrupts registers:
+;		AX, BX, CX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+AppendFileToBufferInESDIfromDtaInDSSI:
+	call	.FilterCurrentDirectory			; We never want "."
+	call	.FilterUpDirectoryWhenInRoot	; No ".." when in root directory
+	; Fall to .PrepareBufferFormattingAndFormatFromDTAinDSSI
+
+;--------------------------------------------------------------------
+; .PrepareBufferFormattingAndFormatFromDTAinDSSI
+;	Parameters:
+;		DS:SI:	Ptr to DTA containing file information
+;		ES:DI:	Ptr to destination string buffer
+;	Returns:
+;		DI:		Updated for next file
+;	Corrupts registers:
+;		AX, BX, CX
+;--------------------------------------------------------------------
+;ALIGN JUMP_ALIGN
+.PrepareBufferFormattingAndFormatFromDTAinDSSI:
+	push	bp
+	push	si
+	mov		cx, di
+	CALL_DISPLAY_LIBRARY PushDisplayContext
+
+	mov		bx, es
+	xchg	ax, cx
+	CALL_DISPLAY_LIBRARY SetCharacterPointerFromBXAX
+	mov		ax, BUFFER_OUTPUT_WITH_CHAR_ONLY
+	CALL_DISPLAY_LIBRARY SetCharacterOutputFunctionFromAX
+
+	call	.FormatFileOrDirectoryToBufferFromDTAinDSSI
+
+	CALL_DISPLAY_LIBRARY GetCharacterPointerToBXAX
+	mov		es, bx
+	xchg	cx, ax
+	CALL_DISPLAY_LIBRARY PopDisplayContext
+	mov		di, cx
+	pop		si
+	pop		bp
+	ret
+
+;--------------------------------------------------------------------
+; .FormatFileOrDirectoryToBufferFromDTAinDSSI
+;	Parameters:
+;		DS:SI:	Ptr to DTA containing file information
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI, BP
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.FormatFileOrDirectoryToBufferFromDTAinDSSI:
+	mov		bp, sp
+	lea		ax, [si+DTA.szFile]
+	push	ax
+	push	ds
+
+	test	BYTE [si+DTA.bFileAttributes], FLG_FILEATTR_DIRECTORY
+	jnz		SHORT .FormatDirectory
+
+	mov		ax, [si+DTA.dwFileSize]
+	mov		dx, [si+DTA.dwFileSize+2]
+	xor		bx, bx
+	xor		cx, cx
+	call	Size_GetSizeToAXAndCharToDLfromBXDXAXwithMagnitudeInCX
+	mov		cl, 'i'
+	cmp		dl, ' '
+	eCMOVE	cl, dl
+	push	ax
+	push	dx
+	push	cx
+	mov		si, g_szFileFormat
+	jmp		SHORT .FormatStringInCSSIandReturn
+
+ALIGN JUMP_ALIGN
+.FormatDirectory:
+	mov		ax, g_szSub
+	cmp		WORD [si+DTA.szFile], UPDIR_CHARACTERS
+	eCMOVE	ax, g_szUp
+	push	ax
+	mov		si, g_szDirectoryFormat
+ALIGN JUMP_ALIGN
+.FormatStringInCSSIandReturn:
+	CALL_DISPLAY_LIBRARY FormatNullTerminatedStringFromCSSI
+	ret
+
+;--------------------------------------------------------------------
+; .FilterCurrentDirectory
+; .FilterUpDirectoryWhenInRoot
+;	Parameters:
+;		DL:		Zero if root directory selected
+;		DS:SI:	Ptr to DTA containing file information
+;	Returns:
+;		Nothing
+;		Returns from AppendFileToBufferInESDIfromDtaInDSSI when filtering
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.FilterCurrentDirectory:
+	cmp		WORD [si+DTA.szFile], CURRENTDIR_CHARACTERS
+	jne		SHORT .ReturnWithoutFiltering
+	add		sp, BYTE 2		; Remove return address from stack
+	ret
+
+ALIGN JUMP_ALIGN
+.FilterUpDirectoryWhenInRoot:
+	test	dl, dl			; Set ZF if root directory selected
+	jnz		SHORT .ReturnWithoutFiltering
+	cmp		WORD [si+DTA.szFile], UPDIR_CHARACTERS
+	jne		SHORT .ReturnWithoutFiltering
+	add		sp, BYTE 2		; Remove return address from stack
+ALIGN JUMP_ALIGN, ret
+.ReturnWithoutFiltering:
+	ret
+
+
+;--------------------------------------------------------------------
+; GetInfoLinesToCXandDialogFlagsToAX
+;	Parameters:
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		AX:		Dialog flags
+;		CX:		Number of info lines to be displayed
+;	Corrupts registers:
+;		SI, DS
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+GetInfoLinesToCXandDialogFlagsToAX:
+	xor		ax, ax
+	call	GetDialogFlagsToAL
+	jmp		Bit_GetSetCountToCXfromAX
+
+;--------------------------------------------------------------------
+; GetDialogFlagsToAL
+;	Parameters:
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		AL:		Dialog flags
+;	Corrupts registers:
+;		SI, DS
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+GetDialogFlagsToAL:
+	lds		si, [bp+DIALOG.fpDialogIO]
+	mov		al, [si+FILE_DIALOG_IO.bDialogFlags]
+	ret
+
+
+;--------------------------------------------------------------------
+; ParseSelectionFromItemLineInDSSI
+;	Parameters:
+;		DS:SI:	Ptr to char buffer containing file or directory to be selected
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		All, except BP
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+ParseSelectionFromItemLineInDSSI:
+	cmp		BYTE [si], '['
+	je		SHORT .ChangeToSubdirInDSSI
+	; Fall to .SelectFileFromDSSI
+
+;--------------------------------------------------------------------
+; .SelectFileFromDSSI
+;	Parameters:
+;		DS:SI:	Ptr to char buffer containing file name to be selected
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		Nothing (exits dialog)
+;	Corrupts registers:
+;		All, except BP
+;--------------------------------------------------------------------
+;ALIGN JUMP_ALIGN
+.SelectFileFromDSSI:
+	les		di, [bp+DIALOG.fpDialogIO]
+	add		di, BYTE FILE_DIALOG_IO.szFile
+	mov		cx, FILENAME_BUFFER_SIZE-1
+	cld
+	rep movsb
+	xor		ax, ax
+	stosb						; Terminate with NULL
+	jmp		CloseFileDialogAfterSuccessfullSelection
+
+;--------------------------------------------------------------------
+; ChangeToSubdirInDSSI
+;	Parameters:
+;		DS:SI:	NULL terminated string containing new subdir in []
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		All, except BP
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.ChangeToSubdirInDSSI:
+	inc		si					; Skip '['
+	mov		BYTE [si+12], NULL	; Replace ']' with NULL
+	cmp		WORD [si], UPDIR_CHARACTERS
+	eCMOVE	si, g_szUpdir		; Real DOS do not accept spaces after ".."
+	call	Directory_ChangeToPathFromDSSI
+	; Fall to RefreshFilesToDisplay
+
+;--------------------------------------------------------------------
+; RefreshFilesToDisplay
+;	Parameters:
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		All, except BP
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+RefreshFilesToDisplay:
+	call	InitializeMenuinitFromSSBP
+	jmp		MenuInit_RefreshMenuWindow
+
+
+;--------------------------------------------------------------------
+; HandleFunctionKeyFromAH
+;	Parameters:
+;		AH:		Scancode for function key
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, SI, DI, BP
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+HandleFunctionKeyFromAH:
+	call	GetDialogFlagsToAL
+	cmp		ah, KEY_FILEDIALOG_NEW_FILE_OR_DIR
+	je		SHORT HandleFunctionKeyForCreatingNewFileOrDirectory
+	cmp		ah, KEY_FILEDIALOG_SELECT_DIRECTORY
+	je		SHORT HandleFunctionKeyForSelectingDirectoryInsteadOfFile
+	cmp		ah, KEY_FILEDIALOG_CHANGE_DRIVE
+	je		SHORT HandleFunctionKeyForDriveChange
+ReturnWithoutHandlingKeystroke:
+	clc		; Event not processed
+	ret
+
+
+;--------------------------------------------------------------------
+; HandleFunctionKeyForCreatingNewFileOrDirectory
+;	Parameters:
+;		AL:		File dialog flags
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		Closes file dialog
+;	Corrupts registers:
+;		All, except BP
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+HandleFunctionKeyForCreatingNewFileOrDirectory:
+	test	al, FLG_FILEDIALOG_NEW
+	jz		SHORT ReturnWithoutHandlingKeystroke
+
+	mov		cx, STRING_DIALOG_IO_size
+	call	Memory_ReserveCXbytesFromStackToDSSI
+	call	.InitializeStringDialogIoInDSSIforInputtingFileName
+
+	CALL_MENU_LIBRARY GetStringWithIoInDSSI
+	mov		al, [si+STRING_DIALOG_IO.bUserCancellation]
+	add		sp, BYTE STRING_DIALOG_IO_size
+	test	al, al		; User cancellation?
+	jnz		SHORT ReturnWithoutHandlingKeystroke
+	jmp		CloseFileDialogAfterSuccessfullSelection
+
+ALIGN JUMP_ALIGN
+.InitializeStringDialogIoInDSSIforInputtingFileName:
+	call	InitializeNullStringsToDialogInputInDSSI
+	mov		WORD [si+DIALOG_INPUT.fszTitle], g_szEnterNewFileOrDirectory
+	mov		WORD [si+STRING_DIALOG_IO.fnCharFilter], NULL
+	mov		WORD [si+STRING_DIALOG_IO.wBufferSize], FILENAME_BUFFER_SIZE
+	les		ax, [bp+DIALOG.fpDialogIO]
+	add		ax, BYTE FILE_DIALOG_IO.szFile
+	mov		[si+STRING_DIALOG_IO.fpReturnBuffer], ax
+	mov		[si+STRING_DIALOG_IO.fpReturnBuffer+2], es
+	ret
+
+
+;--------------------------------------------------------------------
+; HandleFunctionKeyForSelectingDirectoryInsteadOfFile
+;	Parameters:
+;		AL:		File dialog flags
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		Closes file dialog
+;	Corrupts registers:
+;		All, except BP
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+HandleFunctionKeyForSelectingDirectoryInsteadOfFile:
+	test	al, FLG_FILEDIALOG_DIRECTORY
+	jz		SHORT ReturnWithoutHandlingKeystroke
+	; Fall to CloseFileDialogAfterSuccessfullSelection
+
+;--------------------------------------------------------------------
+; CloseFileDialogAfterSuccessfullSelection
+;	Parameters:
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		Nothing (exits dialog)
+;	Corrupts registers:
+;		All, except BP
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+CloseFileDialogAfterSuccessfullSelection:
+	lds		di, [bp+DIALOG.fpDialogIO]
+	mov		BYTE [di+FILE_DIALOG_IO.bUserCancellation], FALSE
+	jmp		MenuInit_CloseMenuWindow
+
+
+;--------------------------------------------------------------------
+; HandleFunctionKeyForDriveChange
+;	Parameters:
+;		AL:		File dialog flags
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		All, except BP
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+HandleFunctionKeyForDriveChange:
+	test	al, FLG_FILEDIALOG_DRIVES
+	jz		SHORT ReturnWithoutHandlingKeystroke
+
+	call	.ShowDriveSelectionDialogAndGetDriveNumberToDL
+	jnc		SHORT RefreshFilesToDisplay
+	call	Drive_SetDefaultFromDL
+	jmp		SHORT RefreshFilesToDisplay
+
+;--------------------------------------------------------------------
+; .ShowDriveSelectionDialogAndGetDriveNumberToDL
+;	Parameters:
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		DL:		Drive selected by user
+;		CF:		Set if new drive selected
+;				Cleared if selection cancelled by user
+;	Corrupts registers:
+;		All, except BP
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.ShowDriveSelectionDialogAndGetDriveNumberToDL:
+	mov		cx, DIALOG_INPUT_size
+	call	Memory_ReserveCXbytesFromStackToDSSI
+	call	.InitializeDialogInputInDSSIforDriveSelection
+	call	DialogSelection_GetSelectionToAXwithInputInDSSI
+	add		sp, BYTE DIALOG_INPUT_size
+	cmp		ax, BYTE NO_ITEM_SELECTED	; Clear CF if equal
+	jne		SHORT .ConvertDriveNumberToDLfromItemIndexInAX
+	ret
+
+ALIGN JUMP_ALIGN
+.InitializeDialogInputInDSSIforDriveSelection:
+	call	InitializeNullStringsToDialogInputInDSSI
+	call	LoadItemStringBufferToESDI
+	mov		WORD [si+DIALOG_INPUT.fszTitle], g_szSelectNewDrive
+	mov		[si+DIALOG_INPUT.fszItems], di
+	mov		[si+DIALOG_INPUT.fszItems+2], es
+	call	Drive_GetFlagsForAvailableDrivesToDXAX
+	; Fall to .GenerateDriveSelectionStringToESDIfromDriveFlagsInDXAX
+
+;--------------------------------------------------------------------
+; .GenerateDriveSelectionStringToESDIfromDriveFlagsInDXAX
+;	Parameters:
+;		DX:AX:	Drive letter flags
+;		ES:DI:	Ptr to item string buffer
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, DI, ES
+;--------------------------------------------------------------------
+;ALIGN JUMP_ALIGN
+.GenerateDriveSelectionStringToESDIfromDriveFlagsInDXAX:
+	cld
+	xchg	cx, ax
+	mov		ax, 3A41h		; A:
+ALIGN JUMP_ALIGN
+.BitShiftLoop:
+	shr		dx, 1
+	rcr		cx, 1
+	jnc		SHORT .CheckIfMoreDrivesLeft
+	stosw
+	mov		BYTE [es:di], LF
+	inc		di
+ALIGN JUMP_ALIGN
+.CheckIfMoreDrivesLeft:
+	inc		ax				; Next drive letter
+	mov		bx, dx
+	or		bx, cx
+	jnz		SHORT .BitShiftLoop
+	jmp		RemoveLastLFandTerminateESDIwithNull
+
+;--------------------------------------------------------------------
+; .ConvertDriveNumberToDLfromItemIndexInAX
+;	Parameters:
+;		AX:		Selected drive item	
+;	Returns:
+;		DL:		Drive number
+;		CF:		Set since drive selected
+;	Corrupts registers:
+;		AX, CX, DH
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.ConvertDriveNumberToDLfromItemIndexInAX:
+	mov		ah, -1
+	xchg	cx, ax
+	call	Drive_GetFlagsForAvailableDrivesToDXAX
+ALIGN JUMP_ALIGN
+.BitScanLoop:
+	shr		dx, 1
+	rcr		ax, 1
+	inc		ch				; Increment drive number
+	sbb		cl, 0			; Decrement selection index
+	jnc		SHORT .BitScanLoop
+	mov		dl, ch
+	stc						; Drive selected by user
+	ret
+
+
+;--------------------------------------------------------------------
+; InitializeNullStringsToDialogInputInDSSI
+;	Parameters:
+;		DS:SI:	Ptr to DIALOG_INPUT
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+InitializeNullStringsToDialogInputInDSSI:
+	mov		ax, g_szNull
+	mov		[si+DIALOG_INPUT.fszTitle], ax
+	mov		[si+DIALOG_INPUT.fszTitle+2], cs
+	mov		[si+DIALOG_INPUT.fszItems], ax
+	mov		[si+DIALOG_INPUT.fszItems+2], cs
+	mov		[si+DIALOG_INPUT.fszInfo], ax
+	mov		[si+DIALOG_INPUT.fszInfo+2], cs
+	ret
Index: /trunk/Assembly_Library/Src/Menu/Dialog/DialogMessage.asm
===================================================================
--- /trunk/Assembly_Library/Src/Menu/Dialog/DialogMessage.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Menu/Dialog/DialogMessage.asm	(revision 41)
@@ -0,0 +1,115 @@
+; File name		:	DialogMessage.asm
+; Project name	:	Assembly Library
+; Created date	:	6.8.2010
+; Last update	:	6.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Displays message dialog.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; DialogMessage_DisplayMessageWithInputInDSSI
+;	Parameters:
+;		DS:SI:	Ptr to DIALOG_INPUT
+;		SS:BP:	Ptr to parent MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DialogMessage_DisplayMessageWithInputInDSSI:
+	mov		bx, MessageEventHandler
+	jmp		Dialog_DisplayWithDialogInputInDSSIandHandlerInBX
+
+
+;--------------------------------------------------------------------
+; MessageEventHandler
+;	Common parameters for all events:
+;		BX:			Menu event (anything from MENUEVENT struct)
+;		SS:BP:		Ptr to DIALOG
+;	Common return values for all events:
+;		CF:			Set if event processed
+;					Cleared if event not processed
+;	Corrupts registers:
+;		All
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MessageEventHandler:
+	jmp		[cs:bx+.rgfnEventHandlers]
+
+
+ALIGN JUMP_ALIGN
+.InitializeMenuinitFromDSSI:
+	or		BYTE [bp+MENU.bFlags], FLG_MENU_USER_HANDLES_SCROLLING | FLG_MENU_NOHIGHLIGHT
+	mov		WORD [bp+MENU.wHighlightedItem], 0
+	jmp		Dialog_EventInitializeMenuinitFromDSSI
+
+
+ALIGN JUMP_ALIGN
+.KeyStrokeInAX:
+	call	ProcessMessageScrollingKeysFromAX
+	stc
+	ret
+
+
+ALIGN WORD_ALIGN
+.rgfnEventHandlers:
+istruc MENUEVENT
+	at	MENUEVENT.InitializeMenuinitFromDSSI,	dw	.InitializeMenuinitFromDSSI
+	at	MENUEVENT.ExitMenu,						dw	Dialog_EventNotHandled
+	at	MENUEVENT.IdleProcessing,				dw	Dialog_EventNotHandled
+	at	MENUEVENT.ItemHighlightedFromCX,		dw	Dialog_EventNotHandled
+	at	MENUEVENT.ItemSelectedFromCX,			dw	Dialog_EventAnyThatClosesDialog
+	at	MENUEVENT.KeyStrokeInAX,				dw	.KeyStrokeInAX
+	at	MENUEVENT.RefreshTitle,					dw	Dialog_EventRefreshTitle
+	at	MENUEVENT.RefreshInformation,			dw	Dialog_EventRefreshInformation
+	at	MENUEVENT.RefreshItemFromCX,			dw	Dialog_EventRefreshItemFromCX
+iend
+
+
+;--------------------------------------------------------------------
+; ProcessMessageScrollingKeysFromAX
+;	Parameters
+;		AL:		ASCII character
+;		AH:		BIOS scan code
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+ProcessMessageScrollingKeysFromAX:
+	cmp		ah, MENU_KEY_UP
+	je		SHORT .DecrementLines
+	cmp		ah, MENU_KEY_DOWN
+	je		SHORT .IncrementLines
+	jmp		MenuLoop_ProcessScrollingKeysFromAX
+
+ALIGN JUMP_ALIGN
+.DecrementLines:
+	cmp		WORD [bp+MENU.wHighlightedItem], BYTE 0
+	je		SHORT .AlreadyAtTheTopOrBottom
+
+	mov		ax, [bp+MENU.wFirstVisibleItem]
+	mov		[bp+MENU.wHighlightedItem], ax
+	mov		ah, MENU_KEY_UP
+	jmp		MenuLoop_ProcessScrollingKeysFromAX
+
+ALIGN JUMP_ALIGN
+.IncrementLines:
+	mov		ax, [bp+MENUINIT.wItems]
+	dec		ax						; Last possible item to highlight
+	cmp		[bp+MENU.wHighlightedItem], ax
+	jae		SHORT .AlreadyAtTheTopOrBottom
+
+	call	MenuScrollbars_GetLastVisibleItemOnPageToAX
+	mov		[bp+MENU.wHighlightedItem], ax
+	mov		ah, MENU_KEY_DOWN
+	jmp		MenuLoop_ProcessScrollingKeysFromAX
+
+ALIGN JUMP_ALIGN
+.AlreadyAtTheTopOrBottom:
+	ret
Index: /trunk/Assembly_Library/Src/Menu/Dialog/DialogProgress.asm
===================================================================
--- /trunk/Assembly_Library/Src/Menu/Dialog/DialogProgress.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Menu/Dialog/DialogProgress.asm	(revision 41)
@@ -0,0 +1,299 @@
+; File name		:	DialogProgress.asm
+; Project name	:	Assembly Library
+; Created date	:	15.8.2010
+; Last update	:	16.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Displays progress bar dialog and starts progress task.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; DialogProgress_GetStringWithIoInDSSI
+;	Parameters:
+;		DS:SI:	Ptr to PROGRESS_DIALOG_IO
+;		SS:BP:	Ptr to parent MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DialogProgress_StartProgressTaskWithIoInDSSIandParamInDXAX:
+	mov		bx, ProgressEventHandler
+	jmp		Dialog_DisplayWithDialogInputInDSSIandHandlerInBX
+
+
+;--------------------------------------------------------------------
+; DialogProgress_SetProgressValueFromAX
+;	Parameters
+;		AX:		Progress bar value to set
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DialogProgress_SetProgressValueFromAX:
+	push	ds
+
+	lds		si, [bp+DIALOG.fpDialogIO]
+	mov		bx, [si+PROGRESS_DIALOG_IO.wMaxProgressValue]
+	MIN_U	ax, bx
+	cmp		ax, bx	; Make sure that last progress character is shown
+	je		SHORT .UpdateProgressBar
+
+	mov		bx, ax
+	sub		bx, [si+PROGRESS_DIALOG_IO.wCurrentProgressValue]
+	cmp		bx, [si+PROGRESS_DIALOG_IO.wProgressPerCharacter]
+	jb		SHORT .ReturnWithoutUpdate
+.UpdateProgressBar:
+	mov		[si+PROGRESS_DIALOG_IO.wCurrentProgressValue], ax
+	xor		ax, ax
+	call	MenuText_RefreshItemFromAX
+	call	MenuText_RefreshInformation
+ALIGN JUMP_ALIGN
+.ReturnWithoutUpdate:
+	pop		ds
+	ret
+
+
+;--------------------------------------------------------------------
+; ProgressEventHandler
+;	Common parameters for all events:
+;		BX:			Menu event (anything from MENUEVENT struct)
+;		SS:BP:		Ptr to DIALOG
+;	Common return values for all events:
+;		CF:			Set if event processed
+;					Cleared if event not processed
+;	Corrupts registers:
+;		All
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+ProgressEventHandler:
+	jmp		[cs:bx+.rgfnEventHandlers]
+
+
+ALIGN JUMP_ALIGN
+.InitializeMenuinitFromDSSI:
+	call	Dialog_EventInitializeMenuinitFromDSSIforSingleItem
+	lds		si, [bp+DIALOG.fpDialogIO]
+	call	TimerTicks_ReadFromBdaToAX
+	mov		[si+PROGRESS_DIALOG_IO.wStartTimeTicks], ax
+	jmp		SHORT CalculateProgressNeededBeforeUpdatingCharacter
+
+
+ALIGN JUMP_ALIGN
+.IdleProcessing:
+	call	MenuInit_GetUserDataToDSSI
+	les		di, [bp+DIALOG.fpDialogIO]
+	call	[es:di+PROGRESS_DIALOG_IO.fnTaskWithParamInDSSI]
+	call	MenuInit_CloseMenuWindow
+	stc
+	ret
+
+
+ALIGN JUMP_ALIGN
+.RefreshItemFromCX:
+	lds		si, [bp+DIALOG.fpDialogIO]
+	call	DrawProgressBarFromDialogIoInDSSI
+	stc
+	ret
+
+
+ALIGN JUMP_ALIGN
+.RefreshInformation:
+	lds		si, [bp+DIALOG.fpDialogIO]
+	call	TimerTicks_ReadFromBdaToAX
+	sub		ax, [si+PROGRESS_DIALOG_IO.wStartTimeTicks]
+	xchg	dx, ax
+	call	DrawTimeElapsedFromDX
+	call	DrawTimeLeftFromProgressDialogIoInDSSIwithTimeElapsedInDX
+	stc
+	ret
+
+
+ALIGN WORD_ALIGN
+.rgfnEventHandlers:
+istruc MENUEVENT
+	at	MENUEVENT.InitializeMenuinitFromDSSI,	dw	.InitializeMenuinitFromDSSI
+	at	MENUEVENT.ExitMenu,						dw	Dialog_EventNotHandled
+	at	MENUEVENT.IdleProcessing,				dw	.IdleProcessing
+	at	MENUEVENT.ItemHighlightedFromCX,		dw	Dialog_EventNotHandled
+	at	MENUEVENT.ItemSelectedFromCX,			dw	Dialog_EventNotHandled
+	at	MENUEVENT.KeyStrokeInAX,				dw	Dialog_EventNotHandled
+	at	MENUEVENT.RefreshTitle,					dw	Dialog_EventRefreshTitle
+	at	MENUEVENT.RefreshInformation,			dw	.RefreshInformation
+	at	MENUEVENT.RefreshItemFromCX,			dw	.RefreshItemFromCX
+iend
+
+
+;--------------------------------------------------------------------
+; CalculateProgressNeededBeforeUpdatingCharacter
+;	Parameters:
+;		DS:SI:	Ptr to PROGRESS_DIALOG_IO
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		CF:		Set since event handled
+;	Corrupts:
+;		AX, BX, DX, SI, DS
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+CalculateProgressNeededBeforeUpdatingCharacter:
+	call	MenuLocation_GetMaxTextLineLengthToAX
+	call	GetProgressLengthToBXfromProgressDialogIoInDSSI
+	xchg	ax, bx
+	xor		dx, dx
+	div		bx
+	mov		[si+PROGRESS_DIALOG_IO.wProgressPerCharacter], ax
+	stc
+	ret
+
+
+;--------------------------------------------------------------------
+; DrawProgressBarFromDialogIoInDSSI
+;	Parameters:
+;		DS:SI:	Ptr to PROGRESS_DIALOG_IO
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		Nothing
+;	Corrupts:
+;		AX, BX, CX, DX, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DrawProgressBarFromDialogIoInDSSI:
+	call	.GetFullCharsToCXandEmptyCharsToDXwithDialogIoInDSSI
+	jcxz	.DrawEmptyCharsOnly
+
+	mov		al, SCROLL_THUMB_CHARACTER
+	CALL_DISPLAY_LIBRARY PrintRepeatedCharacterFromALwithCountInCX
+
+.DrawEmptyCharsOnly:
+	mov		cx, dx
+	jcxz	.NothingLeftToDraw
+	mov		al, SCROLL_TRACK_CHARACTER
+	CALL_DISPLAY_LIBRARY PrintRepeatedCharacterFromALwithCountInCX
+
+.NothingLeftToDraw:
+	ret
+
+;--------------------------------------------------------------------
+; .GetFullCharsToCXandEmptyCharsToDXwithDialogIoInDSSI
+;	Parameters:
+;		DS:SI:	Ptr to PROGRESS_DIALOG_IO
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		CX:		Number of full progress bar characters
+;		DX:		Number of empty progress bar characters
+;	Corrupts:
+;		AX, BX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.GetFullCharsToCXandEmptyCharsToDXwithDialogIoInDSSI:
+	call	MenuLocation_GetMaxTextLineLengthToAX
+	mov		cx, ax
+	mul		WORD [si+PROGRESS_DIALOG_IO.wCurrentProgressValue]
+	call	GetProgressLengthToBXfromProgressDialogIoInDSSI
+	div		bx
+	xchg	cx, ax		; AX = Text line length, CX = Number of full chars
+
+	sub		ax, cx
+	xchg	dx, ax		; DX = Number of empty chars
+	ret
+
+
+;--------------------------------------------------------------------
+; GetProgressLengthToBXfromProgressDialogIoInDSSI
+;	Parameters:
+;		DS:SI:	Ptr to PROGRESS_DIALOG_IO
+;	Returns:
+;		BX:		Progress length
+;	Corrupts:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+GetProgressLengthToBXfromProgressDialogIoInDSSI:
+	mov		bx, [si+PROGRESS_DIALOG_IO.wMaxProgressValue]
+	sub		bx, [si+PROGRESS_DIALOG_IO.wMinProgressValue]
+	ret
+
+	
+;--------------------------------------------------------------------
+; DrawTimeElapsedFromDX
+;	Parameters:
+;		DX:		Ticks elapsed
+;	Returns:
+;		Nothing
+;	Corrupts:
+;		AX, BX, CX, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DrawTimeElapsedFromDX:
+	push	si
+	push	dx
+
+	mov		si, g_szTimeElapsed
+	CALL_DISPLAY_LIBRARY PrintNullTerminatedStringFromCSSI
+	call	FormatTicksFromDX
+
+	pop		dx
+	pop		si
+	ret
+
+
+;--------------------------------------------------------------------
+; DrawTimeLeftFromProgressDialogIoInDSSIwithTimeElapsedInDX
+;	Parameters:
+;		DX:		Ticks elapsed
+;		DS:SI:	Ptr to PROGRESS_DIALOG_IO
+;	Returns:
+;		Nothing
+;	Corrupts:
+;		AX, BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DrawTimeLeftFromProgressDialogIoInDSSIwithTimeElapsedInDX:
+	push	si
+	mov		si, g_szTimeLeft
+	CALL_DISPLAY_LIBRARY PrintNullTerminatedStringFromCSSI
+	pop		si
+
+	mov		cx, [si+PROGRESS_DIALOG_IO.wCurrentProgressValue]
+	mov		ax, [si+PROGRESS_DIALOG_IO.wMaxProgressValue]
+	sub		ax, cx
+	mul		dx			; Progress left * elapsed time
+
+	sub		cx, [si+PROGRESS_DIALOG_IO.wMinProgressValue]
+	jcxz	.PreventDivisionByZero
+	div		cx			; AX = Estimated ticks left
+	xchg	dx, ax
+	jmp		SHORT FormatTicksFromDX
+.PreventDivisionByZero:
+	xor		dx, dx
+	; Fall to FormatTicksFromDX
+
+
+;--------------------------------------------------------------------
+; FormatTicksFromDX
+;	Parameters:
+;		DX:		Ticks to format
+;	Returns:
+;		Nothing
+;	Corrupts:
+;		AX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+FormatTicksFromDX:
+	push	bp
+
+	mov		bp, sp
+	mov		si, g_szTimeFormat
+	call	TimerTicks_GetMinutesToAXfromTicksInDX
+	push	ax
+	call	TimerTicks_GetSecondsToAXfromTicksInDX
+	push	ax
+	CALL_DISPLAY_LIBRARY FormatNullTerminatedStringFromCSSI
+
+	pop		bp
+	ret
Index: /trunk/Assembly_Library/Src/Menu/Dialog/DialogSelection.asm
===================================================================
--- /trunk/Assembly_Library/Src/Menu/Dialog/DialogSelection.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Menu/Dialog/DialogSelection.asm	(revision 41)
@@ -0,0 +1,61 @@
+; File name		:	DialogSelection.asm
+; Project name	:	Assembly Library
+; Created date	:	13.8.2010
+; Last update	:	13.8.2010
+; Author		:	Tomi Tilli
+; Description	:	Displays selection dialog.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; DialogSelection_GetSelectionToAXwithInputInDSSI
+;	Parameters:
+;		DS:SI:	Ptr to DIALOG_INPUT
+;		SS:BP:	Ptr to parent MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DialogSelection_GetSelectionToAXwithInputInDSSI:
+	mov		bx, SelectionEventHandler
+	jmp		Dialog_DisplayWithDialogInputInDSSIandHandlerInBX
+
+
+;--------------------------------------------------------------------
+; SelectionEventHandler
+;	Common parameters for all events:
+;		BX:			Menu event (anything from MENUEVENT struct)
+;		SS:BP:		Ptr to DIALOG
+;	Common return values for all events:
+;		CF:			Set if event processed
+;					Cleared if event not processed
+;	Corrupts registers:
+;		All
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+SelectionEventHandler:
+	jmp		[cs:bx+.rgfnEventHandlers]
+
+
+ALIGN JUMP_ALIGN
+.InitializeMenuinitFromDSSI:
+	mov		WORD [bp+MENU.wHighlightedItem], 0
+	jmp		Dialog_EventInitializeMenuinitFromDSSI
+
+
+ALIGN WORD_ALIGN
+.rgfnEventHandlers:
+istruc MENUEVENT
+	at	MENUEVENT.InitializeMenuinitFromDSSI,	dw	.InitializeMenuinitFromDSSI
+	at	MENUEVENT.ExitMenu,						dw	Dialog_EventNotHandled
+	at	MENUEVENT.IdleProcessing,				dw	Dialog_EventNotHandled
+	at	MENUEVENT.ItemHighlightedFromCX,		dw	Dialog_EventNotHandled
+	at	MENUEVENT.ItemSelectedFromCX,			dw	Dialog_EventAnyThatClosesDialog
+	at	MENUEVENT.KeyStrokeInAX,				dw	Dialog_EventNotHandled
+	at	MENUEVENT.RefreshTitle,					dw	Dialog_EventRefreshTitle
+	at	MENUEVENT.RefreshInformation,			dw	Dialog_EventRefreshInformation
+	at	MENUEVENT.RefreshItemFromCX,			dw	Dialog_EventRefreshItemFromCX
+iend
Index: /trunk/Assembly_Library/Src/Menu/Dialog/DialogString.asm
===================================================================
--- /trunk/Assembly_Library/Src/Menu/Dialog/DialogString.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Menu/Dialog/DialogString.asm	(revision 41)
@@ -0,0 +1,111 @@
+; File name		:	DialogString.asm
+; Project name	:	Assembly Library
+; Created date	:	12.8.2010
+; Last update	:	7.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Displays word input dialog.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; DialogString_GetStringWithIoInDSSI
+;	Parameters:
+;		DS:SI:	Ptr to STRING_DIALOG_IO
+;		SS:BP:	Ptr to parent MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DialogString_GetStringWithIoInDSSI:
+	mov		bx, StringEventHandler
+	mov		BYTE [si+STRING_DIALOG_IO.bUserCancellation], TRUE
+	jmp		Dialog_DisplayWithDialogInputInDSSIandHandlerInBX
+
+
+;--------------------------------------------------------------------
+; StringEventHandler
+;	Common parameters for all events:
+;		BX:			Menu event (anything from MENUEVENT struct)
+;		SS:BP:		Ptr to DIALOG
+;	Common return values for all events:
+;		CF:			Set if event processed
+;					Cleared if event not processed
+;	Corrupts registers:
+;		All
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+StringEventHandler:
+	jmp		[cs:bx+.rgfnEventHandlers]
+
+
+ALIGN JUMP_ALIGN
+.IdleProcessing:
+	xor		ax, ax						; Item 0 is used as input line
+	call	MenuText_AdjustDisplayContextForDrawingItemFromAX
+	call	GetStringFromUser
+	call	MenuInit_CloseMenuWindow
+	stc
+	ret
+
+
+ALIGN WORD_ALIGN
+.rgfnEventHandlers:
+istruc MENUEVENT
+	at	MENUEVENT.InitializeMenuinitFromDSSI,	dw	Dialog_EventInitializeMenuinitFromDSSIforSingleItem
+	at	MENUEVENT.ExitMenu,						dw	Dialog_EventNotHandled
+	at	MENUEVENT.IdleProcessing,				dw	.IdleProcessing
+	at	MENUEVENT.ItemHighlightedFromCX,		dw	Dialog_EventNotHandled
+	at	MENUEVENT.ItemSelectedFromCX,			dw	Dialog_EventNotHandled
+	at	MENUEVENT.KeyStrokeInAX,				dw	Dialog_EventNotHandled
+	at	MENUEVENT.RefreshTitle,					dw	Dialog_EventRefreshTitle
+	at	MENUEVENT.RefreshInformation,			dw	Dialog_EventRefreshInformation
+	at	MENUEVENT.RefreshItemFromCX,			dw	Dialog_EventNotHandled
+iend
+
+
+;--------------------------------------------------------------------
+; GetStringFromUser
+;	Parameters
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		Nothing (User input stored to STRING_DIALOG_IO)
+;	Corrupts registers:
+;		AX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+GetStringFromUser:
+	lds		si, [bp+DIALOG.fpDialogIO]
+	mov		cx, [si+STRING_DIALOG_IO.wBufferSize]
+	les		di, [si+STRING_DIALOG_IO.fpReturnBuffer]
+	call	.GetCharacterFilterFunctionToDX
+
+	call	Keyboard_ReadUserInputtedStringToESDIWhilePrinting
+	jz		SHORT .UserCancellation
+
+	mov		BYTE [si+STRING_DIALOG_IO.bUserCancellation], FALSE
+	mov		[si+STRING_DIALOG_IO.wReturnLength], cx
+.UserCancellation:
+	ret
+
+;--------------------------------------------------------------------
+; .GetCharacterFilterFunctionToDX
+;	Parameters
+;		DS:SI:	Ptr to STRING_DIALOG_IO
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		CS:DX:	Ptr to character filter function
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.GetCharacterFilterFunctionToDX:
+	mov		dx, [si+STRING_DIALOG_IO.fnCharFilter]
+	test	dx, dx
+	jnz		SHORT .ReturnFilterFunctionInDX
+	mov		dx, Char_CharIsValid
+ALIGN JUMP_ALIGN, ret
+.ReturnFilterFunctionInDX:
+	ret
Index: /trunk/Assembly_Library/Src/Menu/Dialog/DialogWord.asm
===================================================================
--- /trunk/Assembly_Library/Src/Menu/Dialog/DialogWord.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Menu/Dialog/DialogWord.asm	(revision 41)
@@ -0,0 +1,122 @@
+; File name		:	DialogWord.asm
+; Project name	:	Assembly Library
+; Created date	:	10.8.2010
+; Last update	:	7.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Displays word input dialog.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; DialogWord_GetWordWithIoInDSSI
+;	Parameters:
+;		DS:SI:	Ptr to WORD_DIALOG_IO
+;		SS:BP:	Ptr to parent MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DialogWord_GetWordWithIoInDSSI:
+	mov		bx, WordEventHandler
+	mov		BYTE [si+WORD_DIALOG_IO.bUserCancellation], TRUE
+	jmp		Dialog_DisplayWithDialogInputInDSSIandHandlerInBX
+
+
+;--------------------------------------------------------------------
+; WordEventHandler
+;	Common parameters for all events:
+;		BX:			Menu event (anything from MENUEVENT struct)
+;		SS:BP:		Ptr to DIALOG
+;	Common return values for all events:
+;		CF:			Set if event processed
+;					Cleared if event not processed
+;	Corrupts registers:
+;		All
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+WordEventHandler:
+	jmp		[cs:bx+.rgfnEventHandlers]
+
+
+ALIGN JUMP_ALIGN
+.IdleProcessing:
+	xor		ax, ax						; Item 0 is used as input line
+	call	MenuText_AdjustDisplayContextForDrawingItemFromAX
+	call	GetWordFromUser
+	call	MenuInit_CloseMenuWindow
+	stc
+	ret
+
+
+ALIGN WORD_ALIGN
+.rgfnEventHandlers:
+istruc MENUEVENT
+	at	MENUEVENT.InitializeMenuinitFromDSSI,	dw	Dialog_EventInitializeMenuinitFromDSSIforSingleItem
+	at	MENUEVENT.ExitMenu,						dw	Dialog_EventNotHandled
+	at	MENUEVENT.IdleProcessing,				dw	.IdleProcessing
+	at	MENUEVENT.ItemHighlightedFromCX,		dw	Dialog_EventNotHandled
+	at	MENUEVENT.ItemSelectedFromCX,			dw	Dialog_EventNotHandled
+	at	MENUEVENT.KeyStrokeInAX,				dw	Dialog_EventNotHandled
+	at	MENUEVENT.RefreshTitle,					dw	Dialog_EventRefreshTitle
+	at	MENUEVENT.RefreshInformation,			dw	Dialog_EventRefreshInformation
+	at	MENUEVENT.RefreshItemFromCX,			dw	Dialog_EventNotHandled
+iend
+
+
+;--------------------------------------------------------------------
+; GetWordFromUser
+;	Parameters
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		Nothing (User input stored to WORD_DIALOG_IO)
+;	Corrupts registers:
+;		AX, BX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+GetWordFromUser:
+	lds		si, [bp+DIALOG.fpDialogIO]
+	eMOVZX	bx, BYTE [si+WORD_DIALOG_IO.bNumericBase]
+ALIGN JUMP_ALIGN
+.GetUserInputIntilValidOrCancelled:
+	call	Keyboard_ReadUserInputtedWordWhilePrinting
+	jz		SHORT .UserCancellation
+
+	cmp		ax, [si+WORD_DIALOG_IO.wMin]
+	jb		SHORT .InputtedWordNotInRange
+	cmp		ax, [si+WORD_DIALOG_IO.wMax]
+	ja		SHORT .InputtedWordNotInRange
+
+	mov		[si+WORD_DIALOG_IO.bUserCancellation], bh	; Zero = FALSE
+	mov		[si+WORD_DIALOG_IO.wReturnWord], ax
+.UserCancellation:
+	ret
+
+.InputtedWordNotInRange:
+	call	Keyboard_PlayBellForUnwantedKeystroke
+	call	.ClearInputtedWordFromDialog
+	jmp		SHORT .GetUserInputIntilValidOrCancelled
+
+;--------------------------------------------------------------------
+; .ClearInputtedWordFromDialog
+;	Parameters
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DX, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.ClearInputtedWordFromDialog:
+	CALL_DISPLAY_LIBRARY GetSoftwareCoordinatesToAX
+	xchg	dx, ax
+
+	mov		al, ' '
+	mov		cx, 5
+	CALL_DISPLAY_LIBRARY PrintRepeatedCharacterFromALwithCountInCX
+
+	xchg	ax, dx
+	CALL_DISPLAY_LIBRARY SetCursorCoordinatesFromAX
+	ret
Index: /trunk/Assembly_Library/Src/Menu/Dialog/LineSplitter.asm
===================================================================
--- /trunk/Assembly_Library/Src/Menu/Dialog/LineSplitter.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Menu/Dialog/LineSplitter.asm	(revision 41)
@@ -0,0 +1,217 @@
+; File name		:	Line Splitter.asm
+; Project name	:	Assembly Library
+; Created date	:	8.8.2010
+; Last update	:	15.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Splits long strings to multiple lines.
+
+struc LINE_SPLITTER
+	.pLastWord			resb	2
+	.wMaxLineLength		resb	2
+	.wLines				resb	2
+endstruc
+
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; LineSplitter_SplitStringFromDSSIwithMaxLineLengthInAXandGetLineCountToAX
+;	Parameters:
+;		AX:		Maximum allowed length for a line
+;		DS:SI:	Ptr to string to split
+;	Returns:
+;		AX:		Number of lines
+;	Corrupts registers:
+;		CX, SI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+LineSplitter_SplitStringFromDSSIwithMaxLineLengthInAXandGetLineCountToAX:
+	xor		cx, cx
+	cmp		[si], cl						; String length zero?
+	jne		SHORT .PrepareToSplit
+	xchg	ax, cx
+	ret
+
+ALIGN JUMP_ALIGN
+.PrepareToSplit:
+	eENTER_STRUCT LINE_SPLITTER_size		; SS:BP now points to LINE_SPLITTER
+
+	mov		[bp+LINE_SPLITTER.wLines], cx
+	call	Memory_SetZFifNullPointerInDSSI
+	jz		SHORT .ReturnNumberOfLinesInAX
+	call	SplitStringFromDSSIusingLineSplitterInSSBP
+
+.ReturnNumberOfLinesInAX:
+	mov		ax, [bp+LINE_SPLITTER.wLines]
+	eLEAVE_STRUCT LINE_SPLITTER_size
+	ret
+
+;--------------------------------------------------------------------
+; SplitStringFromDSSIusingLineSplitterInSSBP
+;	Parameters:
+;		AX:		Maximum allowed length for a line
+;		DS:SI:	Ptr to string to split
+;		SS:BP:	Ptr to LINE_SPLITTER
+;	Returns:
+;		SS:BP:	Ptr to LINE_SPLITTER with number of lines
+;	Corrupts registers:
+;		AX, CX, SI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+SplitStringFromDSSIusingLineSplitterInSSBP:
+	mov		[bp+LINE_SPLITTER.pLastWord], si
+	mov		[bp+LINE_SPLITTER.wMaxLineLength], ax
+	inc		WORD [bp+LINE_SPLITTER.wLines]		; Always at least one line
+	xor		cx, cx								; Length of current line
+	cld
+ALIGN JUMP_ALIGN
+.ScanNextCharacter:
+	lodsb					; Load from [DS:SI] to AL, increment SI
+	cmp		al, ' '			; Control character or space?
+	je		SHORT .ProcessSpace
+	jb		SHORT .ProcessControlCharacter
+.IncrementCharacterCount:
+	inc		cx				; Increment character count
+	cmp		cx, [bp+LINE_SPLITTER.wMaxLineLength]
+	jbe		SHORT .ScanNextCharacter
+
+	mov		si, [bp+LINE_SPLITTER.pLastWord]	; Resume to beginning of last word
+	mov		BYTE [si-1], STX					; STX marks start or new line
+	; Fall to .StartNewLine
+
+;--------------------------------------------------------------------
+; .StartNewLine
+;	Parameters:
+;		CX:		Line length so far
+;		DS:SI:	Ptr character that begins new line
+;		SS:BP:	Ptr to LINE_SPLITTER
+;	Returns:
+;		CX:		Zero
+;		SS:BP:	LINE_SPLITTER updated for number of lines
+;		Jumps to .ScanNextCharacter
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+.StartNewLine:
+	inc		WORD [bp+LINE_SPLITTER.wLines]		; Increment number of lines
+	xor		cx, cx								; Zero line length
+	jmp		SHORT .ScanNextCharacter
+
+;--------------------------------------------------------------------
+; .ProcessSpace
+;	Parameters:
+;		CX:		Line length so far
+;		DS:SI:	Ptr first character after space
+;		SS:BP:	Ptr to LINE_SPLITTER
+;	Returns:
+;		SS:BP:	LINE_SPLITTER updated to beginning of next word
+;		Jumps to .IncrementCharacterCount
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.ProcessSpace:
+	mov		[bp+LINE_SPLITTER.pLastWord], si
+	jmp		SHORT .IncrementCharacterCount
+
+;--------------------------------------------------------------------
+; .ProcessControlCharacter
+;	Parameters:
+;		AL:		Control character
+;		CX:		Line length so far
+;		DS:SI:	Ptr inside string to split
+;		SS:BP:	Ptr to LINE_SPLITTER
+;	Returns:
+;		SS:BP:	LINE_SPLITTER updated to beginning of next line (LF control character)
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.ProcessControlCharacter:
+	cmp		al, NULL			; End of string?
+	je		SHORT .EndOfString
+	cmp		al, LF				; Line feed?
+	je		SHORT .NewlineCharacter
+	cmp		al, SOH				; Previous newline character?
+	je		SHORT .NewlineCharacter
+
+	mov		BYTE [si-1], ' '	; Replace unhandled control characters with space
+	jmp		SHORT .ProcessSpace
+
+ALIGN JUMP_ALIGN
+.NewlineCharacter:
+	mov		BYTE [si-1], SOH					; SOH marks previous newline character
+	mov		[bp+LINE_SPLITTER.pLastWord], si
+	jmp		SHORT .StartNewLine
+
+ALIGN JUMP_ALIGN
+.EndOfString:
+	ret
+
+
+;--------------------------------------------------------------------
+; LineSplitter_PrintLineInCXfromStringInESDI
+;	Parameters:
+;		CX:		Index of line to print
+;		ES:DI:	Ptr to string containing the line
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, SI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+LineSplitter_PrintLineInCXfromStringInESDI:
+	push	di
+	push	cx
+
+	call	LineSplitter_GetOffsetToSIforLineCXfromStringInESDI
+	jnc		SHORT .LineNotFound
+	mov		bx, es
+	CALL_DISPLAY_LIBRARY PrintCharBufferFromBXSIwithLengthInCX
+.LineNotFound:
+	pop		cx
+	pop		di
+	ret
+
+
+;--------------------------------------------------------------------
+; LineSplitter_GetOffsetToSIforLineCXfromStringInESDI
+;	Parameters:
+;		CX:		Index of line to search for
+;		ES:DI:	Ptr to string
+;	Returns:
+;		CX:		Line length
+;		ES:SI:	Ptr to beginning of line
+;		CF:		Set if wanted line was found
+;	Corrupts registers:
+;		AX, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+LineSplitter_GetOffsetToSIforLineCXfromStringInESDI:
+	mov		si, di				; SI points to start of first line
+	mov		al, STX				; Last control character to scan for
+	inc		cx					; Increment CX to get length for first line
+	cld
+ALIGN JUMP_ALIGN
+.LineScanLoop:
+	scasb						; cmp al, [es:di]. Increment DI
+	jb		SHORT .LineScanLoop	; Non control character
+
+	; Our end of line characters or NULL character
+	dec		cx					; Decrement lines to scan through
+	jz		SHORT .WantedLineFound
+	cmp		BYTE [es:di-1], NULL
+	je		SHORT .EndOfString	; Jump with CF cleared
+	mov		si, di				; SI points to start of new line
+	jmp		SHORT .LineScanLoop
+
+ALIGN JUMP_ALIGN
+.WantedLineFound:
+	stc							; Set CF since wanted line was found
+.EndOfString:
+	lahf						; Load FLAGS low to AH
+	lea		cx, [di-1]			; We don't want control character to be printed
+	sub		cx, si				; String length to CX
+	sahf						; Store AH to FLAGS low
+	ret
Index: /trunk/Assembly_Library/Src/Menu/Dialog/StringsForDialogs.asm
===================================================================
--- /trunk/Assembly_Library/Src/Menu/Dialog/StringsForDialogs.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Menu/Dialog/StringsForDialogs.asm	(revision 41)
@@ -0,0 +1,37 @@
+; File name		:	StringsForDialogs.asm
+; Project name	:	Assembly Library
+; Created date	:	14.9.2010
+; Last update	:	16.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Strings used by dialogs.
+
+; Strings for Progress Dialog
+g_szTimeElapsed:		db	"Time elapsed  :",NULL
+g_szTimeLeft:			db	"Estimated left:",NULL
+g_szTimeFormat:			db	" %2u min %2u sec",LF,CR,NULL
+
+; Strings for File Dialog
+g_szChangeDrive:		db	"F2 Change Drive",LF,CR,NULL
+g_szSelectDirectory:	db	"F3 Select Current Directory",LF,CR,NULL
+g_szCreateNew:			db	"F4 Input new File or Directory",NULL
+
+g_szSelectNewDrive:
+	db		"Select new drive.",NULL
+
+g_szEnterNewFileOrDirectory:
+	db		"Enter name for new file or directory.",NULL
+
+g_szFileFormat:
+	db		"%14S  %4u %c%cB",LF,NULL
+g_szDirectoryFormat:
+	db		"[%12S]  %s-DIR",LF,NULL
+g_szSub:
+	db		ANGLE_QUOTE_RIGHT,"SUB",NULL
+g_szUp:
+	db		ANGLE_QUOTE_LEFT,"UP",NULL
+
+g_szSingleItem:			; Used by Dialog.asm for single item line
+g_szUpdir:
+	db		".."
+g_szNull:
+	db		NULL
Index: /trunk/Assembly_Library/Src/Menu/Menu.asm
===================================================================
--- /trunk/Assembly_Library/Src/Menu/Menu.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Menu/Menu.asm	(revision 41)
@@ -0,0 +1,70 @@
+; File name		:	Menu.asm
+; Project name	:	Assembly Library
+; Created date	:	3.8.2010
+; Last update	:	15.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Menu Library functions for CALL_MENU_LIBRARY macro
+;					that users should use to make library call.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; MenuFunctionFromDI
+;	Parameters:
+;		DI:		Function to call (MENU_LIB.functionName)
+;		BP:		Menu handle
+;		Others:	Depends on function to call
+;	Returns:
+;		Depends on function to call
+;	Corrupts registers:
+;		AX (unless used as a return register), DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Menu_FunctionFromDI:
+	push	si
+	push	dx
+	push	cx
+	push	bx
+	call	[cs:di+.rgfnMenuLibraryFunctions]
+	pop		bx
+	pop		cx
+	pop		dx
+	pop		si
+	ret
+
+
+ALIGN WORD_ALIGN
+.rgfnMenuLibraryFunctions:
+istruc MENU_LIB
+	at	MENU_LIB.DisplayWithHandlerInBXandUserDataInDXAX,	dw	MenuInit_DisplayMenuWithHandlerInBXandUserDataInDXAX
+	;at	MENU_LIB.Close,							dw	MenuInit_CloseMenuWindow				; Special case in CALL_MENU_LIBRARY
+	at	MENU_LIB.RefreshWindow,					dw	MenuInit_RefreshMenuWindow
+
+	;at	MENU_LIB.SetUserDataFromDSSI,			dw	MenuInit_SetUserDataFromDSSI			; Special case in CALL_MENU_LIBRARY
+	;at	MENU_LIB.GetUserDataToDSSI,				dw	MenuInit_GetUserDataToDSSI				; Special case in CALL_MENU_LIBRARY
+
+	;at	MENU_LIB.SetTitleHeightFromAL,			dw	MenuInit_SetTitleHeightFromAL			; Special case in CALL_MENU_LIBRARY
+	at	MENU_LIB.RefreshTitle,					dw	MenuText_RefreshTitle
+
+	at	MENU_LIB.HighlightItemFromAX,			dw	MenuInit_HighlightItemFromAX
+	;at	MENU_LIB.SetTotalItemsFromAX,			dw	MenuInit_SetTotalItemsFromAX			; Special case in CALL_MENU_LIBRARY
+	at	MENU_LIB.RefreshItemFromAX,				dw	MenuText_RefreshItemFromAX
+
+	;at	MENU_LIB.SetInformationHeightFromAL,	dw	MenuInit_SetInformationHeightFromAL		; Special case in CALL_MENU_LIBRARY
+	at	MENU_LIB.RefreshInformation,			dw	MenuText_RefreshInformation
+
+	at	MENU_LIB.RestartTimeout,				dw	MenuTime_RestartSelectionTimeout
+	;at	MENU_LIB.SetTimeoutValueFromAX,			dw	MenuTime_SetSelectionTimeoutValueFromAX	; Special case in CALL_MENU_LIBRARY
+
+%ifdef INCLUDE_MENU_DIALOGS
+	at	MENU_LIB.StartProgressTaskWithIoInDSSIandParamInDXAX,	dw	DialogProgress_StartProgressTaskWithIoInDSSIandParamInDXAX
+	at	MENU_LIB.SetProgressValueFromAX,						dw	DialogProgress_SetProgressValueFromAX
+
+	at	MENU_LIB.DisplayMessageWithInputInDSSI,					dw	DialogMessage_DisplayMessageWithInputInDSSI
+	at	MENU_LIB.GetSelectionToAXwithInputInDSSI,				dw	DialogSelection_GetSelectionToAXwithInputInDSSI
+	at	MENU_LIB.GetWordWithIoInDSSI,							dw	DialogWord_GetWordWithIoInDSSI
+	at	MENU_LIB.GetStringWithIoInDSSI,							dw	DialogString_GetStringWithIoInDSSI
+	at	MENU_LIB.GetFileNameWithIoInDSSI,						dw	DialogFile_GetFileNameWithIoInDSSI
+%endif
+iend
Index: /trunk/Assembly_Library/Src/Menu/MenuAttributes.asm
===================================================================
--- /trunk/Assembly_Library/Src/Menu/MenuAttributes.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Menu/MenuAttributes.asm	(revision 41)
@@ -0,0 +1,113 @@
+; File name		:	MenuAttributes.asm
+; Project name	:	Assembly Library
+; Created date	:	15.7.2010
+; Last update	:	9.8.2010
+; Author		:	Tomi Tilli
+; Description	:	Finds suitable character attribute for
+;					color, B/W and monochrome displays.
+
+; Struct containing border characters for different types of menu window lines
+struc ATTRIBUTE_CHARS
+	.cBordersAndBackground	resb	1
+	.cShadow				resb	1
+	.cTitle:
+	.cInformation			resb	1
+	.cItem					resb	1
+	.cHighlightedItem		resb	1
+	.cHurryTimeout			resb	1
+	.cNormalTimeout			resb	1
+endstruc
+
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; MenuAttribute_GetToALfromTypeInSI
+;	Parameters
+;		SI:		Attribute type (from ATTRIBUTE_CHARS)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuAttribute_SetToDisplayContextFromTypeInSI:
+	call	MenuAttribute_GetToAXfromTypeInSI
+	CALL_DISPLAY_LIBRARY SetCharacterAttributeFromAL
+	ret
+
+
+;--------------------------------------------------------------------
+; MenuAttribute_GetToAXfromTypeInSI
+;	Parameters
+;		SI:		Attribute type (from ATTRIBUTE_CHARS)
+;	Returns:
+;		AX:		Wanted attribute
+;	Corrupts registers:
+;		SI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuAttribute_GetToAXfromTypeInSI:
+	push	ds
+
+	LOAD_BDA_SEGMENT_TO	ds, ax
+	mov		al, [VIDEO_BDA.bMode]		; Load BIOS display mode (0, 1, 2, 3 or 7)
+	cmp		al, 7
+	je		SHORT .LoadMonoAttribute
+	test	al, 1						; Even modes (0 and 2) are B/W
+	jnz		SHORT .LoadColorAttribute
+
+.LoadBlackAndWhiteAttribute:
+	add		si, .rgcBlackAndWhiteAttributes
+	jmp		SHORT .LoadAttributeAndReturn
+
+ALIGN JUMP_ALIGN
+.LoadMonoAttribute:
+	add		si, .rgcMonochromeAttributes
+	jmp		SHORT .LoadAttributeAndReturn
+
+ALIGN JUMP_ALIGN
+.LoadColorAttribute:
+	add		si, .rgcColorAttributes
+.LoadAttributeAndReturn:
+	eSEG	cs
+	lodsb								; Load from [CS:SI] to AL
+
+	pop		ds
+	ret
+
+
+
+.rgcColorAttributes:
+istruc ATTRIBUTE_CHARS
+	at	ATTRIBUTE_CHARS.cBordersAndBackground,	db	COLOR_ATTRIBUTE(COLOR_YELLOW, COLOR_BLUE)
+	at	ATTRIBUTE_CHARS.cShadow,				db	COLOR_ATTRIBUTE(COLOR_GRAY, COLOR_BLACK)
+	at	ATTRIBUTE_CHARS.cTitle,					db	COLOR_ATTRIBUTE(COLOR_BRIGHT_WHITE, COLOR_BLUE)
+	at	ATTRIBUTE_CHARS.cItem,					db	COLOR_ATTRIBUTE(COLOR_WHITE, COLOR_BLUE)
+	at	ATTRIBUTE_CHARS.cHighlightedItem,		db	COLOR_ATTRIBUTE(COLOR_BRIGHT_WHITE, COLOR_CYAN)
+	at	ATTRIBUTE_CHARS.cHurryTimeout,			db	COLOR_ATTRIBUTE(COLOR_RED, COLOR_BLUE) | FLG_COLOR_BLINK
+	at	ATTRIBUTE_CHARS.cNormalTimeout,			db	COLOR_ATTRIBUTE(COLOR_GREEN, COLOR_BLUE)
+iend
+
+.rgcBlackAndWhiteAttributes:	; Only COLOR_WHITE, COLOR_BRIGHT_WHITE and COLOR_BLACK should be used
+istruc ATTRIBUTE_CHARS
+	at	ATTRIBUTE_CHARS.cBordersAndBackground,	db	COLOR_ATTRIBUTE(COLOR_BRIGHT_WHITE, COLOR_BLACK)
+	at	ATTRIBUTE_CHARS.cShadow,				db	COLOR_ATTRIBUTE(COLOR_GRAY, COLOR_WHITE)
+	at	ATTRIBUTE_CHARS.cTitle,					db	COLOR_ATTRIBUTE(COLOR_BRIGHT_WHITE, COLOR_BLACK)
+	at	ATTRIBUTE_CHARS.cItem,					db	COLOR_ATTRIBUTE(COLOR_WHITE, COLOR_BLACK)
+	at	ATTRIBUTE_CHARS.cHighlightedItem,		db	COLOR_ATTRIBUTE(COLOR_BLACK, COLOR_WHITE)
+	at	ATTRIBUTE_CHARS.cHurryTimeout,			db	COLOR_ATTRIBUTE(COLOR_BRIGHT_WHITE, COLOR_BLACK) | FLG_COLOR_BLINK
+	at	ATTRIBUTE_CHARS.cNormalTimeout,			db	COLOR_ATTRIBUTE(COLOR_WHITE, COLOR_BLACK)
+iend
+
+.rgcMonochromeAttributes:
+istruc ATTRIBUTE_CHARS
+	at	ATTRIBUTE_CHARS.cBordersAndBackground,	db	MONO_BRIGHT
+	at	ATTRIBUTE_CHARS.cShadow,				db	MONO_REVERSE_DARK
+	at	ATTRIBUTE_CHARS.cTitle,					db	MONO_BRIGHT
+	at	ATTRIBUTE_CHARS.cItem,					db	MONO_NORMAL
+	at	ATTRIBUTE_CHARS.cHighlightedItem,		db	MONO_REVERSE
+	at	ATTRIBUTE_CHARS.cHurryTimeout,			db	MONO_BRIGHT_BLINK
+	at	ATTRIBUTE_CHARS.cNormalTimeout,			db	MONO_NORMAL
+iend
Index: /trunk/Assembly_Library/Src/Menu/MenuBorders.asm
===================================================================
--- /trunk/Assembly_Library/Src/Menu/MenuBorders.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Menu/MenuBorders.asm	(revision 41)
@@ -0,0 +1,359 @@
+; File name		:	MenuBorders.asm
+; Project name	:	Assembly Library
+; Created date	:	14.7.2010
+; Last update	:	7.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for drawing menu borders.
+
+; Struct containing border characters for different types of menu window lines
+struc BORDER_CHARS
+	.cLeft		resb	1
+	.cMiddle	resb	1
+	.cRight		resb	1
+endstruc
+
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; MenuBorders_RefreshAll
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN	
+MenuBorders_RefreshAll:
+	call	MenuBorders_AdjustDisplayContextForDrawingBorders
+	call	GetNumberOfMiddleCharactersToDX
+	call	RefreshTitleBorders
+	call	RefreshItemBorders
+	call	RefreshInformationBorders
+	call	DrawBottomBorderLine
+	call	DrawBottomShadowLine
+	jmp		MenuTime_DrawWithoutUpdating
+
+
+;--------------------------------------------------------------------
+; MenuBorders_AdjustDisplayContextForDrawingBorders
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuBorders_AdjustDisplayContextForDrawingBorders:
+	mov		ax, MenuCharOut_MenuBorderTeletypeOutputWithAttribute
+	CALL_DISPLAY_LIBRARY SetCharacterOutputFunctionFromAX
+
+	mov		ax, bp
+	CALL_DISPLAY_LIBRARY SetCharacterOutputParameterFromAX
+
+	call	MenuLocation_GetTitleBordersTopLeftCoordinatesToAX
+	CALL_DISPLAY_LIBRARY SetCursorCoordinatesFromAX
+
+	mov		si, ATTRIBUTE_CHARS.cBordersAndBackground
+	jmp		MenuAttribute_SetToDisplayContextFromTypeInSI
+
+
+;--------------------------------------------------------------------
+; MenuBorders_RefreshItemBorders
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuBorders_RefreshItemBorders:
+	call	MenuBorders_AdjustDisplayContextForDrawingBorders
+	call	MenuLocation_GetItemBordersTopLeftCoordinatesToAX
+	CALL_DISPLAY_LIBRARY SetCursorCoordinatesFromAX
+
+	call	GetNumberOfMiddleCharactersToDX
+	jmp		SHORT RefreshItemBorders
+
+
+;--------------------------------------------------------------------
+; GetNumberOfMiddleCharactersToDX
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		DX:		Number of middle border characters when drawing border lines
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+GetNumberOfMiddleCharactersToDX:
+	eMOVZX	dx, BYTE [bp+MENUINIT.bWidth]
+	sub		dx, BYTE MENU_HORIZONTAL_BORDER_LINES
+	ret
+
+
+;--------------------------------------------------------------------
+; RefreshTitleBorders
+;	Parameters
+;		DX:		Number of times to repeat middle character
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+RefreshTitleBorders:
+	call	DrawTopBorderLine
+	eMOVZX	cx, BYTE [bp+MENUINIT.bTitleLines]
+	jmp		SHORT DrawTextBorderLinesByCXtimes
+
+;--------------------------------------------------------------------
+; RefreshInformationBorders
+;	Parameters
+;		DX:		Number of times to repeat middle character
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+RefreshInformationBorders:
+	call	DrawSeparationBorderLine
+	eMOVZX	cx, BYTE [bp+MENUINIT.bInfoLines]
+	jmp		SHORT DrawTextBorderLinesByCXtimes
+
+;--------------------------------------------------------------------
+; RefreshItemBorders
+;	Parameters
+;		DX:		Number of times to repeat middle character
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+RefreshItemBorders:
+	call	DrawSeparationBorderLine
+	call	MenuScrollbars_GetMaxVisibleItemsOnPageToCX
+DrawTextBorderLinesByCXtimes:
+	mov		bx, DrawTextBorderLine
+	; Fall to DrawBorderLinesByCXtimes
+
+;--------------------------------------------------------------------
+; DrawBorderLinesByCXtimes
+;	Parameters
+;		BX:		Offset to border drawing function
+;		CX:		Number of border lines to draw
+;		DX:		Number of times to repeat middle character
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, SI, DI
+;--------------------------------------------------------------------
+DrawBorderLinesByCXtimes:
+	jcxz	.Return
+ALIGN JUMP_ALIGN
+.DrawBordersWithFunctionInBX:
+	call	bx
+	loop	.DrawBordersWithFunctionInBX
+.Return:
+	ret
+
+
+;--------------------------------------------------------------------
+; DrawTopBorderLine
+; DrawSeparationBorderLine
+; DrawBottomBorderLine
+; DrawBottomShadowLine
+; DrawTextBorderLine
+;	Parameters
+;		DX:		Number of times to repeat middle character
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DrawTopBorderLine:
+	mov		si, g_rgbTopBorderCharacters
+	call	PrintBorderCharactersFromCSSI
+	jmp		SHORT PrintNewlineToEndBorderLine
+
+ALIGN JUMP_ALIGN
+DrawSeparationBorderLine:
+	mov		si, g_rgbSeparationBorderCharacters
+	jmp		SHORT PrintBorderCharactersFromCSSIandShadowCharacter
+
+ALIGN JUMP_ALIGN
+DrawBottomBorderLine:
+	mov		si, g_rgbBottomBorderCharacters
+	jmp		SHORT PrintBorderCharactersFromCSSIandShadowCharacter
+
+ALIGN JUMP_ALIGN
+DrawBottomShadowLine:
+	CALL_DISPLAY_LIBRARY GetSoftwareCoordinatesToAX
+	inc		ax			; Increment column
+	CALL_DISPLAY_LIBRARY SetCursorCoordinatesFromAX
+	inc		dx			; Increment repeat count...
+	inc		dx			; ...for both corner characters
+	call	PrintShadowCharactersByDXtimes
+	dec		dx			; Restore...
+	dec		dx			; ...DX
+	ret
+
+ALIGN JUMP_ALIGN
+DrawTextBorderLine:
+	mov		si, g_rgbTextBorderCharacters
+	; Fall to PrintBorderCharactersFromCSSIandShadowCharacter
+
+;--------------------------------------------------------------------
+; PrintBorderCharactersFromCSSIandShadowCharacter
+;	Parameters
+;		DX:		Number of times to repeat middle character
+;		CS:SI:	Ptr to BORDER_CHARS
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+PrintBorderCharactersFromCSSIandShadowCharacter:
+	call	PrintBorderCharactersFromCSSI
+	push	dx
+	mov		dx, 1
+	call	PrintShadowCharactersByDXtimes
+	pop		dx
+	; Fall to PrintNewlineToEndBorderLine
+
+;--------------------------------------------------------------------
+; PrintNewlineToEndBorderLine
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+PrintNewlineToEndBorderLine:
+	CALL_DISPLAY_LIBRARY PrintNewlineCharacters
+	ret
+
+
+;--------------------------------------------------------------------
+; PrintShadowCharactersByDXtimes
+;	Parameters
+;		DX:		Number of shadow characters to print
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+PrintShadowCharactersByDXtimes:
+	CALL_DISPLAY_LIBRARY PushDisplayContext
+
+	mov		si, ATTRIBUTE_CHARS.cShadow
+	call	MenuAttribute_SetToDisplayContextFromTypeInSI
+
+	mov		ax, FAST_OUTPUT_WITH_ATTRIBUTE_ONLY
+	CALL_DISPLAY_LIBRARY SetCharacterOutputFunctionFromAX
+
+	call	PrintMultipleBorderCharactersFromAL	; AL does not matter
+
+	CALL_DISPLAY_LIBRARY PopDisplayContext
+	ret
+
+
+;--------------------------------------------------------------------
+; PrintBorderCharactersFromCSSI
+;	Parameters
+;		DX:		Number of times to repeat middle character
+;		CS:SI:	Ptr to BORDER_CHARS
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+PrintBorderCharactersFromCSSI:
+	cld
+	eSEG	cs
+	lodsb			; Load from [si+BORDER_CHARS.cLeft] to AL
+	call	MenuBorders_PrintSingleBorderCharacterFromAL
+
+	eSEG	cs
+	lodsb			; Load from [si+BORDER_CHARS.cMiddle] to AL
+	call	PrintMultipleBorderCharactersFromAL
+
+	eSEG	cs
+	lodsb			; Load from [si+BORDER_CHARS.cRight] to AL
+	; Fall to MenuBorders_PrintSingleBorderCharacterFromAL
+
+;--------------------------------------------------------------------
+; MenuBorders_PrintSingleBorderCharacterFromAL
+; PrintMultipleBorderCharactersFromAL
+;	Parameters
+;		AL:		Character to print
+;		DX:		Repeat count (PrintMultipleBorderCharactersFromAL)
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuBorders_PrintSingleBorderCharacterFromAL:
+	CALL_DISPLAY_LIBRARY PrintCharacterFromAL
+	ret
+
+ALIGN JUMP_ALIGN
+PrintMultipleBorderCharactersFromAL:
+	push	cx
+	mov		cx, dx
+	CALL_DISPLAY_LIBRARY PrintRepeatedCharacterFromALwithCountInCX
+	pop		cx
+	ret
+
+
+
+; Lookup tables for border characters
+g_rgbTopBorderCharacters:
+istruc BORDER_CHARS
+	at	BORDER_CHARS.cLeft,		db	DOUBLE_TOP_LEFT_CORNER
+	at	BORDER_CHARS.cMiddle,	db	DOUBLE_HORIZONTAL
+	at	BORDER_CHARS.cRight,	db	DOUBLE_TOP_RIGHT_CORNER
+iend
+
+g_rgbSeparationBorderCharacters:
+istruc BORDER_CHARS
+	at	BORDER_CHARS.cLeft,		db	DOUBLE_VERTICAL_TO_RIGHT_SINGLE
+	at	BORDER_CHARS.cMiddle,	db	SINGLE_HORIZONTAL
+	at	BORDER_CHARS.cRight,	db	DOUBLE_VERTICAL_TO_LEFT_SINGLE
+iend
+
+g_rgbBottomBorderCharacters:
+istruc BORDER_CHARS
+	at	BORDER_CHARS.cLeft,		db	DOUBLE_BOTTOM_LEFT_CORNER
+	at	BORDER_CHARS.cMiddle,	db	DOUBLE_HORIZONTAL
+	at	BORDER_CHARS.cRight,	db	DOUBLE_BOTTOM_RIGHT_CORNER
+iend
+
+g_rgbTextBorderCharacters:
+istruc BORDER_CHARS
+	at	BORDER_CHARS.cLeft,		db	DOUBLE_VERTICAL
+	at	BORDER_CHARS.cMiddle,	db	' '
+	at	BORDER_CHARS.cRight,	db	DOUBLE_VERTICAL
+iend
Index: /trunk/Assembly_Library/Src/Menu/MenuCharOut.asm
===================================================================
--- /trunk/Assembly_Library/Src/Menu/MenuCharOut.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Menu/MenuCharOut.asm	(revision 41)
@@ -0,0 +1,100 @@
+; File name		:	MenuCharOut.asm
+; Project name	:	Assembly Library
+; Created date	:	15.7.2010
+; Last update	:	4.8.2010
+; Author		:	Tomi Tilli
+; Description	:	Character out function for printing withing menu window.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; MenuCharOut_MenuBorderTeletypeOutputWithAttribute
+;	Parameters:
+;		AL:		Character to output
+;		AH:		Attribute to output
+;		DS:		BDA segment (zero)
+;		ES:DI:	Ptr to video memory where to output
+;	Returns:
+;		DI:		Incremented for next character
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuCharOut_MenuBorderTeletypeOutputWithAttribute:
+	cmp		al, CR					; Carriage return?
+	je		SHORT .PrintCRandAdjustColumnToMenuBorders
+	jmp		DisplayCharOut_TeletypeOutputWithAttribute
+
+ALIGN JUMP_ALIGN
+.PrintCRandAdjustColumnToMenuBorders:
+	call	DisplayCharOut_TeletypeOutputWithAttribute
+	xor		ax, ax					; No offset, cursor to start of border
+	jmp		SHORT SetCursorToNextMenuLine
+
+
+;--------------------------------------------------------------------
+; MenuCharOut_MenuTextTeletypeOutputWithAttribute
+;	Parameters:
+;		AL:		Character to output
+;		AH:		Attribute to output
+;		DS:		BDA segment (zero)
+;		ES:DI:	Ptr to video memory where to output
+;	Returns:
+;		DI:		Incremented for next character
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuCharOut_MenuTextTeletypeOutputWithAttribute:
+	cmp		al, CR						; Carriage return?
+	je		SHORT .PrintCRandAdjustColumnToMenuText
+	jmp		DisplayCharOut_TeletypeOutputWithAttribute
+
+ALIGN JUMP_ALIGN
+.PrintCRandAdjustColumnToMenuText:
+	call	DisplayCharOut_TeletypeOutputWithAttribute
+	mov		al, MENU_TEXT_COLUMN_OFFSET	; Offset to start of text
+	; Fall to SetCursorToNextMenuLine
+
+;--------------------------------------------------------------------
+; SetCursorToNextMenuLine
+;	Parameters:
+;		AL:		Column offset from start of borders
+;		DS:		BDA segment (zero)
+;		ES:DI:	Ptr to video memory where to output
+;	Returns:
+;		DI:		Adjusted for next line
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+SetCursorToNextMenuLine:
+	push	bp
+
+	mov		bp, [VIDEO_BDA.displayContext+DISPLAY_CONTEXT.wCharOutParam]
+	call	.AddCoordinatesForNewBorderLineToAX
+	call	DisplayCursor_SetCoordinatesFromAX	; Updates DI
+
+	pop		bp
+	ret
+
+;--------------------------------------------------------------------
+; .AddCoordinatesForNewBorderLineToAX
+;	Parameters:
+;		AL:		Column offset from start of borders
+;		DS:		BDA segment (zero)
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		AX:		Coordinates for new line
+;	Corrupts registers:
+;		DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.AddCoordinatesForNewBorderLineToAX:
+	call	MenuLocation_AddTitleBordersTopLeftCoordinatesToAX
+	push	ax
+	call	DisplayCursor_GetSoftwareCoordinatesToAX
+	pop		dx
+	mov		al, dl					; Adjust column to borders
+	ret
Index: /trunk/Assembly_Library/Src/Menu/MenuEvent.asm
===================================================================
--- /trunk/Assembly_Library/Src/Menu/MenuEvent.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Menu/MenuEvent.asm	(revision 41)
@@ -0,0 +1,184 @@
+; File name		:	MenuEvent.asm
+; Project name	:	Assembly Library
+; Created date	:	13.7.2010
+; Last update	:	11.8.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for initializing menu system.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; MenuEvent_InitializeMenuinit
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		DS:SI:	Ptr to MENU with MENUINIT initialized from user handler
+;		CF:		Set if event processed
+;				Cleared if event not processed
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuEvent_InitializeMenuinit:
+	push	ss
+	pop		ds
+	mov		si, bp
+	mov		bx, MENUEVENT.InitializeMenuinitFromDSSI
+	jmp		SHORT MenuEvent_SendFromBX
+
+
+;--------------------------------------------------------------------
+; MenuEvent_ExitMenu
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		CF:		Set if event processed
+;				Cleared if event not processed
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuEvent_ExitMenu:
+	mov		bx, MENUEVENT.ExitMenu
+	jmp		SHORT MenuEvent_SendFromBX
+
+
+;--------------------------------------------------------------------
+; MenuEvent_IdleProcessing
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		CF:		Set if event processed
+;				Cleared if event not processed
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuEvent_IdleProcessing:
+	mov		bx, MENUEVENT.IdleProcessing
+	jmp		SHORT MenuEvent_SendFromBX
+
+
+;--------------------------------------------------------------------
+; MenuEvent_RefreshTitle
+; MenuEvent_RefreshInformation
+;	Parameters
+;		Cursor will be positioned to beginning of window
+;	Returns:
+;		CF:		Set if event processed
+;				Cleared if event not processed
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuEvent_RefreshTitle:
+	mov		bx, MENUEVENT.RefreshTitle
+	jmp		SHORT MenuEvent_SendFromBX
+ALIGN JUMP_ALIGN
+MenuEvent_RefreshInformation:
+	mov		bx, MENUEVENT.RefreshInformation
+	jmp		SHORT MenuEvent_SendFromBX
+
+
+;--------------------------------------------------------------------
+; MenuEvent_RefreshItemFromCX
+;	Parameters
+;		CX:		Index of item to refresh
+;		Cursor has been positioned to the beginning of item line
+;	Returns:
+;		CF:		Set if event processed
+;				Cleared if event not processed
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuEvent_RefreshItemFromCX:
+	mov		bx, MENUEVENT.RefreshItemFromCX
+	jmp		SHORT MenuEvent_SendFromBX
+
+
+;--------------------------------------------------------------------
+; MenuEvent_HighlightItemFromCX
+;	Parameters
+;		CX:		Index of item to highlight
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuEvent_HighlightItemFromCX:
+	mov		dx, cx
+	xchg	dx, [bp+MENU.wHighlightedItem]
+	push	dx
+
+	mov		bx, MENUEVENT.ItemHighlightedFromCX
+	call	MenuEvent_SendFromBX
+
+	pop		ax
+	call	MenuText_RefreshItemFromAX
+	mov		ax, [bp+MENU.wHighlightedItem]
+	jmp		MenuText_RefreshItemFromAX
+
+
+;--------------------------------------------------------------------
+; MenuEvent_KeyStrokeInAX
+;	Parameters
+;		AL:		ASCII character for the key
+;		AH:		Keyboard library scan code for the key
+;	Returns:
+;		CF:		Set if event processed
+;				Cleared if event not processed
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuEvent_KeyStrokeInAX:
+	mov		bx, MENUEVENT.KeyStrokeInAX
+	jmp		SHORT MenuEvent_SendFromBX
+
+
+;--------------------------------------------------------------------
+; MenuEvent_ItemSelectedFromCX
+;	Parameters
+;		CX:		Index of selected item
+;	Returns:
+;		CF:		Set if event processed
+;				Cleared if event not processed
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuEvent_ItemSelectedFromCX:
+	mov		bx, MENUEVENT.ItemSelectedFromCX
+	jmp		SHORT MenuEvent_SendFromBX
+
+
+;--------------------------------------------------------------------
+; MenuEvent_SendFromBX
+;	Parameters
+;		BX:					Menu event to send
+;		SS:BP:				Ptr to MENU
+;		Other registers:	Event specific parameters
+;	Returns:
+;		AX, DX:				Event specific return values
+;		CF:					Set if event processed
+;							Cleared if event not processed
+;	Corrupts registers:
+;		BX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuEvent_SendFromBX:
+	push	es
+	push	ds
+	push	di
+	push	si
+	push	cx
+	call	[bp+MENU.fnEventHandler]
+	pop		cx
+	pop		si
+	pop		di
+	pop		ds
+	pop		es
+	ret
Index: /trunk/Assembly_Library/Src/Menu/MenuInit.asm
===================================================================
--- /trunk/Assembly_Library/Src/Menu/MenuInit.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Menu/MenuInit.asm	(revision 41)
@@ -0,0 +1,164 @@
+; File name		:	MenuInit.asm
+; Project name	:	Assembly Library
+; Created date	:	13.7.2010
+; Last update	:	16.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for initializing menu system.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; MenuInit_DisplayMenuWithHandlerInBXandUserDataInDXAX
+;	Parameters
+;		DX:AX:	User specified data
+;		BX:		Menu event handler
+;	Returns:
+;		AX:		Index of selected item or NO_ITEM_SELECTED
+;	Corrupts registers:
+;		All except segments
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuInit_DisplayMenuWithHandlerInBXandUserDataInDXAX:
+	push	es
+	push	ds
+	LOAD_BDA_SEGMENT_TO ds, cx
+	push	WORD [BDA.wVidCurShape]
+	eENTER_STRUCT MENU_size
+
+	mov		cx, MENU_size / 2
+	call	Memory_ZeroSSBPbyWordsInCX
+	call	MenuInit_EnterMenuWithHandlerInBXandUserDataInDXAX
+	mov		ax, [bp+MENU.wHighlightedItem]
+
+	eLEAVE_STRUCT MENU_size
+	pop		ax
+	CALL_DISPLAY_LIBRARY SetCursorShapeFromAX
+	pop		ds
+	pop		es
+	ret
+
+
+;--------------------------------------------------------------------
+; MenuInit_EnterMenuWithHandlerInBXandUserDataInDXAX
+;	Parameters
+;		DX:AX:	User specified data
+;		BX:		Menu event handler
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		All, except SS:BP
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuInit_EnterMenuWithHandlerInBXandUserDataInDXAX:
+	mov		[bp+MENU.fnEventHandler], bx
+	mov		[bp+MENU.dwUserData], ax
+	mov		[bp+MENU.dwUserData+2], dx
+	mov		WORD [bp+MENU.wHighlightedItem], NO_ITEM_HIGHLIGHTED
+
+	mov		ax, CURSOR_HIDDEN
+	CALL_DISPLAY_LIBRARY SetCursorShapeFromAX
+	call	MenuEvent_InitializeMenuinit		; User initialization
+	call	MenuTime_RestartSelectionTimeout
+	call	MenuInit_RefreshMenuWindow
+	jmp		MenuLoop_Enter
+
+
+;--------------------------------------------------------------------
+; MenuInit_RefreshMenuWindow
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuInit_RefreshMenuWindow:
+	call	MenuBorders_RefreshAll			; Draw borders
+	call	MenuText_RefreshTitle			; Draw title strings
+	call	MenuText_RefreshAllItems		; Draw item strings
+	jmp		MenuText_RefreshInformation		; Draw information strings	
+
+
+;--------------------------------------------------------------------
+; MenuInit_CloseMenuWindow
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuInit_CloseMenuWindow:
+	or		BYTE [bp+MENU.bFlags], FLG_MENU_EXIT
+	ret
+
+
+;--------------------------------------------------------------------
+; MenuInit_HighlightItemFromAX
+;	Parameters
+;		AX:		Item to highlight
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuInit_HighlightItemFromAX:
+	sub		ax, [bp+MENU.wHighlightedItem]
+	jmp		MenuScrollbars_MoveHighlightedItemByAX
+
+
+;--------------------------------------------------------------------
+; MenuInit_SetTitleHeightFromAL
+; MenuInit_SetInformationHeightFromAL
+; MenuInit_SetTotalItemsFromAX
+;	Parameters
+;		AX/AL:	Parameter
+;		SS:BP:		Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuInit_SetTitleHeightFromAL:
+	mov		[bp+MENUINIT.bTitleLines], al
+	ret
+
+ALIGN JUMP_ALIGN
+MenuInit_SetInformationHeightFromAL:
+	mov		[bp+MENUINIT.bInfoLines], al
+	ret
+
+ALIGN JUMP_ALIGN
+MenuInit_SetTotalItemsFromAX:
+	mov		[bp+MENUINIT.wItems], ax
+	ret
+
+
+;--------------------------------------------------------------------
+; MenuInit_SetUserDataFromDSSI
+; MenuInit_GetUserDataToDSSI
+;	Parameters
+;		DS:SI:	User data (MenuInit_SetUserDataFromDSSI)
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		DS:SI:	User data (MenuInit_GetUserDataToDSSI)
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuInit_SetUserDataFromDSSI:
+	mov		[bp+MENU.dwUserData], si
+	mov		[bp+MENU.dwUserData+2], ds
+	ret
+
+ALIGN JUMP_ALIGN
+MenuInit_GetUserDataToDSSI:
+	lds		si, [bp+MENU.dwUserData]
+	ret
Index: /trunk/Assembly_Library/Src/Menu/MenuLocation.asm
===================================================================
--- /trunk/Assembly_Library/Src/Menu/MenuLocation.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Menu/MenuLocation.asm	(revision 41)
@@ -0,0 +1,161 @@
+; File name		:	MenuLocation.asm
+; Project name	:	Assembly Library
+; Created date	:	14.7.2010
+; Last update	:	11.8.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for calculation menu window dimensions.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; MenuLocation_GetScrollbarCoordinatesToAXforItemInAX
+;	Parameters
+;		AX:		Item index
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		AL:		Column (X)
+;		AH:		Row (Y)
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuLocation_GetScrollbarCoordinatesToAXforItemInAX:
+	call	MenuLocation_GetTextCoordinatesToAXforItemInAX
+	add		al, [bp+MENUINIT.bWidth]
+	sub		al, MENU_TEXT_COLUMN_OFFSET*2
+	ret
+
+
+;--------------------------------------------------------------------
+; MenuLocation_GetTitleTextTopLeftCoordinatesToAX
+; MenuLocation_GetInformationTextTopLeftCoordinatesToAX
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		AL:		Column (X)
+;		AH:		Row (Y)
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuLocation_GetTitleTextTopLeftCoordinatesToAX:
+	mov		ax, (MENU_TEXT_ROW_OFFSET<<8) | MENU_TEXT_COLUMN_OFFSET
+	jmp		SHORT MenuLocation_AddTitleBordersTopLeftCoordinatesToAX
+
+ALIGN JUMP_ALIGN
+MenuLocation_GetInformationTextTopLeftCoordinatesToAX:
+	mov		ax, (MENU_TEXT_ROW_OFFSET<<8) | MENU_TEXT_COLUMN_OFFSET
+	jmp		SHORT AddInformationBordersTopLeftCoordinatesToAX
+
+
+;--------------------------------------------------------------------
+; MenuLocation_GetTextCoordinatesToAXforItemInAX
+;	Parameters
+;		AX:		Item index
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		AL:		Column (X)
+;		AH:		Row (Y)
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuLocation_GetTextCoordinatesToAXforItemInAX:
+	sub		ax, [bp+MENU.wFirstVisibleItem]		; Item to line
+	xchg	al, ah								; Line to AH, clear AL
+	add		ax, (MENU_TEXT_ROW_OFFSET<<8) | MENU_TEXT_COLUMN_OFFSET
+	jmp		SHORT AddItemBordersTopLeftCoordinatesToAX
+
+
+;--------------------------------------------------------------------
+; MenuLocation_GetTitleBordersTopLeftCoordinatesToAX
+; MenuLocation_GetItemBordersTopLeftCoordinatesToAX
+; MenuLocation_GetInformationBordersTopLeftCoordinatesToAX
+; MenuLocation_GetBottomBordersTopLeftCoordinatesToAX
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		AL:		Column (X)
+;		AH:		Row (Y)
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuLocation_GetTitleBordersTopLeftCoordinatesToAX:
+	xor		ax, ax
+	jmp		SHORT MenuLocation_AddTitleBordersTopLeftCoordinatesToAX
+
+ALIGN JUMP_ALIGN
+MenuLocation_GetItemBordersTopLeftCoordinatesToAX:
+	xor		ax, ax
+	jmp		SHORT AddItemBordersTopLeftCoordinatesToAX
+
+ALIGN JUMP_ALIGN
+MenuLocation_GetInformationBordersTopLeftCoordinatesToAX:
+	xor		ax, ax
+	jmp		SHORT AddInformationBordersTopLeftCoordinatesToAX
+
+ALIGN JUMP_ALIGN
+MenuLocation_GetBottomBordersTopLeftCoordinatesToAX:
+	xor		ax, ax
+	; Fall to AddBottomBordersTopLeftCoordinatesToAX
+
+;--------------------------------------------------------------------
+; AddBottomBordersTopLeftCoordinatesToAX
+; AddInformationBordersTopLeftCoordinatesToAX
+; AddItemBordersTopLeftCoordinatesToAX
+; MenuLocation_AddTitleBordersTopLeftCoordinatesToAX
+;	Parameters
+;		AX:		Zero of offset
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		AL:		Column (X)
+;		AH:		Row (Y)
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+AddBottomBordersTopLeftCoordinatesToAX:
+	stc							; Compensate for Information top border
+	adc		ah, [bp+MENUINIT.bInfoLines]
+ALIGN JUMP_ALIGN
+AddInformationBordersTopLeftCoordinatesToAX:
+	push	cx
+	call	MenuScrollbars_GetMaxVisibleItemsOnPageToCX
+	inc		cx					; Compensate for Items top border
+	add		ah, cl
+	pop		cx
+ALIGN JUMP_ALIGN
+AddItemBordersTopLeftCoordinatesToAX:
+	stc							; Compensate for Title top border
+	adc		ah, [bp+MENUINIT.bTitleLines]
+ALIGN JUMP_ALIGN
+MenuLocation_AddTitleBordersTopLeftCoordinatesToAX:
+	push	di
+	push	ax
+	CALL_DISPLAY_LIBRARY GetColumnsToALandRowsToAH
+	sub		al, [bp+MENUINIT.bWidth]
+	sub		ah, [bp+MENUINIT.bHeight]
+	shr		al, 1
+	shr		ah, 1
+	pop		di					; Old AX to DI
+	add		ax, di				; Add old AX to menu top left coordinates
+	pop		di
+	ret
+
+
+;--------------------------------------------------------------------
+; MenuLocation_GetMaxTextLineLengthToAX
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		AX:		Maximum text line length in characters
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuLocation_GetMaxTextLineLengthToAX:
+	eMOVZX	ax, BYTE [bp+MENUINIT.bWidth]
+	sub		ax, BYTE MENU_HORIZONTAL_BORDER_LINES + MENU_TEXT_COLUMN_OFFSET
+	ret
Index: /trunk/Assembly_Library/Src/Menu/MenuLoop.asm
===================================================================
--- /trunk/Assembly_Library/Src/Menu/MenuLoop.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Menu/MenuLoop.asm	(revision 41)
@@ -0,0 +1,191 @@
+; File name		:	MenuLoop.asm
+; Project name	:	Assembly Library
+; Created date	:	22.7.2010
+; Last update	:	16.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Menu loop for waiting keystrokes.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; MenuLoop_Enter
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuLoop_Enter:
+	test	BYTE [bp+MENU.bFlags], FLG_MENU_EXIT
+	jnz		SHORT .ExitMenu
+	call	IdleTimeProcessing
+
+	call	MenuTime_UpdateSelectionTimeout
+	mov		ah, MENU_KEY_ENTER			; Fake ENTER to select item
+	jc		SHORT .ProcessFakedKeystrokeCausedByTimeout
+
+	call	Keyboard_GetKeystrokeToAX
+	jz		SHORT MenuLoop_Enter
+.ProcessFakedKeystrokeCausedByTimeout:
+	call	ProcessKeystrokeFromAX
+	jmp		SHORT MenuLoop_Enter
+
+ALIGN JUMP_ALIGN
+.ExitMenu:
+	jmp		MenuEvent_ExitMenu
+
+
+;--------------------------------------------------------------------
+; IdleTimeProcessing
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+IdleTimeProcessing:
+	jmp		MenuEvent_IdleProcessing	; User idle processing
+
+
+;--------------------------------------------------------------------
+; ProcessKeystrokeFromAX
+;	Parameters
+;		AL:		ASCII character
+;		AH:		BIOS scan code
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing	
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+ProcessKeystrokeFromAX:
+	call	.ProcessMenuSystemKeystroke
+	jc		SHORT .Return
+	jmp		MenuEvent_KeyStrokeInAX
+ALIGN JUMP_ALIGN, ret
+.Return:
+	ret
+
+;--------------------------------------------------------------------
+; .ProcessMenuSystemKeystroke
+;	Parameters
+;		AL:		ASCII character
+;		AH:		BIOS scan code
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		CF:		Set if keystroke processed
+;				Cleared if keystroke not processed
+;		AL:		ASCII character (if CF cleared)
+;		AH:		BIOS scan code (if CF cleared)
+;	Corrupts registers:
+;		BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.ProcessMenuSystemKeystroke:
+	cmp		ah, MENU_KEY_ESC
+	je		SHORT .LeaveMenuWithoutSelectingItem
+	cmp		ah, MENU_KEY_ENTER
+	je		SHORT .SelectItem
+
+	test	BYTE [bp+MENU.bFlags], FLG_MENU_USER_HANDLES_SCROLLING
+	jz		SHORT MenuLoop_ProcessScrollingKeysFromAX
+	clc		; Clear CF since keystroke not processed
+	ret
+
+ALIGN JUMP_ALIGN
+.LeaveMenuWithoutSelectingItem:
+	call	MenuInit_CloseMenuWindow
+	mov		WORD [bp+MENU.wHighlightedItem], NO_ITEM_HIGHLIGHTED
+	stc
+	ret
+
+ALIGN JUMP_ALIGN
+.SelectItem:
+	mov		cx, [bp+MENU.wHighlightedItem]
+	call	MenuEvent_ItemSelectedFromCX
+	stc
+	ret
+
+
+;--------------------------------------------------------------------
+; MenuLoop_ProcessScrollingKeysFromAX
+;	Parameters
+;		AL:		ASCII character
+;		AH:		BIOS scan code
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		CF:		Set if keystroke processed
+;				Cleared if keystroke not processed
+;		AL:		ASCII character (if CF cleared)
+;		AH:		BIOS scan code (if CF cleared)
+;	Corrupts registers:
+;		BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuLoop_ProcessScrollingKeysFromAX:
+	cmp		ah, MENU_KEY_PGUP
+	je		SHORT .ChangeToPreviousPage
+	cmp		ah, MENU_KEY_PGDN
+	je		SHORT .ChangeToNextPage
+	cmp		ah, MENU_KEY_HOME
+	je		SHORT .SelectFirstItem
+	cmp		ah, MENU_KEY_END
+	je		SHORT .SelectLastItem
+
+	cmp		ah, MENU_KEY_UP
+	je		SHORT .DecrementSelectedItem
+	cmp		ah, MENU_KEY_DOWN
+	je		SHORT .IncrementSelectedItem
+	clc		; Clear CF since keystroke not processed
+	ret
+
+ALIGN JUMP_ALIGN
+.ChangeToPreviousPage:
+	call	MenuScrollbars_GetMaxVisibleItemsOnPageToCX
+	xchg	ax, cx
+	neg		ax
+	mov		cx, [bp+MENU.wHighlightedItem]
+	add		cx, ax
+	jge		SHORT .MoveHighlightedItemByAX	; No rotation for PgUp
+	; Fall to .SelectFirstItem
+ALIGN JUMP_ALIGN
+.SelectFirstItem:
+	mov		ax, [bp+MENU.wHighlightedItem]
+	neg		ax
+	jmp		SHORT .MoveHighlightedItemByAX
+
+ALIGN JUMP_ALIGN
+.ChangeToNextPage:
+	call	MenuScrollbars_GetMaxVisibleItemsOnPageToCX
+	xchg	ax, cx
+	mov		cx, [bp+MENU.wHighlightedItem]
+	add		cx, ax
+	cmp		cx, [bp+MENUINIT.wItems]
+	jb		SHORT .MoveHighlightedItemByAX	; No rotation for PgDn
+	; Fall to .SelectLastItem
+ALIGN JUMP_ALIGN
+.SelectLastItem:
+	mov		ax, [bp+MENUINIT.wItems]
+	sub		ax, [bp+MENU.wHighlightedItem]
+	dec		ax
+	jmp		SHORT .MoveHighlightedItemByAX
+
+ALIGN JUMP_ALIGN
+.DecrementSelectedItem:
+	mov		ax, -1
+	jmp		SHORT .MoveHighlightedItemByAX
+ALIGN JUMP_ALIGN
+.IncrementSelectedItem:
+	mov		ax, 1
+ALIGN JUMP_ALIGN
+.MoveHighlightedItemByAX:
+	call	MenuScrollbars_MoveHighlightedItemByAX
+	call	MenuTime_RestartSelectionTimeout
+	stc
+	ret
Index: /trunk/Assembly_Library/Src/Menu/MenuScrollbars.asm
===================================================================
--- /trunk/Assembly_Library/Src/Menu/MenuScrollbars.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Menu/MenuScrollbars.asm	(revision 41)
@@ -0,0 +1,267 @@
+; File name		:	MenuScrollbars.asm
+; Project name	:	Assembly Library
+; Created date	:	20.7.2010
+; Last update	:	9.8.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for drawing scroll bars over menu borders.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; MenuScrollbars_AreScrollbarsNeeded
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		CF:		Set if scroll bars are needed
+;				Cleared if no scroll bars needed
+;	Corrupts registers:
+;		CX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuScrollbars_AreScrollbarsNeeded:
+	call	MenuScrollbars_GetMaxVisibleItemsOnPageToCX
+	cmp		cx, [bp+MENUINIT.wItems]		; Set CF if max visible < total items
+	ret
+
+
+;--------------------------------------------------------------------
+; MenuScrollbars_GetScrollCharacterToALForLineInDI
+;	Parameters
+;		DI:		Index of item line to draw
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		AL:		Scroll track or thumb character
+;	Corrupts registers:
+;		AH, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuScrollbars_GetScrollCharacterToALForLineInDI:
+	call	MenuScrollbars_GetMaxVisibleItemsOnPageToCX
+	call	.GetFirstThumbLineToAX
+	cmp		di, ax				; Before first thumb line?
+	jb		SHORT .ReturnTrackCharacter
+	call	.GetLastThumbLineToAX
+	cmp		di, ax				; After last thumb line?
+	ja		SHORT .ReturnTrackCharacter
+	mov		al, SCROLL_THUMB_CHARACTER
+	ret
+ALIGN JUMP_ALIGN
+.ReturnTrackCharacter:
+	mov		al, SCROLL_TRACK_CHARACTER
+	ret
+
+;--------------------------------------------------------------------
+; .GetLastThumbLineToAX
+;	Parameters
+;		CX:		Max visible items on page
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		AX:		Item line for last thumb character
+;	Corrupts registers:
+;		CX, DX
+;--------------------------------------------------------------------	
+ALIGN JUMP_ALIGN
+.GetLastThumbLineToAX:
+	call	MenuScrollbars_GetLastVisibleItemOnPageToAX
+	jmp		SHORT .CalculateFirstOrLastThumbLineToAX
+
+;--------------------------------------------------------------------
+; .GetFirstThumbLineToAX
+;	Parameters
+;		CX:		Max visible items on page
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		AX:		Item line for first thumb character
+;	Corrupts registers:
+;		CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.GetFirstThumbLineToAX:
+	mov		ax, [bp+MENU.wFirstVisibleItem]
+.CalculateFirstOrLastThumbLineToAX:
+	mul		cx
+	div		WORD [bp+MENUINIT.wItems]
+	ret		; (Visible items on page * First visible item on page) / total items
+
+
+;--------------------------------------------------------------------
+; MenuScrollbars_MoveHighlightedItemByAX
+;	Parameters
+;		AX:		Signed offset to new item to be highlighted
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuScrollbars_MoveHighlightedItemByAX:
+	mov		cx, [bp+MENU.wHighlightedItem]
+	add		cx, ax
+	call	.RotateItemInCX
+	; Fall to .ScrollPageForNewItemInCX
+
+;--------------------------------------------------------------------
+; .ScrollPageForNewItemInCX
+;	Parameters
+;		CX:		New item to be highlighted
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+.ScrollPageForNewItemInCX:
+	call	MenuScrollbars_IsItemInCXonVisiblePage
+	jc		SHORT .HighlightNewItemOnCX
+
+	mov		dx, [bp+MENU.wFirstVisibleItem]
+	sub		dx, [bp+MENU.wHighlightedItem]
+	add		dx, cx
+	MAX_S	dx, 0
+	call	.GetMaxFirstVisibleItemToAX
+	MIN_U	ax, dx
+	mov		[bp+MENU.wFirstVisibleItem], ax
+	call	MenuText_RefreshAllItems
+
+ALIGN JUMP_ALIGN
+.HighlightNewItemOnCX:
+	jmp		MenuEvent_HighlightItemFromCX
+
+;--------------------------------------------------------------------
+; .GetMaxFirstVisibleItemToAX
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		AX:		Max first visible item
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.GetMaxFirstVisibleItemToAX:
+	push	cx
+
+	call	MenuScrollbars_GetMaxVisibleItemsOnPageToCX
+	mov		ax, [bp+MENUINIT.wItems]
+	sub		ax, cx
+
+	pop		cx
+	ret
+
+;--------------------------------------------------------------------
+; .RotateItemInCX
+;	Parameters
+;		CX:		Possibly under of overflown item to be rotated
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		CX:		Valid item index
+;	Corrupts registers:
+;		DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.RotateItemInCX:
+	mov		dx, [bp+MENUINIT.wItems]
+	cmp		cx, BYTE 0
+	jl		SHORT .RotateNegativeItemInCX
+	cmp		cx, dx
+	jae		SHORT .RotatePositiveItemInCX
+	ret
+
+ALIGN JUMP_ALIGN
+.RotatePositiveItemInCX:
+	sub		cx, dx
+	;jae	SHORT .RotatePositiveItemInCX	; Not needed by scrolling
+	ret
+
+ALIGN JUMP_ALIGN
+.RotateNegativeItemInCX:
+	add		cx, dx
+	;js		SHORT .RotateNegativeItemInCX	; Not needed by scrolling
+	ret
+
+
+;--------------------------------------------------------------------
+; .IsItemInCXonVisiblePage
+;	Parameters
+;		CX:		Item whose visibility is to be checked
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		CF:		Set if item is on visible page
+;				Cleared if item is not on visible page
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuScrollbars_IsItemInCXonVisiblePage:
+	cmp		cx, [bp+MENUINIT.wItems]
+	jae		SHORT .ItemIsNotVisible
+
+	cmp		cx, [bp+MENU.wFirstVisibleItem]
+	jb		SHORT .ItemIsNotVisible
+
+	call	MenuScrollbars_GetLastVisibleItemOnPageToAX
+	cmp		cx, ax
+	ja		SHORT .ItemIsNotVisible
+	stc		; Item is visible
+	ret
+ALIGN JUMP_ALIGN
+.ItemIsNotVisible:
+	clc
+	ret
+
+
+;--------------------------------------------------------------------
+; MenuLocation_GetLastVisibleItemOnPageToAX
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		AX:		Index of last visible item on page
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuScrollbars_GetLastVisibleItemOnPageToAX:
+	push	cx
+
+	call	MenuScrollbars_GetActualVisibleItemsOnPageToCX
+	xchg	ax, cx
+	dec		ax
+	add		ax, [bp+MENU.wFirstVisibleItem]
+
+	pop		cx
+	ret
+
+
+;--------------------------------------------------------------------
+; MenuScrollbars_GetActualVisibleItemsOnPageToCX
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		CX:		Currently visible items
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuScrollbars_GetActualVisibleItemsOnPageToCX:
+	call	MenuScrollbars_GetMaxVisibleItemsOnPageToCX
+	MIN_U	cx, [bp+MENUINIT.wItems]
+	ret
+
+
+;--------------------------------------------------------------------
+; MenuScrollbars_GetMaxVisibleItemsOnPageToCX
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		CX:		Maximum number of visible items
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuScrollbars_GetMaxVisibleItemsOnPageToCX:
+	eMOVZX	cx, BYTE [bp+MENUINIT.bHeight]
+	sub		cl, [bp+MENUINIT.bTitleLines]
+	sub		cl, [bp+MENUINIT.bInfoLines]
+	sub		cl, MENU_VERTICAL_BORDER_LINES
+	ret
Index: /trunk/Assembly_Library/Src/Menu/MenuText.asm
===================================================================
--- /trunk/Assembly_Library/Src/Menu/MenuText.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Menu/MenuText.asm	(revision 41)
@@ -0,0 +1,230 @@
+; File name		:	MenuText.asm
+; Project name	:	Assembly Library
+; Created date	:	21.7.2010
+; Last update	:	11.8.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for drawing menu texts by the user.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; MenuText_RefreshTitle
+; MenuText_RefreshInformation
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuText_RefreshTitle:
+	cmp		BYTE [bp+MENUINIT.bTitleLines], 0
+	jz		SHORT NothingToRefresh
+
+	mov		si, ATTRIBUTE_CHARS.cTitle
+	call	AdjustDisplayContextForDrawingTexts
+	call	MenuLocation_GetTitleTextTopLeftCoordinatesToAX
+	CALL_DISPLAY_LIBRARY SetCursorCoordinatesFromAX
+	jmp		MenuEvent_RefreshTitle
+
+ALIGN JUMP_ALIGN
+MenuText_RefreshInformation:
+	cmp		BYTE [bp+MENUINIT.bInfoLines], 0
+	jz		SHORT NothingToRefresh
+
+	mov		si, ATTRIBUTE_CHARS.cInformation
+	call	AdjustDisplayContextForDrawingTexts
+	call	MenuLocation_GetInformationTextTopLeftCoordinatesToAX
+	CALL_DISPLAY_LIBRARY SetCursorCoordinatesFromAX
+	jmp		MenuEvent_RefreshInformation
+
+
+;--------------------------------------------------------------------
+; MenuText_RefreshAllItems
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuText_RefreshAllItems:
+	push	cx
+
+	call	MenuScrollbars_GetActualVisibleItemsOnPageToCX
+	mov		ax, [bp+MENU.wFirstVisibleItem]
+ALIGN JUMP_ALIGN
+.ItemRefreshLoop:
+	call	MenuText_RefreshItemFromAX
+	inc		ax
+	loop	.ItemRefreshLoop
+
+	pop		cx
+NothingToRefresh:
+	ret
+
+;--------------------------------------------------------------------
+; MenuText_RefreshItemFromAX
+;	Parameters
+;		AX:		Item to refresh
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		BX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuText_RefreshItemFromAX:
+	push	cx
+	mov		cx, ax					; Backup item to CX
+
+	call	MenuScrollbars_IsItemInCXonVisiblePage
+	jnc		SHORT .InvalidItem
+	mov		ax, cx
+	call	MenuText_AdjustDisplayContextForDrawingItemFromAX
+	call	MenuEvent_RefreshItemFromCX
+	call	DrawScrollbarIfNecessary
+.InvalidItem:
+	xchg	ax, cx					; Restore AX
+	pop		cx
+	ret
+
+;--------------------------------------------------------------------
+; MenuText_AdjustDisplayContextForDrawingItemFromAX
+;	Parameters
+;		AX:		Item to refresh
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		CX:		Item to refresh
+;	Corrupts registers:
+;		AX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuText_AdjustDisplayContextForDrawingItemFromAX:
+	mov		cx, ax
+	call	MenuLocation_GetTextCoordinatesToAXforItemInAX
+	CALL_DISPLAY_LIBRARY SetCursorCoordinatesFromAX
+	call	.GetItemTextAttributeTypeToSIforItemInCX
+	jmp		SHORT AdjustDisplayContextForDrawingTexts
+
+;--------------------------------------------------------------------
+; .GetItemTextAttributeTypeToSIforItemInCX
+;	Parameters
+;		CX:		Item to refresh
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		SI:		Text attribute type (ATTRIBUTE_CHARS)
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.GetItemTextAttributeTypeToSIforItemInCX:
+	mov		si, ATTRIBUTE_CHARS.cItem
+	test	BYTE [bp+MENU.bFlags], FLG_MENU_NOHIGHLIGHT
+	jnz		SHORT .ReturnAttributeTypeInSI
+	cmp		cx, [bp+MENU.wHighlightedItem]
+	jne		SHORT .ReturnAttributeTypeInSI
+	sub		si, BYTE ATTRIBUTE_CHARS.cItem - ATTRIBUTE_CHARS.cHighlightedItem
+ALIGN JUMP_ALIGN, ret
+.ReturnAttributeTypeInSI:
+	ret
+
+
+;--------------------------------------------------------------------
+; DrawScrollbarIfNecessary
+;	Parameters
+;		CX:		Item to refresh
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DrawScrollbarIfNecessary:
+	push	cx
+	call	.DrawSpacesBeforeScrollbarCharacter
+	call	MenuScrollbars_AreScrollbarsNeeded
+	pop		cx
+	jc		SHORT .DrawScrollbarCharacter
+	ret
+
+;--------------------------------------------------------------------
+; .DrawSpacesBeforeScrollbarCharacter
+;	Parameters
+;		CX:		Item to refresh
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DX, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.DrawSpacesBeforeScrollbarCharacter:
+	CALL_DISPLAY_LIBRARY GetSoftwareCoordinatesToAX
+	xchg	dx, ax					; Current coordinates to DX
+	mov		ax, cx
+	call	MenuLocation_GetScrollbarCoordinatesToAXforItemInAX
+	sub		al, dl
+	sub		al, MENU_TEXT_COLUMN_OFFSET/2
+
+	eMOVZX	cx, al
+	jcxz	.NoSpacesNeeded
+	mov		al, ' '
+	CALL_DISPLAY_LIBRARY PrintRepeatedCharacterFromALwithCountInCX
+ALIGN JUMP_ALIGN, ret
+.NoSpacesNeeded:
+	ret
+
+;--------------------------------------------------------------------
+; .DrawScrollbarCharacter
+;	Parameters
+;		CX:		Item to refresh
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.DrawScrollbarCharacter:
+	push	cx
+
+	mov		si, ATTRIBUTE_CHARS.cBordersAndBackground
+	call	MenuAttribute_SetToDisplayContextFromTypeInSI
+
+	mov		ax, cx
+	call	MenuLocation_GetScrollbarCoordinatesToAXforItemInAX
+	CALL_DISPLAY_LIBRARY SetCursorCoordinatesFromAX
+
+	mov		di, cx
+	sub		di, [bp+MENU.wFirstVisibleItem]		; Item to line
+	call	MenuScrollbars_GetScrollCharacterToALForLineInDI
+	CALL_DISPLAY_LIBRARY PrintCharacterFromAL
+
+	pop		cx
+	ret
+
+
+;--------------------------------------------------------------------
+; AdjustDisplayContextForDrawingTexts
+;	Parameters
+;		SI:		Attribute type (from ATTRIBUTE_CHARS)
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+AdjustDisplayContextForDrawingTexts:
+	mov		ax, MenuCharOut_MenuTextTeletypeOutputWithAttribute
+	CALL_DISPLAY_LIBRARY SetCharacterOutputFunctionFromAX
+
+	mov		ax, bp
+	CALL_DISPLAY_LIBRARY SetCharacterOutputParameterFromAX
+
+	jmp		MenuAttribute_SetToDisplayContextFromTypeInSI
Index: /trunk/Assembly_Library/Src/Menu/MenuTime.asm
===================================================================
--- /trunk/Assembly_Library/Src/Menu/MenuTime.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Menu/MenuTime.asm	(revision 41)
@@ -0,0 +1,200 @@
+; File name		:	MenuTime.asm
+; Project name	:	Assembly Library
+; Created date	:	25.7.2010
+; Last update	:	13.8.2010
+; Author		:	Tomi Tilli
+; Description	:	Menu timeouts other time related functions.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; MenuTime_SetSelectionTimeoutValueFromAX
+;	Parameters
+;		AX:		Selection timeout in system timer ticks
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuTime_SetSelectionTimeoutValueFromAX:
+	mov		[bp+MENUINIT.wTimeoutTicks], ax
+	ret
+
+
+;--------------------------------------------------------------------
+; MenuTime_RestartSelectionTimeout
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuTime_RestartSelectionTimeout:
+	push	ds
+	call	PointDSBXtoTimeoutCounter
+	mov		ax, [bp+MENUINIT.wTimeoutTicks]
+	call	TimerTicks_InitializeTimeoutFromAX	; End time to [DS:BX]
+	pop		ds
+	ret
+
+
+;--------------------------------------------------------------------
+; MenuTime_UpdateSelectionTimeout
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		CF:		Set if timeout
+;				Cleared if time left
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuTime_UpdateSelectionTimeout:
+	cmp		WORD [bp+MENUINIT.wTimeoutTicks], BYTE 0
+	je		SHORT .ReturnSinceTimeoutDisabled	; CF cleared
+	push	ds
+
+	call	GetSecondsUntilTimeoutToAXandPtrToTimeoutCounterToDSBX
+	cmp		al, [bp+MENU.bLastSecondPrinted]
+	je		SHORT .SetCFifTimeoutAndReturn
+	mov		[bp+MENU.bLastSecondPrinted], al
+	call	DrawTimeoutInAXoverMenuBorders
+
+ALIGN JUMP_ALIGN
+.SetCFifTimeoutAndReturn:
+	call	TimerTicks_SetCarryIfTimeoutFromDSBX
+	pop		ds
+.ReturnSinceTimeoutDisabled:
+	ret
+
+
+;--------------------------------------------------------------------
+; MenuTime_DrawWithoutUpdating
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+MenuTime_DrawWithoutUpdating:
+	cmp		WORD [bp+MENUINIT.wTimeoutTicks], BYTE 0
+	je		SHORT .ReturnSinceTimeoutDisabled
+
+	push	ds
+	call	GetSecondsUntilTimeoutToAXandPtrToTimeoutCounterToDSBX
+	call	DrawTimeoutInAXoverMenuBorders
+	pop		ds
+.ReturnSinceTimeoutDisabled:
+	ret
+
+
+;--------------------------------------------------------------------
+; PointDSBXtoTimeoutCounter
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		DS:BX:	Ptr to timeout counter
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+PointDSBXtoTimeoutCounter:
+	push	ss
+	pop		ds
+	lea		bx, [bp+MENU.wTimeoutCounter]
+	ret
+
+
+;--------------------------------------------------------------------
+; GetSecondsUntilTimeoutToAXandPtrToTimeoutCounterToDSBX
+;	Parameters
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		AX:		Seconds until timeout
+;		DS:BX:	Ptr to timeout counter
+;	Corrupts registers:
+;		AX, CX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+GetSecondsUntilTimeoutToAXandPtrToTimeoutCounterToDSBX:
+	call	PointDSBXtoTimeoutCounter
+	call	TimerTicks_GetElapsedToAXfromDSBX
+	neg		ax			; Negate since DS:BX points to end time
+	MAX_S	ax, 0		; Set to zero if overflow
+	xchg	dx, ax
+	jmp		TimerTicks_GetSecondsToAXfromTicksInDX
+
+
+;--------------------------------------------------------------------
+; DrawTimeoutInAXoverMenuBorders
+;	Parameters
+;		AX:		Seconds to draw
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DX, SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DrawTimeoutInAXoverMenuBorders:
+	xchg	dx, ax
+	call	MenuBorders_AdjustDisplayContextForDrawingBorders
+	call	MenuLocation_GetBottomBordersTopLeftCoordinatesToAX
+	CALL_DISPLAY_LIBRARY SetCursorCoordinatesFromAX
+	; Fall to .PrintTimeoutStringWithSecondsInDX
+
+;--------------------------------------------------------------------
+; .PrintTimeoutStringWithSecondsInDX
+;	Parameters
+;		DX:		Seconds to print
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DX, SI, DI
+;--------------------------------------------------------------------
+;ALIGN JUMP_ALIGN
+.PrintTimeoutStringWithSecondsInDX:
+	push	bp
+
+	mov		bp, sp
+	call	.GetTimeoutAttributeToAXfromSecondsInDX
+	mov		si, .szSelectionTimeout
+	push	ax			; Push attribute
+	push	dx			; Push seconds
+	CALL_DISPLAY_LIBRARY FormatNullTerminatedStringFromCSSI
+	pop		bp
+
+	mov		al, DOUBLE_RIGHT_HORIZONTAL_TO_SINGLE_VERTICAL
+	jmp		MenuBorders_PrintSingleBorderCharacterFromAL
+.szSelectionTimeout:
+	db		DOUBLE_BOTTOM_LEFT_CORNER
+	db		DOUBLE_LEFT_HORIZONTAL_TO_SINGLE_VERTICAL
+	db		"%AAutoselection in %2ds",NULL
+
+;--------------------------------------------------------------------
+; .GetTimeoutAttributeToAXfromSecondsInDX
+;	Parameters
+;		DX:		Seconds to print
+;	Returns:
+;		AX:		Attribute byte for seconds
+;		DX:		Seconds to print
+;	Corrupts registers:
+;		SI, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.GetTimeoutAttributeToAXfromSecondsInDX:
+	mov		si, ATTRIBUTE_CHARS.cNormalTimeout
+	cmp		dx, BYTE 3
+	ja		SHORT .GetAttributeToAX
+	add		si, BYTE ATTRIBUTE_CHARS.cHurryTimeout - ATTRIBUTE_CHARS.cNormalTimeout
+ALIGN JUMP_ALIGN
+.GetAttributeToAX:
+	jmp		MenuAttribute_GetToAXfromTypeInSI
Index: /trunk/Assembly_Library/Src/String/Char.asm
===================================================================
--- /trunk/Assembly_Library/Src/String/Char.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/String/Char.asm	(revision 41)
@@ -0,0 +1,199 @@
+; File name		:	Char.asm
+; Project name	:	Assembly Library
+; Created date	:	28.6.2010
+; Last update	:	7.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for handling characters.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; This macro can only be used within this source file!!!
+; IS_BETWEEN_IMMEDIATES
+;	Parameters:
+;		%1:		Value to check
+;		%2:		First accepted value in range
+;		%3:		Last accepted value in range
+;	Returns:
+;		CF:		Set if character is range
+;				(Jumps to CharIsNotValid if before range)
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+%macro IS_BETWEEN_IMMEDIATES 3
+	cmp		%1, %2
+	jb		SHORT CharIsNotValid
+	cmp		%1, (%3)+1				; Set CF if %1 is lesser
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Char_IsLowerCaseLetterInAL
+;	Parameters:
+;		AL:		Character to check
+;	Returns:
+;		CF:		Set if character is lower case letter ('a'...'z')
+;				Cleared if character is not lower case letter
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Char_IsLowerCaseLetterInAL:
+	IS_BETWEEN_IMMEDIATES al, 'a', 'z'
+	ret
+
+;--------------------------------------------------------------------
+; Char_IsUpperCaseLetterInAL
+;	Parameters:
+;		AL:		Character to check
+;	Returns:
+;		CF:		Set if character is upper case letter ('A'...'Z')
+;				Cleared if character is not upper case letter
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Char_IsUpperCaseLetterInAL:
+	IS_BETWEEN_IMMEDIATES al, 'A', 'Z'
+	ret
+
+;--------------------------------------------------------------------
+; Char_IsHexadecimalDigitInAL
+;	Parameters:
+;		AL:		Character to check
+;	Returns:
+;		AL:		Character converted to lower case
+;		CF:		Set if character is decimal digit ('0'...'F')
+;				Cleared if character is not decimal digit
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Char_IsHexadecimalDigitInAL:
+	call	Char_IsDecimalDigitInAL
+	jc		SHORT Char_CharIsValid
+	call	Char_ALtoLowerCaseLetter
+	IS_BETWEEN_IMMEDIATES al, 'a', 'f'
+	ret
+
+;--------------------------------------------------------------------
+; Char_IsDecimalDigitInAL
+;	Parameters:
+;		AL:		Character to check
+;	Returns:
+;		CF:		Set if character is decimal digit ('0'...'9')
+;				Cleared if character is not decimal digit
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Char_IsDecimalDigitInAL:
+	IS_BETWEEN_IMMEDIATES al, '0', '9'
+	ret
+
+
+;--------------------------------------------------------------------
+; Char_ConvertIntegerToALfromDigitInALwithBaseInBX
+;	Parameters:
+;		AL:		Character to convert
+;		BX:		Numeric base (10 or 16)
+;	Returns:
+;		AL:		Character converted to integer
+;		CF:		Set if character was valid
+;				Cleared if character was invalid
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Char_ConvertIntegerToALfromDigitInALwithBaseInBX:
+	push	dx
+	call	Char_GetFilterFunctionToDXforNumericBaseInBX
+	call	dx						; Converts to lower case
+	pop		dx
+	jnc		SHORT CharIsNotValid
+
+	cmp		al, '9'					; Decimal digit
+	jbe		SHORT .ConvertToDecimalDigit
+	sub		al, 'a'-10				; Convert to hexadecimal integer
+	stc
+	ret
+ALIGN JUMP_ALIGN
+.ConvertToDecimalDigit:
+	sub		al, '0'					; Convert to decimal integer
+	; Fall to CharIsValid
+
+;--------------------------------------------------------------------
+; CharIsValid
+; CharIsNotValid
+;	Parameters:
+;		Nothing
+;	Returns:
+;		CF:		Set for CharIsValid
+;				Cleared for CharIsNotValid
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Char_CharIsValid:
+	stc
+	ret
+
+ALIGN JUMP_ALIGN
+CharIsNotValid:
+	clc
+	ret
+
+
+;--------------------------------------------------------------------
+; Char_ALtoLowerCaseLetter
+;	Parameters:
+;		AL:		Character to convert
+;	Returns:
+;		AL:		Character with possible conversion
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Char_ALtoLowerCaseLetter:
+	call	Char_IsUpperCaseLetterInAL	; Is upper case character?
+	jnc		SHORT .Return				;  If not, return
+	add		al, 'a'-'A'					; Convert to lower case
+.Return:
+	ret
+
+;--------------------------------------------------------------------
+; Char_ALtoUpperCaseLetter
+;	Parameters:
+;		AL:		Character to convert
+;	Returns:
+;		AL:		Character with possible conversion
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Char_ALtoUpperCaseLetter:
+	call	Char_IsLowerCaseLetterInAL	; Is lower case character?
+	jnc		SHORT .Return				;  If not, return
+	sub		al, 'a'-'A'					; Convert to upper case
+.Return:
+	ret
+
+
+;--------------------------------------------------------------------
+; Char_GetFilterFunctionToDXforNumericBaseInBX
+;	Parameters
+;		BX:		Numeric base (10 or 16)
+;	Returns:
+;		CS:DX:	Ptr to character filter function
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Char_GetFilterFunctionToDXforNumericBaseInBX:
+	mov		dx, Char_IsDecimalDigitInAL
+	cmp		bl, 10
+	je		SHORT .Return
+	sub		dx, BYTE Char_IsDecimalDigitInAL - Char_IsHexadecimalDigitInAL
+.Return:
+	ret
Index: /trunk/Assembly_Library/Src/String/String.asm
===================================================================
--- /trunk/Assembly_Library/Src/String/String.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/String/String.asm	(revision 41)
@@ -0,0 +1,77 @@
+; File name		:	String.asm
+; Project name	:	Assembly Library
+; Created date	:	12.7.2010
+; Last update	:	6.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for handling characters.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; String_ConvertWordToAXfromStringInDSSIwithBaseInBX
+;	Parameters:
+;		BX:		Numeric base (10 or 16)
+;		DS:SI:	Ptr to string to convert
+;	Returns:
+;		AX:		Word converted from string
+;		DI:		Offset to NULL or first invalid character
+;		CF:		Set if conversion successfull
+;				Cleared if invalid string
+;	Corrupts registers:
+;		DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+String_ConvertWordToAXfromStringInDSSIwithBaseInBX:
+	xor		dx, dx
+	cld
+
+ALIGN JUMP_ALIGN
+.ConvertWordToAXfromStringInDSSIwithBaseInBX:
+	lodsb						; Load character from DS:SI to AL
+	call	Char_ConvertIntegerToALfromDigitInALwithBaseInBX
+	jnc		SHORT .InvalidCharacter
+	xor		ah, ah
+	push	ax					; Push integer
+	xchg	ax, dx				; Copy WORD to AX
+	mul		bx					; DX:AX = word in AX * base in BX
+	pop		dx					; Pop integer
+	add		dx, ax				; WORD back to DX
+	jmp		SHORT .ConvertWordToAXfromStringInDSSIwithBaseInBX
+
+ALIGN JUMP_ALIGN
+.InvalidCharacter:
+	sub		al, 1				; Set CF if NULL character, clear CF otherwise
+	xchg	ax, dx				; Return WORD in AX
+	ret
+
+
+;--------------------------------------------------------------------
+; String_CopyToESDIfromDSSIwithoutTerminatingESDI
+;	Parameters:
+;		DS:SI:	Ptr to source NULL terminated string
+;		ES:DI:	Ptr to destination buffer
+;	Returns:
+;		CX:		Number of characters copied
+;		SI,DI:	Updated by CX characters
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+String_CopyToESDIfromDSSIwithoutTerminatingESDI:
+	push	ax
+	xor		cx, cx
+
+ALIGN JUMP_ALIGN
+.GetAndStoreNewCharacter:
+	lodsb						; Load from DS:SI to AL
+	test	al, al				; NULL to end string?
+	jz		SHORT .EndOfString
+	stosb						; Store from AL to ES:DI
+	inc		cx					; Increment number of characters written
+	jmp		SHORT .GetAndStoreNewCharacter
+
+ALIGN JUMP_ALIGN
+.EndOfString:
+	pop		ax
+	ret
Index: /trunk/Assembly_Library/Src/Time/Delay.asm
===================================================================
--- /trunk/Assembly_Library/Src/Time/Delay.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Time/Delay.asm	(revision 41)
@@ -0,0 +1,88 @@
+; File name		:	Delay.asm
+; Project name	:	Assembly Library
+; Created date	:	24.7.2010
+; Last update	:	16.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Delay functions.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Mimimun delays (without fetching) with some CPU architectures:
+;	8088/8086:	17 cycles for jump + 5 cycles for last comparison
+;	286:		10 cycles for jump + 4 cycles for last comparison
+;	386:		13 cycles for jump + ? cycles for last comparison
+;	486:		 7 cycles for jump + 6 cycles for last comparison
+;
+; DELAY_WITH_LOOP_INSTRUCTION
+;	Parameters
+;		CX:		Loop iterations (0 is maximum delay with 65536 iterations)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		CX
+;--------------------------------------------------------------------
+%macro DELAY_WITH_LOOP_INSTRUCTION 0
+%%StartOfLoop:
+	loop	%%StartOfLoop
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Delay is always at least one millisecond since
+; RTC resolution is 977 microsecs.
+;
+; Delay_MicrosecondsFromAX
+;	Parameters:
+;		AX:		Number of microsecs to wait
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Delay_MicrosecondsFromAX:
+	push	dx
+	push	cx
+
+	xor		cx, cx
+	xchg	dx, ax							; Microsecs now in CX:DX
+	mov		ah, EVENT_WAIT					; Event Wait
+	int		BIOS_SYSTEM_INTERRUPT_15h
+	sti										; XT BIOSes return with interrupt disabled
+
+	pop		cx
+	pop		dx
+	mov		ax, 1							; Prepare to wait 1 timer tick
+	jc		SHORT Delay_TimerTicksFromAX	; Event Wait was unsupported or busy
+	ret
+
+
+;--------------------------------------------------------------------
+; First tick might take 0...54.9 ms and remaining ticks
+; will occur at 54.9 ms intervals.
+;
+; Delay_TimerTicksFromAX
+;	Parameters:
+;		AX:		Number of timer ticks to wait
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Delay_TimerTicksFromAX:
+	push	dx
+
+	xchg	dx, ax
+	call	TimerTicks_ReadFromBdaToAX
+	add		dx, ax				; DX = end time
+	sti							; Make sure that interrupts are enabled
+.WaitLoop:
+	call	TimerTicks_ReadFromBdaToAX
+	cmp		ax, dx
+	jb		SHORT .WaitLoop		; Loop until end time is reached
+
+	pop		dx
+	ret
Index: /trunk/Assembly_Library/Src/Time/TimerTicks.asm
===================================================================
--- /trunk/Assembly_Library/Src/Time/TimerTicks.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Time/TimerTicks.asm	(revision 41)
@@ -0,0 +1,146 @@
+; File name		:	TimerTicks.asm
+; Project name	:	Assembly Library
+; Created date	:	24.7.2010
+; Last update	:	3.8.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for system timer related operations.
+
+; System timer ticks 18.2 times per second = 54.9 ms / tick
+TICKS_PER_HOUR			EQU		65520
+TICKS_PER_MINUTE		EQU		1092
+TICKS_PER_SECOND		EQU		18
+
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; TimerTicks_GetHoursToAXfromTicksInDXAX
+; TimerTicks_GetMinutesToAXfromTicksInDX
+; TimerTicks_GetSecondsToAXfromTicksInDX
+;	Parameters
+;		DX(:AX):	Timer ticks to convert
+;	Returns:
+;		AX:			Hours, minutes or seconds
+;		DX:			Remainder ticks
+;	Corrupts registers:
+;		CX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+TimerTicks_GetHoursToAXfromTicksInDXAX:
+	mov		cx, TICKS_PER_HOUR
+	div		cx		; Divide DX:AX by CX, Hours to AX, remainder ticks to DX
+	ret
+
+ALIGN JUMP_ALIGN
+TimerTicks_GetMinutesToAXfromTicksInDX:
+	xor		ax, ax
+	xchg	ax, dx	; Ticks now in DX:AX
+	mov		cx, TICKS_PER_MINUTE
+	div		cx		; Divide DX:AX by CX, Minutes to AX, remainder ticks to DX
+	ret
+
+ALIGN JUMP_ALIGN
+TimerTicks_GetSecondsToAXfromTicksInDX:
+	xchg	ax, dx	; Ticks now in AX
+	mov		cl, TICKS_PER_SECOND
+	div		cl		; Divide AX by CL, Seconds to AL, remainder ticks to AH
+	xor		dx, dx
+	xchg	dl, ah	; Seconds in AX, remainder in DX
+	ret
+
+
+;--------------------------------------------------------------------
+; First tick might take 0...54.9 ms and remaining ticks
+; will occur at 54.9 ms intervals. Use delay of two (or more) ticks to
+; ensure at least 54.9 ms timeout.
+;
+; TimerTicks_InitializeTimeoutFromAX
+;	Parameters:
+;		AX:			Timeout ticks (54.9 ms) before timeout
+;		DS:BX:		Ptr to timeout variable WORD
+;	Returns:
+;		[DS:BX]:	Initialized for TimerTicks_SetCarryIfTimeoutFromDSBX
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+TimerTicks_InitializeTimeoutFromAX:
+	mov		[bx], ax					; Store timeout ticks
+	call	TimerTicks_ReadFromBdaToAX
+	add		[bx], ax					; Add latest time to timeout ticks
+	ret
+
+;--------------------------------------------------------------------
+; Timeout counter can be initialized with TimerTicks_InitializeTimeoutFromAX.
+;
+; TimerTicks_SetCarryIfTimeoutFromDSBX
+;	Parameters:
+;		DS:BX:		Ptr to timeout variable WORD
+;	Returns:
+;		CF:			Set if timeout
+;					Cleared if time left
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+TimerTicks_SetCarryIfTimeoutFromDSBX:
+	push	ax
+	call	TimerTicks_ReadFromBdaToAX
+	cmp		[bx], ax		; Set CF if timeout WORD is less than time
+	pop		ax
+	ret
+
+
+;--------------------------------------------------------------------
+; TimerTicks_GetElapsedToAXandResetDSBX
+;	Parameters
+;		DS:BX:		Ptr to WORD containing previous reset time
+;	Returns:
+;		AX:			54.9 ms ticks elapsed since last reset
+;		[DS:BX]:	Reset to latest time
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+TimerTicks_GetElapsedToAXandResetDSBX:
+	call	TimerTicks_ReadFromBdaToAX
+	push	ax
+	sub		ax, [bx]
+	pop		WORD [bx]			; Latest time to [DS:BX]
+	ret
+
+;--------------------------------------------------------------------
+; TimerTicks_GetElapsedToAXfromDSBX
+;	Parameters
+;		DS:BX:		Ptr to WORD containing previous update time
+;	Returns:
+;		AX:			54.9 ms ticks elapsed since initializing [DS:BX]
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+TimerTicks_GetElapsedToAXfromDSBX:
+	call	TimerTicks_ReadFromBdaToAX
+	sub		ax, [bx]
+	ret
+
+
+;--------------------------------------------------------------------
+; TimerTicks_ReadFromBdaToAX
+;	Parameters
+;		Nothing
+;	Returns:
+;		AX:		System time in 54.9 ms ticks
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+TimerTicks_ReadFromBdaToAX:
+	push	ds
+
+	LOAD_BDA_SEGMENT_TO	ds, ax
+	mov		ax, [BDA.dwTimerTicks]	; Read low WORD only
+
+	pop		ds
+	ret
Index: /trunk/Assembly_Library/Src/Util/Bit.asm
===================================================================
--- /trunk/Assembly_Library/Src/Util/Bit.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Util/Bit.asm	(revision 41)
@@ -0,0 +1,104 @@
+; File name		:	Bit.asm
+; Project name	:	Assembly Library
+; Created date	:	3.9.2010
+; Last update	:	3.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for bit handling.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Bit_GetSetCountToCXfromDXAX
+;	Parameters
+;		DX:AX:		Source DWORD
+;	Returns:
+;		CX:		Number of bits set in DX:AX
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Bit_GetSetCountToCXfromDXAX:
+	push	bx
+
+	call	Bit_GetSetCountToCXfromAX
+	mov		bx, cx
+	xchg	ax, dx
+	call	Bit_GetSetCountToCXfromAX
+	xchg	ax, dx
+	add		cx, bx
+
+	pop		bx
+	ret
+
+
+;--------------------------------------------------------------------
+; Bit_GetSetCountToCXfromAX
+;	Parameters
+;		AX:		Source WORD
+;	Returns:
+;		CX:		Number of bits set in AX
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Bit_GetSetCountToCXfromAX:
+	push	ax
+
+	xor		cx, cx
+ALIGN JUMP_ALIGN
+.BitScanLoop:
+	shr		ax, 1
+	jz		SHORT .LastBitInCF
+	adc		cx, BYTE 0
+	jmp		SHORT .BitScanLoop
+ALIGN JUMP_ALIGN
+.LastBitInCF:
+	adc		cx, BYTE 0
+
+	pop		ax
+	ret
+
+
+;--------------------------------------------------------------------
+; Bit_SetToDXAXfromIndexInCL
+;	Parameters:
+;		CL:		Index of bit to set (0...31)
+;		DX:AX:	Destination DWORD with flag to be set
+;	Returns:
+;		DX:AX:	DWORD with wanted bit set
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Bit_SetToDXAXfromIndexInCL:
+	cmp		cl, 16
+	jb		SHORT Bit_SetToAXfromIndexInCL
+
+	sub		cl, 16
+	xchg	ax, dx
+	call	Bit_SetToAXfromIndexInCL
+	xchg	dx, ax
+	add		cl, 16
+	ret
+
+;--------------------------------------------------------------------
+; Bit_SetToAXfromIndexInCL
+;	Parameters:
+;		CL:		Index of bit to set (0...15)
+;		AX:		Destination WORD with flag to be set
+;	Returns:
+;		AX:		WORD with wanted bit set
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Bit_SetToAXfromIndexInCL:
+	push	dx
+
+	mov		dx, 1
+	shl		dx, cl
+	or		ax, dx
+
+	pop		dx
+	ret
Index: /trunk/Assembly_Library/Src/Util/Memory.asm
===================================================================
--- /trunk/Assembly_Library/Src/Util/Memory.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Util/Memory.asm	(revision 41)
@@ -0,0 +1,168 @@
+; File name		:	Memory.asm
+; Project name	:	Assembly Library
+; Created date	:	14.7.2010
+; Last update	:	15.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for memory access.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Memory_ZeroDSSIbyWordsInCX
+;	Parameters
+;		CX:		Number of words to zero
+;		DS:SI:	Ptr to buffer to zero
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Memory_ZeroDSSIbyWordsInCX:
+	call	Memory_ExchangeDSSIwithESDI
+	call	Memory_ZeroESDIbyWordsInCX
+	jmp		SHORT Memory_ExchangeDSSIwithESDI
+
+;--------------------------------------------------------------------
+; Memory_ZeroSSBPbyWordsInCX
+;	Parameters
+;		CX:		Number of words to zero
+;		SS:BP:	Ptr to buffer to zero
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Memory_ZeroSSBPbyWordsInCX:
+	push	es
+	push	di
+	push	ax
+
+	push	ss
+	pop		es
+	mov		di, bp
+	call	Memory_ZeroESDIbyWordsInCX
+
+	pop		ax
+	pop		di
+	pop		es
+	ret
+
+;--------------------------------------------------------------------
+; Memory_ZeroESDIbyWordsInCX
+;	Parameters
+;		CX:		Number of words to zero
+;		ES:DI:	Ptr to buffer to zero
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Memory_ZeroESDIbyWordsInCX:
+	xor		ax, ax
+	; Fall to Memory_FillESDIwithAXbyCXtimes
+
+;--------------------------------------------------------------------
+; Memory_FillESDIwithAXbyCXtimes
+;	Parameters
+;		AX:		Word to use to fill buffer
+;		CX:		Number of words to fill
+;		ES:DI:	Ptr to buffer to fill
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Memory_FillESDIwithAXbyCXtimes:
+	cld
+	push	di
+	push	cx
+	rep stosw
+	pop		cx
+	pop		di
+	ret
+
+
+;--------------------------------------------------------------------
+; Memory_ExchangeDSSIwithESDI
+;	Parameters
+;		Nothing
+;	Returns:
+;		DS:SI and ES:DI are exchanged.
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Memory_ExchangeDSSIwithESDI:
+	xchg	si, di
+	push	ds
+	push	es
+	pop		ds
+	pop		es
+	ret
+
+
+;--------------------------------------------------------------------
+; Memory_CopySSBPtoDSSI
+; Memory_CopySSBPtoESDI
+;	Parameters
+;		Nothing
+;	Returns:
+;		DS:SI:		Same as SS:BP
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Memory_CopySSBPtoDSSI:
+	push	ss
+	pop		ds
+	mov		si, bp
+	ret
+
+ALIGN JUMP_ALIGN
+Memory_CopySSBPtoESDI:
+	push	ss
+	pop		es
+	mov		di, bp
+	ret
+
+
+;--------------------------------------------------------------------
+; Memory_SetZFifNullPointerInDSSI
+;	Parameters
+;		DS:SI:	Far pointer
+;	Returns:
+;		ZF:		Set if NULL pointer in DS:SI
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Memory_SetZFifNullPointerInDSSI:
+	push	ax
+	mov		ax, ds
+	or		ax, si
+	pop		ax
+	ret
+
+
+;--------------------------------------------------------------------
+; Memory_ReserveCXbytesFromStackToDSSI
+;	Parameters
+;		CX:		Number of bytes to reserve
+;	Returns:
+;		DS:SI:	Ptr to reserved buffer
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Memory_ReserveCXbytesFromStackToDSSI:
+	pop		ax
+	push	ss
+	pop		ds
+	sub		sp, cx
+	mov		si, sp
+	jmp		ax
Index: /trunk/Assembly_Library/Src/Util/Size.asm
===================================================================
--- /trunk/Assembly_Library/Src/Util/Size.asm	(revision 41)
+++ /trunk/Assembly_Library/Src/Util/Size.asm	(revision 41)
@@ -0,0 +1,135 @@
+; File name		:	Size.asm
+; Project name	:	Assembly Library
+; Created date	:	7.9.2010
+; Last update	:	15.9.2010
+; Author		:	Tomi Tilli
+; Description	:	Functions for size calculations.
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Size_GetWordSizeToAXfromBXDXAXwithMagnitudeInCX
+;	Parameters:
+;		BX:DX:AX:	Size in magnitude
+;		CX:			Magnitude (0=B, 1=kiB, 2=MiB...)
+;	Returns:
+;		AX:			Size in magnitude
+;		CX:			Tenths
+;		DL:			Magnitude character:
+;						'k' = *1024   B = kiB
+;						'M' = *1024 kiB = MiB
+;						'G' = *1024 MiB = GiB
+;						'T' = *1024 GiB = TiB
+;						'P' = *1024 TiB = PiB
+;	Corrupts registers:
+;		BX, DH
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Size_GetSizeToAXAndCharToDLfromBXDXAXwithMagnitudeInCX:
+	push	si
+
+ALIGN JUMP_ALIGN
+.MagnitudeConversionLoop:
+	ePUSH_T	si, .MagnitudeConversionLoop
+	test	bx, bx					; Bits 32...47 in use?
+	jnz		SHORT Size_DivideSizeInBXDXAXby1024andIncrementMagnitudeInCX
+	test	dx, dx					; Bits 16...31 in use?
+	jnz		SHORT Size_DivideSizeInBXDXAXby1024andIncrementMagnitudeInCX
+	cmp		ax, 10000				; 5 digits needed?
+	jae		SHORT Size_DivideSizeInBXDXAXby1024andIncrementMagnitudeInCX
+
+	add		sp, BYTE 2				; Clean return address from stack
+	call	Size_ConvertMagnitudeRemainderInSItoTenths
+	call	Size_GetMagnitudeCharacterToDLfromMagnitudeInCX
+	mov		cx, si
+
+	pop		si
+	ret
+
+;--------------------------------------------------------------------
+; Size_DivideSizeInBXDXAXby1024andIncrementMagnitudeInCX
+;	Parameters:
+;		BX:DX:AX:	Size
+;		CX:			Magnitude (0=B, 1=kiB, 2=MiB...)
+;	Returns:
+;		BX:DX:AX:	Size in magnitude
+;		SI:			Remainder (0...1023)
+;		CX:			Magnitude (1=kiB, 2=MiB...)
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Size_DivideSizeInBXDXAXby1024andIncrementMagnitudeInCX:
+	push	cx
+	xor		si, si					; Zero remainder
+	mov		cl, 10					; Divide by 1024
+ALIGN JUMP_ALIGN
+.ShiftLoop:
+	call	Size_DivideBXDXAXbyTwo
+	rcr		si, 1					; Update remainder
+	loop	.ShiftLoop
+	eSHR_IM	si, 6					; Remainder to SI beginning
+	pop		cx
+	inc		cx						; Increment magnitude
+	ret
+
+
+;--------------------------------------------------------------------
+; Size_ConvertSectorCountInBXDXAXtoKiB
+; Size_DivideBXDXAXbyTwo
+;	Parameters:
+;		BX:DX:AX:	Total sector count
+;	Returns:
+;		BX:DX:AX:	Total size in kiB
+;		CF:			Remainder from division
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Size_ConvertSectorCountInBXDXAXtoKiB:
+Size_DivideBXDXAXbyTwo:
+	shr		bx, 1					; Divide sector count by 2...
+	rcr		dx, 1					; ...to get disk size in...
+	rcr		ax, 1					; ...kiB
+	ret
+
+
+;--------------------------------------------------------------------
+; Size_ConvertMagnitudeRemainderInSItoTenths
+;	Parameters:
+;		SI:			Remainder from last magnitude division (0...1023)
+;	Returns:
+;		SI:			Tenths
+;	Corrupts registers:
+;		DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Size_ConvertMagnitudeRemainderInSItoTenths:
+	push	ax
+
+	mov		ax, 10
+	mul		si					; DX:AX = remainder * 10
+	eSHR_IM	ax, 10				; Divide AX by 1024
+	xchg	si, ax				; SI = tenths
+
+	pop		ax
+	ret
+
+
+;--------------------------------------------------------------------
+; Size_GetMagnitudeCharacterToDLfromMagnitudeInCX
+;	Parameters:
+;		CX:		Magnitude (0=B, 1=kiB, 2=MiB...)
+;	Returns:
+;		DL:		Magnitude character
+;	Corrupts registers:
+;		BX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Size_GetMagnitudeCharacterToDLfromMagnitudeInCX:
+	mov		bx, cx
+	mov		dl, [cs:bx+.rgbMagnitudeToChar]
+	ret
+ALIGN WORD_ALIGN
+.rgbMagnitudeToChar:	db	" kMGTP"
Index: /trunk/Assembly_Library/gpl-2.0.txt
===================================================================
--- /trunk/Assembly_Library/gpl-2.0.txt	(revision 41)
+++ /trunk/Assembly_Library/gpl-2.0.txt	(revision 41)
@@ -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: /trunk/Assembly_Library/makefile
===================================================================
--- /trunk/Assembly_Library/makefile	(revision 41)
+++ /trunk/Assembly_Library/makefile	(revision 41)
@@ -0,0 +1,126 @@
+###############################################################################
+# Generic makefile for building BIOS binary file.                             #
+# v. 1.0.0 (28.7.2007 ... 27.6.2010)                                          #
+# (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/LibraryTests.asm
+#SRC_ASM = Src/LibSizeCheck.asm
+
+# Program executable file name without extension:
+PROG = test
+EXTENSION = com
+
+
+#######################################
+# 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/Display/
+HEADERS += Src/File/
+HEADERS += Src/Keyboard/
+HEADERS += Src/Menu/
+HEADERS += Src/Menu/Dialog/
+HEADERS += Src/String/
+HEADERS += Src/Time/
+HEADERS += Src/Util/
+
+
+#################################################################
+# Assembler preprocessor defines.                               #
+#################################################################
+DEFINES =
+DEFINES_XT = 
+DEFINES_XTPLUS = USE_186
+DEFINES_AT = USE_186 USE_286 USE_AT
+
+
+###################
+# Other variables #
+###################
+
+# Add -D in front of every preprocessor define declaration
+DEFS = $(DEFINES:%=-D%)
+DEFS_XT = $(DEFINES_XT:%=-D%)
+DEFS_XTPLUS = $(DEFINES_XTPLUS:%=-D%)
+DEFS_AT = $(DEFINES_AT:%=-D%)
+
+# Add -I in front of all header directories
+IHEADERS = $(HEADERS:%=-I%)
+
+# Path + target file to be build
+TARGET = $(BUILD_DIR)/$(PROG)
+
+
+#########################
+# Compilers and linkers #
+#########################
+
+# Make
+MAKE = mingw32-make.exe
+
+# Assembler
+AS = yasm.exe
+#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 at xtplus xt clean
+
+# Make clean debug and release versions
+all: clean at xtplus xt
+	@echo All build!
+
+at:
+	@$(AS) "$(SRC_ASM)" $(ASFLAGS) $(DEFS_AT) -o"$(TARGET)_at.$(EXTENSION)"
+	@echo AT version "$(TARGET)_at.$(EXTENSION)" build.
+
+xtplus:
+	@$(AS) "$(SRC_ASM)" $(ASFLAGS) $(DEFS_XTPLUS) -o"$(TARGET)_xtp.$(EXTENSION)"
+	@echo XT plus version "$(TARGET)_xtp.$(EXTENSION)" build.
+
+xt:
+	@$(AS) "$(SRC_ASM)" $(ASFLAGS) $(DEFS_XT) -o"$(TARGET)_xt.$(EXTENSION)"
+	@echo XT version "$(TARGET)_xt.$(EXTENSION)" build.
+
+clean:
+	@$(RM) $(BUILD_DIR)\*.*
+	@echo Deleted "(*.*)" from "$(BUILD_DIR)/"
