Index: /trunk/XTIDE_Universal_BIOS_Configurator_v2/Inc/Variables.inc
===================================================================
--- /trunk/XTIDE_Universal_BIOS_Configurator_v2/Inc/Variables.inc	(revision 619)
+++ /trunk/XTIDE_Universal_BIOS_Configurator_v2/Inc/Variables.inc	(revision 620)
@@ -22,12 +22,13 @@
 
 ; Equates and defines
-BOOT_MENU_DEFAULT_TIMEOUT			EQU		(TICKS_PER_MINUTE / 2)
-MAX_ALLOWED_IDE_CONTROLLERS			EQU		4	; Maximum number of IDE controllers
-MAX_LITE_MODE_CONTROLLERS			EQU		2
-EEPROM_POLLING_TIMEOUT_TICKS		EQU		3	; 1 tick = 54.9 ms
-XTIDE_SIGNATURE_LENGTH				EQU		6	; XTIDE Universal BIOS signature string length (must be even)
-NUMBER_OF_EEPROM_TYPES				EQU		5
-MAX_EEPROM_SIZE_IN_BYTES			EQU		65536
-
+BOOT_MENU_DEFAULT_TIMEOUT				EQU		(TICKS_PER_MINUTE / 2)
+MAX_ALLOWED_IDE_CONTROLLERS				EQU		4		; Maximum number of IDE controllers
+MAX_LITE_MODE_CONTROLLERS				EQU		2
+EEPROM_POLLING_TIMEOUT_TICKS			EQU		3		; 1 tick = 54.9 ms
+XTIDE_SIGNATURE_LENGTH					EQU		6		; XTIDE Universal BIOS signature string length (must be even)
+NUMBER_OF_EEPROM_TYPES					EQU		5
+MAX_EEPROM_SIZE_IN_BYTES				EQU		65536
+SST_PAGE_SIZE_SHIFT						EQU		12		; Minimum we can erase is a 4K sector.
+SST_PAGE_SIZE							EQU		(1 << SST_PAGE_SIZE_SHIFT)	
 
 ; Program global variables
@@ -57,4 +58,5 @@
 	.28256_32kiB		resb	2
 	.28512_64kiB		resb	2
+	.SST_39SF			resb	2
 endstruc
 
@@ -96,5 +98,5 @@
 
 	.wProgressUpdateParam		resb	2
-	.wTimeoutCounter			resb	2
+	.wTimeoutCounter			resb	2	; On SSI, this is timeout cal
 	.wLastOffsetWritten			resb	2
 	.bLastByteWritten			resb	1
@@ -105,4 +107,5 @@
 struc FLASH_RESULT
 	.success					resb	2
+	.DeviceNotDetected			resb	2
 	.PollingTimeoutError		resb	2
 	.DataVerifyError			resb	2
Index: /trunk/XTIDE_Universal_BIOS_Configurator_v2/Src/Buffers.asm
===================================================================
--- /trunk/XTIDE_Universal_BIOS_Configurator_v2/Src/Buffers.asm	(revision 619)
+++ /trunk/XTIDE_Universal_BIOS_Configurator_v2/Src/Buffers.asm	(revision 620)
@@ -173,4 +173,25 @@
 	ret
 
+;--------------------------------------------------------------------
+; Buffers_GetSelectedEepromSizeInWordsToAX
+;	Parameters:
+;		Nothing
+;	Returns:
+;		AX:		Selected EEPROM size in WORDs
+;	Corrupts registers:
+;		BX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Buffers_GetSelectedEepromSizeInWordsToAX:
+	eMOVZX	bx, [cs:g_cfgVars+CFGVARS.bEepromType]
+	mov		ax, [cs:bx+g_rgwEepromTypeToSizeInWords]
+
+	cmp		bl, EEPROM_TYPE.SST_39SF
+	jnz		SHORT .HaveEepromSize
+	cmp		ax, [cs:g_cfgVars+CFGVARS.wImageSizeInWords]
+	jae		SHORT .HaveEepromSize		
+	shl		ax, 1	; Auto-double SST size when too small.
+.HaveEepromSize:
+	ret
 
 ;--------------------------------------------------------------------
@@ -181,5 +202,5 @@
 ;		Nothing
 ;	Corrupts registers:
-;		AX, CX, DI
+;		AX, BX, CX, DI
 ;--------------------------------------------------------------------
 ALIGN JUMP_ALIGN
@@ -187,6 +208,6 @@
 	push	es
 
-	eMOVZX	di, [cs:g_cfgVars+CFGVARS.bEepromType]
-	mov		cx, [cs:di+g_rgwEepromTypeToSizeInWords]
+	call	Buffers_GetSelectedEepromSizeInWordsToAX
+	mov		cx, ax
 	sub		cx, [cs:g_cfgVars+CFGVARS.wImageSizeInWords]	; CX = WORDs to append
 	jbe		SHORT .NoNeedToAppendZeroes
Index: /trunk/XTIDE_Universal_BIOS_Configurator_v2/Src/EEPROM.asm
===================================================================
--- /trunk/XTIDE_Universal_BIOS_Configurator_v2/Src/EEPROM.asm	(revision 619)
+++ /trunk/XTIDE_Universal_BIOS_Configurator_v2/Src/EEPROM.asm	(revision 620)
@@ -28,4 +28,7 @@
 	dw		(32<<10) / 2
 	dw		(64<<10) / 2
+	dw		(32<<10) / 2	; EEPROM_TYPE.SST_39SF
+							; Actual size of flash will be larger than 32K,
+							; however most (all?) XUB devices map a 32K window.
 
 g_rgwEepromPageToSizeInBytes:
Index: /trunk/XTIDE_Universal_BIOS_Configurator_v2/Src/Flash.asm
===================================================================
--- /trunk/XTIDE_Universal_BIOS_Configurator_v2/Src/Flash.asm	(revision 619)
+++ /trunk/XTIDE_Universal_BIOS_Configurator_v2/Src/Flash.asm	(revision 620)
@@ -123,4 +123,5 @@
 	dw		DoNotWriteAnySdpCommand					; EEPROM_TYPE.28256_32kiB
 	dw		DoNotWriteAnySdpCommand					; EEPROM_TYPE.28512_64kiB
+	dw		DoNotWriteAnySdpCommand					; EEPROM_TYPE.SST_39SF
 .rgfnEnableSdpAndFlash:		; SDP_COMMAND.enable
 	dw		WriteSdpEnableCommandFor2816			; EEPROM_TYPE.2816_2kiB
@@ -129,4 +130,5 @@
 	dw		WriteSdpEnableCommandFor28256or28512	; EEPROM_TYPE.28256_32kiB
 	dw		WriteSdpEnableCommandFor28256or28512	; EEPROM_TYPE.28512_64kiB
+	dw		DoNotWriteAnySdpCommand					; EEPROM_TYPE.SST_39SF
 .rgfnDisableSdpAndFlash:	; SDP_COMMAND.disable
 	dw		WriteSdpDisableCommandFor2816			; EEPROM_TYPE.2816_2kiB
@@ -135,4 +137,5 @@
 	dw		WriteSdpDisableCommandFor28256or28512	; EEPROM_TYPE.28256_32kiB
 	dw		WriteSdpDisableCommandFor28256or28512	; EEPROM_TYPE.28512_64kiB
+	dw		DoNotWriteAnySdpCommand					; EEPROM_TYPE.SST_39SF
 
 
Index: /trunk/XTIDE_Universal_BIOS_Configurator_v2/Src/FlashSST.asm
===================================================================
--- /trunk/XTIDE_Universal_BIOS_Configurator_v2/Src/FlashSST.asm	(revision 620)
+++ /trunk/XTIDE_Universal_BIOS_Configurator_v2/Src/FlashSST.asm	(revision 620)
@@ -0,0 +1,268 @@
+; Project name	:	XTIDE Universal BIOS Configurator v2
+; Description	:	Functions for flashing SST flash devices.
+
+;
+; Created by Jayeson Lee-Steere
+; Hereby placed into the public domain.
+;
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; FlashSst_WithFlashvarsInDSSI
+;	Parameters:
+;		DS:BX:	Ptr to FLASHVARS
+;	Returns:
+;		Updated FLASHVARS in DS:BX
+;	Corrupts registers:
+;		AX, DX, DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+FlashSst_WithFlashvarsInDSBX:
+	push	ds
+	push	es
+	push	bx
+	push	cx
+	push	si
+	push	bp
+	mov		bp, bx					; Flashvars now in SS:BP.
+
+	mov		BYTE [bp+FLASHVARS.flashResult], FLASH_RESULT.DeviceNotDetected
+	call	DetectSstDevice
+	jc		SHORT .ExitOnError
+
+	call	CalibrateSstTimeout
+	
+	mov		BYTE [bp+FLASHVARS.flashResult], FLASH_RESULT.PollingTimeoutError
+	mov		cx, [bp+FLASHVARS.wPagesToFlash]
+	lds		si, [bp+FLASHVARS.fpNextSourcePage]
+	les		di, [bp+FLASHVARS.fpNextDestinationPage]
+%ifdef CLD_NEEDED
+	cld
+%endif
+
+ALIGN JUMP_ALIGN
+.NextPage:
+	; See if this page needs updating.
+	push	si
+	push	di
+	push	cx
+	mov		cx, [bp+FLASHVARS.wEepromPageSize]
+	mov		bx, cx
+	repe cmpsb
+	pop		cx
+	pop		di
+	pop		si
+	jnz		SHORT .FlashThisPage
+	add		si, bx
+	add		di, bx
+	jmp		SHORT .ContinueLoop
+
+.FlashThisPage:
+	call	EraseSstPage
+	jc		SHORT .ExitOnError
+	call	WriteSstPage
+	jc		SHORT .ExitOnError
+.ContinueLoop:
+	loop	.NextPage
+
+	; The write process has already confirmed the results one byte at a time.
+	; Here we do an additional verify check just in case there was some 
+	; kind of oddity with pages / addresses.
+	mov		BYTE [bp+FLASHVARS.flashResult], FLASH_RESULT.DataVerifyError
+	mov		ax, [bp+FLASHVARS.wPagesToFlash]
+	mov		cl, SST_PAGE_SIZE_SHIFT
+	shl		ax, cl
+	mov		cx, ax
+	lds		si, [bp+FLASHVARS.fpNextSourcePage]
+	les		di, [bp+FLASHVARS.fpNextDestinationPage]
+	repe cmpsb
+	jnz		SHORT .ExitOnError
+
+%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
+%if FLASH_RESULT.success = 0	; Just in case this should ever change
+	mov		[bp+FLASHVARS.flashResult], cl
+%else
+	mov		BYTE [bp+FLASHVARS.flashResult], FLASH_RESULT.success
+%endif
+%endif
+ALIGN JUMP_ALIGN
+.ExitOnError:
+	pop		bp
+	pop		si
+	pop		cx
+	pop		bx
+	pop		es
+	pop		ds
+	ret
+
+;--------------------------------------------------------------------
+; DetectSstDevice
+;	Parameters:
+;		SS:BP:	Ptr to FLASHVARS
+;	Returns:
+;		CF:	Clear if supported SST device found
+;			Set if supported SST device not found
+;	Corrupts registers:
+;		AX, DI, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+DetectSstDevice:
+	les		di, [bp+FLASHVARS.fpNextDestinationPage]
+
+	cli
+	mov		BYTE [es:05555h], 0AAh	; Enter software ID sequence.
+	mov		BYTE [es:02AAAh], 055h
+	mov		BYTE [es:05555h], 090h
+	mov		al, [es:di]				; Extra reads to be sure device
+	mov		al, [es:di]				; has time to respond.
+	mov		al, [es:di]
+	mov		ah, [es:di]				; Vendor ID in AH.
+	mov		al, [es:di + 1]			; Device ID in AL.
+	mov		BYTE [es:05555h], 0F0h	; Exit software ID.
+	sti
+
+	cmp		al, 0B4h
+	jb		SHORT .NotValidDevice
+	cmp		al, 0B7h
+	ja		SHORT .NotValidDevice
+	cmp		ah, 0BFh
+	jne		SHORT .NotValidDevice
+	ret
+
+.NotValidDevice:
+	stc
+	ret
+	
+;--------------------------------------------------------------------
+; CalibrateSstTimeout
+;	Parameters:
+;		SS:BP:	Ptr to FLASHVARS
+;	Returns:
+;		FLASHVARS.wTimeoutCounter
+;	Corrupts registers:
+;		AX, BX, CX, SI, DI, DS, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+CalibrateSstTimeout:
+	LOAD_BDA_SEGMENT_TO	ds, ax
+	les		di, [bp+FLASHVARS.fpNextDestinationPage]
+	xor		cx, cx
+	mov		si, cx
+	mov		di, cx
+	mov		al, [es:di]
+	not		al							; Forces poll to fail.
+
+	mov		bx, [BDA.dwTimerTicks]		; Read low word only.
+	inc		bx
+.WaitForFirstIncrement:
+	cmp		bx, [BDA.dwTimerTicks]
+	jnz		SHORT .WaitForFirstIncrement
+
+	inc		bx
+
+.WaitForSecondIncrement:
+	inc		ch							; cx now 0x0100
+.PollLoop:								; Identical to poll loop used 
+	cmp		[es:di], al					; during programming
+	jz		SHORT .PollComplete			; Will never branch in this case
+	loop	.PollLoop
+.PollComplete:
+	add		si, 1						; number of poll loops completed
+	jc		SHORT .countOverflow
+	cmp		bx, [BDA.dwTimerTicks]
+	jnz		SHORT .WaitForSecondIncrement
+
+.CalComplete:
+	; SI ~= number of polling loops in 215us.
+	mov		[bp+FLASHVARS.wTimeoutCounter], si
+	ret
+		
+.countOverflow:
+	; Clamp on overflow, although it should not be possible on
+	; real hardware. In principle SI could overflow on a very
+	; fast CPU. However the SST device is on a slow bus. Even
+	; running at the min read cycle time of fastest version of
+	; the device, SI can not overflow.
+	dec		si
+	jmp		SHORT .CalComplete
+
+;--------------------------------------------------------------------
+; EraseSstPage
+;	Parameters:
+;		ES:DI:	Destination ptr.
+;	Returns:
+;		CF:		Set on error.
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+EraseSstPage:
+	push	cx
+
+	mov		BYTE [es:05555h], 0AAh	; Sector erase sequence.
+	mov		BYTE [es:02AAAh], 055h
+	mov		BYTE [es:05555h], 080h
+	mov		BYTE [es:05555h], 0AAh
+	mov		BYTE [es:02AAAh], 055h
+	mov		BYTE [es:di], 030h
+
+	mov		ax, 1163				; 1163 x ~215us = 250ms = 10x datasheet max
+.TimeoutOuterLoop:
+	mov		cx, [bp+FLASHVARS.wTimeoutCounter]
+.TimeoutInnerLoop:
+	cmp		BYTE [es:di], 0FFh		; Will return 0FFh when erase complete.
+	jz		SHORT .Exit
+	loop	.TimeoutInnerLoop
+	dec		ax
+	jnz		SHORT .TimeoutOuterLoop
+	stc								; Timed out.
+.Exit:
+	pop		cx
+	ret
+
+;--------------------------------------------------------------------
+; WriteSstPage
+;	Parameters:
+;		DS:SI:	Source ptr.
+;		ES:DI:	Destination ptr.
+;	Returns:
+;		SI, DI:	Each advanced forward 1 page.
+;		CF:		Set on error.
+;	Corrupts registers:
+;		AL, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+WriteSstPage:
+	push	cx
+
+	mov		bx, [bp+FLASHVARS.wTimeoutCounter]
+	mov		dx, [bp+FLASHVARS.wEepromPageSize]
+	cli
+
+.NextByte:
+	lodsb
+	mov		BYTE [es:05555h], 0AAh	; Byte program sequence.
+	mov		BYTE [es:02AAAh], 055h
+	mov		BYTE [es:05555h], 0A0h
+	mov		[es:di], al
+
+	mov		cx, bx
+.WaitLoop:
+	cmp		[es:di], al				; Device won't return actual data until 
+	jz		SHORT .ByteFinished		; write complete. Timeout ~215us, or 
+	loop	.WaitLoop				; ~10x 20us max program time from datasheet.
+
+	stc								; Write timeout.
+	jmp		SHORT .Exit
+
+.ByteFinished:
+	inc		di
+	dec		dx
+	jnz		SHORT .NextByte
+	clc
+.Exit:
+	sti
+	pop		cx
+	ret
Index: /trunk/XTIDE_Universal_BIOS_Configurator_v2/Src/Main.asm
===================================================================
--- /trunk/XTIDE_Universal_BIOS_Configurator_v2/Src/Main.asm	(revision 619)
+++ /trunk/XTIDE_Universal_BIOS_Configurator_v2/Src/Main.asm	(revision 620)
@@ -56,4 +56,5 @@
 %include "EEPROM.asm"
 %include "Flash.asm"
+%include "FlashSST.asm"
 %include "IdeAutodetect.asm"
 %include "MenuEvents.asm"
Index: /trunk/XTIDE_Universal_BIOS_Configurator_v2/Src/Menupages/FlashMenu.asm
===================================================================
--- /trunk/XTIDE_Universal_BIOS_Configurator_v2/Src/Menupages/FlashMenu.asm	(revision 619)
+++ /trunk/XTIDE_Universal_BIOS_Configurator_v2/Src/Menupages/FlashMenu.asm	(revision 620)
@@ -56,5 +56,5 @@
 	at	MENUITEM.szQuickInfo,		dw	g_szNfoFlashEepromType
 	at	MENUITEM.szHelp,			dw	g_szNfoFlashEepromType
-	at	MENUITEM.bFlags,			db	FLG_MENUITEM_PROGRAMVAR | FLG_MENUITEM_BYTEVALUE | FLG_MENUITEM_VISIBLE
+	at	MENUITEM.bFlags,			db	FLG_MENUITEM_MODIFY_MENU | FLG_MENUITEM_PROGRAMVAR | FLG_MENUITEM_BYTEVALUE | FLG_MENUITEM_VISIBLE
 	at	MENUITEM.bType,				db	TYPE_MENUITEM_MULTICHOICE
 	at	MENUITEM.itemValue + ITEM_VALUE.wRomvarsValueOffset,		dw	CFGVARS.bEepromType
@@ -72,5 +72,5 @@
 	at	MENUITEM.szQuickInfo,		dw	g_szNfoFlashSDP
 	at	MENUITEM.szHelp,			dw	g_szHelpFlashSDP
-	at	MENUITEM.bFlags,			db	FLG_MENUITEM_PROGRAMVAR | FLG_MENUITEM_BYTEVALUE | FLG_MENUITEM_VISIBLE
+	at	MENUITEM.bFlags,			db	FLG_MENUITEM_PROGRAMVAR | FLG_MENUITEM_BYTEVALUE
 	at	MENUITEM.bType,				db	TYPE_MENUITEM_MULTICHOICE
 	at	MENUITEM.itemValue + ITEM_VALUE.wRomvarsValueOffset,		dw	CFGVARS.bSdpCommand
@@ -88,5 +88,5 @@
 	at	MENUITEM.szQuickInfo,		dw	g_szNfoFlashPageSize
 	at	MENUITEM.szHelp,			dw	g_szHelpFlashPageSize
-	at	MENUITEM.bFlags,			db	FLG_MENUITEM_PROGRAMVAR | FLG_MENUITEM_BYTEVALUE | FLG_MENUITEM_VISIBLE
+	at	MENUITEM.bFlags,			db	FLG_MENUITEM_PROGRAMVAR | FLG_MENUITEM_BYTEVALUE
 	at	MENUITEM.bType,				db	TYPE_MENUITEM_MULTICHOICE
 	at	MENUITEM.itemValue + ITEM_VALUE.wRomvarsValueOffset,		dw	CFGVARS.bEepromPage
@@ -134,4 +134,6 @@
 	dw	EEPROM_TYPE.28256_32kiB
 	dw	EEPROM_TYPE.28512_64kiB
+	dw	EEPROM_TYPE.SST_39SF
+
 g_rgszValueToStringLookupForEepromType:
 	dw	g_szValueFlash2816
@@ -140,4 +142,5 @@
 	dw	g_szValueFlash28256
 	dw	g_szValueFlash28512
+	dw	g_szValueFlashSST39SF
 
 g_rgwChoiceToValueLookupForSdpCommand:
@@ -201,6 +204,40 @@
 .AlreadySet:
 	mov		si, g_MenupageForFlashMenu
-	jmp		Menupage_ChangeToNewMenupageInDSSI
-
+	ePUSH_T	bx, Menupage_ChangeToNewMenupageInDSSI
+	cmp		WORD [g_cfgVars+CFGVARS.bEepromType], EEPROM_TYPE.SST_39SF
+	jz		SHORT .DisableMenuitemsUnusedBySstFlash
+	; Fall to .EnableMenuitemsUnusedBySstFlash
+
+;--------------------------------------------------------------------
+; .EnableMenuitemsUnusedBySstFlash
+;	Parameters:
+;		SS:BP:	Menu handle
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.EnableMenuitemsUnusedBySstFlash:
+	mov		bx, g_MenuitemFlashSdpCommand
+	call	EnableMenuitemFromCSBX
+	mov		bx, g_MenuitemFlashPageSize
+	jmp		EnableMenuitemFromCSBX
+
+;--------------------------------------------------------------------
+; .DisableMenuitemsUnusedBySstFlash
+;	Parameters:
+;		SS:BP:	Menu handle
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.DisableMenuitemsUnusedBySstFlash:
+	mov		bx, g_MenuitemFlashSdpCommand
+	call	DisableMenuitemFromCSBX
+	mov		bx, g_MenuitemFlashPageSize
+	jmp		DisableMenuitemFromCSBX
 
 ;--------------------------------------------------------------------
@@ -217,4 +254,9 @@
 	call	.MakeSureThatImageFitsInEeprom
 	jc		SHORT .InvalidFlashingParameters
+	cmp		WORD [cs:g_cfgVars+CFGVARS.bEepromType], EEPROM_TYPE.SST_39SF
+	jnz		SHORT .SkipAlignmentCheck
+	call	.MakeSureAddress32KAligned
+	jc		SHORT .InvalidFlashingParameters
+.SkipAlignmentCheck:
 	push	es
 	push	ds
@@ -225,6 +267,9 @@
 	call	.InitializeFlashvarsFromDSSI
 	mov		bx, si							; DS:BX now points to FLASHVARS
+	cmp		WORD [cs:g_cfgVars+CFGVARS.bEepromType], EEPROM_TYPE.SST_39SF
+	jz		SHORT .FlashWithoutProgressBar
 	add		si, BYTE FLASHVARS_size			; DS:SI now points to PROGRESS_DIALOG_IO
 	call	Dialogs_DisplayProgressDialogForFlashingWithDialogIoInDSSIandFlashvarsInDSBX
+.FlashComplete:
 	call	.DisplayFlashingResultsFromFlashvarsInDSBX
 
@@ -235,4 +280,8 @@
 	ret
 
+.FlashWithoutProgressBar:					; Worst case. SST devices will
+	call	FlashSst_WithFlashvarsInDSBX	; either complete flashing
+	jmp		SHORT .FlashComplete			; or timeout within 2 seconds. 
+
 ;--------------------------------------------------------------------
 ; .MakeSureThatImageFitsInEeprom
@@ -246,5 +295,5 @@
 ALIGN JUMP_ALIGN
 .MakeSureThatImageFitsInEeprom:
-	call	.GetSelectedEepromSizeInWordsToAX
+	call	Buffers_GetSelectedEepromSizeInWordsToAX
 	cmp		ax, [cs:g_cfgVars+CFGVARS.wImageSizeInWords]
 	jae		SHORT .ImageFitsInSelectedEeprom
@@ -254,5 +303,25 @@
 ALIGN JUMP_ALIGN, ret
 .ImageFitsInSelectedEeprom:
+.AlignmentIs32K:
 .DoNotGenerateChecksumByte:
+	ret
+
+;--------------------------------------------------------------------
+; .MakeSureAddress32KAligned
+;	Parameters:
+;		SS:BP:	Ptr to MENU
+;	Returns:
+;		CF:		Set if EEPROM segment is not 32K aligned
+;	Corrupts registers:
+;		AX, BX, DX
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.MakeSureAddress32KAligned:
+	mov		ax, [cs:g_cfgVars+CFGVARS.wEepromSegment]
+	and		ax, 007FFh
+	jz		SHORT .AlignmentIs32K
+	mov		dx, g_szErrAddrNot32KAligned
+	call	Dialogs_DisplayErrorFromCSDX
+	stc
 	ret
 
@@ -304,6 +373,11 @@
 	mov		[si+FLASHVARS.bEepromSdpCommand], al
 
+	mov		ax, SST_PAGE_SIZE
+	cmp		WORD [g_cfgVars+CFGVARS.bEepromType], EEPROM_TYPE.SST_39SF
+	jz		SHORT .UseSstPageSize
+
 	eMOVZX	bx, [cs:g_cfgVars+CFGVARS.bEepromPage]
 	mov		ax, [cs:bx+g_rgwEepromPageToSizeInBytes]
+.UseSstPageSize:
 	mov		[si+FLASHVARS.wEepromPageSize], ax
 
@@ -323,5 +397,5 @@
 ALIGN JUMP_ALIGN
 .GetNumberOfPagesToFlashToAX:
-	call	.GetSelectedEepromSizeInWordsToAX
+	call	Buffers_GetSelectedEepromSizeInWordsToAX
 	xor		dx, dx
 	eSHL_IM	ax, 1		; Size in bytes to...
@@ -335,20 +409,4 @@
 
 ;--------------------------------------------------------------------
-; .GetSelectedEepromSizeInWordsToAX
-;	Parameters:
-;		Nothing
-;	Returns:
-;		AX:		Selected EEPROM size in WORDs
-;	Corrupts registers:
-;		BX
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-.GetSelectedEepromSizeInWordsToAX:
-	eMOVZX	bx, [cs:g_cfgVars+CFGVARS.bEepromType]
-	mov		ax, [cs:bx+g_rgwEepromTypeToSizeInWords]
-	ret
-
-
-;--------------------------------------------------------------------
 ; .DisplayFlashingResultsFromFlashvarsInDSBX
 ;	Parameters:
@@ -368,4 +426,5 @@
 .rgfnFlashResultMessage:
 	dw		.DisplayFlashSuccessful
+	dw		.DisplayDeviceDetectionError
 	dw		.DisplayPollingError
 	dw		.DisplayDataVerifyError
@@ -373,4 +432,5 @@
 
 ;--------------------------------------------------------------------
+; .DisplayDeviceDetectionError
 ; .DisplayPollingError
 ; .DisplayDataVerifyError
@@ -383,4 +443,9 @@
 ;		AX, DX, DI, ES
 ;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.DisplayDeviceDetectionError:
+	mov		dx, g_szErrEepromDetection
+	jmp		Dialogs_DisplayErrorFromCSDX
+
 ALIGN JUMP_ALIGN
 .DisplayPollingError:
Index: /trunk/XTIDE_Universal_BIOS_Configurator_v2/Src/Strings.asm
===================================================================
--- /trunk/XTIDE_Universal_BIOS_Configurator_v2/Src/Strings.asm	(revision 619)
+++ /trunk/XTIDE_Universal_BIOS_Configurator_v2/Src/Strings.asm	(revision 620)
@@ -53,13 +53,17 @@
 
 ; Flashing related strings
-g_szFlashTitle:			db	"Flashing EEPROM, please wait.",NULL
-g_szErrEepromTooSmall:	db	"Image is too large for selected EEPROM type!",NULL
-g_szErrEepromPolling:	db	"Timeout when polling EEPROM.",LF
-						db	"EEPROM was not flashed properly!",NULL
-g_szErrEepromVerify:	db	"EEPROM did not return the same byte that was written.",LF
-						db	"EEPROM was not flashed properly!",NULL
-g_szPCFlashSuccessful:	db	"EEPROM was written successfully.",LF
-						db	"Press any key to reboot.",NULL
-g_szForeignFlash:		db	"EEPROM was written successfully.",NULL
+g_szFlashTitle:				db	"Flashing EEPROM, please wait.",NULL
+g_szErrEepromTooSmall:		db	"Image is too large for selected EEPROM type!",NULL
+g_szErrAddrNot32KAligned:	db	"The selected EEPROM type requires the address to be 32 "
+							db	"kiB aligned (C800, D000, D800, E000, etc.)",NULL
+g_szErrEepromDetection:		db	"EEPROM of type not found.",LF
+							db	"EEPROM was not flashed properly!",NULL
+g_szErrEepromPolling:		db	"Timeout when polling EEPROM.",LF
+							db	"EEPROM was not flashed properly!",NULL
+g_szErrEepromVerify:		db	"EEPROM did not return the same byte that was written.",LF
+							db	"EEPROM was not flashed properly!",NULL
+g_szPCFlashSuccessful:		db	"EEPROM was written successfully.",LF
+							db	"Press any key to reboot.",NULL
+g_szForeignFlash:			db	"EEPROM was written successfully.",NULL
 
 
@@ -556,5 +560,6 @@
 								db	"2864 mod (8 kiB)",LF
 								db	"28256 (32 kiB)",LF
-								db	"28512 (64 kiB)",NULL
+								db	"28512 (64 kiB)",LF
+								db	"SST39SFx flash",NULL
 g_szValueFlash2816:				db	"2816",NULL
 g_szValueFlash2864:				db	"2864",NULL
@@ -562,4 +567,5 @@
 g_szValueFlash28256:			db	"28256",NULL
 g_szValueFlash28512:			db	"28512",NULL
+g_szValueFlashSST39SF:			db	"SST39SFx",NULL
 
 g_szMultichoiceSdpCommand:		db	"None",LF
